From 7ecccd50b94fe5a7d4b90101bab99bc6ec4fafea Mon Sep 17 00:00:00 2001 From: William Casarin Date: Mon, 18 Dec 2017 02:10:43 -0800 Subject: [PATCH] wireaddr: add ip[:port] parsing * Add port parsing support to parse_wireaddr. This is in preparation for storing addresses in the peers table. This also makes parse_wireaddr a proper inverse of fmt_wireaddr. * Move parse_wireaddr to common/wireaddr.c this seems like a better place for it. I bring along parse_ip_port with it for convenience. This also fixes some issues with the upcoming ip/port parsing tests. Signed-off-by: William Casarin --- common/wireaddr.c | 83 +++++++++++++++++++++++++++++++++++++++++ common/wireaddr.h | 5 +++ lightningd/netaddress.c | 28 -------------- lightningd/netaddress.h | 1 - wallet/test/Makefile | 3 ++ 5 files changed, 91 insertions(+), 29 deletions(-) diff --git a/common/wireaddr.c b/common/wireaddr.c index 9d529bacb..b2058d1a5 100644 --- a/common/wireaddr.c +++ b/common/wireaddr.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -61,3 +62,85 @@ static char *fmt_wireaddr(const tal_t *ctx, const struct wireaddr *a) return ret; } REGISTER_TYPE_TO_STRING(wireaddr, fmt_wireaddr); + + +bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 defport) +{ + struct in6_addr v6; + struct in_addr v4; + u16 port; + char *ip; + bool res; + tal_t *tmpctx = tal_tmpctx(NULL); + + res = false; + port = defport; + + if (!parse_ip_port(tmpctx, arg, &ip, &port)) + port = defport; + + /* FIXME: change arg to addr[:port] and use getaddrinfo? */ + if (streq(arg, "localhost")) + ip = "127.0.0.1"; + else if (streq(arg, "ip6-localhost")) + ip = "::1"; + + memset(&addr->addr, 0, sizeof(addr->addr)); + + if (inet_pton(AF_INET, ip, &v4) == 1) { + addr->type = ADDR_TYPE_IPV4; + addr->addrlen = 4; + addr->port = port; + memcpy(&addr->addr, &v4, addr->addrlen); + res = true; + } else if (inet_pton(AF_INET6, ip, &v6) == 1) { + addr->type = ADDR_TYPE_IPV6; + addr->addrlen = 16; + addr->port = port; + memcpy(&addr->addr, &v6, addr->addrlen); + res = true; + } + + tal_free(tmpctx); + return res; +} + +// NOTE: arg is assumed to be an ipv4/6 addr string with optional port +bool parse_ip_port(tal_t *ctx, const char *arg, char **ip, u16 *port) { + bool ipv6, has_brackets, has_colon; + + *port = 0; + ipv6 = true; + has_brackets = false; + has_colon = false; + + *ip = tal_strdup(ctx, arg); + + ipv6 = strchr(*ip, '.') == NULL; + has_brackets = strchr(*ip, '['); + has_colon = strchr(*ip, ':'); + + // we have an ip addr with no port + if ((ipv6 && !has_brackets) || (!ipv6 && !has_colon)) + return false; + + /* IPv6 can have [ ], trim them here */ + if (ipv6 && strstarts(*ip, "[") && strends(*ip, "]")) { + (*ip)++; + (*ip)[strlen(*ip)-1] = '\0'; + return false; + } + + // we have a port, let's go to it + const char *last_colon = strrchr(*ip, ':'); + assert(last_colon); + + // chop off port + (*ip)[last_colon - *ip - ipv6] = '\0'; + + // skip over first [ if ipv6 + if (ipv6) (*ip)++; + + *port = atoi(last_colon + 1); + return *port != 0; +} diff --git a/common/wireaddr.h b/common/wireaddr.h index ab51b3c98..7c4f4a4a1 100644 --- a/common/wireaddr.h +++ b/common/wireaddr.h @@ -2,6 +2,7 @@ #define LIGHTNING_COMMON_WIREADDR_H #include "config.h" #include +#include #include #include @@ -39,4 +40,8 @@ struct wireaddr { /* Inserts a single ADDR_TYPE_PADDING if addr is NULL */ void towire_wireaddr(u8 **pptr, const struct wireaddr *addr); bool fromwire_wireaddr(const u8 **cursor, size_t *max, struct wireaddr *addr); + +bool parse_ip_port(tal_t *ctx, const char *arg, char **ip, u16 *port); +bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 port); + #endif /* LIGHTNING_COMMON_WIREADDR_H */ diff --git a/lightningd/netaddress.c b/lightningd/netaddress.c index c838e7b17..2b80e08a5 100644 --- a/lightningd/netaddress.c +++ b/lightningd/netaddress.c @@ -296,31 +296,3 @@ void guess_addresses(struct lightningd *ld) if (!guess_one_address(ld, &ld->wireaddrs[n], ld->portnum, ADDR_TYPE_IPV6)) tal_resize(&ld->wireaddrs, n); } - -bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 port) -{ - struct in6_addr v6; - struct in_addr v4; - - /* FIXME: change arg to addr[:port] and use getaddrinfo? */ - if (streq(arg, "localhost")) - arg = "127.0.0.1"; - else if (streq(arg, "ip6-localhost")) - arg = "::1"; - - memset(&addr->addr, 0, sizeof(addr->addr)); - if (inet_pton(AF_INET, arg, &v4) == 1) { - addr->type = ADDR_TYPE_IPV4; - addr->addrlen = 4; - addr->port = port; - memcpy(&addr->addr, &v4, addr->addrlen); - return true; - } else if (inet_pton(AF_INET6, arg, &v6) == 1) { - addr->type = ADDR_TYPE_IPV6; - addr->addrlen = 16; - addr->port = port; - memcpy(&addr->addr, &v6, addr->addrlen); - return true; - } - return false; -} diff --git a/lightningd/netaddress.h b/lightningd/netaddress.h index 17b70e799..a2428a9e7 100644 --- a/lightningd/netaddress.h +++ b/lightningd/netaddress.h @@ -7,6 +7,5 @@ struct lightningd; void guess_addresses(struct lightningd *ld); -bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 port); #endif /* LIGHTNING_LIGHTNINGD_NETADDRESS_H */ diff --git a/wallet/test/Makefile b/wallet/test/Makefile index d4d2b3813..47fb50cdf 100644 --- a/wallet/test/Makefile +++ b/wallet/test/Makefile @@ -8,6 +8,9 @@ WALLET_TEST_COMMON_OBJS := \ common/memleak.o \ common/pseudorand.o \ common/utils.o \ + common/wireaddr.o \ + wire/towire.o \ + wire/fromwire.o \ lightningd/htlc_end.o \ lightningd/log.o