diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 440a34694..d047650e4 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -203,6 +203,9 @@ static struct lightningd *new_lightningd(const tal_t *ctx) * NULL. So we start with a zero-length array. */ ld->proposed_wireaddr = tal_arr(ld, struct wireaddr_internal, 0); ld->proposed_listen_announce = tal_arr(ld, enum addr_listen_announce, 0); + + ld->remote_addr_v4 = NULL; + ld->remote_addr_v6 = NULL; ld->listen = true; ld->autolisten = true; ld->reconnect = true; diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index 5573a9470..c5150146c 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -148,6 +148,12 @@ struct lightningd { struct wireaddr_internal *binding; struct wireaddr *announceable; + /* unverified remote_addr as reported by recent peers */ + struct wireaddr *remote_addr_v4; + struct wireaddr *remote_addr_v6; + struct node_id remote_addr_v4_peer; + struct node_id remote_addr_v6_peer; + /* Bearer of all my secrets. */ int hsm_fd; struct subd *hsm; diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 45fa36dec..e53c6db56 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1109,6 +1109,53 @@ peer_connected_hook_deserialize(struct peer_connected_hook_payload *payload, return true; } +/* Compare and store `remote_addr` and the `peer_id` that reported it. + * If new address was reported by at least one other, do node_announcement */ +static void update_remote_addr(struct lightningd *ld, + const struct wireaddr *remote_addr, + const struct node_id peer_id) +{ + switch (remote_addr->type) { + case ADDR_TYPE_IPV4: + /* init pointers first time */ + if (ld->remote_addr_v4 == NULL) { + ld->remote_addr_v4 = tal_dup(ld, struct wireaddr, + remote_addr); + ld->remote_addr_v4_peer = peer_id; + } + /* if updated by the same peer just remember the latest addr */ + if (node_id_eq(&ld->remote_addr_v4_peer, &peer_id)) { + *ld->remote_addr_v4 = *remote_addr; + break; + } + /* store latest values */ + *ld->remote_addr_v4 = *remote_addr; + ld->remote_addr_v4_peer = peer_id; + break; + case ADDR_TYPE_IPV6: + /* same code :s/4/6/ without the comments ;) */ + if (ld->remote_addr_v6 == NULL) { + ld->remote_addr_v6 = tal_dup(ld, struct wireaddr, + remote_addr); + ld->remote_addr_v6_peer = peer_id; + } + if (node_id_eq(&ld->remote_addr_v6_peer, &peer_id)) { + *ld->remote_addr_v6 = *remote_addr; + break; + } + *ld->remote_addr_v6 = *remote_addr; + ld->remote_addr_v6_peer = peer_id; + break; + + /* ignore all other cases */ + case ADDR_TYPE_TOR_V2_REMOVED: + case ADDR_TYPE_TOR_V3: + case ADDR_TYPE_DNS: + case ADDR_TYPE_WEBSOCKET: + break; + } +} + REGISTER_PLUGIN_HOOK(peer_connected, peer_connected_hook_deserialize, peer_connected_hook_final, @@ -1160,12 +1207,14 @@ void peer_connected(struct lightningd *ld, const u8 *msg, int peer_fd) if (!hook_payload->channel) hook_payload->channel = peer_unsaved_channel(peer); - /* Log remote_addr for now */ - if (hook_payload->remote_addr && ( - hook_payload->remote_addr->type == ADDR_TYPE_IPV4 || - hook_payload->remote_addr->type == ADDR_TYPE_IPV6)) { + /* Log and update remote_addr for Nat/IP discovery. */ + if (hook_payload->remote_addr) { log_info(ld->log, "Peer says it sees our address as: %s", fmt_wireaddr(tmpctx, hook_payload->remote_addr)); + /* Currently only from peers we have a channel with, until we + * do stuff like probing for remote_addr to a random node. */ + if (hook_payload->channel) + update_remote_addr(ld, hook_payload->remote_addr, id); } plugin_hook_call_peer_connected(ld, hook_payload);