[Babel-users] [PATCH] Filter netlink messages from self out in the kernel

Dave Taht dave.taht at gmail.com
Mon Aug 12 18:25:54 BST 2019


BPF magic courtesy Stephen Hemminger - from 2008.
---
 kernel_netlink.c | 41 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/kernel_netlink.c b/kernel_netlink.c
index 8b7f75d..cceb468 100644
--- a/kernel_netlink.c
+++ b/kernel_netlink.c
@@ -22,6 +22,7 @@ THE SOFTWARE.
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <stddef.h>
 #include <errno.h>
 #include <string.h>
 #include <unistd.h>
@@ -40,6 +41,7 @@ THE SOFTWARE.
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
 #include <linux/fib_rules.h>
+#include <linux/filter.h>
 #include <net/if_arp.h>
 
 /* From <linux/if_bridge.h> */
@@ -369,7 +371,8 @@ netlink_read(struct netlink *nl, struct netlink *nl_ignore, int answer,
             if(!answer)
                 done = 1;
             if(nl_ignore && nh->nlmsg_pid == nl_ignore->sockaddr.nl_pid) {
-                kdebugf("(ignore), ");
+                fprintf(stderr,"Message from self - we should not see this more than twice - ever\n");
+		kdebugf("(ignore), ");
                 continue;
             } else if(answer && (nh->nlmsg_pid != nl->sockaddr.nl_pid ||
                                  nh->nlmsg_seq != nl->seqno)) {
@@ -472,6 +475,7 @@ netlink_talk(struct nlmsghdr *nh)
     return rc;
 }
 
+
 static int
 netlink_send_dump(int type, void *data, int len) {
 
@@ -604,6 +608,40 @@ rtnlgrp_to_mask(unsigned int grp)
     return grp ? 1 << (grp - 1) : 0;
 }
 
+#define array_size(ar) (sizeof(ar) / sizeof(ar[0]))
+/* Filter out messages from self that occur on listener socket,
+   caused by our actions on the command socket
+ */
+
+static void netlink_install_filter (int sock, __u32 pid)
+{
+  struct sock_filter filter[] = {
+    /* 0: ldh [4]                 */
+    BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)),
+    /* 1: jeq 0x18 jt 3 jf 6  */
+    BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 1, 0),
+    /* 2: jeq 0x19 jt 3 jf 6  */
+    BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 0, 3),
+    /* 3: ldw [12]                */
+    BPF_STMT(BPF_LD|BPF_ABS|BPF_W, offsetof(struct nlmsghdr, nlmsg_pid)),
+    /* 4: jeq XX  jt 5 jf 6   */
+    BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htonl(pid), 0, 1),
+    /* 5: ret 0    (skip)     */
+    BPF_STMT(BPF_RET|BPF_K, 0),
+    /* 6: ret 0xffff (keep)   */
+    BPF_STMT(BPF_RET|BPF_K, 0xffff),
+  };
+
+  struct sock_fprog prog = {
+    .len = array_size(filter),
+    .filter = filter,
+  };
+
+  if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)) < 0)
+      fprintf(stderr,"Can't install socket filter for some reason - will see messages from self: %s\n",
+	      strerror(errno));
+}
+
 int
 kernel_setup_socket(int setup)
 {
@@ -626,6 +664,7 @@ kernel_setup_socket(int setup)
             return -1;
         }
 
+	netlink_install_filter(nl_listen.sock,getpid());
         kernel_socket = nl_listen.sock;
 
         return 1;
-- 
2.17.1




More information about the Babel-users mailing list