From 9b4aa8d2abbce71398e58188209a1b1d04885b96 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 17 Jun 2005 20:37:21 +0000 Subject: [PATCH] Implement all the easy bits of the new control protocol svn:r4449 --- src/or/buffers.c | 9 +- src/or/control.c | 500 +++++++++++++++++++++++++++++++++++++---------- src/or/main.c | 4 +- 3 files changed, 400 insertions(+), 113 deletions(-) diff --git a/src/or/buffers.c b/src/or/buffers.c index 4c813eb2ef..7b8f919ccd 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -1198,19 +1198,20 @@ fetch_from_buf_line(buf_t *buf, char *data_out, size_t *data_len) char *eol; size_t sz; /* Look for a CRLF. */ - if (!(eol = find_crlf_on_buf(buf, buf->cur))) + if (!(eol = find_crlf_on_buf(buf, buf->cur))) { return 0; + } sz = _buf_offset(buf, eol); - if (sz+2 > *data_len) { - *data_len = sz+2; + if (sz+3 > *data_len) { + *data_len = sz+3; return -1; } fetch_from_buf(data_out, sz+2, buf); + data_out[sz+2] = '\0'; *data_len = sz+2; return 1; } - /** Log an error and exit if buf is corrupted. */ void assert_buf_ok(buf_t *buf) diff --git a/src/or/control.c b/src/or/control.c index 1136bab2cd..91abc1a072 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -102,11 +102,15 @@ static const char * CONTROL0_COMMANDS[_CONTROL0_CMD_MAX_RECOGNIZED+1] = { * has interest in without having to walk over the global connection * list to find out. **/ -static uint32_t global_event_mask = 0; +static uint32_t global_event_mask0 = 0; +static uint32_t global_event_mask1 = 0; /** Macro: true if any control connection is interested in events of type * e. */ -#define EVENT_IS_INTERESTING(e) (global_event_mask & (1<<(e))) +#define EVENT_IS_INTERESTING0(e) (global_event_mask0 & (1<<(e))) +#define EVENT_IS_INTERESTING1(e) (global_event_mask1 & (1<<(e))) +#define EVENT_IS_INTERESTING(e) \ + ((global_event_mask0|global_event_mask1) & (1<<(e))) /** If we're using cookie-type authentication, how long should our cookies be? */ @@ -117,6 +121,8 @@ static uint32_t global_event_mask = 0; static int authentication_cookie_is_set = 0; static char authentication_cookie[AUTHENTICATION_COOKIE_LEN]; +static void connection_printf_to_buf(connection_t *conn, const char *format, ...) + CHECK_PRINTF(2,3); static void update_global_event_mask(void); static void send_control0_message(connection_t *conn, uint16_t type, uint32_t len, const char *body); @@ -125,6 +131,8 @@ static void send_control_done2(connection_t *conn, const char *msg, size_t len); static void send_control0_error(connection_t *conn, uint16_t error, const char *message); static void send_control0_event(uint16_t event, uint32_t len, const char *body); +static void send_control1_event(uint16_t event, const char *format, ...) + CHECK_PRINTF(2,3); static int handle_control_setconf(connection_t *conn, uint32_t len, char *body); static int handle_control_getconf(connection_t *conn, uint32_t len, @@ -196,12 +204,16 @@ update_global_event_mask(void) { connection_t **conns; int n_conns, i; - global_event_mask = 0; + global_event_mask0 = 0; + global_event_mask1 = 0; get_connection_array(&conns, &n_conns); for (i = 0; i < n_conns; ++i) { if (conns[i]->type == CONN_TYPE_CONTROL && STATE_IS_OPEN(conns[i]->state)) { - global_event_mask |= conns[i]->event_mask; + if (STATE_IS_V0(conns[i]->state)) + global_event_mask0 |= conns[i]->event_mask; + else + global_event_mask1 |= conns[i]->event_mask; } } @@ -246,6 +258,7 @@ connection_write_str_to_buf(const char *s, connection_t *conn) } + static void connection_printf_to_buf(connection_t *conn, const char *format, ...) { @@ -254,7 +267,7 @@ connection_printf_to_buf(connection_t *conn, const char *format, ...) int r; size_t len; va_start(ap,format); - r = tor_snprintf(buf, sizeof(buf), format, ap); + r = tor_vsnprintf(buf, sizeof(buf), format, ap); va_end(ap); len = strlen(buf); if (memcmp("\r\n\0", buf+len-2, 3)) { @@ -265,6 +278,28 @@ connection_printf_to_buf(connection_t *conn, const char *format, ...) connection_write_to_buf(buf, len, conn); } +#if 0 +static void +connection_write_reply_lines_to_buf(connection_t *conn, + const char *code, smartlist_t *lines) +{ + int i, len; + + tor_assert(strlen(code) == 3); + len = smartlist_len(lines); + if (!len) + return; + + for (i=0; i < len-1; ++i) { + connection_write_to_buf(code, 3, conn); + connection_write_to_buf("-", 1, conn); + connection_write_str_to_buf(smartlist_get(lines, i), conn); + } + connection_write_to_buf(code, 3, conn); + connection_write_to_buf(" ", 1, conn); + connection_write_str_to_buf(smartlist_get(lines, len-1), conn); +} +#endif /** Send a message of type type containing len bytes * from body along the control connection conn */ @@ -371,11 +406,47 @@ send_control0_event(uint16_t event, uint32_t len, const char *body) tor_free(buf); } +static void +send_control1_event(uint16_t event, const char *format, ...) +{ + connection_t **conns; + int n_conns, i, r; + char buf[1024]; /* XXXX Length */ + va_list ap; + size_t len; + + va_start(ap, format); + r = tor_vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + len = strlen(buf); + if (memcmp("\r\n\0", buf+len-2, 3)) { + buf[1023] = '\0'; + buf[1022] = '\n'; + buf[1021] = '\r'; + } + + tor_assert(event >= _EVENT_MIN && event <= _EVENT_MAX); + + get_connection_array(&conns, &n_conns); + for (i = 0; i < n_conns; ++i) { + if (conns[i]->type == CONN_TYPE_CONTROL && + conns[i]->state == CONTROL_CONN_STATE_OPEN_V1 && + conns[i]->event_mask & (1<state); questions = smartlist_create(); - smartlist_split_string(questions, body, "\n", - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + if (v0) { + smartlist_split_string(questions, body, "\n", + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + } else { + smartlist_split_string(questions, body, " ", + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + } answers = smartlist_create(); - SMARTLIST_FOREACH(questions, const char *, q, + unrecognized = smartlist_create(); + SMARTLIST_FOREACH(questions, char *, q, { - int recognized = config_option_is_recognized(q); - if (!recognized) { - send_control0_error(conn, ERR_UNRECOGNIZED_CONFIG_KEY, q); - goto done; + if (!config_option_is_recognized(q)) { + if (v0) { + send_control0_error(conn, ERR_UNRECOGNIZED_CONFIG_KEY, q); + goto done; + } else { + smartlist_add(unrecognized, q); + } } else { struct config_line_t *answer = config_get_assigned_option(options,q); while (answer) { struct config_line_t *next; - size_t alen = strlen(answer->key)+strlen(answer->value)+3; + size_t alen = strlen(answer->key)+strlen(answer->value)+8; char *astr = tor_malloc(alen); - tor_snprintf(astr, alen, "%s %s\n", answer->key, answer->value); + if (v0) + tor_snprintf(astr, alen, "%s %s\n", answer->key, answer->value); + else + tor_snprintf(astr, alen, "250-%s=%s\r\n", answer->key, answer->value); smartlist_add(answers, astr); next = answer->next; @@ -446,15 +531,37 @@ handle_control_getconf(connection_t *conn, uint32_t body_len, const char *body) } }); - msg = smartlist_join_strings(answers, "", 0, &msg_len); - send_control0_message(conn, CONTROL0_CMD_CONFVALUE, - (uint16_t)msg_len, msg_len?msg:NULL); + if (v0) { + msg = smartlist_join_strings(answers, "", 0, &msg_len); + send_control0_message(conn, CONTROL0_CMD_CONFVALUE, + (uint16_t)msg_len, msg_len?msg:NULL); + } else { + int i,len; + if ((len = smartlist_len(unrecognized))) { + for (i=0; i < len-1; ++i) + connection_printf_to_buf(conn, + "552-Unrecognized configuration key \"%s\"\r\n", + (char*)smartlist_get(unrecognized, i)); + connection_printf_to_buf(conn, + "552 Unrecognized configuration key \"%s\"\r\n", + (char*)smartlist_get(unrecognized, len-1)); + } else if ((len = smartlist_len(answers))) { + char *tmp = smartlist_get(answers, len-1); + tor_assert(strlen(tmp)>4); + tmp[3] = ' '; + msg = smartlist_join_strings(answers, "", 0, &msg_len); + connection_write_to_buf(msg, msg_len, conn); + } else { + connection_write_str_to_buf("250 OK\r\n", conn); + } + } done: if (answers) SMARTLIST_FOREACH(answers, char *, cp, tor_free(cp)); if (questions) SMARTLIST_FOREACH(questions, char *, cp, tor_free(cp)); smartlist_free(answers); smartlist_free(questions); + smartlist_free(unrecognized); tor_free(msg); return 0; @@ -467,22 +574,61 @@ handle_control_setevents(connection_t *conn, uint32_t len, const char *body) { uint16_t event_code; uint32_t event_mask = 0; - if (len % 2) { - send_control0_error(conn, ERR_SYNTAX, - "Odd number of bytes in setevents message"); - return 0; - } - for (; len; len -= 2, body += 2) { - event_code = ntohs(get_uint16(body)); - if (event_code < _EVENT_MIN || event_code > _EVENT_MAX) { - send_control0_error(conn, ERR_UNRECOGNIZED_EVENT_CODE, - "Unrecognized event code"); + if (STATE_IS_V0(conn->state)) { + if (len % 2) { + send_control0_error(conn, ERR_SYNTAX, + "Odd number of bytes in setevents message"); return 0; } - event_mask |= (1 << event_code); - } + for (; len; len -= 2, body += 2) { + event_code = ntohs(get_uint16(body)); + if (event_code < _EVENT_MIN || event_code > _EVENT_MAX) { + send_control0_error(conn, ERR_UNRECOGNIZED_EVENT_CODE, + "Unrecognized event code"); + return 0; + } + event_mask |= (1 << event_code); + } + } else { + smartlist_t *events = smartlist_create(); + smartlist_split_string(events, body, " ", + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + SMARTLIST_FOREACH(events, const char *, ev, + { + if (!strcasecmp(ev, "CIRC")) + event_code = EVENT_CIRCUIT_STATUS; + else if (!strcasecmp(ev, "STREAM")) + event_code = EVENT_STREAM_STATUS; + else if (!strcasecmp(ev, "ORCONN")) + event_code = EVENT_OR_CONN_STATUS; + else if (!strcasecmp(ev, "BW")) + event_code = EVENT_BANDWIDTH_USED; + else if (!strcasecmp(ev, "DEBUG")) + continue; /* Don't do debug messages */ + else if (!strcasecmp(ev, "INFO")) + event_code = EVENT_INFO_MSG; + else if (!strcasecmp(ev, "NOTICE")) + event_code = EVENT_NOTICE_MSG; + else if (!strcasecmp(ev, "WARN")) + event_code = EVENT_WARN_MSG; + else if (!strcasecmp(ev, "ERR")) + event_code = EVENT_ERR_MSG; + else if (!strcasecmp(ev, "NEWDESC")) + event_code = EVENT_NEW_DESC; + else { + connection_printf_to_buf(conn, "552 Unrecognized event \"%s\"\r\n", + ev); + SMARTLIST_FOREACH(events, char *, e, tor_free(e)); + smartlist_free(events); + return 0; + } + event_mask |= (1 << event_code); + }); + SMARTLIST_FOREACH(events, char *, e, tor_free(e)); + smartlist_free(events); + } conn->event_mask = event_mask; update_global_event_mask(); @@ -522,6 +668,7 @@ decode_hashed_password(char *buf, const char *hashed) static int handle_control_authenticate(connection_t *conn, uint32_t len, const char *body) { + /* XXXX V1 */ or_options_t *options = get_options(); if (options->CookieAuthentication) { if (len == AUTHENTICATION_COOKIE_LEN && @@ -540,16 +687,16 @@ handle_control_authenticate(connection_t *conn, uint32_t len, const char *body) goto ok; goto err; } else { - if (len == 0) { - /* if Tor doesn't demand any stronger authentication, then - * the controller can get in with a blank auth line. */ - goto ok; - } - goto err; + /* if Tor doesn't demand any stronger authentication, then + * the controller can get in with anything. */ + goto ok; } err: - send_control0_error(conn, ERR_REJECTED_AUTHENTICATION,"Authentication failed"); + if (STATE_IS_V0(conn->state)) + send_control0_error(conn,ERR_REJECTED_AUTHENTICATION,"Authentication failed"); + else + connection_write_str_to_buf("515 Authentication failed\r\n", conn); return 0; ok: log_fn(LOG_INFO, "Authenticated control connection (%d)", conn->s); @@ -567,8 +714,12 @@ handle_control_saveconf(connection_t *conn, uint32_t len, const char *body) { if (save_current_config()<0) { - send_control0_error(conn, ERR_INTERNAL, - "Unable to write configuration to disk."); + if (STATE_IS_V0(conn->state)) + send_control0_error(conn, ERR_INTERNAL, + "Unable to write configuration to disk."); + else + connection_write_str_to_buf("551 Unable to write configuration to disk.", + conn); } else { send_control_done(conn); } @@ -580,11 +731,47 @@ static int handle_control_signal(connection_t *conn, uint32_t len, const char *body) { - if (len != 1) { - send_control0_error(conn, ERR_SYNTAX, - "Body of SIGNAL command too long or too short."); - } else if (control_signal_act((uint8_t)body[0]) < 0) { - send_control0_error(conn, ERR_SYNTAX, "Unrecognized signal number."); + int sig; + if (STATE_IS_V0(conn->state)) { + if (len != 1) { + send_control0_error(conn, ERR_SYNTAX, + "Body of SIGNAL command too long or too short."); + return 0; + } else { + sig = (uint8_t)body[0]; + } + } else { + int n = 0; + char *s; + while (body[n] && ! TOR_ISSPACE(body[n])) + ++n; + s = tor_strndup(body, n); + if (!strcasecmp(s, "RELOAD") || !strcasecmp(s, "HUP")) + sig = SIGHUP; + else if (!strcasecmp(s, "SHUTDOWN") || !strcasecmp(s, "INT")) + sig = SIGINT; + else if (!strcasecmp(s, "DUMP") || !strcasecmp(s, "USR1")) + sig = SIGUSR1; + else if (!strcasecmp(s, "DEBUG") || !strcasecmp(s, "USR2")) + sig = SIGUSR2; + else if (!strcasecmp(s, "HALT") || !strcasecmp(s, "TERM")) + sig = SIGTERM; + else { + connection_printf_to_buf(conn, "552 Unrecognized signal code \"%s\"\r\n", + body); + sig = -1; + } + tor_free(s); + if (sig<0) + return 0; + } + + if (control_signal_act(sig) < 0) { + if (STATE_IS_V0(conn->state)) + send_control0_error(conn, ERR_SYNTAX, "Unrecognized signal number."); + else + connection_write_str_to_buf("551 Internal error acting on signal\r\n", + conn); } else { send_control_done(conn); } @@ -595,6 +782,7 @@ handle_control_signal(connection_t *conn, uint32_t len, static int handle_control_mapaddress(connection_t *conn, uint32_t len, const char *body) { + /* XXXX V1 */ smartlist_t *elts; smartlist_t *lines; smartlist_t *reply; @@ -704,6 +892,7 @@ handle_getinfo_helper(const char *question, char **answer) static int handle_control_getinfo(connection_t *conn, uint32_t len, const char *body) { + /* XXXX V1 */ smartlist_t *questions = NULL; smartlist_t *answers = NULL; char *msg = NULL, *ans; @@ -746,6 +935,7 @@ static int handle_control_extendcircuit(connection_t *conn, uint32_t len, const char *body) { + /* XXXX V1 */ smartlist_t *router_nicknames, *routers; uint32_t circ_id; circuit_t *circ; @@ -825,6 +1015,7 @@ static int handle_control_attachstream(connection_t *conn, uint32_t len, const char *body) { + /* XXXX V1 */ uint32_t conn_id; uint32_t circ_id; connection_t *ap_conn; @@ -878,6 +1069,7 @@ static int handle_control_postdescriptor(connection_t *conn, uint32_t len, const char *body) { + /* XXXX V1 */ const char *msg=NULL; switch (router_load_single_router(body, &msg)) { case -1: @@ -899,6 +1091,7 @@ static int handle_control_redirectstream(connection_t *conn, uint32_t len, const char *body) { + /* XXXX V1 */ connection_t *ap_conn; uint32_t conn_id; if (len < 6) { @@ -926,6 +1119,7 @@ static int handle_control_closestream(connection_t *conn, uint32_t len, const char *body) { + /* XXXX V1 */ uint32_t conn_id; connection_t *ap_conn; uint8_t reason; @@ -955,6 +1149,7 @@ static int handle_control_closecircuit(connection_t *conn, uint32_t len, const char *body) { + /* XXXX V1 */ uint32_t circ_id; circuit_t *circ; int safe; @@ -1048,6 +1243,7 @@ static int connection_control_process_inbuf_v1(connection_t *conn) { size_t data_len, cmd_len; + char *args; tor_assert(conn); tor_assert(conn->type == CONN_TYPE_CONTROL); @@ -1064,7 +1260,7 @@ connection_control_process_inbuf_v1(connection_t *conn) while (1) { size_t last_idx; int r; - while (1) { + do { data_len = conn->incoming_cmd_len - conn->incoming_cmd_cur_len; r = fetch_from_buf_line(conn->inbuf, conn->incoming_cmd+conn->incoming_cmd_cur_len, @@ -1073,7 +1269,7 @@ connection_control_process_inbuf_v1(connection_t *conn) /* Line not all here yet. Wait. */ return 0; else if (r == -1) { - while (conn->incoming_cmd_len < data_len) + 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); } @@ -1098,70 +1294,84 @@ connection_control_process_inbuf_v1(connection_t *conn) /* Okay, we now have a command sitting on conn->incoming_cmd. See if we * recognize it. */ + cmd_len = 0; while (cmd_len < data_len && !isspace(conn->incoming_cmd[cmd_len])) ++cmd_len; + /* + log_fn(LOG_NOTICE, "READ A COMMAND FROM THE BUFFER: <%s> [%d]", + conn->incoming_cmd, (int)cmd_len); + */ + data_len -= cmd_len; + conn->incoming_cmd[cmd_len]='\0'; + args = conn->incoming_cmd+cmd_len+1; + while (*args == ' ' || *args == '\t') { + ++args; + --data_len; + } + /* + log_fn(LOG_NOTICE, "COMMAND IS: <%s>", conn->incoming_cmd); + log_fn(LOG_NOTICE, "ARGS ARE: <%s>", args); + */ + if (conn->state == CONTROL_CONN_STATE_NEEDAUTH_V1 && - strncasecmp(conn->incoming_cmd, "AUTHENTICATE", cmd_len)) { + strcasecmp(conn->incoming_cmd, "AUTHENTICATE")) { connection_write_str_to_buf("514 Authentication required.\r\n", conn); conn->incoming_cmd_cur_len = 0; goto again; } - if (!strncasecmp(conn->incoming_cmd, "SETCONF", cmd_len)) { - if (handle_control_setconf(conn, 0, NULL)) + if (!strcasecmp(conn->incoming_cmd, "SETCONF")) { + if (handle_control_setconf(conn, data_len, args)) return -1; - } else if (!strncasecmp(conn->incoming_cmd, "GETCONF", cmd_len)) { - if (handle_control_getconf(conn, 0, NULL)) + } else if (!strcasecmp(conn->incoming_cmd, "GETCONF")) { + if (handle_control_getconf(conn, data_len, args)) return -1; - } else if (!strncasecmp(conn->incoming_cmd, "SETEVENTS", cmd_len)) { - if (handle_control_setevents(conn, 0, NULL)) + } else if (!strcasecmp(conn->incoming_cmd, "SETEVENTS")) { + if (handle_control_setevents(conn, data_len, args)) return -1; - } else if (!strncasecmp(conn->incoming_cmd, "AUTENTICATE", cmd_len)) { - if (handle_control_authenticate(conn, 0, NULL)) + } else if (!strcasecmp(conn->incoming_cmd, "AUTHENTICATE")) { + if (handle_control_authenticate(conn, data_len, args)) return -1; - } else if (!strncasecmp(conn->incoming_cmd, "SAVECONF", cmd_len)) { - if (handle_control_saveconf(conn, 0, NULL)) + } else if (!strcasecmp(conn->incoming_cmd, "SAVECONF")) { + if (handle_control_saveconf(conn, data_len, args)) return -1; - } else if (!strncasecmp(conn->incoming_cmd, "SIGNAL", cmd_len)) { - if (handle_control_signal(conn, 0, NULL)) + } else if (!strcasecmp(conn->incoming_cmd, "SIGNAL")) { + if (handle_control_signal(conn, data_len, args)) return -1; - } else if (!strncasecmp(conn->incoming_cmd, "MAPADDRESS", cmd_len)) { - if (handle_control_mapaddress(conn, 0, NULL)) + } else if (!strcasecmp(conn->incoming_cmd, "MAPADDRESS")) { + if (handle_control_mapaddress(conn, data_len, args)) return -1; - } else if (!strncasecmp(conn->incoming_cmd, "GETINFO", cmd_len)) { - if (handle_control_getinfo(conn, 0, NULL)) + } else if (!strcasecmp(conn->incoming_cmd, "GETINFO")) { + if (handle_control_getinfo(conn, data_len, args)) return -1; - } else if (!strncasecmp(conn->incoming_cmd, "EXTENDCIRCUIT", cmd_len)) { - if (handle_control_extendcircuit(conn, 0, NULL)) + } else if (!strcasecmp(conn->incoming_cmd, "EXTENDCIRCUIT")) { + if (handle_control_extendcircuit(conn, data_len, args)) return -1; - } else if (!strncasecmp(conn->incoming_cmd, "ATTACHSTREAM", cmd_len)) { - if (handle_control_attachstream(conn, 0, NULL)) + } else if (!strcasecmp(conn->incoming_cmd, "ATTACHSTREAM")) { + if (handle_control_attachstream(conn, data_len, args)) return -1; - } else if (!strncasecmp(conn->incoming_cmd, "+POSTDESCRIPTOR", cmd_len)) { - if (handle_control_postdescriptor(conn, 0, NULL)) + } else if (!strcasecmp(conn->incoming_cmd, "+POSTDESCRIPTOR")) { + if (handle_control_postdescriptor(conn, data_len, args)) return -1; - } else if (!strncasecmp(conn->incoming_cmd, "REDIRECTSTREAM", cmd_len)) { - if (handle_control_redirectstream(conn, 0, NULL)) + } else if (!strcasecmp(conn->incoming_cmd, "REDIRECTSTREAM")) { + if (handle_control_redirectstream(conn, data_len, args)) return -1; - } else if (!strncasecmp(conn->incoming_cmd, "CLOSESTREAM", cmd_len)) { - if (handle_control_closestream(conn, 0, NULL)) + } else if (!strcasecmp(conn->incoming_cmd, "CLOSESTREAM")) { + if (handle_control_closestream(conn, data_len, args)) return -1; - } else if (!strncasecmp(conn->incoming_cmd, "CLOSECIRCUIT", cmd_len)) { - if (handle_control_closecircuit(conn, 0, NULL)) + } else if (!strcasecmp(conn->incoming_cmd, "CLOSECIRCUIT")) { + if (handle_control_closecircuit(conn, data_len, args)) return -1; } else { - conn->incoming_cmd[cmd_len] = '\0'; - connection_printf_to_buf(conn, "510 Unrecognizd command \"%s\"\r\n", + connection_printf_to_buf(conn, "510 Unrecognized command \"%s\"\r\n", conn->incoming_cmd); } conn->incoming_cmd_cur_len = 0; goto again; - } - static int connection_control_process_inbuf_v0(connection_t *conn) { @@ -1326,22 +1536,42 @@ int control_event_circuit_status(circuit_t *circ, circuit_status_event_t tp) { char *path, *msg; - size_t path_len; if (!EVENT_IS_INTERESTING(EVENT_CIRCUIT_STATUS)) return 0; tor_assert(circ); tor_assert(CIRCUIT_IS_ORIGIN(circ)); path = circuit_list_path(circ,0); - path_len = strlen(path); - msg = tor_malloc(1+4+path_len+1); /* event, circid, path, NUL. */ - msg[0] = (uint8_t) tp; - set_uint32(msg+1, htonl(circ->global_identifier)); - strlcpy(msg+5,path,path_len+1); + if (EVENT_IS_INTERESTING0(EVENT_CIRCUIT_STATUS)) { + size_t path_len = strlen(path); + msg = tor_malloc(1+4+path_len+1); /* event, circid, path, NUL. */ + msg[0] = (uint8_t) tp; + set_uint32(msg+1, htonl(circ->global_identifier)); + strlcpy(msg+5,path,path_len+1); - send_control0_event(EVENT_CIRCUIT_STATUS, (uint32_t)(path_len+6), msg); + send_control0_event(EVENT_CIRCUIT_STATUS, (uint32_t)(path_len+6), msg); + tor_free(msg); + } + if (EVENT_IS_INTERESTING1(EVENT_CIRCUIT_STATUS)) { + const char *status; + 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_fn(LOG_WARN, "Unrecognized status code %d", (int)tp); + return 0; + } + send_control1_event(EVENT_CIRCUIT_STATUS, + "650 CIRC %lu %s %s\r\n", + (unsigned long)circ->global_identifier, + status, path); + } tor_free(path); - tor_free(msg); + return 0; } @@ -1364,15 +1594,38 @@ control_event_stream_status(connection_t *conn, stream_status_event_t tp) tor_snprintf(buf, sizeof(buf), "%s%s:%d", conn->socks_request->address, conn->chosen_exit_name ? buf2 : "", - conn->socks_request->port), - len = strlen(buf); - msg = tor_malloc(5+len+1); - msg[0] = (uint8_t) tp; - set_uint32(msg+1, htonl(conn->global_identifier)); - strlcpy(msg+5, buf, len+1); + conn->socks_request->port); + if (EVENT_IS_INTERESTING0(EVENT_STREAM_STATUS)) { + len = strlen(buf); + msg = tor_malloc(5+len+1); + msg[0] = (uint8_t) tp; + set_uint32(msg+1, htonl(conn->global_identifier)); + strlcpy(msg+5, buf, len+1); - send_control0_event(EVENT_STREAM_STATUS, (uint32_t)(5+len+1), msg); - tor_free(msg); + send_control0_event(EVENT_STREAM_STATUS, (uint32_t)(5+len+1), msg); + tor_free(msg); + } + if (EVENT_IS_INTERESTING0(EVENT_STREAM_STATUS)) { + const char *status; + 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; + default: + log_fn(LOG_WARN, "Unrecognized status code %d", (int)tp); + return 0; + } + send_control1_event(EVENT_STREAM_STATUS, + "650 STREAM %lu %s %s\r\n", + (unsigned long)conn->global_identifier, + status, buf); + } return 0; } @@ -1389,10 +1642,28 @@ control_event_or_conn_status(connection_t *conn,or_conn_status_event_t tp) if (!EVENT_IS_INTERESTING(EVENT_OR_CONN_STATUS)) return 0; - buf[0] = (uint8_t)tp; - strlcpy(buf+1,conn->nickname,sizeof(buf)-1); - len = strlen(buf+1); - send_control0_event(EVENT_OR_CONN_STATUS, (uint32_t)(len+1), buf); + if (EVENT_IS_INTERESTING0(EVENT_OR_CONN_STATUS)) { + buf[0] = (uint8_t)tp; + strlcpy(buf+1,conn->nickname,sizeof(buf)-1); + len = strlen(buf+1); + send_control0_event(EVENT_OR_CONN_STATUS, (uint32_t)(len+1), buf); + } + if (EVENT_IS_INTERESTING1(EVENT_OR_CONN_STATUS)) { + const char *status; + 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; + default: + log_fn(LOG_WARN, "Unrecognized status code %d", (int)tp); + return 0; + } + send_control1_event(EVENT_OR_CONN_STATUS, + "650 ORCONN %s %s\r\n", + conn->nickname, status); + } return 0; } @@ -1403,12 +1674,17 @@ control_event_bandwidth_used(uint32_t n_read, uint32_t n_written) { char buf[8]; - if (!EVENT_IS_INTERESTING(EVENT_BANDWIDTH_USED)) - return 0; - - set_uint32(buf, htonl(n_read)); - set_uint32(buf+4, htonl(n_written)); - send_control0_event(EVENT_BANDWIDTH_USED, 8, buf); + if (EVENT_IS_INTERESTING0(EVENT_BANDWIDTH_USED)) { + set_uint32(buf, htonl(n_read)); + set_uint32(buf+4, htonl(n_written)); + send_control0_event(EVENT_BANDWIDTH_USED, 8, buf); + } + if (EVENT_IS_INTERESTING1(EVENT_BANDWIDTH_USED)) { + send_control1_event(EVENT_BANDWIDTH_USED, + "650 BW %lu %lu\r\n", + (unsigned long)n_read, + (unsigned long)n_written); + } return 0; } @@ -1417,6 +1693,7 @@ control_event_bandwidth_used(uint32_t n_read, uint32_t n_written) void control_event_logmsg(int severity, const char *msg) { + /* XXXX V1 */ static int sending_logmsg=0; int oldlog, event; @@ -1461,12 +1738,19 @@ control_event_descriptors_changed(smartlist_t *routers) base16_encode(buf,sizeof(buf),r->identity_digest,DIGEST_LEN); smartlist_add(identities, tor_strdup(buf)); }); - msg = smartlist_join_strings(identities, ",", 1, &len); - send_control0_event(EVENT_NEW_DESC, len+1, msg); - + if (EVENT_IS_INTERESTING0(EVENT_NEW_DESC)) { + msg = smartlist_join_strings(identities, ",", 0, &len); + send_control0_event(EVENT_NEW_DESC, len+1, msg); + tor_free(msg); + } + if (EVENT_IS_INTERESTING1(EVENT_NEW_DESC)) { + msg = smartlist_join_strings(identities, " ", 0, &len); + send_control1_event(EVENT_NEW_DESC, "650 NEWDESC %s\r\n", msg); + tor_free(msg); + } SMARTLIST_FOREACH(identities, char *, cp, tor_free(cp)); smartlist_free(identities); - tor_free(msg); + return 0; } diff --git a/src/or/main.c b/src/or/main.c index e855c06ee1..66eb2fd787 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -16,7 +16,9 @@ const char main_c_id[] = "$Id$"; #include #endif -/* These signals are defined to help control_signal_act work. */ +/* These signals are defined to help control_signal_act work. + * XXXX Move into or.h or compat.h + */ #ifndef SIGHUP #define SIGHUP 1 #endif