wireaddr_internal: new type for where we can also use a local socket.

This was something @icota implemented, but it fits logically into this
cleanup series.  We create a new type which is the internal generalization
of a wireaddr (which is defined by the spec), and add a case here for
a socket name.

Based-on-the-true-story-by: @icota
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2018-05-07 13:59:21 +09:30
committed by Christian Decker
parent e6c678e5df
commit 6b2282fc1d
4 changed files with 131 additions and 0 deletions

View File

@@ -1,5 +1,6 @@
#include <arpa/inet.h>
#include <assert.h>
#include <ccan/build_assert/build_assert.h>
#include <ccan/tal/str/str.h>
#include <common/type_to_string.h>
#include <common/utils.h>
@@ -8,6 +9,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. */
@@ -53,6 +55,40 @@ 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_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_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];
@@ -122,6 +158,19 @@ bool wireaddr_to_ipv6(const struct wireaddr *addr, struct sockaddr_in6 *s6)
return true;
}
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_WIREADDR:
return fmt_wireaddr(ctx, &a->u.wireaddr);
}
abort();
}
REGISTER_TYPE_TO_STRING(wireaddr_internal, fmt_wireaddr_internal);
/* Valid forms:
*
* [anything]:<number>
@@ -247,3 +296,42 @@ finish:
*err_msg = "Error parsing hostname";
return res;
}
bool parse_wireaddr_internal(const char *arg, struct wireaddr_internal *addr, u16 port, const char **err_msg)
{
/* 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;
}
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;
}