From 6b157a67c296e5f651ba2025acddd2f967b45929 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 1 Aug 2008 18:11:20 -0700 Subject: Make log message lookup function use const tables Message tables should be unaltered. --- zebra/rt_netlink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 3e8048ba..9860d4f9 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -53,7 +53,7 @@ struct nlsock } netlink = { -1, 0, {0}, "netlink-listen"}, /* kernel messages */ netlink_cmd = { -1, 0, {0}, "netlink-cmd"}; /* command channel */ -static struct message nlmsg_str[] = { +static const struct message nlmsg_str[] = { {RTM_NEWROUTE, "RTM_NEWROUTE"}, {RTM_DELROUTE, "RTM_DELROUTE"}, {RTM_GETROUTE, "RTM_GETROUTE"}, @@ -733,7 +733,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) return 0; } -struct message rtproto_str[] = { +static const struct message rtproto_str[] = { {RTPROT_REDIRECT, "redirect"}, {RTPROT_KERNEL, "kernel"}, {RTPROT_BOOT, "boot"}, -- cgit v1.2.3 From 4535c40dc4dee1822fed7f2a14e92b04f5d48f94 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 15 Aug 2008 21:31:29 -0700 Subject: Manage system routes with zebra This adds a new flag to the zebra daemon that causes it to add and remove system routes (ie connected and kernel routes). This causes user space (zebra) to do what the kernel was doing in hollwood. --- zebra/rt_netlink.c | 132 +++++++++++++++++++++++------------------------------ 1 file changed, 56 insertions(+), 76 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 9860d4f9..020aaefc 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -87,6 +87,12 @@ extern struct zebra_privs_t zserv_privs; extern u_int32_t nl_rcvbufsize; +extern int rib_system_routes; + +static void +netlink_delroute (int family, void *dest, int length, void *gate, + int index, int table, int proto); + static int netlink_recvbuf (struct nlsock *nl, uint32_t newsize) { @@ -462,7 +468,6 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h) strncpy(ifp->name, name, INTERFACE_NAMSIZ); ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); - ifp->metric = 1; /* Hardware type and address. */ ifp->hw_type = ifi->ifi_type; @@ -515,7 +520,7 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) #ifdef HAVE_IPV6 && ifa->ifa_family != AF_INET6 #endif /* HAVE_IPV6 */ - ) + ) return 0; if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR) @@ -540,7 +545,7 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) { char buf[BUFSIZ]; zlog_debug ("netlink_interface_addr %s %s:", - lookup (nlmsg_str, h->nlmsg_type), ifp->name); + lookup (nlmsg_str, h->nlmsg_type), ifp->name); if (tb[IFA_LOCAL]) zlog_debug (" IFA_LOCAL %s/%d", inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]), @@ -606,9 +611,25 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) if (ifa->ifa_family == AF_INET) { if (h->nlmsg_type == RTM_NEWADDR) - connected_add_ipv4 (ifp, flags, - (struct in_addr *) addr, ifa->ifa_prefixlen, - (struct in_addr *) broad, label); + { + struct connected *ifc; + ifc = connected_add_ipv4 (ifp, flags, + (struct in_addr *) addr, ifa->ifa_prefixlen, + (struct in_addr *) broad, label); + + /* If address added, but interface is down, + then remove the FIB entry from kernel. + */ + if (rib_system_routes && ifc && !if_is_operative (ifp)) + { + struct prefix_ipv4 p; + PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); + apply_mask_ipv4 (&p); + + netlink_delroute (p.family, &p.prefix, p.prefixlen, NULL, + ifp->ifindex, RT_TABLE_MAIN, RTPROT_KERNEL); + } + } else connected_delete_ipv4 (ifp, flags, (struct in_addr *) addr, ifa->ifa_prefixlen, @@ -618,9 +639,9 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) if (ifa->ifa_family == AF_INET6) { if (h->nlmsg_type == RTM_NEWADDR) - connected_add_ipv6 (ifp, flags, - (struct in6_addr *) addr, ifa->ifa_prefixlen, - (struct in6_addr *) broad, label); + connected_add_ipv6 (ifp, flags, + (struct in6_addr *) addr, ifa->ifa_prefixlen, + (struct in6_addr *) broad, label); else connected_delete_ipv6 (ifp, (struct in6_addr *) addr, ifa->ifa_prefixlen, @@ -715,7 +736,8 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) memcpy (&p.prefix, dest, 4); p.prefixlen = rtm->rtm_dst_len; - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index, table, metric, 0); + rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index, + table, metric, 0, rtm->rtm_scope); } #ifdef HAVE_IPV6 if (rtm->rtm_family == AF_INET6) @@ -853,7 +875,8 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) } if (h->nlmsg_type == RTM_NEWROUTE) - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table, 0, 0); + rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table, 0, + 0, rtm->rtm_scope); else rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table); } @@ -961,7 +984,6 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) ifp->flags = new_flags; ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); - ifp->metric = 1; /* If new link is added. */ if_add_update (ifp); @@ -970,7 +992,6 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) { /* Interface status change. */ ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); - ifp->metric = 1; if (new_flags != ifp->flags) { @@ -1204,11 +1225,6 @@ netlink_talk (struct nlmsghdr *n, struct nlsock *nl) /* Request an acknowledgement by setting NLM_F_ACK */ n->nlmsg_flags |= NLM_F_ACK; - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("netlink_talk: %s type %s(%u), seq=%u", nl->name, - lookup (nlmsg_str, n->nlmsg_type), n->nlmsg_type, - n->nlmsg_seq); - /* Send message to netlink interface. */ if (zserv_privs.change (ZPRIVS_RAISE)) zlog (NULL, LOG_ERR, "Can't raise privileges"); @@ -1233,15 +1249,11 @@ netlink_talk (struct nlmsghdr *n, struct nlsock *nl) } /* Routing table change via netlink interface. */ -static int -netlink_route (int cmd, int family, void *dest, int length, void *gate, - int index, int zebra_flags, int table) +static void +netlink_delroute (int family, void *dest, int length, void *gate, + int index, int table, int proto) { - int ret; - int bytelen; - struct sockaddr_nl snl; - int discard; - + int bytelen = (family == AF_INET ? 4 : 16); struct { struct nlmsghdr n; @@ -1251,60 +1263,25 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate, memset (&req, 0, sizeof req); - bytelen = (family == AF_INET ? 4 : 16); - req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg)); - req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; - req.n.nlmsg_type = cmd; + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = RTM_DELROUTE; req.r.rtm_family = family; + req.r.rtm_scope = RT_SCOPE_NOWHERE; req.r.rtm_table = table; req.r.rtm_dst_len = length; - if ((zebra_flags & ZEBRA_FLAG_BLACKHOLE) - || (zebra_flags & ZEBRA_FLAG_REJECT)) - discard = 1; - else - discard = 0; - - if (cmd == RTM_NEWROUTE) - { - req.r.rtm_protocol = RTPROT_ZEBRA; - req.r.rtm_scope = RT_SCOPE_UNIVERSE; - - if (discard) - { - if (zebra_flags & ZEBRA_FLAG_BLACKHOLE) - req.r.rtm_type = RTN_BLACKHOLE; - else if (zebra_flags & ZEBRA_FLAG_REJECT) - req.r.rtm_type = RTN_UNREACHABLE; - else - assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */ - } - else - req.r.rtm_type = RTN_UNICAST; - } - if (dest) addattr_l (&req.n, sizeof req, RTA_DST, dest, bytelen); - if (!discard) - { - if (gate) - addattr_l (&req.n, sizeof req, RTA_GATEWAY, gate, bytelen); - if (index > 0) - addattr32 (&req.n, sizeof req, RTA_OIF, index); - } + if (gate) + addattr_l (&req.n, sizeof req, RTA_GATEWAY, gate, bytelen); - /* Destination netlink address. */ - memset (&snl, 0, sizeof snl); - snl.nl_family = AF_NETLINK; + if (index > 0) + addattr32 (&req.n, sizeof req, RTA_OIF, index); /* Talk to netlink socket. */ - ret = netlink_talk (&req.n, &netlink_cmd); - if (ret < 0) - return -1; - - return 0; + netlink_talk (&req.n, &netlink_cmd); } /* Routing table change via netlink interface. */ @@ -1341,11 +1318,14 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, else discard = 0; + if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT) + req.r.rtm_protocol = RTPROT_KERNEL; + else + req.r.rtm_protocol = RTPROT_ZEBRA; + req.r.rtm_scope = rib->scope; + if (cmd == RTM_NEWROUTE) { - req.r.rtm_protocol = RTPROT_ZEBRA; - req.r.rtm_scope = RT_SCOPE_UNIVERSE; - if (discard) { if (rib->flags & ZEBRA_FLAG_BLACKHOLE) @@ -1761,12 +1741,12 @@ kernel_delete_ipv6 (struct prefix *p, struct rib *rib) } /* Delete IPv6 route from the kernel. */ -int +void kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate, - unsigned int index, int flags, int table) + unsigned int index, int table) { - return netlink_route (RTM_DELROUTE, AF_INET6, &dest->prefix, - dest->prefixlen, gate, index, flags, table); + netlink_delroute (AF_INET6, &dest->prefix, + dest->prefixlen, gate, index, table, RTPROT_ZEBRA); } #endif /* HAVE_IPV6 */ -- cgit v1.2.3 From e5d63369e1f3fdc1c22ae15fe477de1f97022703 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 18 Aug 2008 14:12:11 -0700 Subject: Filter messages so that only netlink messages from kernel are allowed. This is a refinement of the socket filter, and also closes a security hole that would allow non-kernel messages to confuse quagga. --- zebra/rt_netlink.c | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 020aaefc..1e993742 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -139,7 +139,7 @@ netlink_socket (struct nlsock *nl, unsigned long groups) int ret; struct sockaddr_nl snl; int sock; - int namelen; + socklen_t namelen; int save_errno; sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); @@ -177,7 +177,7 @@ netlink_socket (struct nlsock *nl, unsigned long groups) /* multiple netlink sockets will have different nl_pid */ namelen = sizeof snl; - ret = getsockname (sock, (struct sockaddr *) &snl, (socklen_t *) &namelen); + ret = getsockname (sock, (struct sockaddr *) &snl, &namelen); if (ret < 0 || namelen != sizeof snl) { zlog (NULL, LOG_ERR, "Can't get %s socket name: %s", nl->name, @@ -220,7 +220,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 = nl->snl.nl_pid; + req.nlh.nlmsg_pid = 0; req.nlh.nlmsg_seq = ++nl->seq; req.g.rtgen_family = family; @@ -295,6 +295,13 @@ 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_debug ("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)) { @@ -1039,13 +1046,6 @@ 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: @@ -1829,26 +1829,18 @@ kernel_read (struct thread *thread) return 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) +/* Filter out messages that are not from kernel. */ +static void netlink_install_filter (int sock) { 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] */ + /* 0: 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) */ + /* 1: jeq XX jt 5 jf 6 */ + BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0, 0, 1), + /* 2: ret 0xffff (keep) */ BPF_STMT(BPF_RET|BPF_K, 0xffff), + /* 3: ret 0 (skip) */ + BPF_STMT(BPF_RET|BPF_K, 0), }; struct sock_fprog prog = { @@ -1886,7 +1878,7 @@ kernel_init (void) if (nl_rcvbufsize) netlink_recvbuf (&netlink, nl_rcvbufsize); - netlink_install_filter (netlink.sock, netlink_cmd.snl.nl_pid); + netlink_install_filter (netlink.sock); thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock); } } -- cgit v1.2.3 From df1b37b7e0f14e5bcff29c5bae5f5e5b1d1f8e69 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 18 Aug 2008 15:23:05 -0700 Subject: Revert "Filter messages so that only netlink messages from kernel are allowed." This reverts commit e5d63369e1f3fdc1c22ae15fe477de1f97022703. --- zebra/rt_netlink.c | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 1e993742..020aaefc 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -139,7 +139,7 @@ netlink_socket (struct nlsock *nl, unsigned long groups) int ret; struct sockaddr_nl snl; int sock; - socklen_t namelen; + int namelen; int save_errno; sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); @@ -177,7 +177,7 @@ netlink_socket (struct nlsock *nl, unsigned long groups) /* multiple netlink sockets will have different nl_pid */ namelen = sizeof snl; - ret = getsockname (sock, (struct sockaddr *) &snl, &namelen); + ret = getsockname (sock, (struct sockaddr *) &snl, (socklen_t *) &namelen); if (ret < 0 || namelen != sizeof snl) { zlog (NULL, LOG_ERR, "Can't get %s socket name: %s", nl->name, @@ -220,7 +220,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; @@ -295,13 +295,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_debug ("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)) { @@ -1046,6 +1039,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: @@ -1829,18 +1829,26 @@ kernel_read (struct thread *thread) return 0; } -/* Filter out messages that are not from kernel. */ -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) { struct sock_filter filter[] = { - /* 0: ldw [12] */ + /* 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)), - /* 1: jeq XX jt 5 jf 6 */ - BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0, 0, 1), - /* 2: ret 0xffff (keep) */ - BPF_STMT(BPF_RET|BPF_K, 0xffff), - /* 3: ret 0 (skip) */ + /* 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 = { @@ -1878,7 +1886,7 @@ kernel_init (void) if (nl_rcvbufsize) netlink_recvbuf (&netlink, nl_rcvbufsize); - 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); } } -- cgit v1.2.3 From 591886e7ae3585967f7855ce34c476f40af7c36b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 18 Aug 2008 15:48:07 -0700 Subject: Fix up filtering of netlink pid There are two distinct pid's in netlink message. The one in the receive address is the pid of the sender (ie kernel), the other in the netlink message is the originator (ie quagga or ip command). --- zebra/rt_netlink.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 020aaefc..0b35f2a8 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -295,6 +295,13 @@ 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_debug ("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)) { @@ -1835,19 +1842,13 @@ kernel_read (struct thread *thread) 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] */ + /* 0: ldw [12] */ BPF_STMT(BPF_LD|BPF_ABS|BPF_W, offsetof(struct nlmsghdr, nlmsg_pid)), - /* 4: jeq XX jt 5 jf 6 */ + /* 1: jeq XX jt 2 jf 3 */ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htonl(pid), 0, 1), - /* 5: ret 0 (skip) */ + /* 2: ret 0 (skip) */ BPF_STMT(BPF_RET|BPF_K, 0), - /* 6: ret 0xffff (keep) */ + /* 3: ret 0xffff (keep) */ BPF_STMT(BPF_RET|BPF_K, 0xffff), }; -- cgit v1.2.3 From 7978e4d05ca24e62e282d4318e2332b0277137dd Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 17 Sep 2008 13:29:59 -0700 Subject: Set proper protocol for routes from command line Bugzilla 3681 fix. Routes from 'ip route' default to protocol boot. Need to use this same value when deleting or udpating. --- zebra/rt_netlink.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 0b35f2a8..80fee286 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1325,10 +1325,18 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, else discard = 0; - if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT) + switch (rib->type) { + case ZEBRA_ROUTE_KERNEL: + /* FIXME: should remember original protocol from RTM_NEWLINK */ + req.r.rtm_protocol = RTPROT_BOOT; + break; + case ZEBRA_ROUTE_CONNECT: req.r.rtm_protocol = RTPROT_KERNEL; - else + break; + default: req.r.rtm_protocol = RTPROT_ZEBRA; + } + req.r.rtm_scope = rib->scope; if (cmd == RTM_NEWROUTE) -- cgit v1.2.3 From ceaf189147231cbcb847ba8b22e20b3bee199783 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 17 Sep 2008 13:44:27 -0700 Subject: Handle device renames correctly Bugfix 3658 If inactive device is renamed, just do it. If active device is renamed, update RIB if needed. --- zebra/rt_netlink.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 80fee286..011d59d2 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -970,20 +970,16 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) unsigned long new_flags = ifi->ifi_flags & 0x0000fffff; ifp = if_lookup_by_index (ifi->ifi_index); - if (ifp && strcmp(ifp->name, name) != 0) - { - zlog_info("interface index %d was renamed from %s to %s", - ifi->ifi_index, ifp->name, name); - - strncpy(ifp->name, name, INTERFACE_NAMSIZ); - } - if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) { if (ifp == NULL) { ifp = if_create(name, strlen(name)); ifp->ifindex = ifi->ifi_index; + } + else if (strcmp(ifp->name, name) != 0) + { + strncpy(ifp->name, name, INTERFACE_NAMSIZ); } zlog_info ("interface %s index %d %s added.", @@ -1021,6 +1017,15 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) if_up (ifp); } } + else if (strcmp(ifp->name, name) != 0) + { + zlog_info("interface index %d was renamed from %s to %s", + ifi->ifi_index, ifp->name, name); + + strncpy(ifp->name, name, INTERFACE_NAMSIZ); + rib_update(); + } + } } else -- cgit v1.2.3 From 17b2df401d1b4de90fd1c7c005abc42fc9de9eb8 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 17 Sep 2008 14:14:50 -0700 Subject: Set metric in RIB for connected routes Set metric in RIB to keep OSPF happy, but don't set the metric in the kernel since the kernel portion of connected route has metric=0. Bugfix 3668 --- zebra/rt_netlink.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 011d59d2..167ea1ab 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -475,6 +475,7 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h) strncpy(ifp->name, name, INTERFACE_NAMSIZ); ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); + ifp->metric = 1; /* Hardware type and address. */ ifp->hw_type = ifi->ifi_type; @@ -976,6 +977,7 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) { ifp = if_create(name, strlen(name)); ifp->ifindex = ifi->ifi_index; + ifp->metric = 1; } else if (strcmp(ifp->name, name) != 0) { @@ -1361,8 +1363,8 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen); - /* Metric. */ - addattr32 (&req.n, sizeof req, RTA_PRIORITY, rib->metric); + if (rib->type != ZEBRA_ROUTE_CONNECT) + addattr32 (&req.n, sizeof req, RTA_PRIORITY, rib->metric); if (discard) { -- cgit v1.2.3 From c31e78dd4ac8b86fde9e8f46a40246c49044d5d8 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 18 Sep 2008 10:13:48 -0700 Subject: Add delete interface cleanout Quagga needs to fully cleanout state when interface is deleted from system. Bugfix: 3962, 3693 --- zebra/rt_netlink.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 167ea1ab..0a464f92 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1033,12 +1033,11 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) else { // RTM_DELLINK. - ifp = if_lookup_by_name (name); - + ifp = if_lookup_by_index (ifi->ifi_index); if (ifp == NULL) { - zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find", - name); + zlog (NULL, LOG_WARNING, "interface %s index %d is deleted but can't find", + name, ifi->ifi_index); return 0; } else @@ -1046,6 +1045,7 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) name, ifi->ifi_index); if_delete_update (ifp); + if_delete (ifp); } return 0; } -- cgit v1.2.3 From 6926a30b14d1f0c2905925d0e886d5a8ee1689de Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 8 Oct 2008 16:31:24 +0200 Subject: netlink message signed/unsigned cleanup Avoid possible problems where netlink message is being formatted with unsigned 32 bit value, which was being read as int. --- zebra/rt_netlink.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 0a464f92..12978c4e 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -474,7 +474,7 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h) } strncpy(ifp->name, name, INTERFACE_NAMSIZ); ifp->flags = ifi->ifi_flags & 0x0000fffff; - ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); + ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); ifp->metric = 1; /* Hardware type and address. */ @@ -720,7 +720,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) src = NULL; if (tb[RTA_OIF]) - index = *(int *) RTA_DATA (tb[RTA_OIF]); + index = *(uint32_t *) RTA_DATA (tb[RTA_OIF]); if (tb[RTA_DST]) dest = RTA_DATA (tb[RTA_DST]); @@ -735,7 +735,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) gate = RTA_DATA (tb[RTA_GATEWAY]); if (tb[RTA_PRIORITY]) - metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]); + metric = *(uint32_t *) RTA_DATA(tb[RTA_PRIORITY]); if (rtm->rtm_family == AF_INET) { @@ -852,7 +852,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) src = NULL; if (tb[RTA_OIF]) - index = *(int *) RTA_DATA (tb[RTA_OIF]); + index = *(uint32_t *) RTA_DATA (tb[RTA_OIF]); if (tb[RTA_DST]) dest = RTA_DATA (tb[RTA_DST]); @@ -988,7 +988,7 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) name, ifi->ifi_index, if_flag_dump(new_flags)); ifp->flags = new_flags; - ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); + ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); /* If new link is added. */ if_add_update (ifp); @@ -996,7 +996,7 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) else { /* Interface status change. */ - ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); + ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); if (new_flags != ifp->flags) { -- cgit v1.2.3 From d4aad5852a6be45eda78971b3b40350bc5e9ab5b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 8 Oct 2008 16:33:39 +0200 Subject: Notify on MTU changes Bugfix 3732 Notify routing protocols about MTU changes --- zebra/rt_netlink.c | 81 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 36 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 12978c4e..f9f90224 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -969,15 +969,17 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) if (h->nlmsg_type == RTM_NEWLINK) { unsigned long new_flags = ifi->ifi_flags & 0x0000fffff; + unsigned int mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); ifp = if_lookup_by_index (ifi->ifi_index); + /* New interface */ if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) { if (ifp == NULL) { - ifp = if_create(name, strlen(name)); - ifp->ifindex = ifi->ifi_index; - ifp->metric = 1; + ifp = if_create(name, strlen(name)); + ifp->ifindex = ifi->ifi_index; + ifp->metric = 1; } else if (strcmp(ifp->name, name) != 0) { @@ -988,47 +990,54 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) name, ifi->ifi_index, if_flag_dump(new_flags)); ifp->flags = new_flags; - ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); + ifp->mtu6 = ifp->mtu = mtu; - /* If new link is added. */ - if_add_update (ifp); + /* If new link is added. */ + if_add_update (ifp); } - else - { - /* Interface status change. */ - ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); + /* Interface status change. */ + else if (new_flags != ifp->flags) + { + ifp->mtu6 = ifp->mtu = mtu; - if (new_flags != ifp->flags) - { - zlog_info ("interface %s index %d changed %s.", - name, ifi->ifi_index, if_flag_dump(new_flags)); + zlog_info ("interface %s index %d changed %s.", + name, ifi->ifi_index, if_flag_dump(new_flags)); - if (if_is_operative (ifp)) - { - ifp->flags = new_flags; - if (!if_is_operative (ifp)) - if_down (ifp); - else - /* Must notify client daemons of new interface status. */ - zebra_interface_up_update (ifp); - } + if (if_is_operative (ifp)) + { + ifp->flags = new_flags; + if (!if_is_operative (ifp)) + if_down (ifp); else - { - ifp->flags = new_flags; - if (if_is_operative (ifp)) - if_up (ifp); - } + /* Must notify client daemons of new interface status. */ + zebra_interface_up_update (ifp); } - else if (strcmp(ifp->name, name) != 0) + else { - zlog_info("interface index %d was renamed from %s to %s", - ifi->ifi_index, ifp->name, name); - - strncpy(ifp->name, name, INTERFACE_NAMSIZ); - rib_update(); + ifp->flags = new_flags; + if (if_is_operative (ifp)) + if_up (ifp); } - - } + } + /* Interface name change */ + else if (strcmp(ifp->name, name) != 0) + { + ifp->mtu = ifp->mtu6 = mtu; + zlog_info("interface index %d was renamed from %s to %s", + ifi->ifi_index, ifp->name, name); + + strncpy(ifp->name, name, INTERFACE_NAMSIZ); + rib_update(); + } + /* Interface mtu change */ + else if (mtu != ifp->mtu) + { + zlog_info("interface index %d mtu changed from %u to %u", + ifp->mtu, mtu); + ifp->mtu = ifp->mtu6 = mtu; + if (if_is_operative (ifp)) + zebra_interface_up_update (ifp); + } } else { -- cgit v1.2.3