Browse Source

Write automatically-chosen control ports to a file.

Nick Mathewson 14 years ago
parent
commit
dad12188a6
8 changed files with 60 additions and 2 deletions
  1. 3 0
      changes/feature3076
  2. 5 0
      doc/tor.1.txt
  3. 1 0
      src/or/config.c
  4. 3 0
      src/or/connection.c
  5. 39 0
      src/or/control.c
  6. 2 0
      src/or/control.h
  7. 4 2
      src/or/main.c
  8. 3 0
      src/or/or.h

+ 3 - 0
changes/feature3076

@@ -6,3 +6,6 @@
       and ports that are bound for listeners for a given connection
       and ports that are bound for listeners for a given connection
       type.  This is useful for if the user has selected SocksPort
       type.  This is useful for if the user has selected SocksPort
       "auto", and you need to know which port got chosen.
       "auto", and you need to know which port got chosen.
+    - There is a ControlPortWriteToFile option that tells Tor to write
+      its actual control port or ports to a chosen file.
+

+ 5 - 0
doc/tor.1.txt

@@ -191,6 +191,11 @@ Other options can be specified either on the command-line (--option
     the default GID. [Making the file readable by other groups is not yet
     the default GID. [Making the file readable by other groups is not yet
     implemented; let us know if you need this for some reason.] (Default: 0).
     implemented; let us know if you need this for some reason.] (Default: 0).
 
 
+**ControlPortWriteToFile** __Path__::
+    If set, Tor writes the address and port of any control port it opens to
+    this address.  Usable by controllers to learn the actual control port
+    when ControlPort is set to "auto".
+
 **DataDirectory** __DIR__::
 **DataDirectory** __DIR__::
     Store working data in DIR (Default: @LOCALSTATEDIR@/lib/tor)
     Store working data in DIR (Default: @LOCALSTATEDIR@/lib/tor)
 
 

+ 1 - 0
src/or/config.c

@@ -206,6 +206,7 @@ static config_var_t _option_vars[] = {
   V(ContactInfo,                 STRING,   NULL),
   V(ContactInfo,                 STRING,   NULL),
   V(ControlListenAddress,        LINELIST, NULL),
   V(ControlListenAddress,        LINELIST, NULL),
   V(ControlPort,                 PORT,     "0"),
   V(ControlPort,                 PORT,     "0"),
+  V(ControlPortWriteToFile,      FILENAME, NULL),
   V(ControlSocket,               LINELIST, NULL),
   V(ControlSocket,               LINELIST, NULL),
   V(CookieAuthentication,        BOOL,     "0"),
   V(CookieAuthentication,        BOOL,     "0"),
   V(CookieAuthFileGroupReadable, BOOL,     "0"),
   V(CookieAuthFileGroupReadable, BOOL,     "0"),

+ 3 - 0
src/or/connection.c

@@ -998,6 +998,9 @@ connection_create_listener(const struct sockaddr *listensockaddr,
          "%s listening on port %u.",
          "%s listening on port %u.",
          conn_type_to_string(type), gotPort);
          conn_type_to_string(type), gotPort);
 
 
+  if (type == CONN_TYPE_CONTROL_LISTENER)
+    control_ports_write_to_file();
+
   conn->state = LISTENER_STATE_READY;
   conn->state = LISTENER_STATE_READY;
   if (start_reading) {
   if (start_reading) {
     connection_start_reading(conn);
     connection_start_reading(conn);

+ 39 - 0
src/or/control.c

@@ -508,6 +508,45 @@ connection_printf_to_buf(control_connection_t *conn, const char *format, ...)
   connection_write_to_buf(buf, len, TO_CONN(conn));
   connection_write_to_buf(buf, len, TO_CONN(conn));
 }
 }
 
 
+/** Write all of the open control ports to ControlPortWriteToFile */
+void
+control_ports_write_to_file(void)
+{
+  smartlist_t *lines;
+  char *joined = NULL;
+  or_options_t *options = get_options();
+
+  if (!options->ControlPortWriteToFile)
+    return;
+
+  lines = smartlist_create();
+
+  SMARTLIST_FOREACH_BEGIN(get_connection_array(), const connection_t *, conn) {
+    char *port_str = NULL;
+    if (conn->type != CONN_TYPE_CONTROL_LISTENER || conn->marked_for_close)
+      continue;
+#ifdef AF_UNIX
+    if (conn->socket_family == AF_UNIX) {
+      tor_asprintf(&port_str, "UNIX_PORT=%s\n", conn->address);
+      smartlist_add(lines, port_str);
+      continue;
+    }
+#endif
+    tor_asprintf(&port_str, "PORT=%s:%d\n", conn->address, conn->port);
+    smartlist_add(lines, port_str);
+  } SMARTLIST_FOREACH_END(conn);
+
+  joined = smartlist_join_strings(lines, "", 0, NULL);
+
+  if (write_str_to_file(options->ControlPortWriteToFile, joined, 0) < 0) {
+    log_warn(LD_CONTROL, "Writing %s failed: %s",
+             options->ControlPortWriteToFile, strerror(errno));
+  }
+  tor_free(joined);
+  SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
+  smartlist_free(lines);
+}
+
 /** Send a "DONE" message down the control connection <b>conn</b>. */
 /** Send a "DONE" message down the control connection <b>conn</b>. */
 static void
 static void
 send_control_done(control_connection_t *conn)
 send_control_done(control_connection_t *conn)

+ 2 - 0
src/or/control.h

@@ -15,6 +15,8 @@
 void control_update_global_event_mask(void);
 void control_update_global_event_mask(void);
 void control_adjust_event_log_severity(void);
 void control_adjust_event_log_severity(void);
 
 
+void control_ports_write_to_file(void);
+
 /** Log information about the connection <b>conn</b>, protecting it as with
 /** Log information about the connection <b>conn</b>, protecting it as with
  * CONN_LOG_PROTECT. Example:
  * CONN_LOG_PROTECT. Example:
  *
  *

+ 4 - 2
src/or/main.c

@@ -2046,12 +2046,14 @@ void
 tor_cleanup(void)
 tor_cleanup(void)
 {
 {
   or_options_t *options = get_options();
   or_options_t *options = get_options();
-  /* Remove our pid file. We don't care if there was an error when we
-   * unlink, nothing we could do about it anyways. */
   if (options->command == CMD_RUN_TOR) {
   if (options->command == CMD_RUN_TOR) {
     time_t now = time(NULL);
     time_t now = time(NULL);
+    /* Remove our pid file. We don't care if there was an error when we
+     * unlink, nothing we could do about it anyways. */
     if (options->PidFile)
     if (options->PidFile)
       unlink(options->PidFile);
       unlink(options->PidFile);
+    if (options->ControlPortWriteToFile)
+      unlink(options->ControlPortWriteToFile);
     if (accounting_is_enabled(options))
     if (accounting_is_enabled(options))
       accounting_record_bandwidth_usage(now, get_or_state());
       accounting_record_bandwidth_usage(now, get_or_state());
     or_state_mark_dirty(get_or_state(), 0); /* force an immediate save. */
     or_state_mark_dirty(get_or_state(), 0); /* force an immediate save. */

+ 3 - 0
src/or/or.h

@@ -2874,6 +2874,9 @@ typedef struct {
    * the defaults have changed. */
    * the defaults have changed. */
   int _UsingTestNetworkDefaults;
   int _UsingTestNetworkDefaults;
 
 
+  /** File where we should write the ControlPort. */
+  char *ControlPortWriteToFile;
+
 } or_options_t;
 } or_options_t;
 
 
 /** Persistent state for an onion router, as saved to disk. */
 /** Persistent state for an onion router, as saved to disk. */