summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2020-10-04 20:32:26 +0100
committerRoy Marples <roy@marples.name>2020-10-04 20:32:26 +0100
commit68cd699df58b6a5a39d9655d90ba400960fa87d0 (patch)
tree5057a543363a414e42ef8466773a14d762a0a6df
parent4b40d5ffb0c34d4e99dd121085b46d4f4a896b72 (diff)
BSD: Detect route(4) overflows
NetBSD and DragonFlyBSD support reporting of route(4) overflows by setting the socket option SO_RERROR. This is handled the same as on Linux by exiting with a -1 error code. Signed-off-by: Roy Marples <roy@marples.name>
-rw-r--r--zebra/kernel_socket.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index 40ac44b77f..16a9669e89 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -1340,13 +1340,27 @@ static int kernel_read(struct thread *thread)
nbytes = read(sock, &buf, sizeof(buf));
- if (nbytes <= 0) {
- if (nbytes < 0 && errno != EWOULDBLOCK && errno != EAGAIN)
+ if (nbytes < 0) {
+ if (errno == ENOBUFS) {
+ flog_err(EC_ZEBRA_RECVMSG_OVERRUN,
+ "routing socket overrun: %s",
+ safe_strerror(errno));
+ /*
+ * In this case we are screwed.
+ * There is no good way to
+ * recover zebra at this point.
+ */
+ exit(-1);
+ }
+ if (errno != EAGAIN && errno != EWOULDBLOCK)
flog_err_sys(EC_LIB_SOCKET, "routing socket error: %s",
safe_strerror(errno));
return 0;
}
+ if (nbytes == 0)
+ return 0;
+
thread_add_read(zrouter.master, kernel_read, NULL, sock, NULL);
if (IS_ZEBRA_DEBUG_KERNEL)
@@ -1412,6 +1426,14 @@ static void routing_socket(struct zebra_ns *zns)
return;
}
+#ifdef SO_RERROR
+ /* Allow reporting of route(4) buffer overflow errors */
+ int n = 1;
+ if (setsockopt(routing_sock, SOL_SOCKET, SO_RERROR, &n, sizeof(n)) < 0)
+ flog_err_sys(EC_LIB_SOCKET,
+ "Can't set SO_RERROR on routing socket");
+#endif
+
/* XXX: Socket should be NONBLOCK, however as we currently
* discard failed writes, this will lead to inconsistencies.
* For now, socket must be blocking.