mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 22:03:31 +01:00
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:
parent
b5fd75a063
commit
64fc1f7bae
20
doc/TODO
20
doc/TODO
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
355
src/or/control.c
355
src/or/control.c
@ -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. */
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user