Browse Source

Make an options_act() where we do all the things a new options set
needs.
Still needs more work.


svn:r2716

Roger Dingledine 20 years ago
parent
commit
90b47172bd
4 changed files with 106 additions and 104 deletions
  1. 85 12
      src/or/config.c
  2. 5 1
      src/or/control.c
  3. 14 90
      src/or/main.c
  4. 2 1
      src/or/or.h

+ 85 - 12
src/or/config.c

@@ -204,26 +204,95 @@ get_options(void) {
  */
 void
 set_options(or_options_t *new_val) {
-  struct config_line_t *cl;
-
   if (global_options)
     options_free(global_options);
   global_options = new_val;
+}
+
+/** Fetch the active option list, and take actions based on it. All
+ * of the things we do should survive being done repeatedly.
+ * Return 0 if all goes well, return -1 if it's time to die.
+ */
+int
+options_act(void) {
+  struct config_line_t *cl;
+  or_options_t *options = get_options();
 
   clear_trusted_dir_servers();
-  for (cl = new_val->DirServers; cl; cl = cl->next) {
+  for (cl = options->DirServers; cl; cl = cl->next) {
     if (parse_dir_server_line(cl->value, 0)<0) {
       log_fn(LOG_ERR,
              "Previously validated DirServer line could not be added!");
-      tor_assert(0);
+      return -1;
     }
   }
 
-  if (rend_config_services(new_val, 0)<0) {
+  if (rend_config_services(options, 0)<0) {
     log_fn(LOG_ERR,
            "Previously validated hidden services line could not be added!");
-    tor_assert(0);
+    return -1;
+  }
+
+  /* Setuid/setgid as appropriate */
+  if(options->User || options->Group) {
+    if(switch_id(options->User, options->Group) != 0) {
+      return -1;
+    }
   }
+
+/*XXX in options_validate, we should check if this is going to fail */
+  /* Ensure data directory is private; create if possible. */
+  if (get_data_directory() &&
+      check_private_dir(get_data_directory(), 1) != 0) {
+    log_fn(LOG_ERR, "Couldn't access/create private data directory %s",
+           get_data_directory());
+    return -1;
+  }
+
+  /* Bail out at this point if we're not going to be a server: we want
+   * to not fork, and to log stuff to stderr. */
+  if (options->command != CMD_RUN_TOR)
+    return 0;
+
+  if (set_max_file_descriptors(get_options()->MaxConn) < 0)
+    return -1;
+
+  /* Configure the log(s) */
+  if (config_init_logs(options)<0)
+    return -1;
+  /* Close the temporary log we used while starting up, if it isn't already
+   * gone. */
+  close_temp_logs();
+  add_callback_log(LOG_WARN, LOG_ERR, control_event_logmsg);
+
+  /* Start backgrounding the process, if requested. */
+  if (options->RunAsDaemon) {
+    start_daemon(get_data_directory());
+  }
+
+  /* Finish backgrounding the process */
+  if(options->RunAsDaemon) {
+    /* XXXX Can we delay this any more? */
+    finish_daemon();
+  }
+
+  /* Write our pid to the pid file. If we do not have write permissions we
+   * will log a warning */
+  if(options->PidFile)
+    write_pidfile(options->PidFile);
+
+  /* reload keys as needed for rendezvous services. */
+  if (rend_service_load_keys()<0) {
+    log_fn(LOG_ERR,"Error reloading rendezvous service keys");
+    return -1;
+  }
+
+  if(retry_all_listeners(1) < 0) {
+    log_fn(LOG_ERR,"Failed to bind one of the listener ports.");
+    return -1;
+  }
+
+  return 0;
 }
 
 /*
@@ -612,7 +681,6 @@ config_trial_assign(or_options_t **options, struct config_line_t *list, int rese
     return -3;
   }
 
-  set_options(trial_options);
   return 0;
 }
 
@@ -1219,9 +1287,10 @@ static int check_nickname_list(const char *lst, const char *name)
 
 /** Read a configuration file into <b>options</b>, finding the configuration
  * file location based on the command line.  After loading the options,
- * validate them for consistency. Return 0 if success, <0 if failure. */
+ * validate them for consistency, then take actions based on them.
+ * Return 0 if success, -1 if failure. */
 int
-getconfig(int argc, char **argv)
+init_from_config(int argc, char **argv)
 {
   or_options_t *oldoptions, *newoptions;
   struct config_line_t *cl;
@@ -1318,21 +1387,25 @@ getconfig(int argc, char **argv)
       goto err;
   }
 
-/* go through command-line variables too */
+  /* Go through command-line variables too */
   cl = config_get_commandlines(argc,argv);
   retval = config_assign(newoptions,cl,0);
   config_free_lines(cl);
   if (retval < 0)
     goto err;
 
-/* Validate newoptions */
+  /* Validate newoptions */
   if (options_validate(newoptions) < 0)
     goto err;
 
   if (options_transition_allowed(oldoptions, newoptions) < 0)
     goto err;
 
-  set_options(newoptions);
+  set_options(newoptions); /* frees and replaces old options */
+  if (options_act() < 0) { /* acting on them failed. die. */
+    log_fn(LOG_ERR,"Acting on config options left us in a broken state. Dying.");
+    exit(1);
+  }
   return 0;
  err:
   options_free(newoptions);

+ 5 - 1
src/or/control.c

@@ -222,8 +222,12 @@ handle_control_setconf(connection_t *conn, uint16_t len, char *body)
     return 0;
   }
 
-  set_options(options); /* put the new one into place */
   config_free_lines(lines);
+  set_options(options); /* put the new one into place */
+  if (options_act() < 0) { /* acting on them failed. die. */
+    log_fn(LOG_ERR,"Acting on config options left us in a broken state. Dying.");
+    exit(1);
+  }
   send_control_done(conn);
   return 0;
 }

+ 14 - 90
src/or/main.c

@@ -14,7 +14,6 @@
 /********* PROTOTYPES **********/
 
 static void dumpstats(int severity); /* log stats */
-static int init_from_config(int argc, char **argv);
 
 /********* START VARIABLES **********/
 
@@ -689,72 +688,6 @@ static int prepare_for_poll(void) {
   return (1000 - (now.tv_usec / 1000)); /* how many milliseconds til the next second? */
 }
 
-/** Configure the Tor process from the command line arguments and from the
- * configuration file.
- */
-static int init_from_config(int argc, char **argv) {
-  or_options_t *options;
-
-  /* read the configuration file. init and assign options. */
-  if(getconfig(argc,argv) < 0) {
-    log_fn(LOG_ERR,"Reading config failed--see warnings above. For usage, try -h.");
-    return -1;
-  }
-
-  options = get_options();
-
-  /* Setuid/setgid as appropriate */
-  if(options->User || options->Group) {
-    if(switch_id(options->User, options->Group) != 0) {
-      return -1;
-    }
-  }
-
-  /* Ensure data directory is private; create if possible. */
-  if (get_data_directory() &&
-      check_private_dir(get_data_directory(), 1) != 0) {
-    log_fn(LOG_ERR, "Couldn't access/create private data directory %s",
-           get_data_directory());
-    return -1;
-  }
-
-  /* Bail out at this point if we're not going to be a server: we want
-   * to not fork, and to log stuff to stderr. */
-  if (options->command != CMD_RUN_TOR)
-    return 0;
-
-  /* Configure the log(s) */
-  if (config_init_logs(options)<0)
-    return -1;
-  /* Close the temporary log we used while starting up, if it isn't already
-   * gone. */
-  close_temp_logs();
-  add_callback_log(LOG_WARN, LOG_ERR, control_event_logmsg);
-
-  /* Start backgrounding the process, if requested. */
-  if (options->RunAsDaemon) {
-    start_daemon(get_data_directory());
-  }
-
-  /* Set up our buckets */
-  connection_bucket_init();
-  stats_prev_global_read_bucket = global_read_bucket;
-  stats_prev_global_write_bucket = global_write_bucket;
-
-  /* Finish backgrounding the process */
-  if(options->RunAsDaemon) {
-    /* XXXX Can we delay this any more? */
-    finish_daemon();
-  }
-
-  /* Write our pid to the pid file. If we do not have write permissions we
-   * will log a warning */
-  if(options->PidFile)
-    write_pidfile(options->PidFile);
-
-  return 0;
-}
-
 /** Called when we get a SIGHUP: reload configuration files and keys,
  * retry all connections, re-upload all descriptors, and so on. */
 static int do_hup(void) {
@@ -766,17 +699,11 @@ static int do_hup(void) {
   /* first, reload config variables, in case they've changed */
   /* no need to provide argc/v, they've been cached inside init_from_config */
   if (init_from_config(0, NULL) < 0) {
+    log_fn(LOG_ERR,"Reading config failed--see warnings above. For usage, try -h.");
     return -1;
   }
-  /* reload keys as needed for rendezvous services. */
-  if (rend_service_load_keys()<0) {
-    log_fn(LOG_ERR,"Error reloading rendezvous service keys");
-    return -1;
-  }
-  if(retry_all_listeners(1) < 0) {
-    log_fn(LOG_ERR,"Failed to bind one of the listener ports.");
-    return -1;
-  }
+/*XXX this should move to options_act, but only once it's been
+ * removed from init_keys() */
   if(authdir_mode(get_options())) {
     /* reload the approved-routers file */
     tor_snprintf(keydir,sizeof(keydir),"%s/approved-routers", get_data_directory());
@@ -816,11 +743,17 @@ static int do_main_loop(void) {
 
   /* load the private keys, if we're supposed to have them, and set up the
    * TLS context. */
-  if (init_keys() < 0 || rend_service_load_keys() < 0) {
+  if (init_keys() < 0) {
     log_fn(LOG_ERR,"Error initializing keys; exiting");
     return -1;
   }
 
+  /* Set up our buckets */
+  connection_bucket_init();
+  stats_prev_global_read_bucket = global_read_bucket;
+  stats_prev_global_write_bucket = global_write_bucket;
+
+/*XXX move to options_act? */
   /* Set up accounting */
   if (get_options()->AccountingMaxKB)
     configure_accounting(time(NULL));
@@ -840,12 +773,6 @@ static int do_main_loop(void) {
     cpu_init();
   }
 
-  /* start up the necessary listeners based on which ports are non-zero. */
-  if(retry_all_listeners(1) < 0) {
-    log_fn(LOG_ERR,"Failed to bind one of the listener ports.");
-    return -1;
-  }
-
   for(;;) {
 #ifdef MS_WINDOWS_SERVICE /* Do service stuff only on windows. */
     if (service_status.dwCurrentState != SERVICE_RUNNING) {
@@ -1079,8 +1006,10 @@ static int tor_init(int argc, char *argv[]) {
   }
   atexit(exit_function);
 
-  if (init_from_config(argc,argv) < 0)
+  if (init_from_config(argc,argv) < 0) {
+    log_fn(LOG_ERR,"Reading config failed--see warnings above. For usage, try -h.");
     return -1;
+  }
 
 #ifndef MS_WINDOWS
   if(geteuid()==0)
@@ -1090,15 +1019,10 @@ static int tor_init(int argc, char *argv[]) {
   if(server_mode(get_options())) { /* only spawn dns handlers if we're a router */
     dns_init(); /* initialize the dns resolve tree, and spawn workers */
   }
-  if(proxy_mode(get_options())) {
-    client_dns_init(); /* init the client dns cache */
-  }
+  client_dns_init(); /* Init the client dns cache. Do it always, since it's cheap. */
 
   handle_signals(1);
 
-  if (set_max_file_descriptors(get_options()->MaxConn) < 0)
-    return -1;
-
   crypto_global_init();
   crypto_seed_rng();
   return 0;

+ 2 - 1
src/or/or.h

@@ -1093,13 +1093,14 @@ struct config_line_t {
 
 or_options_t *get_options(void);
 void set_options(or_options_t *new_val);
+int options_act(void);
 
 int config_get_lines(char *string, struct config_line_t **result);
 void config_free_lines(struct config_line_t *front);
 int config_trial_assign(or_options_t **options, struct config_line_t *list, int reset);
 int resolve_my_address(const char *address, uint32_t *addr);
 void options_init(or_options_t *options);
-int getconfig(int argc, char **argv);
+int init_from_config(int argc, char **argv);
 int config_init_logs(or_options_t *options);
 void config_parse_exit_policy(struct config_line_t *cfg,
                               struct exit_policy_t **dest);