diff options
Diffstat (limited to 'zebra/rt_netlink.c')
-rw-r--r-- | zebra/rt_netlink.c | 41 |
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); + } } |