Browse Source

Factor out cell packing and unpacking

svn:r240
Nick Mathewson 22 years ago
parent
commit
97d847b9e3
4 changed files with 67 additions and 38 deletions
  1. 4 10
      doc/tor-spec.txt
  2. 45 20
      src/or/connection.c
  3. 10 8
      src/or/connection_edge.c
  4. 8 0
      src/or/or.h

+ 4 - 10
doc/tor-spec.txt

@@ -281,12 +281,6 @@ which reveals the downstream node.
 
      The value of Version is currently 2.
 
-     The forward and backward ciphers fields can take the following values:
-          0: Identity 
-          1: Single DES in OFB
-          2: RC4
-          3: Triple DES (encrypt-decrypt-encrypt) in OFB
-
      The port and address field denote the IPV4 address and port of
      the next onion router in the circuit, or are set to 0 for the
      last hop.
@@ -316,7 +310,7 @@ which reveals the downstream node.
 
          D. Encrypt the first 128 bytes of M with the RSA key of
             OR_I, using no padding.  Encrypt the remaining portion of
-            M with DES/OFB, using K1_I as a key and an all-0 IV.
+            M with 3DES/OFB, using K1_I as a key and an all-0 IV.
 
       3. M is now the onion.
 
@@ -365,7 +359,7 @@ which reveals the downstream node.
           in the past, then tear down the circuit (see section 4.2).
 
           Compute K1 through K3 as above.  Use K1 to decrypt the rest
-          of the onion using DES/OFB.
+          of the onion using 3DES/OFB.
 
           If we are not the exit node, remove the first layer from the
           decrypted onion, and send the remainder to the next OR
@@ -403,14 +397,14 @@ which reveals the downstream node.
 
    Otherwise, if the OR is not at the OP edge of the circuit (that is,
    either an 'exit node' or a non-edge node), it de/encrypts the length
-   field and the payload with DES/OFB, as follows:
+   field and the payload with 3DES/OFB, as follows:
         'Forward' data cell (same direction as onion):
             Use K2 as key; encrypt.
         'Back' data cell (opposite direction from onion):
             Use K3 as key; decrypt.
 
    Otherwise, if the data cell has arrived to the OP edge of the circuit,
-   the OP de/encrypts the length and payload fields with DES/OFB as
+   the OP de/encrypts the length and payload fields with 3DES/OFB as
    follows:
          OP sends data cell:
             For I=1...N, decrypt with K2_I.

+ 45 - 20
src/or/connection.c

