diff --git a/gossipd/gossip.c b/gossipd/gossip.c index 750281ed3..19dc43fbf 100644 --- a/gossipd/gossip.c +++ b/gossipd/gossip.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -81,6 +82,9 @@ struct reaching { /* The ID of the peer (not necessarily unique, in transit!) */ struct pubkey id; + /* Where I'm reaching to. */ + struct ipaddr addr; + /* Did we succeed? */ bool succeeded; }; @@ -94,6 +98,9 @@ struct peer { /* The ID of the peer (not necessarily unique, in transit!) */ struct pubkey id; + /* Where it's connected to. */ + struct ipaddr addr; + /* Feature bitmaps. */ u8 *gfeatures, *lfeatures; @@ -332,6 +339,7 @@ static struct io_plan *read_init(struct io_conn *conn, struct peer *peer) * we have the features. */ static struct io_plan *init_new_peer(struct io_conn *conn, const struct pubkey *their_id, + const struct ipaddr *addr, const struct crypto_state *cs, struct daemon *daemon) { @@ -339,6 +347,7 @@ static struct io_plan *init_new_peer(struct io_conn *conn, u8 *initmsg; peer->fd = io_conn_fd(conn); + peer->addr = *addr; /* BOLT #1: * @@ -935,8 +944,38 @@ fail: static struct io_plan *connection_in(struct io_conn *conn, struct daemon *daemon) { + struct ipaddr addr; + struct sockaddr_storage s; + socklen_t len = sizeof(s); + + if (getpeername(io_conn_fd(conn), (struct sockaddr *)&s, &len) != 0) { + status_trace("Failed to get peername for incoming conn"); + return io_close(conn); + } + + if (s.ss_family == AF_INET6) { + struct sockaddr_in6 *s6 = (void *)&s; + addr.type = ADDR_TYPE_IPV6; + addr.addrlen = sizeof(s6->sin6_addr); + BUILD_ASSERT(sizeof(s6->sin6_addr) <= sizeof(addr.addr)); + memcpy(addr.addr, &s6->sin6_addr, addr.addrlen); + addr.port = ntohs(s6->sin6_port); + } else if (s.ss_family == AF_INET) { + struct sockaddr_in *s4 = (void *)&s; + addr.type = ADDR_TYPE_IPV4; + addr.addrlen = sizeof(s4->sin_addr); + BUILD_ASSERT(sizeof(s4->sin_addr) <= sizeof(addr.addr)); + memcpy(addr.addr, &s4->sin_addr, addr.addrlen); + addr.port = ntohs(s4->sin_port); + } else { + status_trace("Unknown socket type %i for incoming conn", + s.ss_family); + return io_close(conn); + } + /* FIXME: Timeout */ - return responder_handshake(conn, &daemon->id, init_new_peer, daemon); + return responder_handshake(conn, &daemon->id, &addr, + init_new_peer, daemon); } static void setup_listeners(struct daemon *daemon, u16 portnum) @@ -1068,10 +1107,11 @@ static void handle_forwarded_msg(struct io_conn *conn, struct daemon *daemon, co static struct io_plan *handshake_out_success(struct io_conn *conn, const struct pubkey *id, + const struct ipaddr *addr, const struct crypto_state *cs, struct reaching *reach) { - return init_new_peer(conn, id, cs, reach->daemon); + return init_new_peer(conn, id, addr, cs, reach->daemon); } @@ -1083,6 +1123,7 @@ static struct io_plan *connection_out(struct io_conn *conn, type_to_string(trc, struct pubkey, &reach->id)); return initiator_handshake(conn, &reach->daemon->id, &reach->id, + &reach->addr, handshake_out_success, reach); } @@ -1099,14 +1140,8 @@ static void connect_failed(struct io_conn *conn, struct reaching *reach) try_connect, reach); } -struct reach_addr { - struct reaching *reach; - struct ipaddr addr; -}; - -static struct io_plan *conn_init(struct io_conn *conn, struct reach_addr *r) +static struct io_plan *conn_init(struct io_conn *conn, struct reaching *reach) { - struct reaching *reach = r->reach; struct addrinfo ai; struct sockaddr_in sin; struct sockaddr_in6 sin6; @@ -1118,12 +1153,12 @@ static struct io_plan *conn_init(struct io_conn *conn, struct reach_addr *r) ai.ai_canonname = NULL; ai.ai_next = NULL; - switch (r->addr.type) { + switch (reach->addr.type) { case ADDR_TYPE_IPV4: ai.ai_family = AF_INET; sin.sin_family = AF_INET; - sin.sin_port = htons(r->addr.port); - memcpy(&sin.sin_addr, r->addr.addr, sizeof(sin.sin_addr)); + sin.sin_port = htons(reach->addr.port); + memcpy(&sin.sin_addr, reach->addr.addr, sizeof(sin.sin_addr)); ai.ai_addrlen = sizeof(sin); ai.ai_addr = (struct sockaddr *)&sin; break; @@ -1131,8 +1166,8 @@ static struct io_plan *conn_init(struct io_conn *conn, struct reach_addr *r) ai.ai_family = AF_INET6; memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6; - sin6.sin6_port = htons(r->addr.port); - memcpy(&sin6.sin6_addr, r->addr.addr, sizeof(sin6.sin6_addr)); + sin6.sin6_port = htons(reach->addr.port); + memcpy(&sin6.sin6_addr, reach->addr.addr, sizeof(sin6.sin6_addr)); ai.ai_addrlen = sizeof(sin6); ai.ai_addr = (struct sockaddr *)&sin6; break; @@ -1148,7 +1183,6 @@ static struct io_plan *conn_init(struct io_conn *conn, struct reach_addr *r) static void try_connect(struct reaching *reach) { struct addrhint *a; - struct reach_addr r; int fd; /* Already succeeded somehow? */ @@ -1192,9 +1226,8 @@ static void try_connect(struct reaching *reach) return; } - r.reach = reach; - r.addr = a->addr; - io_new_conn(reach, fd, conn_init, &r); + reach->addr = a->addr; + io_new_conn(reach, fd, conn_init, reach); } static void try_reach_peer(struct daemon *daemon, const struct pubkey *id) diff --git a/gossipd/handshake.c b/gossipd/handshake.c index 247a2ceda..7cefb2df9 100644 --- a/gossipd/handshake.c +++ b/gossipd/handshake.c @@ -19,6 +19,7 @@ #include #include #include +#include #define HSM_FD 3 @@ -169,6 +170,9 @@ struct handshake { struct act_two act2; struct act_three act3; + /* Where is connection from/to */ + struct ipaddr addr; + /* Who we are */ struct pubkey my_id; /* Who they are: set already if we're initiator. */ @@ -180,6 +184,7 @@ struct handshake { /* Function to call once handshake complete. */ struct io_plan *(*cb)(struct io_conn *conn, const struct pubkey *their_id, + const struct ipaddr *ipaddr, const struct crypto_state *cs, void *cbarg); void *cbarg; @@ -348,10 +353,12 @@ static struct io_plan *handshake_succeeded(struct io_conn *conn, struct crypto_state cs; struct io_plan *(*cb)(struct io_conn *conn, const struct pubkey *their_id, + const struct ipaddr *addr, const struct crypto_state *cs, void *cbarg); void *cbarg; struct pubkey their_id; + struct ipaddr addr; /* BOLT #8: * @@ -376,9 +383,10 @@ static struct io_plan *handshake_succeeded(struct io_conn *conn, cb = h->cb; cbarg = h->cbarg; their_id = h->their_id; + addr = h->addr; tal_free(h); - return cb(conn, &their_id, &cs, cbarg); + return cb(conn, &their_id, &addr, &cs, cbarg); } static struct handshake *new_handshake(const tal_t *ctx, @@ -953,8 +961,10 @@ static struct io_plan *act_one_responder(struct io_conn *conn, struct io_plan *responder_handshake_(struct io_conn *conn, const struct pubkey *my_id, + const struct ipaddr *addr, struct io_plan *(*cb)(struct io_conn *, const struct pubkey *, + const struct ipaddr *, const struct crypto_state *, void *cbarg), void *cbarg) @@ -963,6 +973,7 @@ struct io_plan *responder_handshake_(struct io_conn *conn, h->side = RESPONDER; h->my_id = *my_id; + h->addr = *addr; h->cbarg = cbarg; h->cb = cb; @@ -972,8 +983,10 @@ struct io_plan *responder_handshake_(struct io_conn *conn, struct io_plan *initiator_handshake_(struct io_conn *conn, const struct pubkey *my_id, const struct pubkey *their_id, + const struct ipaddr *addr, struct io_plan *(*cb)(struct io_conn *, const struct pubkey *, + const struct ipaddr *, const struct crypto_state *, void *cbarg), void *cbarg) @@ -983,6 +996,7 @@ struct io_plan *initiator_handshake_(struct io_conn *conn, h->side = INITIATOR; h->my_id = *my_id; h->their_id = *their_id; + h->addr = *addr; h->cbarg = cbarg; h->cb = cb; diff --git a/gossipd/handshake.h b/gossipd/handshake.h index 41167ae73..343dc501b 100644 --- a/gossipd/handshake.h +++ b/gossipd/handshake.h @@ -5,14 +5,16 @@ struct crypto_state; struct io_conn; +struct ipaddr; struct pubkey; -#define initiator_handshake(conn, my_id, their_id, cb, cbarg) \ - initiator_handshake_((conn), (my_id), (their_id), \ +#define initiator_handshake(conn, my_id, their_id, addr, cb, cbarg) \ + initiator_handshake_((conn), (my_id), (their_id), (addr), \ typesafe_cb_preargs(struct io_plan *, void *, \ (cb), (cbarg), \ struct io_conn *, \ const struct pubkey *, \ + const struct ipaddr *, \ const struct crypto_state *), \ (cbarg)) @@ -20,26 +22,31 @@ struct pubkey; struct io_plan *initiator_handshake_(struct io_conn *conn, const struct pubkey *my_id, const struct pubkey *their_id, + const struct ipaddr *addr, struct io_plan *(*cb)(struct io_conn *, const struct pubkey *, + const struct ipaddr *, const struct crypto_state *, void *cbarg), void *cbarg); -#define responder_handshake(conn, my_id, cb, cbarg) \ - responder_handshake_((conn), (my_id), \ +#define responder_handshake(conn, my_id, addr, cb, cbarg) \ + responder_handshake_((conn), (my_id), (addr), \ typesafe_cb_preargs(struct io_plan *, void *, \ (cb), (cbarg), \ struct io_conn *, \ const struct pubkey *, \ + const struct ipaddr *, \ const struct crypto_state *), \ (cbarg)) struct io_plan *responder_handshake_(struct io_conn *conn, const struct pubkey *my_id, + const struct ipaddr *addr, struct io_plan *(*cb)(struct io_conn *, const struct pubkey *, + const struct ipaddr *, const struct crypto_state *, void *cbarg), void *cbarg); diff --git a/gossipd/test/run-initiator-success.c b/gossipd/test/run-initiator-success.c index 7bb32eb0d..8f87df896 100644 --- a/gossipd/test/run-initiator-success.c +++ b/gossipd/test/run-initiator-success.c @@ -176,6 +176,7 @@ static struct io_plan *test_read(struct io_conn *conn, static struct io_plan *success(struct io_conn *conn, const struct pubkey *them, + const struct ipaddr *addr, const struct crypto_state *cs, void *ctx) { @@ -199,6 +200,7 @@ bool hsm_do_ecdh(struct secret *ss, const struct pubkey *point) int main(void) { tal_t *ctx = tal_tmpctx(NULL); + struct ipaddr dummy; trc = tal_tmpctx(ctx); @@ -221,7 +223,7 @@ int main(void) e_priv = privkey("1212121212121212121212121212121212121212121212121212121212121212"); e_pub = pubkey("036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f7"); - initiator_handshake(ctx, &ls_pub, &rs_pub, success, ctx); + initiator_handshake(ctx, &ls_pub, &rs_pub, &dummy, success, ctx); /* Should not exit! */ abort(); } diff --git a/gossipd/test/run-responder-success.c b/gossipd/test/run-responder-success.c index e50816803..ab3799d98 100644 --- a/gossipd/test/run-responder-success.c +++ b/gossipd/test/run-responder-success.c @@ -176,6 +176,7 @@ static struct io_plan *test_read(struct io_conn *conn, static struct io_plan *success(struct io_conn *conn, const struct pubkey *them, + const struct ipaddr *addr, const struct crypto_state *cs, void *ctx) { @@ -197,6 +198,7 @@ bool hsm_do_ecdh(struct secret *ss, const struct pubkey *point) int main(void) { tal_t *ctx = tal_tmpctx(NULL); + struct ipaddr dummy; trc = tal_tmpctx(ctx); @@ -217,7 +219,7 @@ int main(void) e_priv = privkey("2222222222222222222222222222222222222222222222222222222222222222"); e_pub = pubkey("02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27"); - responder_handshake(ctx, &ls_pub, success, ctx); + responder_handshake(ctx, &ls_pub, &dummy, success, ctx); /* Should not exit! */ abort(); }