[or-cvs] cpath is now a doubly linked list, not an array

Roger Dingledine arma at seul.org
Thu May 1 22:55:53 UTC 2003


Update of /home/or/cvsroot/src/or
In directory moria.mit.edu:/home/arma/work/onion/cvs/src/or

Modified Files:
	circuit.c connection_ap.c main.c onion.c or.h test.c 
Log Message:
cpath is now a doubly linked list, not an array


Index: circuit.c
===================================================================
RCS file: /home/or/cvsroot/src/or/circuit.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- circuit.c	1 May 2003 06:42:28 -0000	1.39
+++ circuit.c	1 May 2003 22:55:50 -0000	1.40
@@ -89,8 +89,7 @@
 
   if(circ->onion)
     free(circ->onion);
-  if(circ->cpath)
-    circuit_free_cpath(circ->cpath, circ->cpathlen);
+  circuit_free_cpath(circ->cpath);
   while(circ->relay_queue) {
     tmpd = circ->relay_queue;
     circ->relay_queue = tmpd->next;
@@ -101,13 +100,29 @@
   free(circ);
 }
 
-void circuit_free_cpath(crypt_path_t **cpath, int cpathlen) {
-  int i;
+void circuit_free_cpath(crypt_path_t *cpath) {
+  crypt_path_t *victim, *head=cpath;
 
-  for(i=0;i<cpathlen;i++)
-    free(cpath[i]);
+  if(!cpath)
+    return;
 
-  free(cpath);
+  /* it's a doubly linked list, so we have to notice when we've
+   * gone through it once. */
+  while(cpath->next && cpath->next != head) {
+    victim = cpath;
+    cpath = victim->next;
+    circuit_free_cpath_node(victim);
+  }
+
+  circuit_free_cpath_node(cpath);
+}
+
+void circuit_free_cpath_node(crypt_path_t *victim) {
+  if(victim->f_crypto)
+    crypto_free_cipher_env(victim->f_crypto);
+  if(victim->b_crypto)
+    crypto_free_cipher_env(victim->b_crypto);
+  free(victim);
 }
 
 /* return 0 if can't get a unique aci. */
@@ -250,23 +265,18 @@
   return NULL;
 }
 
