This makes a number of changes to improve error reporting while connecting a new spliced socket: * We use flow_err() and similar functions so all messages include info on which specific flow was affected * We use strerror() to interpret raw error values * We now report errors on connection (at "trace" level, since this would allow spamming the logs) * We also look up and report some details on EPOLLERR events, which can include connection errors, since we use a non-blocking connect(). Again we use "trace" level since this can spam the logs. * Use the 'goto fail' idiom in tcp_splice_conn_from_sock to combine some common handling Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au> --- tcp_splice.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/tcp_splice.c b/tcp_splice.c index 30b4d58a..abd698d4 100644 --- a/tcp_splice.c +++ b/tcp_splice.c @@ -387,7 +387,7 @@ bool tcp_splice_conn_from_sock(const struct ctx *c, in_port_t srcport, dstport = ref.port; union inany_addr src; sa_family_t af; - int s1; + int s1, rc; ASSERT(c->mode == MODE_PASTA); @@ -420,15 +420,25 @@ bool tcp_splice_conn_from_sock(const struct ctx *c, } if (s1 < 0) { - warn("Couldn't open connectable socket for splice (%d)", s1); - conn_flag(c, conn, CLOSING); - return true; + flow_err(conn, + "Couldn't open connectable socket for splice: %s", + strerror(-s1)); + goto fail; } - if (tcp_splice_connect(c, conn, s1, dstport)) - conn_flag(c, conn, CLOSING); + if ((rc = tcp_splice_connect(c, conn, s1, dstport))) { + flow_trace(conn, "Couldn't connect socket for splice: %s", + strerror(-rc)); + goto fail; + } return true; + +fail: + /* This is *supposed* to be a spliced connection, but something went + * wrong */ + conn_flag(c, conn, CLOSING); + return true; } /** @@ -452,8 +462,20 @@ void tcp_splice_sock_handler(struct ctx *c, union epoll_ref ref, if (conn->events == SPLICE_CLOSED) return; - if (events & EPOLLERR) + if (events & EPOLLERR) { + int err, rc; + socklen_t sl = sizeof(err); + + rc = getsockopt(ref.fd, SOL_SOCKET, SO_ERROR, &err, &sl); + if (rc) + flow_err(conn, "Error retrieving SO_ERROR: %s", + strerror(errno)); + else + flow_trace(conn, "Error event on socket: %s", + strerror(err)); + goto close; + } if (conn->events == SPLICE_CONNECT) { if (!(events & EPOLLOUT)) -- 2.43.0