@@ -543,7 +543,6 @@ void connection_send_cell(connection_t *conn) {
    */
   conn->outbuf_flushlen += sizeof(cell_t); /* instruct it to send a cell */
   connection_start_writing(conn);
-
 }
 
 void connection_increment_send_timeval(connection_t *conn) {
@@ -584,12 +583,7 @@ int connection_write_cell_to_buf(const cell_t *cellp, connection_t *conn) {
   char networkcell[CELL_NETWORK_SIZE];
   char *n = networkcell;
  
-  memset(n,0,CELL_NETWORK_SIZE); /* zero it out to start */
-  *(aci_t *)n = htons(cellp->aci);
-  *(n+2) = cellp->command;
-  *(n+3) = cellp->length;
-  /* seq is reserved, leave zero */
-  memcpy(n+8,cellp->payload,CELL_PAYLOAD_SIZE);
+  cell_pack(n, cellp);
 
   if(connection_encrypt_cell(n,conn)<0) {
     return -1;
@@ -676,7 +670,7 @@ repeat_connection_package_raw_inbuf:
    *       compressing.
    *    2) 
    */
-  len = connection_compress_from_buf(cell.payload + TOPIC_HEADER_SIZE,
+  len = connection_compress_from_buf(cell.payload,
                                      CELL_PAYLOAD_SIZE - TOPIC_HEADER_SIZE,
                                      conn, Z_SYNC_FLUSH);
   if (len < 0)
@@ -690,7 +684,7 @@ repeat_connection_package_raw_inbuf:
     cell.length = amount_to_process;
   }
 
-  if(connection_fetch_from_buf(cell.payload+TOPIC_HEADER_SIZE, cell.length, conn) < 0)
+  if(connection_fetch_from_buf(cell.payload, cell.length, conn) < 0)
     return -1;
 #endif
 
@@ -702,10 +696,11 @@ repeat_connection_package_raw_inbuf:
 
   log(LOG_DEBUG,"connection_package_raw_inbuf(): (%d) Packaging %d bytes (%d waiting).",conn->s,cell.length, conn->inbuf_datalen);
 
-  *(uint16_t *)(cell.payload+2) = htons(conn->topic_id);
-  *cell.payload = TOPIC_COMMAND_DATA;
-  cell.length += TOPIC_HEADER_SIZE;
+
   cell.command = CELL_DATA;
+  cell.topic_command = TOPIC_COMMAND_DATA;
+  cell.topic_id = conn->topic_id;
+  cell.length += TOPIC_HEADER_SIZE;
 
   if(conn->type == CONN_TYPE_EXIT) {
     cell.aci = circ->p_aci;
@@ -756,10 +751,10 @@ int connection_consider_sending_sendme(connection_t *conn, int edge_type) {
   }
 
   memset(&cell, 0, sizeof(cell_t));
-  *(uint16_t *)(cell.payload+2) = htons(conn->topic_id);
-  *cell.payload = TOPIC_COMMAND_SENDME;
-  cell.length += TOPIC_HEADER_SIZE;
   cell.command = CELL_DATA;
+  cell.topic_command = TOPIC_COMMAND_SENDME;
+  cell.topic_id = conn->topic_id;
+  cell.length += TOPIC_HEADER_SIZE;
 
   if(edge_type == EDGE_EXIT) { /* we're at an exit */
     if(conn->p_receive_topicwindow < TOPICWINDOW_START - TOPICWINDOW_INCREMENT) {
@@ -850,11 +845,7 @@ int connection_process_cell_from_inbuf(connection_t *conn) {
 #endif
 
   /* retrieve cell info from outbuf (create the host-order struct from the network-order string) */
-  memset(&cell,0,sizeof(cell_t)); /* zero it out to start */
-  cell.aci = ntohs(*(aci_t *)outbuf);
-  cell.command = *(outbuf+2);
-  cell.length = *(outbuf+3);
-  memcpy(cell.payload, outbuf+8, CELL_PAYLOAD_SIZE);
+  cell_unpack(&cell, outbuf);
 
 //  log(LOG_DEBUG,"connection_process_cell_from_inbuf(): Decrypted cell is of type %u (ACI %u).",cellp->command,cellp->aci);
   command_process_cell(&cell, conn);
@@ -862,6 +853,40 @@ int connection_process_cell_from_inbuf(connection_t *conn) {
   return connection_process_inbuf(conn); /* process the remainder of the buffer */
 }
 
+void
+cell_pack(char *dest, const cell_t *src)
+{
+  *(uint16_t*)dest     = htons(src->aci);
+  *(uint8_t*)(dest+2)  = src->command;
+  *(uint8_t*)(dest+3)  = src->length;
+  *(uint32_t*)(dest+4) = 0; /* Reserved */
+  if (src->command != CELL_DATA) {
+    memcpy(dest+8, src->payload, CELL_PAYLOAD_SIZE);
+  } else {
+    *(uint8_t*)(dest+8)  = src->topic_command;
+    *(uint8_t*)(dest+9)  = 0;
+    *(uint16_t*)(dest+10) = htons(src->topic_id);
+    memcpy(dest+12, src->payload, CELL_PAYLOAD_SIZE - TOPIC_HEADER_SIZE);
+  }
+}
+
+void
+cell_unpack(cell_t *dest, const char *src)
+{
+  dest->aci     = ntohs(*(uint16_t*)(src));
+  dest->command = *(uint8_t*)(src+2);
+  dest->length  = *(uint8_t*)(src+3);
+  dest->seq     = ntohl(*(uint32_t*)(src+4));
+  if (dest->command != CELL_DATA) {
+    memcpy(dest->payload, src+8, CELL_PAYLOAD_SIZE);
+  } else {
+    dest->topic_command = *(uint8_t*)(src+8);
+    /* zero  = *(uint8_t*)(src+9); */
+    dest->topic_id = ntohs(*(uint16_t*)(src+10));
+    memcpy(dest->payload, src+12, CELL_PAYLOAD_SIZE - TOPIC_HEADER_SIZE);
+  }
+}
+
 /*
   Local Variables:
   mode:c

+ 10 - 8
src/or/connection_edge.c

@@ -27,9 +27,10 @@ int connection_edge_process_inbuf(connection_t *conn) {
     memset(&cell, 0, sizeof(cell_t));
     cell.command = CELL_DATA;
     cell.length = TOPIC_HEADER_SIZE;
-    *(uint16_t *)(cell.payload+2) = htons(conn->topic_id);
-    *cell.payload = TOPIC_COMMAND_END;
+    cell.topic_command = TOPIC_COMMAND_END;
+    cell.topic_id = conn->topic_id;
     cell.aci = circ->n_aci;
+
     if (circuit_deliver_data_cell_from_edge(&cell, circ, conn->type) < 0) {
       log(LOG_DEBUG,"connection_edge_process_inbuf: circuit_deliver_data_cell_from_edge failed.  Closing");
       circuit_close(circ);
@@ -75,8 +76,9 @@ int connection_edge_send_command(connection_t *conn, circuit_t *circ, int topic_
   else
     cell.aci = circ->p_aci;
   cell.command = CELL_DATA;
-  *(uint16_t *)(cell.payload+2) = htons(conn->topic_id);
-  *cell.payload = topic_command;
+  cell.topic_command = topic_command;
+  cell.topic_id = conn->topic_id;
+
   cell.length = TOPIC_HEADER_SIZE;
   log(LOG_INFO,"connection_edge_send_command(): delivering %d cell %s.", topic_command, conn->type == CONN_TYPE_AP ? "forward" : "backward");
 
@@ -98,8 +100,8 @@ int connection_edge_process_data_cell(cell_t *cell, circuit_t *circ, int edge_ty
 
   assert(cell && circ);
 
-  topic_command = *cell->payload;
-  topic_id = ntohs(*(uint16_t *)(cell->payload+2));
+  topic_command = cell->topic_command;
+  topic_id = cell->topic_id;
   log(LOG_DEBUG,"connection_edge_process_data_cell(): command %d topic %d", topic_command, topic_id);
   num_seen++;
   log(LOG_DEBUG,"connection_edge_process_data_cell(): Now seen %d data cells here.", num_seen);
@@ -151,7 +153,7 @@ int connection_edge_process_data_cell(cell_t *cell, circuit_t *circ, int edge_ty
       }
 
 #ifdef USE_ZLIB
-      if(connection_decompress_to_buf(cell->payload + TOPIC_HEADER_SIZE,
+      if(connection_decompress_to_buf(cell->payload,
                                       cell->length - TOPIC_HEADER_SIZE, 
                                       conn, Z_SYNC_FLUSH) < 0) {
         log(LOG_INFO,"connection_edge_process_data_cell(): write to buf failed. Marking for close.");
@@ -159,7 +161,7 @@ int connection_edge_process_data_cell(cell_t *cell, circuit_t *circ, int edge_ty
         return 0;
       }
 #else
-      if(connection_write_to_buf(cell->payload + TOPIC_HEADER_SIZE,
+      if(connection_write_to_buf(cell->payload,
                                  cell->length - TOPIC_HEADER_SIZE, conn) < 0) {
         conn->marked_for_close = 1;
         return 0;

+ 8 - 0
src/or/or.h

@@ -197,6 +197,11 @@ typedef struct {
   unsigned char command;
   unsigned char length; /* of payload if data cell, else value of sendme */
   uint32_t seq; /* sequence number */
+
+  /* The following 2 fields are only set when command is CELL_DATA */
+  unsigned char topic_command;
+  uint16_t topic_id;
+
   unsigned char payload[CELL_PAYLOAD_SIZE];
 } cell_t;
 
@@ -614,6 +619,9 @@ int connection_process_cell_from_inbuf(connection_t *conn);
 int connection_consider_sending_sendme(connection_t *conn, int edge_type);
 int connection_finished_flushing(connection_t *conn);
 
+void cell_pack(char *dest, const cell_t *src);
+void cell_unpack(cell_t *dest, const char *src);
+
 /********************************* connection_ap.c ****************************/
 
 int ap_handshake_process_socks(connection_t *conn);