diff --git a/gossipd/gossip.c b/gossipd/gossip.c index 439ce8253..76a647003 100644 --- a/gossipd/gossip.c +++ b/gossipd/gossip.c @@ -1890,17 +1890,21 @@ static struct io_plan *handle_routing_failure(struct io_conn *conn, struct pubkey erring_node; struct short_channel_id erring_channel; u16 failcode; + u8 *channel_update; - if (!fromwire_gossip_routing_failure(msg, NULL, + if (!fromwire_gossip_routing_failure(msg, + msg, NULL, &erring_node, &erring_channel, - &failcode)) + &failcode, + &channel_update)) master_badmsg(WIRE_GOSSIP_ROUTING_FAILURE, msg); routing_failure(daemon->rstate, &erring_node, &erring_channel, - (enum onion_type) failcode); + (enum onion_type) failcode, + channel_update); return daemon_conn_read_next(conn, &daemon->master); } diff --git a/gossipd/gossip_wire.csv b/gossipd/gossip_wire.csv index e6c35ee22..756953e9a 100644 --- a/gossipd/gossip_wire.csv +++ b/gossipd/gossip_wire.csv @@ -202,3 +202,5 @@ gossip_routing_failure,3021 gossip_routing_failure,,erring_node,struct pubkey 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 diff --git a/gossipd/routing.c b/gossipd/routing.c index 08e6bd615..f9d45ea15 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -1054,12 +1054,14 @@ static void routing_failure_on_nc(struct routing_state *rstate, void routing_failure(struct routing_state *rstate, const struct pubkey *erring_node_pubkey, const struct short_channel_id *scid, - enum onion_type failcode) + enum onion_type failcode, + const u8 *channel_update) { const tal_t *tmpctx = tal_tmpctx(rstate); struct node *node; struct node_connection *nc; int i; + enum wire_type t; status_trace("Received routing failure 0x%04x (%s), " "erring node %s, " @@ -1106,7 +1108,35 @@ void routing_failure(struct routing_state *rstate, erring_node_pubkey)); } - /* FIXME: if UPDATE is set, apply the channel update. */ + /* Update the channel if UPDATE failcode. Do + * this after deactivating, so that if the + * channel_update is newer it will be + * reactivated. */ + if (failcode & UPDATE) { + if (tal_len(channel_update) == 0) { + status_trace("UNUSUAL routing_failure: " + "UPDATE bit set, no channel_update. " + "failcode: 0x%04x", + (int) failcode); + goto out; + } + t = fromwire_peektype(channel_update); + if (t != WIRE_CHANNEL_UPDATE) { + status_trace("UNUSUAL routing_failure: " + "not a channel_update. " + "type: %d", + (int) t); + goto out; + } + handle_channel_update(rstate, channel_update); + } else { + if (tal_len(channel_update) != 0) + status_trace("UNUSUAL routing_failure: " + "UPDATE bit clear, channel_update given. " + "failcode: 0x%04x", + (int) failcode); + } + out: tal_free(tmpctx); } diff --git a/gossipd/routing.h b/gossipd/routing.h index aa5a74ce4..68d590bfa 100644 --- a/gossipd/routing.h +++ b/gossipd/routing.h @@ -153,7 +153,8 @@ struct route_hop *get_route(tal_t *ctx, struct routing_state *rstate, void routing_failure(struct routing_state *rstate, const struct pubkey *erring_node, const struct short_channel_id *erring_channel, - enum onion_type failcode); + enum onion_type failcode, + const u8 *channel_update); /* Utility function that, given a source and a destination, gives us * the direction bit the matching channel should get */ diff --git a/gossipd/test/run-bench-find_route.c b/gossipd/test/run-bench-find_route.c index 05b70001f..9be41701e 100644 --- a/gossipd/test/run-bench-find_route.c +++ b/gossipd/test/run-bench-find_route.c @@ -57,6 +57,9 @@ bool fromwire_channel_update(const void *p UNNEEDED, size_t *plen UNNEEDED, secp /* Generated stub for fromwire_node_announcement */ bool fromwire_node_announcement(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, u8 **features UNNEEDED, u32 *timestamp UNNEEDED, struct pubkey *node_id UNNEEDED, u8 rgb_color[3] UNNEEDED, u8 alias[32] UNNEEDED, u8 **addresses UNNEEDED) { fprintf(stderr, "fromwire_node_announcement called!\n"); abort(); } +/* Generated stub for fromwire_peektype */ +int fromwire_peektype(const u8 *cursor UNNEEDED) +{ fprintf(stderr, "fromwire_peektype called!\n"); abort(); } /* Generated stub for fromwire_u8 */ u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_u8 called!\n"); abort(); } diff --git a/gossipd/test/run-find_route-specific.c b/gossipd/test/run-find_route-specific.c index 837c843ff..29c89485f 100644 --- a/gossipd/test/run-find_route-specific.c +++ b/gossipd/test/run-find_route-specific.c @@ -28,6 +28,9 @@ bool fromwire_channel_update(const void *p UNNEEDED, size_t *plen UNNEEDED, secp /* Generated stub for fromwire_node_announcement */ bool fromwire_node_announcement(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, u8 **features UNNEEDED, u32 *timestamp UNNEEDED, struct pubkey *node_id UNNEEDED, u8 rgb_color[3] UNNEEDED, u8 alias[32] UNNEEDED, u8 **addresses UNNEEDED) { fprintf(stderr, "fromwire_node_announcement called!\n"); abort(); } +/* Generated stub for fromwire_peektype */ +int fromwire_peektype(const u8 *cursor UNNEEDED) +{ fprintf(stderr, "fromwire_peektype called!\n"); abort(); } /* Generated stub for fromwire_u8 */ u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_u8 called!\n"); abort(); } diff --git a/gossipd/test/run-find_route.c b/gossipd/test/run-find_route.c index 095cb89a6..0883e4806 100644 --- a/gossipd/test/run-find_route.c +++ b/gossipd/test/run-find_route.c @@ -21,6 +21,9 @@ bool fromwire_channel_update(const void *p UNNEEDED, size_t *plen UNNEEDED, secp /* Generated stub for fromwire_node_announcement */ bool fromwire_node_announcement(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, u8 **features UNNEEDED, u32 *timestamp UNNEEDED, struct pubkey *node_id UNNEEDED, u8 rgb_color[3] UNNEEDED, u8 alias[32] UNNEEDED, u8 **addresses UNNEEDED) { fprintf(stderr, "fromwire_node_announcement called!\n"); abort(); } +/* Generated stub for fromwire_peektype */ +int fromwire_peektype(const u8 *cursor UNNEEDED) +{ fprintf(stderr, "fromwire_peektype called!\n"); abort(); } /* Generated stub for fromwire_u8 */ u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_u8 called!\n"); abort(); }