From 068e2739098dda92a86a10871a7018bbf9f2d86a Mon Sep 17 00:00:00 2001 From: Radkesvat <134321679+radkesvat@users.noreply.github.com> Date: Thu, 15 Aug 2024 23:01:46 +0000 Subject: [PATCH] better failure handling --- ww/devices/capture/capture_linux.c | 31 ++++++++++++++---- ww/devices/raw/raw_linux.c | 51 +++++++++++++++++++++++------- ww/devices/tun/tun_linux.c | 41 ++++++++++++++++++++---- 3 files changed, 99 insertions(+), 24 deletions(-) diff --git a/ww/devices/capture/capture_linux.c b/ww/devices/capture/capture_linux.c index 3824aae..966de02 100644 --- a/ww/devices/capture/capture_linux.c +++ b/ww/devices/capture/capture_linux.c @@ -295,10 +295,17 @@ static HTHREAD_ROUTINE(routineReadFromCapture) // NOLINT nread = netfilterGetPacket(cdev->socket, cdev->queue_number, buf); + if (nread == 0) + { + reuseBuffer(cdev->reader_buffer_pool, buf); + LOGW("CaptureDevice: Exit read routine due to End Of File"); + return 0; + } + if (nread < 0) { - LOGW("CaptureDevice: failed to read packet from netfilter socket"); reuseBuffer(cdev->reader_buffer_pool, buf); + LOGW("CaptureDevice: failed to read a packet from netfilter socket, retrying..."); continue; } @@ -337,9 +344,20 @@ static HTHREAD_ROUTINE(routineWriteToCapture) // NOLINT reuseBuffer(cdev->writer_buffer_pool, buf); + if (nwrite == 0) + { + LOGW("CaptureDevice: Exit write routine due to End Of File"); + return 0; + } + if (nwrite < 0) { - LOGE("CaptureDevice: writing to Capture device failed"); + LOGW("CaptureDevice: writing a packet to Capture device failed, code: %d", (int) nwrite); + if (errno == EINVAL || errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) + { + continue; + } + LOGE("CaptureDevice: Exit write routine due to critical error"); return 0; } } @@ -445,10 +463,11 @@ capture_device_t *createCaptureDevice(const char *name, uint32_t queue_number, v LOGE("CaptureDevice: unable to set netfilter queue maximum length to %u", kQueueLen); } - generic_pool_t *reader_sb_pool = newGenericPoolWithCap(GSTATE.masterpool_shift_buffer_pools, (64) + GSTATE.ram_profile, - allocShiftBufferPoolHandle, destroyShiftBufferPoolHandle); - buffer_pool_t *reader_bpool = createBufferPool(GSTATE.masterpool_buffer_pools_large, GSTATE.masterpool_buffer_pools_small, - reader_sb_pool, GSTATE.ram_profile); + generic_pool_t *reader_sb_pool = + newGenericPoolWithCap(GSTATE.masterpool_shift_buffer_pools, (64) + GSTATE.ram_profile, + allocShiftBufferPoolHandle, destroyShiftBufferPoolHandle); + buffer_pool_t *reader_bpool = createBufferPool( + GSTATE.masterpool_buffer_pools_large, GSTATE.masterpool_buffer_pools_small, reader_sb_pool, GSTATE.ram_profile); generic_pool_t *writer_sb_pool = newGenericPoolWithCap(GSTATE.masterpool_shift_buffer_pools, 1, allocShiftBufferPoolHandle, destroyShiftBufferPoolHandle); diff --git a/ww/devices/raw/raw_linux.c b/ww/devices/raw/raw_linux.c index 24bcb52..1720d8b 100644 --- a/ww/devices/raw/raw_linux.c +++ b/ww/devices/raw/raw_linux.c @@ -81,10 +81,23 @@ static HTHREAD_ROUTINE(routineReadFromRaw) // NOLINT nread = recvfrom(rdev->socket, rawBufMut(buf), kReadPacketSize, 0, &saddr, (socklen_t *) &saddr_len); + if (nread == 0) + { + reuseBuffer(rdev->reader_buffer_pool, buf); + LOGW("RawDevice: Exit read routine due to End Of File"); + return 0; + } + if (nread < 0) { - LOGE("RawDevice: reading from RAW device failed"); reuseBuffer(rdev->reader_buffer_pool, buf); + + LOGE("RawDevice: reading a packet from RAW device failed, code: %d", (int) nread); + if (errno == EINVAL || errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) + { + continue; + } + LOGE("RawDevice: Exit read routine due to critical error"); return 0; } @@ -115,6 +128,8 @@ static HTHREAD_ROUTINE(routineWriteToRaw) // NOLINT return 0; } + assert(bufLen(buf) > sizeof(struct iphdr)); + struct iphdr *ip_header = (struct iphdr *) rawBuf(buf); struct sockaddr_in to_addr = {.sin_family = AF_INET, .sin_addr.s_addr = ip_header->daddr}; @@ -123,9 +138,20 @@ static HTHREAD_ROUTINE(routineWriteToRaw) // NOLINT reuseBuffer(rdev->writer_buffer_pool, buf); + if (nwrite == 0) + { + LOGW("RawDevice: Exit write routine due to End Of File"); + return 0; + } + if (nwrite < 0) { - LOGE("RawDevice: writing to RAW device failed"); + LOGW("RawDevice: writing a packet to RAW device failed, code: %d", (int) nwrite); + if (errno == EINVAL || errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) + { + continue; + } + LOGE("RawDevice: Exit write routine due to critical error"); return 0; } } @@ -134,6 +160,8 @@ static HTHREAD_ROUTINE(routineWriteToRaw) // NOLINT bool writeToRawDevce(raw_device_t *rdev, shift_buffer_t *buf) { + assert(bufLen(buf) > sizeof(struct iphdr)); + bool closed = false; if (! hchanTrySend(rdev->writer_buffer_channel, &buf, &closed)) { @@ -214,26 +242,25 @@ raw_device_t *createRawDevice(const char *name, uint32_t mark, void *userdata, R raw_device_t *rdev = globalMalloc(sizeof(raw_device_t)); - generic_pool_t *reader_sb_pool = NULL; - buffer_pool_t *reader_bpool = NULL; - master_pool_t *reader_message_pool = NULL; + generic_pool_t *reader_sb_pool = NULL; + buffer_pool_t *reader_bpool = NULL; + master_pool_t *reader_message_pool = NULL; if (cb != NULL) { // if the user really wanted to read from raw socket reader_sb_pool = newGenericPoolWithCap(GSTATE.masterpool_shift_buffer_pools, (64) + GSTATE.ram_profile, - allocShiftBufferPoolHandle, destroyShiftBufferPoolHandle); - reader_bpool = createBufferPool(GSTATE.masterpool_buffer_pools_large, GSTATE.masterpool_buffer_pools_small, reader_sb_pool, - GSTATE.ram_profile); - reader_message_pool = newMasterPoolWithCap(kMasterMessagePoolCap); + allocShiftBufferPoolHandle, destroyShiftBufferPoolHandle); + reader_bpool = createBufferPool(GSTATE.masterpool_buffer_pools_large, GSTATE.masterpool_buffer_pools_small, + reader_sb_pool, GSTATE.ram_profile); + reader_message_pool = newMasterPoolWithCap(kMasterMessagePoolCap); installMasterPoolAllocCallbacks(reader_message_pool, allocRawMsgPoolHandle, destroyRawMsgPoolHandle); } - generic_pool_t *writer_sb_pool = newGenericPoolWithCap(GSTATE.masterpool_shift_buffer_pools, GSTATE.ram_profile, allocShiftBufferPoolHandle, destroyShiftBufferPoolHandle); - buffer_pool_t *writer_bpool = createBufferPool(GSTATE.masterpool_buffer_pools_large, - GSTATE.masterpool_buffer_pools_small, writer_sb_pool, GSTATE.ram_profile); + buffer_pool_t *writer_bpool = createBufferPool( + GSTATE.masterpool_buffer_pools_large, GSTATE.masterpool_buffer_pools_small, writer_sb_pool, GSTATE.ram_profile); *rdev = (raw_device_t) {.name = strdup(name), .running = false, diff --git a/ww/devices/tun/tun_linux.c b/ww/devices/tun/tun_linux.c index 6acbfee..9fdcb54 100644 --- a/ww/devices/tun/tun_linux.c +++ b/ww/devices/tun/tun_linux.c @@ -131,10 +131,23 @@ static HTHREAD_ROUTINE(routineReadFromTun) // NOLINT nread = read(tdev->handle, rawBufMut(buf), kReadPacketSize); + if (nread == 0) + { + reuseBuffer(tdev->reader_buffer_pool, buf); + LOGW("TunDevice: Exit read routine due to End Of File"); + return 0; + } + if (nread < 0) { - LOGE("TunDevice: reading from TUN device failed"); reuseBuffer(tdev->reader_buffer_pool, buf); + + LOGE("TunDevice: reading a packet from TUN device failed, code: %d", (int) nread); + if (errno == EINVAL || errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) + { + continue; + } + LOGE("TunDevice: Exit read routine due to critical error"); return 0; } @@ -170,13 +183,26 @@ static HTHREAD_ROUTINE(routineWriteToTun) // NOLINT return 0; } + assert(bufLen(buf) > sizeof(struct iphdr)); + nwrite = write(tdev->handle, rawBuf(buf), bufLen(buf)); reuseBuffer(tdev->writer_buffer_pool, buf); + if (nwrite == 0) + { + LOGW("TunDevice: Exit write routine due to End Of File"); + return 0; + } + if (nwrite < 0) { - LOGE("TunDevice: writing to TUN device failed"); + LOGW("TunDevice: writing a packet to TUN device failed, code: %d", (int) nwrite); + if (errno == EINVAL || errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) + { + continue; + } + LOGE("TunDevice: Exit write routine due to critical error"); return 0; } } @@ -185,6 +211,7 @@ static HTHREAD_ROUTINE(routineWriteToTun) // NOLINT bool writeToTunDevce(tun_device_t *tdev, shift_buffer_t *buf) { + assert(bufLen(buf) > sizeof(struct iphdr)); bool closed = false; if (! hchanTrySend(tdev->writer_buffer_channel, &buf, &closed)) @@ -317,10 +344,12 @@ tun_device_t *createTunDevice(const char *name, bool offload, void *userdata, Tu return NULL; } - generic_pool_t *reader_sb_pool = newGenericPoolWithCap(GSTATE.masterpool_shift_buffer_pools, (64) + GSTATE.ram_profile, - allocShiftBufferPoolHandle, destroyShiftBufferPoolHandle); - buffer_pool_t *reader_bpool = createBufferPool(GSTATE.masterpool_buffer_pools_large, GSTATE.masterpool_buffer_pools_small, - reader_sb_pool, (0) + GSTATE.ram_profile); + generic_pool_t *reader_sb_pool = + newGenericPoolWithCap(GSTATE.masterpool_shift_buffer_pools, (64) + GSTATE.ram_profile, + allocShiftBufferPoolHandle, destroyShiftBufferPoolHandle); + buffer_pool_t *reader_bpool = + createBufferPool(GSTATE.masterpool_buffer_pools_large, GSTATE.masterpool_buffer_pools_small, reader_sb_pool, + (0) + GSTATE.ram_profile); generic_pool_t *writer_sb_pool = newGenericPoolWithCap(GSTATE.masterpool_shift_buffer_pools, 1, allocShiftBufferPoolHandle, destroyShiftBufferPoolHandle);