From ada3758d3977726fa3140a27a0e503787a83ab71 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 5 Feb 2010 03:55:24 +0100 Subject: zebra: netlink: kill netlink_route kernel_delete_ipv6_old is the only user of netlink_route. kill the latter, let it be assimilated by the former. --- zebra/rt_netlink.c | 117 ++++++++++++++++++----------------------------------- 1 file changed, 40 insertions(+), 77 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index d25543ff..10363e67 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1217,80 +1217,6 @@ netlink_talk (struct nlmsghdr *n, struct nlsock *nl) return netlink_parse_info (netlink_talk_filter, 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) -{ - int ret; - int bytelen; - struct sockaddr_nl snl; - int discard; - - struct - { - struct nlmsghdr n; - struct rtmsg r; - char buf[1024]; - } req; - - 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.r.rtm_family = family; - req.r.rtm_table = table; - req.r.rtm_dst_len = length; - req.r.rtm_protocol = RTPROT_ZEBRA; - req.r.rtm_scope = RT_SCOPE_UNIVERSE; - - if ((zebra_flags & ZEBRA_FLAG_BLACKHOLE) - || (zebra_flags & ZEBRA_FLAG_REJECT)) - discard = 1; - else - discard = 0; - - if (cmd == RTM_NEWROUTE) - { - 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); - } - - /* Destination netlink address. */ - memset (&snl, 0, sizeof snl); - snl.nl_family = AF_NETLINK; - - /* Talk to netlink socket. */ - ret = netlink_talk (&req.n, &netlink_cmd); - if (ret < 0) - return -1; - - return 0; -} - /* Routing table change via netlink interface. */ static int netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, @@ -1743,13 +1669,50 @@ kernel_delete_ipv6 (struct prefix *p, struct rib *rib) return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET6); } -/* Delete IPv6 route from the kernel. */ +/* Delete IPv6 route from the kernel. + * only called from rib_bogus_ipv6 */ int kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate, unsigned int index, int flags, int table) { - return netlink_route (RTM_DELROUTE, AF_INET6, &dest->prefix, - dest->prefixlen, gate, index, flags, table); + int ret; + struct sockaddr_nl snl; + + struct + { + struct nlmsghdr n; + struct rtmsg r; + char buf[1024]; + } req; + + memset (&req, 0, sizeof req); + + req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg)); + req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; + req.n.nlmsg_type = RTM_DELROUTE; + req.r.rtm_family = AF_INET6; + req.r.rtm_table = table; + req.r.rtm_dst_len = dest->prefixlen; + req.r.rtm_protocol = RTPROT_ZEBRA; + req.r.rtm_scope = RT_SCOPE_UNIVERSE; + + addattr_l (&req.n, sizeof req, RTA_DST, &dest->prefix, 16); + + if (gate) + addattr_l (&req.n, sizeof req, RTA_GATEWAY, gate, 16); + if (index > 0) + addattr32 (&req.n, sizeof req, RTA_OIF, index); + + /* Destination netlink address. */ + memset (&snl, 0, sizeof snl); + snl.nl_family = AF_NETLINK; + + /* Talk to netlink socket. */ + ret = netlink_talk (&req.n, &netlink_cmd); + if (ret < 0) + return -1; + + return 0; } #endif /* HAVE_IPV6 */ -- cgit v1.2.3 From cf245afd5dd1f8c7c80089465e610acaaa1e2f24 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 5 Feb 2010 04:31:56 +0100 Subject: zebra: cleanup blackhole support blackhole support was horribly broken. cleanup by removing blackhole stuff from ZEBRA_FLAG_*, instead add a "zflags" field inside struct rib. introduces support for "prohibit" routes (Linux/netlink only) also clean up blackhole options on "ip route" vty commands. --- zebra/rt_netlink.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 10363e67..b29cb216 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1226,7 +1226,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, struct sockaddr_nl snl; struct nexthop *nexthop = NULL; int nexthop_num = 0; - int discard; + unsigned discard; struct { @@ -1248,24 +1248,29 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, req.r.rtm_protocol = RTPROT_ZEBRA; req.r.rtm_scope = RT_SCOPE_UNIVERSE; - if ((rib->flags & ZEBRA_FLAG_BLACKHOLE) || (rib->flags & ZEBRA_FLAG_REJECT)) - discard = 1; - else - discard = 0; + discard = RIB_ZF_BLACKHOLE_FLAGS (rib->zflags); if (cmd == RTM_NEWROUTE) { - if (discard) - { - if (rib->flags & ZEBRA_FLAG_BLACKHOLE) - req.r.rtm_type = RTN_BLACKHOLE; - else if (rib->flags & ZEBRA_FLAG_REJECT) - req.r.rtm_type = RTN_UNREACHABLE; - else - assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */ - } - else - req.r.rtm_type = RTN_UNICAST; + switch (discard) + { + case RIB_ZF_REJECT: + req.r.rtm_type = RTN_UNREACHABLE; + break; + /* IPv6 only supports RTN_UNREACHABLE on Linux, it seems */ + case RIB_ZF_PROHIBIT: + req.r.rtm_type = RTN_PROHIBIT; + if (family == AF_INET6) + req.r.rtm_type = RTN_UNREACHABLE; + break; + case RIB_ZF_BLACKHOLE: + req.r.rtm_type = RTN_BLACKHOLE; + if (family == AF_INET6) + req.r.rtm_type = RTN_UNREACHABLE; + break; + default: + req.r.rtm_type = RTN_UNICAST; + } } addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen); -- cgit v1.2.3 From 38c85a4010c812a381a3e3f14bfac5db7f192d99 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 5 Feb 2010 04:58:46 +0100 Subject: zebra: netlink: grab blackhole list from kernel support processing of RTM_BLACKHOLE et al. from kernel and dump them into appropriate blackhole rib entries. this exhibits the deletion bug famously fixed by Joakim Tjernlund, if that patch isn't applied blackhole route deletion from kernel doesn't work... --- zebra/rt_netlink.c | 50 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 10 deletions(-) (limited to 'zebra/rt_netlink.c') diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index b29cb216..23acd5f3 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -85,6 +85,28 @@ extern struct zebra_privs_t zserv_privs; extern u_int32_t nl_rcvbufsize; +/* dispatch rtm_type field, return 1 if we want to process this */ +static int +get_discard_or_unicast (unsigned char rtm_type, unsigned *zflags) +{ + switch (rtm_type) + { + case RTN_UNICAST: + *zflags = 0; + return 1; + case RTN_UNREACHABLE: + *zflags = RIB_ZF_REJECT; + return 1; + case RTN_PROHIBIT: + *zflags = RIB_ZF_PROHIBIT; + return 1; + case RTN_BLACKHOLE: + *zflags = RIB_ZF_BLACKHOLE; + return 1; + } + return 0; +} + /* Note: on netlink systems, there should be a 1-to-1 mapping between interface names and ifindex values. */ static void @@ -648,6 +670,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) struct rtmsg *rtm; struct rtattr *tb[RTA_MAX + 1]; u_char flags = 0; + unsigned discard = 0; char anyaddr[16] = { 0 }; @@ -663,7 +686,8 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) if (h->nlmsg_type != RTM_NEWROUTE) return 0; - if (rtm->rtm_type != RTN_UNICAST) + + if (!get_discard_or_unicast (rtm->rtm_type, &discard)) return 0; table = rtm->rtm_table; @@ -724,7 +748,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 | (discard << 8), &p, + gate, src, index, table, metric, 0); } #ifdef HAVE_IPV6 if (rtm->rtm_family == AF_INET6) @@ -734,8 +759,8 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) memcpy (&p.prefix, dest, 16); p.prefixlen = rtm->rtm_dst_len; - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table, - metric, 0); + rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags | (discard << 8), &p, + gate, index, table, metric, 0); } #endif /* HAVE_IPV6 */ @@ -772,6 +797,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) void *dest; void *gate; void *src; + unsigned discard = 0; rtm = NLMSG_DATA (h); @@ -788,10 +814,10 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE", rtm->rtm_family == AF_INET ? "ipv4" : "ipv6", - rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast", + rtm->rtm_type == RTN_UNICAST ? "unicast" : "!unicast", lookup (rtproto_str, rtm->rtm_protocol)); - if (rtm->rtm_type != RTN_UNICAST) + if (!get_discard_or_unicast (rtm->rtm_type, &discard)) { return 0; } @@ -862,9 +888,11 @@ 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, discard << 8, &p, + gate, src, index, table, 0, 0); else - rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table); + rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, discard << 8, &p, + gate, index, table); } #ifdef HAVE_IPV6 @@ -890,9 +918,11 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) } if (h->nlmsg_type == RTM_NEWROUTE) - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, 0, 0); + rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, discard << 8, &p, + gate, index, table, 0, 0); else - rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table); + rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, discard << 8, &p, + gate, index, table); } #endif /* HAVE_IPV6 */ -- cgit v1.2.3