diff options
Diffstat (limited to 'zebra')
-rw-r--r-- | zebra/.cvsignore | 13 | ||||
-rw-r--r-- | zebra/client_main.c | 1 | ||||
-rw-r--r-- | zebra/connected.c | 8 | ||||
-rw-r--r-- | zebra/if_netlink.c | 2 | ||||
-rw-r--r-- | zebra/interface.c | 24 | ||||
-rw-r--r-- | zebra/interface.h | 17 | ||||
-rw-r--r-- | zebra/ipforward_proc.c | 9 | ||||
-rw-r--r-- | zebra/irdp_interface.c | 3 | ||||
-rw-r--r-- | zebra/kernel_socket.c | 28 | ||||
-rw-r--r-- | zebra/main.c | 12 | ||||
-rw-r--r-- | zebra/redistribute.c | 46 | ||||
-rw-r--r-- | zebra/rib.h | 11 | ||||
-rw-r--r-- | zebra/rt_netlink.c | 24 | ||||
-rw-r--r-- | zebra/rtadv.c | 338 | ||||
-rw-r--r-- | zebra/rtadv.h | 6 | ||||
-rw-r--r-- | zebra/rtread_getmsg.c | 2 | ||||
-rw-r--r-- | zebra/rtread_netlink.c | 3 | ||||
-rw-r--r-- | zebra/rtread_proc.c | 2 | ||||
-rw-r--r-- | zebra/zebra_rib.c | 102 | ||||
-rw-r--r-- | zebra/zebra_vty.c | 163 | ||||
-rw-r--r-- | zebra/zserv.c | 81 | ||||
-rw-r--r-- | zebra/zserv.h | 2 |
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); |