diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 451584cd3e..d49e68931d 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -912,16 +912,34 @@ static int connection_ap_handshake_process_socks(connection_t *conn) { addresstype = parse_extended_hostname(socks->address); if (addresstype == EXIT_HOSTNAME) { - /* .exit -- modify conn to specify the exit node. */ + /* foo.exit -- modify conn->chosen_exit_node to specify the exit + * node, and conn->address to hold only the address portion.*/ char *s = strrchr(socks->address,'.'); - if (!s || s[1] == '\0') { - log_fn(LOG_WARN,"Malformed exit address '%s'. Refusing.", + if (s && s[1] != '\0') { + conn->chosen_exit_name = tor_strdup(s+1); + *s = 0; + } else if (s[1] == '\0') { + log_fn(LOG_WARN,"Malformed exit address '%s.exit'. Refusing.", safe_str(socks->address)); connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); return -1; + } else { + tor_assert(!s); /* address is of the form server.exit. */ + struct in_addr in; + routerinfo_t *r = router_get_by_nickname(socks->address); + if (r) { + conn->chosen_exit_name = tor_strdup(socks->address); + /* XXXX Should this use server->address instead? */ + in.s_addr = htonl(r->addr); + strlcpy(socks->address, inet_ntoa(in), sizeof(socks->address)); + } else { + log_fn(LOG_WARN, + "Unrecognized server in exit address '%s.exit'. Refusing.", + safe_str(socks->address)); + connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); + return -1; + } } - conn->chosen_exit_name = tor_strdup(s+1); - *s = 0; } if (addresstype != ONION_HOSTNAME) {