[or-cvs] r11654: Backend for descriptor annotations: parse annotations as key (in tor/trunk: . src/or)

nickm at seul.org nickm at seul.org
Wed Sep 26 16:19:44 UTC 2007


Author: nickm
Date: 2007-09-26 12:19:44 -0400 (Wed, 26 Sep 2007)
New Revision: 11654

Modified:
   tor/trunk/
   tor/trunk/src/or/dirserv.c
   tor/trunk/src/or/or.h
   tor/trunk/src/or/router.c
   tor/trunk/src/or/routerlist.c
   tor/trunk/src/or/routerparse.c
   tor/trunk/src/or/test.c
Log:
 r15400 at catbus:  nickm | 2007-09-26 12:13:12 -0400
 Backend for descriptor annotations: parse annotations as keywords; only allow them to appear in the cache; do not serve them as part of the descriptor if we are a dirserver.  Still need mechanism to set annotations.  Still need to rename cache file.



Property changes on: tor/trunk
___________________________________________________________________
 svk:merge ticket from /tor/trunk [r15400] on 8246c3cf-6607-4228-993b-4d95d33730f1

Modified: tor/trunk/src/or/dirserv.c
===================================================================
--- tor/trunk/src/or/dirserv.c	2007-09-26 14:52:10 UTC (rev 11653)
+++ tor/trunk/src/or/dirserv.c	2007-09-26 16:19:44 UTC (rev 11654)
@@ -536,7 +536,7 @@
 
   s = desc;
   list = smartlist_create();
