Skip to content

Commit 3feee7a

Browse files
committed
openingd: handle unexpected messages better.
In particular, this one didn't handle them trying to open a different channel at the same time. Again, deliberately very similar, but unfortunately different enough that sharing is awkward. Signed-off-by: Rusty Russell <[email protected]>
1 parent ec3e858 commit 3feee7a

File tree

1 file changed

+85
-64
lines changed

1 file changed

+85
-64
lines changed

openingd/opening.c

Lines changed: 85 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -203,60 +203,90 @@ static void temporary_channel_id(struct channel_id *channel_id)
203203
channel_id->id[i] = pseudorand(256);
204204
}
205205

206-
/* We have to handle random gossip message and pings. */
207-
static u8 *read_next_peer_msg(struct state *state, const tal_t *ctx)
206+
static void handle_ping(const u8 *msg,
207+
struct crypto_state *cs,
208+
const struct channel_id *our_channel_id)
208209
{
209-
for (;;) {
210-
u8 *msg = sync_crypto_read(ctx, &state->cs, PEER_FD);
211-
if (!msg)
212-
return NULL;
213-
214-
if (fromwire_peektype(msg) == WIRE_PING) {
215-
u8 *pong;
216-
if (!check_ping_make_pong(ctx, msg, &pong)) {
217-
status_trace("Bad ping message");
218-
return tal_free(msg);
219-
}
220-
if (pong && !sync_crypto_write(&state->cs, PEER_FD,
221-
take(pong)))
222-
status_failed(STATUS_FAIL_PEER_IO,
223-
"Sending pong");
224-
} else if (is_gossip_msg(msg)) {
225-
/* We relay gossip to gossipd, but don't relay from */
226-
if (!wire_sync_write(GOSSIP_FD, take(msg)))
227-
status_failed(STATUS_FAIL_PEER_IO,
228-
"Relaying gossip message");
229-
} else if (fromwire_peektype(msg) == WIRE_ERROR) {
230-
struct channel_id chanid;
231-
char *err = sanitize_error(msg, msg, &chanid);
232-
233-
/* BOLT #1:
234-
*
235-
* The channel is referred to by `channel_id`, unless
236-
* `channel_id` is 0 (i.e. all bytes are 0), in which
237-
* case it refers to all channels.
238-
* ...
239-
240-
* The receiving node:
241-
* - upon receiving `error`:
242-
* - MUST fail the channel referred to by the error
243-
* message.
244-
* - if no existing channel is referred to by the
245-
* message:
246-
* - MUST ignore the message.
247-
*/
248-
if (channel_id_is_all(&chanid))
249-
peer_failed(PEER_FD, &state->cs,
250-
&state->channel_id,
251-
"Error packet: %s", err);
252-
253-
if (structeq(&chanid, &state->channel_id))
254-
negotiation_failed(state, false,
255-
"Error packet: %s", err);
256-
} else {
257-
return msg;
258-
}
210+
u8 *pong;
211+
212+
if (!check_ping_make_pong(msg, msg, &pong))
213+
peer_failed(PEER_FD, cs, our_channel_id, "Bad ping");
214+
215+
status_trace("Got ping, sending %s", pong ?
216+
wire_type_name(fromwire_peektype(pong))
217+
: "nothing");
218+
219+
if (pong && !sync_crypto_write(cs, PEER_FD, take(pong)))
220+
status_failed(STATUS_FAIL_PEER_IO,
221+
"Failed writing pong: %s", strerror(errno));
222+
}
223+
224+
/* Handle random messages we might get, returning NULL if we handled it. */
225+
static u8 *read_peer_msg(struct state *state)
226+
{
227+
u8 *msg;
228+
struct channel_id channel_id;
229+
230+
msg = sync_crypto_read(state, &state->cs, PEER_FD);
231+
if (!msg)
232+
status_failed(STATUS_FAIL_PEER_IO,
233+
"Failed reading from peer: %s", strerror(errno));
234+
235+
if (is_gossip_msg(msg)) {
236+
/* Forward to gossip daemon */
237+
wire_sync_write(GOSSIP_FD, take(msg));
238+
return NULL;
259239
}
240+
241+
if (fromwire_peektype(msg) == WIRE_PING) {
242+
handle_ping(msg, &state->cs, &state->channel_id);
243+
return tal_free(msg);
244+
}
245+
246+
if (fromwire_peektype(msg) == WIRE_ERROR) {
247+
struct channel_id chanid;
248+
char *err = sanitize_error(msg, msg, &chanid);
249+
250+
/* BOLT #1:
251+
*
252+
* The channel is referred to by `channel_id`, unless
253+
* `channel_id` is 0 (i.e. all bytes are 0), in which
254+
* case it refers to all channels.
255+
* ...
256+
257+
* The receiving node:
258+
* - upon receiving `error`:
259+
* - MUST fail the channel referred to by the error
260+
* message.
261+
* - if no existing channel is referred to by the
262+
* message:
263+
* - MUST ignore the message.
264+
*/
265+
if (channel_id_is_all(&chanid))
266+
status_failed(STATUS_FAIL_PEER_BAD,
267+
"Received ERROR %s", err);
268+
else if (structeq(&chanid, &state->channel_id))
269+
negotiation_failed(state, false,
270+
"Error packet: %s", err);
271+
272+
return tal_free(msg);
273+
}
274+
275+
/* They're talking about a different channel? */
276+
if (extract_channel_id(msg, &channel_id)
277+
&& !structeq(&channel_id, &state->channel_id)) {
278+
status_trace("Rejecting %s for unknown channel_id %s",
279+
wire_type_name(fromwire_peektype(msg)),
280+
type_to_string(msg, struct channel_id,
281+
&channel_id));
282+
sync_crypto_write(&state->cs, PEER_FD,
283+
take(towire_errorfmt(msg, &channel_id,
284+
"Multiple channels"
285+
" unsupported")));
286+
return tal_free(msg);
287+
}
288+
289+
return msg;
260290
}
261291

262292
static u8 *funder_channel(struct state *state,
@@ -323,10 +353,7 @@ static u8 *funder_channel(struct state *state,
323353

324354
state->remoteconf = tal(state, struct channel_config);
325355

326-
msg = read_next_peer_msg(state, state);
327-
if (!msg)
328-
status_failed(STATUS_FAIL_PEER_IO,
329-
"Reading accept_channel: %s", strerror(errno));
356+
while ((msg = read_peer_msg(state)) == NULL);
330357

331358
/* BOLT #2:
332359
*
@@ -447,10 +474,7 @@ static u8 *funder_channel(struct state *state,
447474
* commitment transaction, so they can broadcast it knowing they can
448475
* redeem their funds if they need to.
449476
*/
450-
msg = read_next_peer_msg(state, state);
451-
if (!msg)
452-
status_failed(STATUS_FAIL_PEER_IO,
453-
"Writing funding_signed: %s", strerror(errno));
477+
while ((msg = read_peer_msg(state)) == NULL);
454478

455479
if (!fromwire_funding_signed(msg, NULL, &id_in, &sig))
456480
peer_failed(PEER_FD, &state->cs, &state->channel_id,
@@ -633,10 +657,7 @@ static u8 *fundee_channel(struct state *state,
633657
status_failed(STATUS_FAIL_PEER_IO,
634658
"Writing accept_channel: %s", strerror(errno));
635659

636-
msg = read_next_peer_msg(state, state);
637-
if (!msg)
638-
status_failed(STATUS_FAIL_PEER_IO,
639-
"Reading funding_created: %s", strerror(errno));
660+
while ((msg = read_peer_msg(state)) == NULL);
640661

641662
if (!fromwire_funding_created(msg, NULL, &id_in,
642663
&state->funding_txid,

0 commit comments

Comments
 (0)