summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/zclient.c33
-rw-r--r--lib/zclient.h9
-rw-r--r--lib/zebra.h4
-rw-r--r--ospfd/ospf_zebra.c8
-rw-r--r--zebra/kernel_socket.c15
-rw-r--r--zebra/rib.h30
-rw-r--r--zebra/rt_ioctl.c2
-rw-r--r--zebra/rt_netlink.c204
-rw-r--r--zebra/rt_socket.c7
-rw-r--r--zebra/zebra_rib.c140
-rw-r--r--zebra/zebra_vty.c426
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);