Skip to content

Commit

Permalink
dev_disconnect: new option to stop using connection, but don't close.
Browse files Browse the repository at this point in the history
This allows us to ensure a packet is read by the other end, but we
don't read anything else from them or write anything to them.

Using '+' is similar, but because it closes the connection, the peer
might notice before receiving the packet (such as if it does a write).

Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell committed Jun 25, 2021
1 parent 0fccfc0 commit 62e1e24
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 11 deletions.
11 changes: 8 additions & 3 deletions common/crypto_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
void sync_crypto_write(struct per_peer_state *pps, const void *msg TAKES)
{
#if DEVELOPER
bool post_sabotage = false;
bool post_sabotage = false, post_close;
int type = fromwire_peektype(msg);
#endif
u8 *enc;
Expand All @@ -28,18 +28,23 @@ void sync_crypto_write(struct per_peer_state *pps, const void *msg TAKES)
#if DEVELOPER
switch (dev_disconnect(type)) {
case DEV_DISCONNECT_BEFORE:
dev_sabotage_fd(pps->peer_fd);
dev_sabotage_fd(pps->peer_fd, true);
peer_failed_connection_lost();
case DEV_DISCONNECT_DROPPKT:
enc = tal_free(enc); /* FALL THRU */
case DEV_DISCONNECT_AFTER:
post_sabotage = true;
post_close = true;
break;
case DEV_DISCONNECT_BLACKHOLE:
dev_blackhole_fd(pps->peer_fd);
break;
case DEV_DISCONNECT_NORMAL:
break;
case DEV_DISCONNECT_DISABLE_AFTER:
post_sabotage = true;
post_close = false;
break;
}
#endif
if (!write_all(pps->peer_fd, enc, tal_count(enc)))
Expand All @@ -48,7 +53,7 @@ void sync_crypto_write(struct per_peer_state *pps, const void *msg TAKES)

#if DEVELOPER
if (post_sabotage)
dev_sabotage_fd(pps->peer_fd);
dev_sabotage_fd(pps->peer_fd, post_close);
#endif
}

Expand Down
13 changes: 9 additions & 4 deletions common/dev_disconnect.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,13 @@ enum dev_disconnect dev_disconnect(int pkt_type)
return dev_disconnect_line[0];
}

void dev_sabotage_fd(int fd)
void dev_sabotage_fd(int fd, bool close_fd)
{
int fds[2];

if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) != 0)
err(1, "dev_sabotage_fd: creating socketpair");

/* Close one. */
close(fds[0]);

#if defined(TCP_NODELAY)
/* On Linux, at least, this flushes. */
int opt = TCP_NODELAY;
Expand All @@ -108,6 +105,14 @@ void dev_sabotage_fd(int fd)
#else
#error No TCP_NODELAY?
#endif

/* Move fd out the way if we don't want to close it. */
if (!close_fd)
dup(fd);
else
/* Close other end of socket. */
close(fds[0]);

/* Move other over to the fd we want to sabotage. */
dup2(fds[1], fd);
close(fds[1]);
Expand Down
4 changes: 3 additions & 1 deletion common/dev_disconnect.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ enum dev_disconnect {
DEV_DISCONNECT_DROPPKT = '@',
/* Swallow all writes from now on, and do no more reads. */
DEV_DISCONNECT_BLACKHOLE = '0',
/* Don't use connection after sending packet, but don't close. */
DEV_DISCONNECT_DISABLE_AFTER = 'x',
};

/* Force a close fd before or after a certain packet type */
enum dev_disconnect dev_disconnect(int pkt_type);

/* Make next write on fd fail as if they'd disconnected. */
void dev_sabotage_fd(int fd);
void dev_sabotage_fd(int fd, bool close_fd);

/* No more data to arrive, what's written is swallowed. */
void dev_blackhole_fd(int fd);
Expand Down
14 changes: 12 additions & 2 deletions connectd/peer_exchange_initmsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,14 @@ static struct io_plan *read_init(struct io_conn *conn, struct peer *peer)
static struct io_plan *peer_write_postclose(struct io_conn *conn,
struct peer *peer)
{
dev_sabotage_fd(io_conn_fd(conn));
dev_sabotage_fd(io_conn_fd(conn), true);
return read_init(conn, peer);
}

static struct io_plan *peer_write_post_sabotage(struct io_conn *conn,
struct peer *peer)
{
dev_sabotage_fd(io_conn_fd(conn), false);
return read_init(conn, peer);
}
#endif
Expand Down Expand Up @@ -197,7 +204,7 @@ struct io_plan *peer_exchange_initmsg(struct io_conn *conn,
#if DEVELOPER
switch (dev_disconnect(WIRE_INIT)) {
case DEV_DISCONNECT_BEFORE:
dev_sabotage_fd(io_conn_fd(conn));
dev_sabotage_fd(io_conn_fd(conn), true);
break;
case DEV_DISCONNECT_DROPPKT:
peer->msg = tal_free(peer->msg); /* FALL THRU */
Expand All @@ -209,6 +216,9 @@ struct io_plan *peer_exchange_initmsg(struct io_conn *conn,
break;
case DEV_DISCONNECT_NORMAL:
break;
case DEV_DISCONNECT_DISABLE_AFTER:
next = peer_write_post_sabotage;
break;
}
#endif /* DEVELOPER */

Expand Down
2 changes: 1 addition & 1 deletion devtools/gossipwith.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ void status_fmt(enum log_level level,
}

#if DEVELOPER
void dev_sabotage_fd(int fd)
void dev_sabotage_fd(int fd, bool close_fd)
{
abort();
}
Expand Down

0 comments on commit 62e1e24

Please sign in to comment.