diff --git a/gossipd/gossip.c b/gossipd/gossip.c index f42828fe1..7db101439 100644 --- a/gossipd/gossip.c +++ b/gossipd/gossip.c @@ -1915,6 +1915,20 @@ static struct io_plan *handle_routing_failure(struct io_conn *conn, return daemon_conn_read_next(conn, &daemon->master); } +static struct io_plan * +handle_mark_channel_unroutable(struct io_conn *conn, + struct daemon *daemon, + const u8 *msg) +{ + struct short_channel_id channel; + + if (!fromwire_gossip_mark_channel_unroutable(msg, NULL, &channel)) + master_badmsg(WIRE_GOSSIP_MARK_CHANNEL_UNROUTABLE, msg); + + mark_channel_unroutable(daemon->rstate, &channel); + + return daemon_conn_read_next(conn, &daemon->master); +} static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master) { @@ -1967,6 +1981,9 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master case WIRE_GOSSIP_ROUTING_FAILURE: return handle_routing_failure(conn, daemon, master->msg_in); + case WIRE_GOSSIP_MARK_CHANNEL_UNROUTABLE: + return handle_mark_channel_unroutable(conn, daemon, master->msg_in); + /* We send these, we don't receive them */ case WIRE_GOSSIPCTL_RELEASE_PEER_REPLY: case WIRE_GOSSIPCTL_RELEASE_PEER_REPLYFAIL: diff --git a/gossipd/gossip_wire.csv b/gossipd/gossip_wire.csv index 756953e9a..8f8d6f265 100644 --- a/gossipd/gossip_wire.csv +++ b/gossipd/gossip_wire.csv @@ -204,3 +204,8 @@ gossip_routing_failure,,erring_channel,struct short_channel_id gossip_routing_failure,,failcode,u16 gossip_routing_failure,,len,u16 gossip_routing_failure,,channel_update,len*u8 + +# master->gossipd temporarily mark a channel unroutable +# (used in case of unparseable onion reply) +gossip_mark_channel_unroutable,3022 +gossip_mark_channel_unroutable,,channel,struct short_channel_id diff --git a/gossipd/routing.c b/gossipd/routing.c index 719ddc548..d9452e9be 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -1289,3 +1289,32 @@ void routing_failure(struct routing_state *rstate, out: tal_free(tmpctx); } + +void mark_channel_unroutable(struct routing_state *rstate, + const struct short_channel_id *channel) +{ + const tal_t *tmpctx = tal_tmpctx(rstate); + struct routing_channel *chan; + time_t now = time_now().ts.tv_sec; + const char *scid = type_to_string(tmpctx, struct short_channel_id, + channel); + + status_trace("Received mark_channel_unroutable channel %s", + scid); + + chan = uintmap_get(&rstate->channels, + short_channel_id_to_uint(channel)); + + if (!chan) { + status_trace("UNUSUAL mark_channel_unroutable: " + "channel %s not in routemap", + scid); + tal_free(tmpctx); + return; + } + if (chan->connections[0]) + chan->connections[0]->unroutable_until = now + 20; + if (chan->connections[1]) + chan->connections[1]->unroutable_until = now + 20; + tal_free(tmpctx); +} diff --git a/gossipd/routing.h b/gossipd/routing.h index a709fa98c..214985a3b 100644 --- a/gossipd/routing.h +++ b/gossipd/routing.h @@ -193,6 +193,9 @@ void routing_failure(struct routing_state *rstate, const struct short_channel_id *erring_channel, enum onion_type failcode, const u8 *channel_update); +/* Disable specific channel from routing. */ +void mark_channel_unroutable(struct routing_state *rstate, + const struct short_channel_id *channel); /* routing_channel constructor */ struct routing_channel *routing_channel_new(const tal_t *ctx, diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index 9dd3228f3..300f6cb5a 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -111,6 +111,7 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) case WIRE_GOSSIP_GET_TXOUT_REPLY: case WIRE_GOSSIP_DISABLE_CHANNEL: case WIRE_GOSSIP_ROUTING_FAILURE: + case WIRE_GOSSIP_MARK_CHANNEL_UNROUTABLE: /* This is a reply, so never gets through to here. */ case WIRE_GOSSIP_GET_UPDATE_REPLY: case WIRE_GOSSIP_GETNODES_REPLY: