Commit 1359871c authored by Nick Mathewson's avatar Nick Mathewson 🐻
Browse files

r13070@catbus: nickm | 2007-05-29 15:53:21 -0400

 Fix handling of resolves with very long or otherwise malformed addresses, and comment dns_resolve better, and stop making what should be a BUG warning into an assert(0).  This fixes bug 427, which was introduced around 9900/9931/9932.  Not a backport candidate: 0.1.2.x never had this bug.


svn:r10399
parent 3f9afa06
...@@ -536,8 +536,9 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn) ...@@ -536,8 +536,9 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn)
} }
} }
log_err(LD_BUG,"edge conn not in circuit's list?"); log_warn(LD_BUG,"Edge connection not in circuit's list.");
tor_assert(0); /* should never get here */ /* Don't give an error here; it's harmless. */
// tor_fragile_assert();
} }
/** Find each circuit that has been unused for too long, or dirty /** Find each circuit that has been unused for too long, or dirty
......
...@@ -536,30 +536,42 @@ dns_resolve(edge_connection_t *exitconn) ...@@ -536,30 +536,42 @@ dns_resolve(edge_connection_t *exitconn)
r = dns_resolve_impl(exitconn, is_resolve, oncirc, &hostname); r = dns_resolve_impl(exitconn, is_resolve, oncirc, &hostname);
switch (r) { switch (r) {
case 1: case 1:
/* We got an answer without a lookup. (Either the answer was
* cached, or it was obvious (like an IP address).)*/
if (is_resolve) { if (is_resolve) {
/* Send the answer back right now, and detach. */
if (hostname) if (hostname)
send_resolved_hostname_cell(exitconn, hostname); send_resolved_hostname_cell(exitconn, hostname);
else else
send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4); send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4);
exitconn->on_circuit = NULL; exitconn->on_circuit = NULL;
} else { } else {
/* Add to the n_streams list; the calling function will send back a
* connected cell. */
exitconn->next_stream = oncirc->n_streams; exitconn->next_stream = oncirc->n_streams;
oncirc->n_streams = exitconn; oncirc->n_streams = exitconn;
} }
break; break;
case 0: case 0:
/* add it into the linked list of resolving_streams on this circuit */ /* The request is pending: add the connection into the linked list of
* resolving_streams on this circuit. */
exitconn->_base.state = EXIT_CONN_STATE_RESOLVING; exitconn->_base.state = EXIT_CONN_STATE_RESOLVING;
exitconn->next_stream = oncirc->resolving_streams; exitconn->next_stream = oncirc->resolving_streams;
oncirc->resolving_streams = exitconn; oncirc->resolving_streams = exitconn;
break; break;
case -2: case -2:
case -1: case -1:
/* The request failed before it could start: cancel this connection,
* and stop everybody waiting forthe same connection. */
if (is_resolve) { if (is_resolve) {
send_resolved_cell(exitconn, send_resolved_cell(exitconn,
(r == -1) ? RESOLVED_TYPE_ERROR : RESOLVED_TYPE_ERROR_TRANSIENT); (r == -1) ? RESOLVED_TYPE_ERROR : RESOLVED_TYPE_ERROR_TRANSIENT);
} }
exitconn->on_circuit = NULL; exitconn->on_circuit = NULL;
dns_cancel_pending_resolve(exitconn->_base.address);
if (!exitconn->_base.marked_for_close) { if (!exitconn->_base.marked_for_close) {
connection_free(TO_CONN(exitconn)); connection_free(TO_CONN(exitconn));
//XXX020 ... and we just leak exitconn otherwise? -RD //XXX020 ... and we just leak exitconn otherwise? -RD
...@@ -838,6 +850,7 @@ dns_cancel_pending_resolve(const char *address) ...@@ -838,6 +850,7 @@ dns_cancel_pending_resolve(const char *address)
assert_connection_ok(TO_CONN(pendconn), 0); assert_connection_ok(TO_CONN(pendconn), 0);
tor_assert(pendconn->_base.s == -1); tor_assert(pendconn->_base.s == -1);
if (!pendconn->_base.marked_for_close) { if (!pendconn->_base.marked_for_close) {
/* XXXX020 RESOURCELIMIT? Not RESOLVEFAILED??? */
connection_edge_end(pendconn, END_STREAM_REASON_RESOURCELIMIT); connection_edge_end(pendconn, END_STREAM_REASON_RESOURCELIMIT);
} }
circ = circuit_get_by_edge_conn(pendconn); circ = circuit_get_by_edge_conn(pendconn);
...@@ -1247,8 +1260,8 @@ launch_resolve(edge_connection_t *exitconn) ...@@ -1247,8 +1260,8 @@ launch_resolve(edge_connection_t *exitconn)
log_warn(LD_EXIT, "eventdns rejected address %s: error %d.", log_warn(LD_EXIT, "eventdns rejected address %s: error %d.",
escaped_safe_str(addr), r); escaped_safe_str(addr), r);
r = evdns_err_is_transient(r) ? -2 : -1; r = evdns_err_is_transient(r) ? -2 : -1;
dns_cancel_pending_resolve(addr); /* also sends end and frees */ tor_free(addr); /* There is no evdns request in progress; stop
tor_free(addr); * addr from getting leaked. */
} }
return r; return r;
} }
......
...@@ -2658,14 +2658,23 @@ resolv_conf_parse_line(char *const start, int flags) { ...@@ -2658,14 +2658,23 @@ resolv_conf_parse_line(char *const start, int flags) {
#define NEXT_TOKEN strtok_r(NULL, delims, &strtok_state) #define NEXT_TOKEN strtok_r(NULL, delims, &strtok_state)
char *const first_token = strtok_r(start, delims, &strtok_state); char *const first_token = strtok_r(start, delims, &strtok_state);
if (!first_token) return; if (!first_token) {
log(EVDNS_LOG_WARN,"No token.");
return;
}
log(EVDNS_LOG_WARN,"Token is %s; flags is %d", first_token, flags);
if (!strcmp(first_token, "nameserver") && (flags & DNS_OPTION_NAMESERVERS)) { if (!strcmp(first_token, "nameserver") && (flags & DNS_OPTION_NAMESERVERS)) {
const char *const nameserver = NEXT_TOKEN; const char *const nameserver = NEXT_TOKEN;
struct in_addr ina; struct in_addr ina;
log(EVDNS_LOG_WARN,"Parsed nameserver %s", nameserver);
if (inet_aton(nameserver, &ina)) { if (inet_aton(nameserver, &ina)) {
// address is valid // address is valid
log(EVDNS_LOG_WARN,"Liked it.");
evdns_nameserver_add(ina.s_addr); evdns_nameserver_add(ina.s_addr);
} }
} else if (!strcmp(first_token, "domain") && (flags & DNS_OPTION_SEARCH)) { } else if (!strcmp(first_token, "domain") && (flags & DNS_OPTION_SEARCH)) {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment