gossipd: handle wildcard addresses correctly.
If we're given a wildcard address, we can't announce it like that: we need to try to turn it into a real address (using guess_address). Then we use that address. As a side-effect of this cleanup, we only announce *any* '--addr' if it's routable. This fix means that our tests have to force '--announce-addr' because otherwise localhost isn't routable. This means that gossipd really controls the addresses now, and breaks them into two arrays: what we bind to, and what we announce. That is now what we return to the master for json_getinfo(), which prints them as 'bindings' and 'addresses' respectively. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
52917ff6c9
commit
af065417e1
|
@ -1,6 +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>
|
||||
|
@ -164,6 +165,18 @@ bool wireaddr_to_ipv6(const struct wireaddr *addr, struct sockaddr_in6 *s6)
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -75,6 +75,8 @@ void wireaddr_from_ipv6(struct wireaddr *addr,
|
|||
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,
|
||||
|
|
125
gossipd/gossip.c
125
gossipd/gossip.c
|
@ -129,8 +129,13 @@ struct daemon {
|
|||
|
||||
u8 alias[33];
|
||||
u8 rgb[3];
|
||||
struct wireaddr_internal *wireaddrs;
|
||||
enum addr_listen_announce *listen_announce;
|
||||
|
||||
/* Addresses master told us to use */
|
||||
struct wireaddr_internal *proposed_wireaddr;
|
||||
enum addr_listen_announce *proposed_listen_announce;
|
||||
|
||||
/* What we actually announce. */
|
||||
struct wireaddr *announcable;
|
||||
|
||||
/* To make sure our node_announcement timestamps increase */
|
||||
u32 last_announce_timestamp;
|
||||
|
@ -566,15 +571,8 @@ static u8 *create_node_announcement(const tal_t *ctx, struct daemon *daemon,
|
|||
sig = tal(ctx, secp256k1_ecdsa_signature);
|
||||
memset(sig, 0, sizeof(*sig));
|
||||
}
|
||||
for (i = 0; i < tal_count(daemon->wireaddrs); i++) {
|
||||
if (!(daemon->listen_announce[i] & ADDR_ANNOUNCE))
|
||||
continue;
|
||||
/* You can only announce wiretypes! */
|
||||
if (daemon->wireaddrs[i].itype != ADDR_INTERNAL_WIREADDR)
|
||||
continue;
|
||||
towire_wireaddr(&addresses,
|
||||
&daemon->wireaddrs[i].u.wireaddr);
|
||||
}
|
||||
for (i = 0; i < tal_count(daemon->announcable); i++)
|
||||
towire_wireaddr(&addresses, &daemon->announcable[i]);
|
||||
|
||||
announcement =
|
||||
towire_node_announcement(ctx, sig, features, timestamp,
|
||||
|
@ -1607,51 +1605,113 @@ static bool handle_wireaddr_listen(struct daemon *daemon,
|
|||
"Invalid listener wireaddress type %u", wireaddr->type);
|
||||
}
|
||||
|
||||
static void setup_listeners(struct daemon *daemon)
|
||||
/* If it's a wildcard, turns it into a real address pointing to internet */
|
||||
static bool public_address(struct wireaddr *wireaddr)
|
||||
{
|
||||
if (wireaddr_is_wildcard(wireaddr)) {
|
||||
if (!guess_address(wireaddr))
|
||||
return false;
|
||||
}
|
||||
|
||||
return address_routable(wireaddr);
|
||||
}
|
||||
|
||||
static void add_announcable(struct daemon *daemon, const struct wireaddr *addr)
|
||||
{
|
||||
size_t n = tal_count(daemon->announcable);
|
||||
tal_resize(&daemon->announcable, n+1);
|
||||
daemon->announcable[n] = *addr;
|
||||
}
|
||||
|
||||
static void add_binding(struct wireaddr_internal **binding,
|
||||
const struct wireaddr_internal *addr)
|
||||
{
|
||||
size_t n = tal_count(*binding);
|
||||
tal_resize(binding, n+1);
|
||||
(*binding)[n] = *addr;
|
||||
}
|
||||
|
||||
/* Initializes daemon->announcable array, returns addresses we bound to. */
|
||||
static struct wireaddr_internal *setup_listeners(const tal_t *ctx,
|
||||
struct daemon *daemon)
|
||||
{
|
||||
struct sockaddr_un addrun;
|
||||
int fd;
|
||||
struct wireaddr_internal *binding;
|
||||
|
||||
for (size_t i = 0; i < tal_count(daemon->wireaddrs); i++) {
|
||||
struct wireaddr wa = daemon->wireaddrs[i].u.wireaddr;
|
||||
binding = tal_arr(ctx, struct wireaddr_internal, 0);
|
||||
daemon->announcable = tal_arr(daemon, struct wireaddr, 0);
|
||||
|
||||
if (!(daemon->listen_announce[i] & ADDR_LISTEN))
|
||||
for (size_t i = 0; i < tal_count(daemon->proposed_wireaddr); i++) {
|
||||
struct wireaddr_internal wa = daemon->proposed_wireaddr[i];
|
||||
|
||||
if (!(daemon->proposed_listen_announce[i] & ADDR_LISTEN)) {
|
||||
assert(daemon->proposed_listen_announce[i]
|
||||
& ADDR_ANNOUNCE);
|
||||
/* You can only announce wiretypes! */
|
||||
assert(daemon->proposed_wireaddr[i].itype
|
||||
== ADDR_INTERNAL_WIREADDR);
|
||||
add_announcable(daemon, &wa.u.wireaddr);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (daemon->wireaddrs[i].itype) {
|
||||
switch (wa.itype) {
|
||||
case ADDR_INTERNAL_SOCKNAME:
|
||||
addrun.sun_family = AF_UNIX;
|
||||
memcpy(addrun.sun_path, daemon->wireaddrs[i].u.sockname,
|
||||
memcpy(addrun.sun_path, wa.u.sockname,
|
||||
sizeof(addrun.sun_path));
|
||||
fd = make_listen_fd(AF_INET, &addrun, sizeof(addrun),
|
||||
false);
|
||||
status_trace("Created socket listener on file %s",
|
||||
addrun.sun_path);
|
||||
io_new_listener(daemon, fd, connection_in, daemon);
|
||||
/* We don't announce socket names */
|
||||
add_binding(&binding, &wa);
|
||||
continue;
|
||||
case ADDR_INTERNAL_ALLPROTO: {
|
||||
bool ipv6_ok;
|
||||
|
||||
memset(wa.addr, 0, sizeof(wa.addr));
|
||||
wa.type = ADDR_TYPE_IPV6;
|
||||
wa.addrlen = 16;
|
||||
wa.itype = ADDR_INTERNAL_WIREADDR;
|
||||
wa.u.wireaddr.port = wa.u.port;
|
||||
memset(wa.u.wireaddr.addr, 0,
|
||||
sizeof(wa.u.wireaddr.addr));
|
||||
|
||||
ipv6_ok = handle_wireaddr_listen(daemon, &wa, true);
|
||||
wa.type = ADDR_TYPE_IPV4;
|
||||
wa.addrlen = 4;
|
||||
/* Try both IPv6 and IPv4. */
|
||||
wa.u.wireaddr.type = ADDR_TYPE_IPV6;
|
||||
wa.u.wireaddr.addrlen = 16;
|
||||
|
||||
ipv6_ok = handle_wireaddr_listen(daemon, &wa.u.wireaddr,
|
||||
true);
|
||||
if (ipv6_ok) {
|
||||
add_binding(&binding, &wa);
|
||||
if (public_address(&wa.u.wireaddr))
|
||||
add_announcable(daemon, &wa.u.wireaddr);
|
||||
}
|
||||
wa.u.wireaddr.type = ADDR_TYPE_IPV4;
|
||||
wa.u.wireaddr.addrlen = 4;
|
||||
/* OK if this fails, as long as one succeeds! */
|
||||
handle_wireaddr_listen(daemon, &wa, ipv6_ok);
|
||||
if (handle_wireaddr_listen(daemon, &wa.u.wireaddr,
|
||||
ipv6_ok)) {
|
||||
add_binding(&binding, &wa);
|
||||
if (public_address(&wa.u.wireaddr))
|
||||
add_announcable(daemon, &wa.u.wireaddr);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case ADDR_INTERNAL_WIREADDR:
|
||||
handle_wireaddr_listen(daemon, &wa, false);
|
||||
handle_wireaddr_listen(daemon, &wa.u.wireaddr, false);
|
||||
add_binding(&binding, &wa);
|
||||
if (public_address(&wa.u.wireaddr))
|
||||
add_announcable(daemon, &wa.u.wireaddr);
|
||||
continue;
|
||||
}
|
||||
/* Shouldn't happen. */
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"Invalid listener address type %u",
|
||||
daemon->wireaddrs[i].itype);
|
||||
daemon->proposed_wireaddr[i].itype);
|
||||
}
|
||||
|
||||
return binding;
|
||||
}
|
||||
|
||||
/* Parse an incoming gossip init message and assign config variables
|
||||
|
@ -1667,8 +1727,8 @@ static struct io_plan *gossip_init(struct daemon_conn *master,
|
|||
if (!fromwire_gossipctl_init(
|
||||
daemon, msg, &daemon->broadcast_interval, &chain_hash,
|
||||
&daemon->id, &daemon->globalfeatures,
|
||||
&daemon->localfeatures, &daemon->wireaddrs,
|
||||
&daemon->listen_announce, daemon->rgb,
|
||||
&daemon->localfeatures, &daemon->proposed_wireaddr,
|
||||
&daemon->proposed_listen_announce, daemon->rgb,
|
||||
daemon->alias, &update_channel_interval, &daemon->reconnect)) {
|
||||
master_badmsg(WIRE_GOSSIPCTL_INIT, msg);
|
||||
}
|
||||
|
@ -1691,18 +1751,21 @@ static struct io_plan *gossip_activate(struct daemon_conn *master,
|
|||
const u8 *msg)
|
||||
{
|
||||
bool listen;
|
||||
struct wireaddr_internal *binding;
|
||||
|
||||
if (!fromwire_gossipctl_activate(msg, &listen))
|
||||
master_badmsg(WIRE_GOSSIPCTL_ACTIVATE, msg);
|
||||
|
||||
if (listen)
|
||||
setup_listeners(daemon);
|
||||
binding = setup_listeners(tmpctx, daemon);
|
||||
else
|
||||
binding = NULL;
|
||||
|
||||
/* OK, we're ready! */
|
||||
daemon_conn_send(&daemon->master,
|
||||
take(towire_gossipctl_activate_reply(NULL,
|
||||
daemon->wireaddrs,
|
||||
daemon->listen_announce)));
|
||||
binding,
|
||||
daemon->announcable)));
|
||||
|
||||
return daemon_conn_read_next(master->conn, master);
|
||||
}
|
||||
|
|
|
@ -24,11 +24,12 @@ gossipctl_activate,3025
|
|||
# Do we listen?
|
||||
gossipctl_activate,,listen,bool
|
||||
|
||||
# Gossipd->master, I am ready, here are the final addresses.
|
||||
# Gossipd->master, I am ready, here's the addresses I bound, can announce.
|
||||
gossipctl_activate_reply,3125
|
||||
gossipctl_activate_reply,,num_wireaddrs,u16
|
||||
gossipctl_activate_reply,,wireaddrs,num_wireaddrs*struct wireaddr_internal
|
||||
gossipctl_activate_reply,,listen_announce,num_wireaddrs*enum addr_listen_announce
|
||||
gossipctl_activate_reply,,num_bindings,u16
|
||||
gossipctl_activate_reply,,bindings,num_bindings*struct wireaddr_internal
|
||||
gossipctl_activate_reply,,num_announcable,u16
|
||||
gossipctl_activate_reply,,announcable,num_announcable*struct wireaddr
|
||||
|
||||
# Master -> gossipd: Optional hint for where to find peer.
|
||||
gossipctl_peer_addrhint,3014
|
||||
|
|
|
|
@ -201,48 +201,39 @@ static bool IsRoutable(const struct wireaddr *addr)
|
|||
* then query address. */
|
||||
/* Returns 0 if protocol completely unsupported, ADDR_LISTEN if we
|
||||
* can't reach addr, ADDR_LISTEN_AND_ANNOUNCE if we can (and fill saddr). */
|
||||
static enum addr_listen_announce get_local_sockname(int af, void *saddr,
|
||||
socklen_t saddrlen)
|
||||
static bool get_local_sockname(int af, void *saddr, socklen_t saddrlen)
|
||||
{
|
||||
int fd = socket(af, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
status_trace("Failed to create %u socket: %s",
|
||||
af, strerror(errno));
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (connect(fd, saddr, saddrlen) != 0) {
|
||||
status_trace("Failed to connect %u socket: %s",
|
||||
af, strerror(errno));
|
||||
close(fd);
|
||||
return ADDR_LISTEN;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getsockname(fd, saddr, &saddrlen) != 0) {
|
||||
status_trace("Failed to get %u socket name: %s",
|
||||
af, strerror(errno));
|
||||
close(fd);
|
||||
return ADDR_LISTEN;
|
||||
return false;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return ADDR_LISTEN_AND_ANNOUNCE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Return 0 if not available, or whether it's listenable-only or announceable.
|
||||
* If it's listenable only, will set wireaddr to all-zero address for universal
|
||||
* binding. */
|
||||
static enum addr_listen_announce guess_one_address(struct wireaddr *addr,
|
||||
u16 portnum,
|
||||
enum wire_addr_type type)
|
||||
bool guess_address(struct wireaddr *addr)
|
||||
{
|
||||
enum addr_listen_announce ret;
|
||||
|
||||
addr->type = type;
|
||||
addr->port = portnum;
|
||||
bool ret;
|
||||
|
||||
/* We point to Google nameservers, works unless you're inside Google :) */
|
||||
switch (type) {
|
||||
switch (addr->type) {
|
||||
case ADDR_TYPE_IPV4: {
|
||||
struct sockaddr_in sin;
|
||||
sin.sin_port = htons(53);
|
||||
|
@ -252,7 +243,7 @@ static enum addr_listen_announce guess_one_address(struct wireaddr *addr,
|
|||
ret = get_local_sockname(AF_INET, &sin, sizeof(sin));
|
||||
addr->addrlen = sizeof(sin.sin_addr);
|
||||
memcpy(addr->addr, &sin.sin_addr, addr->addrlen);
|
||||
break;
|
||||
return ret;
|
||||
}
|
||||
case ADDR_TYPE_IPV6: {
|
||||
struct sockaddr_in6 sin6;
|
||||
|
@ -266,59 +257,15 @@ static enum addr_listen_announce guess_one_address(struct wireaddr *addr,
|
|||
ret = get_local_sockname(AF_INET6, &sin6, sizeof(sin6));
|
||||
addr->addrlen = sizeof(sin6.sin6_addr);
|
||||
memcpy(addr->addr, &sin6.sin6_addr, addr->addrlen);
|
||||
break;
|
||||
return ret;
|
||||
}
|
||||
case ADDR_TYPE_PADDING:
|
||||
status_trace("Padding address, ignoring");
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
abort();
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
return ret;
|
||||
|
||||
/* If we can reach it, but resulting address is unroutable, listen only */
|
||||
if (ret == ADDR_LISTEN_AND_ANNOUNCE && !IsRoutable(addr)) {
|
||||
status_trace("Address %s is not routable",
|
||||
type_to_string(tmpctx, struct wireaddr, addr));
|
||||
ret = ADDR_LISTEN;
|
||||
}
|
||||
|
||||
if (ret == ADDR_LISTEN) {
|
||||
/* This corresponds to INADDR_ANY or in6addr_any */
|
||||
memset(addr->addr, 0, addr->addrlen);
|
||||
} else {
|
||||
status_trace("Public address %s",
|
||||
type_to_string(tmpctx, struct wireaddr, addr));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void guess_addresses(struct wireaddr_internal **wireaddrs,
|
||||
enum addr_listen_announce **listen_announce,
|
||||
u16 portnum)
|
||||
bool address_routable(const struct wireaddr *wireaddr)
|
||||
{
|
||||
size_t n = tal_count(*wireaddrs);
|
||||
|
||||
status_trace("Trying to guess public addresses...");
|
||||
|
||||
/* We allocate an extra, then remove if it's not needed. */
|
||||
tal_resize(wireaddrs, n+1);
|
||||
tal_resize(listen_announce, n+1);
|
||||
|
||||
(*wireaddrs)[n].itype = ADDR_INTERNAL_WIREADDR;
|
||||
/* We do IPv6 first: on Linux, that binds to IPv4 too. */
|
||||
(*listen_announce)[n] = guess_one_address(&(*wireaddrs)[n].u.wireaddr,
|
||||
portnum, ADDR_TYPE_IPV6);
|
||||
if ((*listen_announce)[n] != 0) {
|
||||
n++;
|
||||
tal_resize(wireaddrs, n+1);
|
||||
tal_resize(listen_announce, n+1);
|
||||
(*wireaddrs)[n].itype = ADDR_INTERNAL_WIREADDR;
|
||||
}
|
||||
(*listen_announce)[n] = guess_one_address(&(*wireaddrs)[n].u.wireaddr,
|
||||
portnum, ADDR_TYPE_IPV4);
|
||||
if ((*listen_announce)[n] == 0) {
|
||||
tal_resize(wireaddrs, n);
|
||||
tal_resize(listen_announce, n);
|
||||
}
|
||||
return IsRoutable(wireaddr);
|
||||
}
|
||||
|
|
|
@ -4,8 +4,10 @@
|
|||
#include <ccan/short_types/short_types.h>
|
||||
#include <common/wireaddr.h>
|
||||
|
||||
void guess_addresses(struct wireaddr_internal **wireaddrs,
|
||||
enum addr_listen_announce **listen_announce,
|
||||
u16 portnum);
|
||||
/* Address is a wildcard: try to guess what it looks like to outside world */
|
||||
bool guess_address(struct wireaddr *wireaddr);
|
||||
|
||||
/* Is this address public? */
|
||||
bool address_routable(const struct wireaddr *wireaddr);
|
||||
|
||||
#endif /* LIGHTNING_GOSSIPD_NETADDRESS_H */
|
||||
|
|
|
@ -183,8 +183,8 @@ void gossip_init(struct lightningd *ld)
|
|||
u8 *msg;
|
||||
int hsmfd;
|
||||
u64 capabilities = HSM_CAP_ECDH | HSM_CAP_SIGN_GOSSIP;
|
||||
struct wireaddr_internal *wireaddrs = ld->wireaddrs;
|
||||
enum addr_listen_announce *listen_announce = ld->listen_announce;
|
||||
struct wireaddr_internal *wireaddrs = ld->proposed_wireaddr;
|
||||
enum addr_listen_announce *listen_announce = ld->proposed_listen_announce;
|
||||
|
||||
msg = towire_hsm_client_hsmfd(tmpctx, &ld->id, capabilities);
|
||||
if (!wire_sync_write(ld->hsm_fd, msg))
|
||||
|
@ -230,12 +230,9 @@ static void gossip_activate_done(struct subd *gossip UNUSED,
|
|||
{
|
||||
struct lightningd *ld = gossip->ld;
|
||||
|
||||
/* Reply gives us the actual wireaddrs we're using */
|
||||
tal_free(ld->wireaddrs);
|
||||
tal_free(ld->listen_announce);
|
||||
if (!fromwire_gossipctl_activate_reply(gossip->ld, reply,
|
||||
&ld->wireaddrs,
|
||||
&ld->listen_announce))
|
||||
&ld->binding,
|
||||
&ld->announcable))
|
||||
fatal("Bad gossipctl_activate_reply: %s",
|
||||
tal_hex(reply, reply));
|
||||
|
||||
|
|
|
@ -150,31 +150,22 @@ static void json_getinfo(struct command *cmd,
|
|||
json_object_start(response, NULL);
|
||||
json_add_pubkey(response, "id", &cmd->ld->id);
|
||||
if (cmd->ld->listen) {
|
||||
bool have_listen_no_announce = false;
|
||||
if (deprecated_apis)
|
||||
json_add_num(response, "port", cmd->ld->portnum);
|
||||
|
||||
/* These are the addresses we're announcing */
|
||||
json_array_start(response, "address");
|
||||
for (size_t i = 0; i < tal_count(cmd->ld->wireaddrs); i++) {
|
||||
if (cmd->ld->listen_announce[i] & ADDR_ANNOUNCE)
|
||||
json_add_address_internal(response, NULL,
|
||||
cmd->ld->wireaddrs+i);
|
||||
else
|
||||
have_listen_no_announce = true;
|
||||
}
|
||||
for (size_t i = 0; i < tal_count(cmd->ld->announcable); i++)
|
||||
json_add_address(response, NULL, cmd->ld->announcable+i);
|
||||
json_array_end(response);
|
||||
|
||||
if (have_listen_no_announce) {
|
||||
json_array_start(response, "listen-only");
|
||||
for (size_t i = 0; i < tal_count(cmd->ld->wireaddrs); i++) {
|
||||
if (cmd->ld->listen_announce[i] == ADDR_LISTEN)
|
||||
/* This is what we're actually bound to. */
|
||||
json_array_start(response, "binding");
|
||||
for (size_t i = 0; i < tal_count(cmd->ld->binding); i++)
|
||||
json_add_address_internal(response, NULL,
|
||||
cmd->ld->wireaddrs+i);
|
||||
}
|
||||
cmd->ld->binding+i);
|
||||
json_array_end(response);
|
||||
}
|
||||
}
|
||||
json_add_string(response, "version", version());
|
||||
json_add_num(response, "blockheight", get_block_height(cmd->ld->topology));
|
||||
json_add_string(response, "network", get_chainparams(cmd->ld)->network_name);
|
||||
|
|
|
@ -69,8 +69,8 @@ static struct lightningd *new_lightningd(const tal_t *ctx)
|
|||
list_head_init(&ld->waitsendpay_commands);
|
||||
list_head_init(&ld->sendpay_commands);
|
||||
list_head_init(&ld->close_commands);
|
||||
ld->wireaddrs = tal_arr(ld, struct wireaddr_internal, 0);
|
||||
ld->listen_announce = tal_arr(ld, enum addr_listen_announce, 0);
|
||||
ld->proposed_wireaddr = tal_arr(ld, struct wireaddr_internal, 0);
|
||||
ld->proposed_listen_announce = tal_arr(ld, enum addr_listen_announce, 0);
|
||||
ld->portnum = DEFAULT_PORT;
|
||||
ld->listen = true;
|
||||
ld->autolisten = true;
|
||||
|
|
|
@ -120,10 +120,14 @@ struct lightningd {
|
|||
/* Do we want to guess addresses to listen and announce? */
|
||||
bool autolisten;
|
||||
|
||||
/* Addresses to bind/announce to the network (tal_count()) */
|
||||
struct wireaddr_internal *wireaddrs;
|
||||
/* And the bitset for each, whether to listen, announce or both */
|
||||
enum addr_listen_announce *listen_announce;
|
||||
/* Setup: Addresses to bind/announce to the network (tal_count()) */
|
||||
struct wireaddr_internal *proposed_wireaddr;
|
||||
/* Setup: And the bitset for each, whether to listen, announce or both */
|
||||
enum addr_listen_announce *proposed_listen_announce;
|
||||
|
||||
/* Actual bindings and announcables from gossipd */
|
||||
struct wireaddr_internal *binding;
|
||||
struct wireaddr *announcable;
|
||||
|
||||
/* Bearer of all my secrets. */
|
||||
int hsm_fd;
|
||||
|
|
|
@ -149,16 +149,16 @@ static char *opt_add_addr_withtype(const char *arg,
|
|||
struct lightningd *ld,
|
||||
enum addr_listen_announce ala)
|
||||
{
|
||||
size_t n = tal_count(ld->wireaddrs);
|
||||
size_t n = tal_count(ld->proposed_wireaddr);
|
||||
char const *err_msg;
|
||||
|
||||
assert(arg != NULL);
|
||||
|
||||
tal_resize(&ld->wireaddrs, n+1);
|
||||
tal_resize(&ld->listen_announce, n+1);
|
||||
ld->listen_announce[n] = ala;
|
||||
tal_resize(&ld->proposed_wireaddr, n+1);
|
||||
tal_resize(&ld->proposed_listen_announce, n+1);
|
||||
ld->proposed_listen_announce[n] = ala;
|
||||
|
||||
if (!parse_wireaddr_internal(arg, &ld->wireaddrs[n], ld->portnum,
|
||||
if (!parse_wireaddr_internal(arg, &ld->proposed_wireaddr[n], ld->portnum,
|
||||
true, &err_msg)) {
|
||||
return tal_fmt(NULL, "Unable to parse address '%s': %s", arg, err_msg);
|
||||
}
|
||||
|
@ -918,17 +918,20 @@ static void add_config(struct lightningd *ld,
|
|||
/* Covered by opt_add_addr below */
|
||||
} else if (opt->cb_arg == (void *)opt_add_addr) {
|
||||
json_add_opt_addrs(response, name0,
|
||||
ld->wireaddrs, ld->listen_announce,
|
||||
ld->proposed_wireaddr,
|
||||
ld->proposed_listen_announce,
|
||||
ADDR_LISTEN_AND_ANNOUNCE);
|
||||
return;
|
||||
} else if (opt->cb_arg == (void *)opt_add_bind_addr) {
|
||||
json_add_opt_addrs(response, name0,
|
||||
ld->wireaddrs, ld->listen_announce,
|
||||
ld->proposed_wireaddr,
|
||||
ld->proposed_listen_announce,
|
||||
ADDR_LISTEN);
|
||||
return;
|
||||
} else if (opt->cb_arg == (void *)opt_add_announce_addr) {
|
||||
json_add_opt_addrs(response, name0,
|
||||
ld->wireaddrs, ld->listen_announce,
|
||||
ld->proposed_wireaddr,
|
||||
ld->proposed_listen_announce,
|
||||
ADDR_ANNOUNCE);
|
||||
return;
|
||||
#if DEVELOPER
|
||||
|
|
|
@ -4283,10 +4283,17 @@ class LightningDTests(BaseLightningDTests):
|
|||
|
||||
def test_address(self):
|
||||
l1 = self.node_factory.get_node()
|
||||
assert len(l1.rpc.getinfo()['address']) == 1
|
||||
assert l1.rpc.getinfo()['address'][0]['type'] == 'ipv4'
|
||||
assert l1.rpc.getinfo()['address'][0]['address'] == '127.0.0.1'
|
||||
assert int(l1.rpc.getinfo()['address'][0]['port']) == l1.port
|
||||
addr = l1.rpc.getinfo()['address']
|
||||
assert len(addr) == 1
|
||||
assert addr[0]['type'] == 'ipv4'
|
||||
assert addr[0]['address'] == '127.0.0.1'
|
||||
assert int(addr[0]['port']) == l1.port
|
||||
|
||||
bind = l1.rpc.getinfo()['binding']
|
||||
assert len(bind) == 1
|
||||
assert bind[0]['type'] == 'ipv4'
|
||||
assert bind[0]['address'] == '127.0.0.1'
|
||||
assert int(bind[0]['port']) == l1.port
|
||||
|
||||
def test_listconfigs(self):
|
||||
l1 = self.node_factory.get_node()
|
||||
|
|
|
@ -261,7 +261,9 @@ class LightningD(TailableProc):
|
|||
opts = {
|
||||
'bitcoin-datadir': bitcoin_dir,
|
||||
'lightning-dir': lightning_dir,
|
||||
'addr': '127.0.0.1:{}'.format(port),
|
||||
'bind-addr': '127.0.0.1:{}'.format(port),
|
||||
# lightningd won't announce non-routable addresses by default.
|
||||
'announce-addr': '127.0.0.1:{}'.format(port),
|
||||
'allow-deprecated-apis': 'false',
|
||||
'override-fee-rates': '15000/7500/1000',
|
||||
'network': 'regtest',
|
||||
|
@ -370,7 +372,7 @@ class LightningNode(object):
|
|||
def start(self):
|
||||
self.daemon.start()
|
||||
# This shortcut is sufficient for our simple tests.
|
||||
self.port = self.rpc.getinfo()['address'][0]['port']
|
||||
self.port = self.rpc.getinfo()['binding'][0]['port']
|
||||
|
||||
def stop(self, timeout=10):
|
||||
""" Attempt to do a clean shutdown, but kill if it hangs
|
||||
|
|
Loading…
Reference in New Issue