aboutgitcodebugslistschat
path: root/util.c
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2024-07-17 10:36:04 +1000
committerStefano Brivio <sbrivio@redhat.com>2024-07-17 07:05:21 +0200
commit2fa91ee391b7bbed960bf404a405573c64d836aa (patch)
treed958e4017cd4bee9fd4c0a0486000e7ed76613b9 /util.c
parent6bd8283bf962126da73612737a5730082b70b5f3 (diff)
downloadpasst-2fa91ee391b7bbed960bf404a405573c64d836aa.tar
passt-2fa91ee391b7bbed960bf404a405573c64d836aa.tar.gz
passt-2fa91ee391b7bbed960bf404a405573c64d836aa.tar.bz2
passt-2fa91ee391b7bbed960bf404a405573c64d836aa.tar.lz
passt-2fa91ee391b7bbed960bf404a405573c64d836aa.tar.xz
passt-2fa91ee391b7bbed960bf404a405573c64d836aa.tar.zst
passt-2fa91ee391b7bbed960bf404a405573c64d836aa.zip
udp: Handle errors on UDP sockets
Currently we ignore all events other than EPOLLIN on UDP sockets. This means that if we ever receive an EPOLLERR event, we'll enter an infinite loop on epoll, because we'll never do anything to clear the error. Luckily that doesn't seem to have happened in practice, but it's certainly fragile. Furthermore changes in how we handle UDP sockets with the flow table mean we will start receiving error events. Add handling of EPOLLERR events. For now we just read the error from the error queue (thereby clearing the error state) and print a debug message. We can add more substantial handling of specific events in future if we want to. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'util.c')
-rw-r--r--util.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/util.c b/util.c
index 428847d..1569f1c 100644
--- a/util.c
+++ b/util.c
@@ -25,6 +25,7 @@
#include <time.h>
#include <errno.h>
#include <stdbool.h>
+#include <linux/errqueue.h>
#include "util.h"
#include "iov.h"
@@ -97,6 +98,14 @@ static int sock_l4_sa(const struct ctx *c, enum epoll_type type,
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(y)))
debug("Failed to set SO_REUSEADDR on socket %i", fd);
+ if (proto == IPPROTO_UDP) {
+ int level = af == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
+ int opt = af == AF_INET ? IP_RECVERR : IPV6_RECVERR;
+
+ if (setsockopt(fd, level, opt, &y, sizeof(y)))
+ die_perror("Failed to set RECVERR on socket %i", fd);
+ }
+
if (ifname && *ifname) {
/* Supported since kernel version 5.7, commit c427bfec18f2
* ("net: core: enable SO_BINDTODEVICE for non-root users"). If
@@ -654,3 +663,23 @@ const char *sockaddr_ntop(const void *sa, char *dst, socklen_t size)
return dst;
}
+
+/** str_ee_origin() - Convert socket extended error origin to a string
+ * @ee: Socket extended error structure
+ *
+ * Return: Static string describing error origin
+ */
+const char *str_ee_origin(const struct sock_extended_err *ee)
+{
+ const char *const desc[] = {
+ [SO_EE_ORIGIN_NONE] = "<no origin>",
+ [SO_EE_ORIGIN_LOCAL] = "Local",
+ [SO_EE_ORIGIN_ICMP] = "ICMP",
+ [SO_EE_ORIGIN_ICMP6] = "ICMPv6",
+ };
+
+ if (ee->ee_origin < ARRAY_SIZE(desc))
+ return desc[ee->ee_origin];
+
+ return "<invalid>";
+}