diff --git a/lightningd/channel/channel_wire.csv b/lightningd/channel/channel_wire.csv index 11003b0ec..64ae9d3cc 100644 --- a/lightningd/channel/channel_wire.csv +++ b/lightningd/channel/channel_wire.csv @@ -9,7 +9,10 @@ channel_gossip_bad_message,0x8004 # These are due to peer. channel_peer_write_failed,0x8010 channel_peer_read_failed,0x8011 + channel_peer_bad_message,0x8012 +channel_peer_bad_message,,len,u16 +channel_peer_bad_message,,msg,len*u8 # Received and sent funding_locked channel_normal_operation,1001 diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index 3ad340c08..3b54cf5d9 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -99,13 +99,14 @@ static int gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) enum gossip_wire_type t = fromwire_peektype(msg); switch (t) { - /* We don't get told about fatal errors. */ + /* subd already logs fatal errors. */ case WIRE_GOSSIPSTATUS_INIT_FAILED: case WIRE_GOSSIPSTATUS_BAD_NEW_PEER_REQUEST: case WIRE_GOSSIPSTATUS_BAD_REQUEST: case WIRE_GOSSIPSTATUS_FDPASS_FAILED: case WIRE_GOSSIPSTATUS_BAD_RELEASE_REQUEST: case WIRE_GOSSIPSTATUS_BAD_FAIL_REQUEST: + break; /* These are messages we send, not them. */ case WIRE_GOSSIPCTL_INIT: case WIRE_GOSSIPCTL_NEW_PEER: diff --git a/lightningd/hsm_control.c b/lightningd/hsm_control.c index a91a25580..5d42a91e8 100644 --- a/lightningd/hsm_control.c +++ b/lightningd/hsm_control.c @@ -59,12 +59,13 @@ static int hsm_msg(struct subd *hsm, const u8 *msg, const int *fds) : "unknown peer", tal_hex(msg, badmsg)); - /* We don't get called for failed status. */ + /* subd already logs fatal errors. */ case WIRE_HSMSTATUS_INIT_FAILED: case WIRE_HSMSTATUS_WRITEMSG_FAILED: case WIRE_HSMSTATUS_BAD_REQUEST: case WIRE_HSMSTATUS_FD_FAILED: case WIRE_HSMSTATUS_KEY_FAILED: + break; /* HSM doesn't send these */ case WIRE_HSMCTL_INIT: diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 0206e25fa..d674e6ba8 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -940,6 +940,20 @@ static int peer_got_funding_locked(struct peer *peer, const u8 *msg) return 0; } +static int peer_got_bad_message(struct peer *peer, const u8 *msg) +{ + u8 *err; + + /* Don't try to fail this (again!) when owner dies. */ + peer->owner = NULL; + if (!fromwire_channel_peer_bad_message(peer, NULL, NULL, &err)) + err = (u8 *)tal_strdup(peer, "Internal error after bad message"); + peer_fail_permanent(peer, take(err)); + + /* Kill daemon (though it's dying anyway) */ + return -1; +} + static int channel_msg(struct subd *sd, const u8 *msg, const int *unused) { enum channel_wire_type t = fromwire_peektype(msg); @@ -961,7 +975,7 @@ static int channel_msg(struct subd *sd, const u8 *msg, const int *unused) case WIRE_CHANNEL_GOT_FUNDING_LOCKED: return peer_got_funding_locked(sd->peer, msg); - /* We never see fatal ones. */ + /* We let peer_owner_finished handle these as transient errors. */ case WIRE_CHANNEL_BAD_COMMAND: case WIRE_CHANNEL_HSM_FAILED: case WIRE_CHANNEL_CRYPTO_FAILED: @@ -969,7 +983,12 @@ static int channel_msg(struct subd *sd, const u8 *msg, const int *unused) case WIRE_CHANNEL_INTERNAL_ERROR: case WIRE_CHANNEL_PEER_WRITE_FAILED: case WIRE_CHANNEL_PEER_READ_FAILED: + return -1; + + /* This is a permanent error. */ case WIRE_CHANNEL_PEER_BAD_MESSAGE: + return peer_got_bad_message(sd->peer, msg); + /* And we never get these from channeld. */ case WIRE_CHANNEL_INIT: case WIRE_CHANNEL_FUNDING_LOCKED: diff --git a/lightningd/subd.c b/lightningd/subd.c index 7101ae084..1b6e46dd7 100644 --- a/lightningd/subd.c +++ b/lightningd/subd.c @@ -303,11 +303,12 @@ static struct io_plan *sd_msg_read(struct io_conn *conn, struct subd *sd) if (type == STATUS_TRACE) log_debug(sd->log, "TRACE: %.*s", str_len, str); - else if (type & STATUS_FAIL) - log_unusual(sd->log, "FAILURE %s: %.*s", - sd->msgname(type), str_len, str); else { - log_info(sd->log, "UPDATE %s", sd->msgname(type)); + if (type & STATUS_FAIL) + log_unusual(sd->log, "FAILURE %s: %.*s", + sd->msgname(type), str_len, str); + else + log_info(sd->log, "UPDATE %s", sd->msgname(type)); if (sd->msgcb) { int i = sd->msgcb(sd, sd->msg_in, sd->fds_in);