Implement all the rest of the new controller protocol, debug a little, add some new features, add ADDRMAP events.

svn:r4460
This commit is contained in:
Nick Mathewson 2005-06-19 20:40:41 +00:00
parent b5fd75a063
commit 64fc1f7bae
6 changed files with 296 additions and 116 deletions

View File

@ -54,15 +54,19 @@ For 0.1.0.x:
for 0.1.1.x:
N . Controller improvements
. new controller protocol
. Specify
. Implement
- controller should have an event to learn about new addressmappings,
e.g. when we learn a hostname to IP mapping ?
- make sure err-level log events get flushed to the controller
immediately, since tor will exit right after.
- add new getinfo options to enumerate things we only find out about
o new controller protocol
o Specify
o Implement
. Test, debug
o add new getinfo options to enumerate things we only find out about
currently via events.
o controller should have an event to learn about new addressmappings,
e.g. when we learn a hostname to IP mapping ?
. make sure err-level log events get flushed to the controller
immediately, since tor will exit right after.
o Implement
- Test, debug
- Switch example controllers to use new protocol
- switch accountingmax to count total in+out, not either in or
out. it's easy to move in this direction (not risky), but hard to
back, out if we decide we prefer it the way it already is. hm.

View File

@ -159,7 +159,7 @@ $Id$
"SETEVENTS" *(SP EventCode) CRLF
EventCode = "CIRC" / "STREAM" / "ORCONN" / "BW" / "DEBUG" /
"INFO" / "NOTICE" / "WARN" / "ERR" / "NEWDESC"
"INFO" / "NOTICE" / "WARN" / "ERR" / "NEWDESC" / "ADDRMAP"
[XXX We should have an "ADDRESSMAP" event to hear when we learn
about dns resolves, etc, so the controller can keep synced. -RD]
@ -318,7 +318,7 @@ about dns resolves, etc, so the controller can keep synced. -RD]
"stream-status"
A series of lines as for a stream status event. Each is of the form:
StreamID SP StreamStatus SP Target CRLF
StreamID SP StreamStatus SP CircID SP Target CRLF
"orconn-status"
A series of lines as for an OR connection status event. Each is of the
@ -344,9 +344,9 @@ about dns resolves, etc, so the controller can keep synced. -RD]
request for the server to extend an existing circuit with that ID according
to the specified path.
If the request is successful, the server sends a "250 OK" message
containing a message body consisting of the Circuit ID of the (maybe newly
created) circuit.
If the request is successful, the server sends a reply containing a message
body consisting of the Circuit ID of the (maybe newly created) circuit.
The syntax is "250" SP "EXTENDED" SP CircuitID CRLF.
3.10 ATTACHSTREAM
@ -491,6 +491,8 @@ about dns resolves, etc, so the controller can keep synced. -RD]
554 Invalid descriptor
555 Unmanaged entity
650 Asynchronous event notification
Unless specified to have specific contents, the human-readable messages
@ -537,20 +539,22 @@ about dns resolves, etc, so the controller can keep synced. -RD]
The syntax is:
"650" SP "STREAM" SP StreamID SP StreamStatus SP Target
"650" SP "STREAM" SP StreamID SP StreamStatus SP CircID SP Target SP
StreamStatus =
"NEW" / ; New request to connect
"NEWRESOLVE" / ; New request to resolve an address
"SENTCONNECT" / ; Sent a connect cell along a circuit
"SENTRESOLVE" / ; Sent a resolve cell along a circuit
"SUCCEEDED" / ; Received a successful reply; stream established
"SUCCEEDED" / ; Received a reply; stream established
"FAILED" / ; Stream failed and not retriable.
"CLOSED" / ; Stream closed
"DETACHED" ; Stream detached from circuit; still retriable
"DETACHED" ; Detached from circuit; still retriable.
Target = Address ":" Port
The circuit ID designates which circuit this stream is attached to. If
the stream is unattached, the circuit ID "0" is given.
4.1.3 OR Connection status changed
@ -580,6 +584,12 @@ about dns resolves, etc, so the controller can keep synced. -RD]
Syntax:
"650" SP "NEWDESC" 1*(SP ServerID)
4.1.6 New Address mapping
Syntax:
"650" SP "ADDRMAP" SP Address SP Address SP Expiry
Expiry = DQOUTE ISOTime DQUOTE / "NEVER"
5. Implementation notes
5.1. Authentication