-circuit_t *circuit_get_newest_by_edge_type(char edge_type) {
+circuit_t *circuit_get_newest_ap(void) {
   circuit_t *circ, *bestcirc=NULL;
 
   for(circ=global_circuitlist;circ;circ = circ->next) {
-    if(edge_type == EDGE_AP && (!circ->p_conn || circ->p_conn->type == CONN_TYPE_AP)) {
+    if(!circ->p_conn || circ->p_conn->type == CONN_TYPE_AP) {
       if(circ->state == CIRCUIT_STATE_OPEN && (!bestcirc ||
         bestcirc->timestamp_created < circ->timestamp_created)) {
-        log(LOG_DEBUG,"circuit_get_newest_by_edge_type(): Choosing n_aci %d.", circ->n_aci);
+        log(LOG_DEBUG,"circuit_get_newest_ap(): Choosing n_aci %d.", circ->n_aci);
         assert(circ->n_aci);
         bestcirc = circ;
       }
     }
-    if(edge_type == EDGE_EXIT && (!circ->n_conn || circ->n_conn->type == CONN_TYPE_EXIT)) {
-      if(circ->state == CIRCUIT_STATE_OPEN && (!bestcirc ||
-        bestcirc->timestamp_created < circ->timestamp_created))
-        bestcirc = circ;
-    }
   }
   return bestcirc;
 }
@@ -346,7 +356,6 @@
 
 int circuit_crypt(circuit_t *circ, char *in, int inlen, char cell_direction) {
   char *out;
-  int i;
   crypt_path_t *thishop;
 
   assert(circ && in);
@@ -357,12 +366,10 @@
 
   if(cell_direction == CELL_DIRECTION_IN) { 
     if(circ->cpath) { /* we're at the beginning of the circuit. We'll want to do layered crypts. */
-      for (i=circ->cpathlen-1; i >= 0; i--) /* moving from first to last hop 
-                                       * Remember : cpath is in reverse order, i.e. last hop first
-                                       */
-      { 
-        thishop = circ->cpath[i];
-
+      thishop = circ->cpath;
+      /* Remember: cpath is in forward order, that is, first hop first. */
+      do {
+        assert(thishop);
         /* decrypt */
         if(crypto_cipher_decrypt(thishop->b_crypto, in, inlen, out)) {
           log(LOG_ERR,"Error performing decryption:%s",crypto_perror());
@@ -372,7 +379,8 @@
 
         /* copy ciphertext back to buf */
         memcpy(in,out,inlen);
-      }
+        thishop = thishop->next;
+      } while(thishop != circ->cpath);
     } else { /* we're in the middle. Just one crypt. */
       if(crypto_cipher_encrypt(circ->p_crypto,in, inlen, out)) {
         log(LOG_ERR,"circuit_encrypt(): Encryption failed for ACI : %u (%s).",
@@ -384,12 +392,10 @@
     }
   } else if(cell_direction == CELL_DIRECTION_OUT) { 
     if(circ->cpath) { /* we're at the beginning of the circuit. We'll want to do layered crypts. */
-      for (i=0; i < circ->cpathlen; i++) /* moving from last to first hop 
-                                          * Remember : cpath is in reverse order, i.e. last hop first
-                                          */
-      { 
-        thishop = circ->cpath[i];
-    
+      thishop = circ->cpath->prev;
+      /* moving from last to first hop */
+      do {
+        assert(thishop);
         /* encrypt */
         if(crypto_cipher_encrypt(thishop->f_crypto, in, inlen, (unsigned char *)out)) {
           log(LOG_ERR,"Error performing encryption:%s",crypto_perror());
@@ -399,7 +405,8 @@
 
         /* copy ciphertext back to buf */
         memcpy(in,out,inlen);
-      }
+        thishop = thishop->prev;
+      } while(thishop != circ->cpath->prev);
     } else { /* we're in the middle. Just one crypt. */
       if(crypto_cipher_decrypt(circ->n_crypto,in, inlen, out)) {
         log(LOG_ERR,"circuit_crypt(): Decryption failed for ACI : %u (%s).",
@@ -524,7 +531,7 @@
 
   assert(circ);
   if(options.APPort) {
-    youngest = circuit_get_newest_by_edge_type(EDGE_AP);
+    youngest = circuit_get_newest_ap();
     log(LOG_DEBUG,"circuit_close(): youngest %d, circ %d.",youngest,circ);
   }
   circuit_remove(circ);
@@ -623,7 +630,7 @@
   circuit_t *circ, *tmpcirc;
   circuit_t *youngest;
 
-  youngest = circuit_get_newest_by_edge_type(EDGE_AP);
+  youngest = circuit_get_newest_ap();
 
   circ = global_circuitlist;
   while(circ) {
@@ -674,7 +681,7 @@
   unsigned int *route; /* hops in the route as an array of indexes into rarray */
   unsigned char *onion; /* holds the onion */
   int onionlen; /* onion length in host order */
-  crypt_path_t **cpath; /* defines the crypt operations that need to be performed on incoming/outgoing data */
+  crypt_path_t *cpath; /* defines the crypt operations that need to be performed on incoming/outgoing data */
 
   /* choose a route */
   route = (unsigned int *)router_new_route(&routelen);
@@ -684,30 +691,21 @@
   }
   log(LOG_DEBUG,"circuit_create_onion(): Chosen a route of length %u : ",routelen);
 
-  /* allocate memory for the crypt path */
-  cpath = malloc(routelen * sizeof(crypt_path_t *));
-  if (!cpath) { 
-    log(LOG_ERR,"circuit_create_onion(): Error allocating memory for cpath.");
-    free(route);
-    return -1;
-  }
-
   /* create an onion and calculate crypto keys */
-  onion = router_create_onion(route,routelen,&onionlen,cpath);
+  onion = router_create_onion(route,routelen,&onionlen, &cpath);
   if (!onion) {
     log(LOG_ERR,"circuit_create_onion(): Error creating an onion.");
     free(route);
-    free(cpath); /* it's got nothing in it, since !onion */
     return -1;
   }
   log(LOG_DEBUG,"circuit_create_onion(): Created an onion of size %u bytes.",onionlen);
-  log(LOG_DEBUG,"circuit_create_onion(): Crypt path :");
+//  log(LOG_DEBUG,"circuit_create_onion(): Crypt path :");
 
   return circuit_establish_circuit(route, routelen, onion, onionlen, cpath);
 }
 
 int circuit_establish_circuit(unsigned int *route, int routelen, char *onion,
-                                   int onionlen, crypt_path_t **cpath) {
+                                   int onionlen, crypt_path_t *cpath) {
   routerinfo_t *firsthop;
   connection_t *n_conn;
   circuit_t *circ;
@@ -722,7 +720,6 @@
   circ->onion = onion;
   circ->onionlen = onionlen;
   circ->cpath = cpath;
-  circ->cpathlen = routelen;
 
   log(LOG_DEBUG,"circuit_establish_circuit(): Looking for firsthop '%s:%u'",
       firsthop->address,firsthop->or_port);

Index: connection_ap.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection_ap.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- connection_ap.c	1 May 2003 06:42:28 -0000	1.39
+++ connection_ap.c	1 May 2003 22:55:50 -0000	1.40
@@ -94,7 +94,7 @@
   }
 
   /* find the circuit that we should use, if there is one. */
-  circ = circuit_get_newest_by_edge_type(EDGE_AP);
+  circ = circuit_get_newest_ap();
 
   if(!circ) {
     log(LOG_INFO,"ap_handshake_process_socks(): No circuit ready. Closing.");

Index: main.c
===================================================================
RCS file: /home/or/cvsroot/src/or/main.c,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -d -r1.50 -r1.51
--- main.c	18 Apr 2003 18:47:49 -0000	1.50
+++ main.c	1 May 2003 22:55:51 -0000	1.51
@@ -325,7 +325,7 @@
     if(options.APPort && time_to_new_circuit < now.tv_sec) {
       circuit_expire_unused_circuits();
       circuit_launch_new(-1); /* tell it to forget about previous failures */
-      circ = circuit_get_newest_by_edge_type(EDGE_AP);
+      circ = circuit_get_newest_ap();
       if(!circ || circ->dirty) {
         log(LOG_INFO,"prepare_for_poll(): Youngest circuit %s; launching replacement.", circ ? "dirty" : "missing");
         circuit_launch_new(0); /* make an onion and lay the circuit */

Index: onion.c
===================================================================
RCS file: /home/or/cvsroot/src/or/onion.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- onion.c	1 May 2003 19:42:51 -0000	1.40
+++ onion.c	1 May 2003 22:55:51 -0000	1.41
@@ -434,22 +434,24 @@
 /* creates a new onion from route, stores it and its length into buf and len respectively */
 unsigned char *create_onion(routerinfo_t **rarray, int rarray_len, unsigned int *route, int routelen, int *len, crypt_path_t **cpath)
 {
-  int i,j;
+  int i;
   char *layerp;
-  crypt_path_t *hop = NULL;
+  crypt_path_t *hop;
   unsigned char *buf;
   routerinfo_t *router;
   unsigned char iv[16];
   struct in_addr netaddr;
   onion_layer_t layer;
 
-  assert(rarray && route && len && routelen);
+  assert(rarray && route && len && routelen && cpath);
+
+  *cpath = NULL;
 
   /* calculate the size of the onion */
   *len = routelen * ONION_LAYER_SIZE + ONION_PADDING_SIZE;
   /* 28 bytes per layer + 100 bytes padding for the innermost layer */
   log(LOG_DEBUG,"create_onion() : Size of the onion is %u.",*len);
-    
+
   /* allocate memory for the onion */
   buf = malloc(*len);
   if(!buf) {
@@ -457,7 +459,7 @@
     return NULL;
   }
   log(LOG_DEBUG,"create_onion() : Allocated memory for the onion.");
-    
+
   for(i=0; i<routelen; i++) {
     netaddr.s_addr = htonl((rarray[route[i]])->addr);
 
@@ -467,29 +469,20 @@
         (rarray[route[i]])->pkey,
         crypto_pk_keysize((rarray[route[i]])->pkey));
   }
-    
+
   layerp = buf + *len - ONION_LAYER_SIZE - ONION_PADDING_SIZE; /* pointer to innermost layer */
   /* create the onion layer by layer, starting with the innermost */
   for (i=0;i<routelen;i++) {
     router = rarray[route[i]];
-      
-//      log(LOG_DEBUG,"create_onion() : %u",router);
-//      log(LOG_DEBUG,"create_onion() : This router is %s:%u",inet_ntoa(*((struct in_addr *)&router->addr)),router->or_port);
-//      log(LOG_DEBUG,"create_onion() : Key pointer = %u.",router->pkey);
-//      log(LOG_DEBUG,"create_onion() : Key size = %u.",crypto_pk_keysize(router->pkey)); 
-    
 
     layer.version = OR_VERSION;
-    if (i) /* not last hop */
+    if (i) { /* not last hop */
       layer.port = rarray[route[i-1]]->or_port;
-    else
-      layer.port = 0;
-
-    /* Dest Addr */
-    if (i) /* not last hop */
       layer.addr = rarray[route[i-1]]->addr;
-    else
+    } else {
+      layer.port = 0;
       layer.addr = 0;
+    }
 
     /* Expiration Time */
     layer.expire = (uint32_t)(time(NULL) + 86400); /* NOW + 1 day */
@@ -503,47 +496,53 @@
     onion_pack(layerp, &layer);
 
 //      log(LOG_DEBUG,"create_onion() : Onion layer %u built : %u, %u, %u, %s, %u.",i+1,layer->zero,layer->backf,layer->forwf,inet_ntoa(*((struct in_addr *)&layer->addr)),layer->port);
-      
+
     /* build up the crypt_path */
-    if(cpath) {
-      cpath[i] = (crypt_path_t *)malloc(sizeof(crypt_path_t));
-      if(!cpath[i]) {
-        log(LOG_ERR,"Error allocating memory.");
-        goto error;
-      }
-      
-      log(LOG_DEBUG,"create_onion() : Building hop %u of crypt path.",i+1);
-      hop = cpath[i];
+    hop = (crypt_path_t *)malloc(sizeof(crypt_path_t));
+    if(!hop) {
+      log(LOG_ERR,"Error allocating memory.");
+      goto error;
+    }
 
-      /* calculate keys */
-      crypto_SHA_digest(layer.keyseed,16,hop->digest3);
-      log(LOG_DEBUG,"create_onion() : First SHA pass performed.");
-      crypto_SHA_digest(hop->digest3,20,hop->digest2);
-      log(LOG_DEBUG,"create_onion() : Second SHA pass performed.");
-      crypto_SHA_digest(hop->digest2,20,hop->digest3);
-      log(LOG_DEBUG,"create_onion() : Third SHA pass performed.");
-      log(LOG_DEBUG,"create_onion() : Keys generated.");
-      /* set IV to zero */
-      memset((void *)iv,0,16);
+    /* link hop into the cpath, at the front */
+    hop->next = *cpath;
+    hop->prev = NULL;
+    hop->state = CPATH_STATE_OPEN; /* change when we move to incremental paths */
+    if(*cpath) {
+      (*cpath)->prev = hop;
+    }
+    *cpath = hop;
 
-      /* initialize cipher engines */
-      if (! (hop->f_crypto = 
-             crypto_create_init_cipher(DEFAULT_CIPHER, hop->digest3, iv, 1))) {
-        /* cipher initialization failed */
-        log(LOG_ERR,"Could not create a crypto environment.");
-        goto error;
-      }
+    log(LOG_DEBUG,"create_onion() : Building hop %u of crypt path.",i+1);
 
-      if (! (hop->b_crypto = 
-             crypto_create_init_cipher(DEFAULT_CIPHER, hop->digest2, iv, 0))) {
-        /* cipher initialization failed */
-        log(LOG_ERR,"Could not create a crypto environment.");
-        goto error;
-      }
- 
-      log(LOG_DEBUG,"create_onion() : Built corresponding crypt path hop.");
+    /* calculate keys */
+    crypto_SHA_digest(layer.keyseed,16,hop->digest3);
+    log(LOG_DEBUG,"create_onion() : First SHA pass performed.");
+    crypto_SHA_digest(hop->digest3,20,hop->digest2);
+    log(LOG_DEBUG,"create_onion() : Second SHA pass performed.");
+    crypto_SHA_digest(hop->digest2,20,hop->digest3);
+    log(LOG_DEBUG,"create_onion() : Third SHA pass performed.");
+    log(LOG_DEBUG,"create_onion() : Keys generated.");
+    /* set IV to zero */
+    memset((void *)iv,0,16);
+
+    /* initialize cipher engines */
+    if (! (hop->f_crypto = 
+           crypto_create_init_cipher(DEFAULT_CIPHER, hop->digest3, iv, 1))) {
+      /* cipher initialization failed */
+      log(LOG_ERR,"Could not create a crypto environment.");
+      goto error;
     }
-      
+
+    if (! (hop->b_crypto = 
+           crypto_create_init_cipher(DEFAULT_CIPHER, hop->digest2, iv, 0))) {
+      /* cipher initialization failed */
+      log(LOG_ERR,"Could not create a crypto environment.");
+      goto error;
+    }
+
+    log(LOG_DEBUG,"create_onion() : Built corresponding crypt path hop.");
+
     /* padding if this is the innermost layer */
     if (!i) {
       if (crypto_pseudo_rand(ONION_PADDING_SIZE, layerp + ONION_LAYER_SIZE)) { /* error */
@@ -552,7 +551,7 @@
       }
       log(LOG_DEBUG,"create_onion() : This is the innermost layer. Adding 100 bytes of padding.");
     }
-      
+
     /* encrypt */
 
     if(encrypt_onion(layerp,ONION_PADDING_SIZE+(i+1)*ONION_LAYER_SIZE,router->pkey,layer.keyseed) < 0) {
@@ -560,25 +559,22 @@
       goto error;
     }
     log(LOG_DEBUG,"create_onion() : Encrypted layer.");
-      
+
     /* calculate pointer to next layer */
     layerp = buf + (routelen-i-2)*ONION_LAYER_SIZE;
   }
 
+  /* now link cpath->prev to the end of cpath */
+  for(hop=*cpath; hop->next; hop=hop->next) ;
+  hop->next = *cpath;
+  (*cpath)->prev = hop;
+
   return buf;
 
  error:
-  if (buf)
+  if(buf)
     free(buf);
-  if (cpath) {
-    for (j=0;j<i;j++) {
-      if(cpath[i]->f_crypto)
-        crypto_free_cipher_env(cpath[i]->f_crypto);
-      if(cpath[i]->b_crypto)
-        crypto_free_cipher_env(cpath[i]->b_crypto);
-      free((void *)cpath[i]);
-    }
-  }
+  circuit_free_cpath(*cpath);
   return NULL;
 }
 

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.69
retrieving revision 1.70
diff -u -d -r1.69 -r1.70
--- or.h	1 May 2003 06:42:29 -0000	1.69
+++ or.h	1 May 2003 22:55:51 -0000	1.70
@@ -342,7 +342,14 @@
   /* crypto environments */
   crypto_cipher_env_t *f_crypto;
   crypto_cipher_env_t *b_crypto;
-  
+
+  char state;
+#define CPATH_STATE_CLOSED 0
+#define CPATH_STATE_AWAITING_KEY 1
+#define CPATH_STATE_OPEN 2
+  void *next;
+  void *prev; /* doubly linked list */
+
 } crypt_path_t;
 
 struct relay_queue_t {
@@ -355,7 +362,7 @@
   uint32_t n_addr;
   uint16_t n_port;
   connection_t *p_conn;
-  connection_t *n_conn;
+  connection_t *n_conn; /* convention: first conn is the OR conn, if there is one */
   int n_receive_circwindow;
   int p_receive_circwindow;
 
@@ -364,11 +371,10 @@
 
   struct relay_queue_t *relay_queue; /* for queueing cells at the edges */
 
-  crypto_cipher_env_t *p_crypto; /* crypto environments */
+  crypto_cipher_env_t *p_crypto; /* used only for intermediate hops */
   crypto_cipher_env_t *n_crypto;
 
-  crypt_path_t **cpath;
-  int cpathlen; 
+  crypt_path_t *cpath;
 
   uint32_t expire; /* expiration time for the corresponding onion */
   long timestamp_created;
@@ -497,7 +503,7 @@
 
 circuit_t *circuit_get_by_aci_conn(aci_t aci, connection_t *conn);
 circuit_t *circuit_get_by_conn(connection_t *conn);
-circuit_t *circuit_get_newest_by_edge_type(char edge_type);
+circuit_t *circuit_get_newest_ap(void);
 circuit_t *circuit_enumerate_by_naddr_nport(circuit_t *start, uint32_t naddr, uint16_t nport);
 
 int circuit_deliver_relay_cell_from_edge(cell_t *cell, circuit_t *circ, char edge_type);
@@ -510,7 +516,8 @@
 
 int circuit_init(circuit_t *circ, int aci_type, onion_layer_t *layer);
 void circuit_free(circuit_t *circ);
-void circuit_free_cpath(crypt_path_t **cpath, int cpathlen);
+void circuit_free_cpath(crypt_path_t *cpath);
+void circuit_free_cpath_node(crypt_path_t *victim);
 
 void circuit_close(circuit_t *circ);
 
@@ -523,7 +530,7 @@
 void circuit_launch_new(int failure_status);
 int circuit_create_onion(void);
 int circuit_establish_circuit(unsigned int *route, int routelen, char *onion,
-                                   int onionlen, crypt_path_t **cpath);
+                                   int onionlen, crypt_path_t *cpath);
 void circuit_n_conn_open(connection_t *or_conn);
 int circuit_send_onion(connection_t *or_conn, circuit_t *circ);
 

Index: test.c
===================================================================
RCS file: /home/or/cvsroot/src/or/test.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- test.c	1 May 2003 19:42:51 -0000	1.9
+++ test.c	1 May 2003 22:55:51 -0000	1.10
@@ -475,7 +475,7 @@
   test_buffers();
   puts("========================== Crypto ==========================");
   test_crypto_dh();
-  test_crypto(); /* this seg faults :( */  /* Still? -NM 2003/04/30 */
+  test_crypto();
   puts("\n========================== Util ============================");
   test_util();
   puts("");



More information about the tor-commits mailing list