Commit 8712a30e authored by Roger Dingledine's avatar Roger Dingledine
Browse files

move cell size to 512 bytes

move length to 2 bytes, put it in the relay header
remove 4 reserved bytes in cell
add 4 bytes to relay header for the integrity check


svn:r942
parent 961ecf7a
Loading
Loading
Loading
Loading
+16 −23
Original line number Diff line number Diff line
@@ -303,24 +303,18 @@ int circuit_deliver_relay_cell(cell_t *cell, circuit_t *circ,
                               int cell_direction, crypt_path_t *layer_hint) {
  connection_t *conn=NULL;
  char recognized=0;
  char buf[1+CELL_PAYLOAD_SIZE];

  assert(cell && circ);
  assert(cell_direction == CELL_DIRECTION_OUT || cell_direction == CELL_DIRECTION_IN); 

  buf[0] = cell->length;
  memcpy(buf+1, cell->payload, CELL_PAYLOAD_SIZE);

  log_fn(LOG_DEBUG,"direction %d, streamid %d before crypt.", cell_direction, *(int*)(cell->payload+1));

  if(relay_crypt(circ, buf, 1+CELL_PAYLOAD_SIZE, cell_direction, &layer_hint, &recognized, &conn) < 0) {
  if(relay_crypt(circ, cell->payload, CELL_PAYLOAD_SIZE, cell_direction,
                 &layer_hint, &recognized, &conn) < 0) {
    log_fn(LOG_WARN,"relay crypt failed. Dropping connection.");
    return -1;
  }

  cell->length = buf[0];
  memcpy(cell->payload, buf+1, CELL_PAYLOAD_SIZE);

  if(recognized) {
    if(cell_direction == CELL_DIRECTION_OUT) {
#if 0
@@ -374,11 +368,11 @@ int circuit_deliver_relay_cell(cell_t *cell, circuit_t *circ,
int relay_crypt(circuit_t *circ, char *in, int inlen, char cell_direction,
                crypt_path_t **layer_hint, char *recognized, connection_t **conn) {
  crypt_path_t *thishop;
  char out[256];
  char out[CELL_NETWORK_SIZE];

  assert(circ && in && recognized && conn);

  assert(inlen < 256);
  assert(inlen < CELL_NETWORK_SIZE);

  if(cell_direction == CELL_DIRECTION_IN) { 
    if(circ->cpath) { /* we're at the beginning of the circuit.
@@ -391,16 +385,16 @@ int relay_crypt(circuit_t *circ, char *in, int inlen, char cell_direction,
      do { /* Remember: cpath is in forward order, that is, first hop first. */
        assert(thishop);

        log_fn(LOG_DEBUG,"before decrypt: %d",*(int*)(in+2));
        log_fn(LOG_DEBUG,"before decrypt: %d",*(int*)(in+1));
        /* decrypt */
        if(crypto_cipher_decrypt(thishop->b_crypto, in, inlen, out)) {
          log_fn(LOG_WARN,"Error performing onion decryption: %s", crypto_perror());
          return -1;
        }
        memcpy(in,out,inlen);
        log_fn(LOG_DEBUG,"after decrypt: %d",*(int*)(in+2));
        log_fn(LOG_DEBUG,"after decrypt: %d",*(int*)(in+1));

        if( (*recognized = relay_check_recognized(circ, cell_direction, in+2, conn))) {
        if( (*recognized = relay_check_recognized(circ, cell_direction, in+1, conn))) {
          *layer_hint = thishop;
          return 0;
        }
@@ -411,14 +405,14 @@ int relay_crypt(circuit_t *circ, char *in, int inlen, char cell_direction,
      return 0;
    } else { /* we're in the middle. Just one crypt. */

      log_fn(LOG_DEBUG,"before encrypt: %d",*(int*)(in+2));
      log_fn(LOG_DEBUG,"before encrypt: %d",*(int*)(in+1));
      if(crypto_cipher_encrypt(circ->p_crypto, in, inlen, out)) {
        log_fn(LOG_WARN,"Onion encryption failed for circID %u: %s",
               circ->p_circ_id, crypto_perror());
        return -1;
      }
      memcpy(in,out,inlen);
      log_fn(LOG_DEBUG,"after encrypt: %d",*(int*)(in+2));
      log_fn(LOG_DEBUG,"after encrypt: %d",*(int*)(in+1));

      log_fn(LOG_DEBUG,"Skipping recognized check, because we're not the OP.");
      /* don't check for recognized. only the OP can recognize a stream on the way back. */
@@ -432,13 +426,13 @@ int relay_crypt(circuit_t *circ, char *in, int inlen, char cell_direction,
      do {
        assert(thishop);

        log_fn(LOG_DEBUG,"before encrypt: %d",*(int*)(in+2));
        log_fn(LOG_DEBUG,"before encrypt: %d",*(int*)(in+1));
        if(crypto_cipher_encrypt(thishop->f_crypto, in, inlen, out)) {
          log_fn(LOG_WARN,"Error performing encryption: %s", crypto_perror());
          return -1;
        }
        memcpy(in,out,inlen);
        log_fn(LOG_DEBUG,"after encrypt: %d",*(int*)(in+2));
        log_fn(LOG_DEBUG,"after encrypt: %d",*(int*)(in+1));

        thishop = thishop->prev;
      } while(thishop != circ->cpath->prev);
@@ -451,7 +445,7 @@ int relay_crypt(circuit_t *circ, char *in, int inlen, char cell_direction,
      }
      memcpy(in,out,inlen);

      if( (*recognized = relay_check_recognized(circ, cell_direction, in+2, conn)))
      if( (*recognized = relay_check_recognized(circ, cell_direction, in+1, conn)))
        return 0;

    }
@@ -556,8 +550,8 @@ int circuit_consider_sending_sendme(circuit_t *circ, int edge_type, crypt_path_t
  cell.command = CELL_RELAY;
  SET_CELL_RELAY_COMMAND(cell, RELAY_COMMAND_SENDME);
  SET_CELL_STREAM_ID(cell, ZERO_STREAM);
  SET_CELL_RELAY_LENGTH(cell, 0);

  cell.length = RELAY_HEADER_SIZE;
  if(edge_type == EDGE_AP) { /* i'm the AP */
    cell.circ_id = circ->n_circ_id;
    while(layer_hint->deliver_window < CIRCWINDOW_START-CIRCWINDOW_INCREMENT) {
@@ -862,7 +856,6 @@ int circuit_send_next_onion_skin(circuit_t *circ) {
    memset(&cell, 0, sizeof(cell_t));
    cell.command = CELL_CREATE;
    cell.circ_id = circ->n_circ_id;
    cell.length = ONIONSKIN_CHALLENGE_LEN;

    if(onion_skin_create(circ->n_conn->onion_pkey, &(circ->cpath->handshake_state), cell.payload) < 0) {
      log_fn(LOG_WARN,"onion_skin_create (first hop) failed.");
@@ -899,11 +892,12 @@ int circuit_send_next_onion_skin(circuit_t *circ) {
    cell.circ_id = circ->n_circ_id;
    SET_CELL_RELAY_COMMAND(cell, RELAY_COMMAND_EXTEND);
    SET_CELL_STREAM_ID(cell, ZERO_STREAM);
    SET_CELL_RELAY_LENGTH(cell, 6+ONIONSKIN_CHALLENGE_LEN);

    cell.length = RELAY_HEADER_SIZE + 6 + ONIONSKIN_CHALLENGE_LEN;
    *(uint32_t*)(cell.payload+RELAY_HEADER_SIZE) = htonl(hop->addr);
    *(uint16_t*)(cell.payload+RELAY_HEADER_SIZE+4) = htons(hop->port);
    if(onion_skin_create(router->onion_pkey, &(hop->handshake_state), cell.payload+RELAY_HEADER_SIZE+6) < 0) {
    if(onion_skin_create(router->onion_pkey, &(hop->handshake_state),
                         cell.payload+RELAY_HEADER_SIZE+6) < 0) {
      log_fn(LOG_WARN,"onion_skin_create failed.");
      return -1;
    }
@@ -971,7 +965,6 @@ int circuit_extend(cell_t *cell, circuit_t *circ) {
  memset(&newcell, 0, sizeof(cell_t));
  newcell.command = CELL_CREATE;
  newcell.circ_id = circ->n_circ_id;
  newcell.length = ONIONSKIN_CHALLENGE_LEN;

  memcpy(newcell.payload, cell->payload+RELAY_HEADER_SIZE+6,
         ONIONSKIN_CHALLENGE_LEN);
+2 −8
Original line number Diff line number Diff line
@@ -103,13 +103,8 @@ static void command_process_create_cell(cell_t *cell, connection_t *conn) {

  circ = circuit_new(cell->circ_id, conn);
  circ->state = CIRCUIT_STATE_ONIONSKIN_PENDING;
  if(cell->length != ONIONSKIN_CHALLENGE_LEN) {
    log_fn(LOG_WARN,"Bad cell length %d. Dropping.", cell->length);
    circuit_close(circ);
    return;
  }

  memcpy(circ->onionskin,cell->payload,cell->length);
  memcpy(circ->onionskin, cell->payload, ONIONSKIN_CHALLENGE_LEN);

  /* hand it off to the cpuworkers, and then return */
  if(assign_to_cpuworker(NULL, CPUWORKER_TASK_ONION, circ) < 0) {
@@ -135,7 +130,6 @@ static void command_process_created_cell(cell_t *cell, connection_t *conn) {
    circuit_close(circ);
    return;
  }
  assert(cell->length == ONIONSKIN_REPLY_LEN);

  if(circ->cpath) { /* we're the OP. Handshake this. */
    log_fn(LOG_DEBUG,"at OP. Finishing handshake.");
@@ -153,7 +147,7 @@ static void command_process_created_cell(cell_t *cell, connection_t *conn) {
  } else { /* pack it into an extended relay cell, and send it. */
    log_fn(LOG_INFO,"Converting created cell to extended relay cell, sending.");
    connection_edge_send_command(NULL, circ, RELAY_COMMAND_EXTENDED,
                                 cell->payload, cell->length, NULL);
                                 cell->payload, ONIONSKIN_REPLY_LEN, NULL);
  }
}

+25 −25
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@ int connection_edge_process_inbuf(connection_t *conn) {
  return 0;
}

char *connection_edge_end_reason(char *payload, unsigned char length) {
static char *connection_edge_end_reason(char *payload, uint16_t length) {
  if(length < 1) {
    log_fn(LOG_WARN,"End cell arrived with length 0. Should be at least 1.");
    return "MALFORMED";
@@ -155,7 +155,7 @@ int connection_edge_send_command(connection_t *fromconn, circuit_t *circ, int re
  else
    SET_CELL_STREAM_ID(cell, fromconn->stream_id);

  cell.length = RELAY_HEADER_SIZE + payload_len;
  SET_CELL_RELAY_LENGTH(cell, payload_len);
  if(payload_len) {
    memcpy(cell.payload+RELAY_HEADER_SIZE,payload,payload_len);
  }
@@ -191,7 +191,7 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection
  if(conn && conn->state != AP_CONN_STATE_OPEN && conn->state != EXIT_CONN_STATE_OPEN) {
    if(conn->type == CONN_TYPE_EXIT && relay_command == RELAY_COMMAND_END) {
      log_fn(LOG_INFO,"Exit got end (%s) before we're connected. Marking for close.",
        connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, cell->length));
        connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, CELL_RELAY_LENGTH(*cell)));
      if(conn->state == EXIT_CONN_STATE_RESOLVING) {
        log_fn(LOG_INFO,"...and informing resolver we don't want the answer anymore.");
        dns_cancel_pending_resolve(conn->address, conn);
@@ -248,19 +248,19 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection
      }

//      printf("New text for buf (%d bytes): '%s'", cell->length - RELAY_HEADER_SIZE, cell->payload + RELAY_HEADER_SIZE);
      stats_n_data_bytes_received += (cell->length - RELAY_HEADER_SIZE);
      stats_n_data_bytes_received += CELL_RELAY_LENGTH(*cell);
      connection_write_to_buf(cell->payload + RELAY_HEADER_SIZE,
                              cell->length - RELAY_HEADER_SIZE, conn);
                              CELL_RELAY_LENGTH(*cell), conn);
      connection_edge_consider_sending_sendme(conn);
      return 0;
    case RELAY_COMMAND_END:
      if(!conn) {
        log_fn(LOG_INFO,"end cell (%s) dropped, unknown stream %d.",
          connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, cell->length),
          connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, CELL_RELAY_LENGTH(*cell)),
          *(int*)conn->stream_id);
        return 0;
      }
      if(cell->length-RELAY_HEADER_SIZE >= 5 &&
      if(CELL_RELAY_LENGTH(*cell) >= 5 &&
         *(cell->payload+RELAY_HEADER_SIZE) == END_STREAM_REASON_EXITPOLICY) {
        /* No need to close the connection. We'll hold it open while
         * we try a new exit node.
@@ -281,7 +281,7 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection
        }
      }
      log_fn(LOG_INFO,"end cell (%s) for stream %d. Removing stream.",
        connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, cell->length),
        connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, CELL_RELAY_LENGTH(*cell)),
        *(int*)conn->stream_id);

#ifdef HALF_OPEN
@@ -347,7 +347,7 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection
        return 0;
      }
      log_fn(LOG_INFO,"Connected! Notifying application.");
      if (cell->length-RELAY_HEADER_SIZE == 4) {
      if (CELL_RELAY_LENGTH(*cell) >= 4) {
        addr = ntohl(*(uint32_t*)(cell->payload + RELAY_HEADER_SIZE));
        client_dns_set_entry(conn->socks_request->address, addr);
      }
@@ -470,8 +470,8 @@ repeat_connection_edge_package_raw_inbuf:
  if(!amount_to_process)
    return 0;

  if(amount_to_process > CELL_PAYLOAD_SIZE - RELAY_HEADER_SIZE) {
    length = CELL_PAYLOAD_SIZE - RELAY_HEADER_SIZE;
  if(amount_to_process > RELAY_PAYLOAD_SIZE) {
    length = RELAY_PAYLOAD_SIZE;
  } else {
    length = amount_to_process;
  }
@@ -740,7 +740,7 @@ static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ) {
   */

  if(!memchr(cell->payload+RELAY_HEADER_SIZE+STREAM_ID_SIZE,0,
             cell->length-RELAY_HEADER_SIZE-STREAM_ID_SIZE)) {
             CELL_RELAY_LENGTH(*cell)-STREAM_ID_SIZE)) {
    log_fn(LOG_WARN,"relay begin cell has no \\0. Dropping.");
    return 0;
  }
+2 −6
Original line number Diff line number Diff line
@@ -14,17 +14,13 @@ static int connection_or_process_cell_from_inbuf(connection_t *conn);
static void cell_pack(char *dest, const cell_t *src) {
  *(uint16_t*)dest     = htons(src->circ_id);
  *(uint8_t*)(dest+2)  = src->command;
  *(uint8_t*)(dest+3)  = src->length;
  *(uint32_t*)(dest+4) = 0; /* Reserved */
  memcpy(dest+8, src->payload, CELL_PAYLOAD_SIZE);
  memcpy(dest+3, src->payload, CELL_PAYLOAD_SIZE);
}

static void cell_unpack(cell_t *dest, const char *src) {
  dest->circ_id = ntohs(*(uint16_t*)(src));
  dest->command = *(uint8_t*)(src+2);
  dest->length  = *(uint8_t*)(src+3);
  dest->seq     = ntohl(*(uint32_t*)(src+4));
  memcpy(dest->payload, src+8, CELL_PAYLOAD_SIZE);
  memcpy(dest->payload, src+3, CELL_PAYLOAD_SIZE);
}

/**************************************************************/
+0 −1
Original line number Diff line number Diff line
@@ -124,7 +124,6 @@ int onionskin_answer(circuit_t *circ, unsigned char *payload, unsigned char *key
  memset(&cell, 0, sizeof(cell_t));
  cell.command = CELL_CREATED;
  cell.circ_id = circ->p_circ_id;
  cell.length = ONIONSKIN_REPLY_LEN;

  circ->state = CIRCUIT_STATE_OPEN;

Loading