View File

@ -154,6 +154,13 @@ circuit_close_all_marked(void)
}
}
/** DOCDOC **/
circuit_t *
_circuit_get_global_list(void)
{
return global_circuitlist;
}
/** Function to make circ-\>state human-readable */
const char *
circuit_state_to_string(int state) {

View File

@ -513,6 +513,7 @@ addressmap_virtaddress_remove(const char *addr, addressmap_entry_t *ent)
}
}
/* DOCDOC */
static void
addressmap_ent_remove(const char *addr, addressmap_entry_t *ent)
{
@ -637,6 +638,7 @@ addressmap_register(const char *address, char *new_address, time_t expires)
log_fn(LOG_INFO, "Addressmap: (re)mapped '%s' to '%s'",
safe_str(address), safe_str(ent->new_address));
control_event_address_mapped(address, ent->new_address, expires);
}
/** An attempt to resolve <b>address</b> failed at some OR.

View File

@ -71,7 +71,8 @@ const char control_c_id[] = "$Id$";
#define EVENT_NOTICE_MSG 0x0009
#define EVENT_WARN_MSG 0x000A
#define EVENT_ERR_MSG 0x000B
#define _EVENT_MAX 0x000B
#define EVENT_ADDRMAP 0x000C
#define _EVENT_MAX 0x000C
/** Array mapping from message type codes to human-readable message
* type names. */
@ -161,6 +162,7 @@ static int handle_control_closestream(connection_t *conn, uint32_t len,
const char *body);
static int handle_control_closecircuit(connection_t *conn, uint32_t len,
const char *body);
static int write_stream_target_to_buf(connection_t *conn, char *buf, size_t len);
/** Given a possibly invalid message type code <b>cmd</b>, return a
* human-readable string equivalent. */
@ -250,6 +252,7 @@ adjust_event_log_severity(void)
control_event_logmsg);
}
/* DOCDOC */
static INLINE void
connection_write_str_to_buf(const char *s, connection_t *conn)
{
@ -257,6 +260,7 @@ connection_write_str_to_buf(const char *s, connection_t *conn)
connection_write_to_buf(s, len, conn);
}
/* DOCDOC ; test */
static size_t
write_escaped_data(const char *data, size_t len, int translate_newlines,
char **out)
@ -288,50 +292,17 @@ write_escaped_data(const char *data, size_t len, int translate_newlines,
}
*outp++ = *data++;
}
*outp++ = '\r';
*outp++ = '\n';
if (outp < *out+2 || memcmp(outp-2, "\r\n", 2)) {
*outp++ = '\r';
*outp++ = '\n';
}
*outp++ = '.';
*outp++ = '\r';
*outp++ = '\n';
return outp - *out;
}
#if 0
static void
connection_write_escaped_data_to_buf(const char *data, size_t len,
int translate_newlines,
connection_t *conn)
{
const char *next;
while (len) {
if (*data == '.')
connection_write_to_buf(".", 1, conn);
if (translate_newlines)
next = tor_memmem(data, len, "\r\n", 2);
else
next = tor_memmem(data, len, "\r\n.", 3);
if (next) {
if (translate_newlines) {
connection_write_to_buf(data, next-data, conn);
connection_write_to_buf("\n", 1, conn);
len -= (next-data+2);
} else {
connection_write_to_buf(data, next-data+2, conn);
len -= (next-data+2);
}
data = next + 2;
} else {
connection_write_to_buf(data, len, conn);
break;
}
}
connection_write_to_buf(".\r\n", 3, conn);
}
#endif
/* DOCDOC ; test */
static size_t
read_escaped_data(const char *data, size_t len, int translate_newlines,
char **out)
@ -368,14 +339,54 @@ read_escaped_data(const char *data, size_t len, int translate_newlines,
return outp - *out;
}
/** DOCDOC; test **/
static const char *
get_escaped_string(const char *start, char **out, size_t *out_len)
get_escaped_string(const char *start, size_t in_len_max,
char **out, size_t *out_len)
{
/* XXXX V1 */
return NULL;
const char *cp, *end;
char *outp;
size_t len=0;
if (*start != '\"')
return NULL;
cp = start+1;
end = start+in_len_max;
/* Calculate length. */
while (1) {
if (cp >= end)
return NULL;
else if (*cp == '\\') {
if (++cp == end)
return NULL; /* Can't escape EOS. */
++cp;
++len;
} else if (*cp == '\"') {
break;
} else {
++cp;
++len;
}
}
end = cp;
outp = *out = tor_malloc(len+1);
*out_len = len;
cp = start+1;
while (cp < end) {
if (*cp == '\\')
++cp;
*outp++ = *cp++;
}
*outp = '\0';
tor_assert((outp - *out) == *out_len);
return end+1;
}
/* DOCDOC */
static void
connection_printf_to_buf(connection_t *conn, const char *format, ...)
{
@ -395,29 +406,6 @@ 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 <b>type</b> containing <b>len</b> bytes
* from <b>body</b> along the control connection <b>conn</b> */
static void
@ -514,15 +502,15 @@ send_control0_event(uint16_t event, uint32_t len, const char *body)
conns[i]->state == CONTROL_CONN_STATE_OPEN_V0 &&
conns[i]->event_mask & (1<<event)) {
send_control0_message(conns[i], CONTROL0_CMD_EVENT, buflen, buf);
if (event == EVENT_ERR_MSG) {
if (event == EVENT_ERR_MSG)
_connection_controller_force_write(conns[i]);
}
}
}
tor_free(buf);
}
/* DOCDOC */
static void
send_control1_event(uint16_t event, const char *format, ...)
{
@ -551,9 +539,8 @@ send_control1_event(uint16_t event, const char *format, ...)
conns[i]->state == CONTROL_CONN_STATE_OPEN_V1 &&
conns[i]->event_mask & (1<<event)) {
connection_write_to_buf(buf, len, conns[i]);
if (event == EVENT_ERR_MSG) {
if (event == EVENT_ERR_MSG)
_connection_controller_force_write(conns[i]);
}
}
}
}
@ -591,6 +578,7 @@ handle_control_setconf(connection_t *conn, uint32_t len, char *body)
{
int r;
struct config_line_t *lines=NULL;
char *start = body;
int v0 = STATE_IS_V0(conn->state);
if (!v0) {
@ -602,6 +590,7 @@ handle_control_setconf(connection_t *conn, uint32_t len, char *body)
++eq;
memcpy(outp, body, eq-body);
outp += (eq-body);
*outp++ = ' ';
body = eq+1;
if (*eq == '=') {
if (*body != '\"') {
@ -610,7 +599,8 @@ handle_control_setconf(connection_t *conn, uint32_t len, char *body)
} else {
char *val;
size_t val_len;
body = (char*)get_escaped_string(body, &val, &val_len);
body = (char*)get_escaped_string(body, (len - (body-start)),
&val, &val_len);
if (!body) {
connection_write_str_to_buf("551 Couldn't parse string\r\n", conn);
tor_free(config);
@ -618,6 +608,7 @@ handle_control_setconf(connection_t *conn, uint32_t len, char *body)
}
memcpy(outp, val, val_len);
outp += val_len;
tor_free(val);
}
}
while (TOR_ISSPACE(*body))
@ -702,6 +693,7 @@ handle_control_getconf(connection_t *conn, uint32_t body_len, const char *body)
}
} else {
struct config_line_t *answer = config_get_assigned_option(options,q);
/* XXXX handle non-set options in V1 at least*/
while (answer) {
struct config_line_t *next;
@ -808,6 +800,8 @@ handle_control_setevents(connection_t *conn, uint32_t len, const char *body)
event_code = EVENT_ERR_MSG;
else if (!strcasecmp(ev, "NEWDESC"))
event_code = EVENT_NEW_DESC;
else if (!strcasecmp(ev, "ADDRMAP"))
event_code = EVENT_ADDRMAP;
else {
connection_printf_to_buf(conn, "552 Unrecognized event \"%s\"\r\n",
ev);
@ -881,7 +875,7 @@ handle_control_authenticate(connection_t *conn, uint32_t len, const char *body)
password = tor_strdup("");
password_len = 0;
} else {
if (!get_escaped_string(body, &password, &password_len)) {
if (!get_escaped_string(body, len, &password, &password_len)) {
connection_write_str_to_buf("551 Invalid quoted string\r\n", conn);
return 0;
}
@ -1003,21 +997,29 @@ 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;
char *r;
size_t sz;
int v0 = STATE_IS_V0(conn->state);
lines = smartlist_create();
elts = smartlist_create();
reply = smartlist_create();
smartlist_split_string(lines, body, "\n",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
if (v0)
smartlist_split_string(lines, body, "\n",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
else
smartlist_split_string(lines, body, " ",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
/* XXXX Make errors conformant. */
SMARTLIST_FOREACH(lines, char *, line,
{
tor_strlower(line);
smartlist_split_string(elts, line, " ", 0, 2);
if (v0)
smartlist_split_string(elts, line, " ", 0, 2);
else
smartlist_split_string(elts, line, "=", 0, 2);
if (smartlist_len(elts) == 2) {
const char *from = smartlist_get(elts,0);
const char *to = smartlist_get(elts,1);
@ -1027,21 +1029,31 @@ handle_control_mapaddress(connection_t *conn, uint32_t len, const char *body)
log_fn(LOG_WARN,"Skipping invalid argument '%s' in MapAddress msg",to);
} else if (!strcmp(from, ".") || !strcmp(from, "0.0.0.0")) {
const char *addr = addressmap_register_virtual_address(
strcmp(from,".") ? RESOLVED_TYPE_HOSTNAME : RESOLVED_TYPE_IPV4,
!strcmp(from,".") ? RESOLVED_TYPE_HOSTNAME : RESOLVED_TYPE_IPV4,
tor_strdup(to));
if (!addr) {
log_fn(LOG_WARN,
"Unable to allocate address for '%s' in MapAddress msg",
safe_str(line));
} else {
size_t anslen = strlen(addr)+strlen(to)+2;
size_t anslen = strlen(addr)+strlen(to)+8;
char *ans = tor_malloc(anslen);
tor_snprintf(ans, anslen, "%s %s", addr, to);
if (v0)
tor_snprintf(ans, anslen, "%s %s", addr, to);
else
tor_snprintf(ans, anslen, "250-%s=%s", addr, to);
smartlist_add(reply, ans);
}
} else {
addressmap_register(from, tor_strdup(to), 1);
smartlist_add(reply, tor_strdup(line));
if (v0)
smartlist_add(reply, tor_strdup(line));
else {
size_t anslen = strlen(line)+8;
char *ans = tor_malloc(anslen);
tor_snprintf(ans, anslen, "250-%s", line);
smartlist_add(reply, ans);
}
}
} else {
log_fn(LOG_WARN, "Skipping MapAddress line with wrong number of items.");
@ -1053,8 +1065,15 @@ handle_control_mapaddress(connection_t *conn, uint32_t len, const char *body)
smartlist_free(lines);
smartlist_free(elts);
r = smartlist_join_strings(reply, "\n", 1, &sz);
send_control_done2(conn,r,sz);
if (v0) {
r = smartlist_join_strings(reply, "\n", 1, &sz);
send_control_done2(conn,r,sz);
} else {
if (smartlist_len(reply))
((char*)smartlist_get(reply,smartlist_len(reply)-1))[3] = ' ';
r = smartlist_join_strings(reply, "\r\n", 1, &sz);
connection_write_to_buf(r, sz, conn);
}
SMARTLIST_FOREACH(reply, char *, cp, tor_free(cp));
smartlist_free(reply);
@ -1086,6 +1105,106 @@ handle_getinfo_helper(const char *question, char **answer)
list_server_status(routerlist->routers, answer) < 0) {
return -1;
}
} else if (!strcmp(question, "circuit-status")) {
circuit_t *circ;
smartlist_t *status = smartlist_create();
for (circ = _circuit_get_global_list(); circ; circ = circ->next) {
char *s, *path;
size_t slen;
const char *state;
if (! CIRCUIT_IS_ORIGIN(circ) || circ->marked_for_close)
continue;
path = circuit_list_path(circ,0);
if (circ->state == CIRCUIT_STATE_OPEN)
state = "BUILT";
else if (strlen(path))
state = "EXTENDED";
else
state = "LAUNCHED";
slen = strlen(path)+strlen(state)+20;
s = tor_malloc(slen+1);
tor_snprintf(s, slen, "%lu %s %s", (unsigned long)circ->global_identifier,
state, path);
smartlist_add(status, s);
tor_free(path);
}
*answer = smartlist_join_strings(status, "\r\n", 1, NULL);
SMARTLIST_FOREACH(status, char *, cp, tor_free(cp));
smartlist_free(status);
} else if (!strcmp(question, "stream-status")) {
connection_t **conns;
int n_conns, i;
char buf[256];
smartlist_t *status = smartlist_create();
get_connection_array(&conns, &n_conns);
for (i=0; i < n_conns; ++i) {
const char *state;
char *s;
size_t slen;
circuit_t *circ;
if (conns[i]->type != CONN_TYPE_AP ||
conns[i]->marked_for_close ||
conns[i]->state == AP_CONN_STATE_SOCKS_WAIT)
continue;
switch (conns[i]->state)
{
case AP_CONN_STATE_CONTROLLER_WAIT:
case AP_CONN_STATE_CIRCUIT_WAIT:
if (conns[i]->socks_request &&
conns[i]->socks_request->command == SOCKS_COMMAND_RESOLVE)
state = "NEWRESOLVE";
else
state = "NEW";
break;
case AP_CONN_STATE_RENDDESC_WAIT:
case AP_CONN_STATE_CONNECT_WAIT:
state = "SENTCONNECT"; break;
case AP_CONN_STATE_RESOLVE_WAIT:
state = "SENTRESOLVE"; break;
case AP_CONN_STATE_OPEN:
state = "SUCCEEDED"; break;
default:
log_fn(LOG_WARN, "Asked for stream in unknown state %d",
conns[i]->state);
continue;
}
circ = circuit_get_by_edge_conn(conns[i]);
write_stream_target_to_buf(conns[i], buf, sizeof(buf));
slen = strlen(buf)+strlen(state)+32;
s = tor_malloc(slen+1);
tor_snprintf(s, slen, "%lu %s %lu %s",
(unsigned long) conns[i]->global_identifier,state,
circ?(unsigned long)circ->global_identifier : 0ul,
buf);
smartlist_add(status, s);
}
*answer = smartlist_join_strings(status, "\r\n", 1, NULL);
SMARTLIST_FOREACH(status, char *, cp, tor_free(cp));
smartlist_free(status);
} else if (!strcmp(question, "orconn-status")) {
connection_t **conns;
int n_conns, i;
smartlist_t *status = smartlist_create();
get_connection_array(&conns, &n_conns);
for (i=0; i < n_conns; ++i) {
const char *state;
char *s;
size_t slen;
if (conns[i]->type != CONN_TYPE_OR || conns[i]->marked_for_close)
continue;
if (conns[i]->state == OR_CONN_STATE_OPEN)
state = "CONNECTED";
else
state = "LAUNCHED";
slen = strlen(conns[i]->nickname)+strlen(state)+2;
s = tor_malloc(slen+1);
tor_snprintf(s, slen, "%s %s",conns[i]->nickname,state);
smartlist_add(status, s);
}
*answer = smartlist_join_strings(status, "\r\n", 1, NULL);
SMARTLIST_FOREACH(status, char *, cp, tor_free(cp));
smartlist_free(status);
} else if (!strcmpstart(question, "addr-mappings/")) {
time_t min_e, max_e;
smartlist_t *mappings;
@ -1152,13 +1271,13 @@ handle_control_getinfo(connection_t *conn, uint32_t len, const char *body)
if (smartlist_len(unrecognized)) {
int i;
tor_assert(!v0);
for (i=0; i < len-1; ++i)
for (i=0; i < smartlist_len(unrecognized)-1; ++i)
connection_printf_to_buf(conn,
"552-Unrecognized configuration key \"%s\"\r\n",
"552-Unrecognized 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));
"552 Unrecognized key \"%s\"\r\n",
(char*)smartlist_get(unrecognized, i));
goto done;
}
@ -1174,12 +1293,14 @@ handle_control_getinfo(connection_t *conn, uint32_t len, const char *body)
char *v = smartlist_get(answers, i+1);
/*XXXX Not an adequate test! XXXX011 */
if (!strchr(v, '\n') && !strchr(v, '\r')) {
connection_printf_to_buf(conn, "250-%s=%s\r\n", k, v);
connection_printf_to_buf(conn, "250-%s=", k);
connection_write_str_to_buf(v, conn);
connection_write_str_to_buf("\r\n", conn);
} else {
char *esc = NULL;
size_t len;
len = write_escaped_data(v, strlen(v), 1, &esc);
connection_printf_to_buf(conn, "250+%s=", k);
connection_printf_to_buf(conn, "250+%s=\r\n", k);
connection_write_to_buf(esc, len, conn);
tor_free(esc);
}
@ -1371,7 +1492,6 @@ handle_control_attachstream(connection_t *conn, uint32_t len,
return 0;
}
if (ap_conn->state != AP_CONN_STATE_CONTROLLER_WAIT) {
if (STATE_IS_V0(conn->state)) {
send_control0_error(conn, ERR_NO_STREAM,
@ -1679,6 +1799,7 @@ connection_control_reached_eof(connection_t *conn)
return 0;
}
/* DOCDOC */
static int
connection_control_process_inbuf_v1(connection_t *conn)
{
@ -1812,6 +1933,7 @@ connection_control_process_inbuf_v1(connection_t *conn)
goto again;
}
/* DOCDOC */
static int
connection_control_process_inbuf_v0(connection_t *conn)
{
@ -2015,6 +2137,22 @@ control_event_circuit_status(circuit_t *circ, circuit_status_event_t tp)
return 0;
}
/** DOCDOC */
static int
write_stream_target_to_buf(connection_t *conn, char *buf, size_t len)
{
char buf2[256];
if (conn->chosen_exit_name)
if (tor_snprintf(buf2, sizeof(buf2), ".%s.exit", conn->chosen_exit_name)<0)
return -1;
if (tor_snprintf(buf, len, "%s%s:%d",
conn->socks_request->address,
conn->chosen_exit_name ? buf2 : "",
conn->socks_request->port)<0)
return -1;
return 0;
}
/** Something has happened to the stream associated with AP connection
* <b>conn</b>: tell any interested control connections. */
int
@ -2022,19 +2160,14 @@ control_event_stream_status(connection_t *conn, stream_status_event_t tp)
{
char *msg;
size_t len;
char buf[256], buf2[256];
char buf[256];
tor_assert(conn->type == CONN_TYPE_AP);
tor_assert(conn->socks_request);
if (!EVENT_IS_INTERESTING(EVENT_STREAM_STATUS))
return 0;
if (conn->chosen_exit_name)
tor_snprintf(buf2, sizeof(buf2), ".%s.exit", conn->chosen_exit_name);
tor_snprintf(buf, sizeof(buf), "%s%s:%d",
conn->socks_request->address,
conn->chosen_exit_name ? buf2 : "",
conn->socks_request->port);
write_stream_target_to_buf(conn, buf, sizeof(buf));
if (EVENT_IS_INTERESTING0(EVENT_STREAM_STATUS)) {
len = strlen(buf);
msg = tor_malloc(5+len+1);
@ -2047,6 +2180,7 @@ control_event_stream_status(connection_t *conn, stream_status_event_t tp)
}
if (EVENT_IS_INTERESTING0(EVENT_STREAM_STATUS)) {
const char *status;
circuit_t *circ;
switch (tp)
{
case STREAM_EVENT_SENT_CONNECT: status = "SENTCONNECT"; break;
@ -2061,10 +2195,12 @@ control_event_stream_status(connection_t *conn, stream_status_event_t tp)
log_fn(LOG_WARN, "Unrecognized status code %d", (int)tp);
return 0;
}
circ = circuit_get_by_edge_conn(conn);
send_control1_event(EVENT_STREAM_STATUS,
"650 STREAM %lu %s %s\r\n",
(unsigned long)conn->global_identifier,
status, buf);
"650 STREAM %lu %s %lu %s\r\n",
(unsigned long)conn->global_identifier, status,
circ?(unsigned long)circ->global_identifier : 0ul,
buf);
}
return 0;
}
@ -2167,7 +2303,7 @@ control_event_logmsg(int severity, const char *msg)
if (*cp == '\r' || *cp == '\n')
*cp = ' ';
}
switch(severity) {
switch (severity) {
case LOG_INFO: s = "INFO"; break;
case LOG_NOTICE: s = "NOTICE"; break;
case LOG_WARN: s = "WARN"; break;
@ -2215,6 +2351,25 @@ control_event_descriptors_changed(smartlist_t *routers)
return 0;
}
/** DOCDOC */
int
control_event_address_mapped(const char *from, const char *to, time_t expires)
{
if (!EVENT_IS_INTERESTING1(EVENT_ADDRMAP))
return 0;
if (expires < 3)
send_control1_event(EVENT_ADDRMAP, "650 ADDRMAP %s %s NEVER\r\n", from, to);
else {
char buf[ISO_TIME_LEN+1];
format_local_iso_time(buf,expires);
send_control1_event(EVENT_ADDRMAP, "650 ADDRMAP %s %s \"%s\"\r\n",
from, to, buf);
}
return 0;
}
/** 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. */

View File

@ -1219,6 +1219,7 @@ void onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop);
/********************************* circuitlist.c ***********************/
circuit_t * _circuit_get_global_list(void);
const char *circuit_state_to_string(int state);
enum which_conn_changed_t { P_CONN_CHANGED=1, N_CONN_CHANGED=0 };
void circuit_set_circid_orconn(circuit_t *circ, uint16_t id,
@ -1478,6 +1479,7 @@ int control_event_or_conn_status(connection_t *conn, or_conn_status_event_t e);
int control_event_bandwidth_used(uint32_t n_read, uint32_t n_written);
void control_event_logmsg(int severity, const char *msg);
int control_event_descriptors_changed(smartlist_t *routers);
int control_event_address_mapped(const char *from, const char *to,time_t expires);
int init_cookie_authentication(int enabled);
int decode_hashed_password(char *buf, const char *hashed);