summaryrefslogtreecommitdiffstats
path: root/zebra/rt_netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/rt_netlink.c')
-rw-r--r--zebra/rt_netlink.c41
1 files changed, 36 insertions, 5 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 5b592f94..07e473bc 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -41,6 +41,7 @@
#include "zebra/redistribute.h"
#include "zebra/interface.h"
#include "zebra/debug.h"
+#include <stddef.h>
/* Socket interface to kernel */
struct nlsock
@@ -103,7 +104,7 @@ set_ifindex(struct interface *ifp, unsigned int ifi_index)
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("interface index %d was renamed from %s to %s",
ifi_index, oifp->name, ifp->name);
- if (if_is_up(oifp))
+ if (if_is_operative(oifp))
zlog_err("interface rename detected on up interface: index %d "
"was renamed from %s to %s, results are uncertain!",
ifi_index, oifp->name, ifp->name);
@@ -328,7 +329,8 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *),
while (1)
{
- char buf[4096];
+ //increased from 4096 to 32768 as recvmsg overrun error
+ char buf[32768];
struct iovec iov = { buf, sizeof buf };
struct sockaddr_nl snl;
struct msghdr msg = { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 };
@@ -1048,7 +1050,7 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
}
else
{
- /* RTM_DELLINK. */
+ // RTM_DELLINK.
ifp = if_lookup_by_name (name);
if (ifp == NULL)
@@ -1060,7 +1062,6 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
if_delete_update (ifp);
}
-
return 0;
}
@@ -1938,6 +1939,33 @@ kernel_read (struct thread *thread)
return 0;
}
+/* Filter out messages from self that occur on listener socket */
+static void netlink_install_filter (int sock)
+{
+ /* BPF code to exclude all RTM_NEWROUTE messages from ZEBRA */
+ struct sock_filter filter[] = {
+ BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)),
+ /* 0: ldh [4] */
+ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 0, 3),
+ /* 1: jeq 0x18 jt 2 jf 5 */
+ BPF_STMT(BPF_LD|BPF_ABS|BPF_B,
+ sizeof(struct nlmsghdr) + offsetof(struct rtmsg, rtm_protocol)),
+ /* 2: ldb [23] */
+ BPF_JUMP(BPF_JMP+ BPF_B, RTPROT_ZEBRA, 2, 0),
+ /* 3: jeq 0xb jt 4 jf 5 */
+ BPF_STMT(BPF_RET|BPF_K, 0), /* 4: ret 0 */
+ BPF_STMT(BPF_RET|BPF_K, 0xffff), /* 5: ret 0xffff */
+ };
+
+ struct sock_fprog prog = {
+ .len = sizeof(filter) / sizeof(filter[0]),
+ .filter = filter,
+ };
+
+ if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)) < 0)
+ zlog_warn ("Can't install socket filter: %s\n", safe_strerror(errno));
+}
+
/* Exported interface function. This function simply calls
netlink_socket (). */
void
@@ -1954,5 +1982,8 @@ kernel_init (void)
/* Register kernel socket. */
if (netlink.sock > 0)
- thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock);
+ {
+ netlink_install_filter (netlink.sock);
+ thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock);
+ }
}