Back to index

tor  0.2.3.18-rc
Defines | Functions
control.h File Reference

Header file for control.c. More...

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define LOG_FN_CONN(conn, args)   CONN_LOG_PROTECT(conn, log_fn args)
 Log information about the connection conn, protecting it as with CONN_LOG_PROTECT.
#define EVENT_AUTHDIR_NEWDESCS   0x000D
#define EVENT_NS   0x000F

Functions

void control_update_global_event_mask (void)
 Set global_event_mask* to the bitwise OR of each live control connection's event_mask field.
void control_adjust_event_log_severity (void)
 Adjust the log severities that result in control_event_logmsg being called to match the severity of log messages that any controllers are interested in.
void control_ports_write_to_file (void)
 Write all of the open control ports to ControlPortWriteToFile.
int connection_control_finished_flushing (control_connection_t *conn)
 Called when conn has no more bytes left on its outbuf.
int connection_control_reached_eof (control_connection_t *conn)
 Called when conn has gotten its socket closed.
void connection_control_closed (control_connection_t *conn)
 Called when conn is being freed.
int connection_control_process_inbuf (control_connection_t *conn)
 Called when data has arrived on a v1 control connection: Try to fetch commands from conn->inbuf, and execute them.
int control_event_is_interesting (int event)
 Return true iff the event with code c is being sent to any current control connection.
int control_event_circuit_status (origin_circuit_t *circ, circuit_status_event_t e, int reason)
 Something major has happened to circuit circ: tell any interested control connections.
int control_event_circuit_purpose_changed (origin_circuit_t *circ, int old_purpose)
 circ has changed its purpose from old_purpose: tell any interested controllers.
int control_event_circuit_cannibalized (origin_circuit_t *circ, int old_purpose, const struct timeval *old_tv_created)
 circ has changed its purpose from old_purpose, and its created-time from old_tv_created: tell any interested controllers.
int control_event_stream_status (entry_connection_t *conn, stream_status_event_t e, int reason)
 Something has happened to the stream associated with AP connection conn: tell any interested control connections.
int control_event_or_conn_status (or_connection_t *conn, or_conn_status_event_t e, int reason)
 Called when the status of an OR connection conn changes: tell any interested control connections.
int control_event_bandwidth_used (uint32_t n_read, uint32_t n_written)
 A second or more has elapsed: tell any interested control connections how much bandwidth we used.
int control_event_stream_bandwidth (edge_connection_t *edge_conn)
 Print out STREAM_BW event for a single conn.
int control_event_stream_bandwidth_used (void)
 A second or more has elapsed: tell any interested control connections how much bandwidth streams have used.
void control_event_logmsg (int severity, uint32_t domain, const char *msg)
 We got a log message: tell any interested control connections.
int control_event_descriptors_changed (smartlist_t *routers)
 Called whenever we receive new router descriptors: tell any interested control connections.
int control_event_address_mapped (const char *from, const char *to, time_t expires, const char *error)
 Called when an address mapping on from from changes to to.
int control_event_or_authdir_new_descriptor (const char *action, const char *desc, size_t desclen, const char *msg)
 The authoritative dirserver has received a new descriptor that has passed basic syntax checks and is properly self-signed.
int control_event_my_descriptor_changed (void)
 Our own router descriptor has changed; tell any controllers that care.
int control_event_networkstatus_changed (smartlist_t *statuses)
 Called when the routerstatus_ts statuses have changed: sends an NS event to any controller that cares.
int control_event_newconsensus (const networkstatus_t *consensus)
 Called when we get a new consensus networkstatus.
int control_event_networkstatus_changed_single (const routerstatus_t *rs)
 Called when a single local_routerstatus_t has changed: Sends an NS event to any controller that cares.
