Sfoglia il codice sorgente

Implement several 008pre1 items: needs more testing

svn:r1981
Nick Mathewson 21 anni fa
parent
commit
8aec3a7301
10 ha cambiato i file con 203 aggiunte e 34 eliminazioni
  1. 14 10
      doc/TODO
  2. 42 9
      src/common/log.c
  3. 37 0
      src/or/config.c
  4. 26 0
      src/or/dirserv.c
  5. 7 0
      src/or/main.c
  6. 4 1
      src/or/or.h
  7. 22 2
      src/or/router.c
  8. 1 0
      src/or/routerlist.c
  9. 49 12
      src/or/routerparse.c
  10. 1 0
      src/or/test.c

+ 14 - 10
doc/TODO

@@ -19,12 +19,12 @@ For scalability:
 For dtor:
 
 NICK  pre1:
-        - make all ORs serve the directory too.
-          - "AuthoritativeDir 1" for dirservers
-          - non-authorative servers with dirport publish opt dircacheport
-          - make clients read that and use it.
-          - make clients able to read a normal dirport from non-trusted OR too
-          - make ORs parse-and-keep the directory they pull down
+        . make all ORs serve the directory too.
+          o "AuthoritativeDir 1" for dirservers
+          o non-authorative servers with dirport publish opt dircacheport
+          o make clients read that and use it.
+          o make clients able to read a normal dirport from non-trusted OR too
+          o make ORs parse-and-keep-and-serve the directory they pull down
           - authoritativedirservers should pull down directories from
             other authdirservers, to merge descriptors.
         - Have clients and dirservers preserve reputation info over
@@ -35,12 +35,16 @@ NICK  pre1:
           - distinguish directory-is-dirty from runninglist-is-dirty
           - ORs keep this too, and serve it
         - tor remembers descriptor-lists across reboots.
-        - Packages define datadir as /var/lib/tor/. If no datadir is defined,
+        . Packages define datadir as /var/lib/tor/. If no datadir is defined,
           then choose, make, and secure ~/.tor as datadir.
-        - Contact info, pgp fingerprint, comments in router desc.
-          - Add a ContactInfo line to torrc, which gets published in
+	  o Adjust tor
+	  o Change torrc.sample
+	  - Change packages
+	  - Look in ~/.torrc if no */etc/torrc is found?
+        o Contact info, pgp fingerprint, comments in router desc.
+          o Add a ContactInfo line to torrc, which gets published in
             descriptor (as opt)
-        - write tor version at the top of each log file
+        o write tor version at the top of each log file
 
       pre2:
         - refer to things by key:

+ 42 - 9
src/common/log.c

@@ -48,20 +48,12 @@ static INLINE const char *sev_to_string(int severity) {
 /** Linked list of logfile_t. */
 static logfile_t *logfiles = NULL;
 
-/** Helper: Format a log message into a fixed-sized buffer. (This is
- * factored out of <b>logv</b> so that we never format a message more
- * than once.)
- */
-static INLINE void format_msg(char *buf, size_t buf_len,
-                              int severity, const char *funcname,
-                              const char *format, va_list ap)
+static INLINE size_t _log_prefix(char *buf, size_t buf_len, int severity)
 {
   time_t t;
   struct timeval now;
   size_t n;
 
-  buf_len -= 2; /* subtract 2 characters so we have room for \n\0 */
-
   tor_gettimeofday(&now);
   t = (time_t)now.tv_sec;
 
@@ -73,6 +65,45 @@ static INLINE void format_msg(char *buf, size_t buf_len,
     n = buf_len-1; /* the *nprintf funcs return how many bytes they
                     * _would_ print, if the output is truncated.
                     * Subtract one because the count doesn't include the \0 */
+  return n;
+}
+
+/** If lf refers to an actual file that we have just opened, and the file
+ * contains no data, log an "opening new logfile" message at the top. **/
+static void log_tor_version(logfile_t *lf)
+{
+  char buf[256];
+  size_t n;
+
+  if (!lf->needs_close)
+    /* If it doesn't get closed, it isn't really a file. */
+    return;
+  if (lf->is_temporary)
+    /* If it's temporary, it isn't really a file. */
+    return;
+  if (ftell(lf->file) != 0)
+    /* We aren't at the start of the file; no need to log. */
+    return;
+  n = _log_prefix(buf, 250, LOG_NOTICE);
+  n += snprintf(buf+n, 250-n, "Tor %s creating new log file\n", VERSION);
+  if (n>250)
+    n = 250;
+  buf[n+1]='\0';
+  fputs(buf, lf->file);
+}
+
+/** Helper: Format a log message into a fixed-sized buffer. (This is
+ * factored out of <b>logv</b> so that we never format a message more
+ * than once.)
+ */
+static INLINE void format_msg(char *buf, size_t buf_len,
+                              int severity, const char *funcname,
+                              const char *format, va_list ap)
+{
+  size_t n;
+  buf_len -= 2; /* subtract 2 characters so we have room for \n\0 */
+
+  n = _log_prefix(buf, buf_len, severity);
 
   if (funcname) {
     n += snprintf(buf+n, buf_len-n, "%s(): ", funcname);
@@ -159,6 +190,7 @@ void reset_logs()
     if (lf->needs_close) {
       fclose(lf->file);
       lf->file = fopen(lf->filename, "a");
+      log_tor_version(lf);
     }
   }
 }
@@ -224,6 +256,7 @@ int add_file_log(int loglevelMin, int loglevelMax, const char *filename)
   if (!f) return -1;
   add_stream_log(loglevelMin, loglevelMax, filename, f);
   logfiles->needs_close = 1;
+  log_tor_version(logfiles);
   return 0;
 }
 

+ 37 - 0
src/or/config.c

@@ -188,10 +188,13 @@ static int config_assign(or_options_t *options, struct config_line_t *list) {
 
     /* string options */
     config_compare(list, "Address",        CONFIG_TYPE_STRING, &options->Address) ||
+    config_compare(list, "AuthoritativeDirectory",CONFIG_TYPE_BOOL, &options->AuthoritativeDir) ||
 
     config_compare(list, "BandwidthRate",  CONFIG_TYPE_INT, &options->BandwidthRate) ||
     config_compare(list, "BandwidthBurst", CONFIG_TYPE_INT, &options->BandwidthBurst) ||
 
+    config_compare(list, "ContactInfo", CONFIG_TYPE_STRING, &options->ContactInfo) ||
+
     config_compare(list, "DebugLogFile",   CONFIG_TYPE_STRING, &options->DebugLogFile) ||
     config_compare(list, "DataDirectory",  CONFIG_TYPE_STRING, &options->DataDirectory) ||
     config_compare(list, "DirPort",        CONFIG_TYPE_INT, &options->DirPort) ||
@@ -627,10 +630,12 @@ int getconfig(int argc, char **argv, or_options_t *options) {
     result = -1;
   }
 
+#if 0
   if(options->ORPort && options->DataDirectory == NULL) {
     log(LOG_WARN,"DataDirectory option required if ORPort is set, but not found.");
     result = -1;
   }
+#endif
 
   if (options->ORPort) {
     if (options->Nickname == NULL) {
@@ -675,6 +680,11 @@ int getconfig(int argc, char **argv, or_options_t *options) {
     result = -1;
   }
 
+  if(options->AuthoritativeDir && !options->DirPort) {
+    log(LOG_WARN,"Running as authoritative directory, but no DirPort set.");
+    result = -1;
+  }
+
   if(options->SocksPort > 1 &&
      (options->PathlenCoinWeight < 0.0 || options->PathlenCoinWeight >= 1.0)) {
     log(LOG_WARN,"PathlenCoinWeight option must be >=0.0 and <1.0.");
@@ -880,6 +890,33 @@ void exit_policy_free(struct exit_policy_t *p) {
   }
 }
 
+const char *get_data_directory(or_options_t *options) {
+  const char *d;
+  char buf[1024];
+  const char *home;
+  size_t n;
+  if (options->DataDirectory)
+    d = options->DataDirectory;
+  else
+    d = "~/.tor";
+
+  if (!strncmp(d,"~/",2)) {
+    home = getenv("HOME");
+    if (!home) {
+      log_fn(LOG_ERR, "Couldn't find $HOME environment variable for data directory %s", d);
+      exit(1);
+    }
+    n = snprintf(buf,1020,"%s/%s",home,d+2);
+    if (n>=1020) {
+      log_fn(LOG_ERR, "Overlong data directory name.");
+      exit(1);
+    }
+    tor_free(options->DataDirectory);
+    options->DataDirectory = tor_strdup(buf);
+  }
+  return options->DataDirectory;
+}
+
 /*
   Local Variables:
   mode:c

+ 26 - 0
src/or/dirserv.c

@@ -576,6 +576,23 @@ dirserv_dump_directory_to_string(char *s, unsigned int maxlen,
 /** Most recently generated encoded signed directory. */
 static char *the_directory = NULL;
 static int the_directory_len = -1;
+static char *cached_directory = NULL;
+static time_t cached_directory_published = 0;
+static int cached_directory_len = -1;
+
+void dirserv_set_cached_directory(const char *directory, time_t when)
+{
+  time_t now;
+  if (!options.AuthoritativeDir)
+    return;
+  now = time(NULL);
+  if (when>cached_directory_published &&
+      when<now+ROUTER_ALLOW_SKEW) {
+    tor_free(cached_directory);
+    cached_directory = tor_strdup(directory);
+    cached_directory_len = strlen(cached_directory);
+  }
+}
 
 /** Set *<b>directory</b> to the most recently generated encoded signed
  * directory, generating a new one as necessary. */
@@ -583,6 +600,15 @@ size_t dirserv_get_directory(const char **directory)
 {
   char *new_directory;
   char filename[512];
+  if (!options.AuthoritativeDir) {
+    if (cached_directory) {
+      *directory = cached_directory;
+      return (size_t) cached_directory_len;
+    } else {
+      /* no directory yet retrieved */
+      return 0;
+    }
+  }
   if (the_directory_is_dirty) {
     new_directory = tor_malloc(MAX_DIR_SIZE);
     if (dirserv_dump_directory_to_string(new_directory, MAX_DIR_SIZE,

+ 7 - 0
src/or/main.c

@@ -576,6 +576,13 @@ static int init_from_config(int argc, char **argv) {
     }
   }
 
+  /* Ensure data directory is private; create if possible. */
+  if (check_private_dir(get_data_directory(&options), 1) != 0) {
+    log_fn(LOG_ERR, "Couldn't access/create private data directory %s",
+           get_data_directory(&options));
+    return -1;
+  }
+
   /* Start backgrounding the process, if requested. */
   if (options.RunAsDaemon) {
     start_daemon(options.DataDirectory);

+ 4 - 1
src/or/or.h

@@ -363,7 +363,6 @@
 #define RELAY_COMMAND_INTRODUCE2 35
 #define RELAY_COMMAND_RENDEZVOUS1 36
 #define RELAY_COMMAND_RENDEZVOUS2 37
-/* DOCDOC Spec these next two. */
 #define RELAY_COMMAND_INTRO_ESTABLISHED 38
 #define RELAY_COMMAND_RENDEZVOUS_ESTABLISHED 39
 #define RELAY_COMMAND_INTRODUCE_ACK 40
@@ -823,6 +822,7 @@ typedef struct {
   int ORPort; /**< Port to listen on for OR connections. */
   int SocksPort; /**< Port to listen on for SOCKS connections. */
   int DirPort; /**< Port to listen on for directory connections. */
+  int AuthoritativeDir; /**< Boolean: is this an authoritative directory? */
   int MaxConn; /**< Maximum number of simultaneous connections. */
   int TrafficShaping; /**< Unused. */
   int LinkPadding; /**< Unused. */
@@ -848,6 +848,7 @@ typedef struct {
                    * other ORs are running. */
   struct config_line_t *RendConfigLines; /**< List of configuration lines
                                           * for rendezvous services. */
+  char *ContactInfo; /** Contact info to be published in the directory */
 } or_options_t;
 
 /* XXX are these good enough defaults? */
@@ -989,6 +990,7 @@ int config_init_logs(or_options_t *options);
 void config_parse_exit_policy(struct config_line_t *cfg,
                               struct exit_policy_t **dest);
 void exit_policy_free(struct exit_policy_t *p);
+const char *get_data_directory(or_options_t *options);
 
 /********************************* connection.c ***************************/
 
@@ -1136,6 +1138,7 @@ int dirserv_dump_directory_to_string(char *s, unsigned int maxlen,
 void directory_set_dirty(void);
 size_t dirserv_get_directory(const char **cp);
 size_t dirserv_get_runningrouters(const char **rr);
+void dirserv_set_cached_directory(const char *directory, time_t when);
 
 /********************************* dns.c ***************************/
 

+ 22 - 2
src/or/router.c

@@ -532,8 +532,10 @@ int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
     router->address,
     router->or_port,
     router->socks_port,
-    router->dir_port,
-    /* XXX008 only use dir_port here if authoritative server, else use opt line below */
+    /* Due to an 0.0.7 bug, we can't actually say that we have a dirport unles
+     * we're an authoritative directory.
+     */
+    router->is_trusted_dir ? router->dir_port : 0,
     router->platform,
     published,
     (int) router->bandwidthrate,
@@ -550,6 +552,24 @@ int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
   /* From now on, we use 'written' to remember the current length of 's'. */
   written = result;
 
+  if (router->dir_port && !router->is_trusted_dir) {
+    /* dircacheport wasn't recognized before 0.0.8pre.  (When 0.0.7 is gone,
+     * we can fold this back into dirport anyway.)
+    result = snprintf(s+written,maxlen-written, "opt dircacheport %d\n",
+                      router->dir_port);
+    if (result<0 || result+written > maxlen)
+      return -1;
+    written += result;
+  }
+
+  if (options.ContactInfo && strlen(options.ContactInfo)) {
+    result = snprintf(s+written,maxlen-written, "opt contact %s\n",
+                      options.ContactInfo);
+    if (result<0 || result+written > maxlen)
+      return -1;
+    written += result;
+  }
+
   /* Write the exit policy to the end of 's'. */
   for(tmpe=router->exit_policy; tmpe; tmpe=tmpe->next) {
     in.s_addr = htonl(tmpe->addr);

+ 1 - 0
src/or/routerlist.c

@@ -477,6 +477,7 @@ int router_load_routerlist_from_directory(const char *s,
     log_fn(LOG_WARN, "Error resolving routerlist");
     return -1;
   }
+  dirserv_set_cached_directory(s, routerlist->published_on);
   return 0;
 }
 

+ 49 - 12
src/or/routerparse.c

@@ -39,6 +39,8 @@ typedef enum {
   K_OPT,
   K_BANDWIDTH,
   K_PORTS,
+  K_DIRCACHEPORT,
+  K_CONTACT,
   _UNRECOGNIZED,
   _ERR,
   _EOF,
@@ -109,7 +111,8 @@ static struct {
   { "platform",            K_PLATFORM,        CONCAT_ARGS, NO_OBJ,  RTR_ONLY },
   { "published",           K_PUBLISHED,       CONCAT_ARGS, NO_OBJ,  ANY },
   { "opt",                 K_OPT,             CONCAT_ARGS, OBJ_OK,  ANY },
-
+  { "dircacheport",        K_DIRCACHEPORT,        ARGS,    NO_OBJ,  RTR_ONLY },
+  { "contact",             K_CONTACT,         CONCAT_ARGS, NO_OBJ,  ANY },
   { NULL, -1 }
 };
 
@@ -587,6 +590,17 @@ routerinfo_t *router_parse_entry_from_string(const char *s,
     ports_set = 1;
   }
 
+  tok = find_first_by_keyword(tokens, K_DIRCACHEPORT);
+  if (tok) {
+    if (router->dir_port)
+      log_fn(LOG_WARN,"Redundant dircacheport line");
+    if (tok->n_args != 1) {
+      log_fn(LOG_WARN,"Wrong # of arguments to \"dircacheport\"");
+      goto err;
+    }
+    router->dir_port = atoi(tok->args[0]);
+  }
+
   tok = find_first_by_keyword(tokens, K_BANDWIDTH);
   if (tok && bw_set) {
     log_fn(LOG_WARN,"Redundant bandwidth line");
@@ -898,7 +912,7 @@ token_free(directory_token_t *tok)
 static directory_token_t *
 get_next_token(const char **s, where_syntax where) {
   const char *next, *obstart;
-  int i, done, allocated;
+  int i, done, allocated, is_opt;
   directory_token_t *tok;
   arg_syntax a_syn;
   obj_syntax o_syn = NO_OBJ;
@@ -923,7 +937,17 @@ get_next_token(const char **s, where_syntax where) {
     tok->error = "Unexpected EOF"; return tok;
   }
   /* It's a keyword... but which one? */
-  for (i = 0 ; token_table[i].t ; ++i) {
+  is_opt = !strncmp("opt", *s, next-*s);
+  if (is_opt) {
+    *s = eat_whitespace(next);
+    next = NULL;
+    if (**s)
+      next = find_whitespace(*s);
+    if (!**s || !next) {
+      RET_ERR("opt without keyword");
+    }
+  }
+  for (i = 0; token_table[i].t ; ++i) {
     if (!strncmp(token_table[i].t, *s, next-*s)) {
       /* We've found the keyword. */
       tok->tp = token_table[i].v;
@@ -979,16 +1003,29 @@ get_next_token(const char **s, where_syntax where) {
     }
   }
   if (tok->tp == _ERR) {
-    tok->tp = _UNRECOGNIZED;
-    next = strchr(*s, '\n');
-    if (!next) {
-      RET_ERR("Unexpected EOF");
+    if (is_opt) {
+      tok->tp = K_OPT;
+      *s = eat_whitespace_no_nl(next);
+      next = strchr(*s,'\n');
+      if (!next)
+        RET_ERR("Unexpected EOF");
+      tok->args = tor_malloc(sizeof(char*));
+      tok->args[0] = tor_strndup(*s,next-*s);
+      tok->n_args = 1;
+      *s = eat_whitespace_no_nl(next+1);
+      a_syn = OBJ_OK;
+    } else {
+      tok->tp = _UNRECOGNIZED;
+      next = strchr(*s, '\n');
+      if (!next) {
+        RET_ERR("Unexpected EOF");
+      }
+      tok->args = tor_malloc(sizeof(char*));
+      tok->args[0] = tor_strndup(*s,next-*s);
+      tok->n_args = 1;
+      *s = next+1;
+      o_syn = OBJ_OK;
     }
-    tok->args = tor_malloc(sizeof(char*));
-    tok->args[0] = tor_strndup(*s,next-*s);
-    tok->n_args = 1;
-    *s = next+1;
-    o_syn = OBJ_OK;
   }
   *s = eat_whitespace(*s);
   if (strncmp(*s, "-----BEGIN ", 11)) {

+ 1 - 0
src/or/test.c

@@ -666,6 +666,7 @@ test_dir_format()
   r1.or_port = 9000;
   r1.socks_port = 9002;
   r1.dir_port = 9003;
+  r1.is_trusted_dir = 1;
   r1.onion_pkey = pk1;
   r1.identity_pkey = pk2;
   r1.bandwidthrate = 1000;