diff --git a/common/wireaddr.c b/common/wireaddr.c index d54634226..941118a5d 100644 --- a/common/wireaddr.c +++ b/common/wireaddr.c @@ -270,7 +270,8 @@ static bool separate_address_and_port(const tal_t *ctx, const char *arg, } bool wireaddr_from_hostname(struct wireaddr *addr, const char *hostname, - const u16 port, bool dns_ok, const char **err_msg) + const u16 port, bool *no_dns, + const char **err_msg) { struct sockaddr_in6 *sa6; struct sockaddr_in *sa4; @@ -279,6 +280,9 @@ bool wireaddr_from_hostname(struct wireaddr *addr, const char *hostname, int gai_err; bool res = false; + if (no_dns) + *no_dns = false; + /* Don't do lookup on onion addresses. */ if (strends(hostname, ".onion")) { u8 *dec = b32_decode(tmpctx, hostname, @@ -299,13 +303,19 @@ bool wireaddr_from_hostname(struct wireaddr *addr, const char *hostname, return true; } + /* Tell them we wanted DNS and fail. */ + if (no_dns) { + if (err_msg) + *err_msg = "Needed DNS, but lookups suppressed"; + *no_dns = true; + return false; + } + memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; hints.ai_flags = AI_ADDRCONFIG; - if (!dns_ok) - hints.ai_flags = AI_NUMERICHOST; gai_err = getaddrinfo(hostname, tal_fmt(tmpctx, "%d", port), &hints, &addrinfo); if (gai_err != 0) { @@ -330,7 +340,7 @@ bool wireaddr_from_hostname(struct wireaddr *addr, const char *hostname, } bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 defport, - bool dns_ok, const char **err_msg) + bool *no_dns, const char **err_msg) { struct in6_addr v6; struct in_addr v4; @@ -363,7 +373,7 @@ bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 defport, /* Resolve with getaddrinfo */ if (!res) - res = wireaddr_from_hostname(addr, ip, port, dns_ok, err_msg); + res = wireaddr_from_hostname(addr, ip, port, no_dns, err_msg); finish: if (!res && err_msg && !*err_msg) @@ -377,6 +387,7 @@ bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr, { u16 wildport; char *ip; + bool needed_dns; /* Addresses starting with '/' are local socket paths */ if (arg[0] == '/') { @@ -408,12 +419,14 @@ bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr, if (strstarts(arg, "autotor:")) { addr->itype = ADDR_INTERNAL_AUTOTOR; return parse_wireaddr(arg + strlen("autotor:"), - &addr->u.torservice, 9051, dns_ok, + &addr->u.torservice, 9051, + dns_ok ? NULL : &needed_dns, err_msg); } addr->itype = ADDR_INTERNAL_WIREADDR; - return parse_wireaddr(arg, &addr->u.wireaddr, port, dns_ok, err_msg); + return parse_wireaddr(arg, &addr->u.wireaddr, port, + dns_ok ? NULL : &needed_dns, err_msg); } void wireaddr_from_sockname(struct wireaddr_internal *addr, diff --git a/common/wireaddr.h b/common/wireaddr.h index 8e62e5c50..a62ee9db5 100644 --- a/common/wireaddr.h +++ b/common/wireaddr.h @@ -75,14 +75,19 @@ enum addr_listen_announce fromwire_addr_listen_announce(const u8 **cursor, size_t *max); void towire_addr_listen_announce(u8 **pptr, enum addr_listen_announce ala); +/* If no_dns is non-NULL, we will set it to true and return false if + * we wanted to do a DNS lookup. */ bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 port, - bool dns_ok, const char **err_msg); + bool *no_dns, const char **err_msg); char *fmt_wireaddr(const tal_t *ctx, const struct wireaddr *a); 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, - const u16 port, bool dns_ok, const char **err_msg); + const u16 port, bool *no_dns, + const char **err_msg); void wireaddr_from_ipv4(struct wireaddr *addr, const struct in_addr *ip4, diff --git a/gossipd/gossip.c b/gossipd/gossip.c index e0e26c4c5..ad7d9d214 100644 --- a/gossipd/gossip.c +++ b/gossipd/gossip.c @@ -1932,8 +1932,7 @@ static struct io_plan *conn_proxy_init(struct io_conn *conn, } static struct addrhint * -seed_resolve_addr(const tal_t *ctx, const struct pubkey *id, const u16 port, - bool dns_ok) +seed_resolve_addr(const tal_t *ctx, const struct pubkey *id, const u16 port) { struct addrhint *a; char bech32[100], *addr; @@ -1949,7 +1948,7 @@ seed_resolve_addr(const tal_t *ctx, const struct pubkey *id, const u16 port, a = tal(ctx, struct addrhint); a->addr.itype = ADDR_INTERNAL_WIREADDR; - if (!wireaddr_from_hostname(&a->addr.u.wireaddr, addr, port, dns_ok, + if (!wireaddr_from_hostname(&a->addr.u.wireaddr, addr, port, NULL, NULL)) { status_trace("Could not resolve %s", addr); return tal_free(a); @@ -2036,9 +2035,8 @@ static void try_reach_peer(struct daemon *daemon, const struct pubkey *id, daemon->rstate, id); - if (!a) - a = seed_resolve_addr(tmpctx, id, 9735, - !daemon->use_proxy_always); + if (!a && !daemon->use_proxy_always) + a = seed_resolve_addr(tmpctx, id, 9735); if (!a) { status_debug("No address known for %s, giving up", diff --git a/lightningd/options.c b/lightningd/options.c index f775fc9f6..a176542c9 100644 --- a/lightningd/options.c +++ b/lightningd/options.c @@ -299,15 +299,17 @@ static char *opt_set_offline(struct lightningd *ld) static char *opt_add_proxy_addr(const char *arg, struct lightningd *ld) { + bool needed_dns; tal_free(ld->proxyaddr); /* We use a tal_arr here, so we can marshal it to gossipd */ ld->proxyaddr = tal_arr(ld, struct wireaddr, 1); - if (!parse_wireaddr(arg, ld->proxyaddr, 9050, !ld->use_proxy_always, + if (!parse_wireaddr(arg, ld->proxyaddr, 9050, + ld->use_proxy_always ? &needed_dns : NULL, NULL)) { - return tal_fmt(NULL, "Unable to parse Tor proxy address '%s'", - arg); + return tal_fmt(NULL, "Unable to parse Tor proxy address '%s' %s", + arg, needed_dns ? " (needed dns)" : ""); } return NULL; }