summaryrefslogtreecommitdiffstats
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-rw-r--r--zebra/Makefile.am2
-rw-r--r--zebra/connected.c105
-rw-r--r--zebra/connected.h11
-rw-r--r--zebra/if_ioctl.c6
-rw-r--r--zebra/if_ioctl_solaris.c4
-rw-r--r--zebra/if_proc.c2
-rw-r--r--zebra/interface.c349
-rw-r--r--zebra/ioctl.c63
-rw-r--r--zebra/kernel_null.c2
-rw-r--r--zebra/kernel_socket.c54
-rw-r--r--zebra/main.c22
-rw-r--r--zebra/redistribute.c46
-rw-r--r--zebra/rib.h31
-rw-r--r--zebra/rt_ioctl.c2
-rw-r--r--zebra/rt_netlink.c227
-rw-r--r--zebra/rt_socket.c7
-rw-r--r--zebra/test_main.c11
-rw-r--r--zebra/zebra_rib.c294
-rw-r--r--zebra/zebra_vty.c504
-rw-r--r--zebra/zserv.c96
-rw-r--r--zebra/zserv.h7
21 files changed, 1214 insertions, 631 deletions
diff --git a/zebra/Makefile.am b/zebra/Makefile.am
index 542f36f4..828e88ff 100644
--- a/zebra/Makefile.am
+++ b/zebra/Makefile.am
@@ -1,7 +1,7 @@
## Process this file with automake to produce Makefile.in.
INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib @SNMP_INCLUDES@
-DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" -DMULTIPATH_NUM=@MULTIPATH_NUM@
+DEFS = @DEFS@ -DMULTIPATH_NUM=@MULTIPATH_NUM@
INSTALL_SDATA=@INSTALL@ -m 600
LIB_IPV6 = @LIB_IPV6@
diff --git a/zebra/connected.c b/zebra/connected.c
index 95399fa1..0c22582d 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -36,6 +36,53 @@
#include "zebra/interface.h"
#include "zebra/connected.h"
extern struct zebra_t zebrad;
+
+#ifdef HAVE_NETLINK
+static const struct message rtscope_str[] = {
+ {RT_SCOPE_UNIVERSE, "global"},
+ {RT_SCOPE_SITE, "site"},
+ {RT_SCOPE_LINK, "link"},
+ {RT_SCOPE_HOST, "host"},
+ {RT_SCOPE_NOWHERE, "nowhere"},
+ {0, NULL}
+};
+
+/* for use in show interface */
+const char *
+connected_scope_name(unsigned value)
+{
+ const char *str;
+ static char buf[16];
+
+ str = lookup (rtscope_str, value);
+ if (!str || !*str) {
+ snprintf (buf, sizeof(buf), "%d", value);
+ str = buf;
+ }
+ return str;
+}
+
+int
+connected_scope_number(const char *name)
+{
+ const struct message *m;
+ char *errptr;
+ unsigned value;
+
+ if (!name || !*name)
+ return -1;
+
+ for (m = rtscope_str; m->str; m++)
+ if (!strcmp (m->str, name))
+ return m->key;
+
+ value = strtoul (name, &errptr, 0);
+ if (*errptr || value > 255)
+ return -1;
+
+ return value;
+}
+#endif /* HAVE_NETLINK */
/* withdraw a connected address */
static void
@@ -112,6 +159,30 @@ connected_check (struct interface *ifp, struct prefix *p)
return NULL;
}
+/* same, but with peer address */
+struct connected *
+connected_check_ptp (struct interface *ifp, struct prefix *p, struct prefix *d)
+{
+ struct connected *ifc;
+ struct listnode *node;
+
+ /* ignore broadcast addresses */
+ if (p->prefixlen != IPV4_MAX_PREFIXLEN)
+ d = NULL;
+
+ for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc))
+ {
+ if (!prefix_same (ifc->address, p))
+ continue;
+ if (!CONNECTED_PEER(ifc) && !d)
+ return ifc;
+ if (CONNECTED_PEER(ifc) && d && prefix_same (ifc->destination, d))
+ return ifc;
+ }
+
+ return NULL;
+}
+
/* Check if two ifc's describe the same address */
static int
connected_same (struct connected *ifc1, struct connected *ifc2)
@@ -148,7 +219,7 @@ connected_implicit_withdraw (struct interface *ifp, struct connected *ifc)
struct connected *current;
/* Check same connected route. */
- if ((current = connected_check (ifp, (struct prefix *) ifc->address)))
+ if ((current = connected_check_ptp (ifp, ifc->address, ifc->destination)))
{
if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED))
SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
@@ -198,7 +269,7 @@ connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
void
connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
u_char prefixlen, struct in_addr *broad,
- const char *label)
+ const char *label, unsigned scope, int preference)
{
struct prefix_ipv4 *p;
struct connected *ifc;
@@ -212,7 +283,8 @@ connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
p = prefix_ipv4_new ();
p->family = AF_INET;
p->prefix = *addr;
- p->prefixlen = prefixlen;
+ p->prefixlen = CHECK_FLAG(flags, ZEBRA_IFA_PEER)
+ ? IPV4_MAX_PREFIXLEN : prefixlen;
ifc->address = (struct prefix *) p;
/* If there is broadcast or peer address. */
@@ -269,6 +341,9 @@ connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
if (label)
ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
+ ifc->scope = scope;
+ ifc->preference = preference;
+
/* nothing to do? */
if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL)
return;
@@ -305,15 +380,27 @@ void
connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
u_char prefixlen, struct in_addr *broad)
{
- struct prefix_ipv4 p;
+ struct prefix_ipv4 p, d;
struct connected *ifc;
memset (&p, 0, sizeof (struct prefix_ipv4));
p.family = AF_INET;
p.prefix = *addr;
- p.prefixlen = prefixlen;
+ p.prefixlen = CHECK_FLAG(flags, ZEBRA_IFA_PEER)
+ ? IPV4_MAX_PREFIXLEN : prefixlen;
+
+ if (broad)
+ {
+ memset (&d, 0, sizeof (struct prefix_ipv4));
+ d.family = AF_INET;
+ d.prefix = *broad;
+ d.prefixlen = prefixlen;
+ ifc = connected_check_ptp (ifp, (struct prefix *) &p,
+ (struct prefix *) &d);
+ }
+ else
+ ifc = connected_check_ptp (ifp, (struct prefix *) &p, NULL);
- ifc = connected_check (ifp, (struct prefix *) &p);
if (! ifc)
return;
@@ -352,7 +439,7 @@ connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
void
connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr,
u_char prefixlen, struct in6_addr *broad,
- const char *label)
+ const char *label, unsigned scope)
{
struct prefix_ipv6 *p;
struct connected *ifc;
@@ -395,7 +482,9 @@ connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr,
/* Label of this address. */
if (label)
ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
-
+
+ ifc->scope = scope;
+
if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL)
return;
diff --git a/zebra/connected.h b/zebra/connected.h
index 9595ddb1..ede75120 100644
--- a/zebra/connected.h
+++ b/zebra/connected.h
@@ -25,11 +25,13 @@
extern struct connected *
connected_check (struct interface *ifp, struct prefix *p);
+extern struct connected *
+connected_check_ptp (struct interface *ifp, struct prefix *p, struct prefix *d);
extern void
connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
u_char prefixlen, struct in_addr *broad,
- const char *label);
+ const char *label, unsigned scope, int preference);
extern void
connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
@@ -42,7 +44,7 @@ extern void connected_down_ipv4 (struct interface *, struct connected *);
extern void
connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *address,
u_char prefixlen, struct in6_addr *broad,
- const char *label);
+ const char *label, unsigned scope);
extern void
connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
u_char prefixlen, struct in6_addr *broad);
@@ -52,4 +54,9 @@ extern void connected_down_ipv6 (struct interface *ifp, struct connected *);
#endif /* HAVE_IPV6 */
+#ifdef HAVE_NETLINK
+extern const char *connected_scope_name (unsigned value);
+extern int connected_scope_number (const char *name);
+#endif /* HAVE_NETLINK */
+
#endif /*_ZEBRA_CONNECTED_H */
diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c
index f357e154..36732704 100644
--- a/zebra/if_ioctl.c
+++ b/zebra/if_ioctl.c
@@ -276,7 +276,7 @@ if_getaddrs (void)
}
connected_add_ipv4 (ifp, flags, &addr->sin_addr,
- prefixlen, dest_pnt, NULL);
+ prefixlen, dest_pnt, NULL, 0, 0);
}
#ifdef HAVE_IPV6
if (ifap->ifa_addr->sa_family == AF_INET6)
@@ -321,7 +321,7 @@ if_getaddrs (void)
#endif
connected_add_ipv6 (ifp, flags, &addr->sin6_addr, prefixlen,
- dest_pnt, NULL);
+ dest_pnt, NULL, 0);
}
#endif /* HAVE_IPV6 */
}
@@ -412,7 +412,7 @@ if_get_addr (struct interface *ifp)
/* Set address to the interface. */
- connected_add_ipv4 (ifp, flags, &addr.sin_addr, prefixlen, dest_pnt, NULL);
+ connected_add_ipv4 (ifp, flags, &addr.sin_addr, prefixlen, dest_pnt, NULL, 0, 0);
return 0;
}
diff --git a/zebra/if_ioctl_solaris.c b/zebra/if_ioctl_solaris.c
index fc384ea2..736232e8 100644
--- a/zebra/if_ioctl_solaris.c
+++ b/zebra/if_ioctl_solaris.c
@@ -327,11 +327,11 @@ if_get_addr (struct interface *ifp, struct sockaddr *addr, const char *label)
/* Set address to the interface. */
if (af == AF_INET)
connected_add_ipv4 (ifp, flags, &SIN (addr)->sin_addr, prefixlen,
- (struct in_addr *) dest_pnt, label);
+ (struct in_addr *) dest_pnt, label, 0, 0);
#ifdef HAVE_IPV6
else if (af == AF_INET6)
connected_add_ipv6 (ifp, flags, &SIN6 (addr)->sin6_addr, prefixlen,
- (struct in6_addr *) dest_pnt, label);
+ (struct in6_addr *) dest_pnt, label, 0);
#endif /* HAVE_IPV6 */
return 0;
diff --git a/zebra/if_proc.c b/zebra/if_proc.c
index 3aec530b..6c538116 100644
--- a/zebra/if_proc.c
+++ b/zebra/if_proc.c
@@ -240,7 +240,7 @@ ifaddr_proc_ipv6 ()
str2in6_addr (addr, &p.prefix);
p.prefixlen = plen;
- connected_add_ipv6 (ifp, 0, &p.prefix, p.prefixlen, NULL, ifname);
+ connected_add_ipv6 (ifp, 0, &p.prefix, p.prefixlen, NULL, ifname, 0);
}
fclose (fp);
return 0;
diff --git a/zebra/interface.c b/zebra/interface.c
index a4f32e78..e19648d7 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -131,7 +131,7 @@ if_subnet_add (struct interface *ifp, struct connected *ifc)
/* Get address derived subnet node and associated address list, while marking
address secondary attribute appropriately. */
- cp = *ifc->address;
+ cp = *CONNECTED_PREFIX(ifc);
apply_mask (&cp);
rn = route_node_get (zebra_if->ipv4_subnets, &cp);
@@ -158,12 +158,16 @@ if_subnet_delete (struct interface *ifp, struct connected *ifc)
struct route_node *rn;
struct zebra_if *zebra_if;
struct list *addr_list;
+ struct prefix cp;
assert (ifp && ifp->info && ifc);
zebra_if = ifp->info;
+ cp = *CONNECTED_PREFIX(ifc);
+ apply_mask (&cp);
+
/* Get address derived subnet node. */
- rn = route_node_lookup (zebra_if->ipv4_subnets, ifc->address);
+ rn = route_node_lookup (zebra_if->ipv4_subnets, &cp);
if (! (rn && rn->info))
return -1;
route_unlock_node (rn);
@@ -592,8 +596,18 @@ connected_dump_vty (struct vty *vty, struct connected *connected)
{
vty_out (vty, (CONNECTED_PEER(connected) ? " peer " : " broadcast "));
prefix_vty_out (vty, connected->destination);
+ vty_out (vty, "/%d", connected->destination->prefixlen);
}
+#ifdef HAVE_NETLINK
+ if (connected->scope != 0)
+ vty_out (vty, " scope %s", connected_scope_name (connected->scope));
+#endif
+#ifdef SIOCSIFADDRPREF
+ if (connected->preference != 0)
+ vty_out (vty, " preference %d", connected->preference);
+#endif
+
if (CHECK_FLAG (connected->flags, ZEBRA_IFA_SECONDARY))
vty_out (vty, " secondary");
@@ -1009,6 +1023,53 @@ DEFUN (no_multicast,
return CMD_SUCCESS;
}
+DEFUN (unnumbered,
+ unnumbered_cmd,
+ "unnumbered",
+ "Set interface to IP Unnumbered mode\n")
+{
+ int ret;
+ struct interface *ifp;
+ struct zebra_if *if_data;
+
+ ifp = (struct interface *) vty->index;
+
+ zlog_debug("VTY: interface %s, Setting ifp->status |= ZEBRA_INTERFACE_UNNUMBERED",
+ ifp->name);
+
+ SET_FLAG(ifp->status, ZEBRA_INTERFACE_UNNUMBERED);
+
+ /* force protocols to recalculate routes due to IP change */
+ if (if_is_operative (ifp))
+ zebra_interface_up_update (ifp);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_unnumbered,
+ no_unnumbered_cmd,
+ "no unnumbered",
+ NO_STR
+ "Set interface to IP Numbered mode\n")
+{
+ int ret;
+ struct interface *ifp;
+ struct zebra_if *if_data;
+
+ ifp = (struct interface *) vty->index;
+
+ zlog_debug("VTY: interface %s, Setting ifp->status &= ~ZEBRA_INTERFACE_UNNUMBERED;",
+ ifp->name);
+
+ UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_UNNUMBERED);
+
+ /* force protocols to recalculate routes due to IP change */
+ if (if_is_operative (ifp))
+ zebra_interface_up_update (ifp);
+
+ return CMD_SUCCESS;
+}
+
DEFUN (linkdetect,
linkdetect_cmd,
"link-detect",
@@ -1156,21 +1217,62 @@ ALIAS (no_bandwidth_if,
static int
ip_address_install (struct vty *vty, struct interface *ifp,
const char *addr_str, const char *peer_str,
- const char *label)
+ const char *label, const char *scope,
+ const char *preference)
{
- struct prefix_ipv4 cp;
+ struct prefix_ipv4 lp, pp;
struct connected *ifc;
struct prefix_ipv4 *p;
int ret;
+ int scopev = 0, preferencev = 0;
- ret = str2prefix_ipv4 (addr_str, &cp);
+ ret = str2prefix_ipv4 (addr_str, &lp);
if (ret <= 0)
+ {
+ vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (peer_str)
{
- vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
- return CMD_WARNING;
+ if (lp.prefixlen != 32)
+ {
+ vty_out (vty, "%% Local prefix length for P-t-P address "
+ "must be /32%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ ret = str2prefix_ipv4 (peer_str, &pp);
+ if (ret <= 0)
+ {
+ vty_out (vty, "%% Malformed peer address %s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
}
- ifc = connected_check (ifp, (struct prefix *) &cp);
+#ifdef HAVE_NETLINK
+ if (scope)
+ {
+ scopev = connected_scope_number (scope);
+ if (scopev < 0)
+ {
+ vty_out (vty, "%% Malformed scope %s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+#endif
+ if (preference)
+ {
+ preferencev = atoi (preference);
+ if (preferencev < -32768 || preferencev > 32767)
+ {
+ vty_out (vty, "%% Invalid preference %s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+
+ ifc = connected_check_ptp (ifp, (struct prefix *) &lp,
+ (struct prefix *)(peer_str ? &pp : NULL));
if (! ifc)
{
ifc = connected_new ();
@@ -1178,14 +1280,23 @@ ip_address_install (struct vty *vty, struct interface *ifp,
/* Address. */
p = prefix_ipv4_new ();
- *p = cp;
+ *p = lp;
ifc->address = (struct prefix *) p;
+ ifc->scope = scopev;
+ ifc->preference = preferencev;
- /* Broadcast. */
- if (p->prefixlen <= IPV4_MAX_PREFIXLEN-2)
+ if (peer_str)
{
+ SET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
p = prefix_ipv4_new ();
- *p = cp;
+ *p = pp;
+ ifc->destination = (struct prefix *) p;
+ }
+ else if (p->prefixlen <= IPV4_MAX_PREFIXLEN-2)
+ {
+ /* Broadcast. */
+ p = prefix_ipv4_new ();
+ *p = lp;
p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,p->prefixlen);
ifc->destination = (struct prefix *) p;
}
@@ -1240,23 +1351,40 @@ ip_address_install (struct vty *vty, struct interface *ifp,
static int
ip_address_uninstall (struct vty *vty, struct interface *ifp,
- const char *addr_str, const char *peer_str,
- const char *label)
+ const char *addr_str, const char *peer_str)
{
- struct prefix_ipv4 cp;
+ struct prefix_ipv4 lp, pp;
struct connected *ifc;
int ret;
/* Convert to prefix structure. */
- ret = str2prefix_ipv4 (addr_str, &cp);
+ ret = str2prefix_ipv4 (addr_str, &lp);
if (ret <= 0)
{
vty_out (vty, "%% Malformed address %s", VTY_NEWLINE);
return CMD_WARNING;
}
+ if (peer_str)
+ {
+ if (lp.prefixlen != 32)
+ {
+ vty_out (vty, "%% Local prefix length for P-t-P address "
+ "must be /32%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ ret = str2prefix_ipv4 (peer_str, &pp);
+ if (ret <= 0)
+ {
+ vty_out (vty, "%% Malformed peer address %s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+
/* Check current interface address. */
- ifc = connected_check (ifp, (struct prefix *) &cp);
+ ifc = connected_check_ptp (ifp, (struct prefix *) &lp,
+ (struct prefix *)(peer_str ? &pp : NULL));
if (! ifc)
{
vty_out (vty, "%% Can't find address%s", VTY_NEWLINE);
@@ -1286,70 +1414,169 @@ ip_address_uninstall (struct vty *vty, struct interface *ifp,
safe_strerror(errno), VTY_NEWLINE);
return CMD_WARNING;
}
+ /* success! now update all internal state... */
+
+ /* Remove connected route. */
+ connected_down_ipv4 (ifp, ifc);
-#if 0
/* Redistribute this information. */
zebra_interface_address_delete_update (ifp, ifc);
- /* Remove connected route. */
- connected_down_ipv4 (ifp, ifc);
+ /* IP address propery set. */
+ UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
+
+ /* remove from interface, remark secondaries */
+ if_subnet_delete (ifp, ifc);
/* Free address information. */
listnode_delete (ifp->connected, ifc);
connected_free (ifc);
-#endif
return CMD_SUCCESS;
}
+#define IP_ADDR_STR \
+ "Interface Internet Protocol config commands\n" \
+ "Set the IP address of an interface\n" \
+ "IP address (e.g. 10.0.0.1/8)\n"
+#define IP_ADDR_PEER_STR \
+ "Interface Internet Protocol config commands\n" \
+ "Set the IP address of an interface\n" \
+ "Local IP (e.g. 10.0.0.1) for P-t-P address\n" \
+ "Specify P-t-P address\n" \
+ "Peer IP address (e.g. 10.0.0.1/8)\n"
+
DEFUN (ip_address,
ip_address_cmd,
"ip address A.B.C.D/M",
- "Interface Internet Protocol config commands\n"
- "Set the IP address of an interface\n"
- "IP address (e.g. 10.0.0.1/8)\n")
+ IP_ADDR_STR)
{
- return ip_address_install (vty, vty->index, argv[0], NULL, NULL);
+ return ip_address_install (vty, vty->index, argv[0], NULL,
+ NULL, NULL, NULL);
}
DEFUN (no_ip_address,
no_ip_address_cmd,
"no ip address A.B.C.D/M",
- NO_STR
- "Interface Internet Protocol config commands\n"
- "Set the IP address of an interface\n"
- "IP Address (e.g. 10.0.0.1/8)")
+ NO_STR IP_ADDR_STR)
+{
+ return ip_address_uninstall (vty, vty->index, argv[0], NULL);
+}
+
+DEFUN (ip_address_peer,
+ ip_address_peer_cmd,
+ "ip address A.B.C.D peer A.B.C.D/M",
+ IP_ADDR_PEER_STR)
+{
+ return ip_address_install (vty, vty->index, argv[0], argv[1],
+ NULL, NULL, NULL);
+}
+
+DEFUN (no_ip_address_peer,
+ no_ip_address_peer_cmd,
+ "no ip address A.B.C.D peer A.B.C.D/M",
+ NO_STR IP_ADDR_PEER_STR)
{
- return ip_address_uninstall (vty, vty->index, argv[0], NULL, NULL);
+ return ip_address_uninstall (vty, vty->index, argv[0], argv[1]);
}
#ifdef HAVE_NETLINK
DEFUN (ip_address_label,
ip_address_label_cmd,
"ip address A.B.C.D/M label LINE",
- "Interface Internet Protocol config commands\n"
- "Set the IP address of an interface\n"
- "IP address (e.g. 10.0.0.1/8)\n"
+ IP_ADDR_STR
"Label of this address\n"
"Label\n")
{
- return ip_address_install (vty, vty->index, argv[0], NULL, argv[1]);
+ return ip_address_install (vty, vty->index, argv[0], NULL,
+ argv[1], NULL, NULL);
}
-DEFUN (no_ip_address_label,
- no_ip_address_label_cmd,
- "no ip address A.B.C.D/M label LINE",
- NO_STR
- "Interface Internet Protocol config commands\n"
- "Set the IP address of an interface\n"
- "IP address (e.g. 10.0.0.1/8)\n"
+DEFUN (ip_address_peer_label,
+ ip_address_peer_label_cmd,
+ "ip address A.B.C.D peer A.B.C.D/M label LINE",
+ IP_ADDR_PEER_STR
"Label of this address\n"
"Label\n")
{
- return ip_address_uninstall (vty, vty->index, argv[0], NULL, argv[1]);
+ return ip_address_install (vty, vty->index, argv[0], argv[1],
+ argv[2], NULL, NULL);
+}
+
+DEFUN (ip_address_scope,
+ ip_address_scope_cmd,
+ "ip address A.B.C.D/M scope WORD",
+ IP_ADDR_STR
+ "Scope of this address\n"
+ "Scope (e.g. 0-255 or global,site,link,host,nowhere)\n")
+{
+ return ip_address_install (vty, vty->index, argv[0], NULL,
+ NULL, argv[1], NULL);
+}
+
+DEFUN (ip_address_peer_scope,
+ ip_address_peer_scope_cmd,
+ "ip address A.B.C.D peer A.B.C.D/M scope WORD",
+ IP_ADDR_PEER_STR
+ "Scope of this address\n"
+ "Scope (e.g. 0-255 or global,site,link,host,nowhere)\n")
+{
+ return ip_address_install (vty, vty->index, argv[0], argv[1],
+ NULL, argv[2], NULL);
}
+
+DEFUN (ip_address_scope_label,
+ ip_address_scope_label_cmd,
+ "ip address A.B.C.D/M scope WORD label LINE",
+ IP_ADDR_STR
+ "Scope of this address\n"
+ "Scope (e.g. 0-255 or global,site,link,host,nowhere)\n"
+ "Label of this address\n"
+ "Label\n")
+{
+ return ip_address_install (vty, vty->index, argv[0], NULL,
+ argv[2], argv[1], NULL);
+}
+
+DEFUN (ip_address_peer_scope_label,
+ ip_address_peer_scope_label_cmd,
+ "ip address A.B.C.D peer A.B.C.D/M scope WORD label LINE",
+ IP_ADDR_PEER_STR
+ "Scope of this address\n"
+ "Scope (e.g. 0-255 or global,site,link,host,nowhere)\n"
+ "Label of this address\n"
+ "Label\n")
+{
+ return ip_address_install (vty, vty->index, argv[0], argv[1],
+ argv[3], argv[2], NULL);
+}
+
#endif /* HAVE_NETLINK */
+#ifdef SIOCSIFADDRPREF
+DEFUN (ip_address_pref,
+ ip_address_pref_cmd,
+ "ip address A.B.C.D/M preference WORD",
+ IP_ADDR_STR
+ "specify IPSRCSEL preference\n"
+ "preference value, higher is preferred\n")
+{
+ return ip_address_install (vty, vty->index, argv[0], NULL,
+ NULL, NULL, argv[1]);
+}
+
+DEFUN (ip_address_peer_pref,
+ ip_address_peer_pref_cmd,
+ "ip address A.B.C.D peer A.B.C.D/M preference WORD",
+ IP_ADDR_PEER_STR
+ "specify IPSRCSEL preference\n"
+ "preference value, higher is preferred\n")
+{
+ return ip_address_install (vty, vty->index, argv[0], argv[1],
+ NULL, NULL, argv[2]);
+}
+#endif
+
#ifdef HAVE_IPV6
static int
ipv6_address_install (struct vty *vty, struct interface *ifp,
@@ -1538,6 +1765,9 @@ if_config_write (struct vty *vty)
if (ifp->bandwidth != 0)
vty_out(vty, " bandwidth %u%s", ifp->bandwidth, VTY_NEWLINE);
+ if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_UNNUMBERED))
+ vty_out (vty, " unnumbered%s", VTY_NEWLINE);
+
if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
vty_out(vty, " link-detect%s", VTY_NEWLINE);
@@ -1547,14 +1777,27 @@ if_config_write (struct vty *vty)
{
char buf[INET6_ADDRSTRLEN];
p = ifc->address;
- vty_out (vty, " ip%s address %s/%d",
+ vty_out (vty, " ip%s address %s",
p->family == AF_INET ? "" : "v6",
- inet_ntop (p->family, &p->u.prefix, buf, sizeof(buf)),
- p->prefixlen);
+ inet_ntop (p->family, &p->u.prefix, buf, sizeof(buf)));
+ if (CONNECTED_PEER (ifc))
+ {
+ p = ifc->destination;
+ vty_out (vty, " peer %s",
+ inet_ntop (p->family, &p->u.prefix, buf, sizeof(buf)));
+ }
+ vty_out (vty, "/%d", p->prefixlen);
+#ifdef HAVE_NETLINK
+ if (ifc->scope)
+ vty_out (vty, " scope %s", connected_scope_name (ifc->scope));
if (ifc->label)
vty_out (vty, " label %s", ifc->label);
-
+#endif
+#ifdef SIOCSIFADDRPREF
+ if (ifc->preference)
+ vty_out (vty, " preference %d", ifc->preference);
+#endif
vty_out (vty, "%s", VTY_NEWLINE);
}
}
@@ -1605,6 +1848,8 @@ zebra_if_init (void)
install_element (INTERFACE_NODE, &no_interface_desc_cmd);
install_element (INTERFACE_NODE, &multicast_cmd);
install_element (INTERFACE_NODE, &no_multicast_cmd);
+ install_element (INTERFACE_NODE, &unnumbered_cmd);
+ install_element (INTERFACE_NODE, &no_unnumbered_cmd);
install_element (INTERFACE_NODE, &linkdetect_cmd);
install_element (INTERFACE_NODE, &no_linkdetect_cmd);
install_element (INTERFACE_NODE, &shutdown_if_cmd);
@@ -1614,12 +1859,22 @@ zebra_if_init (void)
install_element (INTERFACE_NODE, &no_bandwidth_if_val_cmd);
install_element (INTERFACE_NODE, &ip_address_cmd);
install_element (INTERFACE_NODE, &no_ip_address_cmd);
+ install_element (INTERFACE_NODE, &ip_address_peer_cmd);
+ install_element (INTERFACE_NODE, &no_ip_address_peer_cmd);
#ifdef HAVE_IPV6
install_element (INTERFACE_NODE, &ipv6_address_cmd);
install_element (INTERFACE_NODE, &no_ipv6_address_cmd);
#endif /* HAVE_IPV6 */
#ifdef HAVE_NETLINK
install_element (INTERFACE_NODE, &ip_address_label_cmd);
- install_element (INTERFACE_NODE, &no_ip_address_label_cmd);
+ install_element (INTERFACE_NODE, &ip_address_scope_cmd);
+ install_element (INTERFACE_NODE, &ip_address_scope_label_cmd);
+ install_element (INTERFACE_NODE, &ip_address_peer_label_cmd);
+ install_element (INTERFACE_NODE, &ip_address_peer_scope_cmd);
+ install_element (INTERFACE_NODE, &ip_address_peer_scope_label_cmd);
#endif /* HAVE_NETLINK */
+#ifdef SIOCSIFADDRPREF
+ install_element (INTERFACE_NODE, &ip_address_pref_cmd);
+ install_element (INTERFACE_NODE, &ip_address_peer_pref_cmd);
+#endif
}
diff --git a/zebra/ioctl.c b/zebra/ioctl.c
index d783b0a3..6cb428a7 100644
--- a/zebra/ioctl.c
+++ b/zebra/ioctl.c
@@ -191,10 +191,16 @@ if_set_prefix (struct interface *ifp, struct connected *ifc)
{
int ret;
struct ifaliasreq addreq;
- struct sockaddr_in addr;
- struct sockaddr_in mask;
+ struct sockaddr_in addr, mask, peer;
struct prefix_ipv4 *p;
+ /* don't configure PtP addresses on broadcast ifs or reverse */
+ if (!(ifp->flags & IFF_POINTOPOINT) != !CONNECTED_PEER (ifc))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
p = (struct prefix_ipv4 *) ifc->address;
rib_lookup_and_pushup (p);
@@ -209,6 +215,18 @@ if_set_prefix (struct interface *ifp, struct connected *ifc)
#endif
memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in));
+ if (CONNECTED_PEER (ifc))
+ {
+ p = (struct prefix_ipv4 *) ifc->destination;
+ memset (&mask, 0, sizeof (struct sockaddr_in));
+ peer.sin_addr = p->prefix;
+ peer.sin_family = p->family;
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+ peer.sin_len = sizeof (struct sockaddr_in);
+#endif
+ memcpy (&addreq.ifra_broadaddr, &peer, sizeof (struct sockaddr_in));
+ }
+
memset (&mask, 0, sizeof (struct sockaddr_in));
masklen2ip (p->prefixlen, &mask.sin_addr);
mask.sin_family = p->family;
@@ -216,10 +234,27 @@ if_set_prefix (struct interface *ifp, struct connected *ifc)
mask.sin_len = sizeof (struct sockaddr_in);
#endif
memcpy (&addreq.ifra_mask, &mask, sizeof (struct sockaddr_in));
-
+
ret = if_ioctl (SIOCAIFADDR, (caddr_t) &addreq);
if (ret < 0)
return ret;
+
+#ifdef SIOCSIFADDRPREF
+ if (ifc->preference != 0)
+ {
+ struct if_addrprefreq ifapr;
+
+ memset (&ifapr, 0, sizeof ifapr);
+ strncpy ((char *)&ifapr.ifap_name, ifp->name, sizeof ifapr.ifap_name);
+ ifapr.ifap_preference = ifc->preference;
+ memcpy (&ifapr.ifap_addr, &addr, sizeof (struct sockaddr_in));
+
+ ret = if_ioctl (SIOCSIFADDRPREF, (caddr_t) &ifapr);
+ if (ret < 0)
+ zlog_err("if_ioctl(SIOCSIFADDRPREF) failed: %s",
+ safe_strerror(errno));
+ }
+#endif
return 0;
}
@@ -230,10 +265,16 @@ if_unset_prefix (struct interface *ifp, struct connected *ifc)
{
int ret;
struct ifaliasreq addreq;
- struct sockaddr_in addr;
- struct sockaddr_in mask;
+ struct sockaddr_in addr, mask, peer;
struct prefix_ipv4 *p;
+ /* this would probably wreak havoc */
+ if (!(ifp->flags & IFF_POINTOPOINT) != !CONNECTED_PEER (ifc))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
p = (struct prefix_ipv4 *)ifc->address;
memset (&addreq, 0, sizeof addreq);
@@ -247,6 +288,18 @@ if_unset_prefix (struct interface *ifp, struct connected *ifc)
#endif
memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in));
+ if (CONNECTED_PEER (ifc))
+ {
+ p = (struct prefix_ipv4 *) ifc->destination;
+ memset (&mask, 0, sizeof (struct sockaddr_in));
+ peer.sin_addr = p->prefix;
+ peer.sin_family = p->family;
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+ peer.sin_len = sizeof (struct sockaddr_in);
+#endif
+ memcpy (&addreq.ifra_broadaddr, &peer, sizeof (struct sockaddr_in));
+ }
+
memset (&mask, 0, sizeof (struct sockaddr_in));
masklen2ip (p->prefixlen, &mask.sin_addr);
mask.sin_family = p->family;
diff --git a/zebra/kernel_null.c b/zebra/kernel_null.c
index 6b96c6df..f83c2345 100644
--- a/zebra/kernel_null.c
+++ b/zebra/kernel_null.c
@@ -25,7 +25,7 @@ int kernel_address_add_ipv4 (struct interface *a, struct connected *b)
SET_FLAG (b->conf, ZEBRA_IFC_REAL);
connected_add_ipv4 (a, 0, &b->address->u.prefix4, b->address->prefixlen,
(b->destination ? &b->destination->u.prefix4 : NULL),
- NULL);
+ NULL, 0, 0);
return 0;
}
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index feeaf5d0..d0908115 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -253,6 +253,25 @@ rtm_flag_dump (int flag)
zlog_debug ("Kernel: %s", buf);
}
+/* NetBSD IPSRCSEL preference readback */
+static int
+if_get_addrpref (const char *ifname, struct sockaddr_in *addr)
+{
+#ifdef SIOCSIFADDRPREF
+ int ret;
+ struct if_addrprefreq ifapr;
+
+ memset (&ifapr, 0, sizeof ifapr);
+ strncpy ((char *)&ifapr.ifap_name, ifname, sizeof ifapr.ifap_name);
+ memcpy (&ifapr.ifap_addr, addr, sizeof (struct sockaddr_in));
+
+ ret = if_ioctl (SIOCGIFADDRPREF, (caddr_t) &ifapr);
+ if (ret == 0)
+ return ifapr.ifap_preference;
+#endif
+ return 0;
+}
+
#ifdef RTM_IFANNOUNCE
/* Interface adding function */
static int
@@ -319,6 +338,7 @@ int
ifm_read (struct if_msghdr *ifm)
{
struct interface *ifp = NULL;
+ struct sockaddr_dl *sdl;
char ifname[IFNAMSIZ];
short ifnlen = 0;
caddr_t *cp;
@@ -356,6 +376,7 @@ ifm_read (struct if_msghdr *ifm)
RTA_ADDR_GET (NULL, RTA_GATEWAY, ifm->ifm_addrs, cp);
RTA_ATTR_GET (NULL, RTA_NETMASK, ifm->ifm_addrs, cp);
RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifm_addrs, cp);
+ sdl = (struct sockaddr_dl *)cp;
RTA_NAME_GET (ifname, RTA_IFP, ifm->ifm_addrs, cp, ifnlen);
RTA_ADDR_GET (NULL, RTA_IFA, ifm->ifm_addrs, cp);
RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifm_addrs, cp);
@@ -454,6 +475,16 @@ ifm_read (struct if_msghdr *ifm)
#endif /* __bsdi__ */
if_get_metric (ifp);
+ /*
+ * XXX sockaddr_dl contents can be larger than the structure
+ * definition, so the user of the stored structure must be
+ * careful not to read off the end.
+ *
+ * a nonzero ifnlen from RTA_NAME_GET() means sdl is valid
+ */
+ if (ifnlen)
+ memcpy (&ifp->sdl, sdl, sizeof (struct sockaddr_dl));
+
if_add_update (ifp);
}
else
@@ -619,6 +650,7 @@ ifam_read (struct ifa_msghdr *ifam)
short ifnlen = 0;
char isalias = 0;
int flags = 0;
+ int preference = 0;
ifname[0] = ifname[INTERFACE_NAMSIZ - 1] = '\0';
@@ -649,6 +681,9 @@ ifam_read (struct ifa_msghdr *ifam)
*/
ifp->metric = ifam->ifam_metric;
#endif
+ if (sockunion_family (&addr) == AF_INET
+ && ifam->ifam_type == RTM_NEWADDR)
+ preference = if_get_addrpref (ifp->name, &addr.sin);
/* Add connected address. */
switch (sockunion_family (&addr))
@@ -658,7 +693,7 @@ ifam_read (struct ifa_msghdr *ifam)
connected_add_ipv4 (ifp, flags, &addr.sin.sin_addr,
ip_masklen (mask.sin.sin_addr),
&brd.sin.sin_addr,
- (isalias ? ifname : NULL));
+ (isalias ? ifname : NULL), 0, preference);
else
connected_delete_ipv4 (ifp, flags, &addr.sin.sin_addr,
ip_masklen (mask.sin.sin_addr),
@@ -675,7 +710,7 @@ ifam_read (struct ifa_msghdr *ifam)
connected_add_ipv6 (ifp, flags, &addr.sin6.sin6_addr,
ip6_masklen (mask.sin6.sin6_addr),
&brd.sin6.sin6_addr,
- (isalias ? ifname : NULL));
+ (isalias ? ifname : NULL), 0);
else
connected_delete_ipv6 (ifp,
&addr.sin6.sin6_addr,
@@ -804,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)
{
@@ -1037,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/main.c b/zebra/main.c
index d829c046..b58fed12 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -32,6 +32,7 @@
#include "plist.h"
#include "privs.h"
#include "sigevent.h"
+#include "paths.h"
#include "zebra/rib.h"
#include "zebra/zserv.h"
@@ -68,6 +69,7 @@ struct option longopts[] =
{
{ "batch", no_argument, NULL, 'b'},
{ "daemon", no_argument, NULL, 'd'},
+ { "namespace", required_argument, NULL, 'N'},
{ "keep_kernel", no_argument, NULL, 'k'},
{ "config_file", required_argument, NULL, 'f'},
{ "pid_file", required_argument, NULL, 'i'},
@@ -108,10 +110,13 @@ struct zebra_privs_t zserv_privs =
};
/* Default configuration file path. */
-char config_default[] = SYSCONFDIR DEFAULT_CONFIG_FILE;
+char config_default[MAXPATHLEN];
+
+/* pid_file default value */
+static char pid_file_default[MAXPATHLEN];
/* Process ID saved for use by init system */
-const char *pid_file = PATH_ZEBRA_PID;
+const char *pid_file = pid_file_default;
/* Help information display. */
static void
@@ -126,6 +131,7 @@ usage (char *progname, int status)
"redistribution between different routing protocols.\n\n"\
"-b, --batch Runs in batch mode\n"\
"-d, --daemon Runs in daemon mode\n"\
+ "-N, --namespace Insert argument into all paths\n"\
"-f, --config_file Set configuration file name\n"\
"-i, --pid_file Set process identifier file name\n"\
"-k, --keep_kernel Don't delete old routes which installed by "\
@@ -229,9 +235,9 @@ main (int argc, char **argv)
int opt;
#ifdef HAVE_NETLINK
- opt = getopt_long (argc, argv, "bdkf:i:hA:P:ru:g:vs:C", longopts, 0);
+ opt = getopt_long (argc, argv, "bdN:kf:i:hA:P:ru:g:vs:C", longopts, 0);
#else
- opt = getopt_long (argc, argv, "bdkf:i:hA:P:ru:g:vC", longopts, 0);
+ opt = getopt_long (argc, argv, "bdN:kf:i:hA:P:ru:g:vC", longopts, 0);
#endif /* HAVE_NETLINK */
if (opt == EOF)
@@ -246,6 +252,9 @@ main (int argc, char **argv)
case 'd':
daemon_mode = 1;
break;
+ case 'N':
+ path_set_namespace (optarg);
+ break;
case 'k':
keep_kernel_mode = 1;
break;
@@ -300,6 +309,9 @@ main (int argc, char **argv)
}
}
+ strcpy (config_default, path_config (ZEBRA_CONFIG_NAME));
+ strcpy (pid_file_default, path_state (ZEBRA_PID_NAME));
+
/* Make master thread emulator. */
zebrad.master = thread_master_create ();
@@ -389,7 +401,7 @@ main (int argc, char **argv)
zebra_zserv_socket_init ();
/* Make vty server socket. */
- vty_serv_sock (vty_addr, vty_port, ZEBRA_VTYSH_PATH);
+ vty_serv_sock (vty_addr, vty_port, path_state (ZEBRA_VTY_NAME));
/* Print banner. */
zlog_notice ("Zebra %s starting: vty@%d", QUAGGA_VERSION, vty_port);
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index a8107aeb..4276f1d0 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -245,26 +245,15 @@ zebra_redistribute_add (int command, struct zserv *client, int length)
type = stream_getc (client->ibuf);
- switch (type)
+ if (type == 0 || type >= ZEBRA_ROUTE_MAX)
+ return;
+
+ if (! client->redist[type])
{
- case ZEBRA_ROUTE_KERNEL:
- case ZEBRA_ROUTE_CONNECT:
- case ZEBRA_ROUTE_STATIC:
- case ZEBRA_ROUTE_RIP:
- case ZEBRA_ROUTE_RIPNG:
- case ZEBRA_ROUTE_OSPF:
- case ZEBRA_ROUTE_OSPF6:
- case ZEBRA_ROUTE_BGP:
- if (! client->redist[type])
- {
- client->redist[type] = 1;
- zebra_redistribute (client, type);
- }
- break;
- default:
- break;
+ client->redist[type] = 1;
+ zebra_redistribute (client, type);
}
-}
+}
void
zebra_redistribute_delete (int command, struct zserv *client, int length)
@@ -273,22 +262,11 @@ zebra_redistribute_delete (int command, struct zserv *client, int length)
type = stream_getc (client->ibuf);
- switch (type)
- {
- case ZEBRA_ROUTE_KERNEL:
- case ZEBRA_ROUTE_CONNECT:
- case ZEBRA_ROUTE_STATIC:
- case ZEBRA_ROUTE_RIP:
- case ZEBRA_ROUTE_RIPNG:
- case ZEBRA_ROUTE_OSPF:
- case ZEBRA_ROUTE_OSPF6:
- case ZEBRA_ROUTE_BGP:
- client->redist[type] = 0;
- break;
- default:
- break;
- }
-}
+ if (type == 0 || type >= ZEBRA_ROUTE_MAX)
+ return;
+
+ client->redist[type] = 0;
+}
void
zebra_redistribute_default_add (int command, struct zserv *client, int length)
diff --git a/zebra/rib.h b/zebra/rib.h
index 887ed3c2..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 */
@@ -262,6 +264,7 @@ extern struct rib *rib_match_ipv4 (struct in_addr);
extern struct rib *rib_lookup_ipv4 (struct prefix_ipv4 *);
extern void rib_update (void);
+extern void rib_update_background (void);
extern void rib_weed_tables (void);
extern void rib_sweep_route (void);
extern void rib_close (void);
@@ -269,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,
@@ -293,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 7652f80a..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
@@ -549,6 +571,7 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
char buf[BUFSIZ];
zlog_debug ("netlink_interface_addr %s %s:",
lookup (nlmsg_str, h->nlmsg_type), ifp->name);
+ zlog_debug (" ifa_scope %s", connected_scope_name (ifa->ifa_scope));
if (tb[IFA_LOCAL])
zlog_debug (" IFA_LOCAL %s/%d",
inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]),
@@ -616,7 +639,7 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
if (h->nlmsg_type == RTM_NEWADDR)
connected_add_ipv4 (ifp, flags,
(struct in_addr *) addr, ifa->ifa_prefixlen,
- (struct in_addr *) broad, label);
+ (struct in_addr *) broad, label, ifa->ifa_scope, 0);
else
connected_delete_ipv4 (ifp, flags,
(struct in_addr *) addr, ifa->ifa_prefixlen,
@@ -628,7 +651,7 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
if (h->nlmsg_type == RTM_NEWADDR)
connected_add_ipv6 (ifp, flags,
(struct in6_addr *) addr, ifa->ifa_prefixlen,
- (struct in6_addr *) broad, label);
+ (struct in6_addr *) broad, label, ifa->ifa_scope);
else
connected_delete_ipv6 (ifp,
(struct in6_addr *) addr, ifa->ifa_prefixlen,
@@ -647,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 };
@@ -662,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;
@@ -723,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)
@@ -733,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 */
@@ -771,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);
@@ -787,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;
}
@@ -861,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
@@ -889,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 */
@@ -1218,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)
{
@@ -1299,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
{
@@ -1321,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);
@@ -1742,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 */
@@ -1778,20 +1777,30 @@ netlink_address (int cmd, int family, struct interface *ifp,
req.ifa.ifa_family = family;
req.ifa.ifa_index = ifp->ifindex;
- req.ifa.ifa_prefixlen = p->prefixlen;
+ req.ifa.ifa_scope = ifc->scope;
addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen);
- if (family == AF_INET && cmd == RTM_NEWADDR)
+ if (family == AF_INET)
{
- if (!CONNECTED_PEER(ifc) && ifc->destination)
+ if (CONNECTED_PEER(ifc))
{
p = ifc->destination;
- addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix,
+ addattr_l (&req.n, sizeof req, IFA_ADDRESS, &p->u.prefix,
bytelen);
}
+ else
+ if (cmd == RTM_NEWADDR && ifc->destination)
+ {
+ p = ifc->destination;
+ addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix,
+ bytelen);
+ }
}
+ /* p is now either ifc->address or ifc->destination */
+ req.ifa.ifa_prefixlen = p->prefixlen;
+
if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY);
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/test_main.c b/zebra/test_main.c
index 70a1a3a6..4e1002e8 100644
--- a/zebra/test_main.c
+++ b/zebra/test_main.c
@@ -29,6 +29,7 @@
#include "log.h"
#include "privs.h"
#include "sigevent.h"
+#include "paths.h"
#include "zebra/rib.h"
#include "zebra/zserv.h"
@@ -73,10 +74,13 @@ zebra_capabilities_t _caps_p [] =
};
/* Default configuration file path. */
-char config_default[] = SYSCONFDIR DEFAULT_CONFIG_FILE;
+char config_default[MAXPATHLEN];
+
+/* pid_file default value */
+static char pid_file_default[MAXPATHLEN];
/* Process ID saved for use by init system */
-const char *pid_file = PATH_ZEBRA_PID;
+const char *pid_file = pid_file_default;
/* Help information display. */
static void
@@ -276,6 +280,9 @@ main (int argc, char **argv)
usage (progname, 1);
}
+ strcpy (config_default, path_config (ZEBRA_CONFIG_NAME));
+ strcpy (pid_file_default, path_state (ZEBRA_PID_NAME));
+
/* Make master thread emulator. */
zebrad.master = thread_master_create ();
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 12f3fa5a..a10ca84b 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -67,6 +67,7 @@ static const struct
{ZEBRA_ROUTE_OSPF6, 110},
{ZEBRA_ROUTE_ISIS, 115},
{ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */}
+ /* no entry/default: 150 */
};
/* Vector for routing table. */
@@ -298,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);
@@ -352,6 +352,17 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
break;
}
+ if (IS_ZEBRA_DEBUG_RIB) {
+ char buf[INET6_ADDRSTRLEN];
+ inet_ntop(rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
+ zlog_debug("%s: %s/%d: nexthop match %p: %s type=%d sel=%d int=%d",
+ __func__, buf, rn->p.prefixlen, match,
+ match ? zebra_route_string(match->type) : "<?>",
+ match ? match->type : -1,
+ match ? CHECK_FLAG(match->flags, ZEBRA_FLAG_SELECTED) : -1,
+ match ? CHECK_FLAG(match->flags, ZEBRA_FLAG_INTERNAL) : -1);
+ }
+
/* If there is no selected route or matched route is EGP, go up
tree. */
if (! match
@@ -365,7 +376,8 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
}
else
{
- if (match->type == ZEBRA_ROUTE_CONNECT)
+ if (match->type == ZEBRA_ROUTE_CONNECT
+ || (match->nexthop && match->nexthop->type == NEXTHOP_TYPE_IFINDEX))
{
/* Directly point connected route. */
newhop = match->nexthop;
@@ -374,7 +386,8 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
return 1;
}
- else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
+ else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL) ||
+ match->type == ZEBRA_ROUTE_KERNEL)
{
for (newhop = match->nexthop; newhop; newhop = newhop->next)
if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
@@ -755,6 +768,43 @@ rib_match_ipv6 (struct in6_addr *addr)
}
#endif /* HAVE_IPV6 */
+static void nexthop_dump(struct nexthop *nexthop,
+ char *type_str_buf,
+ int type_str_buf_size,
+ char *addr_str_buf,
+ int addr_str_buf_size,
+ char *via_str_buf,
+ int via_str_buf_size)
+{
+ switch (nexthop->type) {
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ snprintf(type_str_buf, type_str_buf_size, "ipv4");
+ snprintf(addr_str_buf, addr_str_buf_size, "%s", inet_ntoa(nexthop->gate.ipv4));
+ snprintf(via_str_buf, via_str_buf_size, "%s", nexthop->ifindex ? ifindex2ifname(nexthop->ifindex) : "<?>");
+ break;
+ case NEXTHOP_TYPE_IFINDEX:
+ snprintf(type_str_buf, type_str_buf_size, "connected");
+ snprintf(addr_str_buf, addr_str_buf_size, "<connected>");
+ snprintf(via_str_buf, via_str_buf_size, "%s", ifindex2ifname(nexthop->ifindex));
+ break;
+ case NEXTHOP_TYPE_IFNAME:
+ snprintf(type_str_buf, type_str_buf_size, "connected");
+ snprintf(addr_str_buf, addr_str_buf_size, "<connected>");
+ snprintf(via_str_buf, via_str_buf_size, "%s", nexthop->ifname);
+ break;
+ case NEXTHOP_TYPE_BLACKHOLE:
+ snprintf(type_str_buf, type_str_buf_size, "blackhole");
+ snprintf(addr_str_buf, addr_str_buf_size, "<blackhole>");
+ snprintf(via_str_buf, via_str_buf_size, "Null0");
+ break;
+ default:
+ snprintf(type_str_buf, type_str_buf_size, "unknown");
+ snprintf(addr_str_buf, addr_str_buf_size, "<unknown>");
+ snprintf(via_str_buf, via_str_buf_size, "<?>");
+ }
+}
+
#define RIB_SYSTEM_ROUTE(R) \
((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
@@ -808,10 +858,27 @@ nexthop_active_check (struct route_node *rn, struct rib *rib,
case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV4_IFINDEX:
family = AFI_IP;
- if (nexthop_active_ipv4 (rib, nexthop, set, rn))
- SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
- else
- UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+ {
+ int nh_active = nexthop_active_ipv4 (rib, nexthop, set, rn);
+ if (IS_ZEBRA_DEBUG_RIB) {
+ char type_str_buf[100];
+ char addr_str_buf[100];
+ char via_str_buf[100];
+ nexthop_dump(nexthop,
+ type_str_buf, sizeof(type_str_buf),
+ addr_str_buf, sizeof(addr_str_buf),
+ via_str_buf, sizeof(via_str_buf));
+ zlog_debug("%s: rib %p nexthop %p type=%d %s %s via %s ifindex=%d nexthop_active_ipv4=%d",
+ __func__, rib, nexthop,
+ nexthop->type, type_str_buf,
+ addr_str_buf, via_str_buf, nexthop->ifindex,
+ nh_active);
+ }
+ if (nh_active)
+ SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+ else
+ UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+ }
break;
#ifdef HAVE_IPV6
case NEXTHOP_TYPE_IPV6:
@@ -891,8 +958,23 @@ nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
{
prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
prev_index = nexthop->ifindex;
- if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
+ new_active = nexthop_active_check (rn, rib, nexthop, set);
+ if (new_active)
rib->nexthop_active_num++;
+ if (IS_ZEBRA_DEBUG_RIB) {
+ char type_str_buf[100];
+ char addr_str_buf[100];
+ char via_str_buf[100];
+ nexthop_dump(nexthop,
+ type_str_buf, sizeof(type_str_buf),
+ addr_str_buf, sizeof(addr_str_buf),
+ via_str_buf, sizeof(via_str_buf));
+ zlog_debug("%s: rib %p nexthop %p type=%d %s %s via %s ifindex=%d act=%d total_act=%d",
+ __func__, rib, nexthop,
+ nexthop->type, type_str_buf,
+ addr_str_buf, via_str_buf, nexthop->ifindex,
+ new_active, rib->nexthop_active_num);
+ }
if (prev_active != new_active ||
prev_index != nexthop->ifindex)
SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
@@ -992,6 +1074,15 @@ rib_process (struct route_node *rn)
* may be passed to rib_unlink() in the middle of iteration.
*/
next = rib->next;
+
+ if (IS_ZEBRA_DEBUG_RIB) {
+ zlog_debug("%s: %s/%d: scan rib %p: type=%d sel=%d rem=%d nh_act=%d dist=%d",
+ __func__, buf, rn->p.prefixlen, rib, rib->type,
+ CHECK_FLAG(rib->flags, ZEBRA_FLAG_SELECTED),
+ CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED),
+ nexthop_active_update(rn, rib, 0),
+ rib->distance);
+ }
/* Currently installed rib. */
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
@@ -1332,7 +1423,6 @@ rib_queue_init (struct zebra_t *zebra)
zebra->ribq->spec.errorfunc = NULL;
/* XXX: TODO: These should be runtime configurable via vty */
zebra->ribq->spec.max_retries = 3;
- zebra->ribq->spec.hold = rib_process_hold_time;
if (!(zebra->mq = meta_queue_new ()))
zlog_err ("%s: could not initialise meta queue!", __func__);
@@ -1511,7 +1601,10 @@ rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
/* Set default distance by route type. */
if (distance == 0)
{
- distance = route_info[type].distance;
+ if ((unsigned)type >= sizeof(route_info) / sizeof(route_info[0]))
+ distance = 150;
+ else
+ distance = route_info[type].distance;
/* iBGP distance is 200. */
if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
@@ -1551,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);
@@ -1830,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);
@@ -1839,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);
@@ -1878,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);
@@ -1891,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
@@ -2011,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);
@@ -2099,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;
@@ -2118,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)
@@ -2151,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;
@@ -2340,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;
@@ -2385,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);
@@ -2426,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);
@@ -2439,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
@@ -2533,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);
}
@@ -2557,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);
@@ -2583,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;
}
@@ -2651,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;
@@ -2694,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)
{
@@ -2708,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
@@ -2791,23 +2945,45 @@ static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
#endif /* HAVE_IPV6 */
/* RIB update function. */
-void
-rib_update (void)
+static void
+rib_update_table (struct table *table)
{
struct route_node *rn;
- struct route_table *table;
-
- table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
if (table)
for (rn = route_top (table); rn; rn = route_next (rn))
if (rn->info)
rib_queue_add (&zebrad, rn);
+}
- table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
- if (table)
- for (rn = route_top (table); rn; rn = route_next (rn))
- if (rn->info)
- rib_queue_add (&zebrad, rn);
+void
+rib_update (void)
+{
+ if (zebrad.update)
+ {
+ thread_cancel (zebrad.update);
+ zebrad.update = NULL;
+ }
+
+ rib_update_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
+
+#ifdef HAVE_IPV6
+ rib_update_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
+#endif
+}
+
+static int
+rib_update_thread (struct thread *self)
+{
+ rib_update ();
+ return 0;
+}
+
+void
+rib_update_background (void)
+{
+ if (!zebrad.update)
+ zebrad.update = thread_add_background (zebrad.master, rib_update_thread,
+ NULL, rib_process_hold_time);
}
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index ecb5d10a..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;
- }
-
- /* 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);
- 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
@@ -802,10 +800,6 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
}
}
-#define SHOW_ROUTE_V4_HEADER "Codes: K - kernel route, C - connected, " \
- "S - static, R - RIP, O - OSPF,%s I - ISIS, B - BGP, " \
- "> - selected route, * - FIB route%s%s"
-
DEFUN (show_ip_route,
show_ip_route_cmd,
"show ip route",
@@ -828,8 +822,7 @@ DEFUN (show_ip_route,
{
if (first)
{
- vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, VTY_NEWLINE,
- VTY_NEWLINE);
+ vty_out (vty, SHOW_ROUTE_V4_HEADER);
first = 0;
}
vty_show_ip_route (vty, rn, rib);
@@ -871,8 +864,7 @@ DEFUN (show_ip_route_prefix_longer,
{
if (first)
{
- vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE,
- VTY_NEWLINE, VTY_NEWLINE);
+ vty_out (vty, SHOW_ROUTE_V4_HEADER);
first = 0;
}
vty_show_ip_route (vty, rn, rib);
@@ -910,8 +902,7 @@ DEFUN (show_ip_route_supernets,
{
if (first)
{
- vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE,
- VTY_NEWLINE, VTY_NEWLINE);
+ vty_out (vty, SHOW_ROUTE_V4_HEADER);
first = 0;
}
vty_show_ip_route (vty, rn, rib);
@@ -922,17 +913,11 @@ DEFUN (show_ip_route_supernets,
DEFUN (show_ip_route_protocol,
show_ip_route_protocol_cmd,
- "show ip route (bgp|connected|isis|kernel|ospf|rip|static)",
+ "show ip route " QUAGGA_IP_REDIST_STR_ZEBRA,
SHOW_STR
IP_STR
"IP routing table\n"
- "Border Gateway Protocol (BGP)\n"
- "Connected\n"
- "ISO IS-IS (ISIS)\n"
- "Kernel\n"
- "Open Shortest Path First (OSPF)\n"
- "Routing Information Protocol (RIP)\n"
- "Static routes\n")
+ QUAGGA_IP_REDIST_HELP_STR_ZEBRA)
{
int type;
struct route_table *table;
@@ -940,21 +925,8 @@ DEFUN (show_ip_route_protocol,
struct rib *rib;
int first = 1;
- if (strncmp (argv[0], "b", 1) == 0)
- type = ZEBRA_ROUTE_BGP;
- else if (strncmp (argv[0], "c", 1) == 0)
- type = ZEBRA_ROUTE_CONNECT;
- else if (strncmp (argv[0], "k", 1) ==0)
- type = ZEBRA_ROUTE_KERNEL;
- else if (strncmp (argv[0], "o", 1) == 0)
- type = ZEBRA_ROUTE_OSPF;
- else if (strncmp (argv[0], "i", 1) == 0)
- type = ZEBRA_ROUTE_ISIS;
- else if (strncmp (argv[0], "r", 1) == 0)
- type = ZEBRA_ROUTE_RIP;
- else if (strncmp (argv[0], "s", 1) == 0)
- type = ZEBRA_ROUTE_STATIC;
- else
+ type = proto_redistnum (AFI_IP, argv[0]);
+ if (type < 0)
{
vty_out (vty, "Unknown route type%s", VTY_NEWLINE);
return CMD_WARNING;
@@ -971,8 +943,7 @@ DEFUN (show_ip_route_protocol,
{
if (first)
{
- vty_out (vty, SHOW_ROUTE_V4_HEADER,
- VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+ vty_out (vty, SHOW_ROUTE_V4_HEADER);
first = 0;
}
vty_show_ip_route (vty, rn, rib);
@@ -1168,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)
@@ -1237,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)
@@ -1249,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)
@@ -1272,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);
@@ -1303,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);
@@ -1322,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",
@@ -1348,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>",
@@ -1375,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>",
@@ -1403,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)",
@@ -1431,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",
@@ -1456,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>",
@@ -1482,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)
@@ -1549,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
@@ -1700,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;
}
@@ -1731,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
@@ -1766,8 +1652,6 @@ vty_show_ipv6_route (struct vty *vty, struct route_node *rn,
}
}
-#define SHOW_ROUTE_V6_HEADER "Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3,%s I - ISIS, B - BGP, * - FIB route.%s%s"
-
DEFUN (show_ipv6_route,
show_ipv6_route_cmd,
"show ipv6 route",
@@ -1790,7 +1674,7 @@ DEFUN (show_ipv6_route,
{
if (first)
{
- vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+ vty_out (vty, SHOW_ROUTE_V6_HEADER);
first = 0;
}
vty_show_ipv6_route (vty, rn, rib);
@@ -1832,7 +1716,7 @@ DEFUN (show_ipv6_route_prefix_longer,
{
if (first)
{
- vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+ vty_out (vty, SHOW_ROUTE_V6_HEADER);
first = 0;
}
vty_show_ipv6_route (vty, rn, rib);
@@ -1842,17 +1726,11 @@ DEFUN (show_ipv6_route_prefix_longer,
DEFUN (show_ipv6_route_protocol,
show_ipv6_route_protocol_cmd,
- "show ipv6 route (bgp|connected|isis|kernel|ospf6|ripng|static)",
+ "show ipv6 route " QUAGGA_IP6_REDIST_STR_ZEBRA,
SHOW_STR
IP_STR
"IP routing table\n"
- "Border Gateway Protocol (BGP)\n"
- "Connected\n"
- "ISO IS-IS (ISIS)\n"
- "Kernel\n"
- "Open Shortest Path First (OSPFv3)\n"
- "Routing Information Protocol (RIPng)\n"
- "Static routes\n")
+ QUAGGA_IP6_REDIST_HELP_STR_ZEBRA)
{
int type;
struct route_table *table;
@@ -1860,21 +1738,8 @@ DEFUN (show_ipv6_route_protocol,
struct rib *rib;
int first = 1;
- if (strncmp (argv[0], "b", 1) == 0)
- type = ZEBRA_ROUTE_BGP;
- else if (strncmp (argv[0], "c", 1) == 0)
- type = ZEBRA_ROUTE_CONNECT;
- else if (strncmp (argv[0], "k", 1) ==0)
- type = ZEBRA_ROUTE_KERNEL;
- else if (strncmp (argv[0], "o", 1) == 0)
- type = ZEBRA_ROUTE_OSPF6;
- else if (strncmp (argv[0], "i", 1) == 0)
- type = ZEBRA_ROUTE_ISIS;
- else if (strncmp (argv[0], "r", 1) == 0)
- type = ZEBRA_ROUTE_RIPNG;
- else if (strncmp (argv[0], "s", 1) == 0)
- type = ZEBRA_ROUTE_STATIC;
- else
+ type = proto_redistnum (AFI_IP6, argv[0]);
+ if (type < 0)
{
vty_out (vty, "Unknown route type%s", VTY_NEWLINE);
return CMD_WARNING;
@@ -1891,7 +1756,7 @@ DEFUN (show_ipv6_route_protocol,
{
if (first)
{
- vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+ vty_out (vty, SHOW_ROUTE_V6_HEADER);
first = 0;
}
vty_show_ipv6_route (vty, rn, rib);
@@ -2031,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);
@@ -2139,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);
diff --git a/zebra/zserv.c b/zebra/zserv.c
index cb5e411c..ced8fa5a 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -1,5 +1,6 @@
/* Zebra daemon server routine.
* Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
+ * Portions Copyright (c) 2008 Everton da Silva Marques <everton.marques@gmail.com>
*
* This file is part of GNU Zebra.
*
@@ -36,6 +37,7 @@
#include "privs.h"
#include "network.h"
#include "buffer.h"
+#include "paths.h"
#include "zebra/zserv.h"
#include "zebra/router-id.h"
@@ -595,6 +597,77 @@ zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr)
return zebra_server_send_message(client);
}
+/*
+ Modified version of zsend_ipv4_nexthop_lookup():
+ 1) Returns both nexthop address and nexthop ifindex
+ (with ZEBRA_NEXTHOP_IPV4_IFINDEX).
+ 2) Returns both route metric and protocol distance.
+*/
+static int
+zsend_ipv4_nexthop_lookup_v2 (struct zserv *client, struct in_addr addr)
+{
+ struct stream *s;
+ struct rib *rib;
+ unsigned long nump;
+ u_char num;
+ struct nexthop *nexthop;
+
+ /* Lookup nexthop. */
+ rib = rib_match_ipv4 (addr);
+
+ /* Get output stream. */
+ s = client->obuf;
+ stream_reset (s);
+
+ /* Fill in result. */
+ zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP_V2);
+ stream_put_in_addr (s, &addr);
+
+ if (rib)
+ {
+ stream_putc (s, rib->distance);
+ stream_putl (s, rib->metric);
+ num = 0;
+ nump = stream_get_endp(s); /* remember position for nexthop_num */
+ stream_putc (s, 0); /* reserve room for nexthop_num */
+ for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+ if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
+ {
+ stream_putc (s, nexthop->type);
+ switch (nexthop->type)
+ {
+ case ZEBRA_NEXTHOP_IPV4:
+ stream_put_in_addr (s, &nexthop->gate.ipv4);
+ break;
+ case ZEBRA_NEXTHOP_IFINDEX:
+ case ZEBRA_NEXTHOP_IFNAME:
+ stream_putl (s, nexthop->ifindex);
+ break;
+ case ZEBRA_NEXTHOP_IPV4_IFINDEX:
+ stream_put_in_addr (s, &nexthop->gate.ipv4);
+ stream_putl (s, nexthop->ifindex);
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ num++;
+ }
+
+ stream_putc_at (s, nump, num); /* store nexthop_num */
+ }
+ else
+ {
+ stream_putc (s, 0); /* distance */
+ stream_putl (s, 0); /* metric */
+ stream_putc (s, 0); /* nexthop_num */
+ }
+
+ stream_putw_at (s, 0, stream_get_endp (s));
+
+ return zebra_server_send_message(client);
+}
+
static int
zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p)
{
@@ -804,6 +877,8 @@ zread_ipv4_add (struct zserv *client, u_short length)
/* Table */
rib->table=zebrad.rtm_table_default;
rib_add_ipv4_multipath (&p, rib);
+
+ rib_update_background ();
return 0;
}
@@ -878,6 +953,8 @@ zread_ipv4_delete (struct zserv *client, u_short length)
rib_delete_ipv4 (api.type, api.flags, &p, &nexthop, ifindex,
client->rtm_table);
+
+ rib_update_background ();
return 0;
}
@@ -891,6 +968,16 @@ zread_ipv4_nexthop_lookup (struct zserv *client, u_short length)
return zsend_ipv4_nexthop_lookup (client, addr);
}
+/* Nexthop lookup v2 for IPv4. */
+static int
+zread_ipv4_nexthop_lookup_v2 (struct zserv *client, u_short length)
+{
+ struct in_addr addr;
+
+ addr.s_addr = stream_get_ipv4 (client->ibuf);
+ return zsend_ipv4_nexthop_lookup_v2 (client, addr);
+}
+
/* Nexthop lookup for IPv4. */
static int
zread_ipv4_import_lookup (struct zserv *client, u_short length)
@@ -969,6 +1056,8 @@ zread_ipv6_add (struct zserv *client, u_short length)
else
rib_add_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, zebrad.rtm_table_default, api.metric,
api.distance);
+
+ rib_update_background ();
return 0;
}
@@ -1033,6 +1122,8 @@ zread_ipv6_delete (struct zserv *client, u_short length)
rib_delete_ipv6 (api.type, api.flags, &p, NULL, ifindex, client->rtm_table);
else
rib_delete_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, client->rtm_table);
+
+ rib_update_background ();
return 0;
}
@@ -1275,6 +1366,9 @@ zebra_client_read (struct thread *thread)
case ZEBRA_IPV4_NEXTHOP_LOOKUP:
zread_ipv4_nexthop_lookup (client, length);
break;
+ case ZEBRA_IPV4_NEXTHOP_LOOKUP_V2:
+ zread_ipv4_nexthop_lookup_v2 (client, length);
+ break;
#ifdef HAVE_IPV6
case ZEBRA_IPV6_NEXTHOP_LOOKUP:
zread_ipv6_nexthop_lookup (client, length);
@@ -1738,6 +1832,6 @@ zebra_zserv_socket_init (void)
#ifdef HAVE_TCP_ZEBRA
zebra_serv ();
#else
- zebra_serv_un (ZEBRA_SERV_PATH);
+ zebra_serv_un (path_state (ZEBRA_SERV_NAME));
#endif /* HAVE_TCP_ZEBRA */
}
diff --git a/zebra/zserv.h b/zebra/zserv.h
index a7371830..340e7f5d 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -30,7 +30,9 @@
#define ZEBRA_VTY_PORT 2601
/* Default configuration filename. */
-#define DEFAULT_CONFIG_FILE "zebra.conf"
+#define ZEBRA_CONFIG_NAME "zebra.conf"
+#define ZEBRA_PID_NAME "zebra.pid"
+#define ZEBRA_VTY_NAME "zebra.vty"
/* Client structure. */
struct zserv
@@ -81,6 +83,9 @@ struct zebra_t
/* rib work queue */
struct work_queue *ribq;
struct meta_queue *mq;
+
+ /* rib update thread */
+ struct thread *update;
};
/* Count prefix size from mask length */