summaryrefslogtreecommitdiff
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-rw-r--r--zebra/.cvsignore13
-rw-r--r--zebra/client_main.c1
-rw-r--r--zebra/connected.c8
-rw-r--r--zebra/if_netlink.c2
-rw-r--r--zebra/interface.c24
-rw-r--r--zebra/interface.h17
-rw-r--r--zebra/ipforward_proc.c9
-rw-r--r--zebra/irdp_interface.c3
-rw-r--r--zebra/kernel_socket.c28
-rw-r--r--zebra/main.c12
-rw-r--r--zebra/redistribute.c46
-rw-r--r--zebra/rib.h11
-rw-r--r--zebra/rt_netlink.c24
-rw-r--r--zebra/rtadv.c338
-rw-r--r--zebra/rtadv.h6
-rw-r--r--zebra/rtread_getmsg.c2
-rw-r--r--zebra/rtread_netlink.c3
-rw-r--r--zebra/rtread_proc.c2
-rw-r--r--zebra/zebra_rib.c102
-rw-r--r--zebra/zebra_vty.c163
-rw-r--r--zebra/zserv.c81
-rw-r--r--zebra/zserv.h2
22 files changed, 588 insertions, 309 deletions
diff --git a/zebra/.cvsignore b/zebra/.cvsignore
deleted file mode 100644
index 59c5889e..00000000
--- a/zebra/.cvsignore
+++ /dev/null
@@ -1,13 +0,0 @@
-Makefile
-Makefile.in
-*.o
-zebra
-zebra.conf
-client
-tags
-TAGS
-.deps
-.nfs*
-.libs
-.arch-inventory
-.arch-ids
diff --git a/zebra/client_main.c b/zebra/client_main.c
index ce01231f..8b95907b 100644
--- a/zebra/client_main.c
+++ b/zebra/client_main.c
@@ -115,6 +115,7 @@ struct zebra_info
{ "static", ZEBRA_ROUTE_STATIC },
{ "rip", ZEBRA_ROUTE_RIP },
{ "ripng", ZEBRA_ROUTE_RIPNG },
+ { "babel", ZEBRA_ROUTE_BABEL },
{ "ospf", ZEBRA_ROUTE_OSPF },
{ "ospf6", ZEBRA_ROUTE_OSPF6 },
{ "bgp", ZEBRA_ROUTE_BGP },
diff --git a/zebra/connected.c b/zebra/connected.c
index 95399fa1..f699b147 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -189,7 +189,7 @@ connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
return;
rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,
- RT_TABLE_MAIN, ifp->metric, 0);
+ RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST);
rib_update ();
}
@@ -295,7 +295,7 @@ connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
return;
/* Same logic as for connected_up_ipv4(): push the changes into the head. */
- rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
+ rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST);
rib_update ();
}
@@ -343,7 +343,7 @@ connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
#endif
rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, RT_TABLE_MAIN,
- ifp->metric, 0);
+ ifp->metric, 0, SAFI_UNICAST);
rib_update ();
}
@@ -417,7 +417,7 @@ connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
return;
- rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
+ rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST);
rib_update ();
}
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 701c81b6..86bd8ffe 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -22,6 +22,8 @@
#include <zebra.h>
+#include "zebra/zserv.h"
+
extern int interface_lookup_netlink (void);
/* Interface information read by netlink. */
diff --git a/zebra/interface.c b/zebra/interface.c
index 03e7ff71..22422594 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -76,9 +76,9 @@ if_zebra_new_hook (struct interface *ifp)
rtadv->AdvReachableTime = 0;
rtadv->AdvRetransTimer = 0;
rtadv->AdvCurHopLimit = 0;
- rtadv->AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
+ rtadv->AdvDefaultLifetime = -1; /* derive from MaxRtrAdvInterval */
rtadv->HomeAgentPreference = 0;
- rtadv->HomeAgentLifetime = RTADV_ADV_DEFAULT_LIFETIME;
+ rtadv->HomeAgentLifetime = -1; /* derive from AdvDefaultLifetime */
rtadv->AdvIntervalOption = 0;
rtadv->DefaultPreference = RTADV_PREF_MEDIUM;
@@ -216,7 +216,7 @@ if_subnet_delete (struct interface *ifp, struct connected *ifc)
* interface will affect only the primary interface/address on Solaris.
************************End Solaris flags hacks ***********************
*/
-static inline void
+static void
if_flags_mangle (struct interface *ifp, uint64_t *newflags)
{
#ifdef SUNOS_5
@@ -630,8 +630,12 @@ nd_dump_vty (struct vty *vty, struct interface *ifp)
vty_out (vty, " ND router advertisements are sent every "
"%d seconds%s", interval / 1000,
VTY_NEWLINE);
- vty_out (vty, " ND router advertisements live for %d seconds%s",
- rtadv->AdvDefaultLifetime, VTY_NEWLINE);
+ if (rtadv->AdvDefaultLifetime != -1)
+ vty_out (vty, " ND router advertisements live for %d seconds%s",
+ rtadv->AdvDefaultLifetime, VTY_NEWLINE);
+ else
+ vty_out (vty, " ND router advertisements lifetime tracks ra-interval%s",
+ VTY_NEWLINE);
vty_out (vty, " ND router advertisement default router preference is "
"%s%s", rtadv_pref_strs[rtadv->DefaultPreference],
VTY_NEWLINE);
@@ -642,9 +646,19 @@ nd_dump_vty (struct vty *vty, struct interface *ifp)
vty_out (vty, " Hosts use stateless autoconfig for addresses.%s",
VTY_NEWLINE);
if (rtadv->AdvHomeAgentFlag)
+ {
vty_out (vty, " ND router advertisements with "
"Home Agent flag bit set.%s",
VTY_NEWLINE);
+ if (rtadv->HomeAgentLifetime != -1)
+ vty_out (vty, " Home Agent lifetime is %u seconds%s",
+ rtadv->HomeAgentLifetime, VTY_NEWLINE);
+ else
+ vty_out (vty, " Home Agent lifetime tracks ra-lifetime%s",
+ VTY_NEWLINE);
+ vty_out (vty, " Home Agent preference is %u%s",
+ rtadv->HomeAgentPreference, VTY_NEWLINE);
+ }
if (rtadv->AdvIntervalOption)
vty_out (vty, " ND router advertisements with Adv. Interval option.%s",
VTY_NEWLINE);
diff --git a/zebra/interface.h b/zebra/interface.h
index 0cf66403..0777a2fa 100644
--- a/zebra/interface.h
+++ b/zebra/interface.h
@@ -46,7 +46,7 @@
#endif
#ifdef RTADV
-/* Router advertisement parameter. From RFC2461, RFC3775 and RFC4191. */
+/* Router advertisement parameter. From RFC4861, RFC6275 and RFC4191. */
struct rtadvconf
{
/* A flag indicating whether or not the router sends periodic Router
@@ -56,8 +56,8 @@ struct rtadvconf
/* The maximum time allowed between sending unsolicited multicast
Router Advertisements from the interface, in milliseconds.
- MUST be no less than 70 ms (RFC3775, section 7.4) and no greater
- than 1800000 ms (See RFC2461).
+ MUST be no less than 70 ms [RFC6275 7.5] and no greater
+ than 1800000 ms [RFC4861 6.2.1].
Default: 600000 milliseconds */
int MaxRtrAdvInterval;
@@ -65,11 +65,11 @@ struct rtadvconf
/* The minimum time allowed between sending unsolicited multicast
Router Advertisements from the interface, in milliseconds.
- MUST be no less than 30 ms (See RFC3775, section 7.4).
+ MUST be no less than 30 ms [RFC6275 7.5].
MUST be no greater than .75 * MaxRtrAdvInterval.
Default: 0.33 * MaxRtrAdvInterval */
- int MinRtrAdvInterval;
+ int MinRtrAdvInterval; /* This field is currently unused. */
#define RTADV_MIN_RTR_ADV_INTERVAL (0.33 * RTADV_MAX_RTR_ADV_INTERVAL)
/* Unsolicited Router Advertisements' interval timer. */
@@ -131,8 +131,7 @@ struct rtadvconf
Default: 3 * MaxRtrAdvInterval */
int AdvDefaultLifetime;
-#define RTADV_ADV_DEFAULT_LIFETIME (3 * RTADV_MAX_RTR_ADV_INTERVAL)
-
+#define RTADV_MAX_RTRLIFETIME 9000 /* 2.5 hours */
/* A list of prefixes to be placed in Prefix Information options in
Router Advertisement messages sent from the interface.
@@ -144,7 +143,7 @@ struct rtadvconf
struct list *AdvPrefixList;
/* The TRUE/FALSE value to be placed in the "Home agent"
- flag field in the Router Advertisement. See [RFC3775 7.1].
+ flag field in the Router Advertisement. See [RFC6275 7.1].
Default: FALSE */
int AdvHomeAgentFlag;
@@ -167,7 +166,7 @@ struct rtadvconf
#define RTADV_MAX_HALIFETIME 65520 /* 18.2 hours */
/* The TRUE/FALSE value to insert or not an Advertisement Interval
- option. See [RFC 3775 7.3]
+ option. See [RFC 6275 7.3]
Default: FALSE */
int AdvIntervalOption;
diff --git a/zebra/ipforward_proc.c b/zebra/ipforward_proc.c
index 73846137..2876eded 100644
--- a/zebra/ipforward_proc.c
+++ b/zebra/ipforward_proc.c
@@ -45,7 +45,6 @@ ipforward (void)
{
FILE *fp;
int ipforwarding = 0;
- char *pnt;
char buf[10];
fp = fopen (proc_net_snmp, "r");
@@ -59,8 +58,8 @@ ipforward (void)
/* Get ip_statistics.IpForwarding :
1 => ip forwarding enabled
2 => ip forwarding off. */
- pnt = fgets (buf, 6, fp);
- sscanf (buf, "Ip: %d", &ipforwarding);
+ if (fgets (buf, 6, fp))
+ sscanf (buf, "Ip: %d", &ipforwarding);
fclose(fp);
@@ -140,8 +139,8 @@ ipforward_ipv6 (void)
if (fp == NULL)
return -1;
- fgets (buf, 2, fp);
- sscanf (buf, "%d", &ipforwarding);
+ if (fgets (buf, 2, fp))
+ sscanf (buf, "%d", &ipforwarding);
fclose (fp);
return ipforwarding;
diff --git a/zebra/irdp_interface.c b/zebra/irdp_interface.c
index 8742b62b..6403830b 100644
--- a/zebra/irdp_interface.c
+++ b/zebra/irdp_interface.c
@@ -99,14 +99,11 @@ if_group (struct interface *ifp,
u_int32_t group,
int add_leave)
{
- struct zebra_if *zi;
struct ip_mreq m;
struct prefix *p;
int ret;
char b1[INET_ADDRSTRLEN];
- zi = ifp->info;
-
memset (&m, 0, sizeof (m));
m.imr_multiaddr.s_addr = htonl (group);
p = irdp_get_prefix(ifp);
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index feeaf5d0..b7061e76 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -319,6 +319,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 +357,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 +456,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
@@ -606,7 +618,7 @@ ifam_read_mesg (struct ifa_msghdr *ifm,
/* Assert read up end point matches to end point */
if (pnt != end)
- zlog_warn ("ifam_read() does't read all socket data");
+ zlog_warn ("ifam_read() doesn't read all socket data");
}
/* Interface's address information get. */
@@ -754,7 +766,7 @@ rtm_read_mesg (struct rt_msghdr *rtm,
/* Assert read up to the end of pointer. */
if (pnt != end)
- zlog (NULL, LOG_WARNING, "rtm_read() does't read all socket data.");
+ zlog (NULL, LOG_WARNING, "rtm_read() doesn't read all socket data.");
return rtm->rtm_flags;
}
@@ -894,16 +906,16 @@ rtm_read (struct rt_msghdr *rtm)
*/
if (rtm->rtm_type == RTM_CHANGE)
rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p,
- NULL, 0, 0);
+ NULL, 0, 0, SAFI_UNICAST);
if (rtm->rtm_type == RTM_GET
|| rtm->rtm_type == RTM_ADD
|| rtm->rtm_type == RTM_CHANGE)
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags,
- &p, &gate.sin.sin_addr, NULL, 0, 0, 0, 0);
+ &p, &gate.sin.sin_addr, NULL, 0, 0, 0, 0, SAFI_UNICAST);
else
rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags,
- &p, &gate.sin.sin_addr, 0, 0);
+ &p, &gate.sin.sin_addr, 0, 0, SAFI_UNICAST);
}
#ifdef HAVE_IPV6
if (dest.sa.sa_family == AF_INET6)
@@ -936,16 +948,16 @@ rtm_read (struct rt_msghdr *rtm)
*/
if (rtm->rtm_type == RTM_CHANGE)
rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p,
- NULL, 0, 0);
+ NULL, 0, 0, SAFI_UNICAST);
if (rtm->rtm_type == RTM_GET
|| rtm->rtm_type == RTM_ADD
|| rtm->rtm_type == RTM_CHANGE)
rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags,
- &p, &gate.sin6.sin6_addr, ifindex, 0, 0, 0);
+ &p, &gate.sin6.sin6_addr, ifindex, 0, 0, 0, SAFI_UNICAST);
else
rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags,
- &p, &gate.sin6.sin6_addr, ifindex, 0);
+ &p, &gate.sin6.sin6_addr, ifindex, 0, SAFI_UNICAST);
}
#endif /* HAVE_IPV6 */
}
diff --git a/zebra/main.c b/zebra/main.c
index d829c046..5f26ce24 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -71,6 +71,7 @@ struct option longopts[] =
{ "keep_kernel", no_argument, NULL, 'k'},
{ "config_file", required_argument, NULL, 'f'},
{ "pid_file", required_argument, NULL, 'i'},
+ { "socket", required_argument, NULL, 'z'},
{ "help", no_argument, NULL, 'h'},
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
@@ -128,6 +129,7 @@ usage (char *progname, int status)
"-d, --daemon Runs in daemon mode\n"\
"-f, --config_file Set configuration file name\n"\
"-i, --pid_file Set process identifier file name\n"\
+ "-z, --socket Set path of zebra socket\n"\
"-k, --keep_kernel Don't delete old routes which installed by "\
"zebra.\n"\
"-C, --dryrun Check configuration for validity and exit\n"\
@@ -214,6 +216,7 @@ main (int argc, char **argv)
char *config_file = NULL;
char *progname;
struct thread thread;
+ char *zserv_path = NULL;
/* Set umask before anything for security */
umask (0027);
@@ -229,9 +232,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, "bdkf:i:z: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, "bdkf:i:z:hA:P:ru:g:vC", longopts, 0);
#endif /* HAVE_NETLINK */
if (opt == EOF)
@@ -261,6 +264,9 @@ main (int argc, char **argv)
case 'i':
pid_file = optarg;
break;
+ case 'z':
+ zserv_path = optarg;
+ break;
case 'P':
/* Deal with atoi() returning 0 on failure, and zebra not
listening on zebra port... */
@@ -386,7 +392,7 @@ main (int argc, char **argv)
pid = getpid ();
/* This must be done only after locking pidfile (bug #403). */
- zebra_zserv_socket_init ();
+ zebra_zserv_socket_init (zserv_path);
/* Make vty server socket. */
vty_serv_sock (vty_addr, vty_port, ZEBRA_VTYSH_PATH);
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..2872fc03 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -249,13 +249,13 @@ extern struct route_table *vrf_static_table (afi_t afi, safi_t safi, u_int32_t i
extern int rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
struct in_addr *gate, struct in_addr *src,
unsigned int ifindex, u_int32_t vrf_id,
- u_int32_t, u_char);
+ u_int32_t, u_char, safi_t);
-extern int rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *);
+extern int rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *, safi_t);
extern int rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
struct in_addr *gate, unsigned int ifindex,
- u_int32_t);
+ u_int32_t, safi_t safi);
extern struct rib *rib_match_ipv4 (struct in_addr);
@@ -266,6 +266,7 @@ extern void rib_weed_tables (void);
extern void rib_sweep_route (void);
extern void rib_close (void);
extern void rib_init (void);
+extern unsigned long rib_score_proto (u_char proto);
extern int
static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
@@ -279,11 +280,11 @@ static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
extern int
rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
- u_int32_t metric, u_char distance);
+ u_int32_t metric, u_char distance, safi_t safi);
extern int
rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
- struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id);
+ struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi);
extern struct rib *rib_lookup_ipv6 (struct in6_addr *);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 7652f80a..f48df2bf 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -723,7 +723,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
memcpy (&p.prefix, dest, 4);
p.prefixlen = rtm->rtm_dst_len;
- rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index, table, metric, 0);
+ rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index, table, metric, 0, SAFI_UNICAST);
}
#ifdef HAVE_IPV6
if (rtm->rtm_family == AF_INET6)
@@ -734,7 +734,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
p.prefixlen = rtm->rtm_dst_len;
rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table,
- metric, 0);
+ metric, 0, SAFI_UNICAST);
}
#endif /* HAVE_IPV6 */
@@ -768,6 +768,8 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
int index;
int table;
+ int metric;
+
void *dest;
void *gate;
void *src;
@@ -825,6 +827,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
}
index = 0;
+ metric = 0;
dest = NULL;
gate = NULL;
src = NULL;
@@ -843,6 +846,9 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
if (tb[RTA_PREFSRC])
src = RTA_DATA (tb[RTA_PREFSRC]);
+ if (h->nlmsg_type == RTM_NEWROUTE && tb[RTA_PRIORITY])
+ metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
+
if (rtm->rtm_family == AF_INET)
{
struct prefix_ipv4 p;
@@ -861,9 +867,9 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
}
if (h->nlmsg_type == RTM_NEWROUTE)
- rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table, 0, 0);
+ rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table, metric, 0, SAFI_UNICAST);
else
- rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table);
+ rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, SAFI_UNICAST);
}
#ifdef HAVE_IPV6
@@ -889,9 +895,9 @@ 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, 0, &p, gate, index, table, metric, 0, SAFI_UNICAST);
else
- rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table);
+ rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, SAFI_UNICAST);
}
#endif /* HAVE_IPV6 */
@@ -1821,11 +1827,7 @@ extern struct thread_master *master;
static int
kernel_read (struct thread *thread)
{
- int ret;
- int sock;
-
- sock = THREAD_FD (thread);
- ret = netlink_parse_info (netlink_information_fetch, &netlink);
+ netlink_parse_info (netlink_information_fetch, &netlink);
thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock);
return 0;
diff --git a/zebra/rtadv.c b/zebra/rtadv.c
index 8cc3c4cb..ae5c5a1c 100644
--- a/zebra/rtadv.c
+++ b/zebra/rtadv.c
@@ -163,6 +163,7 @@ rtadv_send_packet (int sock, struct interface *ifp)
struct rtadv_prefix *rprefix;
u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
struct listnode *node;
+ u_int16_t pkt_RouterLifetime;
/*
* Allocate control message bufffer. This is dynamic because
@@ -190,7 +191,7 @@ rtadv_send_packet (int sock, struct interface *ifp)
addr.sin6_len = sizeof (struct sockaddr_in6);
#endif /* SIN6_LEN */
addr.sin6_port = htons (IPPROTO_ICMPV6);
- memcpy (&addr.sin6_addr, all_nodes_addr, sizeof (struct in6_addr));
+ IPV6_ADDR_COPY (&addr.sin6_addr, all_nodes_addr);
/* Fetch interface information. */
zif = ifp->info;
@@ -215,13 +216,32 @@ rtadv_send_packet (int sock, struct interface *ifp)
rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
if (zif->rtadv.AdvHomeAgentFlag)
rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;
- rtadv->nd_ra_router_lifetime = htons (zif->rtadv.AdvDefaultLifetime);
+ /* Note that according to Neighbor Discovery (RFC 4861 [18]),
+ * AdvDefaultLifetime is by default based on the value of
+ * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
+ * field of Router Advertisements. Given that this field is expressed
+ * in seconds, a small MaxRtrAdvInterval value can result in a zero
+ * value for this field. To prevent this, routers SHOULD keep
+ * AdvDefaultLifetime in at least one second, even if the use of
+ * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
+ pkt_RouterLifetime = zif->rtadv.AdvDefaultLifetime != -1 ?
+ zif->rtadv.AdvDefaultLifetime :
+ MAX (1, 0.003 * zif->rtadv.MaxRtrAdvInterval);
+ rtadv->nd_ra_router_lifetime = htons (pkt_RouterLifetime);
rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);
rtadv->nd_ra_retransmit = htonl (0);
len = sizeof (struct nd_router_advert);
- if (zif->rtadv.AdvHomeAgentFlag)
+ /* If both the Home Agent Preference and Home Agent Lifetime are set to
+ * their default values specified above, this option SHOULD NOT be
+ * included in the Router Advertisement messages sent by this home
+ * agent. -- RFC6275, 7.4 */
+ if
+ (
+ zif->rtadv.AdvHomeAgentFlag &&
+ (zif->rtadv.HomeAgentPreference || zif->rtadv.HomeAgentLifetime != -1)
+ )
{
struct nd_opt_homeagent_info *ndopt_hai =
(struct nd_opt_homeagent_info *)(buf + len);
@@ -229,7 +249,17 @@ rtadv_send_packet (int sock, struct interface *ifp)
ndopt_hai->nd_opt_hai_len = 1;
ndopt_hai->nd_opt_hai_reserved = 0;
ndopt_hai->nd_opt_hai_preference = htons(zif->rtadv.HomeAgentPreference);
- ndopt_hai->nd_opt_hai_lifetime = htons(zif->rtadv.HomeAgentLifetime);
+ /* 16-bit unsigned integer. The lifetime associated with the home
+ * agent in units of seconds. The default value is the same as the
+ * Router Lifetime, as specified in the main body of the Router
+ * Advertisement. The maximum value corresponds to 18.2 hours. A
+ * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
+ ndopt_hai->nd_opt_hai_lifetime = htons
+ (
+ zif->rtadv.HomeAgentLifetime != -1 ?
+ zif->rtadv.HomeAgentLifetime :
+ MAX (1, pkt_RouterLifetime) /* 0 is OK for RL, but not for HAL*/
+ );
len += sizeof(struct nd_opt_homeagent_info);
}
@@ -267,8 +297,7 @@ rtadv_send_packet (int sock, struct interface *ifp)
pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime);
pinfo->nd_opt_pi_reserved2 = 0;
- memcpy (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.u.prefix6,
- sizeof (struct in6_addr));
+ IPV6_ADDR_COPY (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.prefix);
#ifdef DEBUG
{
@@ -319,6 +348,17 @@ rtadv_send_packet (int sock, struct interface *ifp)
}
#endif /* HAVE_STRUCT_SOCKADDR_DL */
+ /* MTU */
+ if (zif->rtadv.AdvLinkMTU)
+ {
+ struct nd_opt_mtu * opt = (struct nd_opt_mtu *) (buf + len);
+ opt->nd_opt_mtu_type = ND_OPT_MTU;
+ opt->nd_opt_mtu_len = 1;
+ opt->nd_opt_mtu_reserved = 0;
+ opt->nd_opt_mtu_mtu = htonl (zif->rtadv.AdvLinkMTU);
+ len += sizeof (struct nd_opt_mtu);
+ }
+
msg.msg_name = (void *) &addr;
msg.msg_namelen = sizeof (struct sockaddr_in6);
msg.msg_iov = &iov;
@@ -368,7 +408,7 @@ rtadv_timer (struct thread *thread)
for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
{
- if (if_is_loopback (ifp))
+ if (if_is_loopback (ifp) || ! if_is_operative (ifp))
continue;
zif = ifp->info;
@@ -378,6 +418,8 @@ rtadv_timer (struct thread *thread)
zif->rtadv.AdvIntervalTimer -= period;
if (zif->rtadv.AdvIntervalTimer <= 0)
{
+ /* FIXME: using MaxRtrAdvInterval each time isn't what section
+ 6.2.4 of RFC4861 tells to do. */
zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
rtadv_send_packet (rtadv->sock, ifp);
}
@@ -552,19 +594,19 @@ rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
}
static struct rtadv_prefix *
-rtadv_prefix_lookup (struct list *rplist, struct prefix *p)
+rtadv_prefix_lookup (struct list *rplist, struct prefix_ipv6 *p)
{
struct listnode *node;
struct rtadv_prefix *rprefix;
for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))
- if (prefix_same (&rprefix->prefix, p))
+ if (prefix_same ((struct prefix *) &rprefix->prefix, (struct prefix *) p))
return rprefix;
return NULL;
}
static struct rtadv_prefix *
-rtadv_prefix_get (struct list *rplist, struct prefix *p)
+rtadv_prefix_get (struct list *rplist, struct prefix_ipv6 *p)
{
struct rtadv_prefix *rprefix;
@@ -573,7 +615,7 @@ rtadv_prefix_get (struct list *rplist, struct prefix *p)
return rprefix;
rprefix = rtadv_prefix_new ();
- memcpy (&rprefix->prefix, p, sizeof (struct prefix));
+ memcpy (&rprefix->prefix, p, sizeof (struct prefix_ipv6));
listnode_add (rplist, rprefix);
return rprefix;
@@ -681,26 +723,22 @@ DEFUN (no_ipv6_nd_suppress_ra,
DEFUN (ipv6_nd_ra_interval_msec,
ipv6_nd_ra_interval_msec_cmd,
- "ipv6 nd ra-interval msec MILLISECONDS",
+ "ipv6 nd ra-interval msec <70-1800000>",
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
"Router Advertisement interval\n"
"Router Advertisement interval in milliseconds\n")
{
- int interval;
- struct interface *ifp;
- struct zebra_if *zif;
-
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
+ unsigned interval;
+ struct interface *ifp = (struct interface *) vty->index;
+ struct zebra_if *zif = ifp->info;
- interval = atoi (argv[0]);
-
- if (interval <= 0)
- {
- vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
+ VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 70, 1800000);
+ if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000))
+ {
+ vty_out (vty, "This ra-interval would conflict with configured ra-lifetime!%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
if (zif->rtadv.MaxRtrAdvInterval % 1000)
rtadv->adv_msec_if_count--;
@@ -717,26 +755,22 @@ DEFUN (ipv6_nd_ra_interval_msec,
DEFUN (ipv6_nd_ra_interval,
ipv6_nd_ra_interval_cmd,
- "ipv6 nd ra-interval SECONDS",
+ "ipv6 nd ra-interval <1-1800>",
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
"Router Advertisement interval\n"
"Router Advertisement interval in seconds\n")
{
- int interval;
- struct interface *ifp;
- struct zebra_if *zif;
-
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
+ unsigned interval;
+ struct interface *ifp = (struct interface *) vty->index;
+ struct zebra_if *zif = ifp->info;
- interval = atoi (argv[0]);
-
- if (interval <= 0)
- {
- vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
+ VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 1, 1800);
+ if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime))
+ {
+ vty_out (vty, "This ra-interval would conflict with configured ra-lifetime!%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
if (zif->rtadv.MaxRtrAdvInterval % 1000)
rtadv->adv_msec_if_count--;
@@ -775,13 +809,30 @@ DEFUN (no_ipv6_nd_ra_interval,
return CMD_SUCCESS;
}
+ALIAS (no_ipv6_nd_ra_interval,
+ no_ipv6_nd_ra_interval_val_cmd,
+ "no ipv6 nd ra-interval <1-1800>",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Router Advertisement interval\n")
+
+ALIAS (no_ipv6_nd_ra_interval,
+ no_ipv6_nd_ra_interval_msec_val_cmd,
+ "no ipv6 nd ra-interval msec <1-1800000>",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Router Advertisement interval\n"
+ "Router Advertisement interval in milliseconds\n")
+
DEFUN (ipv6_nd_ra_lifetime,
ipv6_nd_ra_lifetime_cmd,
- "ipv6 nd ra-lifetime SECONDS",
+ "ipv6 nd ra-lifetime <0-9000>",
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
"Router lifetime\n"
- "Router lifetime in seconds\n")
+ "Router lifetime in seconds (0 stands for a non-default gw)\n")
{
int lifetime;
struct interface *ifp;
@@ -790,11 +841,15 @@ DEFUN (ipv6_nd_ra_lifetime,
ifp = (struct interface *) vty->index;
zif = ifp->info;
- lifetime = atoi (argv[0]);
+ VTY_GET_INTEGER_RANGE ("router lifetime", lifetime, argv[0], 0, 9000);
- if (lifetime < 0 || lifetime > 0xffff)
+ /* The value to be placed in the Router Lifetime field
+ * of Router Advertisements sent from the interface,
+ * in seconds. MUST be either zero or between
+ * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
+ if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval))
{
- vty_out (vty, "Invalid Router Lifetime%s", VTY_NEWLINE);
+ vty_out (vty, "This ra-lifetime would conflict with configured ra-interval%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -817,36 +872,31 @@ DEFUN (no_ipv6_nd_ra_lifetime,
ifp = (struct interface *) vty->index;
zif = ifp->info;
- zif->rtadv.AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
+ zif->rtadv.AdvDefaultLifetime = -1;
return CMD_SUCCESS;
}
+ALIAS (no_ipv6_nd_ra_lifetime,
+ no_ipv6_nd_ra_lifetime_val_cmd,
+ "no ipv6 nd ra-lifetime <0-9000>",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Router lifetime\n"
+ "Router lifetime in seconds (0 stands for a non-default gw)\n")
+
DEFUN (ipv6_nd_reachable_time,
ipv6_nd_reachable_time_cmd,
- "ipv6 nd reachable-time MILLISECONDS",
+ "ipv6 nd reachable-time <1-3600000>",
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
"Reachable time\n"
"Reachable time in milliseconds\n")
{
- u_int32_t rtime;
- struct interface *ifp;
- struct zebra_if *zif;
-
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
-
- rtime = (u_int32_t) atol (argv[0]);
-
- if (rtime > RTADV_MAX_REACHABLE_TIME)
- {
- vty_out (vty, "Invalid Reachable time%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- zif->rtadv.AdvReachableTime = rtime;
-
+ struct interface *ifp = (struct interface *) vty->index;
+ struct zebra_if *zif = ifp->info;
+ VTY_GET_INTEGER_RANGE ("reachable time", zif->rtadv.AdvReachableTime, argv[0], 1, RTADV_MAX_REACHABLE_TIME);
return CMD_SUCCESS;
}
@@ -869,31 +919,26 @@ DEFUN (no_ipv6_nd_reachable_time,
return CMD_SUCCESS;
}
+ALIAS (no_ipv6_nd_reachable_time,
+ no_ipv6_nd_reachable_time_val_cmd,
+ "no ipv6 nd reachable-time <1-3600000>",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Reachable time\n"
+ "Reachable time in milliseconds\n")
+
DEFUN (ipv6_nd_homeagent_preference,
ipv6_nd_homeagent_preference_cmd,
- "ipv6 nd home-agent-preference PREFERENCE",
+ "ipv6 nd home-agent-preference <0-65535>",
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
"Home Agent preference\n"
- "Home Agent preference value 0..65535\n")
+ "preference value (default is 0, least preferred)\n")
{
- u_int32_t hapref;
- struct interface *ifp;
- struct zebra_if *zif;
-
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
-
- hapref = (u_int32_t) atol (argv[0]);
-
- if (hapref > 65535)
- {
- vty_out (vty, "Invalid Home Agent preference%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- zif->rtadv.HomeAgentPreference = hapref;
-
+ struct interface *ifp = (struct interface *) vty->index;
+ struct zebra_if *zif = ifp->info;
+ VTY_GET_INTEGER_RANGE ("home agent preference", zif->rtadv.HomeAgentPreference, argv[0], 0, 65535);
return CMD_SUCCESS;
}
@@ -916,31 +961,26 @@ DEFUN (no_ipv6_nd_homeagent_preference,
return CMD_SUCCESS;
}
+ALIAS (no_ipv6_nd_homeagent_preference,
+ no_ipv6_nd_homeagent_preference_val_cmd,
+ "no ipv6 nd home-agent-preference <0-65535>",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Home Agent preference\n"
+ "preference value (default is 0, least preferred)\n")
+
DEFUN (ipv6_nd_homeagent_lifetime,
ipv6_nd_homeagent_lifetime_cmd,
- "ipv6 nd home-agent-lifetime SECONDS",
+ "ipv6 nd home-agent-lifetime <0-65520>",
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
"Home Agent lifetime\n"
- "Home Agent lifetime in seconds\n")
+ "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
{
- u_int32_t ha_ltime;
- struct interface *ifp;
- struct zebra_if *zif;
-
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
-
- ha_ltime = (u_int32_t) atol (argv[0]);
-
- if (ha_ltime > RTADV_MAX_HALIFETIME)
- {
- vty_out (vty, "Invalid Home Agent Lifetime time%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- zif->rtadv.HomeAgentLifetime = ha_ltime;
-
+ struct interface *ifp = (struct interface *) vty->index;
+ struct zebra_if *zif = ifp->info;
+ VTY_GET_INTEGER_RANGE ("home agent lifetime", zif->rtadv.HomeAgentLifetime, argv[0], 0, RTADV_MAX_HALIFETIME);
return CMD_SUCCESS;
}
@@ -958,11 +998,20 @@ DEFUN (no_ipv6_nd_homeagent_lifetime,
ifp = (struct interface *) vty->index;
zif = ifp->info;
- zif->rtadv.HomeAgentLifetime = 0;
+ zif->rtadv.HomeAgentLifetime = -1;
return CMD_SUCCESS;
}
+ALIAS (no_ipv6_nd_homeagent_lifetime,
+ no_ipv6_nd_homeagent_lifetime_val_cmd,
+ "no ipv6 nd home-agent-lifetime <0-65520>",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Home Agent lifetime\n"
+ "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
+
DEFUN (ipv6_nd_managed_config_flag,
ipv6_nd_managed_config_flag_cmd,
"ipv6 nd managed-config-flag",
@@ -1137,12 +1186,13 @@ DEFUN (ipv6_nd_prefix,
ifp = (struct interface *) vty->index;
zebra_if = ifp->info;
- ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
+ ret = str2prefix_ipv6 (argv[0], &rp.prefix);
if (!ret)
{
vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
return CMD_WARNING;
}
+ apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */
rp.AdvOnLinkFlag = 1;
rp.AdvAutonomousFlag = 1;
rp.AdvRouterAddressFlag = 0;
@@ -1364,12 +1414,13 @@ DEFUN (no_ipv6_nd_prefix,
ifp = (struct interface *) vty->index;
zebra_if = ifp->info;
- ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
+ ret = str2prefix_ipv6 (argv[0], &rp.prefix);
if (!ret)
{
vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
return CMD_WARNING;
}
+ apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */
ret = rtadv_prefix_reset (zebra_if, &rp);
if (!ret)
@@ -1430,6 +1481,54 @@ DEFUN (no_ipv6_nd_router_preference,
return CMD_SUCCESS;
}
+ALIAS (no_ipv6_nd_router_preference,
+ no_ipv6_nd_router_preference_val_cmd,
+ "no ipv6 nd router-preference (high|medium|low",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Default router preference\n"
+ "High default router preference\n"
+ "Low default router preference\n"
+ "Medium default router preference (default)\n")
+
+DEFUN (ipv6_nd_mtu,
+ ipv6_nd_mtu_cmd,
+ "ipv6 nd mtu <1-65535>",
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Advertised MTU\n"
+ "MTU in bytes\n")
+{
+ struct interface *ifp = (struct interface *) vty->index;
+ struct zebra_if *zif = ifp->info;
+ VTY_GET_INTEGER_RANGE ("MTU", zif->rtadv.AdvLinkMTU, argv[0], 1, 65535);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_ipv6_nd_mtu,
+ no_ipv6_nd_mtu_cmd,
+ "no ipv6 nd mtu",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Advertised MTU\n")
+{
+ struct interface *ifp = (struct interface *) vty->index;
+ struct zebra_if *zif = ifp->info;
+ zif->rtadv.AdvLinkMTU = 0;
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_ipv6_nd_mtu,
+ no_ipv6_nd_mtu_val_cmd,
+ "no ipv6 nd mtu <1-65535>",
+ NO_STR
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Advertised MTU\n"
+ "MTU in bytes\n")
+
/* Write configuration about router advertisement. */
void
rtadv_config_write (struct vty *vty, struct interface *ifp)
@@ -1463,10 +1562,24 @@ rtadv_config_write (struct vty *vty, struct interface *ifp)
vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,
VTY_NEWLINE);
- if (zif->rtadv.AdvDefaultLifetime != RTADV_ADV_DEFAULT_LIFETIME)
+ if (zif->rtadv.AdvIntervalOption)
+ vty_out (vty, " ipv6 nd adv-interval-option%s", VTY_NEWLINE);
+
+ if (zif->rtadv.AdvDefaultLifetime != -1)
vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
VTY_NEWLINE);
+ if (zif->rtadv.HomeAgentPreference)
+ vty_out (vty, " ipv6 nd home-agent-preference %u%s",
+ zif->rtadv.HomeAgentPreference, VTY_NEWLINE);
+
+ if (zif->rtadv.HomeAgentLifetime != -1)
+ vty_out (vty, " ipv6 nd home-agent-lifetime %u%s",
+ zif->rtadv.HomeAgentLifetime, VTY_NEWLINE);
+
+ if (zif->rtadv.AdvHomeAgentFlag)
+ vty_out (vty, " ipv6 nd home-agent-config-flag%s", VTY_NEWLINE);
+
if (zif->rtadv.AdvReachableTime)
vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
VTY_NEWLINE);
@@ -1482,10 +1595,13 @@ rtadv_config_write (struct vty *vty, struct interface *ifp)
rtadv_pref_strs[zif->rtadv.DefaultPreference],
VTY_NEWLINE);
+ if (zif->rtadv.AdvLinkMTU)
+ vty_out (vty, " ipv6 nd mtu %d%s", zif->rtadv.AdvLinkMTU, VTY_NEWLINE);
+
for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
{
vty_out (vty, " ipv6 nd prefix %s/%d",
- inet_ntop (AF_INET6, &rprefix->prefix.u.prefix6,
+ inet_ntop (AF_INET6, &rprefix->prefix.prefix,
(char *) buf, INET6_ADDRSTRLEN),
rprefix->prefix.prefixlen);
if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||
@@ -1572,10 +1688,14 @@ rtadv_init (void)
install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
+ install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_val_cmd);
+ install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_msec_val_cmd);
install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
+ install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_val_cmd);
install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
+ install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_val_cmd);
install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
@@ -1584,8 +1704,10 @@ rtadv_init (void)
install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
+ install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_val_cmd);
install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
+ install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_val_cmd);
install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);
install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
@@ -1605,6 +1727,10 @@ rtadv_init (void)
install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
+ install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_val_cmd);
+ install_element (INTERFACE_NODE, &ipv6_nd_mtu_cmd);
+ install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_cmd);
+ install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_val_cmd);
}
static int
diff --git a/zebra/rtadv.h b/zebra/rtadv.h
index d8d263d0..564a4c66 100644
--- a/zebra/rtadv.h
+++ b/zebra/rtadv.h
@@ -30,7 +30,7 @@
struct rtadv_prefix
{
/* Prefix to be advertised. */
- struct prefix prefix;
+ struct prefix_ipv6 prefix;
/* The value to be placed in the Valid Lifetime in the Prefix */
u_int32_t AdvValidLifetime;
@@ -47,7 +47,7 @@ struct rtadv_prefix
/* The value to be placed in the Autonomous Flag. */
int AdvAutonomousFlag;
- /* The value to be placed in the Router Address Flag (RFC3775 7.2). */
+ /* The value to be placed in the Router Address Flag [RFC6275 7.2]. */
int AdvRouterAddressFlag;
#ifndef ND_OPT_PI_FLAG_RADDR
#define ND_OPT_PI_FLAG_RADDR 0x20
@@ -58,7 +58,7 @@ struct rtadv_prefix
extern void rtadv_config_write (struct vty *, struct interface *);
extern void rtadv_init (void);
-/* draft-ietf-mip6-mipext-advapi-03 */
+/* RFC4584 Extension to Sockets API for Mobile IPv6 */
#ifndef ND_OPT_ADV_INTERVAL
#define ND_OPT_ADV_INTERVAL 7 /* Adv Interval Option */
diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c
index 3e065c6f..81bf0de6 100644
--- a/zebra/rtread_getmsg.c
+++ b/zebra/rtread_getmsg.c
@@ -90,7 +90,7 @@ handle_route_entry (mib2_ipRouteEntry_t *routeEntry)
gateway.s_addr = routeEntry->ipRouteNextHop;
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &prefix,
- &gateway, NULL, 0, 0, 0, 0);
+ &gateway, NULL, 0, 0, 0, 0, SAFI_UNICAST);
}
void
diff --git a/zebra/rtread_netlink.c b/zebra/rtread_netlink.c
index 44715d94..066e8443 100644
--- a/zebra/rtread_netlink.c
+++ b/zebra/rtread_netlink.c
@@ -21,6 +21,9 @@
*/
#include <zebra.h>
+
+#include "zebra/zserv.h"
+
extern void netlink_route_read (void);
void route_read (void)
diff --git a/zebra/rtread_proc.c b/zebra/rtread_proc.c
index 1de435a4..07e8491a 100644
--- a/zebra/rtread_proc.c
+++ b/zebra/rtread_proc.c
@@ -96,7 +96,7 @@ proc_route_read (void)
p.prefixlen = ip_masklen (tmpmask);
sscanf (gate, "%lX", (unsigned long *)&gateway);
- rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gateway, NULL, 0, 0, 0, 0);
+ rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gateway, NULL, 0, 0, 0, 0, SAFI_UNICAST);
}
fclose (fp);
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 12f3fa5a..f7f4d0a2 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -55,18 +55,20 @@ static const struct
{
int key;
int distance;
-} route_info[] =
-{
- {ZEBRA_ROUTE_SYSTEM, 0},
- {ZEBRA_ROUTE_KERNEL, 0},
- {ZEBRA_ROUTE_CONNECT, 0},
- {ZEBRA_ROUTE_STATIC, 1},
- {ZEBRA_ROUTE_RIP, 120},
- {ZEBRA_ROUTE_RIPNG, 120},
- {ZEBRA_ROUTE_OSPF, 110},
- {ZEBRA_ROUTE_OSPF6, 110},
- {ZEBRA_ROUTE_ISIS, 115},
- {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */}
+} route_info[ZEBRA_ROUTE_MAX] =
+{
+ [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0},
+ [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0},
+ [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0},
+ [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1},
+ [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120},
+ [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120},
+ [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110},
+ [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110},
+ [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115},
+ [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */},
+ [ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 95},
+ /* no entry/default: 150 */
};
/* Vector for routing table. */
@@ -89,6 +91,11 @@ vrf_alloc (const char *name)
vrf->table[AFI_IP6][SAFI_UNICAST] = route_table_init ();
vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
+ vrf->table[AFI_IP][SAFI_MULTICAST] = route_table_init ();
+ vrf->table[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
+ vrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
+ vrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
+
return vrf;
}
@@ -1229,6 +1236,7 @@ static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
[ZEBRA_ROUTE_ISIS] = 2,
[ZEBRA_ROUTE_BGP] = 3,
[ZEBRA_ROUTE_HSLS] = 4,
+ [ZEBRA_ROUTE_BABEL] = 2,
};
/* Look into the RN and queue it into one or more priority queues,
@@ -1492,7 +1500,7 @@ int
rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
struct in_addr *gate, struct in_addr *src,
unsigned int ifindex, u_int32_t vrf_id,
- u_int32_t metric, u_char distance)
+ u_int32_t metric, u_char distance, safi_t safi)
{
struct rib *rib;
struct rib *same = NULL;
@@ -1501,7 +1509,7 @@ rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
struct nexthop *nexthop;
/* Lookup table. */
- table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
+ table = vrf_table (AFI_IP, safi, 0);
if (! table)
return 0;
@@ -1511,7 +1519,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))
@@ -1747,7 +1758,7 @@ void rib_lookup_and_pushup (struct prefix_ipv4 * p)
}
int
-rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
+rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
{
struct route_table *table;
struct route_node *rn;
@@ -1755,9 +1766,10 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
struct nexthop *nexthop;
/* Lookup table. */
- table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
+ table = vrf_table (AFI_IP, safi, 0);
if (! table)
return 0;
+
/* Make it sure prefixlen is applied to the prefix. */
apply_mask_ipv4 (p);
@@ -1820,7 +1832,7 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
/* XXX factor with rib_delete_ipv6 */
int
rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
- struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
+ struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
{
struct route_table *table;
struct route_node *rn;
@@ -1832,7 +1844,7 @@ rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
char buf2[INET_ADDRSTRLEN];
/* Lookup table. */
- table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
+ table = vrf_table (AFI_IP, safi, 0);
if (! table)
return 0;
@@ -1879,8 +1891,10 @@ 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)
+ nexthop->type == NEXTHOP_TYPE_IFINDEX)
{
+ if (nexthop->ifindex != ifindex)
+ continue;
if (rib->refcnt)
{
rib->refcnt--;
@@ -2281,7 +2295,7 @@ rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
int
rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
- u_int32_t metric, u_char distance)
+ u_int32_t metric, u_char distance, safi_t safi)
{
struct rib *rib;
struct rib *same = NULL;
@@ -2290,7 +2304,7 @@ rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
struct nexthop *nexthop;
/* Lookup table. */
- table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
+ table = vrf_table (AFI_IP6, safi, 0);
if (! table)
return 0;
@@ -2375,7 +2389,7 @@ rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
/* XXX factor with rib_delete_ipv6 */
int
rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
- struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
+ struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)
{
struct route_table *table;
struct route_node *rn;
@@ -2390,7 +2404,7 @@ rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
apply_mask_ipv6 (p);
/* Lookup table. */
- table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
+ table = vrf_table (AFI_IP6, safi, 0);
if (! table)
return 0;
@@ -2427,8 +2441,10 @@ 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)
+ nexthop->type == NEXTHOP_TYPE_IFINDEX)
{
+ if (nexthop->ifindex != ifindex)
+ continue;
if (rib->refcnt)
{
rib->refcnt--;
@@ -2877,7 +2893,41 @@ rib_sweep_route (void)
rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
}
-
+
+/* Remove specific by protocol routes from 'table'. */
+static unsigned long
+rib_score_proto_table (u_char proto, struct route_table *table)
+{
+ struct route_node *rn;
+ struct rib *rib;
+ struct rib *next;
+ unsigned long n = 0;
+
+ if (table)
+ for (rn = route_top (table); rn; rn = route_next (rn))
+ for (rib = rn->info; rib; rib = next)
+ {
+ next = rib->next;
+ if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
+ continue;
+ if (rib->type == proto)
+ {
+ rib_delnode (rn, rib);
+ n++;
+ }
+ }
+
+ return n;
+}
+
+/* Remove specific by protocol routes. */
+unsigned long
+rib_score_proto (u_char proto)
+{
+ return rib_score_proto_table (proto, vrf_table (AFI_IP, SAFI_UNICAST, 0))
+ +rib_score_proto_table (proto, vrf_table (AFI_IP6, SAFI_UNICAST, 0));
+}
+
/* Close RIB and clean up kernel routes. */
static void
rib_close_table (struct route_table *table)
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index ecb5d10a..dafcf75a 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -556,6 +556,7 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn)
#define ONE_WEEK_SECOND 60*60*24*7
if (rib->type == ZEBRA_ROUTE_RIP
|| rib->type == ZEBRA_ROUTE_OSPF
+ || rib->type == ZEBRA_ROUTE_BABEL
|| rib->type == ZEBRA_ROUTE_ISIS
|| rib->type == ZEBRA_ROUTE_BGP)
{
@@ -774,6 +775,7 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
if (rib->type == ZEBRA_ROUTE_RIP
|| rib->type == ZEBRA_ROUTE_OSPF
+ || rib->type == ZEBRA_ROUTE_BABEL
|| rib->type == ZEBRA_ROUTE_ISIS
|| rib->type == ZEBRA_ROUTE_BGP)
{
@@ -802,10 +804,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 +826,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 +868,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 +906,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 +917,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 +929,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 +947,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);
@@ -1559,6 +1534,7 @@ vty_show_ipv6_route_detail (struct vty *vty, struct route_node *rn)
#define ONE_WEEK_SECOND 60*60*24*7
if (rib->type == ZEBRA_ROUTE_RIPNG
|| rib->type == ZEBRA_ROUTE_OSPF6
+ || rib->type == ZEBRA_ROUTE_BABEL
|| rib->type == ZEBRA_ROUTE_ISIS
|| rib->type == ZEBRA_ROUTE_BGP)
{
@@ -1738,6 +1714,7 @@ vty_show_ipv6_route (struct vty *vty, struct route_node *rn,
if (rib->type == ZEBRA_ROUTE_RIPNG
|| rib->type == ZEBRA_ROUTE_OSPF6
+ || rib->type == ZEBRA_ROUTE_BABEL
|| rib->type == ZEBRA_ROUTE_ISIS
|| rib->type == ZEBRA_ROUTE_BGP)
{
@@ -1766,8 +1743,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 +1765,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 +1807,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 +1817,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 +1829,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 +1847,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);
@@ -1995,6 +1951,80 @@ DEFUN (show_ipv6_route_summary,
return CMD_SUCCESS;
}
+/*
+ * Show IP mroute command to dump the BGP Multicast
+ * routing table
+ */
+DEFUN (show_ip_mroute,
+ show_ip_mroute_cmd,
+ "show ip mroute",
+ SHOW_STR
+ IP_STR
+ "IP Multicast routing table\n")
+{
+ struct route_table *table;
+ struct route_node *rn;
+ struct rib *rib;
+ int first = 1;
+
+ table = vrf_table (AFI_IP, SAFI_MULTICAST, 0);
+ if (! table)
+ return CMD_SUCCESS;
+
+ /* Show all IPv4 routes. */
+ for (rn = route_top (table); rn; rn = route_next (rn))
+ for (rib = rn->info; rib; rib = rib->next)
+ {
+ if (first)
+ {
+ vty_out (vty, SHOW_ROUTE_V4_HEADER);
+ first = 0;
+ }
+ vty_show_ip_route (vty, rn, rib);
+ }
+ return CMD_SUCCESS;
+}
+
+/*
+ * Show IPv6 mroute command.Used to dump
+ * the Multicast routing table.
+ */
+
+DEFUN (show_ipv6_mroute,
+ show_ipv6_mroute_cmd,
+ "show ipv6 mroute",
+ SHOW_STR
+ IP_STR
+ "IPv6 Multicast routing table\n")
+{
+ struct route_table *table;
+ struct route_node *rn;
+ struct rib *rib;
+ int first = 1;
+
+ table = vrf_table (AFI_IP6, SAFI_MULTICAST, 0);
+ if (! table)
+ return CMD_SUCCESS;
+
+ /* Show all IPv6 route. */
+ for (rn = route_top (table); rn; rn = route_next (rn))
+ for (rib = rn->info; rib; rib = rib->next)
+ {
+ if (first)
+ {
+ vty_out (vty, SHOW_ROUTE_V6_HEADER);
+ first = 0;
+ }
+ vty_show_ipv6_route (vty, rn, rib);
+ }
+ return CMD_SUCCESS;
+}
+
+
+
+
+
+
/* Write IPv6 static route configuration. */
static int
static_config_ipv6 (struct vty *vty)
@@ -2137,6 +2167,10 @@ zebra_vty_init (void)
install_element (ENABLE_NODE, &show_ip_route_supernets_cmd);
install_element (ENABLE_NODE, &show_ip_route_summary_cmd);
+ install_element (VIEW_NODE, &show_ip_mroute_cmd);
+ install_element (ENABLE_NODE, &show_ip_mroute_cmd);
+
+
#ifdef HAVE_IPV6
install_element (CONFIG_NODE, &ipv6_route_cmd);
install_element (CONFIG_NODE, &ipv6_route_flags_cmd);
@@ -2166,5 +2200,8 @@ zebra_vty_init (void)
install_element (ENABLE_NODE, &show_ipv6_route_prefix_cmd);
install_element (ENABLE_NODE, &show_ipv6_route_prefix_longer_cmd);
install_element (ENABLE_NODE, &show_ipv6_route_summary_cmd);
+
+ install_element (VIEW_NODE, &show_ipv6_mroute_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_mroute_cmd);
#endif /* HAVE_IPV6 */
}
diff --git a/zebra/zserv.c b/zebra/zserv.c
index dc3d432b..672dee88 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -64,6 +64,15 @@ zserv_delayed_close(struct thread *thread)
return 0;
}
+/* When client connects, it sends hello message
+ * with promise to send zebra routes of specific type.
+ * Zebra stores a socket fd of the client into
+ * this array. And use it to clean up routes that
+ * client didn't remove for some reasons after closing
+ * connection.
+ */
+static int route_type_oaths[ZEBRA_ROUTE_MAX];
+
static int
zserv_flush_data(struct thread *thread)
{
@@ -741,6 +750,8 @@ zread_ipv4_add (struct zserv *client, u_short length)
struct stream *s;
unsigned int ifindex;
u_char ifname_len;
+ safi_t safi;
+
/* Get input stream. */
s = client->ibuf;
@@ -752,6 +763,7 @@ zread_ipv4_add (struct zserv *client, u_short length)
rib->type = stream_getc (s);
rib->flags = stream_getc (s);
message = stream_getc (s);
+ safi = stream_getw (s);
rib->uptime = time (NULL);
/* IPv4 prefix. */
@@ -803,7 +815,7 @@ zread_ipv4_add (struct zserv *client, u_short length)
/* Table */
rib->table=zebrad.rtm_table_default;
- rib_add_ipv4_multipath (&p, rib);
+ rib_add_ipv4_multipath (&p, rib, safi);
return 0;
}
@@ -829,6 +841,7 @@ zread_ipv4_delete (struct zserv *client, u_short length)
api.type = stream_getc (s);
api.flags = stream_getc (s);
api.message = stream_getc (s);
+ api.safi = stream_getw (s);
/* IPv4 prefix. */
memset (&p, 0, sizeof (struct prefix_ipv4));
@@ -877,7 +890,7 @@ zread_ipv4_delete (struct zserv *client, u_short length)
api.metric = 0;
rib_delete_ipv4 (api.type, api.flags, &p, &nexthop, ifindex,
- client->rtm_table);
+ client->rtm_table, api.safi);
return 0;
}
@@ -924,6 +937,7 @@ zread_ipv6_add (struct zserv *client, u_short length)
api.type = stream_getc (s);
api.flags = stream_getc (s);
api.message = stream_getc (s);
+ api.safi = stream_getw (s);
/* IPv4 prefix. */
memset (&p, 0, sizeof (struct prefix_ipv6));
@@ -965,10 +979,10 @@ zread_ipv6_add (struct zserv *client, u_short length)
if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
rib_add_ipv6 (api.type, api.flags, &p, NULL, ifindex, zebrad.rtm_table_default, api.metric,
- api.distance);
+ api.distance, api.safi);
else
rib_add_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, zebrad.rtm_table_default, api.metric,
- api.distance);
+ api.distance, api.safi);
return 0;
}
@@ -991,6 +1005,7 @@ zread_ipv6_delete (struct zserv *client, u_short length)
api.type = stream_getc (s);
api.flags = stream_getc (s);
api.message = stream_getc (s);
+ api.safi = stream_getw (s);
/* IPv4 prefix. */
memset (&p, 0, sizeof (struct prefix_ipv6));
@@ -1030,9 +1045,9 @@ zread_ipv6_delete (struct zserv *client, u_short length)
api.metric = 0;
if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
- rib_delete_ipv6 (api.type, api.flags, &p, NULL, ifindex, client->rtm_table);
+ rib_delete_ipv6 (api.type, api.flags, &p, NULL, ifindex, client->rtm_table, api.safi);
else
- rib_delete_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, client->rtm_table);
+ rib_delete_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, client->rtm_table, api.safi);
return 0;
}
@@ -1071,6 +1086,49 @@ zread_router_id_delete (struct zserv *client, u_short length)
return 0;
}
+/* Tie up route-type and client->sock */
+static void
+zread_hello (struct zserv *client)
+{
+ /* type of protocol (lib/zebra.h) */
+ u_char proto;
+ proto = stream_getc (client->ibuf);
+
+ /* accept only dynamic routing protocols */
+ if ((proto < ZEBRA_ROUTE_MAX)
+ && (proto > ZEBRA_ROUTE_STATIC))
+ {
+ zlog_notice ("client %d says hello and bids fair to announce only %s routes",
+ client->sock, zebra_route_string(proto));
+
+ /* if route-type was binded by other client */
+ if (route_type_oaths[proto])
+ zlog_warn ("sender of %s routes changed %c->%c",
+ zebra_route_string(proto), route_type_oaths[proto],
+ client->sock);
+
+ route_type_oaths[proto] = client->sock;
+ }
+}
+
+/* If client sent routes of specific type, zebra removes it
+ * and returns number of deleted routes.
+ */
+static void
+zebra_score_rib (int client_sock)
+{
+ int i;
+
+ for (i = ZEBRA_ROUTE_RIP; i < ZEBRA_ROUTE_MAX; i++)
+ if (client_sock == route_type_oaths[i])
+ {
+ zlog_notice ("client %d disconnected. %lu %s routes removed from the rib",
+ client_sock, rib_score_proto (i), zebra_route_string (i));
+ route_type_oaths[i] = 0;
+ break;
+ }
+}
+
/* Close zebra client. */
static void
zebra_client_close (struct zserv *client)
@@ -1079,6 +1137,7 @@ zebra_client_close (struct zserv *client)
if (client->sock)
{
close (client->sock);
+ zebra_score_rib (client->sock);
client->sock = -1;
}
@@ -1283,6 +1342,9 @@ zebra_client_read (struct thread *thread)
case ZEBRA_IPV4_IMPORT_LOOKUP:
zread_ipv4_import_lookup (client, length);
break;
+ case ZEBRA_HELLO:
+ zread_hello (client);
+ break;
default:
zlog_info ("Zebra received unknown command %d", command);
break;
@@ -1352,6 +1414,7 @@ zebra_serv ()
return;
}
+ memset (&route_type_oaths, 0, sizeof (route_type_oaths));
memset (&addr, 0, sizeof (struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons (ZEBRA_PORT);
@@ -1422,6 +1485,8 @@ zebra_serv_un (const char *path)
return;
}
+ memset (&route_type_oaths, 0, sizeof (route_type_oaths));
+
/* Make server socket. */
memset (&serv, 0, sizeof (struct sockaddr_un));
serv.sun_family = AF_UNIX;
@@ -1733,11 +1798,11 @@ zebra_init (void)
/* Make zebra server socket, wiping any existing one (see bug #403). */
void
-zebra_zserv_socket_init (void)
+zebra_zserv_socket_init (char *path)
{
#ifdef HAVE_TCP_ZEBRA
zebra_serv ();
#else
- zebra_serv_un (ZEBRA_SERV_PATH);
+ zebra_serv_un (path ? path : ZEBRA_SERV_PATH);
#endif /* HAVE_TCP_ZEBRA */
}
diff --git a/zebra/zserv.h b/zebra/zserv.h
index a7371830..5e8bccac 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -89,7 +89,7 @@ struct zebra_t
/* Prototypes. */
extern void zebra_init (void);
extern void zebra_if_init (void);
-extern void zebra_zserv_socket_init (void);
+extern void zebra_zserv_socket_init (char *path);
extern void hostinfo_get (void);
extern void rib_init (void);
extern void interface_list (void);