/* Router advertisement
+ * Copyright (C) 2016 Cumulus Networks
* Copyright (C) 2005 6WIND <jean-mickael.guerin@6wind.com>
* Copyright (C) 1999 Kunihiro Ishiguro
*
#include <zebra.h>
#include "memory.h"
+#include "zebra_memory.h"
#include "sockopt.h"
#include "thread.h"
#include "if.h"
+#include "stream.h"
#include "log.h"
#include "prefix.h"
#include "linklist.h"
#include "command.h"
#include "privs.h"
+#include "vrf.h"
#include "zebra/interface.h"
#include "zebra/rtadv.h"
#include "zebra/debug.h"
#include "zebra/rib.h"
#include "zebra/zserv.h"
+#include "zebra/zebra_ns.h"
+#include "zebra/zebra_vrf.h"
extern struct zebra_privs_t zserv_privs;
-#if defined (HAVE_IPV6) && defined (RTADV)
+#if defined (HAVE_IPV6) && defined (HAVE_RTADV)
#ifdef OPEN_BSD
#include <netinet/icmp6.h>
#define ALLNODE "ff02::1"
#define ALLROUTER "ff02::2"
-extern struct zebra_t zebrad;
-
enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER,
RTADV_TIMER_MSEC, RTADV_READ};
-static void rtadv_event (enum rtadv_event, int);
+static void rtadv_event (struct zebra_ns *, enum rtadv_event, int);
static int if_join_all_router (int, struct interface *);
static int if_leave_all_router (int, struct interface *);
-\f
-/* Structure which hold status of router advertisement. */
-struct rtadv
-{
- int sock;
-
- int adv_if_count;
- int adv_msec_if_count;
- struct thread *ra_read;
- struct thread *ra_timer;
-};
-
-struct rtadv *rtadv = NULL;
-\f
-static struct rtadv *
-rtadv_new (void)
+static int
+rtadv_increment_received(struct zebra_ns *zns, ifindex_t *ifindex)
{
- return XCALLOC (MTYPE_TMP, sizeof (struct rtadv));
+ int ret = -1;
+ struct interface *iface;
+ struct zebra_if *zif;
+
+ iface = if_lookup_by_index_per_ns (zns, *ifindex);
+ if (iface && iface->info)
+ {
+ zif = iface->info;
+ zif->ra_rcvd++;
+ ret = 0;
+ }
+ return ret;
}
static int
-rtadv_recv_packet (int sock, u_char *buf, int buflen,
- struct sockaddr_in6 *from, unsigned int *ifindex,
+rtadv_recv_packet (struct zebra_ns *zns, int sock, u_char *buf, int buflen,
+ struct sockaddr_in6 *from, ifindex_t *ifindex,
int *hoplimit)
{
int ret;
*hoplimit = *hoptr;
}
}
+
+ rtadv_increment_received(zns, ifindex);
return ret;
}
struct cmsghdr *cmsgptr;
struct in6_pktinfo *pkt;
struct sockaddr_in6 addr;
-#ifdef HAVE_STRUCT_SOCKADDR_DL
- struct sockaddr_dl *sdl;
-#endif /* HAVE_STRUCT_SOCKADDR_DL */
static void *adata = NULL;
unsigned char buf[RTADV_MSG_SIZE];
struct nd_router_advert *rtadv;
adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo)));
if (adata == NULL)
- zlog_err("rtadv_send_packet: can't malloc control data\n");
+ zlog_err("rtadv_send_packet: can't malloc control data");
}
/* Logging of packet. */
if (IS_ZEBRA_DEBUG_PACKET)
- zlog_debug ("Router advertisement send to %s", ifp->name);
+ zlog_debug ("%s(%u): Tx RA, socket %u",
+ ifp->name, ifp->ifindex, sock);
/* Fill in sockaddr_in6. */
memset (&addr, 0, sizeof (struct sockaddr_in6));
}
/* Hardware address. */
-#ifdef HAVE_STRUCT_SOCKADDR_DL
- sdl = &ifp->sdl;
- if (sdl != NULL && sdl->sdl_alen != 0)
- {
- buf[len++] = ND_OPT_SOURCE_LINKADDR;
-
- /* Option length should be rounded up to next octet if
- the link address does not end on an octet boundary. */
- buf[len++] = (sdl->sdl_alen + 9) >> 3;
-
- memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen);
- len += sdl->sdl_alen;
-
- /* Pad option to end on an octet boundary. */
- memset (buf + len, 0, -(sdl->sdl_alen + 2) & 0x7);
- len += -(sdl->sdl_alen + 2) & 0x7;
- }
-#else
if (ifp->hw_addr_len != 0)
{
buf[len++] = ND_OPT_SOURCE_LINKADDR;
memset (buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7);
len += -(ifp->hw_addr_len + 2) & 0x7;
}
-#endif /* HAVE_STRUCT_SOCKADDR_DL */
/* MTU */
if (zif->rtadv.AdvLinkMTU)
ret = sendmsg (sock, &msg, 0);
if (ret < 0)
{
- zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
- errno, safe_strerror(errno));
+ zlog_err ("%s(%u): Tx RA failed, socket %u error %d (%s)",
+ ifp->name, ifp->ifindex, sock, errno, safe_strerror(errno));
}
+ else
+ zif->ra_sent++;
}
static int
rtadv_timer (struct thread *thread)
{
+ struct zebra_ns *zns = THREAD_ARG (thread);
+ struct vrf *vrf;
struct listnode *node, *nnode;
struct interface *ifp;
struct zebra_if *zif;
int period;
- rtadv->ra_timer = NULL;
- if (rtadv->adv_msec_if_count == 0)
+ zns->rtadv.ra_timer = NULL;
+ if (zns->rtadv.adv_msec_if_count == 0)
{
period = 1000; /* 1 s */
- rtadv_event (RTADV_TIMER, 1 /* 1 s */);
+ rtadv_event (zns, RTADV_TIMER, 1 /* 1 s */);
}
else
{
period = 10; /* 10 ms */
- rtadv_event (RTADV_TIMER_MSEC, 10 /* 10 ms */);
+ rtadv_event (zns, RTADV_TIMER_MSEC, 10 /* 10 ms */);
}
- for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
- {
- if (if_is_loopback (ifp) || ! if_is_operative (ifp))
- continue;
-
- zif = ifp->info;
+ RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
+ for (ALL_LIST_ELEMENTS (vrf->iflist, node, nnode, ifp))
+ {
+ if (if_is_loopback (ifp) ||
+ CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK) ||
+ ! if_is_operative (ifp))
+ continue;
+
+ zif = ifp->info;
+
+ if (zif->rtadv.AdvSendAdvertisements)
+ {
+ if (zif->rtadv.inFastRexmit)
+ {
+ /* We assume we fast rexmit every sec so no additional vars */
+ if (--zif->rtadv.NumFastReXmitsRemain <= 0)
+ zif->rtadv.inFastRexmit = 0;
+
+ if (IS_ZEBRA_DEBUG_SEND)
+ zlog_debug("Fast RA Rexmit on interface %s", ifp->name);
+
+ rtadv_send_packet (zns->rtadv.sock, ifp);
+ }
+ else
+ {
+ 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 (zns->rtadv.sock, ifp);
+ }
+ }
+ }
+ }
- if (zif->rtadv.AdvSendAdvertisements)
- {
- 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);
- }
- }
- }
return 0;
}
static void
rtadv_process_solicit (struct interface *ifp)
{
- zlog_info ("Router solicitation received on %s", ifp->name);
+ struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
+ struct zebra_ns *zns = zvrf->zns;
- rtadv_send_packet (rtadv->sock, ifp);
+ assert (zns);
+ rtadv_send_packet (zns->rtadv.sock, ifp);
}
static void
-rtadv_process_advert (void)
+rtadv_process_advert (u_char *msg, unsigned int len, struct interface *ifp,
+ struct sockaddr_in6 *addr)
{
- zlog_info ("Router advertisement received");
+ struct nd_router_advert *radvert;
+ char addr_str[INET6_ADDRSTRLEN];
+ struct zebra_if *zif;
+ struct prefix p;
+
+ zif = ifp->info;
+
+ inet_ntop (AF_INET6, &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN);
+
+ if (len < sizeof(struct nd_router_advert)) {
+ zlog_warn("%s(%u): Rx RA with invalid length %d from %s",
+ ifp->name, ifp->ifindex, len, addr_str);
+ return;
+ }
+ if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) {
+ zlog_warn("%s(%u): Rx RA with non-linklocal source address from %s",
+ ifp->name, ifp->ifindex, addr_str);
+ return;
+ }
+
+ radvert = (struct nd_router_advert *) msg;
+
+ if ((radvert->nd_ra_curhoplimit && zif->rtadv.AdvCurHopLimit) &&
+ (radvert->nd_ra_curhoplimit != zif->rtadv.AdvCurHopLimit))
+ {
+ zlog_warn("%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
+ ifp->name, ifp->ifindex, addr_str);
+ }
+
+ if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) &&
+ !zif->rtadv.AdvManagedFlag)
+ {
+ zlog_warn("%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
+ ifp->name, ifp->ifindex, addr_str);
+ }
+
+ if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) &&
+ !zif->rtadv.AdvOtherConfigFlag)
+ {
+ zlog_warn("%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
+ ifp->name, ifp->ifindex, addr_str);
+ }
+
+ if ((radvert->nd_ra_reachable && zif->rtadv.AdvReachableTime) &&
+ (ntohl(radvert->nd_ra_reachable) != zif->rtadv.AdvReachableTime))
+ {
+ zlog_warn("%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
+ ifp->name, ifp->ifindex, addr_str);
+ }
+
+ if ((radvert->nd_ra_retransmit && zif->rtadv.AdvRetransTimer) &&
+ (ntohl(radvert->nd_ra_retransmit) != (unsigned int)zif->rtadv.AdvRetransTimer))
+ {
+ zlog_warn("%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
+ ifp->name, ifp->ifindex, addr_str);
+ }
+
+ /* Create entry for neighbor if not known. */
+ p.family = AF_INET6;
+ IPV6_ADDR_COPY (&p.u.prefix, &addr->sin6_addr);
+ p.prefixlen = IPV6_MAX_PREFIXLEN;
+
+ if (!nbr_connected_check(ifp, &p))
+ nbr_connected_add_ipv6 (ifp, &addr->sin6_addr);
}
+
static void
-rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit)
+rtadv_process_packet (u_char *buf, unsigned int len, ifindex_t ifindex, int hoplimit,
+ struct sockaddr_in6 *from, struct zebra_ns *zns)
{
struct icmp6_hdr *icmph;
struct interface *ifp;
struct zebra_if *zif;
+ char addr_str[INET6_ADDRSTRLEN];
+
+ inet_ntop (AF_INET6, &from->sin6_addr, addr_str, INET6_ADDRSTRLEN);
/* Interface search. */
- ifp = if_lookup_by_index (ifindex);
+ ifp = if_lookup_by_index_per_ns (zns, ifindex);
if (ifp == NULL)
{
- zlog_warn ("Unknown interface index: %d", ifindex);
+ zlog_warn ("RA/RS received on unknown IF %u from %s",
+ ifindex, addr_str);
return;
}
- if (if_is_loopback (ifp))
+ if (IS_ZEBRA_DEBUG_PACKET)
+ zlog_debug ("%s(%u): Rx RA/RS len %d from %s",
+ ifp->name, ifp->ifindex, len, addr_str);
+
+ if (if_is_loopback (ifp) ||
+ CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))
return;
/* Check interface configuration. */
/* ICMP message length check. */
if (len < sizeof (struct icmp6_hdr))
{
- zlog_warn ("Invalid ICMPV6 packet length: %d", len);
+ zlog_warn ("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
+ ifp->name, ifp->ifindex, len);
return;
}
if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
icmph->icmp6_type != ND_ROUTER_ADVERT)
{
- zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type);
+ zlog_warn ("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
+ ifp->name, ifp->ifindex, icmph->icmp6_type);
return;
}
/* Hoplimit check. */
if (hoplimit >= 0 && hoplimit != 255)
{
- zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
- hoplimit);
+ zlog_warn ("%s(%u): Rx RA - Invalid hoplimit %d",
+ ifp->name, ifp->ifindex, hoplimit);
return;
}
if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
rtadv_process_solicit (ifp);
else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
- rtadv_process_advert ();
+ rtadv_process_advert (buf, len, ifp, from);
return;
}
int len;
u_char buf[RTADV_MSG_SIZE];
struct sockaddr_in6 from;
- unsigned int ifindex = 0;
+ ifindex_t ifindex = 0;
int hoplimit = -1;
+ struct zebra_ns *zns = THREAD_ARG (thread);
sock = THREAD_FD (thread);
- rtadv->ra_read = NULL;
+ zns->rtadv.ra_read = NULL;
/* Register myself. */
- rtadv_event (RTADV_READ, sock);
+ rtadv_event (zns, RTADV_READ, sock);
- len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
+ len = rtadv_recv_packet (zns, sock, buf, sizeof (buf), &from, &ifindex, &hoplimit);
if (len < 0)
{
- zlog_warn ("router solicitation recv failed: %s.", safe_strerror (errno));
+ zlog_warn ("RA/RS recv failed, socket %u error %s",
+ sock, safe_strerror (errno));
return len;
}
- rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit);
+ rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit, &from, zns);
return 0;
}
rtadv_make_socket (void)
{
int sock;
- int ret;
+ int ret = 0;
struct icmp6_filter filter;
if ( zserv_privs.change (ZPRIVS_RAISE) )
zlog_err ("rtadv_make_socket: could not lower privs, %s",
safe_strerror (errno) );
- /* When we can't make ICMPV6 socket simply back. Router
- advertisement feature will not be supported. */
if (sock < 0)
- return -1;
+ {
+ close (sock);
+ return -1;
+ }
ret = setsockopt_ipv6_pktinfo (sock, 1);
if (ret < 0)
- return ret;
+ {
+ close (sock);
+ return ret;
+ }
ret = setsockopt_ipv6_multicast_loop (sock, 0);
if (ret < 0)
- return ret;
+ {
+ close (sock);
+ return ret;
+ }
ret = setsockopt_ipv6_unicast_hops (sock, 255);
if (ret < 0)
- return ret;
+ {
+ close (sock);
+ return ret;
+ }
ret = setsockopt_ipv6_multicast_hops (sock, 255);
if (ret < 0)
- return ret;
+ {
+ close (sock);
+ return ret;
+ }
ret = setsockopt_ipv6_hoplimit (sock, 1);
if (ret < 0)
- return ret;
+ {
+ close (sock);
+ return ret;
+ }
ICMP6_FILTER_SETBLOCKALL(&filter);
ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
return sock;
}
-\f
+
static struct rtadv_prefix *
rtadv_prefix_new (void)
{
return 0;
}
-DEFUN (ipv6_nd_suppress_ra,
- ipv6_nd_suppress_ra_cmd,
- "ipv6 nd suppress-ra",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Suppress Router Advertisement\n")
+static void
+ipv6_nd_suppress_ra_set (struct interface *ifp, ipv6_nd_suppress_ra_status status)
{
- struct interface *ifp;
struct zebra_if *zif;
+ struct zebra_vrf *zvrf;
+ struct zebra_ns *zns;
- ifp = vty->index;
zif = ifp->info;
+ zvrf = vrf_info_lookup (ifp->vrf_id);
+ zns = zvrf->zns;
- if (if_is_loopback (ifp))
+ if (status == RA_SUPPRESS)
{
- vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
- return CMD_WARNING;
+ /* RA is currently enabled */
+ if (zif->rtadv.AdvSendAdvertisements)
+ {
+ zif->rtadv.AdvSendAdvertisements = 0;
+ zif->rtadv.AdvIntervalTimer = 0;
+ zns->rtadv.adv_if_count--;
+
+ if_leave_all_router (zns->rtadv.sock, ifp);
+
+ if (zns->rtadv.adv_if_count == 0)
+ rtadv_event (zns, RTADV_STOP, 0);
+ }
}
+ else
+ {
+ if (! zif->rtadv.AdvSendAdvertisements)
+ {
+ zif->rtadv.AdvSendAdvertisements = 1;
+ zif->rtadv.AdvIntervalTimer = 0;
+ zns->rtadv.adv_if_count++;
+
+ if (zif->rtadv.MaxRtrAdvInterval >= 1000)
+ {
+ /* Enable Fast RA only when RA interval is in secs */
+ zif->rtadv.inFastRexmit = 1;
+ zif->rtadv.NumFastReXmitsRemain = RTADV_NUM_FAST_REXMITS;
+ }
+
+ if_join_all_router (zns->rtadv.sock, ifp);
+
+ if (zns->rtadv.adv_if_count == 1)
+ rtadv_event (zns, RTADV_START, zns->rtadv.sock);
+ }
+ }
+}
+
+/*
+ * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
+ * Note that while the client could request RA on an interface on which the
+ * operator has not enabled RA, RA won't be disabled upon client request
+ * if the operator has explicitly enabled RA. The enable request can also
+ * specify a RA interval (in seconds).
+ */
+void
+zebra_interface_radv_set (struct zserv *client, int sock, u_short length,
+ struct zebra_vrf *zvrf, int enable)
+{
+ struct stream *s;
+ unsigned int ifindex;
+ struct interface *ifp;
+ struct zebra_if *zif;
+ int ra_interval;
- if (zif->rtadv.AdvSendAdvertisements)
+ s = client->ibuf;
+
+ /* Get interface index and RA interval. */
+ ifindex = stream_getl (s);
+ ra_interval = stream_getl (s);
+
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
+ zvrf_id (zvrf), ifindex, enable ? "enable" : "disable",
+ zebra_route_string(client->proto), ra_interval);
+
+ /* Locate interface and check VRF match. */
+ ifp = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT), ifindex);
+ if (!ifp)
{
- zif->rtadv.AdvSendAdvertisements = 0;
- zif->rtadv.AdvIntervalTimer = 0;
- rtadv->adv_if_count--;
+ zlog_warn("%u: IF %u RA %s client %s - interface unknown",
+ zvrf_id (zvrf), ifindex, enable ? "enable" : "disable",
+ zebra_route_string(client->proto));
+ return;
+ }
+ if (ifp->vrf_id != zvrf_id (zvrf))
+ {
+ zlog_warn("%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
+ zvrf_id (zvrf), ifindex, enable ? "enable" : "disable",
+ zebra_route_string(client->proto), ifp->vrf_id);
+ return;
+ }
- if_leave_all_router (rtadv->sock, ifp);
+ zif = ifp->info;
+ if (enable)
+ {
+ ipv6_nd_suppress_ra_set (ifp, RA_ENABLE);
+ if (ra_interval &&
+ (ra_interval * 1000) < zif->rtadv.MaxRtrAdvInterval)
+ zif->rtadv.MaxRtrAdvInterval = ra_interval * 1000;
+ }
+ else
+ {
+ if (!zif->rtadv.configured)
+ {
+ zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
+ ipv6_nd_suppress_ra_set (ifp, RA_SUPPRESS);
+ }
+ }
+}
- if (rtadv->adv_if_count == 0)
- rtadv_event (RTADV_STOP, 0);
+DEFUN (ipv6_nd_suppress_ra,
+ ipv6_nd_suppress_ra_cmd,
+ "ipv6 nd suppress-ra",
+ "Interface IPv6 config commands\n"
+ "Neighbor discovery\n"
+ "Suppress Router Advertisement\n")
+{
+ VTY_DECLVAR_CONTEXT (interface, ifp);
+ struct zebra_if *zif = ifp->info;
+
+ if (if_is_loopback (ifp) ||
+ CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))
+ {
+ vty_out (vty, "Cannot configure IPv6 Router Advertisements on this interface%s", VTY_NEWLINE);
+ return CMD_WARNING;
}
+ ipv6_nd_suppress_ra_set (ifp, RA_SUPPRESS);
+ zif->rtadv.configured = 0;
return CMD_SUCCESS;
}
"Neighbor discovery\n"
"Suppress Router Advertisement\n")
{
- struct interface *ifp;
- struct zebra_if *zif;
-
- ifp = vty->index;
- zif = ifp->info;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
+ struct zebra_if *zif = ifp->info;
- if (if_is_loopback (ifp))
+ if (if_is_loopback (ifp) ||
+ CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))
{
- vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
+ vty_out (vty, "Cannot configure IPv6 Router Advertisements on this interface%s", VTY_NEWLINE);
return CMD_WARNING;
}
- if (! zif->rtadv.AdvSendAdvertisements)
- {
- zif->rtadv.AdvSendAdvertisements = 1;
- zif->rtadv.AdvIntervalTimer = 0;
- rtadv->adv_if_count++;
-
- if_join_all_router (rtadv->sock, ifp);
-
- if (rtadv->adv_if_count == 1)
- rtadv_event (RTADV_START, rtadv->sock);
- }
-
+ ipv6_nd_suppress_ra_set (ifp, RA_ENABLE);
+ zif->rtadv.configured = 1;
return CMD_SUCCESS;
}
DEFUN (ipv6_nd_ra_interval_msec,
ipv6_nd_ra_interval_msec_cmd,
- "ipv6 nd ra-interval msec <70-1800000>",
+ "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"
"Router Advertisement interval in milliseconds\n")
{
+ int idx_number = 4;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
unsigned interval;
- struct interface *ifp = (struct interface *) vty->index;
struct zebra_if *zif = ifp->info;
+ struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
+ struct zebra_ns *zns;
- VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 70, 1800000);
+ zns = zvrf->zns;
+ VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[idx_number]->arg, 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);
}
if (zif->rtadv.MaxRtrAdvInterval % 1000)
- rtadv->adv_msec_if_count--;
+ zns->rtadv.adv_msec_if_count--;
if (interval % 1000)
- rtadv->adv_msec_if_count++;
+ zns->rtadv.adv_msec_if_count++;
zif->rtadv.MaxRtrAdvInterval = interval;
zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
DEFUN (ipv6_nd_ra_interval,
ipv6_nd_ra_interval_cmd,
- "ipv6 nd ra-interval <1-1800>",
+ "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 idx_number = 3;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
unsigned interval;
- struct interface *ifp = (struct interface *) vty->index;
struct zebra_if *zif = ifp->info;
+ struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
+ struct zebra_ns *zns;
- VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 1, 1800);
+ zns = zvrf->zns;
+ VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[idx_number]->arg, 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);
}
if (zif->rtadv.MaxRtrAdvInterval % 1000)
- rtadv->adv_msec_if_count--;
+ zns->rtadv.adv_msec_if_count--;
/* convert to milliseconds */
interval = interval * 1000;
DEFUN (no_ipv6_nd_ra_interval,
no_ipv6_nd_ra_interval_cmd,
- "no ipv6 nd ra-interval",
+ "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
NO_STR
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
- "Router Advertisement interval\n")
+ "Router Advertisement interval\n"
+ "Router Advertisement interval in seconds\n"
+ "Specify millisecond router advertisement interval\n"
+ "Router Advertisement interval in milliseconds\n")
{
- struct interface *ifp;
- struct zebra_if *zif;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
+ struct zebra_if *zif = ifp->info;
+ struct zebra_vrf *zvrf;
+ struct zebra_ns *zns;
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
+ zvrf = vrf_info_lookup (ifp->vrf_id);
+ zns = zvrf->zns;
if (zif->rtadv.MaxRtrAdvInterval % 1000)
- rtadv->adv_msec_if_count--;
+ zns->rtadv.adv_msec_if_count--;
zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_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 <0-9000>",
+ "ipv6 nd ra-lifetime (0-9000)",
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
"Router lifetime\n"
"Router lifetime in seconds (0 stands for a non-default gw)\n")
{
+ int idx_number = 3;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
+ struct zebra_if *zif = ifp->info;
int lifetime;
- struct interface *ifp;
- struct zebra_if *zif;
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
-
- VTY_GET_INTEGER_RANGE ("router lifetime", lifetime, argv[0], 0, 9000);
+ VTY_GET_INTEGER_RANGE ("router lifetime", lifetime, argv[idx_number]->arg, 0, 9000);
/* The value to be placed in the Router Lifetime field
* of Router Advertisements sent from the interface,
DEFUN (no_ipv6_nd_ra_lifetime,
no_ipv6_nd_ra_lifetime_cmd,
- "no ipv6 nd ra-lifetime",
+ "no ipv6 nd ra-lifetime [(0-9000)]",
NO_STR
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
- "Router lifetime\n")
+ "Router lifetime\n"
+ "Router lifetime in seconds (0 stands for a non-default gw)\n")
{
- struct interface *ifp;
- struct zebra_if *zif;
-
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
+ struct zebra_if *zif = ifp->info;
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 <1-3600000>",
+ "ipv6 nd reachable-time (1-3600000)",
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
"Reachable time\n"
"Reachable time in milliseconds\n")
{
- struct interface *ifp = (struct interface *) vty->index;
+ int idx_number = 3;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
struct zebra_if *zif = ifp->info;
- VTY_GET_INTEGER_RANGE ("reachable time", zif->rtadv.AdvReachableTime, argv[0], 1, RTADV_MAX_REACHABLE_TIME);
+ VTY_GET_INTEGER_RANGE ("reachable time", zif->rtadv.AdvReachableTime, argv[idx_number]->arg, 1, RTADV_MAX_REACHABLE_TIME);
return CMD_SUCCESS;
}
DEFUN (no_ipv6_nd_reachable_time,
no_ipv6_nd_reachable_time_cmd,
- "no ipv6 nd reachable-time",
+ "no ipv6 nd reachable-time [(1-3600000)]",
NO_STR
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
- "Reachable time\n")
+ "Reachable time\n"
+ "Reachable time in milliseconds\n")
{
- struct interface *ifp;
- struct zebra_if *zif;
-
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
+ struct zebra_if *zif = ifp->info;
zif->rtadv.AdvReachableTime = 0;
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 <0-65535>",
+ "ipv6 nd home-agent-preference (0-65535)",
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
"Home Agent preference\n"
"preference value (default is 0, least preferred)\n")
{
- struct interface *ifp = (struct interface *) vty->index;
+ int idx_number = 3;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
struct zebra_if *zif = ifp->info;
- VTY_GET_INTEGER_RANGE ("home agent preference", zif->rtadv.HomeAgentPreference, argv[0], 0, 65535);
+ VTY_GET_INTEGER_RANGE ("home agent preference", zif->rtadv.HomeAgentPreference, argv[idx_number]->arg, 0, 65535);
return CMD_SUCCESS;
}
DEFUN (no_ipv6_nd_homeagent_preference,
no_ipv6_nd_homeagent_preference_cmd,
- "no ipv6 nd home-agent-preference",
+ "no ipv6 nd home-agent-preference [(0-65535)]",
NO_STR
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
- "Home Agent preference\n")
+ "Home Agent preference\n"
+ "preference value (default is 0, least preferred)\n")
{
- struct interface *ifp;
- struct zebra_if *zif;
-
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
+ struct zebra_if *zif = ifp->info;
zif->rtadv.HomeAgentPreference = 0;
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 <0-65520>",
+ "ipv6 nd home-agent-lifetime (0-65520)",
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
"Home Agent lifetime\n"
"Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
{
- struct interface *ifp = (struct interface *) vty->index;
+ int idx_number = 3;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
struct zebra_if *zif = ifp->info;
- VTY_GET_INTEGER_RANGE ("home agent lifetime", zif->rtadv.HomeAgentLifetime, argv[0], 0, RTADV_MAX_HALIFETIME);
+ VTY_GET_INTEGER_RANGE ("home agent lifetime", zif->rtadv.HomeAgentLifetime, argv[idx_number]->arg, 0, RTADV_MAX_HALIFETIME);
return CMD_SUCCESS;
}
DEFUN (no_ipv6_nd_homeagent_lifetime,
no_ipv6_nd_homeagent_lifetime_cmd,
- "no ipv6 nd home-agent-lifetime",
+ "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\n"
+ "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
{
- struct interface *ifp;
- struct zebra_if *zif;
-
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
+ struct zebra_if *zif = ifp->info;
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",
"Neighbor discovery\n"
"Managed address configuration flag\n")
{
- struct interface *ifp;
- struct zebra_if *zif;
-
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
+ struct zebra_if *zif = ifp->info;
zif->rtadv.AdvManagedFlag = 1;
"Neighbor discovery\n"
"Managed address configuration flag\n")
{
- struct interface *ifp;
- struct zebra_if *zif;
-
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
+ struct zebra_if *zif = ifp->info;
zif->rtadv.AdvManagedFlag = 0;
"Neighbor discovery\n"
"Home Agent configuration flag\n")
{
- struct interface *ifp;
- struct zebra_if *zif;
-
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
+ struct zebra_if *zif = ifp->info;
zif->rtadv.AdvHomeAgentFlag = 1;
"Neighbor discovery\n"
"Home Agent configuration flag\n")
{
- struct interface *ifp;
- struct zebra_if *zif;
-
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
+ struct zebra_if *zif = ifp->info;
zif->rtadv.AdvHomeAgentFlag = 0;
"Neighbor discovery\n"
"Advertisement Interval Option\n")
{
- struct interface *ifp;
- struct zebra_if *zif;
-
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
+ struct zebra_if *zif = ifp->info;
zif->rtadv.AdvIntervalOption = 1;
"Neighbor discovery\n"
"Advertisement Interval Option\n")
{
- struct interface *ifp;
- struct zebra_if *zif;
-
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
+ struct zebra_if *zif = ifp->info;
zif->rtadv.AdvIntervalOption = 0;
"Neighbor discovery\n"
"Other statefull configuration flag\n")
{
- struct interface *ifp;
- struct zebra_if *zif;
-
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
+ struct zebra_if *zif = ifp->info;
zif->rtadv.AdvOtherConfigFlag = 1;
"Neighbor discovery\n"
"Other statefull configuration flag\n")
{
- struct interface *ifp;
- struct zebra_if *zif;
-
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
+ struct zebra_if *zif = ifp->info;
zif->rtadv.AdvOtherConfigFlag = 0;
DEFUN (ipv6_nd_prefix,
ipv6_nd_prefix_cmd,
- "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
- "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|) (router-address|)",
+ "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
"Prefix information\n"
"Infinite valid lifetime\n"
"Preferred lifetime in seconds\n"
"Infinite preferred lifetime\n"
+ "Set Router Address flag\n"
"Do not use prefix for onlink determination\n"
"Do not use prefix for autoconfiguration\n"
- "Set Router Address flag\n")
+ "Do not use prefix for autoconfiguration\n"
+ "Do not use prefix for onlink determination\n")
{
- int i;
+ /* prelude */
+ char *prefix = argv[3]->arg;
+ int lifetimes = (argc > 4) && (argv[4]->type == RANGE_TKN || strmatch (argv[4]->text, "infinite"));
+ int routeropts = lifetimes ? argc > 6 : argc > 4;
+
+ int idx_routeropts = routeropts ? (lifetimes ? 6 : 4) : 0;
+
+ char *lifetime = NULL, *preflifetime = NULL;
+ int routeraddr = 0, offlink = 0, noautoconf = 0;
+ if (lifetimes)
+ {
+ lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg : argv[4]->text;
+ preflifetime = argv[5]->type == RANGE_TKN ? argv[5]->arg : argv[5]->text;
+ }
+ if (routeropts)
+ {
+ routeraddr = strmatch (argv[idx_routeropts]->text, "router-address");
+ if (!routeraddr)
+ {
+ offlink = (argc > idx_routeropts + 1 || strmatch (argv[idx_routeropts]->text, "off-link"));
+ noautoconf = (argc > idx_routeropts + 1 || strmatch (argv[idx_routeropts]->text, "no-autoconfig"));
+ }
+ }
+
+ /* business */
+ VTY_DECLVAR_CONTEXT (interface, ifp);
+ struct zebra_if *zebra_if = ifp->info;
int ret;
- int cursor = 1;
- struct interface *ifp;
- struct zebra_if *zebra_if;
struct rtadv_prefix rp;
- ifp = (struct interface *) vty->index;
- zebra_if = ifp->info;
-
- ret = str2prefix_ipv6 (argv[0], &rp.prefix);
+ ret = str2prefix_ipv6 (prefix, &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;
+ rp.AdvOnLinkFlag = !offlink;
+ rp.AdvAutonomousFlag = !noautoconf;
+ rp.AdvRouterAddressFlag = routeraddr;
rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
- if (argc > 1)
- {
- if ((isdigit(argv[1][0])) || strncmp (argv[1], "i", 1) == 0)
- {
- if ( strncmp (argv[1], "i", 1) == 0)
- rp.AdvValidLifetime = UINT32_MAX;
- else
- rp.AdvValidLifetime = (u_int32_t) strtoll (argv[1],
- (char **)NULL, 10);
-
- if ( strncmp (argv[2], "i", 1) == 0)
- rp.AdvPreferredLifetime = UINT32_MAX;
- else
- rp.AdvPreferredLifetime = (u_int32_t) strtoll (argv[2],
- (char **)NULL, 10);
-
- if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
- {
- vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- cursor = cursor + 2;
- }
- if (argc > cursor)
- {
- for (i = cursor; i < argc; i++)
- {
- if (strncmp (argv[i], "of", 2) == 0)
- rp.AdvOnLinkFlag = 0;
- if (strncmp (argv[i], "no", 2) == 0)
- rp.AdvAutonomousFlag = 0;
- if (strncmp (argv[i], "ro", 2) == 0)
- rp.AdvRouterAddressFlag = 1;
- }
- }
- }
+ if (lifetimes)
+ {
+ rp.AdvValidLifetime = strmatch (lifetime, "infinite") ? UINT32_MAX : strtoll (lifetime, NULL, 10);
+ rp.AdvPreferredLifetime = strmatch (preflifetime, "infinite") ? UINT32_MAX : strtoll (preflifetime, NULL, 10);
+ if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
+ {
+ vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
rtadv_prefix_set (zebra_if, &rp);
return CMD_SUCCESS;
}
-ALIAS (ipv6_nd_prefix,
- ipv6_nd_prefix_val_nortaddr_cmd,
- "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
- "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
+DEFUN (no_ipv6_nd_prefix,
+ no_ipv6_nd_prefix_cmd,
+ "no ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
+ NO_STR
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
"Prefix information\n"
"Infinite valid lifetime\n"
"Preferred lifetime in seconds\n"
"Infinite preferred lifetime\n"
+ "Set Router Address flag\n"
"Do not use prefix for onlink determination\n"
- "Do not use prefix for autoconfiguration\n")
-
-ALIAS (ipv6_nd_prefix,
- ipv6_nd_prefix_val_rev_cmd,
- "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
- "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Prefix information\n"
- "IPv6 prefix\n"
- "Valid lifetime in seconds\n"
- "Infinite valid lifetime\n"
- "Preferred lifetime in seconds\n"
- "Infinite preferred lifetime\n"
"Do not use prefix for autoconfiguration\n"
- "Do not use prefix for onlink determination\n")
-
-ALIAS (ipv6_nd_prefix,
- ipv6_nd_prefix_val_rev_rtaddr_cmd,
- "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
- "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|) (router-address|)",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Prefix information\n"
- "IPv6 prefix\n"
- "Valid lifetime in seconds\n"
- "Infinite valid lifetime\n"
- "Preferred lifetime in seconds\n"
- "Infinite preferred lifetime\n"
"Do not use prefix for autoconfiguration\n"
- "Do not use prefix for onlink determination\n"
- "Set Router Address flag\n")
-
-ALIAS (ipv6_nd_prefix,
- ipv6_nd_prefix_val_noauto_cmd,
- "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
- "(<0-4294967295>|infinite) (no-autoconfig|)",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Prefix information\n"
- "IPv6 prefix\n"
- "Valid lifetime in seconds\n"
- "Infinite valid lifetime\n"
- "Preferred lifetime in seconds\n"
- "Infinite preferred lifetime\n"
- "Do not use prefix for autoconfiguration")
-
-ALIAS (ipv6_nd_prefix,
- ipv6_nd_prefix_val_offlink_cmd,
- "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
- "(<0-4294967295>|infinite) (off-link|)",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Prefix information\n"
- "IPv6 prefix\n"
- "Valid lifetime in seconds\n"
- "Infinite valid lifetime\n"
- "Preferred lifetime in seconds\n"
- "Infinite preferred lifetime\n"
"Do not use prefix for onlink determination\n")
-
-ALIAS (ipv6_nd_prefix,
- ipv6_nd_prefix_val_rtaddr_cmd,
- "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
- "(<0-4294967295>|infinite) (router-address|)",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Prefix information\n"
- "IPv6 prefix\n"
- "Valid lifetime in seconds\n"
- "Infinite valid lifetime\n"
- "Preferred lifetime in seconds\n"
- "Infinite preferred lifetime\n"
- "Set Router Address flag\n")
-
-ALIAS (ipv6_nd_prefix,
- ipv6_nd_prefix_val_cmd,
- "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
- "(<0-4294967295>|infinite)",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Prefix information\n"
- "IPv6 prefix\n"
- "Valid lifetime in seconds\n"
- "Infinite valid lifetime\n"
- "Preferred lifetime in seconds\n"
- "Infinite preferred lifetime\n")
-
-ALIAS (ipv6_nd_prefix,
- ipv6_nd_prefix_noval_cmd,
- "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Prefix information\n"
- "IPv6 prefix\n"
- "Do not use prefix for autoconfiguration\n"
- "Do not use prefix for onlink determination\n")
-
-ALIAS (ipv6_nd_prefix,
- ipv6_nd_prefix_noval_rev_cmd,
- "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Prefix information\n"
- "IPv6 prefix\n"
- "Do not use prefix for onlink determination\n"
- "Do not use prefix for autoconfiguration\n")
-
-ALIAS (ipv6_nd_prefix,
- ipv6_nd_prefix_noval_noauto_cmd,
- "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Prefix information\n"
- "IPv6 prefix\n"
- "Do not use prefix for autoconfiguration\n")
-
-ALIAS (ipv6_nd_prefix,
- ipv6_nd_prefix_noval_offlink_cmd,
- "ipv6 nd prefix X:X::X:X/M (off-link|)",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Prefix information\n"
- "IPv6 prefix\n"
- "Do not use prefix for onlink determination\n")
-
-ALIAS (ipv6_nd_prefix,
- ipv6_nd_prefix_noval_rtaddr_cmd,
- "ipv6 nd prefix X:X::X:X/M (router-address|)",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Prefix information\n"
- "IPv6 prefix\n"
- "Set Router Address flag\n")
-
-ALIAS (ipv6_nd_prefix,
- ipv6_nd_prefix_prefix_cmd,
- "ipv6 nd prefix X:X::X:X/M",
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Prefix information\n"
- "IPv6 prefix\n")
-
-DEFUN (no_ipv6_nd_prefix,
- no_ipv6_nd_prefix_cmd,
- "no ipv6 nd prefix IPV6PREFIX",
- NO_STR
- "Interface IPv6 config commands\n"
- "Neighbor discovery\n"
- "Prefix information\n"
- "IPv6 prefix\n")
{
+ VTY_DECLVAR_CONTEXT (interface, ifp);
+ struct zebra_if *zebra_if = ifp->info;
int ret;
- struct interface *ifp;
- struct zebra_if *zebra_if;
struct rtadv_prefix rp;
+ char *prefix = argv[4]->arg;
- ifp = (struct interface *) vty->index;
- zebra_if = ifp->info;
-
- ret = str2prefix_ipv6 (argv[0], &rp.prefix);
+ ret = str2prefix_ipv6 (prefix, &rp.prefix);
if (!ret)
{
vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
ret = rtadv_prefix_reset (zebra_if, &rp);
if (!ret)
{
- vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
+ vty_out (vty, "Non-existant IPv6 prefix%s", VTY_NEWLINE);
return CMD_WARNING;
}
DEFUN (ipv6_nd_router_preference,
ipv6_nd_router_preference_cmd,
- "ipv6 nd router-preference (high|medium|low)",
+ "ipv6 nd router-preference <high|medium|low>",
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
"Default router preference\n"
"Low default router preference\n"
"Medium default router preference (default)\n")
{
- struct interface *ifp;
- struct zebra_if *zif;
+ int idx_high_medium_low = 3;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
+ struct zebra_if *zif = ifp->info;
int i = 0;
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
-
while (0 != rtadv_pref_strs[i])
{
- if (strncmp (argv[0], rtadv_pref_strs[i], 1) == 0)
+ if (strncmp (argv[idx_high_medium_low]->arg, rtadv_pref_strs[i], 1) == 0)
{
zif->rtadv.DefaultPreference = i;
return CMD_SUCCESS;
DEFUN (no_ipv6_nd_router_preference,
no_ipv6_nd_router_preference_cmd,
- "no ipv6 nd router-preference",
+ "no ipv6 nd router-preference [<high|medium|low>]",
NO_STR
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
- "Default router preference\n")
+ "Default router preference\n"
+ "High default router preference\n"
+ "Medium default router preference (default)\n"
+ "Low default router preference\n")
{
- struct interface *ifp;
- struct zebra_if *zif;
-
- ifp = (struct interface *) vty->index;
- zif = ifp->info;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
+ struct zebra_if *zif = ifp->info;
zif->rtadv.DefaultPreference = RTADV_PREF_MEDIUM; /* Default per RFC4191. */
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>",
+ "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;
+ int idx_number = 3;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
struct zebra_if *zif = ifp->info;
- VTY_GET_INTEGER_RANGE ("MTU", zif->rtadv.AdvLinkMTU, argv[0], 1, 65535);
+ VTY_GET_INTEGER_RANGE ("MTU", zif->rtadv.AdvLinkMTU, argv[idx_number]->arg, 1, 65535);
return CMD_SUCCESS;
}
DEFUN (no_ipv6_nd_mtu,
no_ipv6_nd_mtu_cmd,
- "no ipv6 nd mtu",
+ "no ipv6 nd mtu [(1-65535)]",
NO_STR
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
- "Advertised MTU\n")
+ "Advertised MTU\n"
+ "MTU in bytes\n")
{
- struct interface *ifp = (struct interface *) vty->index;
+ VTY_DECLVAR_CONTEXT (interface, ifp);
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
struct zebra_if *zif;
struct listnode *node;
struct rtadv_prefix *rprefix;
- u_char buf[INET6_ADDRSTRLEN];
+ char buf[PREFIX_STRLEN];
int interval;
- if (! rtadv)
- return;
-
zif = ifp->info;
- if (! if_is_loopback (ifp))
+ if (!(if_is_loopback (ifp) ||
+ CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)))
{
if (zif->rtadv.AdvSendAdvertisements)
- vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
- else
- vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE);
+ vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
}
-
interval = zif->rtadv.MaxRtrAdvInterval;
if (interval % 1000)
for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
{
- vty_out (vty, " ipv6 nd prefix %s/%d",
- inet_ntop (AF_INET6, &rprefix->prefix.prefix,
- (char *) buf, INET6_ADDRSTRLEN),
- rprefix->prefix.prefixlen);
+ vty_out (vty, " ipv6 nd prefix %s",
+ prefix2str (&rprefix->prefix, buf, sizeof(buf)));
if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||
(rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
{
static void
-rtadv_event (enum rtadv_event event, int val)
+rtadv_event (struct zebra_ns *zns, enum rtadv_event event, int val)
{
+ struct rtadv *rtadv = &zns->rtadv;
+
switch (event)
{
case RTADV_START:
if (! rtadv->ra_read)
- rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
+ rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, zns, val);
if (! rtadv->ra_timer)
- rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
- NULL, 0);
+ rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
+ zns, 0);
break;
case RTADV_STOP:
if (rtadv->ra_timer)
break;
case RTADV_TIMER:
if (! rtadv->ra_timer)
- rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL,
+ rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, zns,
val);
break;
case RTADV_TIMER_MSEC:
if (! rtadv->ra_timer)
rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer,
- NULL, val);
+ zns, val);
break;
case RTADV_READ:
if (! rtadv->ra_read)
- rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
+ rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, zns, val);
break;
default:
break;
}
void
-rtadv_init (void)
+rtadv_init (struct zebra_ns *zns)
{
- int sock;
+ zns->rtadv.sock = rtadv_make_socket ();
+}
- sock = rtadv_make_socket ();
- if (sock < 0)
- return;
+void
+rtadv_terminate (struct zebra_ns *zns)
+{
+ rtadv_event (zns, RTADV_STOP, 0);
+ if (zns->rtadv.sock >= 0)
+ {
+ close (zns->rtadv.sock);
+ zns->rtadv.sock = -1;
+ }
- rtadv = rtadv_new ();
- rtadv->sock = sock;
+ zns->rtadv.adv_if_count = 0;
+ zns->rtadv.adv_msec_if_count = 0;
+}
+void
+rtadv_cmd_init (void)
+{
install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
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);
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);
- install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_rtaddr_cmd);
- install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_nortaddr_cmd);
- install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_cmd);
- install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_noauto_cmd);
- install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_offlink_cmd);
- install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rtaddr_cmd);
- install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_cmd);
- install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_cmd);
- install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rev_cmd);
- install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_noauto_cmd);
- install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_offlink_cmd);
- install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd);
- install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
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
ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
(char *) &mreq, sizeof mreq);
if (ret < 0)
- zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", safe_strerror (errno));
+ zlog_warn ("%s(%u): Failed to join group, socket %u error %s",
+ ifp->name, ifp->ifindex, sock, safe_strerror (errno));
- zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug ("%s(%u): Join All-Routers multicast group, socket %u",
+ ifp->name, ifp->ifindex, sock);
return 0;
}
ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
(char *) &mreq, sizeof mreq);
if (ret < 0)
- zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", safe_strerror (errno));
+ zlog_warn ("%s(%u): Failed to leave group, socket %u error %s",
+ ifp->name, ifp->ifindex, sock,safe_strerror (errno));
- zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug ("%s(%u): Leave All-Routers multicast group, socket %u",
+ ifp->name, ifp->ifindex, sock);
return 0;
}
#else
void
-rtadv_init (void)
+rtadv_init (struct zebra_ns *zns)
+{
+ /* Empty.*/;
+}
+void
+rtadv_terminate (struct zebra_ns *zns)
+{
+ /* Empty.*/;
+}
+void
+rtadv_cmd_init (void)
{
/* Empty.*/;
}
-#endif /* RTADV && HAVE_IPV6 */
+#endif /* HAVE_RTADV && HAVE_IPV6 */