Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions common/test/run-ip_port_parsing.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,18 @@
/* Generated stub for fromwire */
const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED)
{ fprintf(stderr, "fromwire called!\n"); abort(); }
/* Generated stub for fromwire_fail */
const void *fromwire_fail(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_fail called!\n"); abort(); }
/* Generated stub for fromwire_u16 */
u16 fromwire_u16(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_u16 called!\n"); abort(); }
/* Generated stub for fromwire_u8 */
u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_u8 called!\n"); abort(); }
/* Generated stub for fromwire_u8_array */
void fromwire_u8_array(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, u8 *arr UNNEEDED, size_t num UNNEEDED)
{ fprintf(stderr, "fromwire_u8_array called!\n"); abort(); }
/* Generated stub for towire */
void towire(u8 **pptr UNNEEDED, const void *data UNNEEDED, size_t len UNNEEDED)
{ fprintf(stderr, "towire called!\n"); abort(); }
Expand All @@ -23,6 +29,9 @@ void towire_u16(u8 **pptr UNNEEDED, u16 v UNNEEDED)
/* Generated stub for towire_u8 */
void towire_u8(u8 **pptr UNNEEDED, u8 v UNNEEDED)
{ fprintf(stderr, "towire_u8 called!\n"); abort(); }
/* Generated stub for towire_u8_array */
void towire_u8_array(u8 **pptr UNNEEDED, const u8 *arr UNNEEDED, size_t num UNNEEDED)
{ fprintf(stderr, "towire_u8_array called!\n"); abort(); }
/* AUTOGENERATED MOCKS END */

int main(void)
Expand Down
1 change: 1 addition & 0 deletions common/type_to_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ union printable_types {
const struct preimage *preimage;
const struct channel_oneside *channel_oneside;
const struct wireaddr *wireaddr;
const struct wireaddr_internal *wireaddr_internal;
const secp256k1_pubkey *secp256k1_pubkey;
const struct channel_id *channel_id;
const struct short_channel_id *short_channel_id;
Expand Down
198 changes: 182 additions & 16 deletions common/wireaddr.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include <arpa/inet.h>
#include <assert.h>
#include <ccan/build_assert/build_assert.h>
#include <ccan/mem/mem.h>
#include <ccan/tal/str/str.h>
#include <common/type_to_string.h>
#include <common/utils.h>
Expand All @@ -8,6 +10,7 @@
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <wire/wire.h>

/* Returns false if we didn't parse it, and *cursor == NULL if malformed. */
Expand Down Expand Up @@ -42,6 +45,57 @@ void towire_wireaddr(u8 **pptr, const struct wireaddr *addr)
towire_u16(pptr, addr->port);
}

enum addr_listen_announce fromwire_addr_listen_announce(const u8 **cursor,
size_t *max)
{
return fromwire_u8(cursor, max);
}

void towire_addr_listen_announce(u8 **pptr, enum addr_listen_announce ala)
{
towire_u8(pptr, ala);
}

void towire_wireaddr_internal(u8 **pptr, const struct wireaddr_internal *addr)
{
towire_u8(pptr, addr->itype);
switch (addr->itype) {
case ADDR_INTERNAL_SOCKNAME:
towire_u8_array(pptr, (const u8 *)addr->u.sockname,
sizeof(addr->u.sockname));
return;
case ADDR_INTERNAL_ALLPROTO:
towire_u16(pptr, addr->u.port);
return;
case ADDR_INTERNAL_WIREADDR:
towire_wireaddr(pptr, &addr->u.wireaddr);
return;
}
abort();
}

bool fromwire_wireaddr_internal(const u8 **cursor, size_t *max,
struct wireaddr_internal *addr)
{
addr->itype = fromwire_u8(cursor, max);
switch (addr->itype) {
case ADDR_INTERNAL_SOCKNAME:
fromwire_u8_array(cursor, max, (u8 *)addr->u.sockname,
sizeof(addr->u.sockname));
/* Must be NUL terminated */
if (!memchr(addr->u.sockname, 0, sizeof(addr->u.sockname)))
fromwire_fail(cursor, max);
return *cursor != NULL;
case ADDR_INTERNAL_ALLPROTO:
addr->u.port = fromwire_u16(cursor, max);
return *cursor != NULL;
case ADDR_INTERNAL_WIREADDR:
return fromwire_wireaddr(cursor, max, &addr->u.wireaddr);
}
fromwire_fail(cursor, max);
return false;
}

char *fmt_wireaddr(const tal_t *ctx, const struct wireaddr *a)
{
char addrstr[INET6_ADDRSTRLEN];
Expand All @@ -67,6 +121,77 @@ 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;
}

bool wireaddr_is_wildcard(const struct wireaddr *addr)
{
switch (addr->type) {
case ADDR_TYPE_IPV6:
case ADDR_TYPE_IPV4:
return memeqzero(addr->addr, addr->addrlen);
case ADDR_TYPE_PADDING:
return false;
}
abort();
}

char *fmt_wireaddr_internal(const tal_t *ctx,
const struct wireaddr_internal *a)
{
switch (a->itype) {
case ADDR_INTERNAL_SOCKNAME:
return tal_fmt(ctx, "%s", a->u.sockname);
case ADDR_INTERNAL_ALLPROTO:
return tal_fmt(ctx, ":%u", a->u.port);
case ADDR_INTERNAL_WIREADDR:
return fmt_wireaddr(ctx, &a->u.wireaddr);
}
abort();
}
REGISTER_TYPE_TO_STRING(wireaddr_internal, fmt_wireaddr_internal);

/* Valid forms:
*
* [anything]:<number>
Expand Down Expand Up @@ -137,18 +262,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;
}

Expand Down Expand Up @@ -182,16 +301,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;
}

Expand All @@ -204,3 +317,56 @@ bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 defport,
*err_msg = "Error parsing hostname";
return res;
}

bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr,
u16 port, bool wildcard_ok, const char **err_msg)
{
u16 wildport;
char *ip;

/* Addresses starting with '/' are local socket paths */
if (arg[0] == '/') {
addr->itype = ADDR_INTERNAL_SOCKNAME;

/* Check if the path is too long */
if (strlen(arg) >= sizeof(addr->u.sockname)) {
if (err_msg)
*err_msg = "Socket name too long";
return false;
}
strcpy(addr->u.sockname, arg);
return true;
}

/* An empty string means IPv4 and IPv6 (which under Linux by default
* means just IPv6, and IPv4 gets autobound). */
if (wildcard_ok
&& separate_address_and_port(tmpctx, arg, &ip, &wildport)
&& streq(ip, "")) {
addr->itype = ADDR_INTERNAL_ALLPROTO;
addr->u.port = wildport;
return true;
}

addr->itype = ADDR_INTERNAL_WIREADDR;
return parse_wireaddr(arg, &addr->u.wireaddr, port, err_msg);
}

void wireaddr_from_sockname(struct wireaddr_internal *addr,
const char *sockname)
{
addr->itype = ADDR_INTERNAL_SOCKNAME;
memset(addr->u.sockname, 0, sizeof(addr->u.sockname));
strncpy(addr->u.sockname, sockname, sizeof(addr->u.sockname)-1);
}

bool wireaddr_to_sockname(const struct wireaddr_internal *addr,
struct sockaddr_un *sun)
{
if (addr->itype != ADDR_INTERNAL_SOCKNAME)
return false;
sun->sun_family = AF_LOCAL;
BUILD_ASSERT(sizeof(sun->sun_path) == sizeof(addr->u.sockname));
memcpy(sun->sun_path, addr->u.sockname, sizeof(addr->u.sockname));
return true;
}
60 changes: 60 additions & 0 deletions common/wireaddr.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
#include <stdbool.h>
#include <stdlib.h>

struct in6_addr;
struct in_addr;
struct sockaddr_in6;
struct sockaddr_in;
struct sockaddr_un;

/* BOLT #7:
*
* The following `address descriptor` types are defined:
Expand Down Expand Up @@ -37,15 +43,69 @@ struct wireaddr {
u16 port;
};

/* We use wireaddr to tell gossipd both what to listen on, and what to
* announce */
enum addr_listen_announce {
ADDR_LISTEN = (1 << 0),
ADDR_ANNOUNCE = (1 << 1),
ADDR_LISTEN_AND_ANNOUNCE = ADDR_LISTEN|ADDR_ANNOUNCE
};

/* 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);

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);

bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 port, const char **err_msg);

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);

bool wireaddr_is_wildcard(const struct wireaddr *addr);

enum wireaddr_internal_type {
ADDR_INTERNAL_SOCKNAME,
ADDR_INTERNAL_ALLPROTO,
ADDR_INTERNAL_WIREADDR,
};

/* For internal use, where we can also supply a local socket, wildcard. */
struct wireaddr_internal {
enum wireaddr_internal_type itype;
union {
/* ADDR_INTERNAL_SOCKNAME */
struct wireaddr wireaddr;
/* ADDR_INTERNAL_ALLPROTO */
u16 port;
/* ADDR_INTERNAL_WIREADDR */
char sockname[108];
} u;
};
bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr, u16 port, bool wildcard_ok, const char **err_msg);

void towire_wireaddr_internal(u8 **pptr,
const struct wireaddr_internal *addr);
bool fromwire_wireaddr_internal(const u8 **cursor, size_t *max,
struct wireaddr_internal *addr);
char *fmt_wireaddr_internal(const tal_t *ctx,
const struct wireaddr_internal *a);

void wireaddr_from_sockname(struct wireaddr_internal *addr,
const char *sockname);
bool wireaddr_to_sockname(const struct wireaddr_internal *addr,
struct sockaddr_un *sun);
#endif /* LIGHTNING_COMMON_WIREADDR_H */
1 change: 1 addition & 0 deletions gossipd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ LIGHTNINGD_GOSSIP_HEADERS := gossipd/gen_gossip_wire.h \
gossipd/gen_gossip_store.h \
gossipd/gossip_store.h \
gossipd/handshake.h \
gossipd/netaddress.h \
gossipd/routing.h \
gossipd/broadcast.h
LIGHTNINGD_GOSSIP_SRC := gossipd/gossip.c \
Expand Down
Loading