diff options
-rw-r--r-- | lib/zclient.c | 33 | ||||
-rw-r--r-- | lib/zclient.h | 9 | ||||
-rw-r--r-- | lib/zebra.h | 4 | ||||
-rw-r--r-- | ospfd/ospf_zebra.c | 8 | ||||
-rw-r--r-- | zebra/kernel_socket.c | 15 | ||||
-rw-r--r-- | zebra/rib.h | 30 | ||||
-rw-r--r-- | zebra/rt_ioctl.c | 2 | ||||
-rw-r--r-- | zebra/rt_netlink.c | 204 | ||||
-rw-r--r-- | zebra/rt_socket.c | 7 | ||||
-rw-r--r-- | zebra/zebra_rib.c | 140 | ||||
-rw-r--r-- | zebra/zebra_vty.c | 426 |
11 files changed, 427 insertions, 451 deletions
diff --git a/lib/zclient.c b/lib/zclient.c index 0d531ce7..8be9d040 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -405,10 +405,10 @@ zclient_connect (struct thread *t) * | IPv4 Nexthop address or Interface Index number | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * - * Alternatively, if the flags field has ZEBRA_FLAG_BLACKHOLE or - * ZEBRA_FLAG_REJECT is set then Nexthop count is set to 1, then _no_ + * Alternatively, if the route is a blackhole route (indicated to zapi + * by ZAPI_MESSAGE_BLACKHOLE), then Nexthop count is set to 1 and _no_ * nexthop information is provided, and the message describes a prefix - * to blackhole or reject route. + * to blackhole route. * * If ZAPI_MESSAGE_DISTANCE is set, the distance value is written as a 1 * byte value. @@ -424,8 +424,18 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p, { int i; int psize; + int blackhole = 0; struct stream *s; + /* blackhole routes are sent as containing a single nexthop + * of type blackhole. */ + if (CHECK_FLAG (api->message, ZAPI_MESSAGE_BLACKHOLE)) + { + blackhole = 1; + UNSET_FLAG (api->message, ZAPI_MESSAGE_BLACKHOLE); + SET_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP); + } + /* Reset stream. */ s = zclient->obuf; stream_reset (s); @@ -443,17 +453,14 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p, stream_write (s, (u_char *) & p->prefix, psize); /* Nexthop, ifindex, distance and metric information. */ - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP)) + if (blackhole) { - if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE)) - { - stream_putc (s, 1); - stream_putc (s, ZEBRA_NEXTHOP_BLACKHOLE); - /* XXX assert(api->nexthop_num == 0); */ - /* XXX assert(api->ifindex_num == 0); */ - } - else - stream_putc (s, api->nexthop_num + api->ifindex_num); + stream_putc (s, 1); + stream_putc (s, ZEBRA_NEXTHOP_BLACKHOLE); + } + else if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP)) + { + stream_putc (s, api->nexthop_num + api->ifindex_num); for (i = 0; i < api->nexthop_num; i++) { diff --git a/lib/zclient.h b/lib/zclient.h index 6a63ffa4..7cce73f5 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -85,10 +85,11 @@ struct zclient }; /* Zebra API message flag. */ -#define ZAPI_MESSAGE_NEXTHOP 0x01 -#define ZAPI_MESSAGE_IFINDEX 0x02 -#define ZAPI_MESSAGE_DISTANCE 0x04 -#define ZAPI_MESSAGE_METRIC 0x08 +#define ZAPI_MESSAGE_NEXTHOP 0x01 +#define ZAPI_MESSAGE_IFINDEX 0x02 +#define ZAPI_MESSAGE_DISTANCE 0x04 +#define ZAPI_MESSAGE_METRIC 0x08 +#define ZAPI_MESSAGE_BLACKHOLE 0x10 /* only for zapi_ipv4_route */ /* Zserv protocol message header */ struct zserv_header diff --git a/lib/zebra.h b/lib/zebra.h index 757a3757..63eb373a 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -469,12 +469,12 @@ extern const char *zserv_command_string (unsigned int command); /* Zebra message flags */ #define ZEBRA_FLAG_INTERNAL 0x01 #define ZEBRA_FLAG_SELFROUTE 0x02 -#define ZEBRA_FLAG_BLACKHOLE 0x04 +/* 0x04 was: FLAG_BLACKHOLE */ #define ZEBRA_FLAG_IBGP 0x08 #define ZEBRA_FLAG_SELECTED 0x10 #define ZEBRA_FLAG_CHANGED 0x20 #define ZEBRA_FLAG_STATIC 0x40 -#define ZEBRA_FLAG_REJECT 0x80 +/* 0x80 was: FLAG_REJECT */ /* Zebra nexthop flags. */ #define ZEBRA_NEXTHOP_IFINDEX 1 diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index bcc8905f..484aba98 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -493,9 +493,9 @@ ospf_zebra_add_discard (struct prefix_ipv4 *p) if (zclient->redist[ZEBRA_ROUTE_OSPF]) { api.type = ZEBRA_ROUTE_OSPF; - api.flags = ZEBRA_FLAG_BLACKHOLE; + api.flags = 0; api.message = 0; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); + SET_FLAG (api.message, ZAPI_MESSAGE_BLACKHOLE); api.nexthop_num = 0; api.ifindex_num = 0; @@ -515,9 +515,9 @@ ospf_zebra_delete_discard (struct prefix_ipv4 *p) if (zclient->redist[ZEBRA_ROUTE_OSPF]) { api.type = ZEBRA_ROUTE_OSPF; - api.flags = ZEBRA_FLAG_BLACKHOLE; + api.flags = 0; api.message = 0; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); + SET_FLAG (api.message, ZAPI_MESSAGE_BLACKHOLE); api.nexthop_num = 0; api.ifindex_num = 0; diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 639617a5..d0908115 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -839,9 +839,9 @@ rtm_read (struct rt_msghdr *rtm) /* This is a reject or blackhole route */ if (flags & RTF_REJECT) - SET_FLAG (zebra_flags, ZEBRA_FLAG_REJECT); + SET_FLAG (zebra_flags, RIB_ZF_REJECT << 8); if (flags & RTF_BLACKHOLE) - SET_FLAG (zebra_flags, ZEBRA_FLAG_BLACKHOLE); + SET_FLAG (zebra_flags, RIB_ZF_BLACKHOLE << 8); if (dest.sa.sa_family == AF_INET) { @@ -1072,11 +1072,12 @@ rtm_write (int message, msg.rtm.rtm_flags |= (RTF_PROTO1); /* Additional flags. */ - if (zebra_flags & ZEBRA_FLAG_BLACKHOLE) - msg.rtm.rtm_flags |= RTF_BLACKHOLE; - if (zebra_flags & ZEBRA_FLAG_REJECT) - msg.rtm.rtm_flags |= RTF_REJECT; - + if (RIB_ZF_BLACKHOLE_FLAGS (zebra_flags >> 8)) + { + unsigned bh_type = RIB_ZF_BLACKHOLE_FLAGS(zebra_flags >> 8); + msg.rtm.rtm_flags |= (bh_type == RIB_ZF_REJECT) + ? RTF_REJECT : RTF_BLACKHOLE; + } #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN #define SOCKADDRSET(X,R) \ diff --git a/zebra/rib.h b/zebra/rib.h index 499d48b2..2abfed19 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -73,6 +73,15 @@ struct rib */ u_char flags; + /* flags internal to zebra, not sent to clients */ + unsigned zflags; + /* blackhole route zflags, for static routes: */ +#define RIB_ZF_REJECT 1 +#define RIB_ZF_PROHIBIT 2 +#define RIB_ZF_BLACKHOLE 3 + +#define RIB_ZF_BLACKHOLE_FLAGS(zflags) ((zflags) & RIB_ZF_BLACKHOLE) + /* RIB internal status */ u_char status; #define RIB_ENTRY_REMOVED (1 << 0) @@ -120,12 +129,8 @@ struct static_ipv4 char *ifname; } gate; - /* bit flags */ - u_char flags; -/* - see ZEBRA_FLAG_REJECT - ZEBRA_FLAG_BLACKHOLE - */ + /* zflags for rib */ + unsigned zflags; }; #ifdef HAVE_IPV6 @@ -144,17 +149,14 @@ struct static_ipv6 #define STATIC_IPV6_GATEWAY 1 #define STATIC_IPV6_GATEWAY_IFNAME 2 #define STATIC_IPV6_IFNAME 3 +#define STATIC_IPV6_BLACKHOLE 4 /* Nexthop value. */ struct in6_addr ipv6; char *ifname; - /* bit flags */ - u_char flags; -/* - see ZEBRA_FLAG_REJECT - ZEBRA_FLAG_BLACKHOLE - */ + /* zflags for rib */ + unsigned zflags; }; #endif /* HAVE_IPV6 */ @@ -270,7 +272,7 @@ extern void rib_init (void); extern int static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, - u_char flags, u_char distance, u_int32_t vrf_id); + unsigned zflags, u_char distance, u_int32_t vrf_id); extern int static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, @@ -294,7 +296,7 @@ extern struct route_table *rib_table_ipv6; extern int static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - const char *ifname, u_char flags, u_char distance, + const char *ifname, unsigned zflags, u_char distance, u_int32_t vrf_id); extern int diff --git a/zebra/rt_ioctl.c b/zebra/rt_ioctl.c index a5d588c7..390e6a1d 100644 --- a/zebra/rt_ioctl.c +++ b/zebra/rt_ioctl.c @@ -183,7 +183,7 @@ kernel_ioctl_ipv4 (u_long cmd, struct prefix *p, struct rib *rib, int family) #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ sin_dest.sin_addr = p->u.prefix4; - if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE)) + if (RIB_ZF_BLACKHOLE_FLAGS (rib->zflags)) { SET_FLAG (rtentry.rt_flags, RTF_REJECT); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index d25543ff..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 */ @@ -1219,80 +1249,6 @@ 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) -{ - 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, int family) { @@ -1300,7 +1256,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 { @@ -1322,24 +1278,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); @@ -1743,13 +1704,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 */ diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index 1b8ded7e..4fadc7e9 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -163,7 +163,7 @@ kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib *rib, int family) (union sockunion *)mask, gate ? (union sockunion *)&sin_gate : NULL, ifindex, - rib->flags, + rib->flags | (rib->zflags << 8), rib->metric); if (IS_ZEBRA_DEBUG_RIB) @@ -286,7 +286,8 @@ sin6_masklen (struct in6_addr mask) return len; } -/* Interface between zebra message and rtm message. */ +/* Interface between zebra message and rtm message. + * only called by kernel_delete_ipv6_old by rib_bogus_ipv6 */ static int kernel_rtm_ipv6 (int message, struct prefix_ipv6 *dest, struct in6_addr *gate, int index, int flags) @@ -453,7 +454,7 @@ kernel_rtm_ipv6_multipath (int cmd, struct prefix *p, struct rib *rib, (union sockunion *) mask, gate ? (union sockunion *)&sin_gate : NULL, ifindex, - rib->flags, + rib->flags | (rib->zflags << 8), rib->metric); #if 0 diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 6ac43d8c..a10ca84b 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -299,7 +299,6 @@ nexthop_blackhole_add (struct rib *rib) nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); nexthop->type = NEXTHOP_TYPE_BLACKHOLE; - SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE); nexthop_add (rib, nexthop); @@ -1645,13 +1644,16 @@ rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p, rib->type = type; rib->distance = distance; rib->flags = flags; + rib->zflags = flags >> 8; rib->metric = metric; rib->table = vrf_id; rib->nexthop_num = 0; rib->uptime = time (NULL); /* Nexthop settings. */ - if (gate) + if (RIB_ZF_BLACKHOLE_FLAGS (rib->zflags)) + nexthop_blackhole_add (rib); + else if (gate) { if (ifindex) nexthop_ipv4_ifindex_add (rib, gate, src, ifindex); @@ -1924,6 +1926,7 @@ rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p, struct nexthop *nexthop; char buf1[INET_ADDRSTRLEN]; char buf2[INET_ADDRSTRLEN]; + unsigned discard = RIB_ZF_BLACKHOLE_FLAGS (flags >> 8); /* Lookup table. */ table = vrf_table (AFI_IP, SAFI_UNICAST, 0); @@ -1933,12 +1936,19 @@ rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p, /* Apply mask. */ apply_mask_ipv4 (p); - if (IS_ZEBRA_DEBUG_KERNEL && gate) - zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d", - inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN), - p->prefixlen, - inet_ntoa (*gate), - ifindex); + if (IS_ZEBRA_DEBUG_KERNEL) + if (gate) + zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d", + inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ), + p->prefixlen, + inet_ntoa (*gate), + ifindex); + else + zlog_debug ("rib_delete_ipv4(): route delete %s/%d ifname %s ifindex %d", + inet_ntop (AF_INET, &p->prefix, buf1, BUFSIZ), + p->prefixlen, + ifindex2ifname(ifindex), + ifindex); /* Lookup route node. */ rn = route_node_lookup (table, (struct prefix *) p); @@ -1972,11 +1982,37 @@ rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p, if (rib->type != type) continue; - if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) && - nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex) + + if (rib->zflags == discard) { - if (rib->refcnt) + same = rib; + break; + } + if (gate) + { + for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) + if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) || + IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate)) + /* make sure ifindex matches if specified */ + if (!ifindex || ifindex == nexthop->ifindex) + break; + + if (nexthop) { + same = rib; + break; + } + } + else + { + nexthop = rib->nexthop; + if (nexthop && nexthop->ifindex != ifindex) + continue; + if (nexthop && + rib->type == ZEBRA_ROUTE_CONNECT && + nexthop->type == NEXTHOP_TYPE_IFINDEX && + rib->refcnt) + { /* Duplicated connected route. */ rib->refcnt--; route_unlock_node (rn); route_unlock_node (rn); @@ -1985,15 +2021,6 @@ rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p, same = rib; break; } - /* Make sure that the route found has the same gateway. */ - else if (gate == NULL || - ((nexthop = rib->nexthop) && - (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) || - IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate)))) - { - same = rib; - break; - } } /* If same type of route can't be found and this message is from @@ -2105,7 +2132,7 @@ static_install_ipv4 (struct prefix *p, struct static_ipv4 *si) } /* Save the flags of this static routes (reject, blackhole) */ - rib->flags = si->flags; + rib->zflags = si->zflags; /* Link this rib to the tree. */ rib_addnode (rn, rib); @@ -2193,7 +2220,7 @@ static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si) /* Add static route into static route configuration. */ int static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, - u_char flags, u_char distance, u_int32_t vrf_id) + unsigned zflags, u_char distance, u_int32_t vrf_id) { u_char type = 0; struct route_node *rn; @@ -2212,12 +2239,14 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, rn = route_node_get (stable, p); /* Make flags. */ - if (gate) + if (RIB_ZF_BLACKHOLE_FLAGS (zflags)) + type = STATIC_IPV4_BLACKHOLE; + else if (gate) type = STATIC_IPV4_GATEWAY; else if (ifname) type = STATIC_IPV4_IFNAME; else - type = STATIC_IPV4_BLACKHOLE; + return -1; /* Do nothing if there is a same static route. */ for (si = rn->info; si; si = si->next) @@ -2245,7 +2274,7 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, si->type = type; si->distance = distance; - si->flags = flags; + si->zflags = zflags; if (gate) si->gate.ipv4 = *gate; @@ -2434,6 +2463,7 @@ rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p, rib->type = type; rib->distance = distance; rib->flags = flags; + rib->zflags = flags >> 8; rib->metric = metric; rib->table = vrf_id; rib->nexthop_num = 0; @@ -2479,6 +2509,7 @@ rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p, struct nexthop *nexthop; char buf1[INET6_ADDRSTRLEN]; char buf2[INET6_ADDRSTRLEN]; + unsigned discard = RIB_ZF_BLACKHOLE_FLAGS (flags >> 8); /* Apply mask. */ apply_mask_ipv6 (p); @@ -2520,11 +2551,37 @@ rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p, if (rib->type != type) continue; - if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) && - nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex) + + if (rib->zflags == discard) + { + same = rib; + break; + } + if (gate) { - if (rib->refcnt) + for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) + if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) || + IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate)) + /* make sure ifindex matches if specified */ + if (!ifindex || ifindex == nexthop->ifindex) + break; + + if (nexthop) { + same = rib; + break; + } + } + else + { + nexthop = rib->nexthop; + if (nexthop && nexthop->ifindex != ifindex) + continue; + if (nexthop && + rib->type == ZEBRA_ROUTE_CONNECT && + nexthop->type == NEXTHOP_TYPE_IFINDEX && + rib->refcnt) + { /* Duplicated connected route. */ rib->refcnt--; route_unlock_node (rn); route_unlock_node (rn); @@ -2533,15 +2590,7 @@ rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p, same = rib; break; } - /* Make sure that the route found has the same gateway. */ - else if (gate == NULL || - ((nexthop = rib->nexthop) && - (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) || - IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate)))) - { - same = rib; - break; - } + } /* If same type of route can't be found and this message is from @@ -2627,6 +2676,9 @@ static_install_ipv6 (struct prefix *p, struct static_ipv6 *si) case STATIC_IPV6_GATEWAY_IFNAME: nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname); break; + case STATIC_IPV6_BLACKHOLE: + nexthop_blackhole_add (rib); + break; } rib_queue_add (&zebrad, rn); } @@ -2651,10 +2703,13 @@ static_install_ipv6 (struct prefix *p, struct static_ipv6 *si) case STATIC_IPV6_GATEWAY_IFNAME: nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname); break; + case STATIC_IPV6_BLACKHOLE: + nexthop_blackhole_add (rib); + break; } /* Save the flags of this static routes (reject, blackhole) */ - rib->flags = si->flags; + rib->zflags = si->zflags; /* Link this rib to the tree. */ rib_addnode (rn, rib); @@ -2677,6 +2732,9 @@ static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si) && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6) && strcmp (nexthop->ifname, si->ifname) == 0) return 1; + if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE + && si->type == STATIC_IPV6_BLACKHOLE) + return 1; return 0; } @@ -2745,7 +2803,7 @@ static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si) /* Add static route into static route configuration. */ int static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - const char *ifname, u_char flags, u_char distance, + const char *ifname, unsigned zflags, u_char distance, u_int32_t vrf_id) { struct route_node *rn; @@ -2788,7 +2846,7 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, si->type = type; si->distance = distance; - si->flags = flags; + si->zflags = zflags; switch (type) { @@ -2802,6 +2860,8 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, si->ipv6 = *gate; si->ifname = XSTRDUP (0, ifname); break; + case STATIC_IPV6_BLACKHOLE: + break; } /* Add new static route information to the tree with sort by diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 05485a13..db56a335 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -30,6 +30,50 @@ #include "zebra/zserv.h" +/* small helper for blackhole routes */ +static const struct message blackhole_str[] = { + {RIB_ZF_REJECT, "reject"}, + {RIB_ZF_PROHIBIT, "prohibit"}, + {RIB_ZF_BLACKHOLE, "blackhole"}, + {0, NULL} +}; + +#define BLACKHOLE_NAME(type) \ + lookup (blackhole_str, RIB_ZF_BLACKHOLE_FLAGS(type)) + +#define BLACKHOLE_CMD "(reject|prohibit|blackhole)" +#define BLACKHOLE_STR \ + "Emit ICMP unreachable when matched\n" \ + "Emit ICMP prohibited when matched\n" \ + "Silently discard packets\n" + +static unsigned +zebra_static_parse_flags (const char *gate_str, const char *flag_str) +{ + unsigned zflags = 0; + + /* Null0 static route. */ + if ((gate_str != NULL) && (strncasecmp (gate_str, "Null0", strlen (gate_str)) == 0)) + zflags = RIB_ZF_BLACKHOLE; + + /* Route flags. override RIB_ZF_BLACKHOLE from above if given. */ + if (flag_str) { + switch (tolower (flag_str[0])) { + case 'r': + zflags = RIB_ZF_REJECT; + break; + case 'p': + zflags = RIB_ZF_PROHIBIT; + break; + case 'b': + zflags = RIB_ZF_BLACKHOLE; + break; + /* syntax checking happens in vty code */ + } + } + return zflags; +} + /* General fucntion for static route. */ static int zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, @@ -42,7 +86,7 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, struct in_addr gate; struct in_addr mask; const char *ifname; - u_char flag = 0; + unsigned zflags; ret = str2prefix (dest_str, &p); if (ret <= 0) @@ -72,42 +116,13 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, else distance = ZEBRA_STATIC_DISTANCE_DEFAULT; - /* Null0 static route. */ - if ((gate_str != NULL) && (strncasecmp (gate_str, "Null0", strlen (gate_str)) == 0)) - { - if (flag_str) - { - vty_out (vty, "%% can not have flag %s with Null0%s", flag_str, VTY_NEWLINE); - return CMD_WARNING; - } - if (add_cmd) - static_add_ipv4 (&p, NULL, NULL, ZEBRA_FLAG_BLACKHOLE, distance, 0); - else - static_delete_ipv4 (&p, NULL, NULL, distance, 0); - return CMD_SUCCESS; - } + zflags = zebra_static_parse_flags (gate_str, flag_str); - /* Route flags */ - if (flag_str) { - switch(flag_str[0]) { - case 'r': - case 'R': /* XXX */ - SET_FLAG (flag, ZEBRA_FLAG_REJECT); - break; - case 'b': - case 'B': /* XXX */ - SET_FLAG (flag, ZEBRA_FLAG_BLACKHOLE); - break; - default: - vty_out (vty, "%% Malformed flag %s %s", flag_str, VTY_NEWLINE); - return CMD_WARNING; - } - } - - if (gate_str == NULL) + /* blackhole with nexthop makes no sense, don't add nexthop */ + if (gate_str == NULL || RIB_ZF_BLACKHOLE_FLAGS (zflags)) { if (add_cmd) - static_add_ipv4 (&p, NULL, NULL, flag, distance, 0); + static_add_ipv4 (&p, NULL, NULL, zflags, distance, 0); else static_delete_ipv4 (&p, NULL, NULL, distance, 0); @@ -123,7 +138,7 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, ifname = gate_str; if (add_cmd) - static_add_ipv4 (&p, ifname ? NULL : &gate, ifname, flag, distance, 0); + static_add_ipv4 (&p, ifname ? NULL : &gate, ifname, 0, distance, 0); else static_delete_ipv4 (&p, ifname ? NULL : &gate, ifname, distance, 0); @@ -146,26 +161,25 @@ DEFUN (ip_route, DEFUN (ip_route_flags, ip_route_flags_cmd, - "ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole)", + "ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) " BLACKHOLE_CMD, IP_STR "Establish static routes\n" "IP destination prefix (e.g. 10.0.0.0/8)\n" "IP gateway address\n" "IP gateway interface name\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n") + "Null interface\n" + BLACKHOLE_STR) { return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL); } DEFUN (ip_route_flags2, ip_route_flags2_cmd, - "ip route A.B.C.D/M (reject|blackhole)", + "ip route A.B.C.D/M " BLACKHOLE_CMD, IP_STR "Establish static routes\n" "IP destination prefix (e.g. 10.0.0.0/8)\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n") + BLACKHOLE_STR) { return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], NULL); } @@ -187,28 +201,27 @@ DEFUN (ip_route_mask, DEFUN (ip_route_mask_flags, ip_route_mask_flags_cmd, - "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole)", + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) " BLACKHOLE_CMD, IP_STR "Establish static routes\n" "IP destination prefix\n" "IP destination prefix mask\n" "IP gateway address\n" "IP gateway interface name\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n") + "Null interface\n" + BLACKHOLE_STR) { return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL); } DEFUN (ip_route_mask_flags2, ip_route_mask_flags2_cmd, - "ip route A.B.C.D A.B.C.D (reject|blackhole)", + "ip route A.B.C.D A.B.C.D " BLACKHOLE_CMD, IP_STR "Establish static routes\n" "IP destination prefix\n" "IP destination prefix mask\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n") + BLACKHOLE_STR) { return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], NULL); } @@ -230,14 +243,14 @@ DEFUN (ip_route_distance, DEFUN (ip_route_flags_distance, ip_route_flags_distance_cmd, - "ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>", + "ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) " BLACKHOLE_CMD " <1-255>", IP_STR "Establish static routes\n" "IP destination prefix (e.g. 10.0.0.0/8)\n" "IP gateway address\n" "IP gateway interface name\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n" + "Null interface\n" + BLACKHOLE_STR "Distance value for this route\n") { return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3]); @@ -245,12 +258,11 @@ DEFUN (ip_route_flags_distance, DEFUN (ip_route_flags_distance2, ip_route_flags_distance2_cmd, - "ip route A.B.C.D/M (reject|blackhole) <1-255>", + "ip route A.B.C.D/M " BLACKHOLE_CMD " <1-255>", IP_STR "Establish static routes\n" "IP destination prefix (e.g. 10.0.0.0/8)\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n" + BLACKHOLE_STR "Distance value for this route\n") { return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], argv[2]); @@ -273,30 +285,29 @@ DEFUN (ip_route_mask_distance, DEFUN (ip_route_mask_flags_distance, ip_route_mask_flags_distance_cmd, - "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>", + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) " BLACKHOLE_CMD " <1-255>", IP_STR "Establish static routes\n" "IP destination prefix\n" "IP destination prefix mask\n" "IP gateway address\n" "IP gateway interface name\n" - "Distance value for this route\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n") + "Null interface\n" + BLACKHOLE_STR + "Distance value for this route\n") { return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4]); } DEFUN (ip_route_mask_flags_distance2, ip_route_mask_flags_distance2_cmd, - "ip route A.B.C.D A.B.C.D (reject|blackhole) <1-255>", + "ip route A.B.C.D A.B.C.D " BLACKHOLE_CMD " <1-255>", IP_STR "Establish static routes\n" "IP destination prefix\n" "IP destination prefix mask\n" - "Distance value for this route\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n") + BLACKHOLE_STR + "Distance value for this route\n") { return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3]); } @@ -317,25 +328,24 @@ DEFUN (no_ip_route, ALIAS (no_ip_route, no_ip_route_flags_cmd, - "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole)", + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) " BLACKHOLE_CMD, NO_STR IP_STR "Establish static routes\n" "IP destination prefix (e.g. 10.0.0.0/8)\n" "IP gateway address\n" "IP gateway interface name\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n") + "Null interface\n" + BLACKHOLE_STR) DEFUN (no_ip_route_flags2, no_ip_route_flags2_cmd, - "no ip route A.B.C.D/M (reject|blackhole)", + "no ip route A.B.C.D/M " BLACKHOLE_CMD, NO_STR IP_STR "Establish static routes\n" "IP destination prefix (e.g. 10.0.0.0/8)\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n") + BLACKHOLE_STR) { return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, NULL, NULL); } @@ -357,7 +367,7 @@ DEFUN (no_ip_route_mask, ALIAS (no_ip_route_mask, no_ip_route_mask_flags_cmd, - "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole)", + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) " BLACKHOLE_CMD, NO_STR IP_STR "Establish static routes\n" @@ -365,19 +375,18 @@ ALIAS (no_ip_route_mask, "IP destination prefix mask\n" "IP gateway address\n" "IP gateway interface name\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n") + "Null interface\n" + BLACKHOLE_STR) DEFUN (no_ip_route_mask_flags2, no_ip_route_mask_flags2_cmd, - "no ip route A.B.C.D A.B.C.D (reject|blackhole)", + "no ip route A.B.C.D A.B.C.D " BLACKHOLE_CMD, NO_STR IP_STR "Establish static routes\n" "IP destination prefix\n" "IP destination prefix mask\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n") + BLACKHOLE_STR) { return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, NULL, NULL); } @@ -399,15 +408,15 @@ DEFUN (no_ip_route_distance, DEFUN (no_ip_route_flags_distance, no_ip_route_flags_distance_cmd, - "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>", + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) " BLACKHOLE_CMD " <1-255>", NO_STR IP_STR "Establish static routes\n" "IP destination prefix (e.g. 10.0.0.0/8)\n" "IP gateway address\n" "IP gateway interface name\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n" + "Null interface\n" + BLACKHOLE_STR "Distance value for this route\n") { return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], argv[3]); @@ -415,13 +424,12 @@ DEFUN (no_ip_route_flags_distance, DEFUN (no_ip_route_flags_distance2, no_ip_route_flags_distance2_cmd, - "no ip route A.B.C.D/M (reject|blackhole) <1-255>", + "no ip route A.B.C.D/M " BLACKHOLE_CMD " <1-255>", NO_STR IP_STR "Establish static routes\n" "IP destination prefix (e.g. 10.0.0.0/8)\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n" + BLACKHOLE_STR "Distance value for this route\n") { return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, argv[1], argv[2]); @@ -445,7 +453,7 @@ DEFUN (no_ip_route_mask_distance, DEFUN (no_ip_route_mask_flags_distance, no_ip_route_mask_flags_distance_cmd, - "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>", + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) " BLACKHOLE_CMD " <1-255>", NO_STR IP_STR "Establish static routes\n" @@ -453,8 +461,8 @@ DEFUN (no_ip_route_mask_flags_distance, "IP destination prefix mask\n" "IP gateway address\n" "IP gateway interface name\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n" + "Null interface\n" + BLACKHOLE_STR "Distance value for this route\n") { return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4]); @@ -462,14 +470,13 @@ DEFUN (no_ip_route_mask_flags_distance, DEFUN (no_ip_route_mask_flags_distance2, no_ip_route_mask_flags_distance2_cmd, - "no ip route A.B.C.D A.B.C.D (reject|blackhole) <1-255>", + "no ip route A.B.C.D A.B.C.D " BLACKHOLE_CMD " <1-255>", NO_STR IP_STR "Establish static routes\n" "IP destination prefix\n" "IP destination prefix mask\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n" + BLACKHOLE_STR "Distance value for this route\n") { return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3]); @@ -546,10 +553,6 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn) vty_out (vty, ", best"); if (rib->refcnt) vty_out (vty, ", refcnt %ld", rib->refcnt); - if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE)) - vty_out (vty, ", blackhole"); - if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT)) - vty_out (vty, ", reject"); vty_out (vty, "%s", VTY_NEWLINE); #define ONE_DAY_SECOND 60*60*24 @@ -603,10 +606,10 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn) case NEXTHOP_TYPE_IFNAME: vty_out (vty, " directly connected, %s", nexthop->ifname); break; - case NEXTHOP_TYPE_BLACKHOLE: - vty_out (vty, " directly connected, Null0"); - break; - default: + case NEXTHOP_TYPE_BLACKHOLE: + vty_out (vty, " Null0, %s", BLACKHOLE_NAME (rib->zflags)); + break; + default: break; } if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) @@ -713,10 +716,10 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib) case NEXTHOP_TYPE_IFNAME: vty_out (vty, " is directly connected, %s", nexthop->ifname); break; - case NEXTHOP_TYPE_BLACKHOLE: - vty_out (vty, " is directly connected, Null0"); - break; - default: + case NEXTHOP_TYPE_BLACKHOLE: + vty_out (vty, " Null0, %s", BLACKHOLE_NAME (rib->zflags)); + break; + default: break; } if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) @@ -767,11 +770,6 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib) break; } - if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE)) - vty_out (vty, ", bh"); - if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT)) - vty_out (vty, ", rej"); - if (rib->type == ZEBRA_ROUTE_RIP || rib->type == ZEBRA_ROUTE_OSPF || rib->type == ZEBRA_ROUTE_ISIS @@ -1141,19 +1139,9 @@ static_config_ipv4 (struct vty *vty) case STATIC_IPV4_IFNAME: vty_out (vty, " %s", si->gate.ifname); break; - case STATIC_IPV4_BLACKHOLE: - vty_out (vty, " Null0"); - break; - } - - /* flags are incompatible with STATIC_IPV4_BLACKHOLE */ - if (si->type != STATIC_IPV4_BLACKHOLE) - { - if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT)) - vty_out (vty, " %s", "reject"); - - if (CHECK_FLAG(si->flags, ZEBRA_FLAG_BLACKHOLE)) - vty_out (vty, " %s", "blackhole"); + case STATIC_IPV4_BLACKHOLE: + vty_out (vty, " Null0 %s", BLACKHOLE_NAME (si->zflags)); + break; } if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) @@ -1210,7 +1198,7 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, struct in6_addr gate_addr; u_char type = 0; int table = 0; - u_char flag = 0; + unsigned zflags; ret = str2prefix (dest_str, &p); if (ret <= 0) @@ -1222,22 +1210,7 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, /* Apply mask for given prefix. */ apply_mask (&p); - /* Route flags */ - if (flag_str) { - switch(flag_str[0]) { - case 'r': - case 'R': /* XXX */ - SET_FLAG (flag, ZEBRA_FLAG_REJECT); - break; - case 'b': - case 'B': /* XXX */ - SET_FLAG (flag, ZEBRA_FLAG_BLACKHOLE); - break; - default: - vty_out (vty, "%% Malformed flag %s %s", flag_str, VTY_NEWLINE); - return CMD_WARNING; - } - } + zflags = zebra_static_parse_flags (gate_str, flag_str); /* Administrative distance. */ if (distance_str) @@ -1245,6 +1218,17 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, else distance = ZEBRA_STATIC_DISTANCE_DEFAULT; + /* blackhole routes don't have nexthops */ + if (RIB_ZF_BLACKHOLE_FLAGS (zflags)) + { + type = STATIC_IPV6_BLACKHOLE; + if (add_cmd) + static_add_ipv6 (&p, type, NULL, NULL, zflags, distance, table); + else + static_delete_ipv6 (&p, type, NULL, NULL, distance, table); + return CMD_SUCCESS; + } + /* When gateway is valid IPv6 addrees, then gate is treated as nexthop address other case gate is treated as interface name. */ ret = inet_pton (AF_INET6, gate_str, &gate_addr); @@ -1276,7 +1260,7 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, } if (add_cmd) - static_add_ipv6 (&p, type, gate, ifname, flag, distance, table); + static_add_ipv6 (&p, type, gate, ifname, zflags, distance, table); else static_delete_ipv6 (&p, type, gate, ifname, distance, table); @@ -1295,20 +1279,6 @@ DEFUN (ipv6_route, return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL); } -DEFUN (ipv6_route_flags, - ipv6_route_flags_cmd, - "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole)", - IP_STR - "Establish static routes\n" - "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" - "IPv6 gateway address\n" - "IPv6 gateway interface name\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n") -{ - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL); -} - DEFUN (ipv6_route_ifname, ipv6_route_ifname_cmd, "ipv6 route X:X::X:X/M X:X::X:X INTERFACE", @@ -1321,20 +1291,6 @@ DEFUN (ipv6_route_ifname, return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL); } -DEFUN (ipv6_route_ifname_flags, - ipv6_route_ifname_flags_cmd, - "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole)", - IP_STR - "Establish static routes\n" - "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" - "IPv6 gateway address\n" - "IPv6 gateway interface name\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n") -{ - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL); -} - DEFUN (ipv6_route_pref, ipv6_route_pref_cmd, "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>", @@ -1348,21 +1304,6 @@ DEFUN (ipv6_route_pref, return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2]); } -DEFUN (ipv6_route_flags_pref, - ipv6_route_flags_pref_cmd, - "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) <1-255>", - IP_STR - "Establish static routes\n" - "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" - "IPv6 gateway address\n" - "IPv6 gateway interface name\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n" - "Distance value for this prefix\n") -{ - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3]); -} - DEFUN (ipv6_route_ifname_pref, ipv6_route_ifname_pref_cmd, "ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>", @@ -1376,21 +1317,6 @@ DEFUN (ipv6_route_ifname_pref, return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3]); } -DEFUN (ipv6_route_ifname_flags_pref, - ipv6_route_ifname_flags_pref_cmd, - "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) <1-255>", - IP_STR - "Establish static routes\n" - "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" - "IPv6 gateway address\n" - "IPv6 gateway interface name\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n" - "Distance value for this prefix\n") -{ - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4]); -} - DEFUN (no_ipv6_route, no_ipv6_route_cmd, "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE)", @@ -1404,18 +1330,6 @@ DEFUN (no_ipv6_route, return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL); } -ALIAS (no_ipv6_route, - no_ipv6_route_flags_cmd, - "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole)", - NO_STR - IP_STR - "Establish static routes\n" - "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" - "IPv6 gateway address\n" - "IPv6 gateway interface name\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n") - DEFUN (no_ipv6_route_ifname, no_ipv6_route_ifname_cmd, "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE", @@ -1429,18 +1343,6 @@ DEFUN (no_ipv6_route_ifname, return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL); } -ALIAS (no_ipv6_route_ifname, - no_ipv6_route_ifname_flags_cmd, - "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole)", - NO_STR - IP_STR - "Establish static routes\n" - "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" - "IPv6 gateway address\n" - "IPv6 gateway interface name\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n") - DEFUN (no_ipv6_route_pref, no_ipv6_route_pref_cmd, "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>", @@ -1455,53 +1357,70 @@ DEFUN (no_ipv6_route_pref, return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2]); } -DEFUN (no_ipv6_route_flags_pref, - no_ipv6_route_flags_pref_cmd, - "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) <1-255>", +DEFUN (no_ipv6_route_ifname_pref, + no_ipv6_route_ifname_pref_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>", NO_STR IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" "IPv6 gateway address\n" "IPv6 gateway interface name\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n" "Distance value for this prefix\n") { - /* We do not care about argv[2] */ - return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3]); + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3]); } -DEFUN (no_ipv6_route_ifname_pref, - no_ipv6_route_ifname_pref_cmd, - "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>", - NO_STR +DEFUN (ipv6_route_blackhole, + ipv6_route_blackhole_cmd, + "ipv6 route X:X::X:X/M Null0 " BLACKHOLE_CMD, IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" - "IPv6 gateway address\n" - "IPv6 gateway interface name\n" + "Specify blackhole route\n" + BLACKHOLE_STR) +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL); +} + +DEFUN (ipv6_route_blackhole_pref, + ipv6_route_blackhole_pref_cmd, + "ipv6 route X:X::X:X/M Null0 " BLACKHOLE_CMD " <1-255>", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "Specify blackhole route\n" + BLACKHOLE_STR "Distance value for this prefix\n") { - return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3]); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3]); } -DEFUN (no_ipv6_route_ifname_flags_pref, - no_ipv6_route_ifname_flags_pref_cmd, - "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) <1-255>", +DEFUN (no_ipv6_route_blackhole_pref, + no_ipv6_route_blackhole_pref_cmd, + "no ipv6 route X:X::X:X/M Null0 " BLACKHOLE_CMD " <1-255>", NO_STR IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" - "IPv6 gateway address\n" - "IPv6 gateway interface name\n" - "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n" + "Specify blackhole route\n" + BLACKHOLE_STR "Distance value for this prefix\n") { - return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4]); + const char *dist = argc > 3 ? argv[3] : NULL; + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], dist); } +ALIAS (no_ipv6_route_blackhole_pref, + no_ipv6_route_blackhole_cmd, + "no ipv6 route X:X::X:X/M Null0 " BLACKHOLE_CMD, + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "Specify blackhole route\n" + BLACKHOLE_STR) + /* New RIB. Detailed information for IPv6 route. */ static void vty_show_ipv6_route_detail (struct vty *vty, struct route_node *rn) @@ -1522,10 +1441,6 @@ vty_show_ipv6_route_detail (struct vty *vty, struct route_node *rn) vty_out (vty, ", best"); if (rib->refcnt) vty_out (vty, ", refcnt %ld", rib->refcnt); - if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE)) - vty_out (vty, ", blackhole"); - if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT)) - vty_out (vty, ", reject"); vty_out (vty, "%s", VTY_NEWLINE); #define ONE_DAY_SECOND 60*60*24 @@ -1673,6 +1588,9 @@ vty_show_ipv6_route (struct vty *vty, struct route_node *rn, vty_out (vty, " is directly connected, %s", nexthop->ifname); break; + case NEXTHOP_TYPE_BLACKHOLE: + vty_out (vty, " Null0, %s", BLACKHOLE_NAME (rib->zflags)); + break; default: break; } @@ -1704,11 +1622,6 @@ vty_show_ipv6_route (struct vty *vty, struct route_node *rn, } } - if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE)) - vty_out (vty, ", bh"); - if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT)) - vty_out (vty, ", rej"); - if (rib->type == ZEBRA_ROUTE_RIPNG || rib->type == ZEBRA_ROUTE_OSPF6 || rib->type == ZEBRA_ROUTE_ISIS @@ -1983,14 +1896,11 @@ static_config_ipv6 (struct vty *vty) vty_out (vty, " %s %s", inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ), si->ifname); break; + case STATIC_IPV6_BLACKHOLE: + vty_out (vty, " Null0 %s", BLACKHOLE_NAME (si->zflags)); + break; } - if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT)) - vty_out (vty, " %s", "reject"); - - if (CHECK_FLAG(si->flags, ZEBRA_FLAG_BLACKHOLE)) - vty_out (vty, " %s", "blackhole"); - if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) vty_out (vty, " %d", si->distance); vty_out (vty, "%s", VTY_NEWLINE); @@ -2091,21 +2001,17 @@ zebra_vty_init (void) #ifdef HAVE_IPV6 install_element (CONFIG_NODE, &ipv6_route_cmd); - install_element (CONFIG_NODE, &ipv6_route_flags_cmd); install_element (CONFIG_NODE, &ipv6_route_ifname_cmd); - install_element (CONFIG_NODE, &ipv6_route_ifname_flags_cmd); install_element (CONFIG_NODE, &no_ipv6_route_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_flags_cmd); install_element (CONFIG_NODE, &no_ipv6_route_ifname_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_cmd); install_element (CONFIG_NODE, &ipv6_route_pref_cmd); - install_element (CONFIG_NODE, &ipv6_route_flags_pref_cmd); install_element (CONFIG_NODE, &ipv6_route_ifname_pref_cmd); - install_element (CONFIG_NODE, &ipv6_route_ifname_flags_pref_cmd); install_element (CONFIG_NODE, &no_ipv6_route_pref_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_flags_pref_cmd); install_element (CONFIG_NODE, &no_ipv6_route_ifname_pref_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_pref_cmd); + install_element (CONFIG_NODE, &ipv6_route_blackhole_cmd); + install_element (CONFIG_NODE, &ipv6_route_blackhole_pref_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_blackhole_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_blackhole_pref_cmd); install_element (VIEW_NODE, &show_ipv6_route_cmd); install_element (VIEW_NODE, &show_ipv6_route_summary_cmd); install_element (VIEW_NODE, &show_ipv6_route_protocol_cmd); |