-  if (!router_parse_list_from_string(&s, NULL, list, SAVED_NOWHERE, 0)) {
+  if (!router_parse_list_from_string(&s, NULL, list, SAVED_NOWHERE, 0, 0)) {
     SMARTLIST_FOREACH(list, routerinfo_t *, ri, {
         msg_out = NULL;
 
@@ -561,7 +561,7 @@
   smartlist_clear(list);
 
   s = desc;
-  if (!router_parse_list_from_string(&s, NULL, list, SAVED_NOWHERE, 1)) {
+  if (!router_parse_list_from_string(&s, NULL, list, SAVED_NOWHERE, 1, 0)) {
     SMARTLIST_FOREACH(list, extrainfo_t *, ei, {
         msg_out = NULL;
 

Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h	2007-09-26 14:52:10 UTC (rev 11653)
+++ tor/trunk/src/or/or.h	2007-09-26 16:19:44 UTC (rev 11654)
@@ -20,23 +20,15 @@
 #define WIN32_LEAN_AND_MEAN
 #endif
 
-// #include <stdio.h>
-// #include <stdlib.h>
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
-//#ifdef HAVE_STRING_H
-//#include <string.h>
-//#endif
 #ifdef HAVE_SIGNAL_H
 #include <signal.h>
 #endif
 #ifdef HAVE_NETDB_H
 #include <netdb.h>
 #endif
-//#ifdef HAVE_CTYPE_H
-//#include <ctype.h>
-//#endif
 #ifdef HAVE_SYS_PARAM_H
 #include <sys/param.h> /* FreeBSD needs this to know what version it is */
 #endif
@@ -53,21 +45,12 @@
 #ifdef HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
 #endif
-//#ifdef HAVE_SYS_SOCKET_H
-//#include <sys/socket.h>
-//#endif
 #ifdef HAVE_SYS_UN_H
 #include <sys/un.h>
 #endif
-//#ifdef HAVE_SYS_TIME_H
-//#include <sys/time.h>
-//#endif
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
 #endif
-//#ifdef HAVE_NETINET_IN_H
-//#include <netinet/in.h>
-//#endif
 #ifdef HAVE_ARPA_INET_H
 #include <arpa/inet.h>
 #endif
@@ -91,26 +74,7 @@
 #define MAXCONNECTIONS 15000
 #endif
 
-#if 0
 #ifdef MS_WINDOWS
-/* No, we don't need to redefine FD_SETSIZE before including winsock:
- * we use libevent now, and libevent handles the select() stuff.  Yes,
- * some documents imply that we need to redefine anyway if we're using
- * select() anywhere in our application or in anything it links to: these
- * documents are either the holy texts of a cargo cult of network
- * programmers, or more likely a simplification of what's going on for
- * people who haven't read winsock[2].h for themselves.
- */
-#if defined(_MSC_VER) && (_MSC_VER <= 1300)
-#include <winsock.h>
-#else
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#endif
-#endif
-#endif
-
-#ifdef MS_WINDOWS
 #include <io.h>
 #include <process.h>
 #include <direct.h>
@@ -1118,9 +1082,12 @@
 
 /** Information need to cache an onion router's descriptor. */
 typedef struct signed_descriptor_t {
-  /** Pointer to the raw server descriptor.  Not necessarily NUL-terminated.
-   * If saved_location is SAVED_IN_CACHE, this pointer is null.  */
+  /** Pointer to the raw server descriptor, preceeded by annotatinos.  Not
+   * necessarily NUL-terminated.  If saved_location is SAVED_IN_CACHE, this
+   * pointer is null.  */
   char *signed_descriptor_body;
+  /** Length of the annotations preceeding the server descriptor. */
+  size_t annotations_len;
   /** Length of the server descriptor. */
   size_t signed_descriptor_len;
   /** Digest of the server descriptor, computed as specified in dir-spec.txt */
@@ -1135,7 +1102,7 @@
    * extrainfo. */
   download_status_t ei_dl_status;
   /** Where is the descriptor saved? */
-  saved_location_t saved_location ;
+  saved_location_t saved_location;
   /** If saved_location is SAVED_IN_CACHE or SAVED_IN_JOURNAL, the offset of
    * this descriptor in the corresponding file. */
   off_t saved_offset;
@@ -2894,10 +2861,6 @@
                                        const char *identity);
 int networkstatus_check_consensus_signature(networkstatus_vote_t *consensus,
                                             int warn);
-#if 0
-int networkstatus_add_consensus_signatures(networkstatus_vote_t *target,
-                                           networkstatus_vote_t *src);
-#endif
 int networkstatus_add_detached_signatures(networkstatus_vote_t *target,
                                           ns_detached_signatures_t *sigs);
 char *networkstatus_get_detached_signatures(networkstatus_vote_t *consensus);
@@ -3639,7 +3602,8 @@
 int router_parse_list_from_string(const char **s, const char *eos,
                                   smartlist_t *dest,
                                   saved_location_t saved_location,
-                                  int is_extrainfo);
+                                  int is_extrainfo,
+                                  int allow_annotations);
 int router_parse_routerlist_from_directory(const char *s,
                                            routerlist_t **dest,
                                            crypto_pk_env_t *pkey,
@@ -3648,7 +3612,8 @@
 int router_parse_runningrouters(const char *str);
 int router_parse_directory(const char *str);
 routerinfo_t *router_parse_entry_from_string(const char *s, const char *end,
-                                             int cache_copy);
+                                             int cache_copy,
+                                             int allow_annotations);
 extrainfo_t *extrainfo_parse_entry_from_string(const char *s, const char *end,
                          int cache_copy, struct digest_ri_map_t *routermap);
 addr_policy_t *router_parse_addr_policy_from_string(const char *s,

Modified: tor/trunk/src/or/router.c
===================================================================
--- tor/trunk/src/or/router.c	2007-09-26 14:52:10 UTC (rev 11653)
+++ tor/trunk/src/or/router.c	2007-09-26 16:19:44 UTC (rev 11654)
@@ -485,7 +485,7 @@
       return -1;
     }
     if (mydesc) {
-      ri = router_parse_entry_from_string(mydesc, NULL, 1);
+      ri = router_parse_entry_from_string(mydesc, NULL, 1, 0);
       if (!ri) {
         log_err(LD_GENERAL,"Generated a routerinfo we couldn't parse.");
         return -1;
@@ -1632,7 +1632,7 @@
     const char *cp;
     routerinfo_t *ri_tmp;
     cp = s_dup = tor_strdup(s);
-    ri_tmp = router_parse_entry_from_string(cp, NULL, 1);
+    ri_tmp = router_parse_entry_from_string(cp, NULL, 1, 0);
     if (!ri_tmp) {
       log_err(LD_BUG,
               "We just generated a router descriptor we can't parse.");

Modified: tor/trunk/src/or/routerlist.c
===================================================================
--- tor/trunk/src/or/routerlist.c	2007-09-26 14:52:10 UTC (rev 11653)
+++ tor/trunk/src/or/routerlist.c	2007-09-26 16:19:44 UTC (rev 11654)
@@ -43,6 +43,8 @@
                                                 int warn_if_unnamed);
 static void update_router_have_minimum_dir_info(void);
 static void router_dir_info_changed(void);
+static const char *signed_descriptor_get_body_impl(signed_descriptor_t *desc,
+                                                   int with_annotations);
 
 DECLARE_TYPED_DIGESTMAP_FNS(sdmap_, digest_sd_map_t, signed_descriptor_t)
 DECLARE_TYPED_DIGESTMAP_FNS(rimap_, digest_ri_map_t, routerinfo_t)
@@ -522,8 +524,8 @@
   or_options_t *options = get_options();
   size_t fname_len = strlen(options->DataDirectory)+32;
   char *fname;
-  const char *body = signed_descriptor_get_body(desc);
-  size_t len = desc->signed_descriptor_len;
+  const char *body = signed_descriptor_get_body_impl(desc,1);
+  size_t len = desc->signed_descriptor_len + desc->annotations_len;
 
   if (purpose != ROUTER_PURPOSE_GENERAL &&
       purpose != EXTRAINFO_PURPOSE_GENERAL) {
@@ -629,7 +631,7 @@
   SMARTLIST_FOREACH(signed_descriptors, signed_descriptor_t *, sd,
     {
       sized_chunk_t *c;
-      const char *body = signed_descriptor_get_body(sd);
+      const char *body = signed_descriptor_get_body_impl(sd, 1);
       if (!body) {
         log_warn(LD_BUG, "No descriptor available for router.");
         goto done;
@@ -638,7 +640,7 @@
         continue;
       c = tor_malloc(sizeof(sized_chunk_t));
       c->bytes = body;
-      c->len = sd->signed_descriptor_len;
+      c->len = sd->signed_descriptor_len + sd->annotations_len;
       smartlist_add(chunk_list, c);
     });
 
@@ -1965,21 +1967,29 @@
 /** Return a pointer to the signed textual representation of a descriptor.
  * The returned string is not guaranteed to be NUL-terminated: the string's
  * length will be in desc-\>signed_descriptor_len. */
-const char *
-signed_descriptor_get_body(signed_descriptor_t *desc)
+static const char *
+signed_descriptor_get_body_impl(signed_descriptor_t *desc,
+                                int with_annotations)
 {
   const char *r = NULL;
   size_t len = desc->signed_descriptor_len;
+  off_t offset = desc->saved_offset;
+  if (with_annotations)
+    len += desc->annotations_len;
+  else
+    offset += desc->annotations_len;
+
   tor_assert(len > 32);
   if (desc->saved_location == SAVED_IN_CACHE && routerlist) {
     desc_store_t *store = desc_get_store(router_get_routerlist(), desc);
     if (store && store->mmap) {
       tor_assert(desc->saved_offset + len <= store->mmap->size);
-      r = store->mmap->data + desc->saved_offset;
+      r = store->mmap->data + offset;
     }
   }
   if (!r) /* no mmap, or not in cache. */
-    r = desc->signed_descriptor_body;
+    r = desc->signed_descriptor_body +
+      (with_annotations ? 0 : desc->annotations_len);
 
   tor_assert(r);
   if (memcmp("router ", r, 7) && memcmp("extra-info ", r, 11)) {
@@ -1991,6 +2001,13 @@
   return r;
 }
 
+/** DOCDOC */
+const char *
+signed_descriptor_get_body(signed_descriptor_t *desc)
+{
+  return signed_descriptor_get_body_impl(desc, 0);
+}
+
 /** Return the current list of all known routers. */
 routerlist_t *
 router_get_routerlist(void)
@@ -3089,7 +3106,7 @@
   tor_assert(msg);
   *msg = NULL;
 
-  if (!(ri = router_parse_entry_from_string(s, NULL, 1))) {
+  if (!(ri = router_parse_entry_from_string(s, NULL, 1, 0))) {
     log_warn(LD_DIR, "Error parsing router descriptor; dropping.");
     *msg = "Couldn't parse router descriptor.";
     return -1;
@@ -3147,8 +3164,10 @@
   char fp[HEX_DIGEST_LEN+1];
   const char *msg;
   int from_cache = (saved_location != SAVED_NOWHERE);
+  int allow_annotations = (saved_location != SAVED_NOWHERE);
 
-  router_parse_list_from_string(&s, eos, routers, saved_location, 0);
+  router_parse_list_from_string(&s, eos, routers, saved_location, 0,
+                                allow_annotations);
 
   routers_update_status_from_networkstatus(routers, !from_cache);
 
@@ -3209,7 +3228,7 @@
   const char *msg;
   int from_cache = (saved_location != SAVED_NOWHERE);
 
-  router_parse_list_from_string(&s, eos, extrainfo_list, saved_location, 1);
+  router_parse_list_from_string(&s, eos, extrainfo_list, saved_location, 1, 0);
 
   log_info(LD_DIR, "%d elements to add", smartlist_len(extrainfo_list));
 

Modified: tor/trunk/src/or/routerparse.c
===================================================================
--- tor/trunk/src/or/routerparse.c	2007-09-26 14:52:10 UTC (rev 11653)
+++ tor/trunk/src/or/routerparse.c	2007-09-26 16:19:44 UTC (rev 11654)
@@ -1,4 +1,4 @@
-/* oCpyright (c) 2001 Matej Pfajfar.
+/* Copyright (c) 2001 Matej Pfajfar.
  * Copyright (c) 2001-2004, Roger Dingledine.
  * Copyright (c) 2004-2007, Roger Dingledine, Nick Mathewson. */
 /* See LICENSE for licensing information */
@@ -15,11 +15,9 @@
 
 /****************************************************************************/
 
-/** Enumeration of possible token types.  The ones starting with K_
- * correspond to directory 'keywords'.  _UNRECOGNIZED is for an
- * unrecognized keyword; _ERR is an error in the tokenizing process,
- * _EOF is an end-of-file marker, and _NIL is used to encode
- * not-a-token.
+/** Enumeration of possible token types.  The ones starting with K_ correspond
+ * to directory 'keywords'. _ERR is an error in the tokenizing process, _EOF
+ * is an end-of-file marker, and _NIL is used to encode not-a-token.
  */
 typedef enum {
   K_ACCEPT = 0,
@@ -77,12 +75,18 @@
   K_CONSENSUS_DIGEST,
   K_CONSENSUS_METHODS,
 
+  A_PURPOSE,
+  _A_UNKNOWN,
+
   _UNRECOGNIZED,
   _ERR,
   _EOF,
   _NIL
 } directory_keyword;
 
+#define MIN_ANNOTATION A_PURPOSE
+#define MAX_ANNOTATION _A_UNKNOWN
+
 /** Structure to hold a single directory token.
  *
  * We parse a directory by breaking it into "tokens", each consisting
@@ -139,6 +143,8 @@
   /** One or more of AT_START/AT_END to limit where the item may appear in a
    * document. */
   int pos;
+  /** DOCDOC */
+  int is_annotation;
 } token_rule_t;
 
 /*
@@ -149,21 +155,23 @@
  */
 
 /** Appears to indicate the end of a table. */
-#define END_OF_TABLE { NULL, _NIL, 0,0,0, NO_OBJ, 0, INT_MAX, 0 }
+#define END_OF_TABLE { NULL, _NIL, 0,0,0, NO_OBJ, 0, INT_MAX, 0, 0 }
 /** An item with no restrictions: used for obsolete document types */
-#define T(s,t,a,o)    { s, t, a, o, 0, INT_MAX, 0 }
+#define T(s,t,a,o)    { s, t, a, o, 0, INT_MAX, 0, 0 }
 /** An item with no restrictions on multiplicity or location. */
-#define T0N(s,t,a,o)  { s, t, a, o, 0, INT_MAX, 0 }
+#define T0N(s,t,a,o)  { s, t, a, o, 0, INT_MAX, 0, 0 }
 /** An item that must appear exactly once */
-#define T1(s,t,a,o)   { s, t, a, o, 1, 1, 0 }
+#define T1(s,t,a,o)   { s, t, a, o, 1, 1, 0, 0 }
 /** An item that must appear exactly once, at the start of the document */
-#define T1_START(s,t,a,o)   { s, t, a, o, 1, 1, AT_START }
+#define T1_START(s,t,a,o)   { s, t, a, o, 1, 1, AT_START, 0 }
 /** An item that must appear exactly once, at the end of the document */
-#define T1_END(s,t,a,o)   { s, t, a, o, 1, 1, AT_END }
+#define T1_END(s,t,a,o)   { s, t, a, o, 1, 1, AT_END, 0 }
 /** An item that must appear one or more times */
-#define T1N(s,t,a,o)  { s, t, a, o, 1, INT_MAX, 0 }
+#define T1N(s,t,a,o)  { s, t, a, o, 1, INT_MAX, 0, 0 }
 /** An item that must appear no more than once */
-#define T01(s,t,a,o)  { s, t, a, o, 0, 1, 0 }
+#define T01(s,t,a,o)  { s, t, a, o, 0, 1, 0, 0 }
+/** An annotation that must appear no more than once */
+#define A01(s,t,a,o)  { s, t, a, o, 0, 1, 0, 0 }
 
 /* Argument multiplicity: any number of arguments. */
 #define ARGS        0,INT_MAX,0
@@ -200,6 +208,7 @@
 
   T0N("opt",                 K_OPT,             CONCAT_ARGS, OBJ_OK ),
   T1( "bandwidth",           K_BANDWIDTH,           GE(3),   NO_OBJ ),
+  A01("@purpose",            A_PURPOSE,             GE(1),   NO_OBJ ),
 
   END_OF_TABLE
 };
@@ -365,7 +374,8 @@
                                                 directory_keyword keyword);
 static int tokenize_string(const char *start, const char *end,
                            smartlist_t *out,
-                           token_rule_t *table);
+                           token_rule_t *table,
+                           int allow_annotations);
 static directory_token_t *get_next_token(const char **s,
                                          const char *eos,
                                          token_rule_t *table);
@@ -614,7 +624,7 @@
   }
   ++cp;
   tokens = smartlist_create();
-  if (tokenize_string(cp,strchr(cp,'\0'),tokens,dir_token_table)) {
+  if (tokenize_string(cp,strchr(cp,'\0'),tokens,dir_token_table,0)) {
     log_warn(LD_DIR, "Error tokenizing directory signature"); goto err;
   }
   if (smartlist_len(tokens) != 1) {
@@ -643,7 +653,7 @@
   }
 
   tokens = smartlist_create();
-  if (tokenize_string(str,end,tokens,dir_token_table)) {
+  if (tokenize_string(str,end,tokens,dir_token_table,0)) {
     log_warn(LD_DIR, "Error tokenizing directory"); goto err;
   }
 
@@ -692,7 +702,7 @@
     goto err;
   }
   tokens = smartlist_create();
-  if (tokenize_string(str,eos,tokens,dir_token_table)) {
+  if (tokenize_string(str,eos,tokens,dir_token_table,0)) {
     log_warn(LD_DIR, "Error tokenizing running-routers"); goto err;
   }
   tok = smartlist_get(tokens,0);
@@ -858,7 +868,8 @@
 router_parse_list_from_string(const char **s, const char *eos,
                               smartlist_t *dest,
                               saved_location_t saved_location,
-                              int want_extrainfo)
+                              int want_extrainfo,
+                              int allow_annotations)
 {
   routerinfo_t *router;
   extrainfo_t *extrainfo;
@@ -923,7 +934,8 @@
       }
     } else if (!have_extrainfo && !want_extrainfo) {
       router = router_parse_entry_from_string(*s, end,
-                                          saved_location != SAVED_IN_CACHE);
+                                              saved_location != SAVED_IN_CACHE,
+                                              allow_annotations);
       if (router) {
         signed_desc = &router->cache_info;
         elt = router;
@@ -977,13 +989,14 @@
  */
 routerinfo_t *
 router_parse_entry_from_string(const char *s, const char *end,
-                               int cache_copy)
+                               int cache_copy, int allow_annotations)
 {
   routerinfo_t *router = NULL;
   char digest[128];
   smartlist_t *tokens = NULL, *exit_policy_tokens = NULL;
   directory_token_t *tok;
   struct in_addr in;
+  const char *start_of_annotations, *cp;
 
   if (!end) {
     end = s + strlen(s);
@@ -993,12 +1006,23 @@
   while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
     --end;
 
+  start_of_annotations = s;
+  cp = tor_memstr(s, end-s, "\nrouter ");
+  if (!cp) {
+    if (end-s < 7 || strcmpstart(s, "router ")) {
+      log_warn(LD_DIR, "No router keyword found.");
+      goto err;
+    }
+  } else {
+    s = cp+1;
+  }
+
   if (router_get_router_hash(s, digest) < 0) {
     log_warn(LD_DIR, "Couldn't compute router hash.");
     return NULL;
   }
   tokens = smartlist_create();
-  if (tokenize_string(s,end,tokens,routerdesc_token_table)) {
+  if (tokenize_string(s,end,tokens,routerdesc_token_table,allow_annotations)) {
     log_warn(LD_DIR, "Error tokenizing router descriptor.");
     goto err;
   }
@@ -1019,6 +1043,7 @@
   router->routerlist_index = -1;
   if (cache_copy)
     router->cache_info.signed_descriptor_body = tor_strndup(s, end-s);
+  router->cache_info.signed_descriptor_len = s-start_of_annotations;
   router->cache_info.signed_descriptor_len = end-s;
   memcpy(router->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
 
@@ -1218,13 +1243,13 @@
     return NULL;
   }
   tokens = smartlist_create();
-  if (tokenize_string(s,end,tokens,extrainfo_token_table)) {
-    log_warn(LD_DIR, "Error tokenizing router descriptor.");
+  if (tokenize_string(s,end,tokens,extrainfo_token_table,0)) {
+    log_warn(LD_DIR, "Error tokenizing extra-info document.");
     goto err;
   }
 
   if (smartlist_len(tokens) < 2) {
-    log_warn(LD_DIR, "Impossibly short router descriptor.");
+    log_warn(LD_DIR, "Impossibly short extra-info document.");
     goto err;
   }
 
@@ -1328,7 +1353,7 @@
   len = eos - s;
 
   tokens = smartlist_create();
-  if (tokenize_string(s, eos, tokens, dir_key_certificate_table) < 0) {
+  if (tokenize_string(s, eos, tokens, dir_key_certificate_table,0) < 0) {
     log_warn(LD_DIR, "Error tokenizing key certificate");
     goto err;
   }
@@ -1468,7 +1493,7 @@
 
   eos = find_start_of_next_routerstatus(*s);
 
-  if (tokenize_string(*s, eos, tokens, rtrstatus_token_table)) {
+  if (tokenize_string(*s, eos, tokens, rtrstatus_token_table,0)) {
     log_warn(LD_DIR, "Error tokenizing router status");
     goto err;
   }
@@ -1640,7 +1665,7 @@
   }
 
   eos = find_start_of_next_routerstatus(s);
-  if (tokenize_string(s, eos, tokens, netstatus_token_table)) {
+  if (tokenize_string(s, eos, tokens, netstatus_token_table,0)) {
     log_warn(LD_DIR, "Error tokenizing network-status header.");
     goto err;
   }
@@ -1752,7 +1777,7 @@
   smartlist_uniq(ns->entries, _compare_routerstatus_entries,
                  _free_duplicate_routerstatus_entry);
 
-  if (tokenize_string(s, NULL, footer_tokens, dir_footer_token_table)) {
+  if (tokenize_string(s, NULL, footer_tokens, dir_footer_token_table,0)) {
     log_warn(LD_DIR, "Error tokenizing network-status footer.");
     goto err;
   }
@@ -1812,7 +1837,7 @@
   end_of_header = find_start_of_next_routerstatus(s);
   if (tokenize_string(s, end_of_header, tokens,
                       is_vote ? networkstatus_vote_token_table :
-                                networkstatus_consensus_token_table)) {
+                                networkstatus_consensus_token_table, 0)) {
     log_warn(LD_DIR, "Error tokenizing network-status vote header.");
     goto err;
   }
@@ -2032,7 +2057,7 @@
   else
     end_of_footer = s + strlen(s);
   if (tokenize_string(s, end_of_footer, footer_tokens,
-                      networkstatus_vote_footer_token_table)) {
+                      networkstatus_vote_footer_token_table, 0)) {
     log_warn(LD_DIR, "Error tokenizing network-status vote footer.");
     goto err;
   }
@@ -2143,7 +2168,7 @@
     eos = s + strlen(s);
 
   if (tokenize_string(s, eos, tokens,
-                      networkstatus_detached_signature_token_table)) {
+                      networkstatus_detached_signature_token_table, 0)) {
     log_warn(LD_DIR, "Error tokenizing detached networkstatus signatures");
     goto err;
   }
@@ -2569,8 +2594,12 @@
     }
   }
 
-  if (tok->tp == _ERR) { /* No keyword matched; call it an "opt". */
-    tok->tp = K_OPT;
+  if (tok->tp == _ERR) {
+    /* No keyword matched; call it an "K_opt" or "A_unrecognized" */
+    if (**s == '@')
+      tok->tp = _A_UNKNOWN;
+    else
+      tok->tp = K_OPT;
     tok->args = tor_malloc(sizeof(char*));
     tok->args[0] = tor_strndup(*s, eol-*s);
     tok->n_args = 1;
@@ -2637,12 +2666,13 @@
  */
 static int
 tokenize_string(const char *start, const char *end, smartlist_t *out,
-                token_rule_t *table)
+                token_rule_t *table, int allow_annotations)
 {
   const char **s;
   directory_token_t *tok = NULL;
   int counts[_NIL];
   int i;
+  int first_nonannotation;
 
   s = &start;
   if (!end)
@@ -2661,6 +2691,36 @@
     *s = eat_whitespace_eos(*s, end);
   }
 
+  if (allow_annotations) {
+    first_nonannotation = -1;
+    for (i = 0; i < smartlist_len(out); ++i) {
+      tok = smartlist_get(out, i);
+      if (tok->tp < MIN_ANNOTATION || tok->tp > MAX_ANNOTATION) {
+        first_nonannotation = i;
+        break;
+      }
+    }
+    if (first_nonannotation < 0) {
+      log_warn(LD_DIR, "parse error: item contains only annotations");
+      return -1;
+    }
+    for (i=first_nonannotation;  i < smartlist_len(out); ++i) {
+      tok = smartlist_get(out, i);
+      if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
+        log_warn(LD_DIR, "parse error: Annotations mixed with keywords");
+        return -1;
+      }
+    }
+  } else {
+    for (i=0;  i < smartlist_len(out); ++i) {
+      tok = smartlist_get(out, i);
+      if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
+        log_warn(LD_DIR, "parse error: no annotations allowed.");
+        return -1;
+      }
+    }
+    first_nonannotation = 0;
+  }
   for (i = 0; table[i].t; ++i) {
     if (counts[table[i].v] < table[i].min_cnt) {
       log_warn(LD_DIR, "Parse error: missing %s element.", table[i].t);
@@ -2672,7 +2732,7 @@
     }
     if (table[i].pos & AT_START) {
       if (smartlist_len(out) < 1 ||
-          (tok = smartlist_get(out, 0))->tp != table[i].v) {
+          (tok = smartlist_get(out, first_nonannotation))->tp != table[i].v) {
         log_warn(LD_DIR, "Parse error: first item is not %s.", table[i].t);
         return -1;
       }

Modified: tor/trunk/src/or/test.c
===================================================================
--- tor/trunk/src/or/test.c	2007-09-26 14:52:10 UTC (rev 11653)
+++ tor/trunk/src/or/test.c	2007-09-26 16:19:44 UTC (rev 11654)
@@ -2189,7 +2189,7 @@
 
   test_assert(router_dump_router_to_string(buf, 2048, &r1, pk2)>0);
   cp = buf;
-  rp1 = router_parse_entry_from_string((const char*)cp,NULL,1);
+  rp1 = router_parse_entry_from_string((const char*)cp,NULL,1,0);
   test_assert(rp1);
   test_streq(rp1->address, r1.address);
   test_eq(rp1->or_port, r1.or_port);



More information about the tor-commits mailing list