tap: Fold reset handling into tap_handler_passt()

We call tap_sock_reset() if tap_handler_passt() fails, or if we get an
error event on the socket.  Fold that logic into tap_handler() passt itself
which simplifies the caller.  It also makes it clearer that we had a
redundant EPOLL_CTL_DEL and close() in one of the reset paths, so fix that
too.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
David Gibson 2023-08-11 15:12:20 +10:00 committed by Stefano Brivio
parent 0d870c5da6
commit e26282b67d

68
tap.c
View file

@ -891,19 +891,41 @@ append:
return in->count; return in->count;
} }
/**
* tap_sock_reset() - Handle closing or failure of connect AF_UNIX socket
* @c: Execution context
*/
static void tap_sock_reset(struct ctx *c)
{
if (c->one_off) {
info("Client closed connection, exiting");
exit(EXIT_SUCCESS);
}
/* Close the connected socket, wait for a new connection */
epoll_ctl(c->epollfd, EPOLL_CTL_DEL, c->fd_tap, NULL);
close(c->fd_tap);
c->fd_tap = -1;
}
/** /**
* tap_handler_passt() - Packet handler for AF_UNIX file descriptor * tap_handler_passt() - Packet handler for AF_UNIX file descriptor
* @c: Execution context * @c: Execution context
* @events: epoll events
* @now: Current timestamp * @now: Current timestamp
*
* Return: -ECONNRESET on receive error, 0 otherwise
*/ */
static int tap_handler_passt(struct ctx *c, const struct timespec *now) static void tap_handler_passt(struct ctx *c, uint32_t events,
const struct timespec *now)
{ {
struct ethhdr *eh; struct ethhdr *eh;
ssize_t n, rem; ssize_t n, rem;
char *p; char *p;
if (events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR)) {
tap_sock_reset(c);
return;
}
redo: redo:
p = pkt_buf; p = pkt_buf;
rem = 0; rem = 0;
@ -913,13 +935,9 @@ redo:
n = recv(c->fd_tap, p, TAP_BUF_FILL, MSG_DONTWAIT); n = recv(c->fd_tap, p, TAP_BUF_FILL, MSG_DONTWAIT);
if (n < 0) { if (n < 0) {
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK)
return 0; tap_sock_reset(c);
return;
epoll_ctl(c->epollfd, EPOLL_CTL_DEL, c->fd_tap, NULL);
close(c->fd_tap);
return -ECONNRESET;
} }
while (n > (ssize_t)sizeof(uint32_t)) { while (n > (ssize_t)sizeof(uint32_t)) {
@ -934,7 +952,7 @@ redo:
if (len > n) { if (len > n) {
rem = recv(c->fd_tap, p + n, len - n, 0); rem = recv(c->fd_tap, p + n, len - n, 0);
if ((n += rem) != len) if ((n += rem) != len)
return 0; return;
} }
/* Complete the partial read above before discarding a malformed /* Complete the partial read above before discarding a malformed
@ -975,8 +993,6 @@ next:
/* We can't use EPOLLET otherwise. */ /* We can't use EPOLLET otherwise. */
if (rem) if (rem)
goto redo; goto redo;
return 0;
} }
/** /**
@ -1258,23 +1274,6 @@ void tap_sock_init(struct ctx *c)
} }
} }
/**
* tap_sock_reset() - Handle closing or failure of connect AF_UNIX socket
* @c: Execution context
*/
static void tap_sock_reset(struct ctx *c)
{
if (c->one_off) {
info("Client closed connection, exiting");
exit(EXIT_SUCCESS);
}
/* Close the connected socket, wait for a new connection */
epoll_ctl(c->epollfd, EPOLL_CTL_DEL, c->fd_tap, NULL);
close(c->fd_tap);
c->fd_tap = -1;
}
/** /**
* tap_handler() - Packet handler for AF_UNIX or tuntap file descriptor * tap_handler() - Packet handler for AF_UNIX or tuntap file descriptor
* @c: Execution context * @c: Execution context
@ -1290,11 +1289,8 @@ void tap_handler(struct ctx *c, int fd, uint32_t events,
return; return;
} }
if (c->mode == MODE_PASST) { if (c->mode == MODE_PASST)
if (tap_handler_passt(c, now) || tap_handler_passt(c, events, now);
(events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR))) else if (c->mode == MODE_PASTA)
tap_sock_reset(c);
} else if (c->mode == MODE_PASTA) {
tap_handler_pasta(c, events, now); tap_handler_pasta(c, events, now);
}
} }