From a7d6326bef9cf943665aafca3474376df0d6e178 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 23 Oct 2017 14:48:38 +1030 Subject: [PATCH] type_to_string: format wireaddr. Good for printing, and removes some code from peer_control. Signed-off-by: Rusty Russell --- common/type_to_string.h | 1 + common/wireaddr.c | 29 +++++++++++++++++++++++++++++ lightningd/netaddress.c | 37 +++++++++++++++++++++++++++++-------- lightningd/options.c | 10 ++++++---- lightningd/peer_control.c | 25 ++----------------------- 5 files changed, 67 insertions(+), 35 deletions(-) diff --git a/common/type_to_string.h b/common/type_to_string.h index 87b929105..c12258283 100644 --- a/common/type_to_string.h +++ b/common/type_to_string.h @@ -18,6 +18,7 @@ union printable_types { const struct preimage *preimage; const struct channel_state *channel_state; const struct channel_oneside *channel_oneside; + const struct wireaddr *wireaddr; const secp256k1_pubkey *secp256k1_pubkey; const struct channel_id *channel_id; const struct short_channel_id *short_channel_id; diff --git a/common/wireaddr.c b/common/wireaddr.c index 784f304f0..ce4bea332 100644 --- a/common/wireaddr.c +++ b/common/wireaddr.c @@ -1,3 +1,7 @@ +#include +#include +#include +#include #include #include @@ -28,3 +32,28 @@ void towire_wireaddr(u8 **pptr, const struct wireaddr *addr) towire(pptr, addr->addr, addr->addrlen); towire_u16(pptr, addr->port); } + +static char *fmt_wireaddr(const tal_t *ctx, const struct wireaddr *a) +{ + char addrstr[INET6_ADDRSTRLEN]; + char *ret, *hex; + + switch (a->type) { + case ADDR_TYPE_IPV4: + if (!inet_ntop(AF_INET, a->addr, addrstr, INET_ADDRSTRLEN)) + return "Unprintable-ipv4-address"; + return tal_fmt(ctx, "%s:%u", addrstr, a->port); + case ADDR_TYPE_IPV6: + if (!inet_ntop(AF_INET6, a->addr, addrstr, INET6_ADDRSTRLEN)) + return "Unprintable-ipv6-address"; + return tal_fmt(ctx, "%s:%u", addrstr, a->port); + case ADDR_TYPE_PADDING: + break; + } + + hex = tal_hexstr(ctx, a->addr, a->addrlen); + ret = tal_fmt(ctx, "Unknown type %u %s:%u", a->type, hex, a->port); + tal_free(hex); + return ret; +} +REGISTER_TYPE_TO_STRING(wireaddr, fmt_wireaddr); diff --git a/lightningd/netaddress.c b/lightningd/netaddress.c index 8b04012de..c838e7b17 100644 --- a/lightningd/netaddress.c +++ b/lightningd/netaddress.c @@ -1,7 +1,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -198,18 +200,26 @@ static bool IsRoutable(const struct wireaddr *addr) /* Trick I learned from Harald Welte: create UDP socket, connect() and * then query address. */ -static bool get_local_sockname(int af, void *saddr, socklen_t saddrlen) +static bool get_local_sockname(struct lightningd *ld, + int af, void *saddr, socklen_t saddrlen) { int fd = socket(af, SOCK_DGRAM, 0); - if (fd < 0) + if (fd < 0) { + log_debug(ld->log, "Failed to create %u socket: %s", + af, strerror(errno)); return false; + } if (connect(fd, saddr, saddrlen) != 0) { + log_debug(ld->log, "Failed to connect %u socket: %s", + af, strerror(errno)); close(fd); return false; } if (getsockname(fd, saddr, &saddrlen) != 0) { + log_debug(ld->log, "Failed to get %u socket name: %s", + af, strerror(errno)); close(fd); return false; } @@ -219,7 +229,8 @@ static bool get_local_sockname(int af, void *saddr, socklen_t saddrlen) } /* Return an wireaddr without port filled in */ -static bool guess_one_address(struct wireaddr *addr, u16 portnum, +static bool guess_one_address(struct lightningd *ld, + struct wireaddr *addr, u16 portnum, enum wire_addr_type type) { addr->type = type; @@ -232,7 +243,8 @@ static bool guess_one_address(struct wireaddr *addr, u16 portnum, sin.sin_port = htons(53); /* 8.8.8.8 */ sin.sin_addr.s_addr = 0x08080808; - if (!get_local_sockname(AF_INET, &sin, sizeof(sin))) + sin.sin_family = AF_INET; + if (!get_local_sockname(ld, AF_INET, &sin, sizeof(sin))) return false; addr->addrlen = sizeof(sin.sin_addr); memcpy(addr->addr, &sin.sin_addr, addr->addrlen); @@ -245,20 +257,27 @@ static bool guess_one_address(struct wireaddr *addr, u16 portnum, = {0x20,0x01,0x48,0x60,0x48,0x60,0,0,0,0,0,0,8,8,8,8}; memset(&sin6, 0, sizeof(sin6)); sin6.sin6_port = htons(53); + sin6.sin6_family = AF_INET6; memcpy(sin6.sin6_addr.s6_addr, pchGoogle, sizeof(pchGoogle)); - if (!get_local_sockname(AF_INET6, &sin6, sizeof(sin6))) + if (!get_local_sockname(ld, AF_INET6, &sin6, sizeof(sin6))) return false; addr->addrlen = sizeof(sin6.sin6_addr); memcpy(addr->addr, &sin6.sin6_addr, addr->addrlen); break; } case ADDR_TYPE_PADDING: + log_debug(ld->log, "Padding address, ignoring"); return false; } - if (!IsRoutable(addr)) + if (!IsRoutable(addr)) { + log_debug(ld->log, "Address %s is not routable", + type_to_string(ltmp, struct wireaddr, addr)); return false; + } + log_debug(ld->log, "Public address %s", + type_to_string(ltmp, struct wireaddr, addr)); return true; } @@ -266,13 +285,15 @@ void guess_addresses(struct lightningd *ld) { size_t n = tal_count(ld->wireaddrs); + log_debug(ld->log, "Trying to guess public addresses..."); + /* We allocate an extra, then remove if it's not needed. */ tal_resize(&ld->wireaddrs, n+1); - if (guess_one_address(&ld->wireaddrs[n], ld->portnum, ADDR_TYPE_IPV4)) { + if (guess_one_address(ld, &ld->wireaddrs[n], ld->portnum, ADDR_TYPE_IPV4)) { n++; tal_resize(&ld->wireaddrs, n+1); } - if (!guess_one_address(&ld->wireaddrs[n], ld->portnum, ADDR_TYPE_IPV6)) + if (!guess_one_address(ld, &ld->wireaddrs[n], ld->portnum, ADDR_TYPE_IPV6)) tal_resize(&ld->wireaddrs, n); } diff --git a/lightningd/options.c b/lightningd/options.c index d3fa48a16..dcfd2bfd7 100644 --- a/lightningd/options.c +++ b/lightningd/options.c @@ -509,10 +509,6 @@ static void opt_parse_from_config(struct lightningd *ld) setup_default_config(ld); opt_parse(&argc, argv, config_log_stderr_exit); - - if (ld->portnum && tal_count(ld->wireaddrs) == 0) - guess_addresses(ld); - tal_free(contents); } @@ -613,6 +609,12 @@ bool handle_opts(struct lightningd *ld, int argc, char *argv[]) check_config(ld); + if (ld->portnum && tal_count(ld->wireaddrs) == 0) + guess_addresses(ld); + else + log_debug(ld->log, "Not guessing addresses: %s", + ld->portnum ? "manually set" : "port set to zero"); + #if DEVELOPER if (ld->dev_hsm_seed) { int fd; diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index e90fd5d2e..cc6796a8c 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -786,28 +786,6 @@ static void log_to_json(unsigned int skipped, json_add_string(info->response, NULL, log); } -static const char *wireaddr_name(const tal_t *ctx, const struct wireaddr *a) -{ - char name[INET6_ADDRSTRLEN]; - int af; - - switch (a->type) { - case ADDR_TYPE_IPV4: - af = AF_INET; - break; - case ADDR_TYPE_IPV6: - af = AF_INET6; - break; - default: - return tal_fmt(ctx, "Unknown type %u", a->type); - } - - if (!inet_ntop(af, a->addr, name, sizeof(name))) - sprintf(name, "Unprintable-%u-address", a->type); - - return tal_fmt(ctx, "%s:%u", name, a->port); -} - static void json_getpeers(struct command *cmd, const char *buffer, const jsmntok_t *params) { @@ -839,7 +817,8 @@ static void json_getpeers(struct command *cmd, json_object_start(response, NULL); json_add_string(response, "state", peer_state_name(p->state)); json_add_string(response, "netaddr", - wireaddr_name(response, &p->addr)); + type_to_string(response, struct wireaddr, + &p->addr)); json_add_pubkey(response, "peerid", &p->id); json_add_bool(response, "connected", p->owner != NULL); if (p->owner)