From 85003f4c80b7c980099fedca7dba0c0a90209084 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 22 Feb 2013 16:10:40 -0500 Subject: [PATCH] Add a new ipv6=address:orport flag to DirAuthority and FallbackDir Resolves # 6027 --- changes/bug6027 | 4 ++++ doc/tor.1.txt | 9 ++++++--- src/or/config.c | 32 +++++++++++++++++++++++++++++++- src/or/or.h | 2 ++ src/or/router.c | 1 + src/or/routerlist.c | 27 ++++++++++++++++++++++++--- src/or/routerlist.h | 2 ++ 7 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 changes/bug6027 diff --git a/changes/bug6027 b/changes/bug6027 new file mode 100644 index 0000000000..5233876a49 --- /dev/null +++ b/changes/bug6027 @@ -0,0 +1,4 @@ + o Minor features: + - Allow users to configure directory authorities and fallback + directory servers with IPv6 addresses and ORPorts. Resolves + ticket 6027. diff --git a/doc/tor.1.txt b/doc/tor.1.txt index 041b000f09..3ef5674d2b 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -358,7 +358,7 @@ GENERAL OPTIONS DataDirectory. If the option is set to 1, make the DataDirectory readable by the default GID. (Default: 0) -[[FallbackDir]] **FallbackDir** __address__:__port__ orport=__port__ id=__fingerprint__ [weight=__num__]:: +[[FallbackDir]] **FallbackDir** __address__:__port__ orport=__port__ id=__fingerprint__ [weight=__num__] [ipv6=__address__:__orport__]:: When we're unable to connect to any directory cache for directory info (usually because we don't know about any yet) we try a FallbackDir. By default, the directory authorities are also FallbackDirs. @@ -374,9 +374,12 @@ GENERAL OPTIONS "bridge" flag is set. If a flag "orport=**port**" is given, Tor will use the given port when opening encrypted tunnels to the dirserver. If a flag "weight=**num**" is given, then the directory server is chosen randomly - with probability proportional to that weight (default 1.0). Lastly, if a + with probability proportional to that weight (default 1.0). If a flag "v3ident=**fp**" is given, the dirserver is a v3 directory authority - whose v3 long-term signing key has the fingerprint **fp**. + + whose v3 long-term signing key has the fingerprint **fp**. Lastly, + if an "ipv6=__address__:__orport__" flag is present, then the directory + authority is listening for IPv6 connections on the indicated IPv6 address + and OR Port. + + If no **DirAuthority** line is given, Tor will use the default directory authorities. NOTE: this option is intended for setting up a private Tor diff --git a/src/or/config.c b/src/or/config.c index 7b42c9fdb3..894bd893d9 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -5538,6 +5538,7 @@ parse_dir_authority_line(const char *line, dirinfo_type_t required_type, smartlist_t *items = NULL; int r; char *addrport=NULL, *address=NULL, *nickname=NULL, *fingerprint=NULL; + tor_addr_port_t ipv6_addrport, *ipv6_addrport_ptr = NULL; uint16_t dir_port = 0, or_port = 0; char digest[DIGEST_LEN]; char v3_digest[DIGEST_LEN]; @@ -5594,6 +5595,19 @@ parse_dir_authority_line(const char *line, dirinfo_type_t required_type, } else { type |= V3_DIRINFO|EXTRAINFO_DIRINFO|MICRODESC_DIRINFO; } + } else if (!strcasecmpstart(flag, "ipv6=")) { + if (ipv6_addrport_ptr) { + log_warn(LD_CONFIG, "Redundant ipv6 addr/port on DirAuthority line"); + } else { + if (tor_addr_port_parse(LOG_WARN, flag+strlen("ipv6="), + &ipv6_addrport.addr, &ipv6_addrport.port) < 0 + || tor_addr_family(&ipv6_addrport.addr) != AF_INET6) { + log_warn(LD_CONFIG, "Bad ipv6 addr/port %s on DirAuthority line", + escaped(flag)); + goto err; + } + ipv6_addrport_ptr = &ipv6_addrport; + } } else { log_warn(LD_CONFIG, "Unrecognized flag '%s' on DirAuthority line", flag); @@ -5636,6 +5650,7 @@ parse_dir_authority_line(const char *line, dirinfo_type_t required_type, log_debug(LD_DIR, "Trusted %d dirserver at %s:%d (%s)", (int)type, address, (int)dir_port, (char*)smartlist_get(items,0)); if (!(ds = trusted_dir_server_new(nickname, address, dir_port, or_port, + ipv6_addrport_ptr, digest, v3_digest, type, weight))) goto err; dir_server_add(ds); @@ -5673,6 +5688,7 @@ parse_dir_fallback_line(const char *line, int ok; char id[DIGEST_LEN]; char *address=NULL; + tor_addr_port_t ipv6_addrport, *ipv6_addrport_ptr = NULL; double weight=1.0; memset(id, 0, sizeof(id)); @@ -5691,6 +5707,19 @@ parse_dir_fallback_line(const char *line, } else if (!strcmpstart(cp, "id=")) { ok = !base16_decode(id, DIGEST_LEN, cp+strlen("id="), strlen(cp)-strlen("id=")); + } else if (!strcasecmpstart(cp, "ipv6=")) { + if (ipv6_addrport_ptr) { + log_warn(LD_CONFIG, "Redundant ipv6 addr/port on FallbackDir line"); + } else { + if (tor_addr_port_parse(LOG_WARN, cp+strlen("ipv6="), + &ipv6_addrport.addr, &ipv6_addrport.port) < 0 + || tor_addr_family(&ipv6_addrport.addr) != AF_INET6) { + log_warn(LD_CONFIG, "Bad ipv6 addr/port %s on FallbackDir line", + escaped(cp)); + goto end; + } + ipv6_addrport_ptr = &ipv6_addrport; + } } else if (!strcmpstart(cp, "weight=")) { int ok; const char *wstring = cp + strlen("weight="); @@ -5732,7 +5761,8 @@ parse_dir_fallback_line(const char *line, if (!validate_only) { dir_server_t *ds; - ds = fallback_dir_server_new(&addr, dirport, orport, id, weight); + ds = fallback_dir_server_new(&addr, dirport, orport, ipv6_addrport_ptr, + id, weight); if (!ds) { log_warn(LD_CONFIG, "Couldn't create FallbackDir %s", escaped(line)); goto end; diff --git a/src/or/or.h b/src/or/or.h index 945934e271..8fd141bec9 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -5009,9 +5009,11 @@ typedef struct dir_server_t { char *description; char *nickname; char *address; /**< Hostname. */ + tor_addr_t ipv6_addr; /**< IPv6 address if present; AF_UNSPEC if not */ uint32_t addr; /**< IPv4 address. */ uint16_t dir_port; /**< Directory port. */ uint16_t or_port; /**< OR port: Used for tunneling connections. */ + uint16_t ipv6_orport; /**< OR port corresponding to ipv6_addr. */ double weight; /** Weight used when selecting this node at random */ char digest[DIGEST_LEN]; /**< Digest of identity key. */ char v3_identity_digest[DIGEST_LEN]; /**< Digest of v3 (authority only, diff --git a/src/or/router.c b/src/or/router.c index bed9dc5e43..49e2e318f5 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -1026,6 +1026,7 @@ init_keys(void) ds = trusted_dir_server_new(options->Nickname, NULL, router_get_advertised_dir_port(options, 0), router_get_advertised_or_port(options), + NULL, digest, v3_digest, type, 0.0); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 5e7906475f..8bded42468 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -4043,6 +4043,7 @@ dir_server_new(int is_authority, const tor_addr_t *addr, const char *hostname, uint16_t dir_port, uint16_t or_port, + const tor_addr_port_t *addrport_ipv6, const char *digest, const char *v3_auth_digest, dirinfo_type_t type, double weight) @@ -4059,7 +4060,7 @@ dir_server_new(int is_authority, if (tor_addr_family(addr) == AF_INET) a = tor_addr_to_ipv4h(addr); else - return NULL; /*XXXX Support IPv6 */ + return NULL; if (!hostname) hostname_ = tor_dup_addr(addr); @@ -4076,6 +4077,18 @@ dir_server_new(int is_authority, ent->is_authority = is_authority; ent->type = type; ent->weight = weight; + if (addrport_ipv6) { + if (tor_addr_family(&addrport_ipv6->addr) != AF_INET6) { + log_warn(LD_BUG, "Hey, I got a non-ipv6 addr as addrport_ipv6."); + tor_addr_make_unspec(&ent->ipv6_addr); + } else { + tor_addr_copy(&ent->ipv6_addr, &addrport_ipv6->addr); + ent->ipv6_orport = addrport_ipv6->port; + } + } else { + tor_addr_make_unspec(&ent->ipv6_addr); + } + memcpy(ent->digest, digest, DIGEST_LEN); if (v3_auth_digest && (type & V3_DIRINFO)) memcpy(ent->v3_identity_digest, v3_auth_digest, DIGEST_LEN); @@ -4088,6 +4101,7 @@ dir_server_new(int is_authority, hostname, (int)dir_port); ent->fake_status.addr = ent->addr; + tor_addr_copy(&ent->fake_status.ipv6_addr, &ent->ipv6_addr); memcpy(ent->fake_status.identity_digest, digest, DIGEST_LEN); if (nickname) strlcpy(ent->fake_status.nickname, nickname, @@ -4096,6 +4110,7 @@ dir_server_new(int is_authority, ent->fake_status.nickname[0] = '\0'; ent->fake_status.dir_port = ent->dir_port; ent->fake_status.or_port = ent->or_port; + ent->fake_status.ipv6_orport = ent->ipv6_orport; return ent; } @@ -4107,6 +4122,7 @@ dir_server_new(int is_authority, dir_server_t * trusted_dir_server_new(const char *nickname, const char *address, uint16_t dir_port, uint16_t or_port, + const tor_addr_port_t *ipv6_addrport, const char *digest, const char *v3_auth_digest, dirinfo_type_t type, double weight) { @@ -4137,7 +4153,9 @@ trusted_dir_server_new(const char *nickname, const char *address, tor_addr_from_ipv4h(&addr, a); result = dir_server_new(1, nickname, &addr, hostname, - dir_port, or_port, digest, + dir_port, or_port, + ipv6_addrport, + digest, v3_auth_digest, type, weight); tor_free(hostname); return result; @@ -4149,9 +4167,12 @@ trusted_dir_server_new(const char *nickname, const char *address, dir_server_t * fallback_dir_server_new(const tor_addr_t *addr, uint16_t dir_port, uint16_t or_port, + const tor_addr_port_t *addrport_ipv6, const char *id_digest, double weight) { - return dir_server_new(0, NULL, addr, NULL, dir_port, or_port, id_digest, + return dir_server_new(0, NULL, addr, NULL, dir_port, or_port, + addrport_ipv6, + id_digest, NULL, ALL_DIRINFO, weight); } diff --git a/src/or/routerlist.h b/src/or/routerlist.h index 100ab5848f..3c4c9cde2d 100644 --- a/src/or/routerlist.h +++ b/src/or/routerlist.h @@ -170,10 +170,12 @@ int router_exit_policy_rejects_all(const routerinfo_t *router); dir_server_t *trusted_dir_server_new(const char *nickname, const char *address, uint16_t dir_port, uint16_t or_port, + const tor_addr_port_t *addrport_ipv6, const char *digest, const char *v3_auth_digest, dirinfo_type_t type, double weight); dir_server_t *fallback_dir_server_new(const tor_addr_t *addr, uint16_t dir_port, uint16_t or_port, + const tor_addr_port_t *addrport_ipv6, const char *id_digest, double weight); void dir_server_add(dir_server_t *ent); -- 2.11.4.GIT