Browse Source

wireaddr: Do hostname resolution in parse_wireaddr.

Fixes: #834
ppa-0.6.1
ZmnSCPxj 7 years ago
committed by Rusty Russell
parent
commit
f7f55edcdb
  1. 8
      common/test/run-ip_port_parsing.c
  2. 57
      common/wireaddr.c
  3. 2
      common/wireaddr.h
  4. 7
      lightningd/connect_control.c
  5. 5
      lightningd/options.c
  6. 4
      wallet/wallet.c

8
common/test/run-ip_port_parsing.c

@ -72,23 +72,23 @@ int main(void)
assert(!separate_address_and_port(ctx, "[::1]:http", &ip, &port));
// localhost hostnames for backward compat
parse_wireaddr("localhost", &addr, 200);
parse_wireaddr("localhost", &addr, 200, NULL);
assert(addr.port == 200);
// string should win the port battle
parse_wireaddr("[::1]:9735", &addr, 500);
parse_wireaddr("[::1]:9735", &addr, 500, NULL);
assert(addr.port == 9735);
ip = fmt_wireaddr(ctx, &addr);
assert(streq(ip, "[::1]:9735"));
// should use argument if we have no port in string
parse_wireaddr("2001:db8:85a3::8a2e:370:7334", &addr, 9777);
parse_wireaddr("2001:db8:85a3::8a2e:370:7334", &addr, 9777, NULL);
assert(addr.port == 9777);
ip = fmt_wireaddr(ctx, &addr);
assert(streq(ip, "[2001:db8:85a3::8a2e:370:7334]:9777"));
assert(parse_wireaddr("[::ffff:127.0.0.1]:49150", &addr, 1));
assert(parse_wireaddr("[::ffff:127.0.0.1]:49150", &addr, 1, NULL));
assert(addr.port == 49150);
tal_free(ctx);
return 0;

57
common/wireaddr.c

@ -4,8 +4,10 @@
#include <common/type_to_string.h>
#include <common/utils.h>
#include <common/wireaddr.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <wire/wire.h>
/* Returns false if we didn't parse it, and *cursor == NULL if malformed. */
@ -111,10 +113,16 @@ static bool separate_address_and_port(tal_t *ctx, const char *arg,
return true;
}
bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 defport)
bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 defport,
const char **err_msg)
{
struct in6_addr v6;
struct in_addr v4;
struct sockaddr_in6 *sa6;
struct sockaddr_in *sa4;
struct addrinfo *addrinfo;
struct addrinfo hints;
int gai_err;
u16 port;
char *ip;
bool res;
@ -122,13 +130,12 @@ bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 defport)
res = false;
port = defport;
if (err_msg)
*err_msg = NULL;
if (!separate_address_and_port(tmpctx, arg, &ip, &port)) {
tal_free(tmpctx);
return false;
}
if (!separate_address_and_port(tmpctx, arg, &ip, &port))
goto finish;
/* FIXME: change arg to addr[:port] and use getaddrinfo? */
if (streq(ip, "localhost"))
ip = "127.0.0.1";
else if (streq(ip, "ip6-localhost"))
@ -150,6 +157,44 @@ bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 defport)
res = true;
}
/* Resolve with getaddrinfo */
if (!res) {
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
hints.ai_flags = AI_ADDRCONFIG;
gai_err = getaddrinfo(ip, tal_fmt(tmpctx, "%d", port),
&hints, &addrinfo);
if (gai_err != 0) {
if (err_msg)
*err_msg = gai_strerror(gai_err);
goto finish;
}
/* 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);
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);
res = true;
}
/* Clean up */
freeaddrinfo(addrinfo);
}
finish:
if (!res && err_msg && !*err_msg)
*err_msg = "Error parsing hostname";
tal_free(tmpctx);
return res;
}

2
common/wireaddr.h

@ -41,7 +41,7 @@ struct wireaddr {
void towire_wireaddr(u8 **pptr, const struct wireaddr *addr);
bool fromwire_wireaddr(const u8 **cursor, size_t *max, struct wireaddr *addr);
bool parse_wireaddr(const char *arg, struct wireaddr *addr, u16 port);
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);

7
lightningd/connect_control.c

@ -114,6 +114,7 @@ static void json_connect(struct command *cmd,
const char *name;
struct wireaddr addr;
u8 *msg;
const char *err_msg;
if (!json_get_params(cmd, buffer, params,
"id", &idtok,
@ -178,9 +179,9 @@ static void json_connect(struct command *cmd,
} else {
addr.port = DEFAULT_PORT;
}
if (!parse_wireaddr(name, &addr, addr.port) || !addr.port) {
command_fail(cmd, "Host %s:%u not valid",
name, addr.port);
if (!parse_wireaddr(name, &addr, addr.port, &err_msg) || !addr.port) {
command_fail(cmd, "Host %s:%u not valid: %s",
name, addr.port, err_msg ? err_msg : "port is 0");
return;
}

5
lightningd/options.c

@ -117,11 +117,12 @@ static char *opt_set_s32(const char *arg, s32 *u)
static char *opt_add_ipaddr(const char *arg, struct lightningd *ld)
{
size_t n = tal_count(ld->wireaddrs);
char const *err_msg;
tal_resize(&ld->wireaddrs, n+1);
if (!parse_wireaddr(arg, &ld->wireaddrs[n], ld->portnum)) {
return tal_fmt(NULL, "Unable to parse IP address '%s'", arg);
if (!parse_wireaddr(arg, &ld->wireaddrs[n], ld->portnum, &err_msg)) {
return tal_fmt(NULL, "Unable to parse IP address '%s': %s", arg, err_msg);
}
return NULL;

4
wallet/wallet.c

@ -436,7 +436,7 @@ static struct peer *wallet_peer_load(struct wallet *w, const u64 dbid)
addrstr = sqlite3_column_text(stmt, 2);
if (addrstr) {
addrp = &addr;
if (!parse_wireaddr((const char*)addrstr, addrp, DEFAULT_PORT)) {
if (!parse_wireaddr((const char*)addrstr, addrp, DEFAULT_PORT, NULL)) {
sqlite3_finalize(stmt);
return NULL;
}
@ -466,7 +466,7 @@ bool wallet_peer_by_nodeid(struct wallet *w, const struct pubkey *nodeid,
addrstr = sqlite3_column_text(stmt, 2);
if (addrstr)
parse_wireaddr((const char*)addrstr, &peer->addr, DEFAULT_PORT);
parse_wireaddr((const char*)addrstr, &peer->addr, DEFAULT_PORT, NULL);
} else {
/* Make sure we mark this as a new peer */
peer->dbid = 0;

Loading…
Cancel
Save