[or-cvs] Refactor directories; add unit tests; add router keyword

Nick Mathewson nickm at seul.org
Tue May 6 17:38:19 UTC 2003


Update of /home/or/cvsroot/src/or
In directory moria.mit.edu:/tmp/cvs-serv27084/or

Modified Files:
	main.c onion.c or.h routers.c test.c 
Log Message:
Refactor directories; add unit tests; add router keyword

Index: main.c
===================================================================
RCS file: /home/or/cvsroot/src/or/main.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -d -r1.52 -r1.53
--- main.c	5 May 2003 23:24:45 -0000	1.52
+++ main.c	6 May 2003 17:38:15 -0000	1.53
@@ -565,7 +565,7 @@
     return 0;
   }
 
-  result = snprintf(s, maxlen, "%s %d %d %d %d %d\n%s",
+  result = snprintf(s, maxlen, "router %s %d %d %d %d %d\n%s",
     router->address,
     router->or_port,
     router->op_port,

Index: onion.c
===================================================================
RCS file: /home/or/cvsroot/src/or/onion.c,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -d -r1.45 -r1.46
--- onion.c	6 May 2003 05:54:42 -0000	1.45
+++ onion.c	6 May 2003 17:38:15 -0000	1.46
@@ -347,6 +347,7 @@
   int routelen; /* length of the route */
   unsigned int *route; /* hops in the route as an array of indexes into rarray */
   crypt_path_t *cpath=NULL;
+  directory_t *dir;
   routerinfo_t **rarray;
   int rarray_len;
   int i;
@@ -354,7 +355,9 @@
   routerinfo_t *router;
   struct in_addr netaddr;
 
-  router_get_rarray(&rarray, &rarray_len);
+  router_get_directory(&dir);
+  rarray = dir->routers;
+  rarray_len = dir->n_routers;
 
   /* choose a route */
   route = new_route(options.CoinWeight, rarray, rarray_len, &routelen);

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.74
retrieving revision 1.75
diff -u -d -r1.74 -r1.75
--- or.h	6 May 2003 05:54:42 -0000	1.74
+++ or.h	6 May 2003 17:38:16 -0000	1.75
@@ -328,6 +328,11 @@
   void *next;
 } routerinfo_t;
 
+typedef struct {
+  routerinfo_t **routers;
+  int n_routers;
+} directory_t;
+
 struct crypt_path_t { 
 
   /* crypto environments */
@@ -779,11 +784,13 @@
 void router_retry_connections(void);
 routerinfo_t *router_pick_directory_server(void);
 routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port);
-void router_get_rarray(routerinfo_t ***prouter_array, int *prarray_len);
+void router_get_directory(directory_t **pdirectory);
 int router_is_me(uint32_t addr, uint16_t port);
 void router_forget_router(uint32_t addr, uint16_t port);
 int router_get_list_from_file(char *routerfile);
 int router_get_list_from_string(char *s);
+int router_get_list_from_string_impl(char *s, directory_t **dest);
+routerinfo_t *router_get_entry_from_string(char **s);
 
 int router_compare_to_exit_policy(connection_t *conn);
 

Index: routers.c
===================================================================
RCS file: /home/or/cvsroot/src/or/routers.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- routers.c	5 May 2003 23:24:46 -0000	1.22
+++ routers.c	6 May 2003 17:38:16 -0000	1.23
@@ -9,8 +9,7 @@
 /****************************************************************************/
 
 /* router array */
-static routerinfo_t **router_array = NULL;
-static int rarray_len = 0;
+static directory_t *directory = NULL;
 
 extern or_options_t options; /* command-line and config-file options */
 extern routerinfo_t *my_routerinfo; /* from main.c */
@@ -22,7 +21,7 @@
 static routerinfo_t **make_rarray(routerinfo_t* list, int *len);
 static char *eat_whitespace(char *s);
 static char *find_whitespace(char *s);
-static routerinfo_t *router_get_entry_from_string(char **s);
+static int router_resolve(routerinfo_t *router);
 static void router_add_exit_policy(routerinfo_t *router, char *string);
 static void router_free_exit_policy(routerinfo_t *router);
 
@@ -57,8 +56,8 @@
   int i;
   routerinfo_t *router;
 
-  for (i=0;i<rarray_len;i++) {
-    router = router_array[i];
+  for (i=0;i<directory->n_routers;i++) {
+    router = directory->routers[i];
     if(!connection_exact_get_by_addr_port(router->addr,router->or_port)) { /* not in the list */
       log(LOG_DEBUG,"retry_all_connections(): connecting to OR %s:%u.",router->address,router->or_port);
       connection_or_connect_as_or(router);
@@ -71,11 +70,11 @@
   int i;
   routerinfo_t *router;
   
-  if(!router_array)
+  if(!directory)
     return NULL;
 
-  for(i=0;i<rarray_len;i++) {
-    router = router_array[i];
+  for(i=0;i<directory->n_routers;i++) {
+    router = directory->routers[i];
     if(router->dir_port > 0)
       return router;
   }
@@ -87,10 +86,10 @@
   int i;
   routerinfo_t *router;
 
-  assert(router_array);
+  assert(directory);
 
-  for(i=0;i<rarray_len;i++) {
-    router = router_array[i];
+  for(i=0;i<directory->n_routers;i++) {
+    router = directory->routers[i];
     if ((router->addr == addr) && (router->or_port == port))
       return router;
   }
@@ -98,9 +97,8 @@
   return NULL;
 }
 
-void router_get_rarray(routerinfo_t ***prouter_array, int *prarray_len) {
-  *prouter_array = router_array;
-  *prarray_len = rarray_len;
+void router_get_directory(directory_t **pdirectory) {
+  *pdirectory = directory;
 }
 
 /* return 1 if addr and port corresponds to my addr and my or_listenport. else 0,
@@ -129,6 +127,7 @@
 static void routerlist_free(routerinfo_t *list)
 {
   routerinfo_t *tmp = NULL;
+  struct exit_policy_t *e = NULL, *etmp = NULL;
   
   if (!list)
     return;
@@ -136,8 +135,19 @@
   do
   {
     tmp=list->next;
-    free((void *)list->address);
-    crypto_free_pk_env(list->pkey);
+    if (list->address)
+      free((void *)list->address);
+    if (list->pkey)
+      crypto_free_pk_env(list->pkey);
+    e = list->exit_policy;
+    while (e) {
+      etmp = e->next;
+      if (e->string) free(e->string);
+      if (e->address) free(e->address);
+      if (e->port) free(e->port);
+      free(e);
+      e = etmp;
+    }
     free((void *)list);
     list = tmp;
   }
@@ -153,6 +163,12 @@
   free(list);
 }
 
+void directory_free(directory_t *directory)
+{
+  rarray_free(directory->routers);
+  free(directory);
+}
+
 void router_forget_router(uint32_t addr, uint16_t port) {
   int i;
   routerinfo_t *router;
@@ -162,17 +178,17 @@
     return;
 
   /* now walk down router_array until we get to router */
-  for(i=0;i<rarray_len;i++)
-    if(router_array[i] == router)
+  for(i=0;i<directory->n_routers;i++)
+    if(directory->routers[i] == router)
       break;
 
-  assert(i != rarray_len); /* if so then router_get_by_addr_port should have returned null */
+  assert(i != directory->n_routers); /* if so then router_get_by_addr_port should have returned null */
 
 //  free(router); /* don't actually free; we'll free it when we free the whole thing */
 
 //  log(LOG_DEBUG,"router_forget_router(): Forgot about router %d:%d",addr,port);
-  for(; i<rarray_len-1;i++)
-    router_array[i] = router_array[i+1];
+  for(; i<directory->n_routers-1;i++)
+    directory->routers[i] = directory->routers[i+1];
 }
 
 /* create a NULL-terminated array of pointers pointing to elements of a router list */
@@ -272,7 +288,13 @@
   return 0;
 } 
 
-int router_get_list_from_string(char *s) {
+int router_get_list_from_string(char *s) 
+{
+  return router_get_list_from_string_impl(s, &directory);
+}
+
+int router_get_list_from_string_impl(char *s, directory_t **dest)
+{
   routerinfo_t *routerlist=NULL;
   routerinfo_t *router;
   routerinfo_t **new_router_array;
@@ -286,6 +308,11 @@
       routerlist_free(routerlist);
       return -1;
     }
+    if (router_resolve(router)) {
+      routerlist_free(router);      
+      routerlist_free(routerlist);
+      return -1;
+    }
     switch(router_is_me(router->addr, router->or_port)) {
       case 0: /* it's not me */
         router->next = routerlist;
@@ -307,9 +334,11 @@
  
   new_router_array = make_rarray(routerlist, &new_rarray_len);
   if(new_router_array) { /* success! replace the old one */
-    rarray_free(router_array); /* free the old one first */
-    router_array = new_router_array;
-    rarray_len = new_rarray_len;
+    if (*dest) 
+      directory_free(*dest);
+    *dest = (directory_t*) malloc(sizeof(directory_t));
+    (*dest)->routers = new_router_array;
+    (*dest)->n_routers = new_rarray_len;
     return 0;
   }
   return -1;
@@ -342,14 +371,38 @@
   return s;
 }
 
+static int 
+router_resolve(routerinfo_t *router)
+{
+  struct hostent *rent;
+
+  rent = (struct hostent *)gethostbyname(router->address);
+  if (!rent) {
+    log(LOG_ERR,"router_resolve(): Could not get address for router %s.",router->address);
+    return -1; 
+  }
+  assert(rent->h_length == 4);
+  memcpy(&router->addr, rent->h_addr,rent->h_length);
+  router->addr = ntohl(router->addr); /* get it back into host order */
+
+  return 0;
+}
+
 /* reads a single router entry from s.
  * updates s so it points to after the router it just read.
  * mallocs a new router, returns it if all goes well, else returns NULL.
  */
-static routerinfo_t *router_get_entry_from_string(char **s) {
+routerinfo_t *router_get_entry_from_string(char **s) {
   routerinfo_t *router;
   char *next;
-  struct hostent *rent;
+
+  /* Make sure that this string really starts with a router entry. */
+  *s = eat_whitespace(*s);
+  if (strncasecmp(*s, "router ", 7)) {
+    log(LOG_ERR,"router_get_entry_from_string(): Entry does not start with \"router\"");
+    return NULL;
+  }
+  puts("X");
 
   router = malloc(sizeof(routerinfo_t));
   if (!router) {
@@ -357,6 +410,7 @@
     return NULL;
   }
   memset(router,0,sizeof(routerinfo_t)); /* zero it out first */
+  router->next = NULL;
 
 /* Bug: if find_whitespace returns a '#', we'll squish it. */
 #define NEXT_TOKEN(s, next)    \
@@ -367,19 +421,17 @@
   }                            \
   *next = 0;
 
+  /* Skip the "router" */
+  NEXT_TOKEN(s, next);
+  *s = next+1;
+
   /* read router->address */
   NEXT_TOKEN(s, next);
   router->address = strdup(*s);
   *s = next+1;
 
-  rent = (struct hostent *)gethostbyname(router->address);
-  if (!rent) {
-    log(LOG_ERR,"router_get_entry_from_string(): Could not get address for router %s.",router->address);
-    goto router_read_failed;
-  }
-  assert(rent->h_length == 4);
-  memcpy(&router->addr, rent->h_addr,rent->h_length);
-  router->addr = ntohl(router->addr); /* get it back into host order */
+  /* Don't resolve address till later. */
+  router->addr = 0;
 
   /* read router->or_port */
   NEXT_TOKEN(s, next);

Index: test.c
===================================================================
RCS file: /home/or/cvsroot/src/or/test.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- test.c	6 May 2003 05:54:42 -0000	1.12
+++ test.c	6 May 2003 17:38:16 -0000	1.13
@@ -462,8 +462,6 @@
 
 void
 test_onion_handshake() {
-  int i;
-
   /* client-side */
   crypto_dh_env_t *c_dh = NULL;
   char c_buf[DH_ONIONSKIN_LEN];
@@ -500,6 +498,114 @@
   test_memneq(c_keys, s_buf, 40);
 }
 
+/* from main.c */
+int dump_router_to_string(char *s, int maxlen, routerinfo_t *router);
+void dump_directory_to_string(char *s, int maxlen);
+
+void
+test_dir_format()
+{
+  
+  char buf[2048], buf2[512];
+  char *pk1_str, *pk2_str, *cp;
+  int pk1_str_len, pk2_str_len;
+  routerinfo_t r1, r2;
+  crypto_pk_env_t *pk1 = NULL, *pk2 = NULL;
+  routerinfo_t *rp1, *rp2;
+  struct exit_policy_t ex1, ex2, ex3;
+
+  int i;
+
+  test_assert( (pk1 = crypto_new_pk_env(CRYPTO_PK_RSA)) );
+  test_assert( (pk2 = crypto_new_pk_env(CRYPTO_PK_RSA)) );
+  test_assert(! crypto_pk_generate_key(pk1));
+  test_assert(! crypto_pk_generate_key(pk2));
+  
+  r1.address = "testaddr1.foo.bar";
+  r1.addr = 0xc0a80001u; /* 192.168.0.1 */
+  r1.or_port = 9000;
+  r1.op_port = 9001;
+  r1.ap_port = 9002;
+  r1.dir_port = 9003;
+  r1.pkey = pk1;
+  r1.bandwidth = 1000;
+  r1.exit_policy = NULL;
+  r1.next = &r2;
+
+  ex1.policy_type = EXIT_POLICY_ACCEPT;
+  ex1.string = NULL;
+  ex1.address = "*";
+  ex1.port = "80";
+  ex1.next = &ex2;
+  ex2.policy_type = EXIT_POLICY_REJECT;
+  ex2.address = "18.*";
+  ex2.port = "24";
+  ex2.next = NULL;
+  r2.address = "tor.tor.tor";
+  r2.addr = 0x0a030201u; /* 10.3.2.1 */
+  r2.or_port = 9005;
+  r2.op_port = 0;
+  r2.ap_port = 0;
+  r2.dir_port = 0;
+  r2.pkey = pk2;
+  r2.bandwidth = 3000;
+  r2.exit_policy = &ex1;
+  r2.next = NULL;
+
+  test_assert(!crypto_pk_write_public_key_to_string(pk1, &pk1_str, 
+                                                    &pk1_str_len));
+  test_assert(!crypto_pk_write_public_key_to_string(pk2 , &pk2_str, 
+                                                    &pk2_str_len));
+  strcpy(buf2, "router testaddr1.foo.bar 9000 9001 9002 9003 1000\n");
+  strcat(buf2, pk1_str);
+  strcat(buf2, "\n");
+  
+  memset(buf, 0, 2048);
+  test_assert(dump_router_to_string(buf, 2048, &r1)>0);
+  test_streq(buf, buf2);
+
+  cp = buf;
+  rp1 = router_get_entry_from_string(&cp);
+  test_assert(rp1);
+  test_streq(rp1->address, r1.address);
+  test_eq(rp1->or_port, r1.or_port);
+  test_eq(rp1->op_port, r1.op_port);
+  test_eq(rp1->ap_port, r1.ap_port);
+  test_eq(rp1->dir_port, r1.dir_port);
+  test_eq(rp1->bandwidth, r1.bandwidth);
+  test_assert(crypto_pk_cmp_keys(rp1->pkey, pk1) == 0);
+  test_assert(rp1->exit_policy == NULL);
+
+  strcpy(buf2, "router tor.tor.tor 9005 0 0 0 3000\n");
+  strcat(buf2, pk2_str);
+  strcat(buf2, "accept *:80\nreject 18.*:24\n\n");
+  test_assert(dump_router_to_string(buf, 2048, &r2)>0);
+  test_streq(buf, buf2);
+
+  cp = buf;
+  rp2 = router_get_entry_from_string(&cp);
+  test_assert(rp2);
+  test_streq(rp2->address, r2.address);
+  test_eq(rp2->or_port, r2.or_port);
+  test_eq(rp2->op_port, r2.op_port);
+  test_eq(rp2->ap_port, r2.ap_port);
+  test_eq(rp2->dir_port, r2.dir_port);
+  test_eq(rp2->bandwidth, r2.bandwidth);
+  test_assert(crypto_pk_cmp_keys(rp2->pkey, pk2) == 0);
+  test_eq(rp2->exit_policy->policy_type, EXIT_POLICY_ACCEPT);
+  test_streq(rp2->exit_policy->string, "accept *:80");
+  test_streq(rp2->exit_policy->address, "*");
+  test_streq(rp2->exit_policy->port, "80");
+  test_eq(rp2->exit_policy->next->policy_type, EXIT_POLICY_REJECT);
+  test_streq(rp2->exit_policy->next->string, "reject 18.*:24");
+  test_streq(rp2->exit_policy->next->address, "18.*");
+  test_streq(rp2->exit_policy->next->port, "24");
+  test_assert(rp2->exit_policy->next->next == NULL);
+  
+  
+  /* XXXX free everything*/
+}
+
 int 
 main(int c, char**v) {
 #if 0
@@ -511,6 +617,7 @@
   log(LOG_ERR,NULL);         /* make logging quieter */
 
   setup_directory();
+#if 1
   puts("========================== Buffers =========================");
   test_buffers();
   puts("========================== Crypto ==========================");
@@ -518,8 +625,11 @@
   test_crypto();
   puts("\n========================= Util ============================");
   test_util();
-  puts("\n========================= Onion Skins======================");
+  puts("\n========================= Onion Skins =====================");
   test_onion_handshake();
+#endif
+  puts("\n========================= Directory Formats ===============");
+  test_dir_format();
   puts("");
   return 0;
 }



More information about the tor-commits mailing list