From 356e5dcea8eee311c7832d903dec34f5de9a6411 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 7 May 2018 13:59:21 +0930 Subject: [PATCH] wireaddr: helpers to convert to/from IPv4/v6 addresses. Signed-off-by: Rusty Russell --- common/wireaddr.c | 64 +++++++++++++++++++++++++++++++++++------------ common/wireaddr.h | 14 +++++++++++ gossipd/gossip.c | 41 ++++++------------------------ 3 files changed, 70 insertions(+), 49 deletions(-) diff --git a/common/wireaddr.c b/common/wireaddr.c index 1a621027e..f370bafaf 100644 --- a/common/wireaddr.c +++ b/common/wireaddr.c @@ -78,6 +78,50 @@ char *fmt_wireaddr(const tal_t *ctx, const struct wireaddr *a) } REGISTER_TYPE_TO_STRING(wireaddr, fmt_wireaddr); +void wireaddr_from_ipv4(struct wireaddr *addr, + const struct in_addr *ip4, + const u16 port) +{ + addr->type = ADDR_TYPE_IPV4; + addr->addrlen = sizeof(*ip4); + addr->port = port; + memset(addr->addr, 0, sizeof(addr->addr)); + memcpy(addr->addr, ip4, addr->addrlen); +} + +void wireaddr_from_ipv6(struct wireaddr *addr, + const struct in6_addr *ip6, + const u16 port) +{ + addr->type = ADDR_TYPE_IPV6; + addr->addrlen = sizeof(*ip6); + addr->port = port; + memset(addr->addr, 0, sizeof(addr->addr)); + memcpy(&addr->addr, ip6, addr->addrlen); +} + +bool wireaddr_to_ipv4(const struct wireaddr *addr, struct sockaddr_in *s4) +{ + if (addr->type != ADDR_TYPE_IPV4) + return false; + s4->sin_family = AF_INET; + s4->sin_port = htons(addr->port); + assert(addr->addrlen == sizeof(s4->sin_addr)); + memcpy(&s4->sin_addr, addr->addr, sizeof(s4->sin_addr)); + return true; +} + +bool wireaddr_to_ipv6(const struct wireaddr *addr, struct sockaddr_in6 *s6) +{ + if (addr->type != ADDR_TYPE_IPV6) + return false; + s6->sin6_family = AF_INET6; + s6->sin6_port = htons(addr->port); + assert(addr->addrlen == sizeof(s6->sin6_addr)); + memcpy(&s6->sin6_addr, addr->addr, sizeof(s6->sin6_addr)); + return true; +} + /* Valid forms: * * [anything]: @@ -148,18 +192,12 @@ bool wireaddr_from_hostname(struct wireaddr *addr, const char *hostname, } /* Use only the first found address */ if (addrinfo->ai_family == AF_INET) { - addr->type = ADDR_TYPE_IPV4; - addr->addrlen = 4; - addr->port = port; sa4 = (struct sockaddr_in *) addrinfo->ai_addr; - memcpy(&addr->addr, &sa4->sin_addr, addr->addrlen); + wireaddr_from_ipv4(addr, &sa4->sin_addr, port); res = true; } else if (addrinfo->ai_family == AF_INET6) { - addr->type = ADDR_TYPE_IPV6; - addr->addrlen = 16; - addr->port = port; sa6 = (struct sockaddr_in6 *) addrinfo->ai_addr; - memcpy(&addr->addr, &sa6->sin6_addr, addr->addrlen); + wireaddr_from_ipv6(addr, &sa6->sin6_addr, port); res = true; } @@ -193,16 +231,10 @@ bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 defport, 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); + wireaddr_from_ipv4(addr, &v4, port); 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); + wireaddr_from_ipv6(addr, &v6, port); res = true; } diff --git a/common/wireaddr.h b/common/wireaddr.h index 32a67417a..e639b3482 100644 --- a/common/wireaddr.h +++ b/common/wireaddr.h @@ -6,6 +6,11 @@ #include #include +struct in6_addr; +struct in_addr; +struct sockaddr_in6; +struct sockaddr_in; + /* BOLT #7: * * The following `address descriptor` types are defined: @@ -60,4 +65,13 @@ char *fmt_wireaddr(const tal_t *ctx, const struct wireaddr *a); bool wireaddr_from_hostname(struct wireaddr *addr, const char *hostname, const u16 port, const char **err_msg); +void wireaddr_from_ipv4(struct wireaddr *addr, + const struct in_addr *ip4, + const u16 port); +void wireaddr_from_ipv6(struct wireaddr *addr, + const struct in6_addr *ip6, + const u16 port); +bool wireaddr_to_ipv4(const struct wireaddr *addr, struct sockaddr_in *s4); +bool wireaddr_to_ipv6(const struct wireaddr *addr, struct sockaddr_in6 *s6); + #endif /* LIGHTNING_COMMON_WIREADDR_H */ diff --git a/gossipd/gossip.c b/gossipd/gossip.c index 9aa33b223..8dd280722 100644 --- a/gossipd/gossip.c +++ b/gossipd/gossip.c @@ -1532,18 +1532,10 @@ static struct io_plan *connection_in(struct io_conn *conn, struct daemon *daemon if (s.ss_family == AF_INET6) { struct sockaddr_in6 *s6 = (void *)&s; - addr.type = ADDR_TYPE_IPV6; - addr.addrlen = sizeof(s6->sin6_addr); - BUILD_ASSERT(sizeof(s6->sin6_addr) <= sizeof(addr.addr)); - memcpy(addr.addr, &s6->sin6_addr, addr.addrlen); - addr.port = ntohs(s6->sin6_port); + wireaddr_from_ipv6(&addr, &s6->sin6_addr, ntohs(s6->sin6_port)); } else if (s.ss_family == AF_INET) { struct sockaddr_in *s4 = (void *)&s; - addr.type = ADDR_TYPE_IPV4; - addr.addrlen = sizeof(s4->sin_addr); - BUILD_ASSERT(sizeof(s4->sin_addr) <= sizeof(addr.addr)); - memcpy(addr.addr, &s4->sin_addr, addr.addrlen); - addr.port = ntohs(s4->sin_port); + wireaddr_from_ipv4(&addr, &s4->sin_addr, ntohs(s4->sin_port)); } else { status_broken("Unknown socket type %i for incoming conn", s.ss_family); @@ -1568,13 +1560,7 @@ static void setup_listeners(struct daemon *daemon) switch (daemon->wireaddrs[i].type) { case ADDR_TYPE_IPV4: - addr.sin_family = AF_INET; - addr.sin_port = htons(daemon->wireaddrs[i].port); - assert(daemon->wireaddrs[i].addrlen - == sizeof(addr.sin_addr)); - memcpy(&addr.sin_addr, - daemon->wireaddrs[i].addr, - sizeof(addr.sin_addr)); + wireaddr_to_ipv4(&daemon->wireaddrs[i], &addr); /* We might fail if IPv6 bound to port first */ fd = make_listen_fd(AF_INET, &addr, sizeof(addr), !had_ipv6_wildcard); @@ -1586,13 +1572,7 @@ static void setup_listeners(struct daemon *daemon) } continue; case ADDR_TYPE_IPV6: - memset(&addr6, 0, sizeof(addr6)); - addr6.sin6_family = AF_INET6; - addr6.sin6_port = htons(daemon->wireaddrs[i].port); - assert(daemon->wireaddrs[i].addrlen - == sizeof(addr6.sin6_addr)); - memcpy(&addr6.sin6_addr, daemon->wireaddrs[i].addr, - sizeof(addr6.sin6_addr)); + wireaddr_to_ipv6(&daemon->wireaddrs[i], &addr6); if (memeqzero(&addr6.sin6_addr, sizeof(addr6.sin6_addr))) had_ipv6_wildcard = true; fd = make_listen_fd(AF_INET6, &addr6, sizeof(addr6), @@ -1771,19 +1751,14 @@ static struct io_plan *conn_init(struct io_conn *conn, struct reaching *reach) switch (reach->addr.type) { case ADDR_TYPE_IPV4: - ai.ai_family = AF_INET; - sin.sin_family = AF_INET; - sin.sin_port = htons(reach->addr.port); - memcpy(&sin.sin_addr, reach->addr.addr, sizeof(sin.sin_addr)); + wireaddr_to_ipv4(&reach->addr, &sin); + ai.ai_family = sin.sin_family; ai.ai_addrlen = sizeof(sin); ai.ai_addr = (struct sockaddr *)&sin; break; case ADDR_TYPE_IPV6: - ai.ai_family = AF_INET6; - memset(&sin6, 0, sizeof(sin6)); - sin6.sin6_family = AF_INET6; - sin6.sin6_port = htons(reach->addr.port); - memcpy(&sin6.sin6_addr, reach->addr.addr, sizeof(sin6.sin6_addr)); + wireaddr_to_ipv6(&reach->addr, &sin6); + ai.ai_family = sin6.sin6_family; ai.ai_addrlen = sizeof(sin6); ai.ai_addr = (struct sockaddr *)&sin6; break;