summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Larson <slioch@eng-140.vyatta.com>2008-03-31 13:54:48 -0700
committerMichael Larson <slioch@eng-140.vyatta.com>2008-03-31 13:54:48 -0700
commitb788be3f9b20f44ceb463e93977fe5731141ef26 (patch)
treefa6d406f071648674727d120575fac803554575d
parente11fac98b244ce836185a452bf1960cedf26660c (diff)
parent2bc693173112ea436884aca19352624504e2246a (diff)
downloadquagga-b788be3f9b20f44ceb463e93977fe5731141ef26.tar.bz2
quagga-b788be3f9b20f44ceb463e93977fe5731141ef26.tar.xz
Merge branch 'master' of http://git.vyatta.com/vyatta-quagga
-rw-r--r--lib/zebra.h1
-rw-r--r--zebra/rt_netlink.c33
2 files changed, 33 insertions, 1 deletions
diff --git a/lib/zebra.h b/lib/zebra.h
index 150aa2c5..d4f68cf0 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -162,6 +162,7 @@ typedef int socklen_t;
#ifdef HAVE_NETLINK
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
+#include <linux/filter.h>
#else
#define RT_TABLE_MAIN 0
#endif /* HAVE_NETLINK */
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index f071eb24..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
@@ -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);
+ }
}