connectd: get multiple addresses from hostname

This commit is contained in:
darosior 2019-09-02 00:15:08 +02:00 committed by Rusty Russell
parent 9be28fe40f
commit b2bb97adde
3 changed files with 41 additions and 33 deletions

View File

@ -289,17 +289,18 @@ static bool separate_address_and_port(const tal_t *ctx, const char *arg,
return true;
}
bool wireaddr_from_hostname(struct wireaddr *addr, const char *hostname,
bool wireaddr_from_hostname(struct wireaddr **addrs, const char *hostname,
const u16 port, bool *no_dns,
struct sockaddr *broken_reply,
const char **err_msg)
{
struct sockaddr_in6 *sa6;
struct sockaddr_in *sa4;
struct addrinfo *addrinfo;
struct addrinfo *addrinfo, *addrinfos;
struct addrinfo hints;
int gai_err;
bool res = false;
struct wireaddr *addr;
if (no_dns)
*no_dns = false;
@ -309,18 +310,18 @@ bool wireaddr_from_hostname(struct wireaddr *addr, const char *hostname,
u8 *dec = b32_decode(tmpctx, hostname,
strlen(hostname) - strlen(".onion"));
if (tal_count(dec) == TOR_V2_ADDRLEN)
addr->type = ADDR_TYPE_TOR_V2;
addrs[0]->type = ADDR_TYPE_TOR_V2;
else if (tal_count(dec) == TOR_V3_ADDRLEN)
addr->type = ADDR_TYPE_TOR_V3;
addrs[0]->type = ADDR_TYPE_TOR_V3;
else {
if (err_msg)
*err_msg = "Invalid Tor address";
return false;
}
addr->addrlen = tal_count(dec);
addr->port = port;
memcpy(&addr->addr, dec, tal_count(dec));
addrs[0]->addrlen = tal_count(dec);
addrs[0]->port = port;
memcpy(&addrs[0]->addr, dec, tal_count(dec));
return true;
}
@ -338,32 +339,35 @@ bool wireaddr_from_hostname(struct wireaddr *addr, const char *hostname,
hints.ai_protocol = 0;
hints.ai_flags = AI_ADDRCONFIG;
gai_err = getaddrinfo(hostname, tal_fmt(tmpctx, "%d", port),
&hints, &addrinfo);
&hints, &addrinfos);
if (gai_err != 0) {
if (err_msg)
*err_msg = gai_strerror(gai_err);
return false;
}
if (broken_reply != NULL && memeq(addrinfo->ai_addr, addrinfo->ai_addrlen, broken_reply, tal_count(broken_reply))) {
if (broken_reply != NULL && memeq(addrinfos->ai_addr, addrinfos->ai_addrlen, broken_reply, tal_count(broken_reply))) {
res = false;
goto cleanup;
}
/* Use only the first found address */
if (addrinfo->ai_family == AF_INET) {
sa4 = (struct sockaddr_in *) addrinfo->ai_addr;
wireaddr_from_ipv4(addr, &sa4->sin_addr, port);
res = true;
} else if (addrinfo->ai_family == AF_INET6) {
sa6 = (struct sockaddr_in6 *) addrinfo->ai_addr;
wireaddr_from_ipv6(addr, &sa6->sin6_addr, port);
res = true;
for (addrinfo = addrinfos; addrinfo; addrinfo = addrinfo->ai_next) {
addr = tal(addrs, struct wireaddr);
if (addrinfo->ai_family == AF_INET) {
sa4 = (struct sockaddr_in *) addrinfo->ai_addr;
wireaddr_from_ipv4(addr, &sa4->sin_addr, port);
res = true;
} else if (addrinfo->ai_family == AF_INET6) {
sa6 = (struct sockaddr_in6 *) addrinfo->ai_addr;
wireaddr_from_ipv6(addr, &sa6->sin6_addr, port);
res = true;
}
tal_arr_expand(&addrs, addr);
}
cleanup:
/* Clean up */
freeaddrinfo(addrinfo);
freeaddrinfo(addrinfos);
return res;
}
@ -401,7 +405,7 @@ bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 defport,
/* Resolve with getaddrinfo */
if (!res)
res = wireaddr_from_hostname(addr, ip, port, no_dns, NULL, err_msg);
res = wireaddr_from_hostname(&addr, ip, port, no_dns, NULL, err_msg);
finish:
if (!res && err_msg && !*err_msg)

View File

@ -86,7 +86,7 @@ char *fmt_wireaddr_without_port(const tal_t *ctx, const struct wireaddr *a);
/* If no_dns is non-NULL, we will set it to true and return false if
* we wanted to do a DNS lookup. */
bool wireaddr_from_hostname(struct wireaddr *addr, const char *hostname,
bool wireaddr_from_hostname(struct wireaddr **addrs, const char *hostname,
const u16 port, bool *no_dns,
struct sockaddr *broken_reply,
const char **err_msg);

View File

@ -1264,22 +1264,26 @@ static void add_seed_addrs(struct wireaddr_internal **addrs,
const struct node_id *id,
struct sockaddr *broken_reply)
{
struct wireaddr_internal a;
const char *addr;
struct wireaddr **new_addrs;
const char *hostname;
addr = seedname(tmpctx, id);
status_trace("Resolving %s", addr);
new_addrs = tal_arr(tmpctx, struct wireaddr *, 0);
hostname = seedname(tmpctx, id);
status_trace("Resolving %s", hostname);
a.itype = ADDR_INTERNAL_WIREADDR;
/* FIXME: wireaddr_from_hostname should return multiple addresses. */
if (!wireaddr_from_hostname(&a.u.wireaddr, addr, DEFAULT_PORT, NULL,
if (!wireaddr_from_hostname(new_addrs, hostname, DEFAULT_PORT, NULL,
broken_reply, NULL)) {
status_trace("Could not resolve %s", addr);
status_trace("Could not resolve %s", hostname);
} else {
status_trace("Resolved %s to %s", addr,
type_to_string(tmpctx, struct wireaddr,
&a.u.wireaddr));
tal_arr_expand(addrs, a);
for (size_t i = 0; i < tal_count(new_addrs); i++) {
struct wireaddr_internal a;
a.itype = ADDR_INTERNAL_WIREADDR;
a.u.wireaddr = *new_addrs[i];
status_trace("Resolved %s to %s", hostname,
type_to_string(tmpctx, struct wireaddr,
&a.u.wireaddr));
tal_arr_expand(addrs, a);
}
}
}