summaryrefslogtreecommitdiff
path: root/zebra/kernel_socket.c
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2020-10-05 06:35:38 -0400
committerGitHub <noreply@github.com>2020-10-05 06:35:38 -0400
commitb86d6ac699416da08f0df7bcba57864781272046 (patch)
tree873745d6edf3acc96106f4b1b4f84d80eae4abee /zebra/kernel_socket.c
parent31e7662dbcdc932c51611fc3cd8efc5a2056496d (diff)
parent355c74b7e96730873d51145b63fed2b8d39e3db2 (diff)
Merge pull request #7242 from rsmarples/SO_RERROR
BSD: Detect route(4) overflows
Diffstat (limited to 'zebra/kernel_socket.c')
-rw-r--r--zebra/kernel_socket.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index 40ac44b77f..8fd0c96bd9 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,15 @@ 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.