From 1125682cebd906632423a3cdaa4a125debec448a Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 10 May 2018 13:14:23 +0930 Subject: [PATCH] wireaddr: new type, ADDR_INTERNAL_FORPROXY, use it if we can't/wont resolve. Tor wasn't actually working for me to connect to anything, but it worked for 'ssh -D' testing. Note that the resulting 'netaddr' is a bit weird, but I guess it's honest. $ ./cli/lightning-cli connect 021f2cbffc4045ca2d70678ecf8ed75e488290874c9da38074f6d378248337062b { "id": "021f2cbffc4045ca2d70678ecf8ed75e488290874c9da38074f6d378248337062b" } $ ./cli/lightning-cli listpeers { "peers": [ { "state": "GOSSIPING", "id": "021f2cbffc4045ca2d70678ecf8ed75e488290874c9da38074f6d378248337062b", "netaddr": [ "ln1qg0je0lugpzu5ttsv78vlrkhteyg9yy8fjw68qr57mfhsfyrxurzkq522ah.lseed.bitcoinstats.com:9735" ], "connected": true, "owner": "lightning_gossipd" } ] } Signed-off-by: Rusty Russell --- common/wireaddr.c | 60 +++++++++++++++++++++++++++++++----- common/wireaddr.h | 11 ++++++- gossipd/gossip.c | 28 ++++++++++++++--- lightningd/connect_control.c | 1 + lightningd/json.c | 7 +++++ lightningd/options.c | 2 +- wallet/wallet.c | 2 +- 7 files changed, 97 insertions(+), 14 deletions(-) diff --git a/common/wireaddr.c b/common/wireaddr.c index 941118a5d..093d390d8 100644 --- a/common/wireaddr.c +++ b/common/wireaddr.c @@ -83,6 +83,11 @@ void towire_wireaddr_internal(u8 **pptr, const struct wireaddr_internal *addr) case ADDR_INTERNAL_WIREADDR: towire_wireaddr(pptr, &addr->u.wireaddr); return; + case ADDR_INTERNAL_FORPROXY: + towire_u8_array(pptr, (const u8 *)addr->u.unresolved.name, + sizeof(addr->u.unresolved.name)); + towire_u16(pptr, addr->u.unresolved.port); + return; } abort(); } @@ -106,6 +111,15 @@ bool fromwire_wireaddr_internal(const u8 **cursor, size_t *max, return fromwire_wireaddr(cursor, max, &addr->u.torservice); case ADDR_INTERNAL_WIREADDR: return fromwire_wireaddr(cursor, max, &addr->u.wireaddr); + case ADDR_INTERNAL_FORPROXY: + fromwire_u8_array(cursor, max, (u8 *)addr->u.unresolved.name, + sizeof(addr->u.unresolved.name)); + /* Must be NUL terminated */ + if (!memchr(addr->u.unresolved.name, 0, + sizeof(addr->u.unresolved.name))) + fromwire_fail(cursor, max); + addr->u.unresolved.port = fromwire_u16(cursor, max); + return *cursor != NULL; } fromwire_fail(cursor, max); return false; @@ -179,6 +193,9 @@ char *fmt_wireaddr_internal(const tal_t *ctx, return tal_fmt(ctx, ":%u", a->u.port); case ADDR_INTERNAL_WIREADDR: return fmt_wireaddr(ctx, &a->u.wireaddr); + case ADDR_INTERNAL_FORPROXY: + return tal_fmt(ctx, "%s:%u", + a->u.unresolved.name, a->u.unresolved.port); case ADDR_INTERNAL_AUTOTOR: return tal_fmt(ctx, "autotor:%s", fmt_wireaddr(tmpctx, &a->u.torservice)); @@ -383,11 +400,12 @@ finish: bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr, u16 port, bool wildcard_ok, bool dns_ok, + bool unresolved_ok, const char **err_msg) { - u16 wildport; + u16 splitport; char *ip; - bool needed_dns; + bool needed_dns = false; /* Addresses starting with '/' are local socket paths */ if (arg[0] == '/') { @@ -405,12 +423,12 @@ bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr, /* An empty string means IPv4 and IPv6 (which under Linux by default * means just IPv6, and IPv4 gets autobound). */ - wildport = port; + splitport = port; if (wildcard_ok - && separate_address_and_port(tmpctx, arg, &ip, &wildport) + && separate_address_and_port(tmpctx, arg, &ip, &splitport) && streq(ip, "")) { addr->itype = ADDR_INTERNAL_ALLPROTO; - addr->u.port = wildport; + addr->u.port = splitport; return true; } @@ -425,8 +443,33 @@ bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr, } addr->itype = ADDR_INTERNAL_WIREADDR; - return parse_wireaddr(arg, &addr->u.wireaddr, port, - dns_ok ? NULL : &needed_dns, err_msg); + if (parse_wireaddr(arg, &addr->u.wireaddr, port, + dns_ok ? NULL : &needed_dns, err_msg)) + return true; + + if (!needed_dns || !unresolved_ok) + return false; + + /* We can't do DNS, so keep unresolved. */ + if (!wireaddr_from_unresolved(addr, ip, splitport)) { + if (err_msg) + *err_msg = "Name too long"; + return false; + } + return true; +} + +bool wireaddr_from_unresolved(struct wireaddr_internal *addr, + const char *name, u16 port) +{ + addr->itype = ADDR_INTERNAL_FORPROXY; + if (strlen(name) >= sizeof(addr->u.unresolved.name)) + return false; + + memset(addr->u.unresolved.name, 0, sizeof(addr->u.unresolved.name)); + strcpy(addr->u.unresolved.name, name); + addr->u.unresolved.port = port; + return true; } void wireaddr_from_sockname(struct wireaddr_internal *addr, @@ -466,6 +509,7 @@ struct addrinfo *wireaddr_internal_to_addrinfo(const tal_t *ctx, return ai; case ADDR_INTERNAL_ALLPROTO: case ADDR_INTERNAL_AUTOTOR: + case ADDR_INTERNAL_FORPROXY: break; case ADDR_INTERNAL_WIREADDR: return wireaddr_to_addrinfo(ctx, &wireaddr->u.wireaddr); @@ -511,6 +555,8 @@ bool all_tor_addresses(const struct wireaddr_internal *wireaddr) switch (wireaddr[i].itype) { case ADDR_INTERNAL_SOCKNAME: return false; + case ADDR_INTERNAL_FORPROXY: + abort(); case ADDR_INTERNAL_ALLPROTO: return false; case ADDR_INTERNAL_AUTOTOR: diff --git a/common/wireaddr.h b/common/wireaddr.h index a62ee9db5..3ea63531b 100644 --- a/common/wireaddr.h +++ b/common/wireaddr.h @@ -104,6 +104,7 @@ enum wireaddr_internal_type { ADDR_INTERNAL_SOCKNAME, ADDR_INTERNAL_ALLPROTO, ADDR_INTERNAL_AUTOTOR, + ADDR_INTERNAL_FORPROXY, ADDR_INTERNAL_WIREADDR, }; @@ -117,13 +118,18 @@ struct wireaddr_internal { u16 port; /* ADDR_INTERNAL_AUTOTOR */ struct wireaddr torservice; + /* ADDR_INTERNAL_FORPROXY */ + struct unresolved { + char name[256]; + u16 port; + } unresolved; /* ADDR_INTERNAL_SOCKNAME */ char sockname[sizeof(((struct sockaddr_un *)0)->sun_path)]; } u; }; bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr, u16 port, bool wildcard_ok, bool dns_ok, - const char **err_msg); + bool unresolved_ok, const char **err_msg); void towire_wireaddr_internal(u8 **pptr, const struct wireaddr_internal *addr); @@ -132,6 +138,9 @@ bool fromwire_wireaddr_internal(const u8 **cursor, size_t *max, char *fmt_wireaddr_internal(const tal_t *ctx, const struct wireaddr_internal *a); +bool wireaddr_from_unresolved(struct wireaddr_internal *addr, + const char *name, u16 port); + void wireaddr_from_sockname(struct wireaddr_internal *addr, const char *sockname); bool wireaddr_to_sockname(const struct wireaddr_internal *addr, diff --git a/gossipd/gossip.c b/gossipd/gossip.c index be59a1efa..30bd3abe5 100644 --- a/gossipd/gossip.c +++ b/gossipd/gossip.c @@ -1711,6 +1711,8 @@ static struct wireaddr_internal *setup_listeners(const tal_t *ctx, if (public_address(daemon, &wa.u.wireaddr)) add_announcable(daemon, &wa.u.wireaddr); continue; + case ADDR_INTERNAL_FORPROXY: + break; } /* Shouldn't happen. */ status_failed(STATUS_FAIL_INTERNAL_ERROR, @@ -1911,6 +1913,10 @@ static struct io_plan *conn_init(struct io_conn *conn, struct reaching *reach) status_failed(STATUS_FAIL_INTERNAL_ERROR, "Can't reach to autotor address"); break; + case ADDR_INTERNAL_FORPROXY: + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Can't reach to forproxy address"); + break; case ADDR_INTERNAL_WIREADDR: /* If it was a Tor address, we wouldn't be here. */ ai = wireaddr_to_addrinfo(tmpctx, &reach->addr.u.wireaddr); @@ -1929,6 +1935,10 @@ static struct io_plan *conn_proxy_init(struct io_conn *conn, u16 port; switch (reach->addr.itype) { + case ADDR_INTERNAL_FORPROXY: + host = reach->addr.u.unresolved.name; + port = reach->addr.u.unresolved.port; + break; case ADDR_INTERNAL_WIREADDR: host = fmt_wireaddr_without_port(tmpctx, &reach->addr.u.wireaddr); @@ -2024,7 +2034,7 @@ static void try_reach_peer(struct daemon *daemon, const struct pubkey *id, int fd, af; struct reaching *reach; u8 *msg; - bool use_proxy; + bool use_proxy = daemon->use_proxy_always; struct peer *peer = find_peer(daemon, id); if (peer) { @@ -2063,8 +2073,16 @@ static void try_reach_peer(struct daemon *daemon, const struct pubkey *id, daemon->rstate, id); - if (!a && !daemon->use_proxy_always) - a = seed_resolve_addr(tmpctx, id); + if (!a) { + /* Don't resolve via DNS seed if we're supposed to use proxy. */ + if (use_proxy) { + a = tal(tmpctx, struct wireaddr_internal); + wireaddr_from_unresolved(a, seedname(tmpctx, id), + DEFAULT_PORT); + } else { + a = seed_resolve_addr(tmpctx, id); + } + } if (!a) { status_debug("No address known for %s, giving up", @@ -2080,7 +2098,6 @@ static void try_reach_peer(struct daemon *daemon, const struct pubkey *id, /* Might not even be able to create eg. IPv6 sockets */ af = -1; - use_proxy = daemon->use_proxy_always; switch (a->itype) { case ADDR_INTERNAL_SOCKNAME: @@ -2094,6 +2111,9 @@ static void try_reach_peer(struct daemon *daemon, const struct pubkey *id, case ADDR_INTERNAL_AUTOTOR: status_failed(STATUS_FAIL_INTERNAL_ERROR, "Can't reach AUTOTOR"); + case ADDR_INTERNAL_FORPROXY: + use_proxy = true; + break; case ADDR_INTERNAL_WIREADDR: switch (a->u.wireaddr.type) { case ADDR_TYPE_TOR_V2: diff --git a/lightningd/connect_control.c b/lightningd/connect_control.c index 4de222e1a..068d600dd 100644 --- a/lightningd/connect_control.c +++ b/lightningd/connect_control.c @@ -154,6 +154,7 @@ static void json_connect(struct command *cmd, if (!parse_wireaddr_internal(name, &addr, port, false, !cmd->ld->use_proxy_always && !cmd->ld->pure_tor_setup, + true, &err_msg)) { command_fail(cmd, "Host %s:%u not valid: %s", name, port, err_msg ? err_msg : "port is 0"); diff --git a/lightningd/json.c b/lightningd/json.c index 6dde05f4b..45e180e37 100644 --- a/lightningd/json.c +++ b/lightningd/json.c @@ -174,6 +174,13 @@ void json_add_address_internal(struct json_result *response, json_add_address(response, "service", &addr->u.torservice); json_object_end(response); return; + case ADDR_INTERNAL_FORPROXY: + json_object_start(response, fieldname); + json_add_string(response, "type", "unresolved"); + json_add_string(response, "name", addr->u.unresolved.name); + json_add_num(response, "port", addr->u.unresolved.port); + json_object_end(response); + return; case ADDR_INTERNAL_WIREADDR: json_add_address(response, fieldname, &addr->u.wireaddr); return; diff --git a/lightningd/options.c b/lightningd/options.c index a176542c9..85848775e 100644 --- a/lightningd/options.c +++ b/lightningd/options.c @@ -160,7 +160,7 @@ static char *opt_add_addr_withtype(const char *arg, ld->proposed_listen_announce[n] = ala; if (!parse_wireaddr_internal(arg, &ld->proposed_wireaddr[n], ld->portnum, - wildcard_ok, !ld->use_proxy_always, + wildcard_ok, !ld->use_proxy_always, false, &err_msg)) { return tal_fmt(NULL, "Unable to parse address '%s': %s", arg, err_msg); } diff --git a/wallet/wallet.c b/wallet/wallet.c index 2ac993f84..cb32eb250 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -510,7 +510,7 @@ static struct peer *wallet_peer_load(struct wallet *w, const u64 dbid) addrstr = sqlite3_column_text(stmt, 2); if (addrstr) { addrp = &addr; - if (!parse_wireaddr_internal((const char*)addrstr, addrp, DEFAULT_PORT, false, false, NULL)) { + if (!parse_wireaddr_internal((const char*)addrstr, addrp, DEFAULT_PORT, false, false, true, NULL)) { db_stmt_done(stmt); return NULL; }