tap, pasta: Handle short writes to /dev/tap

tap_send_frames_pasta() sends frames to the namespace by sending them to
our the /dev/tap device.  If that write() returns an error, we already
handle it.  However we don't handle the case where the write() returns
short, meaning we haven't successfully transmitted the whole frame.

I don't know if this can ever happen with the kernel tap device, but we
should at least report the case so we don't get a cryptic failure.  For
the purposes of the return value for tap_send_frames_pasta() we treat this
case as though it was an error (on the grounds that a partial frame is no
use to the namespace).

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
David Gibson 2023-11-08 14:17:54 +11:00 committed by Stefano Brivio
parent f0776eac07
commit 5ec3634b07

8
tap.c
View file

@ -321,7 +321,9 @@ static size_t tap_send_frames_pasta(const struct ctx *c,
size_t i; size_t i;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (write(c->fd_tap, iov[i].iov_base, iov[i].iov_len) < 0) { ssize_t rc = write(c->fd_tap, iov[i].iov_base, iov[i].iov_len);
if (rc < 0) {
debug("tap write: %s", strerror(errno)); debug("tap write: %s", strerror(errno));
switch (errno) { switch (errno) {
@ -336,6 +338,10 @@ static size_t tap_send_frames_pasta(const struct ctx *c,
default: default:
die("Write error on tap device, exiting"); die("Write error on tap device, exiting");
} }
} else if ((size_t)rc < iov[i].iov_len) {
debug("short write on tuntap: %zd/%zu",
rc, iov[i].iov_len);
break;
} }
} }