Karsten Loesing schrieb: > Hi Marcus, > - You changed encoding of v2 hidden service descriptors, so that > introduction points can be addressed via IPv6 in > rend_encode_v2_intro_points(), but I think you did not change parsing of > those descriptors, so that descriptors containing introduction points > with IPv6 addresses would be rejected; see > rend_decrypt_introduction_points(). Hello Karsten, I think I fixed that. Hello Nick, > - You're right that the preferred way to store addresses that could be > either IPv4 or IPv6 is indeed with tor_addr_t. (Thanks for the > reminder, BTW: I fixed tor_addr_t to be a tagged union of in_addr and > in6_addr, not of sockaddr_in and sockaddr_in6.) I changed much of it to tor_addr_t. It looks much better. > - Generally speaking, we try to avoid duplicated "cut and paste" code; > it makes it hard to be sure that we can update all instances of the > original code path. (connection_or_init_conn_from_address6, for > example, is almost exactly the same as the existing > connection_init_conn_from_address.) that one is gone now. Thanks for the info. As for the changed log-strings. I removed them manually from the diff. I hope patch can still work with it. I did test the code and it can connect normally to the ipv4-internet and to the ipv6-hidden-service. Marcus -- Marcus Wolschon Wolschon Softwaredesign und Beratung UStID: DE238951181 Marcus@xxxxxxxxxxxx +49 177/6272871 (m-a-r-c-u-s-1)
Index: or/circuitlist.c
===================================================================
--- or/circuitlist.c
+++ or/circuitlist.c
@@ -235,7 +235,7 @@
tor_assert(circ->state == CIRCUIT_STATE_OR_WAIT);
if (tor_digest_is_zero(circ->n_conn_id_digest)) {
/* Look at addr/port. This is an unkeyed connection. */
- if (circ->n_addr != or_conn->_base.addr ||
+ if ( (compare_addr(circ->n_addr, or_conn->_base.addr) != 0) ||
circ->n_port != or_conn->_base.port)
continue;
} else {
@@ -558,8 +558,8 @@
}
}
}
- if (!circ->n_conn && circ->n_addr && circ->n_port &&
- circ->n_addr == conn->addr &&
+ if (!circ->n_conn && (circ->n_addr.family != AF_INET || circ->n_addr.addr.in_addr.s_addr) && circ->n_port &&
+ (compare_addr(circ->n_addr, conn->addr) == 0)&&
circ->n_port == conn->port &&
conn->type == CONN_TYPE_OR &&
!memcmp(TO_OR_CONN(conn)->identity_digest, circ->n_conn_id_digest,
Index: or/connection_or.c
===================================================================
--- or/connection_or.c
+++ or/connection_or.c
@@ -339,14 +339,20 @@
if (get_options()->HttpsProxy) {
char buf[1024];
- char addrbuf[INET_NTOA_BUF_LEN];
- struct in_addr in;
+ char addrbuf[64];
char *base64_authenticator=NULL;
const char *authenticator = get_options()->HttpsProxyAuthenticator;
+
+ if (conn->addr.family == AF_INET6) {
+ struct in6_addr addr;
+ addr = conn->addr.addr.in6_addr;
+ tor_inet_ntop(AF_INET6, &addr, addrbuf, sizeof(addrbuf));
+ } else {
+ struct in_addr in;
+ in.s_addr = htonl(conn->addr.addr.in_addr.s_addr);
+ tor_inet_ntoa(&in, addrbuf, sizeof(addrbuf));
+ }
- in.s_addr = htonl(conn->addr);
- tor_inet_ntoa(&in, addrbuf, sizeof(addrbuf));
-
if (authenticator) {
base64_authenticator = alloc_http_authenticator(authenticator);
if (!base64_authenticator)
@@ -379,7 +385,7 @@
* by checking to see if this describes a router we know. */
static void
connection_or_init_conn_from_address(or_connection_t *conn,
- uint32_t addr, uint16_t port,
+ struct tor_addr_t addr, uint16_t port,
const char *id_digest,
int started_here)
{
@@ -392,15 +398,17 @@
conn->_base.port = port;
conn->real_addr = addr;
if (r) {
- if (conn->_base.addr == r->addr)
+ if (conn->_base.addr.family == AF_INET && conn->_base.addr.addr.in_addr.s_addr == r->addr)
conn->is_canonical = 1;
+
if (!started_here) {
/* Override the addr/port, so our log messages will make sense.
* This is dangerous, since if we ever try looking up a conn by
* its actual addr/port, we won't remember. Careful! */
/* XXXX020 this is stupid, and it's the reason we need real_addr to
* track is_canonical properly. */
- conn->_base.addr = r->addr;
+ conn->_base.addr.family = AF_INET;
+ conn->_base.addr.addr.in_addr.s_addr = r->addr;
conn->_base.port = r->or_port;
}
conn->nickname = tor_strdup(r->nickname);
@@ -420,7 +428,11 @@
conn->identity_digest, DIGEST_LEN);
}
tor_free(conn->_base.address);
- conn->_base.address = tor_dup_addr(addr);
+ if (addr.family == AF_INET6) {
+ conn->_base.address = tor_dup_addr6(addr.addr.in6_addr);
+ } else {
+ conn->_base.address = tor_dup_addr(addr.addr.in_addr.s_addr);
+ }
}
}
@@ -495,7 +507,7 @@
* Return the launched conn, or NULL if it failed.
*/
or_connection_t *
-connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest)
+connection_or_connect(tor_addr_t addr, uint16_t port, const char *id_digest)
{
or_connection_t *conn;
or_options_t *options = get_options();
@@ -507,7 +519,7 @@
return NULL;
}
- conn = TO_OR_CONN(connection_new(CONN_TYPE_OR, AF_INET));
+ conn = TO_OR_CONN(connection_new(CONN_TYPE_OR, addr.family));
/* set up conn so it's got all the data we need to remember */
connection_or_init_conn_from_address(conn, addr, port, id_digest, 1);
@@ -516,7 +528,8 @@
if (options->HttpsProxy) {
/* we shouldn't connect directly. use the https proxy instead. */
- addr = options->HttpsProxyAddr;
+ addr.family = AF_INET;
+ addr.addr.in_addr.s_addr = options->HttpsProxyAddr;
port = options->HttpsProxyPort;
}
@@ -797,8 +810,13 @@
conn->handshake_state->started_here,
id_digest) < 0)
return -1;
- connection_or_init_conn_from_address(conn, conn->_base.addr,
- conn->_base.port, id_digest, 0);
+ if (conn->_base.socket_family == AF_INET6) {
+ connection_or_init_conn_from_address6(conn, conn->_base.addr6,
+ conn->_base.port, id_digest, 0);
+ } else {
+ connection_or_init_conn_from_address(conn, conn->_base.addr4,
+ conn->_base.port, id_digest, 0);
+ }
if (connection_or_act_on_netinfo(conn)<0)
return -1;
return connection_or_set_state_open(conn);
@@ -1068,7 +1086,11 @@
set_uint32(cell.payload, htonl(now));
cell.payload[4] = RESOLVED_TYPE_IPV4;
cell.payload[5] = 4;
- set_uint32(cell.payload+6, htonl(conn->_base.addr));
+ if (conn->_base.addr.family == AF_INET6) {
+ log_warn(LD_BUG, "we do not support ipv6 in connection_or_send_netinfo() ");
+ return -1;
+ }
+ set_uint32(cell.payload+6, htonl(conn->_base.addr.addr.in_addr.s_addr));
/* My address. */
if ((me = router_get_my_routerinfo())) {
Index: or/config.c
===================================================================
--- or/config.c
+++ or/config.c
@@ -1940,9 +1940,9 @@
*/
int
resolve_my_address(int warn_severity, or_options_t *options,
- uint32_t *addr_out, char **hostname_out)
+ tor_addr_t *addr_out, char **hostname_out)
{
- struct in_addr in;
+ struct in_addr in; //TODO: support ipv4
struct hostent *rent;
char hostname[256];
int explicit_ip=1;
@@ -2056,8 +2056,9 @@
}
log_debug(LD_CONFIG, "Resolved Address to '%s'.", tmpbuf);
- *addr_out = ntohl(in.s_addr);
- if (last_resolved_addr && last_resolved_addr != *addr_out) {
+ addr_out->family = AF_INET;
+ addr_out->addr.in_addr.s_addr = ntohl(in.s_addr);
+ if (last_resolved_addr && last_resolved_addr != addr_out->addr.in_addr.s_addr) {
/* Leave this as a notice, regardless of the requested severity,
* at least until dynamic IP address support becomes bulletproof. */
log_notice(LD_NET,
@@ -2065,7 +2066,7 @@
tmpbuf);
ip_address_changed(0);
}
- if (last_resolved_addr != *addr_out) {
+ if (last_resolved_addr != addr_out->addr.in_addr.s_addr) {
const char *method;
const char *h = hostname;
if (explicit_ip) {
@@ -2083,7 +2084,7 @@
"EXTERNAL_ADDRESS ADDRESS=%s METHOD=%s %s%s",
tmpbuf, method, h?"HOSTNAME=":"", h);
}
- last_resolved_addr = *addr_out;
+ last_resolved_addr = addr_out->addr.in_addr.s_addr;
if (hostname_out)
*hostname_out = tor_strdup(hostname);
return 0;
@@ -2604,7 +2605,7 @@
if (authdir_mode(options)) {
/* confirm that our address isn't broken, so we can complain now */
- uint32_t tmp;
+ struct tor_addr_t tmp;
if (resolve_my_address(LOG_WARN, options, &tmp, NULL) < 0)
REJECT("Failed to resolve/guess local address. See logs for details.");
}
Index: or/rendservice.c
===================================================================
--- or/rendservice.c
+++ or/rendservice.c
@@ -20,7 +20,9 @@
typedef struct rend_service_port_config_t {
uint16_t virtual_port;
uint16_t real_port;
- uint32_t real_addr;
+ u_int16_t real_family; // AF_INET or AF_INET6
+ uint32_t real_addr4; // ipv4-address of hidden service depending on real_family
+ struct in6_addr real_addr6; // ipv6-address of hidden service depending on real_family
} rend_service_port_config_t;
/** Try to maintain this many intro points per service if possible. */
@@ -129,7 +131,6 @@
{
int i;
rend_service_port_config_t *p;
- struct in_addr addr;
if (!service->intro_prefer_nodes)
service->intro_prefer_nodes = tor_strdup("");
@@ -166,15 +167,25 @@
} else {
smartlist_set_capacity(service->ports, -1);
smartlist_add(rend_service_list, service);
- log_debug(LD_REND,"Configuring service with directory \"%s\"",
+ log_debug(LD_REND,"Configuring hidden service with directory \"%s\"",
service->directory);
for (i = 0; i < smartlist_len(service->ports); ++i) {
- char addrbuf[INET_NTOA_BUF_LEN];
p = smartlist_get(service->ports, i);
- addr.s_addr = htonl(p->real_addr);
- tor_inet_ntoa(&addr, addrbuf, sizeof(addrbuf));
- log_debug(LD_REND,"Service maps port %d to %s:%d",
- p->virtual_port, addrbuf, p->real_port);
+ if (p->real_family == AF_INET6) {
+ char addrbuf[42];
+ struct in6_addr addr;
+ addr = p->real_addr6;
+ tor_inet_ntop(AF_INET6, &addr, addrbuf, sizeof(addrbuf));
+ log_debug(LD_REND,"Hidden service maps ipv6 port %d to [%s]:%d",
+ p->virtual_port, addrbuf, p->real_port);
+ } else {
+ char addrbuf[INET_NTOA_BUF_LEN];
+ struct in_addr addr;
+ addr.s_addr = htonl(p->real_addr4);
+ tor_inet_ntoa(&addr, addrbuf, sizeof(addrbuf));
+ log_debug(LD_REND,"Hidden service maps ipv4 port %d to %s:%d",
+ p->virtual_port, addrbuf, p->real_port);
+ }
}
}
}
@@ -193,7 +204,6 @@
int virtport;
int realport;
uint16_t p;
- uint32_t addr;
const char *addrport;
rend_service_port_config_t *result = NULL;
@@ -212,32 +222,60 @@
goto err;
}
+ result = tor_malloc(sizeof(rend_service_port_config_t));
+ result->virtual_port = virtport;
+
if (smartlist_len(sl) == 1) {
/* No addr:port part; use default. */
- realport = virtport;
- addr = 0x7F000001u; /* 127.0.0.1 */
+ result->real_family = AF_INET;
+ result->real_port = virtport;
+ result->real_addr4 = 0x7F000001u; /* 127.0.0.1 */
+ log_warn(LD_CONFIG,"no address nor port in hidden service port "
+ "configuration->localhost.");
} else {
addrport = smartlist_get(sl,1);
if (strchr(addrport, ':') || strchr(addrport, '.')) {
- if (parse_addr_port(LOG_WARN, addrport, NULL, &addr, &p)<0) {
- log_warn(LD_CONFIG,"Unparseable address in hidden service port "
+ uint32_t addr4;
+ if (parse_addr_port(LOG_WARN, addrport, NULL, &addr4, &p)<0) {
+ struct in6_addr addr6;
+ if (parse_addr6_port(LOG_WARN, addrport, NULL, &addr6, &p)<0) {
+ log_warn(LD_CONFIG,"Unparseable address in hidden service port "
"configuration.");
- goto err;
+ goto err;
+ } else {
+ // ipv6-address could be parsed
+ result->real_family = AF_INET6;
+ result->real_addr6 = addr6;
+
+ char addrbuf[42];
+ struct in6_addr addr;
+ addr = result->real_addr6;
+ tor_inet_ntop(AF_INET6, &addr, addrbuf, sizeof(addrbuf));
+ log_warn(LD_CONFIG,"parse_port_config() parseable ipv6-address %s in hidden service port "
+ "configuration.", addrbuf);
+ }
+ } else {
+ // ipv4-address could be parsed
+ result->real_family = AF_INET;
+ result->real_addr4 = addr4;
+ log_warn(LD_CONFIG,"parse_port_config() parseable ipv4-address in hidden service port "
+ "configuration.");
}
realport = p?p:virtport;
+ result->real_port = realport;
} else {
/* No addr:port, no addr -- must be port. */
realport = atoi(addrport);
if (realport < 1 || realport > 65535)
goto err;
- addr = 0x7F000001u; /* Default to 127.0.0.1 */
+ result->real_family = AF_INET;
+ result->real_port = realport;
+ result->real_addr4 = 0x7F000001u; /* 127.0.0.1 */
+ log_warn(LD_CONFIG,"no address in hidden service port "
+ "configuration->localhost.");
}
}
- result = tor_malloc(sizeof(rend_service_port_config_t));
- result->virtual_port = virtport;
- result->real_port = realport;
- result->real_addr = addr;
err:
SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
smartlist_free(sl);
@@ -286,6 +324,7 @@
if (!strcasecmp(line->key, "HiddenServicePort")) {
portcfg = parse_port_config(line->value);
if (!portcfg) {
+ log_warn(LD_CONFIG, "unparsable HiddenServicePort %s", line->value);
rend_service_free(service);
return -1;
}
@@ -387,7 +426,7 @@
const char *name = smartlist_get(service->intro_nodes, i);
router = router_get_by_nickname(name, 1);
if (!router) {
- log_info(LD_REND,"Router '%s' not found for intro point %d. Skipping.",
+ log_info(LD_REND,"Router '%s' not found for hidden service intro point %d. Skipping.",
safe_str(name), i);
continue;
}
@@ -428,7 +467,7 @@
if (strlcpy(fname,s->directory,sizeof(fname)) >= sizeof(fname) ||
strlcat(fname,PATH_SEPARATOR"private_key",sizeof(fname))
>= sizeof(fname)) {
- log_warn(LD_CONFIG, "Directory name too long to store key file: \"%s\".",
+ log_warn(LD_CONFIG, "Directory name too long to store key file: \"%s\" for hidden service.",
s->directory);
return -1;
}
@@ -438,17 +477,17 @@
/* Create service file */
if (rend_get_service_id(s->private_key, s->service_id)<0) {
- log_warn(LD_BUG, "Internal error: couldn't encode service ID.");
+ log_warn(LD_BUG, "Internal error: couldn't encode hidden service ID.");
return -1;
}
if (crypto_pk_get_digest(s->private_key, s->pk_digest)<0) {
- log_warn(LD_BUG, "Couldn't compute hash of public key.");
+ log_warn(LD_BUG, "Couldn't compute hash of public key for hidden service.");
return -1;
}
if (strlcpy(fname,s->directory,sizeof(fname)) >= sizeof(fname) ||
strlcat(fname,PATH_SEPARATOR"hostname",sizeof(fname))
>= sizeof(fname)) {
- log_warn(LD_CONFIG, "Directory name too long to store hostname file:"
+ log_warn(LD_CONFIG, "Directory name too long to store hostname file for hidden service:"
" \"%s\".", s->directory);
return -1;
}
@@ -585,7 +626,8 @@
/* Version 2 INTRODUCE2 cell. */
int klen;
extend_info = tor_malloc_zero(sizeof(extend_info_t));
- extend_info->addr = ntohl(get_uint32(buf+1));
+ extend_info->addr.family = AF_INET;
+ extend_info->addr.addr.in_addr.s_addr = ntohl(get_uint32(buf+1));
extend_info->port = ntohs(get_uint16(buf+5));
memcpy(extend_info->identity_digest, buf+7, DIGEST_LEN);
extend_info->nickname[0] = '$';
@@ -1153,7 +1195,7 @@
smartlist_free(desc_ids);
}
uploaded = 1;
- log_info(LD_REND, "Successfully uploaded v2 rend descriptors!");
+ log_info(LD_REND, "Successfully uploaded v2 rend hidden service descriptors for service %s!", serviceid);
}
}
@@ -1394,11 +1436,25 @@
chosen_port = smartlist_choose(matching_ports);
smartlist_free(matching_ports);
if (chosen_port) {
- conn->_base.addr = chosen_port->real_addr;
+ if (chosen_port->real_family == AF_INET6) {
+ conn->_base.addr.addr.in6_addr = chosen_port->real_addr6;
+
+ char addrbuf[42];
+ struct in6_addr addr;
+ addr = conn->_base.addr.addr.in6_addr;
+ tor_inet_ntop(AF_INET6, &addr, addrbuf, sizeof(addrbuf));
+ log_info(LD_REND, "rend_service_set_connection_addr_port() found virtual ipv6-port mapping exist for port %d on service %s on local ipv6 %s",
+ conn->_base.port, serviceid, addrbuf);
+ } else {
+ conn->_base.addr.addr.in_addr.s_addr = chosen_port->real_addr4;
+ log_info(LD_REND, "rend_service_set_connection_addr_port() found virtual ipv4-port mapping exist for port %d on (ipv4) service %s",
+ conn->_base.port, serviceid);
+ }
+ conn->_base.addr.family = chosen_port->real_family;
conn->_base.port = chosen_port->real_port;
return 0;
}
- log_info(LD_REND, "No virtual port mapping exists for port %d on service %s",
+ log_info(LD_REND, "No virtual port mapping exists for port %d on hidden ipv4 or ipv6 - service %s",
conn->_base.port,serviceid);
return -1;
}
Index: or/routerlist.c
===================================================================
--- or/routerlist.c
+++ or/routerlist.c
@@ -3306,7 +3306,7 @@
authority_type_t type)
{
trusted_dir_server_t *ent;
- uint32_t a;
+ struct tor_addr_t a;
char *hostname = NULL;
size_t dlen;
if (!trusted_dir_servers)
@@ -3320,7 +3320,7 @@
return;
}
} else {
- if (tor_lookup_hostname(address, &a)) {
+ if (tor_addr_lookup(address, AF_INET, &a) || a.family != AF_INET) {
log_warn(LD_CONFIG,
"Unable to lookup address for directory server at '%s'",
address);
@@ -3332,7 +3332,7 @@
ent = tor_malloc_zero(sizeof(trusted_dir_server_t));
ent->nickname = nickname ? tor_strdup(nickname) : NULL;
ent->address = hostname;
- ent->addr = a;
+ ent->addr = a.addr.in_addr.s_addr;
ent->dir_port = dir_port;
ent->or_port = or_port;
ent->is_running = 1;
@@ -4507,7 +4507,7 @@
/* XXX020 make this louder once we have some v2hidservs */
log_info(LD_REND, "We don't have enough hidden service directories to "
- "perform v2 rendezvous operations!");
+ "perform v2 rendezvous operations! id=%s", id);
return -1;
}
Index: or/dirserv.c
===================================================================
--- or/dirserv.c
+++ or/dirserv.c
@@ -2053,7 +2053,7 @@
{
or_options_t *options = get_options();
networkstatus_vote_t *v3_out = NULL;
- uint32_t addr;
+ tor_addr_t addr;
char *hostname = NULL, *client_versions = NULL, *server_versions = NULL;
const char *contact;
smartlist_t *routers, *routerstatuses;
@@ -2082,7 +2082,7 @@
}
if (!strchr(hostname, '.')) {
tor_free(hostname);
- hostname = tor_dup_addr(addr);
+ hostname = tor_dup_addr(addr.addr.in_addr.s_addr);
}
if (crypto_pk_get_digest(private_key, signing_key_digest)<0) {
log_err(LD_BUG, "Error computing signing key digest");
@@ -2201,7 +2201,7 @@
voter->nickname = tor_strdup(options->Nickname);
memcpy(voter->identity_digest, identity_digest, DIGEST_LEN);
voter->address = hostname;
- voter->addr = addr;
+ voter->addr = addr.addr.in_addr.s_addr;
voter->dir_port = options->DirPort;
voter->or_port = options->ORPort;
voter->contact = tor_strdup(contact);
@@ -2245,7 +2245,7 @@
char published[ISO_TIME_LEN+1];
char digest[DIGEST_LEN];
struct in_addr in;
- uint32_t addr;
+ tor_addr_t addr;
crypto_pk_env_t *private_key;
routerlist_t *rl = router_get_routerlist();
time_t now = time(NULL);
@@ -2265,7 +2265,7 @@
log_warn(LD_NET, "Couldn't resolve my hostname");
goto done;
}
- in.s_addr = htonl(addr);
+ in.s_addr = htonl(addr.addr.in_addr.s_addr);
tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr));
format_iso_time(published, now);
@@ -2686,7 +2686,10 @@
/* Remember when we started trying to determine reachability */
if (!router->testing_since)
router->testing_since = now;
- connection_or_connect(router->addr, router->or_port,
+ struct tor_addr_t connectaddr;
+ connectaddr.family = AF_INET;
+ connectaddr.addr.in_addr.s_addr = router->addr;
+ connection_or_connect(connectaddr, router->or_port,
id_digest);
}
});
Index: or/control.c
===================================================================
--- or/control.c
+++ or/control.c
@@ -1233,10 +1233,10 @@
} else if (!strcmp(question, "features/names")) {
*answer = tor_strdup("VERBOSE_NAMES EXTENDED_EVENTS");
} else if (!strcmp(question, "address")) {
- uint32_t addr;
+ tor_addr_t addr;
if (router_pick_published_address(get_options(), &addr) < 0)
return -1;
- *answer = tor_dup_addr(addr);
+ *answer = tor_dup_addr(addr.addr.in_addr.s_addr);
} else if (!strcmp(question, "dir-usage")) {
*answer = directory_dump_request_log();
} else if (!strcmp(question, "fingerprint")) {
Index: or/connection_edge.c
===================================================================
--- or/connection_edge.c
+++ or/connection_edge.c
@@ -204,7 +204,12 @@
payload[0] = reason;
if (reason == END_STREAM_REASON_EXITPOLICY &&
!connection_edge_is_rendezvous_stream(conn)) {
- set_uint32(payload+1, htonl(conn->_base.addr));
+ if (conn->_base.addr.family == AF_INET6) {
+ log_warn(LD_BUG,
+ "ipv6 not supported in connection_edge_end for non-rendezvous-streams");
+ return 0;
+ }
+ set_uint32(payload+1, htonl(conn->_base.addr.addr.in_addr.s_addr));
set_uint32(payload+5, htonl(dns_clip_ttl(conn->address_ttl)));
payload_len += 8;
}
@@ -280,19 +285,27 @@
int
connection_edge_finished_connecting(edge_connection_t *edge_conn)
{
- char valbuf[INET_NTOA_BUF_LEN];
connection_t *conn;
- struct in_addr in;
tor_assert(edge_conn);
tor_assert(edge_conn->_base.type == CONN_TYPE_EXIT);
conn = TO_CONN(edge_conn);
tor_assert(conn->state == EXIT_CONN_STATE_CONNECTING);
- in.s_addr = htonl(conn->addr);
- tor_inet_ntoa(&in,valbuf,sizeof(valbuf));
- log_info(LD_EXIT,"Exit connection to %s:%u (%s) established.",
- escaped_safe_str(conn->address),conn->port,safe_str(valbuf));
+ if (conn->addr.family == AF_INET6) {
+ char addrbuf[42];
+ struct in6_addr addr = conn->addr.addr.in6_addr;
+ tor_inet_ntop(AF_INET6, &addr, addrbuf, sizeof(addrbuf));
+ log_info(LD_EXIT,"Exit connection to %s:%u (%s) established.",
+ escaped_safe_str(conn->address),conn->port,safe_str(addrbuf));
+ } else {
+ char valbuf[INET_NTOA_BUF_LEN];
+ struct in_addr in;
+ in.s_addr = htonl(conn->addr.addr.in_addr.s_addr);
+ tor_inet_ntoa(&in,valbuf,sizeof(valbuf));
+ log_info(LD_EXIT,"Exit connection to %s:%u (%s) established.",
+ escaped_safe_str(conn->address),conn->port,safe_str(valbuf));
+ }
conn->state = EXIT_CONN_STATE_OPEN;
connection_watch_events(conn, EV_READ); /* stop writing, continue reading */
@@ -305,8 +318,16 @@
RELAY_COMMAND_CONNECTED, NULL, 0) < 0)
return 0; /* circuit is closed, don't continue */
} else {
+ if (conn->addr.family == AF_INET6) {
+ char addrbuf[42];
+ struct in6_addr addr = conn->addr.addr.in6_addr;
+ tor_inet_ntop(AF_INET6, &addr, addrbuf, sizeof(addrbuf));
+ log_info(LD_EXIT,"ipv6 not supported for exit connection to %s:%u (%s) that is not a rendezvous_stream.",
+ escaped_safe_str(conn->address),conn->port,safe_str(addrbuf));
+ return -1;
+ }
char connected_payload[8];
- set_uint32(connected_payload, htonl(conn->addr));
+ set_uint32(connected_payload, htonl(conn->addr.addr.in_addr.s_addr));
set_uint32(connected_payload+4,
htonl(dns_clip_ttl(edge_conn->address_ttl)));
if (connection_edge_send_command(edge_conn,
@@ -359,7 +380,7 @@
continue;
conn = TO_EDGE_CONN(c);
/* if it's an internal linked connection, don't yell its status. */
- severity = (!conn->_base.addr && !conn->_base.port)
+ severity = ((conn->_base.addr.family == AF_INET && !conn->_base.addr.addr.in_addr.s_addr) && !conn->_base.port)
? LOG_INFO : LOG_NOTICE;
seconds_idle = now - conn->_base.timestamp_lastread;
@@ -1992,7 +2013,7 @@
}
conn->_base.address = tor_strdup("(Tor_internal)");
- conn->_base.addr = 0;
+ conn->_base.addr.addr.in_addr.s_addr = 0;
conn->_base.port = 0;
if (connection_add(TO_CONN(conn)) < 0) { /* no space, forget it */
@@ -2371,8 +2392,9 @@
if (rh.command == RELAY_COMMAND_BEGIN_DIR) {
tor_assert(or_circ);
- if (or_circ->p_conn && or_circ->p_conn->_base.addr)
- n_stream->_base.addr = or_circ->p_conn->_base.addr;
+ if (or_circ->p_conn && (or_circ->p_conn->_base.addr.family != AF_INET || or_circ->p_conn->_base.addr.addr.in_addr.s_addr)) {
+ n_stream->_base.addr = or_circ->p_conn->_base.addr;
+ }
return connection_exit_connect_dir(n_stream);
}
@@ -2444,6 +2466,12 @@
return 0;
}
+/** compare the 2 given ipv6-addresses
+ * *
+ * * returns 0 if they are equal.
+ * */
+int compare_in6_addr(struct in6_addr a, struct in6_addr b);
+
/** Connect to conn's specified addr and port. If it worked, conn
* has now been added to the connection_array.
*
@@ -2454,10 +2482,11 @@
void
connection_exit_connect(edge_connection_t *edge_conn)
{
- uint32_t addr;
- uint16_t port;
connection_t *conn = TO_CONN(edge_conn);
+ struct tor_addr_t addr = conn->addr;
+ uint16_t port = conn->port;
+
if (!connection_edge_is_rendezvous_stream(edge_conn) &&
router_compare_to_my_exit_policy(edge_conn)) {
log_info(LD_EXIT,"%s:%d failed exit policy. Closing.",
@@ -2468,19 +2497,26 @@
return;
}
- addr = conn->addr;
- port = conn->port;
if (redirect_exit_list) {
SMARTLIST_FOREACH(redirect_exit_list, exit_redirect_t *, r,
- {
- if (!addr_mask_cmp_bits(addr, r->addr, r->maskbits) &&
+ {/*
+ if (!addr_mask_cmp_bits(addr, r->addr, r->maskbits) &&
+ (r->port_min <= port) && (port <= r->port_max)) {
+ */
+ if (
+ (conn->addr.family == AF_INET/*r->family*/ &&
+ ((conn->addr.family == AF_INET && !addr_mask_cmp_bits(addr.addr.in_addr.s_addr, r->addr, r->maskbits)) /*&&
+ (conn->socket_family == AF_INET6 && !compare_addr(addr, r->addr))*/)
+ ) &&
(r->port_min <= port) && (port <= r->port_max)) {
- struct in_addr in;
+
if (r->is_redirect) {
char tmpbuf[INET_NTOA_BUF_LEN];
- addr = r->addr_dest;
+ addr.family = AF_INET;
+ addr.addr.in_addr.s_addr = r->addr_dest;
port = r->port_dest;
- in.s_addr = htonl(addr);
+ struct in_addr in;
+ in.s_addr = htonl(addr.addr.in_addr.s_addr);
tor_inet_ntoa(&in, tmpbuf, sizeof(tmpbuf));
log_debug(LD_EXIT, "Redirecting connection from %s:%d to %s:%d",
escaped_safe_str(conn->address), conn->port,
@@ -2492,7 +2528,8 @@
}
log_debug(LD_EXIT,"about to try connecting");
- switch (connection_connect(conn, conn->address, addr, port)) {
+ int s = connection_connect(conn, conn->address, addr, port);
+ switch (s) {
case -1:
connection_edge_end_errno(edge_conn);
circuit_detach_stream(circuit_get_by_edge_conn(edge_conn), edge_conn);
@@ -2525,8 +2562,11 @@
NULL, 0);
} else { /* normal stream */
/* This must be the original address, not the redirected address. */
+ if (conn->addr.family == AF_INET6) {
+ log_warn(LD_BUG,"we do not support ipv6 in connection_exit_connect!");
+ }
char connected_payload[8];
- set_uint32(connected_payload, htonl(conn->addr));
+ set_uint32(connected_payload, htonl(conn->addr.addr.in_addr.s_addr));
set_uint32(connected_payload+4,
htonl(dns_clip_ttl(edge_conn->address_ttl)));
connection_edge_send_command(edge_conn,
@@ -2554,7 +2594,8 @@
dirconn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR, AF_INET));
- dirconn->_base.addr = 0x7f000001;
+ dirconn->_base.addr.family = AF_INET;
+ dirconn->_base.addr.addr.in_addr.s_addr = 0x7f000001;
dirconn->_base.port = 0;
dirconn->_base.address = tor_strdup("Tor network");
dirconn->_base.type = CONN_TYPE_DIR;
Index: or/dns.c
===================================================================
--- or/dns.c
+++ or/dns.c
@@ -413,7 +413,7 @@
{
case RESOLVED_TYPE_IPV4:
buf[1] = 4;
- set_uint32(buf+2, htonl(conn->_base.addr));
+ set_uint32(buf+2, htonl(conn->_base.addr.addr.in_addr.s_addr));
set_uint32(buf+6, htonl(ttl));
buflen = 10;
break;
@@ -627,7 +627,8 @@
/* first check if exitconn->_base.address is an IP. If so, we already
* know the answer. */
if (tor_inet_aton(exitconn->_base.address, &in) != 0) {
- exitconn->_base.addr = ntohl(in.s_addr);
+ exitconn->_base.addr.family = AF_INET;
+ exitconn->_base.addr.addr.in_addr.s_addr = ntohl(in.s_addr);
exitconn->address_ttl = DEFAULT_DNS_TTL;
return 1;
}
@@ -694,7 +695,8 @@
tor_assert(is_resolve);
*hostname_out = tor_strdup(resolve->result.hostname);
} else {
- exitconn->_base.addr = resolve->result.addr;
+ exitconn->_base.addr.family = AF_INET;
+ exitconn->_base.addr.addr.in_addr.s_addr = resolve->result.addr;
}
return 1;
case CACHE_STATE_CACHED_FAILED:
@@ -1000,7 +1002,8 @@
pendconn = pend->conn; /* don't pass complex things to the
connection_mark_for_close macro */
assert_connection_ok(TO_CONN(pendconn),time(NULL));
- pendconn->_base.addr = addr;
+ pendconn->_base.addr.family = AF_INET;
+ pendconn->_base.addr.addr.in_addr.s_addr = addr;
pendconn->address_ttl = ttl;
if (outcome != DNS_RESOLVE_SUCCEEDED) {
Index: or/or.h
===================================================================
--- or/or.h
+++ or/or.h
@@ -862,11 +862,7 @@
* could write? */
time_t timestamp_created; /**< When was this connection_t created? */
- /* XXXX020 make this ipv6-capable */
- int socket_family; /**< Address family of this connection's socket. Usually
- * AF_INET, but it can also be AF_UNIX, or in the future
- * AF_INET6 */
- uint32_t addr; /**< IP of the other side of the connection; used to identify
+ tor_addr_t addr; /**< IP of the other side of the connection; used to identify
* routers, along with port. */
uint16_t port; /**< If non-zero, port on the other end
* of the connection. */
@@ -928,7 +924,7 @@
* recent, we can rate limit it further. */
time_t client_used;
- uint32_t real_addr; /**DOCDOC */
+ struct tor_addr_t real_addr; /**< DOCDOC*/
circ_id_type_t circ_id_type:2; /**< When we send CREATE cells along this
* connection, which half of the space should
@@ -1598,8 +1594,8 @@
char nickname[MAX_HEX_NICKNAME_LEN+1]; /**< This router's nickname for
* display. */
char identity_digest[DIGEST_LEN]; /**< Hash of this router's identity key. */
- uint16_t port; /**< OR port. */
- uint32_t addr; /**< IP address in host order. */
+ uint16_t port; /**< OR port. */
+ struct tor_addr_t addr; /**< IP address. */
crypto_pk_env_t *onion_key; /**< Current onionskin key. */
} extend_info_t;
@@ -1758,8 +1754,8 @@
uint16_t n_circ_id;
/** The port for the OR that is next in this circuit. */
uint16_t n_port;
- /** The IPv4 address of the OR that is next in this circuit. */
- uint32_t n_addr;
+ /** The IP address of the OR that is next in this circuit. */
+ struct tor_addr_t n_addr;
/** True iff we are waiting for n_conn_cells to become less full before
* allowing p_streams to add any more cells. (Origin circuit only.) */
@@ -2598,7 +2594,7 @@
int options_trial_assign(config_line_t *list, int use_defaults,
int clear_first, char **msg);
int resolve_my_address(int warn_severity, or_options_t *options,
- uint32_t *addr, char **hostname_out);
+ struct tor_addr_t *addr, char **hostname_out);
int is_local_IP(uint32_t ip) ATTR_PURE;
void options_init(or_options_t *options);
int options_init_from_torrc(int argc, char **argv);
@@ -2647,7 +2643,7 @@
void connection_expire_held_open(void);
-int connection_connect(connection_t *conn, const char *address, uint32_t addr,
+int connection_connect(connection_t *conn, const char *address, struct tor_addr_t addr,
uint16_t port);
int retry_all_listeners(smartlist_t *replaced_conns,
smartlist_t *new_conns);
@@ -2800,7 +2796,7 @@
int connection_or_finish_or_handshake(or_connection_t *conn);
#endif
-or_connection_t *connection_or_connect(uint32_t addr, uint16_t port,
+or_connection_t *connection_or_connect(struct tor_addr_t addr, uint16_t port,
const char *id_digest);
int connection_tls_start_handshake(or_connection_t *conn, int receiving);
@@ -3381,6 +3377,12 @@
void policies_parse_from_options(or_options_t *options);
int cmp_addr_policies(addr_policy_t *a, addr_policy_t *b);
+/** compare the 2 given ipv4 or ipv6-addresses
+ *
+ * returns 0 if they are equal.
+ */
+int compare_addr(struct tor_addr_t a, struct tor_addr_t b);
+
addr_policy_result_t compare_addr_to_addr_policy(uint32_t addr,
uint16_t port, addr_policy_t *policy);
int policies_parse_exit_policy(config_line_t *cfg, addr_policy_t **dest,
@@ -3684,7 +3686,7 @@
int router_digest_is_me(const char *digest);
int router_is_me(routerinfo_t *router);
int router_fingerprint_is_me(const char *fp);
-int router_pick_published_address(or_options_t *options, uint32_t *addr);
+int router_pick_published_address(or_options_t *options, struct tor_addr_t *addr);
int router_rebuild_descriptor(int force);
int router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
crypto_pk_env_t *ident_key);
Index: or/connection.c
===================================================================
--- or/connection.c
+++ or/connection.c
@@ -198,7 +198,7 @@
conn->conn_array_index = -1; /* also default to 'not used' */
conn->type = type;
- conn->socket_family = socket_family;
+ conn->addr.family = socket_family;
if (!connection_is_listener(conn)) { /* listeners never use their buf */
conn->inbuf = buf_new();
conn->outbuf = buf_new();
@@ -298,7 +298,7 @@
buf_free(conn->inbuf);
buf_free(conn->outbuf);
} else {
- if (conn->socket_family == AF_UNIX) {
+ if (conn->addr.family == AF_UNIX) {
/* For now only control ports can be unix domain sockets
* and listeners at the same time */
tor_assert(conn->type == CONN_TYPE_CONTROL_LISTENER);
@@ -646,6 +646,44 @@
});
}
+/** Create an AF_INET6 listenaddr struct.
+ * <b>listenaddress</b> provides the host and optionally the port information
+ * for the new structure. If no port is provided in <b>listenaddress</b> then
+ * <b>listenport</b> is used.
+ *
+ * If not NULL <b>readable_addrress</b> will contain a copy of the host part of
+ * <b>listenaddress</b>.
+ *
+ * The listenaddr struct has to be freed by the caller.
+ */
+static struct sockaddr_in6 *
+create_inet6_sockaddr(const char *listenaddress, uint16_t listenport,
+ char **readable_address) {
+ struct sockaddr_in6 *listenaddr = NULL;
+ struct in6_addr addr6;
+ uint16_t usePort = 0;
+
+ if (parse_addr6_port(LOG_WARN,
+ listenaddress, readable_address, &addr6, &usePort)<0) {
+ log_warn(LD_CONFIG,
+ "Error parsing/resolving ipv6 ListenAddress %s", listenaddress);
+ goto err;
+ }
+ if (usePort==0)
+ usePort = listenport;
+
+ listenaddr = tor_malloc_zero(sizeof(struct sockaddr_in6));
+ listenaddr->sin6_addr = addr6;
+ listenaddr->sin6_family = AF_INET;
+ listenaddr->sin6_port = htons((uint16_t) usePort);
+
+ return listenaddr;
+
+ err:
+ tor_free(listenaddr);
+ return NULL;
+}
+
/** Create an AF_INET listenaddr struct.
* <b>listenaddress</b> provides the host and optionally the port information
* for the new structure. If no port is provided in <b>listenaddress</b> then
@@ -748,7 +786,7 @@
return NULL;
}
- if (listensockaddr->sa_family == AF_INET) {
+ if (listensockaddr->sa_family == AF_INET6) {
int is_tcp = (type != CONN_TYPE_AP_DNS_LISTENER);
#ifndef MS_WINDOWS
int one=1;
@@ -757,6 +795,55 @@
start_reading = 1;
usePort = ntohs( (uint16_t)
+ ((struct sockaddr_in6 *)listensockaddr)->sin6_port);
+
+ log_notice(LD_NET, "Opening %s on ipv6 %s:%d",
+ conn_type_to_string(type), address, usePort);
+
+ s = tor_open_socket(PF_INET6,
+ is_tcp ? SOCK_STREAM : SOCK_DGRAM,
+ is_tcp ? IPPROTO_TCP: IPPROTO_UDP);
+ if (s < 0) {
+ log_warn(LD_NET,"ipv6 socket creation failed.");
+ goto err;
+ }
+
+#ifndef MS_WINDOWS
+ /* REUSEADDR on normal places means you can rebind to the port
+ * right after somebody else has let it go. But REUSEADDR on win32
+ * means you can bind to the port _even when somebody else
+ * already has it bound_. So, don't do that on Win32. */
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*) &one, sizeof(one));
+#endif
+
+ if (bind(s, listensockaddr, sizeof(struct sockaddr_in6)) < 0) {
+ const char *helpfulhint = "";
+ int e = tor_socket_errno(s);
+ if (ERRNO_IS_EADDRINUSE(e))
+ helpfulhint = ". Is Tor already running?";
+ log_warn(LD_NET, "Could not bind to ipv6 %s:%u: %s%s", address, usePort,
+ tor_socket_strerror(e), helpfulhint);
+ tor_close_socket(s);
+ goto err;
+ }
+
+ if (is_tcp) {
+ if (listen(s,SOMAXCONN) < 0) {
+ log_warn(LD_NET, "Could not listen on ipv6 %s:%u: %s", address, usePort,
+ tor_socket_strerror(tor_socket_errno(s)));
+ tor_close_socket(s);
+ goto err;
+ }
+ }
+ } else if (listensockaddr->sa_family == AF_INET) {
+ int is_tcp = (type != CONN_TYPE_AP_DNS_LISTENER);
+#ifndef MS_WINDOWS
+ int one=1;
+#endif
+ if (is_tcp)
+ start_reading = 1;
+
+ usePort = ntohs( (uint16_t)
((struct sockaddr_in *)listensockaddr)->sin_port);
log_notice(LD_NET, "Opening %s on %s:%d",
@@ -844,7 +931,7 @@
set_socket_nonblocking(s);
conn = connection_new(type, listensockaddr->sa_family);
- conn->socket_family = listensockaddr->sa_family;
+ conn->addr.family = listensockaddr->sa_family;
conn->s = s;
conn->address = tor_strdup(address);
conn->port = usePort;
@@ -878,23 +965,41 @@
check_sockaddr_in(struct sockaddr *sa, int len, int level)
{
int ok = 1;
- struct sockaddr_in *sin=(struct sockaddr_in*)sa;
- if (len != sizeof(struct sockaddr_in)) {
- log_fn(level, LD_NET, "Length of address not as expected: %d vs %d",
- len,(int)sizeof(struct sockaddr_in));
- ok = 0;
- }
- if (sa->sa_family != AF_INET) {
+ if (sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin=(struct sockaddr_in6*)sa;
+
+ if (len != sizeof(struct sockaddr_in6)) {
+ log_fn(level, LD_NET, "Length of ipv6 address not as expected: %d vs %d",
+ len,(int)sizeof(struct sockaddr_in));
+ ok = 0;
+ }
+
+ if (sin->sin6_port == 0) {
+ log_fn(level, LD_NET,
+ "Address for new connection has port equal to zero.");
+ ok = 0;
+ }
+ } else if (sa->sa_family == AF_INET) {
+ struct sockaddr_in *sin=(struct sockaddr_in*)sa;
+
+ if (len != sizeof(struct sockaddr_in)) {
+ log_fn(level, LD_NET, "Length of ipv4 address not as expected: %d vs %d",
+ len,(int)sizeof(struct sockaddr_in));
+ ok = 0;
+ }
+
+ if (sin->sin_addr.s_addr == 0 || sin->sin_port == 0) {
+ log_fn(level, LD_NET,
+ "Address for new connection has address/port equal to zero.");
+ ok = 0;
+ }
+ } else {
log_fn(level, LD_NET, "Family of address not as expected: %d vs %d",
sa->sa_family, AF_INET);
ok = 0;
}
- if (sin->sin_addr.s_addr == 0 || sin->sin_port == 0) {
- log_fn(level, LD_NET,
- "Address for new connection has address/port equal to zero.");
- ok = 0;
- }
+
return ok ? 0 : -1;
}
@@ -907,7 +1012,8 @@
int news; /* the new socket */
connection_t *newconn;
/* information about the remote peer when connecting to other routers */
- struct sockaddr_in remote;
+ struct sockaddr_in remote4;
+ struct sockaddr_in6 remote6;
char addrbuf[256];
/* length of the remote address. Must be whatever accept() needs. */
socklen_t remotelen = sizeof(addrbuf);
@@ -917,7 +1023,7 @@
tor_assert((size_t)remotelen >= sizeof(struct sockaddr_in));
memset(addrbuf, 0, sizeof(addrbuf));
- news = accept(conn->s,(struct sockaddr *)&addrbuf,&remotelen);
+ news = accept(conn->s ,(struct sockaddr *)&addrbuf, &remotelen);
if (news < 0) { /* accept() error */
int e = tor_socket_errno(conn->s);
if (ERRNO_IS_ACCEPT_EAGAIN(e)) {
@@ -942,19 +1048,19 @@
if (options->ConstrainedSockets)
set_constrained_socket_buffers(news, (int)options->ConstrainedSockSize);
- if (((struct sockaddr*)addrbuf)->sa_family != conn->socket_family) {
+ if (((struct sockaddr*)addrbuf)->sa_family != conn->addr.family) {
/* This is annoying, but can apparently happen on some Darwins. */
log_info(LD_BUG, "A listener connection returned a socket with a "
"mismatched family. %s for addr_family %d gave us a socket "
"with address family %d. Dropping.",
conn_type_to_string(conn->type),
- (int)conn->socket_family,
+ (int)conn->addr.family,
(int)((struct sockaddr*)addrbuf)->sa_family);
tor_close_socket(news);
return 0;
}
- if (conn->socket_family == AF_INET) {
+ if (conn->addr.family == AF_INET || conn->addr.family == AF_INET6) {
if (check_sockaddr_in((struct sockaddr*)addrbuf, remotelen, LOG_INFO)<0) {
log_info(LD_NET,
"accept() returned a strange address; trying getsockname().");
@@ -973,13 +1079,18 @@
}
}
}
- memcpy(&remote, addrbuf, sizeof(struct sockaddr_in));
+ if (conn->addr.family == AF_INET6) {
+ memcpy(&remote6, addrbuf, sizeof(struct sockaddr_in6));
+ } else {
+ memcpy(&remote4, addrbuf, sizeof(struct sockaddr_in));
+ }
/* process entrance policies here, before we even create the connection */
if (new_type == CONN_TYPE_AP) {
/* check sockspolicy to see if we should accept it */
- if (socks_policy_permits_address(ntohl(remote.sin_addr.s_addr)) == 0) {
- tor_inet_ntoa(&remote.sin_addr, tmpbuf, sizeof(tmpbuf));
+ //TODO: support ipv6
+ if (conn->addr.family == AF_INET && socks_policy_permits_address(ntohl(remote4.sin_addr.s_addr)) == 0) {
+ tor_inet_ntoa(&remote4.sin_addr, tmpbuf, sizeof(tmpbuf));
log_notice(LD_APP,
"Denying socks connection from untrusted address %s.",
tmpbuf);
@@ -989,8 +1100,9 @@
}
if (new_type == CONN_TYPE_DIR) {
/* check dirpolicy to see if we should accept it */
- if (dir_policy_permits_address(ntohl(remote.sin_addr.s_addr)) == 0) {
- tor_inet_ntoa(&remote.sin_addr, tmpbuf, sizeof(tmpbuf));
+ //TODO: support ipv6
+ if (conn->addr.family == AF_INET && dir_policy_permits_address(ntohl(remote4.sin_addr.s_addr)) == 0) {
+ tor_inet_ntoa(&remote4.sin_addr, tmpbuf, sizeof(tmpbuf));
log_notice(LD_DIRSERV,"Denying dir connection from address %s.",
tmpbuf);
tor_close_socket(news);
@@ -998,29 +1110,36 @@
}
}
- newconn = connection_new(new_type, conn->socket_family);
+ newconn = connection_new(new_type, conn->addr.family);
newconn->s = news;
/* remember the remote address */
- newconn->addr = ntohl(remote.sin_addr.s_addr);
- newconn->port = ntohs(remote.sin_port);
- newconn->address = tor_dup_addr(newconn->addr);
+ if (conn->addr.family == AF_INET6) {
+ newconn->addr.addr.in6_addr = remote6.sin6_addr;
+ newconn->port = ntohs(remote6.sin6_port);
+ newconn->address = tor_dup_addr6(newconn->addr.addr.in6_addr);
+ } else {
+ newconn->addr.addr.in_addr.s_addr = remote4.sin_addr.s_addr;
+ newconn->port = ntohs(remote4.sin_port);
+ newconn->address = tor_dup_addr(newconn->addr.addr.in_addr.s_addr);
+ }
+ newconn->addr.family = conn->addr.family;
- } else if (conn->socket_family == AF_UNIX) {
+ } else if (conn->addr.family == AF_UNIX) {
/* For now only control ports can be unix domain sockets
* and listeners at the same time */
tor_assert(conn->type == CONN_TYPE_CONTROL_LISTENER);
- newconn = connection_new(new_type, conn->socket_family);
+ newconn = connection_new(new_type, conn->addr.family);
newconn->s = news;
/* remember the remote address -- do we have anything sane to put here? */
- newconn->addr = 0;
+ newconn->addr.addr.in_addr.s_addr = 0;
newconn->port = 1;
newconn->address = tor_strdup(conn->address);
} else {
tor_assert(0);
- };
+ }
if (connection_add(newconn) < 0) { /* no space, forget it */
connection_free(newconn);
@@ -1072,7 +1191,8 @@
return 0;
}
-/** Take conn, make a nonblocking socket; try to connect to
+/** (called by connection_connect)
+ * Take conn, make a nonblocking socket; try to connect to
* addr:port (they arrive in *host order*). If fail, return -1. Else
* assign s to conn-\>s: if connected return 1, if EAGAIN return 0.
*
@@ -1081,7 +1201,7 @@
* On success, add conn to the list of polled connections.
*/
int
-connection_connect(connection_t *conn, const char *address,
+connection_connect4(connection_t *conn, const char *address,
uint32_t addr, uint16_t port)
{
int s, inprogress = 0;
@@ -1162,6 +1282,113 @@
return inprogress ? 0 : 1;
}
+/** (called by connection_connect)
+ * Take conn, make a nonblocking socket; try to connect to
+ * addr:port (they arrive in *host order*). If fail, return -1. Else
+ * assign s to conn-\>s: if connected return 1, if EAGAIN return 0.
+ *
+ * address is used to make the logs useful.
+ *
+ * On success, add conn to the list of polled connections.
+ */
+int
+connection_connect6(connection_t *conn, const char *address,
+ struct in6_addr addr6, uint16_t port)
+{
+ int s, inprogress = 0;
+ struct sockaddr_in6 dest_addr6;
+ or_options_t *options = get_options();
+
+ if (get_n_open_sockets() >= get_options()->_ConnLimit-1) {
+ int n_conns = get_n_open_sockets();
+ log_warn(LD_NET,"Failing because we have %d connections already. Please "
+ "raise your ulimit -n.", n_conns);
+ control_event_general_status(LOG_WARN, "TOO_MANY_CONNECTIONS CURRENT=%d",
+ n_conns);
+ return -1;
+ }
+
+ s = tor_open_socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ if (s < 0) {
+ log_warn(LD_NET,"Error creating network socket: %s",
+ tor_socket_strerror(tor_socket_errno(-1)));
+ return -1;
+ }
+
+ if (options->OutboundBindAddress) {
+ struct sockaddr_in6 ext_addr6;
+
+ memset(&ext_addr6, 0, sizeof(ext_addr6));
+ ext_addr6.sin6_family = AF_INET6;
+ ext_addr6.sin6_port = 0;
+ if (!tor_inet_aton6(options->OutboundBindAddress, &ext_addr6.sin6_addr)) {
+ log_warn(LD_CONFIG,"Outbound ipv6 bind address '%s' didn't parse. Ignoring.",
+ options->OutboundBindAddress);
+ } else {
+ if (bind(s, (struct sockaddr*)&ext_addr6, sizeof(ext_addr6)) < 0) {
+ log_warn(LD_NET,"Error binding network ipv6 socket: %s",
+ tor_socket_strerror(tor_socket_errno(s)));
+ tor_close_socket(s);
+ return -1;
+ }
+ }
+ }
+
+ set_socket_nonblocking(s);
+
+ if (options->ConstrainedSockets)
+ set_constrained_socket_buffers(s, (int)options->ConstrainedSockSize);
+
+ memset(&dest_addr6, 0, sizeof(dest_addr6));
+ dest_addr6.sin6_family = AF_INET6;
+ dest_addr6.sin6_port = htons(port);
+ dest_addr6.sin6_addr = addr6;
+
+ log_debug(LD_NET, "Connecting to ipv6 %s:%u.", escaped_safe_str(address), port);
+
+ if (connect(s, (struct sockaddr *)&dest_addr6, sizeof(dest_addr6)) < 0) {
+ int e = tor_socket_errno(s);
+ if (!ERRNO_IS_CONN_EINPROGRESS(e)) {
+ /* yuck. kill it. */
+ log_info(LD_NET,
+ "connect() to ipv6 %s:%u failed: %s", escaped_safe_str(address),
+ port, tor_socket_strerror(e));
+ tor_close_socket(s);
+ return -1;
+ } else {
+ inprogress = 1;
+ }
+ }
+
+ if (!server_mode(options))
+ client_check_address_changed(s);
+
+ /* it succeeded. we're connected. */
+ log_fn(inprogress?LOG_DEBUG:LOG_INFO, LD_NET,
+ "Connection to ipv6 %s:%u %s (sock %d).", escaped_safe_str(address),
+ port, inprogress?"in progress":"established", s);
+ conn->s = s;
+ if (connection_add(conn) < 0) /* no space, forget it */
+ return -1;
+ return inprogress ? 0 : 1;
+}
+/** Take conn, make a nonblocking socket; try to connect to
+ * addr:port (they arrive in *host order*). If fail, return -1. Else
+ * assign s to conn-\>s: if connected return 1, if EAGAIN return 0.
+ *
+ * address is used to make the logs useful.
+ *
+ * On success, add conn to the list of polled connections.
+ */
+int
+connection_connect(connection_t *conn, const char *address,
+ struct tor_addr_t addr, uint16_t port)
+{
+ if (addr.family == AF_INET)
+ return connection_connect4(conn, address, addr.addr.in_addr.s_addr, port);
+ return connection_connect6(conn, address, addr.addr.in6_addr, port);
+}
+
/**
* Launch any configured listener connections of type <b>type</b>. (A
* listener is configured if <b>port_option</b> is non-zero. If any
@@ -1191,7 +1418,7 @@
connection_t *conn;
config_line_t *line;
- tor_assert(socket_family == AF_INET || socket_family == AF_UNIX);
+ tor_assert(socket_family == AF_INET || socket_family == AF_INET6 || socket_family == AF_UNIX);
if (cfg && port_option) {
for (c = cfg; c; c = c->next) {
@@ -1214,7 +1441,7 @@
SMARTLIST_FOREACH(conns, connection_t *, conn,
{
if (conn->type != type ||
- conn->socket_family != socket_family ||
+ conn->addr.family != socket_family ||
conn->marked_for_close)
continue;
/* Okay, so this is a listener. Is it configured? */
@@ -1224,6 +1451,19 @@
char *address=NULL;
uint16_t port;
switch (socket_family) {
+ case AF_INET6:
+ if (!parse_addr6_port(LOG_WARN,
+ wanted->value, &address, NULL, &port)) {
+ int addr_matches = !strcasecmp(address, conn->address);
+ tor_free(address);
+ if (! port)
+ port = port_option;
+ if (port == conn->port && addr_matches) {
+ line = wanted;
+ break;
+ }
+ }
+ break;
case AF_INET:
if (!parse_addr_port(LOG_WARN,
wanted->value, &address, NULL, &port)) {
@@ -1276,6 +1516,12 @@
struct sockaddr *listensockaddr;
switch (socket_family) {
+ case AF_INET6:
+ listensockaddr = (struct sockaddr *)
+ create_inet6_sockaddr(cfg_line->value,
+ (uint16_t) port_option,
+ &address);
+ break;
case AF_INET:
listensockaddr = (struct sockaddr *)
create_inet_sockaddr(cfg_line->value,
@@ -1343,7 +1589,12 @@
options->SocksPort, "127.0.0.1",
replaced_conns, new_conns, 0,
AF_INET)<0)
- return -1;
+ // maybe the user deliberately configured an ipv6-address to listen on
+ if (retry_listeners(CONN_TYPE_AP_LISTENER, options->SocksListenAddress,
+ options->SocksPort, "::1",
+ replaced_conns, new_conns, 0,
+ AF_INET6)<0)
+ return -1;
if (retry_listeners(CONN_TYPE_AP_TRANS_LISTENER, options->TransListenAddress,
options->TransPort, "127.0.0.1",
replaced_conns, new_conns, 0,
@@ -1381,7 +1632,7 @@
static int
connection_is_rate_limited(connection_t *conn)
{
- if (conn->linked || is_internal_IP(conn->addr, 0))
+ if (conn->linked || (conn->addr.family == AF_INET && is_internal_IP(conn->addr.addr.in_addr.s_addr, 0)))
return 0;
else
return 1;
@@ -2331,7 +2582,8 @@
SMARTLIST_FOREACH(conns, connection_t *, conn,
{
if (conn->type == CONN_TYPE_OR &&
- conn->addr == addr &&
+ conn->addr.family == AF_INET &&
+ conn->addr.addr.in_addr.s_addr == addr &&
conn->port == port &&
!conn->marked_for_close &&
(!best || best->_base.timestamp_created < conn->timestamp_created))
@@ -2351,7 +2603,8 @@
SMARTLIST_FOREACH(conns, connection_t *, conn,
{
if (conn->type == type &&
- conn->addr == addr &&
+ conn->addr.family == AF_INET &&
+ conn->addr.addr.in_addr.s_addr == addr &&
conn->port == port &&
conn->purpose == purpose &&
!conn->marked_for_close)
Index: or/rendcommon.c
===================================================================
--- or/rendcommon.c
+++ or/rendcommon.c
@@ -227,7 +227,11 @@
goto done;
}
/* Assemble everything for this introduction point. */
- address = tor_dup_addr(info->addr);
+ if (info->addr.family == AF_INET6) {
+ address = tor_dup_addr6(info->addr.addr.in6_addr);
+ } else {
+ address = tor_dup_addr(info->addr.addr.in_addr.s_addr);
+ }
res = tor_snprintf(unenc + unenc_written, unenc_len - unenc_written,
"introduction-point %s\n"
"ip-address %s\n"
@@ -760,8 +764,11 @@
{
char key[REND_SERVICE_ID_LEN_BASE32+2]; /* <version><query>\0 */
tor_assert(rend_cache);
- if (!rend_valid_service_id(query))
+ if (!rend_valid_service_id(query)) {
+ log_warn(LD_REND, "hidden service descriptor '%s.onion' ID is not legal.",
+ query);
return -1;
+ }
*e = NULL;
if (version != 0) {
tor_snprintf(key, sizeof(key), "2%s", query);
@@ -771,8 +778,13 @@
tor_snprintf(key, sizeof(key), "0%s", query);
*e = strmap_get_lc(rend_cache, key);
}
- if (!*e)
+ if (!*e) {
+ log_warn(LD_REND, "no cached rend_cache_entry_t for hidden service '%s.onion' with version %i.",
+ query,version);
return 0;
+ }
+ log_warn(LD_REND, "we have a cached rend_cache_entry_t for hidden service '%s.onion' with version %i.",
+ query, version);
return 1;
}
Index: or/directory.c
===================================================================
--- or/directory.c
+++ or/directory.c
@@ -478,7 +478,7 @@
routerinfo_t *me = router_get_my_routerinfo();
if (me &&
router_digest_is_me(conn->identity_digest) &&
- me->addr == conn->_base.addr &&
+ me->addr == conn->_base.addr.addr.in_addr.s_addr && //TODO: support directories on IPv6
me->dir_port == conn->_base.port)
return 1;
}
@@ -644,7 +644,8 @@
conn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR, AF_INET));
/* set up conn so it's got all the data we need to remember */
- conn->_base.addr = addr;
+ conn->_base.addr.family = AF_INET;
+ conn->_base.addr.addr.in_addr.s_addr = addr;
conn->_base.port = use_begindir ? or_port : dir_port;
conn->_base.address = tor_strdup(address);
memcpy(conn->identity_digest, digest, DIGEST_LEN);
@@ -666,7 +667,10 @@
dir_port = options->HttpProxyPort;
}
- switch (connection_connect(TO_CONN(conn), conn->_base.address, addr,
+ struct tor_addr_t connectaddr;
+ connectaddr.family = AF_INET;
+ connectaddr.addr.in_addr.s_addr = addr;
+ switch (connection_connect(TO_CONN(conn), conn->_base.address, connectaddr,
dir_port)) {
case -1:
connection_dir_request_failed(conn); /* retry if we want */
@@ -1948,7 +1952,7 @@
tor_snprintf(cp, sizeof(tmp)-(cp-tmp), "Content-Type: %s\r\n", type);
cp += strlen(cp);
}
- if (!is_internal_IP(conn->_base.addr, 0)) {
+ if (conn->_base.addr.family == AF_INET && !is_internal_IP(conn->_base.addr.addr.in_addr.s_addr, 0)) { //TODO: support ipv6
/* Don't report the source address for a localhost/private connection. */
tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
X_ADDRESS_HEADER "%s\r\n", conn->_base.address);
@@ -3130,7 +3134,7 @@
/* Determine responsible dirs. */
if (hid_serv_get_responsible_directories(responsible_dirs, desc_id) < 0) {
log_warn(LD_REND, "Could not determine the responsible hidden service "
- "directories to post descriptors to.");
+ "directories to post descriptors to. desc_id=%s", desc_id);
smartlist_free(responsible_dirs);
return;
}
@@ -3178,7 +3182,7 @@
if (hid_serv_get_responsible_directories(responsible_dirs, desc_id) < 0) {
/* XXX020 make this louder once we have some v2hidservs */
log_info(LD_REND, "Could not determine the responsible hidden service "
- "directories to fetch descriptors.");
+ "directories to fetch descriptors. desc_id=%s", desc_id);
smartlist_free(responsible_dirs);
return;
}
Index: or/routerparse.c
===================================================================
--- or/routerparse.c
+++ or/routerparse.c
@@ -3376,7 +3376,6 @@
int i;
directory_token_t *tok;
extend_info_t *info;
- struct in_addr ip;
int result;
tor_assert(parsed);
tor_assert(intro_points_encrypted);
@@ -3449,12 +3448,22 @@
info->identity_digest, DIGEST_LEN);
/* Parse IP address. */
tok = find_first_by_keyword(tokens, R_IPO_IP_ADDRESS);
- if (tor_inet_aton(tok->args[0], &ip) == 0) {
- log_warn(LD_REND, "Could not parse IP address.");
- tor_free(info);
- goto err;
+ struct tor_addr_t ip;
+ if (tor_inet_aton(tok->args[0], &(ip.addr.in_addr)) == 0) {
+ if (tor_inet_aton6(tok->args[0], &(ip.addr.in6_addr)) == 0) {
+ log_warn(LD_REND, "Could not parse IP address (tried IPv4 and IPv6).");
+ tor_free(info);
+ goto err;
+ } else {
+ // it's an IPv6-address
+ info->addr.family = AF_INET6;
+ info->addr = ip;
+ }
+ } else {
+ // it's an IPv4-address
+ info->addr.family = AF_INET;
+ info->addr.addr.in_addr.s_addr = ntohl(ip.addr.in_addr.s_addr);
}
- info->addr = ntohl(ip.s_addr);
/* Parse onion port. */
tok = find_first_by_keyword(tokens, R_IPO_ONION_PORT);
info->port = (uint16_t) atoi(tok->args[0]);
Index: or/command.c
===================================================================
--- or/command.c
+++ or/command.c
@@ -554,7 +554,7 @@
}
if (other_addr_type == RESOLVED_TYPE_IPV4 && other_addr_len == 4) {
uint32_t addr = ntohl(get_uint32(cp));
- if (addr == conn->real_addr) {
+ if (conn->real_addr.family == AF_INET && addr == conn->real_addr.addr.in_addr.s_addr) {
conn->handshake_state->apparently_canonical = 1;
break;
}
Index: or/test.c
===================================================================
--- or/test.c
+++ or/test.c
@@ -3311,7 +3311,8 @@
info->nickname[0] = '$';
base16_encode(info->nickname + 1, sizeof(info->nickname) - 1,
info->identity_digest, DIGEST_LEN);
- info->addr = crypto_rand_int(65536); /* Does not cover all IP addresses. */
+ info->addr.family = AF_INET;
+ info->addr.addr.in_addr.s_addr = crypto_rand_int(65536); /* Does not cover all IP addresses. */
info->port = crypto_rand_int(65536);
generated->intro_points[i] = tor_strdup(info->nickname);
generated->intro_point_extend_info[i] = info;
@@ -3346,7 +3347,7 @@
DIGEST_LEN);
test_streq(gen_info->nickname, par_info->nickname);
test_streq(generated->intro_points[i], parsed->intro_points[i]);
- test_eq(gen_info->addr, par_info->addr);
+ test_eq(gen_info->addr.addr.in_addr.s_addr, par_info->addr.addr.in_addr.s_addr);
test_eq(gen_info->port, par_info->port);
}
tor_free(intro_points_encrypted);
Index: or/circuituse.c
===================================================================
--- or/circuituse.c
+++ or/circuituse.c
@@ -1261,7 +1261,7 @@
conn_age = time(NULL) - conn->_base.timestamp_created;
if (conn_age >= get_options()->SocksTimeout) {
- int severity = (!conn->_base.addr && !conn->_base.port) ?
+ int severity = ((conn->_base.addr.family == AF_INET && !conn->_base.addr.addr.in_addr.s_addr) && !conn->_base.port) ?
LOG_INFO : LOG_NOTICE;
log_fn(severity, LD_APP,
"Tried for %d seconds to get a connection to %s:%d. Giving up.",
Index: or/router.c
===================================================================
--- or/router.c
+++ or/router.c
@@ -1049,11 +1049,13 @@
/* make sure it's resolved to something. this way we can't get a
'maybe' below. */
- if (!conn->_base.addr)
+ if (conn->_base.addr.family == AF_INET && !conn->_base.addr.addr.in_addr.s_addr)
return -1;
- return compare_addr_to_addr_policy(conn->_base.addr, conn->_base.port,
- desc_routerinfo->exit_policy) != ADDR_POLICY_ACCEPTED;
+ if (conn->_base.addr.family == AF_INET)
+ return compare_addr_to_addr_policy(conn->_base.addr.addr.in_addr.s_addr, conn->_base.port,
+ desc_routerinfo->exit_policy) != ADDR_POLICY_ACCEPTED;
+ return 0; //TODO: support an ipv6 exit-policy
}
/** Return true iff I'm a server and <b>digest</b> is equal to
@@ -1128,13 +1130,13 @@
* declaration verbatim rather than as digests. */
static smartlist_t *warned_nonexistent_family = NULL;
-static int router_guess_address_from_dir_headers(uint32_t *guess);
+static int router_guess_address_from_dir_headers(struct tor_addr_t *guess);
/** Return our current best guess at our address, either because
* it's configured in torrc, or because we've learned it from
* dirserver headers. */
int
-router_pick_published_address(or_options_t *options, uint32_t *addr)
+router_pick_published_address(or_options_t *options, struct tor_addr_t *addr)
{
if (resolve_my_address(LOG_INFO, options, addr, NULL) < 0) {
log_info(LD_CONFIG, "Could not determine our address locally. "
@@ -1157,7 +1159,7 @@
{
routerinfo_t *ri;
extrainfo_t *ei;
- uint32_t addr;
+ tor_addr_t addr;
char platform[256];
int hibernating = we_are_hibernating();
or_options_t *options = get_options();
@@ -1175,9 +1177,9 @@
ri = tor_malloc_zero(sizeof(routerinfo_t));
ri->cache_info.routerlist_index = -1;
- ri->address = tor_dup_addr(addr);
+ ri->address = tor_dup_addr(addr.addr.in_addr.s_addr);
ri->nickname = tor_strdup(options->Nickname);
- ri->addr = addr;
+ ri->addr = addr.addr.in_addr.s_addr;
ri->or_port = options->ORPort;
ri->dir_port = options->DirPort;
ri->cache_info.published_on = time(NULL);
@@ -1361,20 +1363,20 @@
/** Note at log level severity that our best guess of address has changed from
* <b>prev</b> to <b>cur</b>. */
static void
-log_addr_has_changed(int severity, uint32_t prev, uint32_t cur)
+log_addr_has_changed(int severity, struct tor_addr_t prev, struct tor_addr_t cur)
{
char addrbuf_prev[INET_NTOA_BUF_LEN];
char addrbuf_cur[INET_NTOA_BUF_LEN];
struct in_addr in_prev;
struct in_addr in_cur;
- in_prev.s_addr = htonl(prev);
+ in_prev.s_addr = htonl(prev.addr.in_addr.s_addr);
tor_inet_ntoa(&in_prev, addrbuf_prev, sizeof(addrbuf_prev));
- in_cur.s_addr = htonl(cur);
+ in_cur.s_addr = htonl(cur.addr.in_addr.s_addr);
tor_inet_ntoa(&in_cur, addrbuf_cur, sizeof(addrbuf_cur));
- if (prev)
+ if (prev.addr.in_addr.s_addr)
log_fn(severity, LD_GENERAL,
"Our IP Address has changed from %s to %s; "
"rebuilding descriptor.",
@@ -1391,20 +1393,21 @@
void
check_descriptor_ipaddress_changed(time_t now)
{
- uint32_t prev, cur;
+ struct tor_addr_t prev, cur;
or_options_t *options = get_options();
(void) now;
if (!desc_routerinfo)
return;
- prev = desc_routerinfo->addr;
+ prev.family = AF_INET;
+ prev.addr.in_addr.s_addr = desc_routerinfo->addr;
if (resolve_my_address(LOG_INFO, options, &cur, NULL) < 0) {
log_info(LD_CONFIG,"options->Address didn't resolve into an IP.");
return;
}
- if (prev != cur) {
+ if (compare_addr(prev, cur) != 0) {
log_addr_has_changed(LOG_INFO, prev, cur);
ip_address_changed(0);
}
@@ -1420,7 +1423,11 @@
void
router_new_address_suggestion(const char *suggestion)
{
- uint32_t addr, cur = 0;
+ tor_addr_t addr, cur;
+ addr.family = AF_INET;
+ cur.family = AF_INET;
+ addr.addr.in_addr.s_addr = 0;
+ cur.addr.in_addr.s_addr = 0;
struct in_addr in;
or_options_t *options = get_options();
@@ -1430,21 +1437,22 @@
escaped(suggestion));
return;
}
- addr = ntohl(in.s_addr);
+ addr.family = AF_INET;
+ addr.addr.in_addr.s_addr = ntohl(in.s_addr);
log_debug(LD_DIR, "Got X-Your-Address-Is: %s.", suggestion);
if (!server_mode(options)) {
- last_guessed_ip = addr; /* store it in case we need it later */
+ last_guessed_ip = addr.addr.in_addr.s_addr; /* store it in case we need it later */
return;
}
if (resolve_my_address(LOG_INFO, options, &cur, NULL) >= 0) {
/* We're all set -- we already know our address. Great. */
- last_guessed_ip = cur; /* store it in case we need it later */
+ last_guessed_ip = cur.addr.in_addr.s_addr; /* store it in case we need it later */
return;
}
- if (is_internal_IP(addr, 0)) {
+ if (is_internal_IP(addr.addr.in_addr.s_addr, 0)) {
/* Don't believe anybody who says our IP is, say, 127.0.0.1. */
return;
}
@@ -1452,13 +1460,16 @@
/* Okay. We can't resolve our own address, and X-Your-Address-Is is giving
* us an answer different from what we had the last time we managed to
* resolve it. */
- if (last_guessed_ip != addr) {
+ if (last_guessed_ip != addr.addr.in_addr.s_addr) {
control_event_server_status(LOG_NOTICE,
"EXTERNAL_ADDRESS ADDRESS=%s METHOD=DIRSERV",
suggestion);
- log_addr_has_changed(LOG_NOTICE, last_guessed_ip, addr);
+ struct tor_addr_t last;
+ last.family = AF_INET;
+ last.addr.in_addr.s_addr = last_guessed_ip;
+ log_addr_has_changed(LOG_NOTICE, last, addr);
ip_address_changed(0);
- last_guessed_ip = addr; /* router_rebuild_descriptor() will fetch it */
+ last_guessed_ip = addr.addr.in_addr.s_addr; /* router_rebuild_descriptor() will fetch it */
}
}
@@ -1467,10 +1478,11 @@
* about our address based on directory headers, answer it and return
* 0; else return -1. */
static int
-router_guess_address_from_dir_headers(uint32_t *guess)
+router_guess_address_from_dir_headers(struct tor_addr_t *guess)
{
if (last_guessed_ip) {
- *guess = last_guessed_ip;
+ guess->family = AF_INET;
+ guess->addr.in_addr.s_addr = last_guessed_ip;
return 0;
}
return -1;
Index: or/cpuworker.c
===================================================================
--- or/cpuworker.c
+++ or/cpuworker.c
@@ -468,7 +468,11 @@
log_info(LD_OR,"circ->p_conn gone. Failing circ.");
return -1;
}
- tag_pack(tag, circ->p_conn->_base.addr, circ->p_conn->_base.port,
+ if (circ->p_conn->_base.addr.family == AF_INET6) {
+ log_info(LD_OR,"we do not support ipv6 in assign_to_cpuworker().");
+ return -1;
+ }
+ tag_pack(tag, circ->p_conn->_base.addr.addr.in_addr.s_addr, circ->p_conn->_base.port,
circ->p_circ_id);
cpuworker->state = CPUWORKER_STATE_BUSY_ONION;
Index: or/circuitbuild.c
===================================================================
--- or/circuitbuild.c
+++ or/circuitbuild.c
@@ -350,7 +350,11 @@
tor_assert(firsthop->extend_info);
/* now see if we're already connected to the first OR in 'route' */
- in.s_addr = htonl(firsthop->extend_info->addr);
+ if (firsthop->extend_info->addr.family == AF_INET6) {
+ log_info(LD_CIRC,"we do not support Ipv6 for firsthop yet. Closing.");
+ return -END_CIRC_REASON_CONNECTFAILED;
+ }
+ in.s_addr = htonl(firsthop->extend_info->addr.addr.in_addr.s_addr);
tor_inet_ntoa(&in, tmpbuf, sizeof(tmpbuf));
log_debug(LD_CIRC,"Looking for firsthop '%s:%u'",tmpbuf,
firsthop->extend_info->port);
@@ -367,8 +371,8 @@
router_digest_version_as_new_as(firsthop->extend_info->identity_digest,
"0.1.1.9-alpha-cvs"))) {
/* not currently connected */
- circ->_base.n_addr = firsthop->extend_info->addr;
- circ->_base.n_port = firsthop->extend_info->port;
+ circ->_base.n_addr = firsthop->extend_info->addr;
+ circ->_base.n_port = firsthop->extend_info->port;
if (!n_conn || n_conn->_base.or_is_obsolete) { /* launch the connection */
n_conn = connection_or_connect(firsthop->extend_info->addr,
@@ -399,6 +403,26 @@
return 0;
}
+/** compare the 2 given ipv4 or ipv6-addresses
+ *
+ * returns 0 if they are equal.
+ */
+int compare_addr(struct tor_addr_t a, struct tor_addr_t b) {
+
+ if (a.family != b.family)
+ return 1;
+
+ if (a.family == AF_INET)
+ return a.addr.in_addr.s_addr == b.addr.in_addr.s_addr;
+
+ int i;
+ for (i=0; i<16; i++) {
+ if (a.addr.in6_addr.s6_addr[i] != b.addr.in6_addr.s6_addr[i])
+ return 1;
+ }
+ return 0;
+}
+
/** Find any circuits that are waiting on <b>or_conn</b> to become
* open and get them to send their create cells forward.
*
@@ -426,7 +450,7 @@
continue;
if (tor_digest_is_zero(circ->n_conn_id_digest)) {
/* Look at addr/port. This is an unkeyed connection. */
- if (circ->n_addr != or_conn->_base.addr ||
+ if ((compare_addr(circ->n_addr, or_conn->_base.addr) != 0) ||
circ->n_port != or_conn->_base.port)
continue;
/* now teach circ the right identity_digest */
@@ -654,7 +678,12 @@
return 0;
}
- set_uint32(payload, htonl(hop->extend_info->addr));
+ if (hop->extend_info->addr.family == AF_INET6) {
+ log(LOG_NOTICE, LD_GENERAL,
+ "circuit_send_next_onion_skin() - we do not support ipv6 for next hops yet. Ignoring.");
+ return 0;
+ }
+ set_uint32(payload, htonl(hop->extend_info->addr.addr.in_addr.s_addr));
set_uint16(payload+4, htons(hop->extend_info->port));
onionskin = payload+2+4;
@@ -735,7 +764,8 @@
return -1;
}
- circ->n_addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE));
+ circ->n_addr.family = AF_INET;
+ circ->n_addr.addr.in_addr.s_addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE));
circ->n_port = ntohs(get_uint16(cell->payload+RELAY_HEADER_SIZE+4));
onionskin = cell->payload+RELAY_HEADER_SIZE+4+2;
@@ -750,7 +780,11 @@
router_digest_version_as_new_as(id_digest,"0.1.1.9-alpha-cvs"))) {
struct in_addr in;
char tmpbuf[INET_NTOA_BUF_LEN];
- in.s_addr = htonl(circ->n_addr);
+ if (circ->n_addr.family == AF_INET6) {
+ log_info(LD_CIRC|LD_OR, "Next router is on an ipv6-address. we do not support this yet.");
+ return 0;
+ }
+ in.s_addr = htonl(circ->n_addr.addr.in_addr.s_addr);
tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
log_info(LD_CIRC|LD_OR,"Next router (%s:%d) not connected. Connecting.",
tmpbuf, circ->n_port);
@@ -767,6 +801,11 @@
circ->n_port = n_conn->_base.port;
} else {
/* we should try to open a connection */
+ if (circ->n_addr.family == AF_INET6) {
+ log_info(LD_CIRC,"Cannot launch n_conn because we do not support ipv6 between nodes yet. Closing circuit.");
+ circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED);
+ return 0;
+ }
n_conn = connection_or_connect(circ->n_addr, circ->n_port, id_digest);
if (!n_conn) {
log_info(LD_CIRC,"Launching n_conn failed. Closing circuit.");
@@ -1010,7 +1049,16 @@
circ->p_conn, &cell, CELL_DIRECTION_IN);
log_debug(LD_CIRC,"Finished sending 'created' cell.");
- if (!is_local_IP(circ->p_conn->_base.addr) &&
+ if (circ->p_conn->_base.addr.family == AF_INET6) {
+ log_debug(LD_CIRC,"not checking is_local_IP because we do not support ipv6 yet.");
+ if(connection_or_nonopen_was_started_here(circ->p_conn)) {
+ /* record that we could process create cells from a non-local conn
+ * that we didn't initiate; presumably this means that create cells
+ * can reach us too. */
+ router_orport_found_reachable();
+ }
+ } else
+ if (!is_local_IP(circ->p_conn->_base.addr.addr.in_addr.s_addr) &&
!connection_or_nonopen_was_started_here(circ->p_conn)) {
/* record that we could process create cells from a non-local conn
* that we didn't initiate; presumably this means that create cells
@@ -1751,7 +1799,8 @@
strlcpy(info->nickname, nickname, sizeof(info->nickname));
if (onion_key)
info->onion_key = crypto_pk_dup_key(onion_key);
- info->addr = addr;
+ info->addr.family = AF_INET;
+ info->addr.addr.in_addr.s_addr = addr;
info->port = port;
return info;
}
Index: or/dnsserv.c
===================================================================
--- or/dnsserv.c
+++ or/dnsserv.c
@@ -116,9 +116,10 @@
conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT;
conn->is_dns_request = 1;
- TO_CONN(conn)->addr = ntohl(sin->sin_addr.s_addr);
+ TO_CONN(conn)->addr.family = AF_INET;
+ TO_CONN(conn)->addr.addr.in_addr.s_addr = ntohl(sin->sin_addr.s_addr);
TO_CONN(conn)->port = ntohs(sin->sin_port);
- TO_CONN(conn)->address = tor_dup_addr(TO_CONN(conn)->addr);
+ TO_CONN(conn)->address = tor_dup_addr(TO_CONN(conn)->addr.addr.in_addr.s_addr);
if (q->type == EVDNS_TYPE_A)
conn->socks_request->command = SOCKS_COMMAND_RESOLVE;
Index: or/rendclient.c
===================================================================
--- or/rendclient.c
+++ or/rendclient.c
@@ -117,10 +117,14 @@
if (entry->parsed->protocols & (1<<2)) {
/* version 2 format */
extend_info_t *extend_info = rendcirc->build_state->chosen_exit;
+ if (extend_info->addr.family == AF_INET6) {
+ log_warn(LD_BUG, "we do not support ipv6 in rend_client_send_introduction");
+ goto err;
+ }
int klen;
tmp[0] = 2; /* version 2 of the cell format */
/* nul pads */
- set_uint32(tmp+1, htonl(extend_info->addr));
+ set_uint32(tmp+1, htonl(extend_info->addr.addr.in_addr.s_addr));
set_uint16(tmp+5, htons(extend_info->port));
memcpy(tmp+7, extend_info->identity_digest, DIGEST_LEN);
klen = crypto_pk_asn1_encode(extend_info->onion_key, tmp+7+DIGEST_LEN+2,
@@ -505,7 +509,7 @@
entry->parsed->n_intro_points > 0) {
/* either this fetch worked, or it failed but there was a
* valid entry from before which we should reuse */
- log_info(LD_REND,"Rend desc is usable. Launching circuits.");
+ log_info(LD_REND,"Rend desc for hidden service '%s.onion' is usable. Launching circuits.", safe_str(query));
conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
/* restart their timeout values, so they get a fair shake at
@@ -516,12 +520,12 @@
if (connection_ap_handshake_attach_circuit(conn) < 0) {
/* it will never work */
- log_warn(LD_REND,"Rendezvous attempt failed. Closing.");
+ log_warn(LD_REND,"Rendezvous attempt for hidden service '%s.onion' failed. Closing.", safe_str(query));
connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
}
} else { /* 404, or fetch didn't get that far */
log_notice(LD_REND,"Closing stream for '%s.onion': hidden service is "
- "unavailable (try again later).", safe_str(query));
+ "unavailable (try again later). entry->parsed->n_intro_points=%i", safe_str(query), entry->parsed->n_intro_points);
connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED);
}
});
Index: common/util.c
===================================================================
--- common/util.c
+++ common/util.c
@@ -2223,13 +2223,13 @@
_address = tor_strndup(addrport, colon-addrport);
_port = (int) tor_parse_long(colon+1,10,1,65535,NULL,NULL);
if (!_port) {
- log_fn(severity, LD_GENERAL, "Port %s out of range", escaped(colon+1));
+ log_fn(severity, LD_GENERAL, "ipv4-Port %s out of range", escaped(colon+1));
ok = 0;
}
if (!port_out) {
char *esc_addrport = esc_for_log(addrport);
log_fn(severity, LD_GENERAL,
- "Port %s given on %s when not required",
+ "ipv4-Port %s given on %s when not required",
escaped(colon+1), esc_addrport);
tor_free(esc_addrport);
ok = 0;
@@ -2241,10 +2241,13 @@
if (addr) {
/* There's an addr pointer, so we need to resolve the hostname. */
- if (tor_lookup_hostname(_address,addr)) {
- log_fn(severity, LD_NET, "Couldn't look up %s", escaped(_address));
+ struct tor_addr_t resolv;
+ if (tor_addr_lookup(_address, AF_INET, &resolv)) {
+ log_fn(severity, LD_NET, "Couldn't look up ipv4 %s", escaped(_address));
ok = 0;
*addr = 0;
+ } else {
+ *addr = resolv.addr.in_addr.s_addr;
}
}
@@ -2260,7 +2263,84 @@
return ok ? 0 : -1;
}
+/** Parse a string of the form "[host]" and "[host]:port" from <b>addrport</b>. If
+ * <b>address</b> is provided, set *<b>address</b> to a copy of the
+ * host portion of the string. If <b>addr</b> is provided, try to
+ * resolve the host portion of the string and store it into
+ * *<b>addr</b>. If <b>port_out</b> is provided,
+ * store the port number into *<b>port_out</b>, or 0 if no port is given.
+ * If <b>port_out</b> is NULL, then there must be no port number in
+ * <b>addrport</b>.
+ * Return 0 on success, -1 on failure.
+ */
+int
+parse_addr6_port(int severity, const char *addrport, char **address,
+ struct in6_addr *addr, uint16_t *port_out)
+{
+ const char *colon;
+ char *_address = NULL;
+ int _port;
+ int ok = 1;
+ tor_assert(addrport);
+
+ colon = strstr(addrport, "]:");
+ if (colon) {
+ _address = tor_strndup(addrport, colon - addrport);
+ _port = (int) tor_parse_long(colon + 2, 10, 1, 65535, NULL, NULL);
+ log_fn(severity, LD_NET, "DEBUG ipv6 incl [ and ] is: %s port is %i", escaped(_address), _port);
+ if (!_port) {
+ log_fn(severity, LD_GENERAL, "ipv6-Port %s out of range", escaped(colon+1));
+ ok = 0;
+ }
+ if (!port_out) {
+ char *esc_addrport = esc_for_log(addrport);
+ log_fn(severity, LD_GENERAL,
+ "ipv6-Port %s given on %s when not required",
+ escaped(colon+1), esc_addrport);
+ tor_free(esc_addrport);
+ ok = 0;
+ }
+ } else {
+ _address = tor_strdup(addrport);
+ _port = 0;
+ log_fn(severity, LD_NET, "DEBUG ipv6 incl [ and ] is: %s port is default", escaped(_address));
+ }
+ log_fn(severity, LD_NET, "DEBUG ipv6 incl [ and ] is: %s", escaped(_address));
+ const char *end = strstr(_address, "]");
+ if (end)
+ _address = tor_strndup(_address, end - _address);
+ log_fn(severity, LD_NET, "DEBUG ipv6 incl [ is: %s", escaped(_address));
+ const char *start = strstr(_address, "[");
+ if (start)
+ _address = (char *) start + 1;
+ log_fn(severity, LD_NET, "DEBUG ipv6 without [ is: %s", escaped(_address));
+
+ if (addr) {
+ /* There's an addr pointer, so we need to resolve the hostname. */
+ struct tor_addr_t resolv;
+ if (tor_addr_lookup(_address, AF_INET6, &resolv)) {
+ log_fn(severity, LD_NET, "Couldn't look up ipv6 %s", escaped(_address));
+ ok = 0;
+ //*addr = 0;
+ } else {
+ *addr = resolv.addr.in6_addr;
+ }
+ }
+
+ if (address && ok) {
+ *address = _address;
+ } else {
+ if (address)
+ *address = NULL;
+//TODO this may me a minor memory-leak of 42 byte once on startup tor_free(_address);
+ }
+ if (port_out)
+ *port_out = ok ? ((uint16_t) _port) : 0;
+
+ return ok ? 0 : -1;
+}
+
/** If <b>mask</b> is an address mask for a bit-prefix, return the number of
* bits. Otherwise, return -1. */
int
@@ -2823,6 +2903,18 @@
return -1; /* unknown address family, return unequal? */
}
+/** Given an <b>addr</b>, call tor_inet_ntop() on it
+ * and return a strdup of the resulting address.
+ */
+char *
+tor_dup_addr6(struct in6_addr addr)
+{
+ char buf[42];
+
+ tor_inet_ntop(AF_INET6, &addr, buf, sizeof(buf));
+ return tor_strdup(buf);
+}
+
/** Given a host-order <b>addr</b>, call tor_inet_ntop() on it
* and return a strdup of the resulting address.
*/
Index: common/util.h
===================================================================
--- common/util.h
+++ common/util.h
@@ -271,6 +271,8 @@
int is_internal_IP(uint32_t ip, int for_listening) ATTR_PURE;
int parse_addr_port(int severity, const char *addrport, char **address,
uint32_t *addr, uint16_t *port_out);
+int parse_addr6_port(int severity, const char *addrport, char **address,
+ struct in6_addr *addr, uint16_t *port_out);
int parse_port_range(const char *port, uint16_t *port_min_out,
uint16_t *port_max_out);
int parse_addr_and_port_range(const char *s, uint32_t *addr_out,
@@ -280,6 +282,7 @@
int addr_mask_cmp_bits(uint32_t a1, uint32_t a2, maskbits_t bits);
int tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len);
char *tor_dup_addr(uint32_t addr) ATTR_MALLOC;
+char *tor_dup_addr6(struct in6_addr addr) ATTR_MALLOC;
int get_interface_address(int severity, uint32_t *addr);
int get_interface_address6(int severity, sa_family_t family, tor_addr_t *addr);
Index: common/compat.c
===================================================================
--- common/compat.c
+++ common/compat.c
@@ -834,6 +834,16 @@
* but works on Windows and Solaris.)
*/
int
+tor_inet_aton6(const char *c, struct in6_addr* addr)
+{
+ return tor_inet_pton(AF_INET6, c, addr);
+}
+
+/** Set *addr to the IP address (in dotted-quad notation) stored in c.
+ * Return 1 on success, 0 if c is badly formatted. (Like inet_aton(c,addr),
+ * but works on Windows and Solaris.)
+ */
+int
tor_inet_aton(const char *c, struct in_addr* addr)
{
#ifdef HAVE_INET_ATON
@@ -1051,7 +1061,33 @@
* (This function exists because standard windows gethostbyname
* doesn't treat raw IP addresses properly.)
*/
+/*replaced by tor_addr_lookup
int
+tor_lookup_hostname6(const char *name, struct in6_addr *addr)
+{
+ tor_addr_t myaddr;
+ int ret;
+
+ if ((ret = tor_addr_lookup(name, AF_INET6, &myaddr)))
+ return ret;
+
+ if (IN_FAMILY(&myaddr) == AF_INET6) {
+ *addr = (in6_addr)myaddr.addr;
+ return ret;
+ }
+
+ return -1;
+}
+*/
+/** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
+ * *<b>addr</b> to the proper IP address, in host byte order. Returns 0
+ * on success, -1 on failure; 1 on transient failure.
+ *
+ * (This function exists because standard windows gethostbyname
+ * doesn't treat raw IP addresses properly.)
+ */
+/* replaced by tor_addr_lookup
+int
tor_lookup_hostname(const char *name, uint32_t *addr)
{
tor_addr_t myaddr;
@@ -1067,7 +1103,7 @@
return -1;
}
-
+*/
/** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
* *<b>addr</b> to the proper IP address and family. The <b>family</b>
* argument (which must be AF_INET, AF_INET6, or AF_UNSPEC) declares a
@@ -1086,7 +1122,7 @@
struct in6_addr iaddr6;
tor_assert(name);
tor_assert(addr);
- tor_assert(family == AF_INET || family == AF_UNSPEC);
+ tor_assert(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC);
memset(addr, 0, sizeof(addr)); /* Clear the extraneous fields. */
if (!*name) {
/* Empty address is an error. */
Index: common/compat.h
===================================================================
--- common/compat.h
+++ common/compat.h
@@ -329,11 +329,11 @@
struct in_addr;
typedef struct tor_addr_t
{
- sa_family_t family;
+ sa_family_t family; // AF_INET or AF_INET6 or AF_UNIX
union {
struct in_addr in_addr;
struct in6_addr in6_addr;
- } addr;
+ } addr; // addr is ignored if AF_UNIX
} tor_addr_t;
/* XXXX020 rename these. */
@@ -383,9 +383,11 @@
#define TOR_ADDR_BUF_LEN 46 /* ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255 */
int tor_inet_aton(const char *cp, struct in_addr *addr) ATTR_NONNULL((1,2));
+int tor_inet_aton6(const char *cp, struct in6_addr *addr) ATTR_NONNULL((1,2));
const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len);
int tor_inet_pton(int af, const char *src, void *dst);
int tor_lookup_hostname(const char *name, uint32_t *addr) ATTR_NONNULL((1,2));
+int tor_lookup_hostname6(const char *name, struct in6_addr *addr) ATTR_NONNULL((1,2));
void set_socket_nonblocking(int socket);
int tor_socketpair(int family, int type, int protocol, int fd[2]);
int network_init(void);
Attachment:
signature.asc
Description: OpenPGP digital signature