diff options
-rw-r--r-- | zebra/rt_netlink.c | 73 |
1 files changed, 27 insertions, 46 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 395f1ca6..592dfe2e 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -285,7 +285,7 @@ netlink_request (int family, int type, struct nlsock *nl) req.nlh.nlmsg_len = sizeof req; req.nlh.nlmsg_type = type; req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; - req.nlh.nlmsg_pid = 0; + req.nlh.nlmsg_pid = nl->snl.nl_pid; req.nlh.nlmsg_seq = ++nl->seq; req.g.rtgen_family = family; @@ -367,13 +367,6 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), return -1; } - /* JF: Ignore messages that aren't from the kernel */ - if ( snl.nl_pid != 0 ) - { - zlog ( NULL, LOG_ERR, "Ignoring message from pid %u", snl.nl_pid ); - continue; - } - for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, (unsigned int) status); h = NLMSG_NEXT (h, status)) { @@ -1066,6 +1059,13 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) static int netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h) { + /* JF: Ignore messages that aren't from the kernel */ + if ( snl->nl_pid != 0 ) + { + zlog ( NULL, LOG_ERR, "Ignoring message from pid %u", snl->nl_pid ); + return 0; + } + switch (h->nlmsg_type) { case RTM_NEWROUTE: @@ -1935,45 +1935,26 @@ kernel_read (struct thread *thread) return 0; } -/* Filter out messages from self that occur on listener socket */ -static void netlink_install_filter (int sock) +/* 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) { - /* - * Filter is equivalent to netlink_route_change - * - * if (h->nlmsg_type == RTM_DELROUTE || h->nlmsg_type == RTM_NEWROUTE) { - * if (rtm->rtm_type != RTM_UNICAST) - * return 0; - * if (rtm->rtm_flags & RTM_F_CLONED) - * return 0; - * if (rtm->rtm_protocol == RTPROT_REDIRECT) - * return 0; - * if (rtm->rtm_protocol == RTPROT_KERNEL) - * return 0; - * if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE) - * return 0; - * } - * return 0xffff; - */ struct sock_filter filter[] = { - /* 0*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)), - /* 1*/ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 1, 0), - /* 2*/ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 0, 11), - /* 3*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_B, - sizeof(struct nlmsghdr) + offsetof(struct rtmsg, rtm_type)), - /* 4*/ BPF_JUMP(BPF_JMP|BPF_B, RTN_UNICAST, 0, 8), - /* 5*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_B, - sizeof(struct nlmsghdr) + offsetof(struct rtmsg, rtm_flags)), - /* 6*/ BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, RTM_F_CLONED, 6, 0), - /* 7*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_B, - sizeof(struct nlmsghdr) + offsetof(struct rtmsg, rtm_protocol)), - /* 8*/ BPF_JUMP(BPF_JMP+ BPF_B, RTPROT_REDIRECT, 4, 0), - /* 9*/ BPF_JUMP(BPF_JMP+ BPF_B, RTPROT_KERNEL, 0, 1), - /*10*/ BPF_JUMP(BPF_JMP+ BPF_B, RTPROT_ZEBRA, 0, 3), - /*11*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)), - /*12*/ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 0, 1), - /*13*/ BPF_STMT(BPF_RET|BPF_K, 0), /* drop */ - /*14*/ BPF_STMT(BPF_RET|BPF_K, 0xffff), /* keep */ + /* 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 = { @@ -2002,7 +1983,7 @@ kernel_init (void) /* Register kernel socket. */ if (netlink.sock > 0) { - netlink_install_filter (netlink.sock); + netlink_install_filter (netlink.sock, netlink_cmd.snl.nl_pid); thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock); } } |