int control_event_general_status (int severity, const char *format,...) CHECK_PRINTF(2
int int control_event_client_status (int severity, const char *format,...) CHECK_PRINTF(2
int int int control_event_server_status (int severity, const char *format,...) CHECK_PRINTF(2
int int int int control_event_guard (const char *nickname, const char *digest, const char *status)
 Called when the status of an entry guard with the given nickname and identity digest has changed to status: tells any controllers that care.
int control_event_conf_changed (smartlist_t *elements)
 Called when a configuration option changes.
int control_event_buildtimeout_set (const circuit_build_times_t *cbt, buildtimeout_set_event_t type)
 Called when we compute a new circuitbuildtimeout.
int control_event_signal (uintptr_t signal)
 Called when a signal has been processed from signal_callback.
int init_cookie_authentication (int enabled)
 Choose a random authentication cookie and write it to disk.
smartlist_tdecode_hashed_passwords (config_line_t *passwords)
 Decode the hashed, base64'd passwords stored in passwords.
void disable_control_logging (void)
 Called when we are sending a log message to the controllers: suspend sending further log messages to the controllers until we're done.
void enable_control_logging (void)
 We're done sending a log message to the controllers: re-enable controller logging.
void monitor_owning_controller_process (const char *process_spec)
 Set process_spec as Tor's owning controller process.
void control_event_bootstrap (bootstrap_status_t status, int progress)
 Called when Tor has made progress at bootstrapping its directory information and initial circuits.
void control_event_bootstrap_problem (const char *warn, int reason)
 Called when Tor has failed to make bootstrapping progress in a way that indicates a problem.
void control_event_clients_seen (const char *controller_str)
 We just generated a new summary of which countries we've seen clients from recently.

Detailed Description

Header file for control.c.

Definition in file control.h.


Define Documentation

#define EVENT_AUTHDIR_NEWDESCS   0x000D

Definition at line 34 of file control.h.

#define EVENT_NS   0x000F

Definition at line 35 of file control.h.

#define LOG_FN_CONN (   conn,
  args 
)    CONN_LOG_PROTECT(conn, log_fn args)

Log information about the connection conn, protecting it as with CONN_LOG_PROTECT.

Example:

LOG_FN_CONN(conn, (LOG_DEBUG, "Socket %d wants to write", conn->s));

Definition at line 25 of file control.h.


Function Documentation

Called when conn is being freed.

Definition at line 3179 of file control.c.

{
  tor_assert(conn);

  conn->event_mask = 0;
  control_update_global_event_mask();

  if (conn->is_owning_control_connection) {
    lost_owning_controller("connection", "closed");
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Called when conn has no more bytes left on its outbuf.

Definition at line 3137 of file control.c.

{
  tor_assert(conn);
  return 0;
}

Here is the caller graph for this function:

Called when data has arrived on a v1 control connection: Try to fetch commands from conn->inbuf, and execute them.

Definition at line 3233 of file control.c.

{
  size_t data_len;
  uint32_t cmd_data_len;
  int cmd_len;
  char *args;

  tor_assert(conn);
  tor_assert(conn->_base.state == CONTROL_CONN_STATE_OPEN ||
             conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH);

  if (!conn->incoming_cmd) {
    conn->incoming_cmd = tor_malloc(1024);
    conn->incoming_cmd_len = 1024;
    conn->incoming_cmd_cur_len = 0;
  }

  if (conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH &&
      peek_connection_has_control0_command(TO_CONN(conn))) {
    /* Detect v0 commands and send a "no more v0" message. */
    size_t body_len;
    char buf[128];
    set_uint16(buf+2, htons(0x0000)); /* type == error */
    set_uint16(buf+4, htons(0x0001)); /* code == internal error */
    strlcpy(buf+6, "The v0 control protocol is not supported by Tor 0.1.2.17 "
            "and later; upgrade your controller.",
            sizeof(buf)-6);
    body_len = 2+strlen(buf+6)+2; /* code, msg, nul. */
    set_uint16(buf+0, htons(body_len));
    connection_write_to_buf(buf, 4+body_len, TO_CONN(conn));

    connection_mark_and_flush(TO_CONN(conn));
    return 0;
  }

 again:
  while (1) {
    size_t last_idx;
    int r;
    /* First, fetch a line. */
    do {
      data_len = conn->incoming_cmd_len - conn->incoming_cmd_cur_len;
      r = connection_fetch_from_buf_line(TO_CONN(conn),
                              conn->incoming_cmd+conn->incoming_cmd_cur_len,
                              &data_len);
      if (r == 0)
        /* Line not all here yet. Wait. */
        return 0;
      else if (r == -1) {
        if (data_len + conn->incoming_cmd_cur_len > MAX_COMMAND_LINE_LENGTH) {
          connection_write_str_to_buf("500 Line too long.\r\n", conn);
          connection_stop_reading(TO_CONN(conn));
          connection_mark_and_flush(TO_CONN(conn));
        }
        while (conn->incoming_cmd_len < data_len+conn->incoming_cmd_cur_len)
          conn->incoming_cmd_len *= 2;
        conn->incoming_cmd = tor_realloc(conn->incoming_cmd,
                                         conn->incoming_cmd_len);
      }
    } while (r != 1);

    tor_assert(data_len);

    last_idx = conn->incoming_cmd_cur_len;
    conn->incoming_cmd_cur_len += (int)data_len;

    /* We have appended a line to incoming_cmd.  Is the command done? */
    if (last_idx == 0 && *conn->incoming_cmd != '+')
      /* One line command, didn't start with '+'. */
      break;
    /* XXXX this code duplication is kind of dumb. */
    if (last_idx+3 == conn->incoming_cmd_cur_len &&
        tor_memeq(conn->incoming_cmd + last_idx, ".\r\n", 3)) {
      /* Just appended ".\r\n"; we're done. Remove it. */
      conn->incoming_cmd[last_idx] = '\0';
      conn->incoming_cmd_cur_len -= 3;
      break;
    } else if (last_idx+2 == conn->incoming_cmd_cur_len &&
               tor_memeq(conn->incoming_cmd + last_idx, ".\n", 2)) {
      /* Just appended ".\n"; we're done. Remove it. */
      conn->incoming_cmd[last_idx] = '\0';
      conn->incoming_cmd_cur_len -= 2;
      break;
    }
    /* Otherwise, read another line. */
  }
  data_len = conn->incoming_cmd_cur_len;
  /* Okay, we now have a command sitting on conn->incoming_cmd. See if we
   * recognize it.
   */
  cmd_len = 0;
  while ((size_t)cmd_len < data_len
         && !TOR_ISSPACE(conn->incoming_cmd[cmd_len]))
    ++cmd_len;

  conn->incoming_cmd[cmd_len]='\0';
  args = conn->incoming_cmd+cmd_len+1;
  tor_assert(data_len>(size_t)cmd_len);
  data_len -= (cmd_len+1); /* skip the command and NUL we added after it */
  while (TOR_ISSPACE(*args)) {
    ++args;
    --data_len;
  }

  /* If the connection is already closing, ignore further commands */
  if (TO_CONN(conn)->marked_for_close) {
    return 0;
  }

  /* Otherwise, Quit is always valid. */
  if (!strcasecmp(conn->incoming_cmd, "QUIT")) {
    connection_write_str_to_buf("250 closing connection\r\n", conn);
    connection_mark_and_flush(TO_CONN(conn));
    return 0;
  }

  if (conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH &&
      !is_valid_initial_command(conn, conn->incoming_cmd)) {
    connection_write_str_to_buf("514 Authentication required.\r\n", conn);
    connection_mark_for_close(TO_CONN(conn));
    return 0;
  }

  if (data_len >= UINT32_MAX) {
    connection_write_str_to_buf("500 A 4GB command? Nice try.\r\n", conn);
    connection_mark_for_close(TO_CONN(conn));
    return 0;
  }

  /* XXXX Why is this not implemented as a table like the GETINFO
   * items are?  Even handling the plus signs at the beginnings of
   * commands wouldn't be very hard with proper macros. */
  cmd_data_len = (uint32_t)data_len;
  if (!strcasecmp(conn->incoming_cmd, "SETCONF")) {
    if (handle_control_setconf(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "RESETCONF")) {
    if (handle_control_resetconf(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "GETCONF")) {
    if (handle_control_getconf(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "+LOADCONF")) {
    if (handle_control_loadconf(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "SETEVENTS")) {
    if (handle_control_setevents(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "AUTHENTICATE")) {
    if (handle_control_authenticate(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "SAVECONF")) {
    if (handle_control_saveconf(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "SIGNAL")) {
    if (handle_control_signal(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "TAKEOWNERSHIP")) {
    if (handle_control_takeownership(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "MAPADDRESS")) {
    if (handle_control_mapaddress(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "GETINFO")) {
    if (handle_control_getinfo(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "EXTENDCIRCUIT")) {
    if (handle_control_extendcircuit(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "SETCIRCUITPURPOSE")) {
    if (handle_control_setcircuitpurpose(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "SETROUTERPURPOSE")) {
    connection_write_str_to_buf("511 SETROUTERPURPOSE is obsolete.\r\n", conn);
  } else if (!strcasecmp(conn->incoming_cmd, "ATTACHSTREAM")) {
    if (handle_control_attachstream(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "+POSTDESCRIPTOR")) {
    if (handle_control_postdescriptor(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "REDIRECTSTREAM")) {
    if (handle_control_redirectstream(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "CLOSESTREAM")) {
    if (handle_control_closestream(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "CLOSECIRCUIT")) {
    if (handle_control_closecircuit(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "USEFEATURE")) {
    if (handle_control_usefeature(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "RESOLVE")) {
    if (handle_control_resolve(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "PROTOCOLINFO")) {
    if (handle_control_protocolinfo(conn, cmd_data_len, args))
      return -1;
  } else if (!strcasecmp(conn->incoming_cmd, "AUTHCHALLENGE")) {
    if (handle_control_authchallenge(conn, cmd_data_len, args))
      return -1;
  } else {
    connection_printf_to_buf(conn, "510 Unrecognized command \"%s\"\r\n",
                             conn->incoming_cmd);
  }

  conn->incoming_cmd_cur_len = 0;
  goto again;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Called when conn has gotten its socket closed.

Definition at line 3145 of file control.c.

{
  tor_assert(conn);

  log_info(LD_CONTROL,"Control connection reached EOF. Closing.");
  connection_mark_for_close(TO_CONN(conn));
  return 0;
}

Here is the caller graph for this function:

Adjust the log severities that result in control_event_logmsg being called to match the severity of log messages that any controllers are interested in.

Definition at line 272 of file control.c.

{
  int i;
  int min_log_event=EVENT_ERR_MSG, max_log_event=EVENT_DEBUG_MSG;

  for (i = EVENT_DEBUG_MSG; i <= EVENT_ERR_MSG; ++i) {
    if (EVENT_IS_INTERESTING(i)) {
      min_log_event = i;
      break;
    }
  }
  for (i = EVENT_ERR_MSG; i >= EVENT_DEBUG_MSG; --i) {
    if (EVENT_IS_INTERESTING(i)) {
      max_log_event = i;
      break;
    }
  }
  if (EVENT_IS_INTERESTING(EVENT_STATUS_GENERAL)) {
    if (min_log_event > EVENT_NOTICE_MSG)
      min_log_event = EVENT_NOTICE_MSG;
    if (max_log_event < EVENT_ERR_MSG)
      max_log_event = EVENT_ERR_MSG;
  }
  if (min_log_event <= max_log_event)
    change_callback_log_severity(event_to_log_severity(min_log_event),
                                 event_to_log_severity(max_log_event),
                                 control_event_logmsg);
  else
    change_callback_log_severity(LOG_ERR, LOG_ERR,
                                 control_event_logmsg);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int control_event_address_mapped ( const char *  from,
const char *  to,
time_t  expires,
const char *  error 
)

Called when an address mapping on from from changes to to.

expires values less than 3 are special; see connection_edge.c. If error is non-NULL, it is an error code describing the failure mode of the mapping.

Definition at line 3975 of file control.c.

{
  if (!EVENT_IS_INTERESTING(EVENT_ADDRMAP))
    return 0;

  if (expires < 3 || expires == TIME_MAX)
    send_control_event(EVENT_ADDRMAP, ALL_FORMATS,
                                "650 ADDRMAP %s %s NEVER %s\r\n", from, to,
                                error?error:"");
  else {
    char buf[ISO_TIME_LEN+1];
    char buf2[ISO_TIME_LEN+1];
    format_local_iso_time(buf,expires);
    format_iso_time(buf2,expires);
    send_control_event(EVENT_ADDRMAP, ALL_FORMATS,
                                "650 ADDRMAP %s %s \"%s\""
                                " %s%sEXPIRES=\"%s\"\r\n",
                                from, to, buf,
                                error?error:"", error?" ":"",
                                buf2);
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int control_event_bandwidth_used ( uint32_t  n_read,
uint32_t  n_written 
)

A second or more has elapsed: tell any interested control connections how much bandwidth we used.

Definition at line 3859 of file control.c.

{
  if (EVENT_IS_INTERESTING(EVENT_BANDWIDTH_USED)) {
    send_control_event(EVENT_BANDWIDTH_USED, ALL_FORMATS,
                       "650 BW %lu %lu\r\n",
                       (unsigned long)n_read,
                       (unsigned long)n_written);
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void control_event_bootstrap ( bootstrap_status_t  status,
int  progress 
)

Called when Tor has made progress at bootstrapping its directory information and initial circuits.

status is the new status, that is, what task we will be doing next. progress is zero if we just started this task, else it represents progress on the task.

Definition at line 4592 of file control.c.

{
  const char *tag, *summary;
  char buf[BOOTSTRAP_MSG_LEN];

  if (bootstrap_percent == BOOTSTRAP_STATUS_DONE)
    return; /* already bootstrapped; nothing to be done here. */

  /* special case for handshaking status, since our TLS handshaking code
   * can't distinguish what the connection is going to be for. */
  if (status == BOOTSTRAP_STATUS_HANDSHAKE) {
    if (bootstrap_percent < BOOTSTRAP_STATUS_CONN_OR) {
      status =  BOOTSTRAP_STATUS_HANDSHAKE_DIR;
    } else {
      status = BOOTSTRAP_STATUS_HANDSHAKE_OR;
    }
  }

  if (status > bootstrap_percent ||
      (progress && progress > bootstrap_percent)) {
    bootstrap_status_to_string(status, &tag, &summary);
    log(status ? LOG_NOTICE : LOG_INFO, LD_CONTROL,
        "Bootstrapped %d%%: %s.", progress ? progress : status, summary);
    tor_snprintf(buf, sizeof(buf),
        "BOOTSTRAP PROGRESS=%d TAG=%s SUMMARY=\"%s\"",
        progress ? progress : status, tag, summary);
    tor_snprintf(last_sent_bootstrap_message,
                 sizeof(last_sent_bootstrap_message),
                 "NOTICE %s", buf);
    control_event_client_status(LOG_NOTICE, "%s", buf);
    if (status > bootstrap_percent) {
      bootstrap_percent = status; /* new milestone reached */
    }
    if (progress > bootstrap_percent) {
      /* incremental progress within a milestone */
      bootstrap_percent = progress;
      bootstrap_problems = 0; /* Progress! Reset our problem counter. */
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void control_event_bootstrap_problem ( const char *  warn,
int  reason 
)

Called when Tor has failed to make bootstrapping progress in a way that indicates a problem.

warn gives a hint as to why, and reason provides an "or_conn_end_reason" tag.

Definition at line 4638 of file control.c.

{
  int status = bootstrap_percent;
  const char *tag, *summary;
  char buf[BOOTSTRAP_MSG_LEN];
  const char *recommendation = "ignore";
  int severity;

  /* bootstrap_percent must not be in "undefined" state here. */
  tor_assert(status >= 0);

  if (bootstrap_percent == 100)
    return; /* already bootstrapped; nothing to be done here. */

  bootstrap_problems++;

  if (bootstrap_problems >= BOOTSTRAP_PROBLEM_THRESHOLD)
    recommendation = "warn";

  if (reason == END_OR_CONN_REASON_NO_ROUTE)
    recommendation = "warn";

  if (get_options()->UseBridges &&
      !any_bridge_descriptors_known() &&
      !any_pending_bridge_descriptor_fetches())
    recommendation = "warn";

  while (status>=0 && bootstrap_status_to_string(status, &tag, &summary) < 0)
    status--; /* find a recognized status string based on current progress */
  status = bootstrap_percent; /* set status back to the actual number */

  severity = !strcmp(recommendation, "warn") ? LOG_WARN : LOG_INFO;

  log_fn(severity,
         LD_CONTROL, "Problem bootstrapping. Stuck at %d%%: %s. (%s; %s; "
         "count %d; recommendation %s)",
         status, summary, warn,
         orconn_end_reason_to_control_string(reason),
         bootstrap_problems, recommendation);

  connection_or_report_broken_states(severity, LD_HANDSHAKE);

  tor_snprintf(buf, sizeof(buf),
      "BOOTSTRAP PROGRESS=%d TAG=%s SUMMARY=\"%s\" WARNING=\"%s\" REASON=%s "
      "COUNT=%d RECOMMENDATION=%s",
      bootstrap_percent, tag, summary, warn,
      orconn_end_reason_to_control_string(reason), bootstrap_problems,
      recommendation);
  tor_snprintf(last_sent_bootstrap_message,
               sizeof(last_sent_bootstrap_message),
               "WARN %s", buf);
  control_event_client_status(LOG_WARN, "%s", buf);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Called when we compute a new circuitbuildtimeout.

Definition at line 4101 of file control.c.

{
  const char *type_string = NULL;
  double qnt;

  if (!control_event_is_interesting(EVENT_BUILDTIMEOUT_SET))
    return 0;

  qnt = circuit_build_times_quantile_cutoff();

  switch (type) {
    case BUILDTIMEOUT_SET_EVENT_COMPUTED:
      type_string = "COMPUTED";
      break;
    case BUILDTIMEOUT_SET_EVENT_RESET:
      type_string = "RESET";
      qnt = 1.0;
      break;
    case BUILDTIMEOUT_SET_EVENT_SUSPENDED:
      type_string = "SUSPENDED";
      qnt = 1.0;
      break;
    case BUILDTIMEOUT_SET_EVENT_DISCARD:
      type_string = "DISCARD";
      qnt = 1.0;
      break;
    case BUILDTIMEOUT_SET_EVENT_RESUME:
      type_string = "RESUME";
      break;
    default:
      type_string = "UNKNOWN";
      break;
  }

  send_control_event(EVENT_BUILDTIMEOUT_SET, ALL_FORMATS,
                     "650 BUILDTIMEOUT_SET %s TOTAL_TIMES=%lu "
                     "TIMEOUT_MS=%lu XM=%lu ALPHA=%f CUTOFF_QUANTILE=%f "
                     "TIMEOUT_RATE=%f CLOSE_MS=%lu CLOSE_RATE=%f\r\n",
                     type_string, (unsigned long)cbt->total_build_times,
                     (unsigned long)cbt->timeout_ms,
                     (unsigned long)cbt->Xm, cbt->alpha, qnt,
                     circuit_build_times_timeout_rate(cbt),
                     (unsigned long)cbt->close_ms,
                     circuit_build_times_close_rate(cbt));

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int control_event_circuit_cannibalized ( origin_circuit_t circ,
int  old_purpose,
const struct timeval old_tv_created 
)

circ has changed its purpose from old_purpose, and its created-time from old_tv_created: tell any interested controllers.

Definition at line 3589 of file control.c.

{
  return control_event_circuit_status_minor(circ,
                                            CIRC_MINOR_EVENT_CANNIBALIZED,
                                            old_purpose,
                                            old_tv_created);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int control_event_circuit_purpose_changed ( origin_circuit_t circ,
int  old_purpose 
)

circ has changed its purpose from old_purpose: tell any interested controllers.

Definition at line 3575 of file control.c.

Here is the call graph for this function:

Here is the caller graph for this function:

int control_event_circuit_status ( origin_circuit_t circ,
circuit_status_event_t  tp,
int  reason_code 
)

Something major has happened to circuit circ: tell any interested control connections.

Definition at line 3446 of file control.c.

{
  const char *status;
  char reasons[64] = "";
  if (!EVENT_IS_INTERESTING(EVENT_CIRCUIT_STATUS))
    return 0;
  tor_assert(circ);

  switch (tp)
    {
    case CIRC_EVENT_LAUNCHED: status = "LAUNCHED"; break;
    case CIRC_EVENT_BUILT: status = "BUILT"; break;
    case CIRC_EVENT_EXTENDED: status = "EXTENDED"; break;
    case CIRC_EVENT_FAILED: status = "FAILED"; break;
    case CIRC_EVENT_CLOSED: status = "CLOSED"; break;
    default:
      log_warn(LD_BUG, "Unrecognized status code %d", (int)tp);
      tor_fragile_assert();
      return 0;
    }

  if (tp == CIRC_EVENT_FAILED || tp == CIRC_EVENT_CLOSED) {
    const char *reason_str = circuit_end_reason_to_control_string(reason_code);
    char unk_reason_buf[16];
    if (!reason_str) {
      tor_snprintf(unk_reason_buf, 16, "UNKNOWN_%d", reason_code);
      reason_str = unk_reason_buf;
    }
    if (reason_code > 0 && reason_code & END_CIRC_REASON_FLAG_REMOTE) {
      tor_snprintf(reasons, sizeof(reasons),
                   " REASON=DESTROYED REMOTE_REASON=%s", reason_str);
    } else {
      tor_snprintf(reasons, sizeof(reasons),
                   " REASON=%s", reason_str);
    }
  }

  {
    char *circdesc = circuit_describe_status_for_controller(circ);
    const char *sp = strlen(circdesc) ? " " : "";
    send_control_event(EVENT_CIRCUIT_STATUS, ALL_FORMATS,
                                "650 CIRC %lu %s%s%s%s\r\n",
                                (unsigned long)circ->global_identifier,
                                status, sp,
                                circdesc,
                                reasons);
    tor_free(circdesc);
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int int control_event_client_status ( int  severity,
const char *  format,
  ... 
)
void control_event_clients_seen ( const char *  controller_str)

We just generated a new summary of which countries we've seen clients from recently.

Send a copy to the controller in case it wants to display it for the user.

Definition at line 4696 of file control.c.

{
  send_control_event(EVENT_CLIENTS_SEEN, 0,
    "650 CLIENTS_SEEN %s\r\n", controller_str);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Called when a configuration option changes.

This is generally triggered by SETCONF requests and RELOAD/SIGHUP signals. The elements is a smartlist_t containing (key, value, ...) pairs in sequence. value can be NULL.

Definition at line 4343 of file control.c.

{
  int i;
  char *result;
  smartlist_t *lines;
  if (!EVENT_IS_INTERESTING(EVENT_CONF_CHANGED) ||
      smartlist_len(elements) == 0) {
    return 0;
  }
  lines = smartlist_new();
  for (i = 0; i < smartlist_len(elements); i += 2) {
    char *k = smartlist_get(elements, i);
    char *v = smartlist_get(elements, i+1);
    if (v == NULL) {
      smartlist_add_asprintf(lines, "650-%s", k);
    } else {
      smartlist_add_asprintf(lines, "650-%s=%s", k, v);
    }
  }
  result = smartlist_join_strings(lines, "\r\n", 0, NULL);
  send_control_event(EVENT_CONF_CHANGED, 0,
    "650-CONF_CHANGED\r\n%s\r\n650 OK\r\n", result);
  tor_free(result);
  SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
  smartlist_free(lines);
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Called whenever we receive new router descriptors: tell any interested control connections.

routers is a list of routerinfo_t's.

Definition at line 3943 of file control.c.

{
  char *msg;

  if (!EVENT_IS_INTERESTING(EVENT_NEW_DESC))
    return 0;

  {
    smartlist_t *names = smartlist_new();
    char *ids;
    SMARTLIST_FOREACH(routers, routerinfo_t *, ri, {
        char *b = tor_malloc(MAX_VERBOSE_NICKNAME_LEN+1);
        router_get_verbose_nickname(b, ri);
        smartlist_add(names, b);
      });
    ids = smartlist_join_strings(names, " ", 0, NULL);
    tor_asprintf(&msg, "650 NEWDESC %s\r\n", ids);
    send_control_event_string(EVENT_NEW_DESC, ALL_FORMATS, msg);
    tor_free(ids);
    tor_free(msg);
    SMARTLIST_FOREACH(names, char *, cp, tor_free(cp));
    smartlist_free(names);
  }
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int control_event_general_status ( int  severity,
const char *  format,
  ... 
)
int int int int control_event_guard ( const char *  nickname,
const char *  digest,
const char *  status 
)

Called when the status of an entry guard with the given nickname and identity digest has changed to status: tells any controllers that care.

Definition at line 4316 of file control.c.

{
  char hbuf[HEX_DIGEST_LEN+1];
  base16_encode(hbuf, sizeof(hbuf), digest, DIGEST_LEN);
  if (!EVENT_IS_INTERESTING(EVENT_GUARD))
    return 0;

  {
    char buf[MAX_VERBOSE_NICKNAME_LEN+1];
    const node_t *node = node_get_by_id(digest);
    if (node) {
      node_get_verbose_nickname(node, buf);
    } else {
      tor_snprintf(buf, sizeof(buf), "$%s~%s", hbuf, nickname);
    }
    send_control_event(EVENT_GUARD, ALL_FORMATS,
                       "650 GUARD ENTRY %s %s\r\n", buf, status);
  }
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int control_event_is_interesting ( int  event)

Return true iff the event with code c is being sent to any current control connection.

This is useful if the amount of work needed to prepare to call the appropriate control_event_...() function is high.

Definition at line 309 of file control.c.

{
  return EVENT_IS_INTERESTING(event);
}

Here is the caller graph for this function:

void control_event_logmsg ( int  severity,
uint32_t  domain,
const char *  msg 
)

We got a log message: tell any interested control connections.

Definition at line 3891 of file control.c.

{
  int event;

  /* Don't even think of trying to add stuff to a buffer from a cpuworker
   * thread. */
  if (! in_main_thread())
    return;

  if (disable_log_messages)
    return;

  if (domain == LD_BUG && EVENT_IS_INTERESTING(EVENT_STATUS_GENERAL) &&
      severity <= LOG_NOTICE) {
    char *esc = esc_for_log(msg);
    ++disable_log_messages;
    control_event_general_status(severity, "BUG REASON=%s", esc);
    --disable_log_messages;
    tor_free(esc);
  }

  event = log_severity_to_event(severity);
  if (event >= 0 && EVENT_IS_INTERESTING(event)) {
    char *b = NULL;
    const char *s;
    if (strchr(msg, '\n')) {
      char *cp;
      b = tor_strdup(msg);
      for (cp = b; *cp; ++cp)
        if (*cp == '\r' || *cp == '\n')
          *cp = ' ';
    }
    switch (severity) {
      case LOG_DEBUG: s = "DEBUG"; break;
      case LOG_INFO: s = "INFO"; break;
      case LOG_NOTICE: s = "NOTICE"; break;
      case LOG_WARN: s = "WARN"; break;
      case LOG_ERR: s = "ERR"; break;
      default: s = "UnknownLogSeverity"; break;
    }
    ++disable_log_messages;
    send_control_event(event, ALL_FORMATS, "650 %s %s\r\n", s, b?b:msg);
    --disable_log_messages;
    tor_free(b);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Our own router descriptor has changed; tell any controllers that care.

Definition at line 4207 of file control.c.

{
  send_control_event(EVENT_DESCCHANGED, ALL_FORMATS, "650 DESCCHANGED\r\n");
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Called when the routerstatus_ts statuses have changed: sends an NS event to any controller that cares.

Definition at line 4083 of file control.c.

Here is the call graph for this function:

Here is the caller graph for this function:

Called when a single local_routerstatus_t has changed: Sends an NS event to any controller that cares.

Definition at line 4189 of file control.c.

{
  smartlist_t *statuses;
  int r;

  if (!EVENT_IS_INTERESTING(EVENT_NS))
    return 0;

  statuses = smartlist_new();
  smartlist_add(statuses, (void*)rs);
  r = control_event_networkstatus_changed(statuses);
  smartlist_free(statuses);
  return r;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int control_event_newconsensus ( const networkstatus_t consensus)

Called when we get a new consensus networkstatus.

Sends a NEWCONSENSUS event consisting of an NS-style line for each relay in the consensus.

Definition at line 4091 of file control.c.

Here is the call graph for this function:

Here is the caller graph for this function:

int control_event_or_authdir_new_descriptor ( const char *  action,
const char *  desc,
size_t  desclen,
const char *  msg 
)

The authoritative dirserver has received a new descriptor that has passed basic syntax checks and is properly self-signed.

Notify any interested party of the new descriptor and what has been done with it, and also optionally give an explanation/reason.

Definition at line 4007 of file control.c.

{
  char firstline[1024];
  char *buf;
  size_t totallen;
  char *esc = NULL;
  size_t esclen;

  if (!EVENT_IS_INTERESTING(EVENT_AUTHDIR_NEWDESCS))
    return 0;

  tor_snprintf(firstline, sizeof(firstline),
               "650+AUTHDIR_NEWDESC=\r\n%s\r\n%s\r\n",
               action,
               msg ? msg : "");

  /* Escape the server descriptor properly */
  esclen = write_escaped_data(desc, desclen, &esc);

  totallen = strlen(firstline) + esclen + 1;
  buf = tor_malloc(totallen);
  strlcpy(buf, firstline, totallen);
  strlcpy(buf+strlen(firstline), esc, totallen);
  send_control_event_string(EVENT_AUTHDIR_NEWDESCS, ALL_FORMATS,
                            buf);
  send_control_event_string(EVENT_AUTHDIR_NEWDESCS, ALL_FORMATS,
                            "650 OK\r\n");
  tor_free(esc);
  tor_free(buf);

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Called when the status of an OR connection conn changes: tell any interested control connections.

tp is the new status for the connection. If conn has just closed or failed, then reason may be the reason why.

Definition at line 3763 of file control.c.

{
  int ncircs = 0;
  const char *status;
  char name[128];
  char ncircs_buf[32] = {0}; /* > 8 + log10(2^32)=10 + 2 */

  if (!EVENT_IS_INTERESTING(EVENT_OR_CONN_STATUS))
    return 0;

  switch (tp)
    {
    case OR_CONN_EVENT_LAUNCHED: status = "LAUNCHED"; break;
    case OR_CONN_EVENT_CONNECTED: status = "CONNECTED"; break;
    case OR_CONN_EVENT_FAILED: status = "FAILED"; break;
    case OR_CONN_EVENT_CLOSED: status = "CLOSED"; break;
    case OR_CONN_EVENT_NEW: status = "NEW"; break;
    default:
      log_warn(LD_BUG, "Unrecognized status code %d", (int)tp);
      return 0;
    }
  ncircs = circuit_count_pending_on_or_conn(conn);
  ncircs += conn->n_circuits;
  if (ncircs && (tp == OR_CONN_EVENT_FAILED || tp == OR_CONN_EVENT_CLOSED)) {
    tor_snprintf(ncircs_buf, sizeof(ncircs_buf), "%sNCIRCS=%d",
                 reason ? " " : "", ncircs);
  }

  orconn_target_get_name(name, sizeof(name), conn);
  send_control_event(EVENT_OR_CONN_STATUS, ALL_FORMATS,
                              "650 ORCONN %s %s %s%s%s\r\n",
                              name, status,
                              reason ? "REASON=" : "",
                              orconn_end_reason_to_control_string(reason),
                              ncircs_buf);

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int int int control_event_server_status ( int  severity,
const char *  format,
  ... 
)
int control_event_signal ( uintptr_t  signal)

Called when a signal has been processed from signal_callback.

Definition at line 4152 of file control.c.

{
  const char *signal_string = NULL;

  if (!control_event_is_interesting(EVENT_SIGNAL))
    return 0;

  switch (signal) {
    case SIGHUP:
      signal_string = "RELOAD";
      break;
    case SIGUSR1:
      signal_string = "DUMP";
      break;
    case SIGUSR2:
      signal_string = "DEBUG";
      break;
    case SIGNEWNYM:
      signal_string = "NEWNYM";
      break;
    case SIGCLEARDNSCACHE:
      signal_string = "CLEARDNSCACHE";
      break;
    default:
      log_warn(LD_BUG, "Unrecognized signal %lu in control_event_signal",
               (unsigned long)signal);
      return -1;
  }

  send_control_event(EVENT_SIGNAL, ALL_FORMATS, "650 SIGNAL %s\r\n",
                     signal_string);
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Print out STREAM_BW event for a single conn.

Definition at line 3807 of file control.c.

{
  if (EVENT_IS_INTERESTING(EVENT_STREAM_BANDWIDTH_USED)) {
    if (!edge_conn->n_read && !edge_conn->n_written)
      return 0;

    send_control_event(EVENT_STREAM_BANDWIDTH_USED, ALL_FORMATS,
                       "650 STREAM_BW "U64_FORMAT" %lu %lu\r\n",
                       U64_PRINTF_ARG(edge_conn->_base.global_identifier),
                       (unsigned long)edge_conn->n_read,
                       (unsigned long)edge_conn->n_written);

    edge_conn->n_written = edge_conn->n_read = 0;
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

A second or more has elapsed: tell any interested control connections how much bandwidth streams have used.

Definition at line 3828 of file control.c.

{
  if (EVENT_IS_INTERESTING(EVENT_STREAM_BANDWIDTH_USED)) {
    smartlist_t *conns = get_connection_array();
    edge_connection_t *edge_conn;

    SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn)
    {
        if (conn->type != CONN_TYPE_AP)
          continue;
        edge_conn = TO_EDGE_CONN(conn);
        if (!edge_conn->n_read && !edge_conn->n_written)
          continue;

        send_control_event(EVENT_STREAM_BANDWIDTH_USED, ALL_FORMATS,
                           "650 STREAM_BW "U64_FORMAT" %lu %lu\r\n",
                           U64_PRINTF_ARG(edge_conn->_base.global_identifier),
                           (unsigned long)edge_conn->n_read,
                           (unsigned long)edge_conn->n_written);

        edge_conn->n_written = edge_conn->n_read = 0;
    }
    SMARTLIST_FOREACH_END(conn);
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int control_event_stream_status ( entry_connection_t conn,
stream_status_event_t  tp,
int  reason_code 
)

Something has happened to the stream associated with AP connection conn: tell any interested control connections.

Definition at line 3625 of file control.c.

{
  char reason_buf[64];
  char addrport_buf[64];
  const char *status;
  circuit_t *circ;
  origin_circuit_t *origin_circ = NULL;
  char buf[256];
  const char *purpose = "";
  tor_assert(conn->socks_request);

  if (!EVENT_IS_INTERESTING(EVENT_STREAM_STATUS))
    return 0;

  if (tp == STREAM_EVENT_CLOSED &&
      (reason_code & END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED))
    return 0;

  write_stream_target_to_buf(conn, buf, sizeof(buf));

  reason_buf[0] = '\0';
  switch (tp)
    {
    case STREAM_EVENT_SENT_CONNECT: status = "SENTCONNECT"; break;
    case STREAM_EVENT_SENT_RESOLVE: status = "SENTRESOLVE"; break;
    case STREAM_EVENT_SUCCEEDED: status = "SUCCEEDED"; break;
    case STREAM_EVENT_FAILED: status = "FAILED"; break;
    case STREAM_EVENT_CLOSED: status = "CLOSED"; break;
    case STREAM_EVENT_NEW: status = "NEW"; break;
    case STREAM_EVENT_NEW_RESOLVE: status = "NEWRESOLVE"; break;
    case STREAM_EVENT_FAILED_RETRIABLE: status = "DETACHED"; break;
    case STREAM_EVENT_REMAP: status = "REMAP"; break;
    default:
      log_warn(LD_BUG, "Unrecognized status code %d", (int)tp);
      return 0;
    }
  if (reason_code && (tp == STREAM_EVENT_FAILED ||
                      tp == STREAM_EVENT_CLOSED ||
                      tp == STREAM_EVENT_FAILED_RETRIABLE)) {
    const char *reason_str = stream_end_reason_to_control_string(reason_code);
    char *r = NULL;
    if (!reason_str) {
      tor_asprintf(&r, " UNKNOWN_%d", reason_code);
      reason_str = r;
    }
    if (reason_code & END_STREAM_REASON_FLAG_REMOTE)
      tor_snprintf(reason_buf, sizeof(reason_buf),
                   " REASON=END REMOTE_REASON=%s", reason_str);
    else
      tor_snprintf(reason_buf, sizeof(reason_buf),
                   " REASON=%s", reason_str);
    tor_free(r);
  } else if (reason_code && tp == STREAM_EVENT_REMAP) {
    switch (reason_code) {
    case REMAP_STREAM_SOURCE_CACHE:
      strlcpy(reason_buf, " SOURCE=CACHE", sizeof(reason_buf));
      break;
    case REMAP_STREAM_SOURCE_EXIT:
      strlcpy(reason_buf, " SOURCE=EXIT", sizeof(reason_buf));
      break;
    default:
      tor_snprintf(reason_buf, sizeof(reason_buf), " REASON=UNKNOWN_%d",
                   reason_code);
      /* XXX do we want SOURCE=UNKNOWN_%d above instead? -RD */
      break;
    }
  }

  if (tp == STREAM_EVENT_NEW) {
    tor_snprintf(addrport_buf,sizeof(addrport_buf), " SOURCE_ADDR=%s:%d",
                 ENTRY_TO_CONN(conn)->address, ENTRY_TO_CONN(conn)->port);
  } else {
    addrport_buf[0] = '\0';
  }

  if (tp == STREAM_EVENT_NEW_RESOLVE) {
    purpose = " PURPOSE=DNS_REQUEST";
  } else if (tp == STREAM_EVENT_NEW) {
    if (ENTRY_TO_EDGE_CONN(conn)->is_dns_request ||
        (conn->socks_request &&
         SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)))
      purpose = " PURPOSE=DNS_REQUEST";
    else if (conn->use_begindir) {
      connection_t *linked = ENTRY_TO_CONN(conn)->linked_conn;
      int linked_dir_purpose = -1;
      if (linked && linked->type == CONN_TYPE_DIR)
        linked_dir_purpose = linked->purpose;
      if (DIR_PURPOSE_IS_UPLOAD(linked_dir_purpose))
        purpose = " PURPOSE=DIR_UPLOAD";
      else
        purpose = " PURPOSE=DIR_FETCH";
    } else
      purpose = " PURPOSE=USER";
  }

  circ = circuit_get_by_edge_conn(ENTRY_TO_EDGE_CONN(conn));
  if (circ && CIRCUIT_IS_ORIGIN(circ))
    origin_circ = TO_ORIGIN_CIRCUIT(circ);
  send_control_event(EVENT_STREAM_STATUS, ALL_FORMATS,
                        "650 STREAM "U64_FORMAT" %s %lu %s%s%s%s\r\n",
                     U64_PRINTF_ARG(ENTRY_TO_CONN(conn)->global_identifier),
                     status,
                        origin_circ?
                           (unsigned long)origin_circ->global_identifier : 0ul,
                        buf, reason_buf, addrport_buf, purpose);

  /* XXX need to specify its intended exit, etc? */

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void control_ports_write_to_file ( void  )

Write all of the open control ports to ControlPortWriteToFile.

Definition at line 530 of file control.c.

{
  smartlist_t *lines;
  char *joined = NULL;
  const or_options_t *options = get_options();

  if (!options->ControlPortWriteToFile)
    return;

  lines = smartlist_new();

  SMARTLIST_FOREACH_BEGIN(get_connection_array(), const connection_t *, conn) {
    if (conn->type != CONN_TYPE_CONTROL_LISTENER || conn->marked_for_close)
      continue;
#ifdef AF_UNIX
    if (conn->socket_family == AF_UNIX) {
      smartlist_add_asprintf(lines, "UNIX_PORT=%s\n", conn->address);
      continue;
    }
#endif
    smartlist_add_asprintf(lines, "PORT=%s:%d\n", conn->address, conn->port);
  } 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));
  }
#ifndef _WIN32
  if (options->ControlPortFileGroupReadable) {
    if (chmod(options->ControlPortWriteToFile, 0640)) {
      log_warn(LD_FS,"Unable to make %s group-readable.",
               options->ControlPortWriteToFile);
    }
  }
#endif
  tor_free(joined);
  SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
  smartlist_free(lines);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Set global_event_mask* to the bitwise OR of each live control connection's event_mask field.

Definition at line 232 of file control.c.

{
  smartlist_t *conns = get_connection_array();
  event_mask_t old_mask, new_mask;
  old_mask = global_event_mask;

  global_event_mask = 0;
  SMARTLIST_FOREACH(conns, connection_t *, _conn,
  {
    if (_conn->type == CONN_TYPE_CONTROL &&
        STATE_IS_OPEN(_conn->state)) {
      control_connection_t *conn = TO_CONTROL_CONN(_conn);
      global_event_mask |= conn->event_mask;
    }
  });

  new_mask = global_event_mask;

  /* Handle the aftermath.  Set up the log callback to tell us only what
   * we want to hear...*/
  control_adjust_event_log_severity();

  /* ...then, if we've started logging stream bw, clear the appropriate
   * fields. */
  if (! (old_mask & EVENT_STREAM_BANDWIDTH_USED) &&
      (new_mask & EVENT_STREAM_BANDWIDTH_USED)) {
    SMARTLIST_FOREACH(conns, connection_t *, conn,
    {
      if (conn->type == CONN_TYPE_AP) {
        edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
        edge_conn->n_written = edge_conn->n_read = 0;
      }
    });
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Decode the hashed, base64'd passwords stored in passwords.

Return a smartlist of acceptable passwords (unterminated strings of length S2K_SPECIFIER_LEN+DIGEST_LEN) on success, or NULL on failure.

Definition at line 1012 of file control.c.

{
  char decoded[64];
  config_line_t *cl;
  smartlist_t *sl = smartlist_new();

  tor_assert(passwords);

  for (cl = passwords; cl; cl = cl->next) {
    const char *hashed = cl->value;

    if (!strcmpstart(hashed, "16:")) {
      if (base16_decode(decoded, sizeof(decoded), hashed+3, strlen(hashed+3))<0
          || strlen(hashed+3) != (S2K_SPECIFIER_LEN+DIGEST_LEN)*2) {
        goto err;
      }
    } else {
        if (base64_decode(decoded, sizeof(decoded), hashed, strlen(hashed))
            != S2K_SPECIFIER_LEN+DIGEST_LEN) {
          goto err;
        }
    }
    smartlist_add(sl, tor_memdup(decoded, S2K_SPECIFIER_LEN+DIGEST_LEN));
  }

  return sl;

 err:
  SMARTLIST_FOREACH(sl, char*, cp, tor_free(cp));
  smartlist_free(sl);
  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void disable_control_logging ( void  )

Called when we are sending a log message to the controllers: suspend sending further log messages to the controllers until we're done.

Used by CONN_LOG_PROTECT.

Definition at line 3875 of file control.c.

Here is the caller graph for this function:

void enable_control_logging ( void  )

We're done sending a log message to the controllers: re-enable controller logging.

Used by CONN_LOG_PROTECT.

Definition at line 3883 of file control.c.

{
  if (--disable_log_messages < 0)
    tor_assert(0);
}

Here is the caller graph for this function:

int init_cookie_authentication ( int  enabled)

Choose a random authentication cookie and write it to disk.

Anybody who can read the cookie from disk will be considered authorized to use the control connection. Return -1 if we can't write the file, or 0 on success.

Definition at line 4389 of file control.c.

{
  char *fname;
  if (!enabled) {
    authentication_cookie_is_set = 0;
    return 0;
  }

  /* We don't want to generate a new cookie every time we call
   * options_act(). One should be enough. */
  if (authentication_cookie_is_set)
    return 0; /* all set */

  fname = get_cookie_file();
  crypto_rand(authentication_cookie, AUTHENTICATION_COOKIE_LEN);
  authentication_cookie_is_set = 1;
  if (write_bytes_to_file(fname, authentication_cookie,
                          AUTHENTICATION_COOKIE_LEN, 1)) {
    log_warn(LD_FS,"Error writing authentication cookie to %s.",
             escaped(fname));
    tor_free(fname);
    return -1;
  }
#ifndef _WIN32
  if (get_options()->CookieAuthFileGroupReadable) {
    if (chmod(fname, 0640)) {
      log_warn(LD_FS,"Unable to make %s group-readable.", escaped(fname));
    }
  }
#endif

  tor_free(fname);
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void monitor_owning_controller_process ( const char *  process_spec)

Set process_spec as Tor's owning controller process.

Exit on failure.

Definition at line 4445 of file control.c.

{
  const char *msg;

  tor_assert((owning_controller_process_spec == NULL) ==
             (owning_controller_process_monitor == NULL));

  if (owning_controller_process_spec != NULL) {
    if ((process_spec != NULL) && !strcmp(process_spec,
                                          owning_controller_process_spec)) {
      /* Same process -- return now, instead of disposing of and
       * recreating the process-termination monitor. */
      return;
    }

    /* We are currently owned by a process, and we should no longer be
     * owned by it.  Free the process-termination monitor. */
    tor_process_monitor_free(owning_controller_process_monitor);
    owning_controller_process_monitor = NULL;

    tor_free(owning_controller_process_spec);
    owning_controller_process_spec = NULL;
  }

  tor_assert((owning_controller_process_spec == NULL) &&
             (owning_controller_process_monitor == NULL));

  if (process_spec == NULL)
    return;

  owning_controller_process_spec = tor_strdup(process_spec);
  owning_controller_process_monitor =
    tor_process_monitor_new(tor_libevent_get_base(),
                            owning_controller_process_spec,
                            LD_CONTROL,
                            owning_controller_procmon_cb, NULL,
                            &msg);

  if (owning_controller_process_monitor == NULL) {
    log_err(LD_BUG, "Couldn't create process-termination monitor for "
            "owning controller: %s.  Exiting.",
            msg);
    owning_controller_process_spec = NULL;
    tor_cleanup();
    exit(0);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function: