From f172be71dc9414907c62f0b414c433a1f240f7cf Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 11 Oct 2017 20:27:50 +1030 Subject: [PATCH] gossipd: fail peer for the master daemon. This fixes the only case where the master currently has to write directly to the peer: re-sending an error. We make gossipd do it, by adding a new gossipctl_fail_peer message. Signed-off-by: Rusty Russell --- gossipd/gossip.c | 65 ++++++++++++++++++++++++++++++++----- gossipd/gossip_wire.csv | 8 ++++- lightningd/Makefile | 1 - lightningd/gossip_control.c | 1 + lightningd/peer_control.c | 40 +++++------------------ 5 files changed, 73 insertions(+), 42 deletions(-) diff --git a/gossipd/gossip.c b/gossipd/gossip.c index 9e4314702..4bf10c9b0 100644 --- a/gossipd/gossip.c +++ b/gossipd/gossip.c @@ -99,14 +99,15 @@ static void destroy_peer(struct peer *peer) } } -static struct peer *setup_new_peer(struct daemon *daemon, const u8 *msg) +static struct peer *setup_new_peer(struct daemon *daemon, + u64 unique_id, + const struct crypto_state *cs) { struct peer *peer = tal(daemon, struct peer); init_peer_crypto_state(peer, &peer->pcs); - if (!fromwire_gossipctl_new_peer(msg, NULL, &peer->unique_id, - &peer->pcs.cs)) - return tal_free(peer); + peer->pcs.cs = *cs; + peer->unique_id = unique_id; peer->daemon = daemon; peer->error = NULL; peer->local = true; @@ -115,6 +116,7 @@ static struct peer *setup_new_peer(struct daemon *daemon, const u8 *msg) msg_queue_init(&peer->peer_out, peer); list_add_tail(&daemon->peers, &peer->list); tal_add_destructor(peer, destroy_peer); + wake_pkt_out(peer); return peer; } @@ -416,10 +418,14 @@ static struct io_plan *new_peer_got_fd(struct io_conn *conn, struct peer *peer) static struct io_plan *new_peer(struct io_conn *conn, struct daemon *daemon, const u8 *msg) { - struct peer *peer = setup_new_peer(daemon, msg); - if (!peer) - status_failed(STATUS_FAIL_MASTER_IO, - "bad gossipctl_new_peer: %s", tal_hex(trc, msg)); + struct peer *peer; + struct crypto_state cs; + u64 unique_id; + + if (!fromwire_gossipctl_new_peer(msg, NULL, &unique_id, &cs)) + master_badmsg(WIRE_GOSSIPCTL_NEW_PEER, msg); + + peer = setup_new_peer(daemon, unique_id, &cs); return io_recv_fd(conn, &peer->fd, new_peer_got_fd, peer); } @@ -433,6 +439,45 @@ static struct peer *find_peer(struct daemon *daemon, u64 unique_id) return NULL; } +/* We send error, then close. */ +static struct io_plan *peer_send_error(struct io_conn *conn, struct peer *peer) +{ + const u8 *out = msg_dequeue(&peer->peer_out); + return peer_write_message(conn, &peer->pcs, take(out), + (void *)io_close_cb); +} + +static struct io_plan *fail_peer_got_fd(struct io_conn *conn, struct peer *peer) +{ + peer->conn = io_new_conn(conn, peer->fd, peer_send_error, peer); + if (!peer->conn) { + peer->error = "Could not create connection"; + tal_free(peer); + } else { + /* If conn dies, we forget peer. */ + tal_steal(peer->conn, peer); + } + return daemon_conn_read_next(conn, &peer->daemon->master); +} + +static struct io_plan *fail_peer(struct io_conn *conn, struct daemon *daemon, + const u8 *msg) +{ + struct peer *peer; + struct crypto_state cs; + u64 unique_id; + u8 *failmsg; + + if (!fromwire_gossipctl_fail_peer(msg, msg, NULL, &unique_id, &cs, + &failmsg)) + master_badmsg(WIRE_GOSSIPCTL_FAIL_PEER, msg); + + peer = setup_new_peer(daemon, unique_id, &cs); + msg_enqueue(&peer->peer_out, take(failmsg)); + + return io_recv_fd(conn, &peer->fd, fail_peer_got_fd, peer); +} + static struct io_plan *release_peer(struct io_conn *conn, struct daemon *daemon, const u8 *msg) { @@ -742,6 +787,10 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master case WIRE_GOSSIP_FORWARDED_MSG: handle_forwarded_msg(conn, daemon, daemon->master.msg_in); return daemon_conn_read_next(conn, &daemon->master); + + case WIRE_GOSSIPCTL_FAIL_PEER: + return fail_peer(conn, daemon, master->msg_in); + case WIRE_GOSSIPCTL_RELEASE_PEER_REPLY: case WIRE_GOSSIPCTL_RELEASE_PEER_REPLYFAIL: case WIRE_GOSSIPCTL_GET_PEER_GOSSIPFD_REPLY: diff --git a/gossipd/gossip_wire.csv b/gossipd/gossip_wire.csv index 7cd398080..3d77b4a97 100644 --- a/gossipd/gossip_wire.csv +++ b/gossipd/gossip_wire.csv @@ -18,7 +18,6 @@ gossipctl_init,,broadcast_interval,u32 gossipctl_init,,chain_hash,struct sha256_double # These take an fd, but have no response -# (if it is to move onto a channel, we get a status msg). gossipctl_new_peer,3001 gossipctl_new_peer,,unique_id,u64 gossipctl_new_peer,,crypto_state,struct crypto_state @@ -112,3 +111,10 @@ gossipctl_get_peer_gossipfd_reply,3112 # Failure (can't make new socket) gossipctl_get_peer_gossipfd_replyfail,3212 + +# Send canned message to peer and fail it. +gossipctl_fail_peer,3013 +gossipctl_fail_peer,,unique_id,u64 +gossipctl_fail_peer,,crypto_state,struct crypto_state +gossipctl_fail_peer,,len,u16 +gossipctl_fail_peer,,failmsg,len*u8 diff --git a/lightningd/Makefile b/lightningd/Makefile index af9712c2b..b36eb0ff5 100644 --- a/lightningd/Makefile +++ b/lightningd/Makefile @@ -18,7 +18,6 @@ LIGHTNINGD_COMMON_OBJS := \ common/channel_config.o \ common/configdir.o \ common/crypto_state.o \ - common/cryptomsg.o \ common/derive_basepoints.o \ common/funding_tx.o \ common/htlc_state.o \ diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index f5d6cddcb..90e1410d1 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -95,6 +95,7 @@ static int gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) /* These are messages we send, not them. */ case WIRE_GOSSIPCTL_INIT: case WIRE_GOSSIPCTL_NEW_PEER: + case WIRE_GOSSIPCTL_FAIL_PEER: case WIRE_GOSSIPCTL_RELEASE_PEER: case WIRE_GOSSIPCTL_DROP_PEER: case WIRE_GOSSIPCTL_GET_PEER_GOSSIPFD: diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 5d1ea5cee..d49bc2ca9 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -262,34 +262,6 @@ static void peer_start_closingd(struct peer *peer, int peer_fd, int gossip_fd, bool reconnected); -/* FIXME: Fake NOP dev_disconnect/dev_sabotage_fd for below. */ -enum dev_disconnect dev_disconnect(int pkt_type) -{ - return DEV_DISCONNECT_NORMAL; -} - -void dev_sabotage_fd(int fd) -{ - abort(); -} - -void dev_blackhole_fd(int fd) -{ - abort(); -} - -/* Send (encrypted) error message, then close. */ -static struct io_plan *send_error(struct io_conn *conn, - struct peer_crypto_state *pcs) -{ - log_debug(pcs->peer->log, "Sending canned error"); - /* FIXME: This is the only place where master talks directly to peer; - * and pulls in quite a lot of code to do so. If we got a subdaemon - * to do this work, we'd avoid pulling in cryptomsg.o and the fake - * dev_disconnect. */ - return peer_write_message(conn, pcs, pcs->peer->error, (void *)io_close_cb); -} - /* FIXME: * * This is a lot of code duplication! We should turn gossipd into welcomed(?): @@ -483,10 +455,14 @@ static bool peer_reconnected(struct lightningd *ld, * retransmit the error packet and ignore any other packets for that * channel, and the following requirements do not apply. */ if (peer->error) { - struct peer_crypto_state *pcs = tal(peer, struct peer_crypto_state); - init_peer_crypto_state(peer, pcs); - pcs->cs = *cs; - tal_steal(io_new_conn(peer, fd, send_error, pcs), pcs); + /* FIXME: we should do this in response to reestablish, unless + * global error */ + log_debug(peer->log, "Sending canned error"); + subd_send_msg(peer->ld->gossip, + take(towire_gossipctl_fail_peer(peer, + peer->unique_id, + cs, peer->error))); + subd_send_fd(peer->ld->gossip, fd); return true; }