back to topotato report
topotato coverage report
Current view: top level - zebra - rtadv.c (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 439 1444 30.4 %
Date: 2023-11-16 17:19:14 Functions: 41 211 19.4 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /* Router advertisement
       3             :  * Copyright (C) 2016 Cumulus Networks
       4             :  * Copyright (C) 2005 6WIND <jean-mickael.guerin@6wind.com>
       5             :  * Copyright (C) 1999 Kunihiro Ishiguro
       6             :  */
       7             : 
       8             : #include <zebra.h>
       9             : 
      10             : #include "memory.h"
      11             : #include "sockopt.h"
      12             : #include "frrevent.h"
      13             : #include "if.h"
      14             : #include "stream.h"
      15             : #include "log.h"
      16             : #include "prefix.h"
      17             : #include "linklist.h"
      18             : #include "command.h"
      19             : #include "privs.h"
      20             : #include "vrf.h"
      21             : #include "ns.h"
      22             : #include "lib_errors.h"
      23             : 
      24             : #include "zebra/interface.h"
      25             : #include "zebra/rtadv.h"
      26             : #include "zebra/debug.h"
      27             : #include "zebra/rib.h"
      28             : #include "zebra/zapi_msg.h"
      29             : #include "zebra/zebra_vrf.h"
      30             : #include "zebra/zebra_errors.h"
      31             : #include "zebra/zebra_router.h"
      32             : 
      33             : extern struct zebra_privs_t zserv_privs;
      34             : 
      35             : static uint32_t interfaces_configured_for_ra_from_bgp;
      36             : 
      37             : #if defined(HAVE_RTADV)
      38             : 
      39             : #include "zebra/rtadv_clippy.c"
      40             : 
      41           6 : DEFINE_MTYPE_STATIC(ZEBRA, RTADV_PREFIX, "Router Advertisement Prefix");
      42           6 : DEFINE_MTYPE_STATIC(ZEBRA, ADV_IF, "Advertised Interface");
      43             : 
      44             : #ifdef OPEN_BSD
      45             : #include <netinet/icmp6.h>
      46             : #endif
      47             : 
      48             : /* If RFC2133 definition is used. */
      49             : #ifndef IPV6_JOIN_GROUP
      50             : #define IPV6_JOIN_GROUP  IPV6_ADD_MEMBERSHIP
      51             : #endif
      52             : #ifndef IPV6_LEAVE_GROUP
      53             : #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
      54             : #endif
      55             : 
      56             : #define ALLNODE   "ff02::1"
      57             : #define ALLROUTER "ff02::2"
      58             : 
      59             : /* adv list node */
      60             : struct adv_if {
      61             :         char name[INTERFACE_NAMSIZ];
      62             :         struct adv_if_list_item list_item;
      63             : };
      64             : 
      65           0 : static int adv_if_cmp(const struct adv_if *a, const struct adv_if *b)
      66             : {
      67           0 :         return if_cmp_name_func(a->name, b->name);
      68             : }
      69             : 
      70           3 : DECLARE_SORTLIST_UNIQ(adv_if_list, struct adv_if, list_item, adv_if_cmp);
      71             : 
      72           8 : static int rtadv_prefix_cmp(const struct rtadv_prefix *a,
      73             :                             const struct rtadv_prefix *b)
      74             : {
      75           8 :         return prefix_cmp(&a->prefix, &b->prefix);
      76             : }
      77             : 
      78          24 : DECLARE_RBTREE_UNIQ(rtadv_prefixes, struct rtadv_prefix, item,
      79             :                     rtadv_prefix_cmp);
      80             : 
      81           6 : DEFINE_MTYPE_STATIC(ZEBRA, RTADV_RDNSS, "Router Advertisement RDNSS");
      82           6 : DEFINE_MTYPE_STATIC(ZEBRA, RTADV_DNSSL, "Router Advertisement DNSSL");
      83             : 
      84             : /* Order is intentional.  Matches RFC4191.  This array is also used for
      85             :    command matching, so only modify with care. */
      86             : static const char *const rtadv_pref_strs[] = {
      87             :         "medium", "high", "INVALID", "low", 0
      88             : };
      89             : 
      90             : enum rtadv_event {
      91             :         RTADV_START,
      92             :         RTADV_STOP,
      93             :         RTADV_TIMER,
      94             :         RTADV_TIMER_MSEC,
      95             :         RTADV_READ
      96             : };
      97             : 
      98             : static void rtadv_event(struct zebra_vrf *, enum rtadv_event, int);
      99             : 
     100             : static int if_join_all_router(int, struct interface *);
     101             : static int if_leave_all_router(int, struct interface *);
     102             : 
     103          16 : static struct zebra_vrf *rtadv_interface_get_zvrf(const struct interface *ifp)
     104             : {
     105             :         /* We use the default vrf for rtadv handling except in netns */
     106          16 :         if (!vrf_is_backend_netns())
     107          16 :                 return vrf_info_lookup(VRF_DEFAULT);
     108             : 
     109           0 :         return ifp->vrf->info;
     110             : }
     111             : 
     112           0 : static int rtadv_increment_received(struct zebra_vrf *zvrf, ifindex_t *ifindex)
     113             : {
     114           0 :         int ret = -1;
     115           0 :         struct interface *iface;
     116           0 :         struct zebra_if *zif;
     117             : 
     118           0 :         iface = if_lookup_by_index(*ifindex, zvrf->vrf->vrf_id);
     119           0 :         if (iface && iface->info) {
     120           0 :                 zif = iface->info;
     121           0 :                 zif->ra_rcvd++;
     122           0 :                 ret = 0;
     123             :         }
     124           0 :         return ret;
     125             : }
     126             : 
     127           0 : static int rtadv_recv_packet(struct zebra_vrf *zvrf, int sock, uint8_t *buf,
     128             :                              int buflen, struct sockaddr_in6 *from,
     129             :                              ifindex_t *ifindex, int *hoplimit)
     130             : {
     131           0 :         int ret;
     132           0 :         struct msghdr msg;
     133           0 :         struct iovec iov;
     134           0 :         struct cmsghdr *cmsgptr;
     135           0 :         struct in6_addr dst;
     136             : 
     137           0 :         char adata[1024];
     138             : 
     139             :         /* Fill in message and iovec. */
     140           0 :         memset(&msg, 0, sizeof(msg));
     141           0 :         msg.msg_name = (void *)from;
     142           0 :         msg.msg_namelen = sizeof(struct sockaddr_in6);
     143           0 :         msg.msg_iov = &iov;
     144           0 :         msg.msg_iovlen = 1;
     145           0 :         msg.msg_control = (void *)adata;
     146           0 :         msg.msg_controllen = sizeof(adata);
     147           0 :         iov.iov_base = buf;
     148           0 :         iov.iov_len = buflen;
     149             : 
     150             :         /* If recvmsg fail return minus value. */
     151           0 :         ret = recvmsg(sock, &msg, 0);
     152           0 :         if (ret < 0)
     153             :                 return ret;
     154             : 
     155           0 :         for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
     156           0 :              cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
     157             :                 /* I want interface index which this packet comes from. */
     158           0 :                 if (cmsgptr->cmsg_level == IPPROTO_IPV6
     159           0 :                     && cmsgptr->cmsg_type == IPV6_PKTINFO) {
     160           0 :                         struct in6_pktinfo *ptr;
     161             : 
     162           0 :                         ptr = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
     163           0 :                         *ifindex = ptr->ipi6_ifindex;
     164           0 :                         memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr));
     165             :                 }
     166             : 
     167             :                 /* Incoming packet's hop limit. */
     168           0 :                 if (cmsgptr->cmsg_level == IPPROTO_IPV6
     169           0 :                     && cmsgptr->cmsg_type == IPV6_HOPLIMIT) {
     170           0 :                         int *hoptr = (int *)CMSG_DATA(cmsgptr);
     171           0 :                         *hoplimit = *hoptr;
     172             :                 }
     173             :         }
     174             : 
     175           0 :         rtadv_increment_received(zvrf, ifindex);
     176           0 :         return ret;
     177             : }
     178             : 
     179             : #define RTADV_MSG_SIZE 4096
     180             : 
     181             : /* Send router advertisement packet. */
     182           6 : static void rtadv_send_packet(int sock, struct interface *ifp,
     183             :                               enum ipv6_nd_suppress_ra_status stop)
     184             : {
     185           6 :         struct msghdr msg;
     186           6 :         struct iovec iov;
     187           6 :         struct cmsghdr *cmsgptr;
     188           6 :         struct in6_pktinfo *pkt;
     189           6 :         struct sockaddr_in6 addr;
     190           6 :         static void *adata = NULL;
     191           6 :         unsigned char buf[RTADV_MSG_SIZE];
     192           6 :         struct nd_router_advert *rtadv;
     193           6 :         int ret;
     194           6 :         int len = 0;
     195           6 :         struct zebra_if *zif;
     196           6 :         struct rtadv_prefix *rprefix;
     197           6 :         uint8_t all_nodes_addr[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
     198             :                                     0,    0,    0, 0, 0, 0, 0, 1};
     199           6 :         struct listnode *node;
     200           6 :         uint16_t pkt_RouterLifetime;
     201             : 
     202             :         /*
     203             :          * Allocate control message bufffer.  This is dynamic because
     204             :          * CMSG_SPACE is not guaranteed not to call a function.  Note that
     205             :          * the size will be different on different architectures due to
     206             :          * differing alignment rules.
     207             :          */
     208           6 :         if (adata == NULL) {
     209             :                 /* XXX Free on shutdown. */
     210           1 :                 adata = calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo)));
     211             : 
     212           1 :                 if (adata == NULL) {
     213           0 :                         zlog_debug("%s: can't malloc control data", __func__);
     214           0 :                         exit(-1);
     215             :                 }
     216             :         }
     217             : 
     218             :         /* Logging of packet. */
     219           6 :         if (IS_ZEBRA_DEBUG_PACKET)
     220           0 :                 zlog_debug("%s(%s:%u): Tx RA, socket %u", ifp->name,
     221             :                            ifp->vrf->name, ifp->ifindex, sock);
     222             : 
     223             :         /* Fill in sockaddr_in6. */
     224           6 :         memset(&addr, 0, sizeof(struct sockaddr_in6));
     225           6 :         addr.sin6_family = AF_INET6;
     226             : #ifdef SIN6_LEN
     227             :         addr.sin6_len = sizeof(struct sockaddr_in6);
     228             : #endif /* SIN6_LEN */
     229           6 :         addr.sin6_port = htons(IPPROTO_ICMPV6);
     230           6 :         IPV6_ADDR_COPY(&addr.sin6_addr, all_nodes_addr);
     231             : 
     232             :         /* Fetch interface information. */
     233           6 :         zif = ifp->info;
     234             : 
     235             :         /* Make router advertisement message. */
     236           6 :         rtadv = (struct nd_router_advert *)buf;
     237             : 
     238           6 :         rtadv->nd_ra_type = ND_ROUTER_ADVERT;
     239           6 :         rtadv->nd_ra_code = 0;
     240           6 :         rtadv->nd_ra_cksum = 0;
     241             : 
     242           6 :         rtadv->nd_ra_curhoplimit = zif->rtadv.AdvCurHopLimit;
     243             : 
     244             :         /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
     245           6 :         rtadv->nd_ra_flags_reserved = zif->rtadv.AdvDefaultLifetime == 0
     246             :                                               ? 0
     247           6 :                                               : zif->rtadv.DefaultPreference;
     248           6 :         rtadv->nd_ra_flags_reserved <<= 3;
     249             : 
     250           6 :         if (zif->rtadv.AdvManagedFlag)
     251           0 :                 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
     252           6 :         if (zif->rtadv.AdvOtherConfigFlag)
     253           0 :                 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
     254           6 :         if (zif->rtadv.AdvHomeAgentFlag)
     255           0 :                 rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;
     256             :         /* Note that according to Neighbor Discovery (RFC 4861 [18]),
     257             :          * AdvDefaultLifetime is by default based on the value of
     258             :          * MaxRtrAdvInterval.  AdvDefaultLifetime is used in the Router Lifetime
     259             :          * field of Router Advertisements.  Given that this field is expressed
     260             :          * in seconds, a small MaxRtrAdvInterval value can result in a zero
     261             :          * value for this field.  To prevent this, routers SHOULD keep
     262             :          * AdvDefaultLifetime in at least one second, even if the use of
     263             :          * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
     264          12 :         pkt_RouterLifetime =
     265             :                 zif->rtadv.AdvDefaultLifetime != -1
     266             :                         ? zif->rtadv.AdvDefaultLifetime
     267           6 :                         : MAX(1, 0.003 * zif->rtadv.MaxRtrAdvInterval);
     268             : 
     269             :         /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
     270           6 :         rtadv->nd_ra_router_lifetime =
     271           5 :                 (stop == RA_SUPPRESS) ? htons(0) : htons(pkt_RouterLifetime);
     272           6 :         rtadv->nd_ra_reachable = htonl(zif->rtadv.AdvReachableTime);
     273           6 :         rtadv->nd_ra_retransmit = htonl(zif->rtadv.AdvRetransTimer);
     274             : 
     275           6 :         len = sizeof(struct nd_router_advert);
     276             : 
     277             :         /* If both the Home Agent Preference and Home Agent Lifetime are set to
     278             :          * their default values specified above, this option SHOULD NOT be
     279             :          * included in the Router Advertisement messages sent by this home
     280             :          * agent. -- RFC6275, 7.4 */
     281           6 :         if (zif->rtadv.AdvHomeAgentFlag
     282           0 :             && (zif->rtadv.HomeAgentPreference
     283           0 :                 || zif->rtadv.HomeAgentLifetime != -1)) {
     284           0 :                 struct nd_opt_homeagent_info *ndopt_hai =
     285             :                         (struct nd_opt_homeagent_info *)(buf + len);
     286           0 :                 ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
     287           0 :                 ndopt_hai->nd_opt_hai_len = 1;
     288           0 :                 ndopt_hai->nd_opt_hai_reserved = 0;
     289           0 :                 ndopt_hai->nd_opt_hai_preference =
     290           0 :                         htons(zif->rtadv.HomeAgentPreference);
     291             :                 /* 16-bit unsigned integer.  The lifetime associated with the
     292             :                  * home
     293             :                  * agent in units of seconds.  The default value is the same as
     294             :                  * the
     295             :                  * Router Lifetime, as specified in the main body of the Router
     296             :                  * Advertisement.  The maximum value corresponds to 18.2 hours.
     297             :                  * A
     298             :                  * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
     299           0 :                 ndopt_hai->nd_opt_hai_lifetime =
     300           0 :                         htons(zif->rtadv.HomeAgentLifetime != -1
     301             :                                       ? zif->rtadv.HomeAgentLifetime
     302             :                                       : MAX(1, pkt_RouterLifetime) /* 0 is OK
     303             :                                                                       for RL,
     304             :                                                                       but not
     305             :                                                                       for HAL*/
     306             :                               );
     307           0 :                 len += sizeof(struct nd_opt_homeagent_info);
     308             :         }
     309             : 
     310           6 :         if (zif->rtadv.AdvIntervalOption) {
     311           0 :                 struct nd_opt_adv_interval *ndopt_adv =
     312           0 :                         (struct nd_opt_adv_interval *)(buf + len);
     313           0 :                 ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL;
     314           0 :                 ndopt_adv->nd_opt_ai_len = 1;
     315           0 :                 ndopt_adv->nd_opt_ai_reserved = 0;
     316           0 :                 ndopt_adv->nd_opt_ai_interval =
     317           0 :                         htonl(zif->rtadv.MaxRtrAdvInterval);
     318           0 :                 len += sizeof(struct nd_opt_adv_interval);
     319             :         }
     320             : 
     321             :         /* Fill in prefix. */
     322          17 :         frr_each (rtadv_prefixes, zif->rtadv.prefixes, rprefix) {
     323           5 :                 struct nd_opt_prefix_info *pinfo;
     324             : 
     325           5 :                 pinfo = (struct nd_opt_prefix_info *)(buf + len);
     326             : 
     327           5 :                 pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
     328           5 :                 pinfo->nd_opt_pi_len = 4;
     329           5 :                 pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
     330             : 
     331           5 :                 pinfo->nd_opt_pi_flags_reserved = 0;
     332           5 :                 if (rprefix->AdvOnLinkFlag)
     333           5 :                         pinfo->nd_opt_pi_flags_reserved |=
     334             :                                 ND_OPT_PI_FLAG_ONLINK;
     335           5 :                 if (rprefix->AdvAutonomousFlag)
     336           5 :                         pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
     337           5 :                 if (rprefix->AdvRouterAddressFlag)
     338           0 :                         pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
     339             : 
     340           5 :                 pinfo->nd_opt_pi_valid_time = htonl(rprefix->AdvValidLifetime);
     341           5 :                 pinfo->nd_opt_pi_preferred_time =
     342           5 :                         htonl(rprefix->AdvPreferredLifetime);
     343           5 :                 pinfo->nd_opt_pi_reserved2 = 0;
     344             : 
     345           5 :                 IPV6_ADDR_COPY(&pinfo->nd_opt_pi_prefix,
     346             :                                &rprefix->prefix.prefix);
     347             : 
     348           5 :                 len += sizeof(struct nd_opt_prefix_info);
     349             :         }
     350             : 
     351             :         /* Hardware address. */
     352           6 :         if (ifp->hw_addr_len != 0) {
     353           6 :                 buf[len++] = ND_OPT_SOURCE_LINKADDR;
     354             : 
     355             :                 /* Option length should be rounded up to next octet if
     356             :                    the link address does not end on an octet boundary. */
     357           6 :                 buf[len++] = (ifp->hw_addr_len + 9) >> 3;
     358             : 
     359           6 :                 memcpy(buf + len, ifp->hw_addr, ifp->hw_addr_len);
     360           6 :                 len += ifp->hw_addr_len;
     361             : 
     362             :                 /* Pad option to end on an octet boundary. */
     363           6 :                 memset(buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7);
     364           6 :                 len += -(ifp->hw_addr_len + 2) & 0x7;
     365             :         }
     366             : 
     367             :         /* MTU */
     368           6 :         if (zif->rtadv.AdvLinkMTU) {
     369           0 :                 struct nd_opt_mtu *opt = (struct nd_opt_mtu *)(buf + len);
     370           0 :                 opt->nd_opt_mtu_type = ND_OPT_MTU;
     371           0 :                 opt->nd_opt_mtu_len = 1;
     372           0 :                 opt->nd_opt_mtu_reserved = 0;
     373           0 :                 opt->nd_opt_mtu_mtu = htonl(zif->rtadv.AdvLinkMTU);
     374           0 :                 len += sizeof(struct nd_opt_mtu);
     375             :         }
     376             : 
     377             :         /*
     378             :          * There is no limit on the number of configurable recursive DNS
     379             :          * servers or search list entries. We don't want the RA message
     380             :          * to exceed the link's MTU (risking fragmentation) or even
     381             :          * blow the stack buffer allocated for it.
     382             :          */
     383           6 :         size_t max_len = MIN(ifp->mtu6 - 40, sizeof(buf));
     384             : 
     385             :         /* Recursive DNS servers */
     386           6 :         struct rtadv_rdnss *rdnss;
     387             : 
     388          12 :         for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvRDNSSList, node, rdnss)) {
     389           0 :                 size_t opt_len =
     390             :                         sizeof(struct nd_opt_rdnss) + sizeof(struct in6_addr);
     391             : 
     392           0 :                 if (len + opt_len > max_len) {
     393           0 :                         zlog_warn(
     394             :                                 "%s(%s:%u): Tx RA: RDNSS option would exceed MTU, omitting it",
     395             :                                 ifp->name, ifp->vrf->name, ifp->ifindex);
     396           0 :                         goto no_more_opts;
     397             :                 }
     398           0 :                 struct nd_opt_rdnss *opt = (struct nd_opt_rdnss *)(buf + len);
     399             : 
     400           0 :                 opt->nd_opt_rdnss_type = ND_OPT_RDNSS;
     401           0 :                 opt->nd_opt_rdnss_len = opt_len / 8;
     402           0 :                 opt->nd_opt_rdnss_reserved = 0;
     403           0 :                 opt->nd_opt_rdnss_lifetime = htonl(
     404             :                         rdnss->lifetime_set
     405             :                                 ? rdnss->lifetime
     406             :                                 : MAX(1, 0.003 * zif->rtadv.MaxRtrAdvInterval));
     407             : 
     408           0 :                 len += sizeof(struct nd_opt_rdnss);
     409             : 
     410           0 :                 IPV6_ADDR_COPY(buf + len, &rdnss->addr);
     411           0 :                 len += sizeof(struct in6_addr);
     412             :         }
     413             : 
     414             :         /* DNS search list */
     415           6 :         struct rtadv_dnssl *dnssl;
     416             : 
     417          12 :         for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvDNSSLList, node, dnssl)) {
     418           0 :                 size_t opt_len = sizeof(struct nd_opt_dnssl)
     419           0 :                                  + ((dnssl->encoded_len + 7) & ~7);
     420             : 
     421           0 :                 if (len + opt_len > max_len) {
     422           0 :                         zlog_warn(
     423             :                                 "%s(%u): Tx RA: DNSSL option would exceed MTU, omitting it",
     424             :                                 ifp->name, ifp->ifindex);
     425           0 :                         goto no_more_opts;
     426             :                 }
     427           0 :                 struct nd_opt_dnssl *opt = (struct nd_opt_dnssl *)(buf + len);
     428             : 
     429           0 :                 opt->nd_opt_dnssl_type = ND_OPT_DNSSL;
     430           0 :                 opt->nd_opt_dnssl_len = opt_len / 8;
     431           0 :                 opt->nd_opt_dnssl_reserved = 0;
     432           0 :                 opt->nd_opt_dnssl_lifetime = htonl(
     433             :                         dnssl->lifetime_set
     434             :                                 ? dnssl->lifetime
     435             :                                 : MAX(1, 0.003 * zif->rtadv.MaxRtrAdvInterval));
     436             : 
     437           0 :                 len += sizeof(struct nd_opt_dnssl);
     438             : 
     439           0 :                 memcpy(buf + len, dnssl->encoded_name, dnssl->encoded_len);
     440           0 :                 len += dnssl->encoded_len;
     441             : 
     442             :                 /* Zero-pad to 8-octet boundary */
     443           0 :                 while (len % 8)
     444           0 :                         buf[len++] = '\0';
     445             :         }
     446             : 
     447           6 : no_more_opts:
     448             : 
     449           6 :         msg.msg_name = (void *)&addr;
     450           6 :         msg.msg_namelen = sizeof(struct sockaddr_in6);
     451           6 :         msg.msg_iov = &iov;
     452           6 :         msg.msg_iovlen = 1;
     453           6 :         msg.msg_control = (void *)adata;
     454           6 :         msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
     455           6 :         msg.msg_flags = 0;
     456           6 :         iov.iov_base = buf;
     457           6 :         iov.iov_len = len;
     458             : 
     459           6 :         cmsgptr = CMSG_FIRSTHDR(&msg);
     460           6 :         cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
     461           6 :         cmsgptr->cmsg_level = IPPROTO_IPV6;
     462           6 :         cmsgptr->cmsg_type = IPV6_PKTINFO;
     463             : 
     464           6 :         pkt = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
     465           6 :         memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr));
     466           6 :         pkt->ipi6_ifindex = ifp->ifindex;
     467             : 
     468           6 :         ret = sendmsg(sock, &msg, 0);
     469           6 :         if (ret < 0) {
     470           0 :                 flog_err_sys(EC_LIB_SOCKET,
     471             :                              "%s(%u): Tx RA failed, socket %u error %d (%s)",
     472             :                              ifp->name, ifp->ifindex, sock, errno,
     473             :                              safe_strerror(errno));
     474             :         } else
     475           6 :                 zif->ra_sent++;
     476           6 : }
     477             : 
     478          11 : static void rtadv_timer(struct event *thread)
     479             : {
     480          11 :         struct zebra_vrf *zvrf = EVENT_ARG(thread);
     481          11 :         struct vrf *vrf;
     482          11 :         struct interface *ifp;
     483          11 :         struct zebra_if *zif;
     484          11 :         int period;
     485             : 
     486          11 :         zvrf->rtadv.ra_timer = NULL;
     487          11 :         if (adv_if_list_count(&zvrf->rtadv.adv_msec_if) == 0) {
     488          11 :                 period = 1000; /* 1 s */
     489          11 :                 rtadv_event(zvrf, RTADV_TIMER, 1 /* 1 s */);
     490             :         } else {
     491           0 :                 period = 10; /* 10 ms */
     492           0 :                 rtadv_event(zvrf, RTADV_TIMER_MSEC, 10 /* 10 ms */);
     493             :         }
     494             : 
     495          33 :         RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
     496          55 :                 FOR_ALL_INTERFACES (vrf, ifp) {
     497          44 :                         if (if_is_loopback(ifp) || !if_is_operative(ifp) ||
     498          66 :                             IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) ||
     499          66 :                             !connected_get_linklocal(ifp) ||
     500          33 :                             (vrf_is_backend_netns() &&
     501           0 :                              ifp->vrf->vrf_id != zvrf->vrf->vrf_id))
     502          11 :                                 continue;
     503             : 
     504          33 :                         zif = ifp->info;
     505             : 
     506          33 :                         if (zif->rtadv.AdvSendAdvertisements) {
     507          11 :                                 if (zif->rtadv.inFastRexmit
     508           4 :                                     && zif->rtadv.UseFastRexmit) {
     509             :                                         /* We assume we fast rexmit every sec so
     510             :                                          * no
     511             :                                          * additional vars */
     512           4 :                                         if (--zif->rtadv.NumFastReXmitsRemain
     513             :                                             <= 0)
     514           1 :                                                 zif->rtadv.inFastRexmit = 0;
     515             : 
     516           4 :                                         if (IS_ZEBRA_DEBUG_SEND)
     517           0 :                                                 zlog_debug(
     518             :                                                         "Fast RA Rexmit on interface %s(%s:%u)",
     519             :                                                         ifp->name,
     520             :                                                         ifp->vrf->name,
     521             :                                                         ifp->ifindex);
     522             : 
     523           4 :                                         rtadv_send_packet(zvrf->rtadv.sock, ifp,
     524             :                                                           RA_ENABLE);
     525             :                                 } else {
     526           7 :                                         zif->rtadv.AdvIntervalTimer -= period;
     527           7 :                                         if (zif->rtadv.AdvIntervalTimer <= 0) {
     528             :                                                 /* FIXME: using
     529             :                                                    MaxRtrAdvInterval each
     530             :                                                    time isn't what section
     531             :                                                    6.2.4 of RFC4861 tells to do.
     532             :                                                    */
     533           1 :                                                 zif->rtadv.AdvIntervalTimer =
     534             :                                                         zif->rtadv
     535           1 :                                                                 .MaxRtrAdvInterval;
     536           1 :                                                 rtadv_send_packet(
     537             :                                                         zvrf->rtadv.sock, ifp,
     538             :                                                         RA_ENABLE);
     539             :                                         }
     540             :                                 }
     541             :                         }
     542             :                 }
     543          11 : }
     544             : 
     545           0 : static void rtadv_process_solicit(struct interface *ifp)
     546             : {
     547           0 :         struct zebra_vrf *zvrf;
     548           0 :         struct zebra_if *zif;
     549             : 
     550           0 :         zvrf = rtadv_interface_get_zvrf(ifp);
     551           0 :         assert(zvrf);
     552           0 :         zif = ifp->info;
     553             : 
     554             :         /*
     555             :          * If FastRetransmit is enabled, send the RA immediately.
     556             :          * If not enabled but it has been more than MIN_DELAY_BETWEEN_RAS
     557             :          * (3 seconds) since the last RA was sent, send it now and reset
     558             :          * the timer to start at the max (configured) again.
     559             :          * If not enabled and it is less than 3 seconds since the last
     560             :          * RA packet was sent, set the timer for 3 seconds so the next
     561             :          * one will be sent with a minimum of 3 seconds between RAs.
     562             :          * RFC4861 sec 6.2.6
     563             :          */
     564           0 :         if ((zif->rtadv.UseFastRexmit)
     565           0 :             || (zif->rtadv.AdvIntervalTimer <=
     566           0 :                 (zif->rtadv.MaxRtrAdvInterval - MIN_DELAY_BETWEEN_RAS))) {
     567           0 :                 rtadv_send_packet(zvrf->rtadv.sock, ifp, RA_ENABLE);
     568           0 :                 zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
     569             :         } else
     570           0 :                 zif->rtadv.AdvIntervalTimer = MIN_DELAY_BETWEEN_RAS;
     571           0 : }
     572             : 
     573           0 : static const char *rtadv_optionalhdr2str(uint8_t opt_type)
     574             : {
     575           0 :         switch (opt_type) {
     576             :         case ND_OPT_SOURCE_LINKADDR:
     577             :                 return "Optional Source Link Address";
     578           0 :         case ND_OPT_TARGET_LINKADDR:
     579           0 :                 return "Optional Target Link Address";
     580           0 :         case ND_OPT_PREFIX_INFORMATION:
     581           0 :                 return "Optional Prefix Information";
     582           0 :         case ND_OPT_REDIRECTED_HEADER:
     583           0 :                 return "Optional Redirected Header";
     584           0 :         case ND_OPT_MTU:
     585           0 :                 return "Optional MTU";
     586           0 :         case ND_OPT_RTR_ADV_INTERVAL:
     587           0 :                 return "Optional Advertisement Interval";
     588           0 :         case ND_OPT_HOME_AGENT_INFO:
     589           0 :                 return "Optional Home Agent Information";
     590             :         }
     591             : 
     592           0 :         return "Unknown Optional Type";
     593             : }
     594             : 
     595             : /*
     596             :  * This function processes optional attributes off of
     597             :  * end of a RA packet received.  At this point in
     598             :  * time we only care about this in one situation
     599             :  * which is when a interface does not have a LL
     600             :  * v6 address.  We still need to be able to install
     601             :  * the mac address for v4 to v6 resolution
     602             :  */
     603           0 : static void rtadv_process_optional(uint8_t *optional, unsigned int len,
     604             :                                    struct interface *ifp,
     605             :                                    struct sockaddr_in6 *addr)
     606             : {
     607           0 :         char *mac;
     608             : 
     609           0 :         while (len > 0) {
     610           0 :                 struct nd_opt_hdr *opt_hdr = (struct nd_opt_hdr *)optional;
     611             : 
     612           0 :                 switch(opt_hdr->nd_opt_type) {
     613           0 :                 case ND_OPT_SOURCE_LINKADDR:
     614           0 :                         mac = (char *)(optional+2);
     615           0 :                         if_nbr_mac_to_ipv4ll_neigh_update(ifp, mac,
     616             :                                                           &addr->sin6_addr, 1);
     617           0 :                         break;
     618           0 :                 default:
     619           0 :                         if (IS_ZEBRA_DEBUG_PACKET)
     620           0 :                                 zlog_debug(
     621             :                                         "%s:Received Packet with optional Header type %s(%u) that is being ignored",
     622             :                                         __func__,
     623             :                                         rtadv_optionalhdr2str(
     624             :                                                 opt_hdr->nd_opt_type),
     625             :                                         opt_hdr->nd_opt_type);
     626             :                         break;
     627             :                 }
     628             : 
     629           0 :                 len -= 8 * opt_hdr->nd_opt_len;
     630           0 :                 optional += 8 * opt_hdr->nd_opt_len;
     631             :         }
     632           0 : }
     633             : 
     634           0 : static void rtadv_process_advert(uint8_t *msg, unsigned int len,
     635             :                                  struct interface *ifp,
     636             :                                  struct sockaddr_in6 *addr)
     637             : {
     638           0 :         struct nd_router_advert *radvert;
     639           0 :         char addr_str[INET6_ADDRSTRLEN];
     640           0 :         struct zebra_if *zif;
     641           0 :         struct prefix p;
     642             : 
     643           0 :         zif = ifp->info;
     644             : 
     645           0 :         inet_ntop(AF_INET6, &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN);
     646             : 
     647           0 :         if (len < sizeof(struct nd_router_advert)) {
     648           0 :                 if (IS_ZEBRA_DEBUG_PACKET)
     649           0 :                         zlog_debug(
     650             :                                 "%s(%s:%u): Rx RA with invalid length %d from %s",
     651             :                                 ifp->name, ifp->vrf->name, ifp->ifindex, len,
     652             :                                 addr_str);
     653           0 :                 return;
     654             :         }
     655             : 
     656           0 :         if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) {
     657           0 :                 rtadv_process_optional(msg + sizeof(struct nd_router_advert),
     658             :                                        len - sizeof(struct nd_router_advert),
     659             :                                        ifp, addr);
     660           0 :                 if (IS_ZEBRA_DEBUG_PACKET)
     661           0 :                         zlog_debug(
     662             :                                 "%s(%s:%u): Rx RA with non-linklocal source address from %s",
     663             :                                 ifp->name, ifp->vrf->name, ifp->ifindex,
     664             :                                 addr_str);
     665           0 :                 return;
     666             :         }
     667             : 
     668           0 :         radvert = (struct nd_router_advert *)msg;
     669             : 
     670             : #define SIXHOUR2USEC (int64_t)6 * 60 * 60 * 1000000
     671             : 
     672           0 :         if ((radvert->nd_ra_curhoplimit && zif->rtadv.AdvCurHopLimit) &&
     673           0 :             (radvert->nd_ra_curhoplimit != zif->rtadv.AdvCurHopLimit) &&
     674           0 :             (monotime_since(&zif->rtadv.lastadvcurhoplimit, NULL) >
     675           0 :                      SIXHOUR2USEC ||
     676           0 :              zif->rtadv.lastadvcurhoplimit.tv_sec == 0)) {
     677           0 :                 flog_warn(
     678             :                         EC_ZEBRA_RA_PARAM_MISMATCH,
     679             :                         "%s(%u): Rx RA - our AdvCurHopLimit (%u) doesn't agree with %s (%u)",
     680             :                         ifp->name, ifp->ifindex, zif->rtadv.AdvCurHopLimit,
     681             :                         addr_str, radvert->nd_ra_curhoplimit);
     682           0 :                 monotime(&zif->rtadv.lastadvcurhoplimit);
     683             :         }
     684             : 
     685           0 :         if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) &&
     686           0 :             !zif->rtadv.AdvManagedFlag &&
     687           0 :             (monotime_since(&zif->rtadv.lastadvmanagedflag, NULL) >
     688           0 :                      SIXHOUR2USEC ||
     689           0 :              zif->rtadv.lastadvmanagedflag.tv_sec == 0)) {
     690           0 :                 flog_warn(
     691             :                         EC_ZEBRA_RA_PARAM_MISMATCH,
     692             :                         "%s(%u): Rx RA - our AdvManagedFlag (%u) doesn't agree with %s (%u)",
     693             :                         ifp->name, ifp->ifindex, zif->rtadv.AdvManagedFlag,
     694             :                         addr_str,
     695             :                         !!CHECK_FLAG(radvert->nd_ra_flags_reserved,
     696             :                                      ND_RA_FLAG_MANAGED));
     697           0 :                 monotime(&zif->rtadv.lastadvmanagedflag);
     698             :         }
     699             : 
     700           0 :         if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) &&
     701           0 :             !zif->rtadv.AdvOtherConfigFlag &&
     702           0 :             (monotime_since(&zif->rtadv.lastadvotherconfigflag, NULL) >
     703           0 :                      SIXHOUR2USEC ||
     704           0 :              zif->rtadv.lastadvotherconfigflag.tv_sec == 0)) {
     705           0 :                 flog_warn(
     706             :                         EC_ZEBRA_RA_PARAM_MISMATCH,
     707             :                         "%s(%u): Rx RA - our AdvOtherConfigFlag (%u) doesn't agree with %s (%u)",
     708             :                         ifp->name, ifp->ifindex, zif->rtadv.AdvOtherConfigFlag,
     709             :                         addr_str,
     710             :                         !!CHECK_FLAG(radvert->nd_ra_flags_reserved,
     711             :                                      ND_RA_FLAG_OTHER));
     712           0 :                 monotime(&zif->rtadv.lastadvotherconfigflag);
     713             :         }
     714             : 
     715           0 :         if ((radvert->nd_ra_reachable && zif->rtadv.AdvReachableTime) &&
     716           0 :             (ntohl(radvert->nd_ra_reachable) != zif->rtadv.AdvReachableTime) &&
     717           0 :             (monotime_since(&zif->rtadv.lastadvreachabletime, NULL) >
     718           0 :                      SIXHOUR2USEC ||
     719           0 :              zif->rtadv.lastadvreachabletime.tv_sec == 0)) {
     720           0 :                 flog_warn(
     721             :                         EC_ZEBRA_RA_PARAM_MISMATCH,
     722             :                         "%s(%u): Rx RA - our AdvReachableTime (%u) doesn't agree with %s (%u)",
     723             :                         ifp->name, ifp->ifindex, zif->rtadv.AdvReachableTime,
     724             :                         addr_str, ntohl(radvert->nd_ra_reachable));
     725           0 :                 monotime(&zif->rtadv.lastadvreachabletime);
     726             :         }
     727             : 
     728           0 :         if ((radvert->nd_ra_retransmit && zif->rtadv.AdvRetransTimer) &&
     729           0 :             (ntohl(radvert->nd_ra_retransmit) !=
     730           0 :              (unsigned int)zif->rtadv.AdvRetransTimer) &&
     731           0 :             (monotime_since(&zif->rtadv.lastadvretranstimer, NULL) >
     732           0 :                      SIXHOUR2USEC ||
     733           0 :              zif->rtadv.lastadvretranstimer.tv_sec == 0)) {
     734           0 :                 flog_warn(
     735             :                         EC_ZEBRA_RA_PARAM_MISMATCH,
     736             :                         "%s(%u): Rx RA - our AdvRetransTimer (%u) doesn't agree with %s (%u)",
     737             :                         ifp->name, ifp->ifindex, zif->rtadv.AdvRetransTimer,
     738             :                         addr_str, ntohl(radvert->nd_ra_retransmit));
     739           0 :                 monotime(&zif->rtadv.lastadvretranstimer);
     740             :         }
     741             : 
     742             :         /* Create entry for neighbor if not known. */
     743           0 :         p.family = AF_INET6;
     744           0 :         IPV6_ADDR_COPY(&p.u.prefix6, &addr->sin6_addr);
     745           0 :         p.prefixlen = IPV6_MAX_BITLEN;
     746             : 
     747           0 :         if (!nbr_connected_check(ifp, &p))
     748           0 :                 nbr_connected_add_ipv6(ifp, &addr->sin6_addr);
     749             : }
     750             : 
     751             : 
     752           0 : static void rtadv_process_packet(uint8_t *buf, unsigned int len,
     753             :                                  ifindex_t ifindex, int hoplimit,
     754             :                                  struct sockaddr_in6 *from,
     755             :                                  struct zebra_vrf *zvrf)
     756             : {
     757           0 :         struct icmp6_hdr *icmph;
     758           0 :         struct interface *ifp;
     759           0 :         struct zebra_if *zif;
     760           0 :         char addr_str[INET6_ADDRSTRLEN];
     761             : 
     762           0 :         inet_ntop(AF_INET6, &from->sin6_addr, addr_str, INET6_ADDRSTRLEN);
     763             : 
     764             :         /* Interface search. */
     765           0 :         ifp = if_lookup_by_index(ifindex, zvrf->vrf->vrf_id);
     766           0 :         if (ifp == NULL) {
     767           0 :                 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
     768             :                           "RA/RS received on unknown IF %u from %s", ifindex,
     769             :                           addr_str);
     770           0 :                 return;
     771             :         }
     772             : 
     773           0 :         if (IS_ZEBRA_DEBUG_PACKET)
     774           0 :                 zlog_debug("%s(%s:%u): Rx RA/RS len %d from %s", ifp->name,
     775             :                            ifp->vrf->name, ifp->ifindex, len, addr_str);
     776             : 
     777           0 :         if (if_is_loopback(ifp))
     778             :                 return;
     779             : 
     780             :         /* Check interface configuration. */
     781           0 :         zif = ifp->info;
     782           0 :         if (!zif->rtadv.AdvSendAdvertisements)
     783             :                 return;
     784             : 
     785             :         /* ICMP message length check. */
     786           0 :         if (len < sizeof(struct icmp6_hdr)) {
     787           0 :                 zlog_debug(
     788             :                         "%s(%s:%u): Rx RA with Invalid ICMPV6 packet length %d",
     789             :                         ifp->name, ifp->vrf->name, ifp->ifindex, len);
     790           0 :                 return;
     791             :         }
     792             : 
     793           0 :         icmph = (struct icmp6_hdr *)buf;
     794             : 
     795             :         /* ICMP message type check. */
     796           0 :         if (icmph->icmp6_type != ND_ROUTER_SOLICIT
     797           0 :             && icmph->icmp6_type != ND_ROUTER_ADVERT) {
     798           0 :                 zlog_debug("%s(%s:%u): Rx RA - Unwanted ICMPV6 message type %d",
     799             :                            ifp->name, ifp->vrf->name, ifp->ifindex,
     800             :                            icmph->icmp6_type);
     801           0 :                 return;
     802             :         }
     803             : 
     804             :         /* Hoplimit check. */
     805           0 :         if (hoplimit >= 0 && hoplimit != 255) {
     806           0 :                 zlog_debug("%s(%s:%u): Rx RA - Invalid hoplimit %d", ifp->name,
     807             :                            ifp->vrf->name, ifp->ifindex, hoplimit);
     808           0 :                 return;
     809             :         }
     810             : 
     811             :         /* Check ICMP message type. */
     812           0 :         if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
     813           0 :                 rtadv_process_solicit(ifp);
     814           0 :         else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
     815           0 :                 rtadv_process_advert(buf, len, ifp, from);
     816             : 
     817             :         return;
     818             : }
     819             : 
     820           0 : static void rtadv_read(struct event *thread)
     821             : {
     822           0 :         int sock;
     823           0 :         int len;
     824           0 :         uint8_t buf[RTADV_MSG_SIZE];
     825           0 :         struct sockaddr_in6 from;
     826           0 :         ifindex_t ifindex = 0;
     827           0 :         int hoplimit = -1;
     828           0 :         struct zebra_vrf *zvrf = EVENT_ARG(thread);
     829             : 
     830           0 :         sock = EVENT_FD(thread);
     831           0 :         zvrf->rtadv.ra_read = NULL;
     832             : 
     833             :         /* Register myself. */
     834           0 :         rtadv_event(zvrf, RTADV_READ, 0);
     835             : 
     836           0 :         len = rtadv_recv_packet(zvrf, sock, buf, sizeof(buf), &from, &ifindex,
     837             :                                 &hoplimit);
     838             : 
     839           0 :         if (len < 0) {
     840           0 :                 flog_err_sys(EC_LIB_SOCKET,
     841             :                              "RA/RS recv failed, socket %u error %s", sock,
     842             :                              safe_strerror(errno));
     843           0 :                 return;
     844             :         }
     845             : 
     846           0 :         rtadv_process_packet(buf, (unsigned)len, ifindex, hoplimit, &from, zvrf);
     847             : }
     848             : 
     849           2 : static int rtadv_make_socket(ns_id_t ns_id)
     850             : {
     851           2 :         int sock = -1;
     852           2 :         int ret = 0;
     853           2 :         struct icmp6_filter filter;
     854           2 :         int error;
     855             : 
     856           4 :         frr_with_privs(&zserv_privs) {
     857             : 
     858           2 :                 sock = ns_socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, ns_id);
     859             :                 /*
     860             :                  * with privs might set errno too if it fails save
     861             :                  * to the side
     862             :                  */
     863           2 :                 error = errno;
     864             :         }
     865             : 
     866           2 :         if (sock < 0) {
     867           0 :                 zlog_warn("RTADV socket for ns: %u failure to create: %s(%u)",
     868             :                           ns_id, safe_strerror(error), error);
     869           0 :                 return -1;
     870             :         }
     871             : 
     872           2 :         ret = setsockopt_ipv6_pktinfo(sock, 1);
     873           2 :         if (ret < 0) {
     874           0 :                 zlog_warn("RTADV failure to set Packet Information");
     875           0 :                 close(sock);
     876           0 :                 return ret;
     877             :         }
     878           2 :         ret = setsockopt_ipv6_multicast_loop(sock, 0);
     879           2 :         if (ret < 0) {
     880           0 :                 zlog_warn("RTADV failure to set multicast Loop detection");
     881           0 :                 close(sock);
     882           0 :                 return ret;
     883             :         }
     884           2 :         ret = setsockopt_ipv6_unicast_hops(sock, 255);
     885           2 :         if (ret < 0) {
     886           0 :                 zlog_warn("RTADV failure to set maximum unicast hops");
     887           0 :                 close(sock);
     888           0 :                 return ret;
     889             :         }
     890           2 :         ret = setsockopt_ipv6_multicast_hops(sock, 255);
     891           2 :         if (ret < 0) {
     892           0 :                 zlog_warn("RTADV failure to set maximum multicast hops");
     893           0 :                 close(sock);
     894           0 :                 return ret;
     895             :         }
     896           2 :         ret = setsockopt_ipv6_hoplimit(sock, 1);
     897           2 :         if (ret < 0) {
     898           0 :                 zlog_warn("RTADV failure to set maximum incoming hop limit");
     899           0 :                 close(sock);
     900           0 :                 return ret;
     901             :         }
     902             : 
     903           2 :         ICMP6_FILTER_SETBLOCKALL(&filter);
     904           2 :         ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
     905           2 :         ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
     906             : 
     907           2 :         ret = setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
     908             :                          sizeof(struct icmp6_filter));
     909           2 :         if (ret < 0) {
     910           0 :                 zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno));
     911           0 :                 close(sock);
     912           0 :                 return ret;
     913             :         }
     914             : 
     915             :         return sock;
     916             : }
     917             : 
     918           1 : static struct adv_if *adv_if_new(const char *name)
     919             : {
     920           1 :         struct adv_if *new;
     921             : 
     922           1 :         new = XCALLOC(MTYPE_ADV_IF, sizeof(struct adv_if));
     923             : 
     924           1 :         strlcpy(new->name, name, sizeof(new->name));
     925             : 
     926           1 :         return new;
     927             : }
     928             : 
     929           1 : static void adv_if_free(struct adv_if *adv_if)
     930             : {
     931           2 :         XFREE(MTYPE_ADV_IF, adv_if);
     932           0 : }
     933             : 
     934           4 : static bool adv_if_is_empty_internal(const struct adv_if_list_head *adv_if_head)
     935             : {
     936           4 :         return adv_if_list_count(adv_if_head) ? false : true;
     937             : }
     938             : 
     939           1 : static struct adv_if *adv_if_add_internal(struct adv_if_list_head *adv_if_head,
     940             :                                           const char *name)
     941             : {
     942           1 :         struct adv_if adv_if_lookup = {};
     943           1 :         struct adv_if *adv_if = NULL;
     944             : 
     945           1 :         strlcpy(adv_if_lookup.name, name, sizeof(adv_if_lookup.name));
     946           1 :         adv_if = adv_if_list_find(adv_if_head, &adv_if_lookup);
     947             : 
     948           1 :         if (adv_if != NULL)
     949             :                 return adv_if;
     950             : 
     951           1 :         adv_if = adv_if_new(adv_if_lookup.name);
     952           1 :         adv_if_list_add(adv_if_head, adv_if);
     953             : 
     954           1 :         return NULL;
     955             : }
     956             : 
     957           0 : static struct adv_if *adv_if_del_internal(struct adv_if_list_head *adv_if_head,
     958             :                                           const char *name)
     959             : {
     960           0 :         struct adv_if adv_if_lookup = {};
     961           0 :         struct adv_if *adv_if = NULL;
     962             : 
     963           0 :         strlcpy(adv_if_lookup.name, name, sizeof(adv_if_lookup.name));
     964           0 :         adv_if = adv_if_list_find(adv_if_head, &adv_if_lookup);
     965             : 
     966           0 :         if (adv_if == NULL)
     967             :                 return NULL;
     968             : 
     969           0 :         adv_if_list_del(adv_if_head, adv_if);
     970             : 
     971           0 :         return adv_if;
     972             : }
     973             : 
     974           4 : static void adv_if_clean_internal(struct adv_if_list_head *adv_if_head)
     975             : {
     976           4 :         struct adv_if *node = NULL;
     977             : 
     978           4 :         if (!adv_if_is_empty_internal(adv_if_head)) {
     979           3 :                 frr_each_safe (adv_if_list, adv_if_head, node) {
     980           1 :                         adv_if_list_del(adv_if_head, node);
     981           1 :                         adv_if_free(node);
     982             :                 }
     983             :         }
     984             : 
     985           4 :         adv_if_list_fini(adv_if_head);
     986           4 : }
     987             : 
     988             : 
     989             : /*
     990             :  * Add to list. On Success, return NULL, otherwise return already existing
     991             :  * adv_if.
     992             :  */
     993           1 : static struct adv_if *adv_if_add(struct zebra_vrf *zvrf, const char *name)
     994             : {
     995           1 :         struct adv_if *adv_if = NULL;
     996             : 
     997           1 :         adv_if = adv_if_add_internal(&zvrf->rtadv.adv_if, name);
     998             : 
     999           1 :         if (adv_if != NULL)
    1000             :                 return adv_if;
    1001             : 
    1002           1 :         if (IS_ZEBRA_DEBUG_EVENT) {
    1003           0 :                 struct vrf *vrf = zvrf->vrf;
    1004             : 
    1005           0 :                 zlog_debug("%s: %s:%u IF %s count: %zu", __func__,
    1006             :                            VRF_LOGNAME(vrf), zvrf_id(zvrf), name,
    1007             :                            adv_if_list_count(&zvrf->rtadv.adv_if));
    1008             :         }
    1009             : 
    1010             :         return NULL;
    1011             : }
    1012             : 
    1013             : /*
    1014             :  * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
    1015             :  * frees.
    1016             :  */
    1017           0 : static struct adv_if *adv_if_del(struct zebra_vrf *zvrf, const char *name)
    1018             : {
    1019           0 :         struct adv_if *adv_if = NULL;
    1020             : 
    1021           0 :         adv_if = adv_if_del_internal(&zvrf->rtadv.adv_if, name);
    1022             : 
    1023           0 :         if (adv_if == NULL)
    1024             :                 return NULL;
    1025             : 
    1026           0 :         if (IS_ZEBRA_DEBUG_EVENT) {
    1027           0 :                 struct vrf *vrf = zvrf->vrf;
    1028             : 
    1029           0 :                 zlog_debug("%s: %s:%u IF %s count: %zu", __func__,
    1030             :                            VRF_LOGNAME(vrf), zvrf_id(zvrf), name,
    1031             :                            adv_if_list_count(&zvrf->rtadv.adv_if));
    1032             :         }
    1033             : 
    1034             :         return adv_if;
    1035             : }
    1036             : 
    1037             : /*
    1038             :  * Add to list. On Success, return NULL, otherwise return already existing
    1039             :  * adv_if.
    1040             :  */
    1041           0 : static struct adv_if *adv_msec_if_add(struct zebra_vrf *zvrf, const char *name)
    1042             : {
    1043           0 :         struct adv_if *adv_if = NULL;
    1044             : 
    1045           0 :         adv_if = adv_if_add_internal(&zvrf->rtadv.adv_msec_if, name);
    1046             : 
    1047           0 :         if (adv_if != NULL)
    1048             :                 return adv_if;
    1049             : 
    1050           0 :         if (IS_ZEBRA_DEBUG_EVENT) {
    1051           0 :                 struct vrf *vrf = zvrf->vrf;
    1052             : 
    1053           0 :                 zlog_debug("%s: %s:%u IF %s count: %zu", __func__,
    1054             :                            VRF_LOGNAME(vrf), zvrf_id(zvrf), name,
    1055             :                            adv_if_list_count(&zvrf->rtadv.adv_msec_if));
    1056             :         }
    1057             : 
    1058             :         return NULL;
    1059             : }
    1060             : 
    1061             : /*
    1062             :  * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
    1063             :  * frees.
    1064             :  */
    1065           0 : static struct adv_if *adv_msec_if_del(struct zebra_vrf *zvrf, const char *name)
    1066             : {
    1067           0 :         struct adv_if *adv_if = NULL;
    1068             : 
    1069           0 :         adv_if = adv_if_del_internal(&zvrf->rtadv.adv_msec_if, name);
    1070             : 
    1071           0 :         if (adv_if == NULL)
    1072             :                 return NULL;
    1073             : 
    1074           0 :         if (IS_ZEBRA_DEBUG_EVENT) {
    1075           0 :                 struct vrf *vrf = zvrf->vrf;
    1076             : 
    1077           0 :                 zlog_debug("%s: %s:%u IF %s count: %zu", __func__,
    1078             :                            VRF_LOGNAME(vrf), zvrf_id(zvrf), name,
    1079             :                            adv_if_list_count(&zvrf->rtadv.adv_msec_if));
    1080             :         }
    1081             : 
    1082             :         return adv_if;
    1083             : }
    1084             : 
    1085             : /* Clean adv_if list, called on vrf terminate */
    1086           2 : static void adv_if_clean(struct zebra_vrf *zvrf)
    1087             : {
    1088           2 :         if (IS_ZEBRA_DEBUG_EVENT) {
    1089           0 :                 struct vrf *vrf = zvrf->vrf;
    1090             : 
    1091           0 :                 zlog_debug("%s: %s:%u count: %zu -> 0", __func__,
    1092             :                            VRF_LOGNAME(vrf), zvrf_id(zvrf),
    1093             :                            adv_if_list_count(&zvrf->rtadv.adv_if));
    1094             :         }
    1095             : 
    1096           2 :         adv_if_clean_internal(&zvrf->rtadv.adv_if);
    1097           2 : }
    1098             : 
    1099             : /* Clean adv_msec_if list, called on vrf terminate */
    1100           2 : static void adv_msec_if_clean(struct zebra_vrf *zvrf)
    1101             : {
    1102           2 :         if (IS_ZEBRA_DEBUG_EVENT) {
    1103           0 :                 struct vrf *vrf = zvrf->vrf;
    1104             : 
    1105           0 :                 zlog_debug("%s: %s:%u count: %zu -> 0", __func__,
    1106             :                            VRF_LOGNAME(vrf), zvrf_id(zvrf),
    1107             :                            adv_if_list_count(&zvrf->rtadv.adv_msec_if));
    1108             :         }
    1109             : 
    1110           2 :         adv_if_clean_internal(&zvrf->rtadv.adv_msec_if);
    1111           2 : }
    1112             : 
    1113           8 : static struct rtadv_prefix *rtadv_prefix_new(void)
    1114             : {
    1115           8 :         return XCALLOC(MTYPE_RTADV_PREFIX, sizeof(struct rtadv_prefix));
    1116             : }
    1117             : 
    1118           8 : static void rtadv_prefix_free(struct rtadv_prefix *rtadv_prefix)
    1119             : {
    1120           8 :         XFREE(MTYPE_RTADV_PREFIX, rtadv_prefix);
    1121           0 : }
    1122             : 
    1123           8 : static struct rtadv_prefix *rtadv_prefix_get(struct rtadv_prefixes_head *list,
    1124             :                                              struct prefix_ipv6 *p)
    1125             : {
    1126           8 :         struct rtadv_prefix *rprefix, ref;
    1127             : 
    1128           8 :         ref.prefix = *p;
    1129             : 
    1130           8 :         rprefix = rtadv_prefixes_find(list, &ref);
    1131           8 :         if (rprefix)
    1132             :                 return rprefix;
    1133             : 
    1134           8 :         rprefix = rtadv_prefix_new();
    1135           8 :         memcpy(&rprefix->prefix, p, sizeof(struct prefix_ipv6));
    1136           8 :         rtadv_prefixes_add(list, rprefix);
    1137             : 
    1138           8 :         return rprefix;
    1139             : }
    1140             : 
    1141           8 : static void rtadv_prefix_set_defaults(struct rtadv_prefix *rp)
    1142             : {
    1143           8 :         rp->AdvAutonomousFlag = 1;
    1144           8 :         rp->AdvOnLinkFlag = 1;
    1145           8 :         rp->AdvRouterAddressFlag = 0;
    1146           8 :         rp->AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
    1147           8 :         rp->AdvValidLifetime = RTADV_VALID_LIFETIME;
    1148           8 : }
    1149             : 
    1150           8 : static void rtadv_prefix_set(struct zebra_if *zif, struct rtadv_prefix *rp)
    1151             : {
    1152           8 :         struct rtadv_prefix *rprefix;
    1153             : 
    1154           8 :         rprefix = rtadv_prefix_get(zif->rtadv.prefixes, &rp->prefix);
    1155             : 
    1156             :         /*
    1157             :          * Set parameters based on where the prefix is created.
    1158             :          * If auto-created based on kernel address addition, set the
    1159             :          * default values.  If created from a manual "ipv6 nd prefix"
    1160             :          * command, take the parameters from the manual command. Note
    1161             :          * that if the manual command exists, the default values will
    1162             :          * not overwrite the manual values.
    1163             :          */
    1164           8 :         if (rp->AdvPrefixCreate == PREFIX_SRC_MANUAL) {
    1165           0 :                 if (rprefix->AdvPrefixCreate == PREFIX_SRC_AUTO)
    1166           0 :                         rprefix->AdvPrefixCreate = PREFIX_SRC_BOTH;
    1167             :                 else
    1168           0 :                         rprefix->AdvPrefixCreate = PREFIX_SRC_MANUAL;
    1169             : 
    1170           0 :                 rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
    1171           0 :                 rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
    1172           0 :                 rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
    1173           0 :                 rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
    1174           0 :                 rprefix->AdvValidLifetime = rp->AdvValidLifetime;
    1175           8 :         } else if (rp->AdvPrefixCreate == PREFIX_SRC_AUTO) {
    1176           8 :                 if (rprefix->AdvPrefixCreate == PREFIX_SRC_MANUAL)
    1177           0 :                         rprefix->AdvPrefixCreate = PREFIX_SRC_BOTH;
    1178             :                 else {
    1179           8 :                         rprefix->AdvPrefixCreate = PREFIX_SRC_AUTO;
    1180           8 :                         rtadv_prefix_set_defaults(rprefix);
    1181             :                 }
    1182             :         }
    1183           8 : }
    1184             : 
    1185           8 : static int rtadv_prefix_reset(struct zebra_if *zif, struct rtadv_prefix *rp)
    1186             : {
    1187           8 :         struct rtadv_prefix *rprefix;
    1188             : 
    1189           8 :         rprefix = rtadv_prefixes_find(zif->rtadv.prefixes, rp);
    1190           8 :         if (rprefix != NULL) {
    1191             : 
    1192             :                 /*
    1193             :                  * When deleting an address from the list, need to take care
    1194             :                  * it wasn't defined both automatically via kernel
    1195             :                  * address addition as well as manually by vtysh cli. If both,
    1196             :                  * we don't actually delete but may change the parameters
    1197             :                  * back to default if a manually defined entry is deleted.
    1198             :                  */
    1199           8 :                 if (rp->AdvPrefixCreate == PREFIX_SRC_MANUAL) {
    1200           0 :                         if (rprefix->AdvPrefixCreate == PREFIX_SRC_BOTH) {
    1201           0 :                                 rprefix->AdvPrefixCreate = PREFIX_SRC_AUTO;
    1202           0 :                                 rtadv_prefix_set_defaults(rprefix);
    1203           0 :                                 return 1;
    1204             :                         }
    1205           8 :                 } else if (rp->AdvPrefixCreate == PREFIX_SRC_AUTO) {
    1206           8 :                         if (rprefix->AdvPrefixCreate == PREFIX_SRC_BOTH) {
    1207           0 :                                 rprefix->AdvPrefixCreate = PREFIX_SRC_MANUAL;
    1208           0 :                                 return 1;
    1209             :                         }
    1210             :                 }
    1211             : 
    1212           8 :                 rtadv_prefixes_del(zif->rtadv.prefixes, rprefix);
    1213           8 :                 rtadv_prefix_free(rprefix);
    1214           8 :                 return 1;
    1215             :         } else
    1216             :                 return 0;
    1217             : }
    1218             : 
    1219             : /* Add IPv6 prefixes learned from the kernel to the RA prefix list */
    1220           8 : void rtadv_add_prefix(struct zebra_if *zif, const struct prefix_ipv6 *p)
    1221             : {
    1222           8 :         struct rtadv_prefix rp;
    1223             : 
    1224           8 :         rp.prefix = *p;
    1225           8 :         apply_mask_ipv6(&rp.prefix);
    1226           8 :         rp.AdvPrefixCreate = PREFIX_SRC_AUTO;
    1227           8 :         rtadv_prefix_set(zif, &rp);
    1228           8 : }
    1229             : 
    1230             : /* Delete IPv6 prefixes removed by the kernel from the RA prefix list */
    1231           0 : void rtadv_delete_prefix(struct zebra_if *zif, const struct prefix *p)
    1232             : {
    1233           0 :         struct rtadv_prefix rp;
    1234             : 
    1235           0 :         rp.prefix = *((struct prefix_ipv6 *)p);
    1236           0 :         apply_mask_ipv6(&rp.prefix);
    1237           0 :         rp.AdvPrefixCreate = PREFIX_SRC_AUTO;
    1238           0 :         rtadv_prefix_reset(zif, &rp);
    1239           0 : }
    1240             : 
    1241           1 : static void rtadv_start_interface_events(struct zebra_vrf *zvrf,
    1242             :                                          struct zebra_if *zif)
    1243             : {
    1244           1 :         struct adv_if *adv_if = NULL;
    1245             : 
    1246           1 :         if (zif->ifp->ifindex == IFINDEX_INTERNAL) {
    1247           0 :                 if (IS_ZEBRA_DEBUG_EVENT)
    1248           0 :                         zlog_debug(
    1249             :                                 "%s(%s) has not configured an ifindex yet, delaying until we have one",
    1250             :                                 zif->ifp->name, zvrf->vrf->name);
    1251           0 :                 return;
    1252             :         }
    1253             : 
    1254           1 :         adv_if = adv_if_add(zvrf, zif->ifp->name);
    1255           1 :         if (adv_if != NULL)
    1256             :                 return; /* Already added */
    1257             : 
    1258           1 :         if_join_all_router(zvrf->rtadv.sock, zif->ifp);
    1259             : 
    1260           1 :         if (adv_if_list_count(&zvrf->rtadv.adv_if) == 1)
    1261           1 :                 rtadv_event(zvrf, RTADV_START, 0);
    1262             : }
    1263             : 
    1264           2 : static void ipv6_nd_suppress_ra_set(struct interface *ifp,
    1265             :                                     enum ipv6_nd_suppress_ra_status status)
    1266             : {
    1267           2 :         struct zebra_if *zif;
    1268           2 :         struct zebra_vrf *zvrf;
    1269           2 :         struct adv_if *adv_if = NULL;
    1270             : 
    1271           2 :         zif = ifp->info;
    1272             : 
    1273           2 :         zvrf = rtadv_interface_get_zvrf(ifp);
    1274             : 
    1275           2 :         if (status == RA_SUPPRESS) {
    1276             :                 /* RA is currently enabled */
    1277           0 :                 if (zif->rtadv.AdvSendAdvertisements) {
    1278           0 :                         rtadv_send_packet(zvrf->rtadv.sock, ifp, RA_SUPPRESS);
    1279           0 :                         zif->rtadv.AdvSendAdvertisements = 0;
    1280           0 :                         zif->rtadv.AdvIntervalTimer = 0;
    1281             : 
    1282           0 :                         adv_if = adv_if_del(zvrf, ifp->name);
    1283           0 :                         if (adv_if == NULL)
    1284             :                                 return; /* Nothing to delete */
    1285             : 
    1286           0 :                         adv_if_free(adv_if);
    1287             : 
    1288           0 :                         if_leave_all_router(zvrf->rtadv.sock, ifp);
    1289             : 
    1290           0 :                         if (adv_if_list_count(&zvrf->rtadv.adv_if) == 0)
    1291           0 :                                 rtadv_event(zvrf, RTADV_STOP, 0);
    1292             :                 }
    1293             :         } else {
    1294           2 :                 if (!zif->rtadv.AdvSendAdvertisements) {
    1295           1 :                         zif->rtadv.AdvSendAdvertisements = 1;
    1296           1 :                         zif->rtadv.AdvIntervalTimer = 0;
    1297           1 :                         if ((zif->rtadv.MaxRtrAdvInterval >= 1000)
    1298           1 :                             && zif->rtadv.UseFastRexmit) {
    1299             :                                 /*
    1300             :                                  * Enable Fast RA only when RA interval is in
    1301             :                                  * secs and Fast RA retransmit is enabled
    1302             :                                  */
    1303           1 :                                 zif->rtadv.inFastRexmit = 1;
    1304           1 :                                 zif->rtadv.NumFastReXmitsRemain =
    1305             :                                         RTADV_NUM_FAST_REXMITS;
    1306             :                         }
    1307             : 
    1308           1 :                         rtadv_start_interface_events(zvrf, zif);
    1309             :                 }
    1310             :         }
    1311             : }
    1312             : 
    1313             : /*
    1314             :  * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
    1315             :  * Note that while the client could request RA on an interface on which the
    1316             :  * operator has not enabled RA, RA won't be disabled upon client request
    1317             :  * if the operator has explicitly enabled RA. The enable request can also
    1318             :  * specify a RA interval (in seconds).
    1319             :  */
    1320           2 : static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
    1321             : {
    1322           2 :         struct stream *s;
    1323           2 :         ifindex_t ifindex;
    1324           2 :         struct interface *ifp;
    1325           2 :         struct zebra_if *zif;
    1326           2 :         uint32_t ra_interval;
    1327             : 
    1328           2 :         s = msg;
    1329             : 
    1330             :         /* Get interface index and RA interval. */
    1331           2 :         STREAM_GETL(s, ifindex);
    1332           2 :         STREAM_GETL(s, ra_interval);
    1333             : 
    1334           2 :         if (IS_ZEBRA_DEBUG_EVENT) {
    1335           0 :                 struct vrf *vrf = zvrf->vrf;
    1336             : 
    1337           0 :                 zlog_debug("%s:%u: IF %u RA %s from client %s, interval %ums",
    1338             :                            VRF_LOGNAME(vrf), zvrf_id(zvrf), ifindex,
    1339             :                            enable ? "enable" : "disable",
    1340             :                            zebra_route_string(client->proto), ra_interval);
    1341             :         }
    1342             : 
    1343             :         /* Locate interface and check VRF match. */
    1344           2 :         ifp = if_lookup_by_index(ifindex, zvrf->vrf->vrf_id);
    1345           2 :         if (!ifp) {
    1346           0 :                 struct vrf *vrf = zvrf->vrf;
    1347             : 
    1348           0 :                 flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
    1349             :                           "%s:%u: IF %u RA %s client %s - interface unknown",
    1350             :                           VRF_LOGNAME(vrf), zvrf_id(zvrf), ifindex,
    1351             :                           enable ? "enable" : "disable",
    1352             :                           zebra_route_string(client->proto));
    1353           0 :                 return;
    1354             :         }
    1355           2 :         if (vrf_is_backend_netns() && ifp->vrf->vrf_id != zvrf_id(zvrf)) {
    1356           0 :                 zlog_debug(
    1357             :                         "%s:%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
    1358             :                         ifp->vrf->name, zvrf_id(zvrf), ifindex,
    1359             :                         enable ? "enable" : "disable",
    1360             :                         zebra_route_string(client->proto), ifp->vrf->vrf_id);
    1361           0 :                 return;
    1362             :         }
    1363             : 
    1364           2 :         zif = ifp->info;
    1365           2 :         if (enable) {
    1366           2 :                 if (!CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
    1367           1 :                         interfaces_configured_for_ra_from_bgp++;
    1368             : 
    1369           2 :                 SET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED);
    1370           2 :                 ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
    1371           2 :                 if (ra_interval
    1372           2 :                     && (ra_interval * 1000) < (unsigned int) zif->rtadv.MaxRtrAdvInterval
    1373           1 :                     && !CHECK_FLAG(zif->rtadv.ra_configured,
    1374             :                                    VTY_RA_INTERVAL_CONFIGURED))
    1375           1 :                         zif->rtadv.MaxRtrAdvInterval = ra_interval * 1000;
    1376             :         } else {
    1377           0 :                 if (CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
    1378           0 :                         interfaces_configured_for_ra_from_bgp--;
    1379             : 
    1380           0 :                 UNSET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED);
    1381           0 :                 if (!CHECK_FLAG(zif->rtadv.ra_configured,
    1382             :                                 VTY_RA_INTERVAL_CONFIGURED))
    1383           0 :                         zif->rtadv.MaxRtrAdvInterval =
    1384             :                                 RTADV_MAX_RTR_ADV_INTERVAL;
    1385           0 :                 if (!CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED))
    1386           0 :                         ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
    1387             :         }
    1388           0 : stream_failure:
    1389             :         return;
    1390             : }
    1391             : 
    1392             : /*
    1393             :  * send router lifetime value of zero in RAs on this interface since we're
    1394             :  * ceasing to advertise and want to let our neighbors know.
    1395             :  * RFC 4861 secion 6.2.5
    1396             :  */
    1397           8 : void rtadv_stop_ra(struct interface *ifp)
    1398             : {
    1399           8 :         struct zebra_if *zif;
    1400           8 :         struct zebra_vrf *zvrf;
    1401             : 
    1402           8 :         zif = ifp->info;
    1403           8 :         zvrf = rtadv_interface_get_zvrf(ifp);
    1404             : 
    1405           8 :         if (zif->rtadv.AdvSendAdvertisements)
    1406           1 :                 rtadv_send_packet(zvrf->rtadv.sock, ifp, RA_SUPPRESS);
    1407           8 : }
    1408             : 
    1409             : /*
    1410             :  * Send router lifetime value of zero in RAs on all interfaces since we're
    1411             :  * ceasing to advertise globally and want to let all of our neighbors know
    1412             :  * RFC 4861 secion 6.2.5
    1413             :  *
    1414             :  * Delete all ipv6 global prefixes added to the router advertisement prefix
    1415             :  * lists prior to ceasing.
    1416             :  */
    1417           2 : void rtadv_stop_ra_all(void)
    1418             : {
    1419           2 :         struct vrf *vrf;
    1420           2 :         struct interface *ifp;
    1421           2 :         struct zebra_if *zif;
    1422           2 :         struct rtadv_prefix *rprefix;
    1423             : 
    1424           6 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
    1425          10 :                 FOR_ALL_INTERFACES (vrf, ifp) {
    1426           8 :                         zif = ifp->info;
    1427             : 
    1428          32 :                         frr_each_safe (rtadv_prefixes, zif->rtadv.prefixes,
    1429             :                                        rprefix)
    1430           8 :                                 rtadv_prefix_reset(zif, rprefix);
    1431             : 
    1432           8 :                         rtadv_stop_ra(ifp);
    1433             :                 }
    1434           2 : }
    1435             : 
    1436           0 : void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS)
    1437             : {
    1438           0 :         zebra_interface_radv_set(client, hdr, msg, zvrf, 0);
    1439           0 : }
    1440           2 : void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS)
    1441             : {
    1442           2 :         zebra_interface_radv_set(client, hdr, msg, zvrf, 1);
    1443           2 : }
    1444             : 
    1445           0 : static void show_zvrf_rtadv_adv_if_helper(struct vty *vty,
    1446             :                                           struct adv_if_list_head *adv_if_head)
    1447             : {
    1448           0 :         struct adv_if *node = NULL;
    1449             : 
    1450           0 :         if (!adv_if_is_empty_internal(adv_if_head)) {
    1451           0 :                 frr_each (adv_if_list, adv_if_head, node) {
    1452           0 :                         vty_out(vty, "    %s\n", node->name);
    1453             :                 }
    1454             :         }
    1455             : 
    1456           0 :         vty_out(vty, "\n");
    1457           0 : }
    1458             : 
    1459           0 : static void show_zvrf_rtadv_helper(struct vty *vty, struct zebra_vrf *zvrf)
    1460             : {
    1461           0 :         vty_out(vty, "VRF: %s\n", zvrf_name(zvrf));
    1462           0 :         vty_out(vty, "  Interfaces:\n");
    1463           0 :         show_zvrf_rtadv_adv_if_helper(vty, &zvrf->rtadv.adv_if);
    1464             : 
    1465           0 :         vty_out(vty, "  Interfaces(msec):\n");
    1466           0 :         show_zvrf_rtadv_adv_if_helper(vty, &zvrf->rtadv.adv_msec_if);
    1467           0 : }
    1468             : 
    1469           0 : DEFPY(show_ipv6_nd_ra_if, show_ipv6_nd_ra_if_cmd,
    1470             :       "show ipv6 nd ra-interfaces [vrf<NAME$vrf_name|all$vrf_all>]",
    1471             :       SHOW_STR IP6_STR
    1472             :       "Neighbor discovery\n"
    1473             :       "Route Advertisement Interfaces\n" VRF_FULL_CMD_HELP_STR)
    1474             : {
    1475           0 :         struct zebra_vrf *zvrf = NULL;
    1476             : 
    1477           0 :         if (!vrf_is_backend_netns() && (vrf_name || vrf_all)) {
    1478           0 :                 vty_out(vty,
    1479             :                         "%% VRF subcommand only applicable for netns-based vrfs.\n");
    1480           0 :                 return CMD_WARNING;
    1481             :         }
    1482             : 
    1483           0 :         if (vrf_all) {
    1484           0 :                 struct vrf *vrf;
    1485             : 
    1486           0 :                 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
    1487           0 :                         struct zebra_vrf *zvrf;
    1488             : 
    1489           0 :                         zvrf = vrf->info;
    1490           0 :                         if (!zvrf)
    1491           0 :                                 continue;
    1492             : 
    1493           0 :                         show_zvrf_rtadv_helper(vty, zvrf);
    1494             :                 }
    1495             : 
    1496             :                 return CMD_SUCCESS;
    1497             :         }
    1498             : 
    1499           0 :         if (vrf_name)
    1500           0 :                 zvrf = zebra_vrf_lookup_by_name(vrf_name);
    1501             :         else
    1502           0 :                 zvrf = zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME);
    1503             : 
    1504           0 :         if (!zvrf) {
    1505           0 :                 vty_out(vty, "%% VRF '%s' specified does not exist\n",
    1506             :                         vrf_name);
    1507           0 :                 return CMD_WARNING;
    1508             :         }
    1509             : 
    1510           0 :         show_zvrf_rtadv_helper(vty, zvrf);
    1511             : 
    1512           0 :         return CMD_SUCCESS;
    1513             : }
    1514             : 
    1515           0 : DEFUN (ipv6_nd_ra_fast_retrans,
    1516             :         ipv6_nd_ra_fast_retrans_cmd,
    1517             :         "ipv6 nd ra-fast-retrans",
    1518             :         "Interface IPv6 config commands\n"
    1519             :         "Neighbor discovery\n"
    1520             :         "Fast retransmit of RA packets\n")
    1521             : {
    1522           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1523           0 :         struct zebra_if *zif = ifp->info;
    1524             : 
    1525           0 :         if (if_is_loopback(ifp)) {
    1526           0 :                 vty_out(vty,
    1527             :                         "Cannot configure IPv6 Router Advertisements on this  interface\n");
    1528           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1529             :         }
    1530             : 
    1531           0 :         zif->rtadv.UseFastRexmit = true;
    1532             : 
    1533           0 :         return CMD_SUCCESS;
    1534             : }
    1535             : 
    1536           0 : DEFUN (no_ipv6_nd_ra_fast_retrans,
    1537             :         no_ipv6_nd_ra_fast_retrans_cmd,
    1538             :         "no ipv6 nd ra-fast-retrans",
    1539             :         NO_STR
    1540             :         "Interface IPv6 config commands\n"
    1541             :         "Neighbor discovery\n"
    1542             :         "Fast retransmit of RA packets\n")
    1543             : {
    1544           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1545           0 :         struct zebra_if *zif = ifp->info;
    1546             : 
    1547           0 :         if (if_is_loopback(ifp)) {
    1548           0 :                 vty_out(vty,
    1549             :                         "Cannot configure IPv6 Router Advertisements on this  interface\n");
    1550           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1551             :         }
    1552             : 
    1553           0 :         zif->rtadv.UseFastRexmit = false;
    1554             : 
    1555           0 :         return CMD_SUCCESS;
    1556             : }
    1557             : 
    1558           0 : DEFPY (ipv6_nd_ra_hop_limit,
    1559             :        ipv6_nd_ra_hop_limit_cmd,
    1560             :        "ipv6 nd ra-hop-limit (0-255)$hopcount",
    1561             :        "Interface IPv6 config commands\n"
    1562             :        "Neighbor discovery\n"
    1563             :        "Advertisement Hop Limit\n"
    1564             :        "Advertisement Hop Limit in hops (default:64)\n")
    1565             : {
    1566           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1567           0 :         struct zebra_if *zif = ifp->info;
    1568             : 
    1569           0 :         if (if_is_loopback(ifp)) {
    1570           0 :                 vty_out(vty,
    1571             :                         "Cannot configure IPv6 Router Advertisements on this interface\n");
    1572           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1573             :         }
    1574             : 
    1575           0 :         zif->rtadv.AdvCurHopLimit = hopcount;
    1576             : 
    1577           0 :         return CMD_SUCCESS;
    1578             : }
    1579             : 
    1580           0 : DEFPY (no_ipv6_nd_ra_hop_limit,
    1581             :        no_ipv6_nd_ra_hop_limit_cmd,
    1582             :        "no ipv6 nd ra-hop-limit [(0-255)]",
    1583             :        NO_STR
    1584             :        "Interface IPv6 config commands\n"
    1585             :        "Neighbor discovery\n"
    1586             :        "Advertisement Hop Limit\n"
    1587             :        "Advertisement Hop Limit in hops\n")
    1588             : {
    1589           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1590           0 :         struct zebra_if *zif = ifp->info;
    1591             : 
    1592           0 :         if (if_is_loopback(ifp)) {
    1593           0 :                 vty_out(vty,
    1594             :                         "Cannot configure IPv6 Router Advertisements on this interface\n");
    1595           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1596             :         }
    1597             : 
    1598           0 :         zif->rtadv.AdvCurHopLimit = RTADV_DEFAULT_HOPLIMIT;
    1599             : 
    1600           0 :         return CMD_SUCCESS;
    1601             : }
    1602             : 
    1603           0 : DEFPY (ipv6_nd_ra_retrans_interval,
    1604             :        ipv6_nd_ra_retrans_interval_cmd,
    1605             :        "ipv6 nd ra-retrans-interval (0-4294967295)$interval",
    1606             :        "Interface IPv6 config commands\n"
    1607             :        "Neighbor discovery\n"
    1608             :        "Advertisement Retransmit Interval\n"
    1609             :        "Advertisement Retransmit Interval in msec\n")
    1610             : {
    1611           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1612           0 :         struct zebra_if *zif = ifp->info;
    1613             : 
    1614           0 :         if (if_is_loopback(ifp)) {
    1615           0 :                 vty_out(vty,
    1616             :                         "Cannot configure IPv6 Router Advertisements on loopback interface\n");
    1617           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1618             :         }
    1619             : 
    1620           0 :         zif->rtadv.AdvRetransTimer = interval;
    1621             : 
    1622           0 :         return CMD_SUCCESS;
    1623             : }
    1624             : 
    1625           0 : DEFPY (no_ipv6_nd_ra_retrans_interval,
    1626             :        no_ipv6_nd_ra_retrans_interval_cmd,
    1627             :        "no ipv6 nd ra-retrans-interval [(0-4294967295)]",
    1628             :        NO_STR
    1629             :        "Interface IPv6 config commands\n"
    1630             :        "Neighbor discovery\n"
    1631             :        "Advertisement Retransmit Interval\n"
    1632             :        "Advertisement Retransmit Interval in msec\n")
    1633             : {
    1634           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1635           0 :         struct zebra_if *zif = ifp->info;
    1636             : 
    1637           0 :         if (if_is_loopback(ifp)) {
    1638           0 :                 vty_out(vty,
    1639             :                         "Cannot remove IPv6 Router Advertisements on loopback interface\n");
    1640           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1641             :         }
    1642             : 
    1643           0 :         zif->rtadv.AdvRetransTimer = 0;
    1644             : 
    1645           0 :         return CMD_SUCCESS;
    1646             : }
    1647             : 
    1648           0 : DEFUN (ipv6_nd_suppress_ra,
    1649             :        ipv6_nd_suppress_ra_cmd,
    1650             :        "ipv6 nd suppress-ra",
    1651             :        "Interface IPv6 config commands\n"
    1652             :        "Neighbor discovery\n"
    1653             :        "Suppress Router Advertisement\n")
    1654             : {
    1655           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1656           0 :         struct zebra_if *zif = ifp->info;
    1657             : 
    1658           0 :         if (if_is_loopback(ifp)) {
    1659           0 :                 vty_out(vty,
    1660             :                         "Cannot configure IPv6 Router Advertisements on this  interface\n");
    1661           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1662             :         }
    1663             : 
    1664           0 :         if (!CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
    1665           0 :                 ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
    1666             : 
    1667           0 :         UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
    1668           0 :         return CMD_SUCCESS;
    1669             : }
    1670             : 
    1671           0 : DEFUN (no_ipv6_nd_suppress_ra,
    1672             :        no_ipv6_nd_suppress_ra_cmd,
    1673             :        "no ipv6 nd suppress-ra",
    1674             :        NO_STR
    1675             :        "Interface IPv6 config commands\n"
    1676             :        "Neighbor discovery\n"
    1677             :        "Suppress Router Advertisement\n")
    1678             : {
    1679           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1680           0 :         struct zebra_if *zif = ifp->info;
    1681             : 
    1682           0 :         if (if_is_loopback(ifp)) {
    1683           0 :                 vty_out(vty,
    1684             :                         "Cannot configure IPv6 Router Advertisements on this interface\n");
    1685           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1686             :         }
    1687             : 
    1688           0 :         ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
    1689           0 :         SET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
    1690           0 :         return CMD_SUCCESS;
    1691             : }
    1692             : 
    1693           0 : DEFUN (ipv6_nd_ra_interval_msec,
    1694             :        ipv6_nd_ra_interval_msec_cmd,
    1695             :        "ipv6 nd ra-interval msec (70-1800000)",
    1696             :        "Interface IPv6 config commands\n"
    1697             :        "Neighbor discovery\n"
    1698             :        "Router Advertisement interval\n"
    1699             :        "Router Advertisement interval in milliseconds\n"
    1700             :        "Router Advertisement interval in milliseconds\n")
    1701             : {
    1702           0 :         int idx_number = 4;
    1703           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1704           0 :         unsigned interval;
    1705           0 :         struct zebra_if *zif = ifp->info;
    1706           0 :         struct zebra_vrf *zvrf;
    1707           0 :         struct adv_if *adv_if;
    1708             : 
    1709           0 :         zvrf = rtadv_interface_get_zvrf(ifp);
    1710             : 
    1711           0 :         interval = strtoul(argv[idx_number]->arg, NULL, 10);
    1712           0 :         if ((zif->rtadv.AdvDefaultLifetime != -1
    1713           0 :              && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000)) {
    1714           0 :                 vty_out(vty,
    1715             :                         "This ra-interval would conflict with configured ra-lifetime!\n");
    1716           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1717             :         }
    1718             : 
    1719           0 :         if (zif->rtadv.MaxRtrAdvInterval % 1000) {
    1720           0 :                 adv_if = adv_msec_if_del(zvrf, ifp->name);
    1721           0 :                 if (adv_if != NULL)
    1722           0 :                         adv_if_free(adv_if);
    1723             :         }
    1724             : 
    1725           0 :         if (interval % 1000)
    1726           0 :                 (void)adv_msec_if_add(zvrf, ifp->name);
    1727             : 
    1728           0 :         SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
    1729           0 :         zif->rtadv.MaxRtrAdvInterval = interval;
    1730           0 :         zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
    1731           0 :         zif->rtadv.AdvIntervalTimer = 0;
    1732             : 
    1733           0 :         return CMD_SUCCESS;
    1734             : }
    1735             : 
    1736           0 : DEFUN (ipv6_nd_ra_interval,
    1737             :        ipv6_nd_ra_interval_cmd,
    1738             :        "ipv6 nd ra-interval (1-1800)",
    1739             :        "Interface IPv6 config commands\n"
    1740             :        "Neighbor discovery\n"
    1741             :        "Router Advertisement interval\n"
    1742             :        "Router Advertisement interval in seconds\n")
    1743             : {
    1744           0 :         int idx_number = 3;
    1745           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1746           0 :         unsigned interval;
    1747           0 :         struct zebra_if *zif = ifp->info;
    1748           0 :         struct zebra_vrf *zvrf;
    1749           0 :         struct adv_if *adv_if;
    1750             : 
    1751           0 :         zvrf = rtadv_interface_get_zvrf(ifp);
    1752             : 
    1753           0 :         interval = strtoul(argv[idx_number]->arg, NULL, 10);
    1754           0 :         if ((zif->rtadv.AdvDefaultLifetime != -1
    1755           0 :              && interval > (unsigned)zif->rtadv.AdvDefaultLifetime)) {
    1756           0 :                 vty_out(vty,
    1757             :                         "This ra-interval would conflict with configured ra-lifetime!\n");
    1758           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1759             :         }
    1760             : 
    1761           0 :         if (zif->rtadv.MaxRtrAdvInterval % 1000) {
    1762           0 :                 adv_if = adv_msec_if_del(zvrf, ifp->name);
    1763           0 :                 if (adv_if != NULL)
    1764           0 :                         adv_if_free(adv_if);
    1765             :         }
    1766             : 
    1767             :         /* convert to milliseconds */
    1768           0 :         interval = interval * 1000;
    1769             : 
    1770           0 :         SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
    1771           0 :         zif->rtadv.MaxRtrAdvInterval = interval;
    1772           0 :         zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
    1773           0 :         zif->rtadv.AdvIntervalTimer = 0;
    1774             : 
    1775           0 :         return CMD_SUCCESS;
    1776             : }
    1777             : 
    1778           0 : DEFUN (no_ipv6_nd_ra_interval,
    1779             :        no_ipv6_nd_ra_interval_cmd,
    1780             :        "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
    1781             :        NO_STR
    1782             :        "Interface IPv6 config commands\n"
    1783             :        "Neighbor discovery\n"
    1784             :        "Router Advertisement interval\n"
    1785             :        "Router Advertisement interval in seconds\n"
    1786             :        "Specify millisecond router advertisement interval\n"
    1787             :        "Router Advertisement interval in milliseconds\n")
    1788             : {
    1789           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1790           0 :         struct zebra_if *zif = ifp->info;
    1791           0 :         struct zebra_vrf *zvrf = NULL;
    1792           0 :         struct adv_if *adv_if;
    1793             : 
    1794           0 :         zvrf = rtadv_interface_get_zvrf(ifp);
    1795             : 
    1796           0 :         if (zif->rtadv.MaxRtrAdvInterval % 1000) {
    1797           0 :                 adv_if = adv_msec_if_del(zvrf, ifp->name);
    1798           0 :                 if (adv_if != NULL)
    1799           0 :                         adv_if_free(adv_if);
    1800             :         }
    1801             : 
    1802           0 :         UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
    1803             : 
    1804           0 :         if (CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
    1805           0 :                 zif->rtadv.MaxRtrAdvInterval = 10000;
    1806             :         else
    1807           0 :                 zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
    1808             : 
    1809           0 :         zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
    1810           0 :         zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
    1811             : 
    1812           0 :         return CMD_SUCCESS;
    1813             : }
    1814             : 
    1815           0 : DEFUN (ipv6_nd_ra_lifetime,
    1816             :        ipv6_nd_ra_lifetime_cmd,
    1817             :        "ipv6 nd ra-lifetime (0-9000)",
    1818             :        "Interface IPv6 config commands\n"
    1819             :        "Neighbor discovery\n"
    1820             :        "Router lifetime\n"
    1821             :        "Router lifetime in seconds (0 stands for a non-default gw)\n")
    1822             : {
    1823           0 :         int idx_number = 3;
    1824           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1825           0 :         struct zebra_if *zif = ifp->info;
    1826           0 :         int lifetime;
    1827             : 
    1828           0 :         lifetime = strtoul(argv[idx_number]->arg, NULL, 10);
    1829             : 
    1830             :         /* The value to be placed in the Router Lifetime field
    1831             :          * of Router Advertisements sent from the interface,
    1832             :          * in seconds.  MUST be either zero or between
    1833             :          * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
    1834           0 :         if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval)) {
    1835           0 :                 vty_out(vty,
    1836             :                         "This ra-lifetime would conflict with configured ra-interval\n");
    1837           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1838             :         }
    1839             : 
    1840           0 :         zif->rtadv.AdvDefaultLifetime = lifetime;
    1841             : 
    1842           0 :         return CMD_SUCCESS;
    1843             : }
    1844             : 
    1845           0 : DEFUN (no_ipv6_nd_ra_lifetime,
    1846             :        no_ipv6_nd_ra_lifetime_cmd,
    1847             :        "no ipv6 nd ra-lifetime [(0-9000)]",
    1848             :        NO_STR
    1849             :        "Interface IPv6 config commands\n"
    1850             :        "Neighbor discovery\n"
    1851             :        "Router lifetime\n"
    1852             :        "Router lifetime in seconds (0 stands for a non-default gw)\n")
    1853             : {
    1854           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1855           0 :         struct zebra_if *zif = ifp->info;
    1856             : 
    1857           0 :         zif->rtadv.AdvDefaultLifetime = -1;
    1858             : 
    1859           0 :         return CMD_SUCCESS;
    1860             : }
    1861             : 
    1862           0 : DEFUN (ipv6_nd_reachable_time,
    1863             :        ipv6_nd_reachable_time_cmd,
    1864             :        "ipv6 nd reachable-time (1-3600000)",
    1865             :        "Interface IPv6 config commands\n"
    1866             :        "Neighbor discovery\n"
    1867             :        "Reachable time\n"
    1868             :        "Reachable time in milliseconds\n")
    1869             : {
    1870           0 :         int idx_number = 3;
    1871           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1872           0 :         struct zebra_if *zif = ifp->info;
    1873           0 :         zif->rtadv.AdvReachableTime = strtoul(argv[idx_number]->arg, NULL, 10);
    1874           0 :         return CMD_SUCCESS;
    1875             : }
    1876             : 
    1877           0 : DEFUN (no_ipv6_nd_reachable_time,
    1878             :        no_ipv6_nd_reachable_time_cmd,
    1879             :        "no ipv6 nd reachable-time [(1-3600000)]",
    1880             :        NO_STR
    1881             :        "Interface IPv6 config commands\n"
    1882             :        "Neighbor discovery\n"
    1883             :        "Reachable time\n"
    1884             :        "Reachable time in milliseconds\n")
    1885             : {
    1886           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1887           0 :         struct zebra_if *zif = ifp->info;
    1888             : 
    1889           0 :         zif->rtadv.AdvReachableTime = 0;
    1890             : 
    1891           0 :         return CMD_SUCCESS;
    1892             : }
    1893             : 
    1894           0 : DEFUN (ipv6_nd_homeagent_preference,
    1895             :        ipv6_nd_homeagent_preference_cmd,
    1896             :        "ipv6 nd home-agent-preference (0-65535)",
    1897             :        "Interface IPv6 config commands\n"
    1898             :        "Neighbor discovery\n"
    1899             :        "Home Agent preference\n"
    1900             :        "preference value (default is 0, least preferred)\n")
    1901             : {
    1902           0 :         int idx_number = 3;
    1903           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1904           0 :         struct zebra_if *zif = ifp->info;
    1905           0 :         zif->rtadv.HomeAgentPreference =
    1906           0 :                 strtoul(argv[idx_number]->arg, NULL, 10);
    1907           0 :         return CMD_SUCCESS;
    1908             : }
    1909             : 
    1910           0 : DEFUN (no_ipv6_nd_homeagent_preference,
    1911             :        no_ipv6_nd_homeagent_preference_cmd,
    1912             :        "no ipv6 nd home-agent-preference [(0-65535)]",
    1913             :        NO_STR
    1914             :        "Interface IPv6 config commands\n"
    1915             :        "Neighbor discovery\n"
    1916             :        "Home Agent preference\n"
    1917             :        "preference value (default is 0, least preferred)\n")
    1918             : {
    1919           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1920           0 :         struct zebra_if *zif = ifp->info;
    1921             : 
    1922           0 :         zif->rtadv.HomeAgentPreference = 0;
    1923             : 
    1924           0 :         return CMD_SUCCESS;
    1925             : }
    1926             : 
    1927           0 : DEFUN (ipv6_nd_homeagent_lifetime,
    1928             :        ipv6_nd_homeagent_lifetime_cmd,
    1929             :        "ipv6 nd home-agent-lifetime (0-65520)",
    1930             :        "Interface IPv6 config commands\n"
    1931             :        "Neighbor discovery\n"
    1932             :        "Home Agent lifetime\n"
    1933             :        "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
    1934             : {
    1935           0 :         int idx_number = 3;
    1936           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1937           0 :         struct zebra_if *zif = ifp->info;
    1938           0 :         zif->rtadv.HomeAgentLifetime = strtoul(argv[idx_number]->arg, NULL, 10);
    1939           0 :         return CMD_SUCCESS;
    1940             : }
    1941             : 
    1942           0 : DEFUN (no_ipv6_nd_homeagent_lifetime,
    1943             :        no_ipv6_nd_homeagent_lifetime_cmd,
    1944             :        "no ipv6 nd home-agent-lifetime [(0-65520)]",
    1945             :        NO_STR
    1946             :        "Interface IPv6 config commands\n"
    1947             :        "Neighbor discovery\n"
    1948             :        "Home Agent lifetime\n"
    1949             :        "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
    1950             : {
    1951           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1952           0 :         struct zebra_if *zif = ifp->info;
    1953             : 
    1954           0 :         zif->rtadv.HomeAgentLifetime = -1;
    1955             : 
    1956           0 :         return CMD_SUCCESS;
    1957             : }
    1958             : 
    1959           0 : DEFUN (ipv6_nd_managed_config_flag,
    1960             :        ipv6_nd_managed_config_flag_cmd,
    1961             :        "ipv6 nd managed-config-flag",
    1962             :        "Interface IPv6 config commands\n"
    1963             :        "Neighbor discovery\n"
    1964             :        "Managed address configuration flag\n")
    1965             : {
    1966           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1967           0 :         struct zebra_if *zif = ifp->info;
    1968             : 
    1969           0 :         zif->rtadv.AdvManagedFlag = 1;
    1970             : 
    1971           0 :         return CMD_SUCCESS;
    1972             : }
    1973             : 
    1974           0 : DEFUN (no_ipv6_nd_managed_config_flag,
    1975             :        no_ipv6_nd_managed_config_flag_cmd,
    1976             :        "no ipv6 nd managed-config-flag",
    1977             :        NO_STR
    1978             :        "Interface IPv6 config commands\n"
    1979             :        "Neighbor discovery\n"
    1980             :        "Managed address configuration flag\n")
    1981             : {
    1982           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1983           0 :         struct zebra_if *zif = ifp->info;
    1984             : 
    1985           0 :         zif->rtadv.AdvManagedFlag = 0;
    1986             : 
    1987           0 :         return CMD_SUCCESS;
    1988             : }
    1989             : 
    1990           0 : DEFUN (ipv6_nd_homeagent_config_flag,
    1991             :        ipv6_nd_homeagent_config_flag_cmd,
    1992             :        "ipv6 nd home-agent-config-flag",
    1993             :        "Interface IPv6 config commands\n"
    1994             :        "Neighbor discovery\n"
    1995             :        "Home Agent configuration flag\n")
    1996             : {
    1997           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1998           0 :         struct zebra_if *zif = ifp->info;
    1999             : 
    2000           0 :         zif->rtadv.AdvHomeAgentFlag = 1;
    2001             : 
    2002           0 :         return CMD_SUCCESS;
    2003             : }
    2004             : 
    2005           0 : DEFUN (no_ipv6_nd_homeagent_config_flag,
    2006             :        no_ipv6_nd_homeagent_config_flag_cmd,
    2007             :        "no ipv6 nd home-agent-config-flag",
    2008             :        NO_STR
    2009             :        "Interface IPv6 config commands\n"
    2010             :        "Neighbor discovery\n"
    2011             :        "Home Agent configuration flag\n")
    2012             : {
    2013           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2014           0 :         struct zebra_if *zif = ifp->info;
    2015             : 
    2016           0 :         zif->rtadv.AdvHomeAgentFlag = 0;
    2017             : 
    2018           0 :         return CMD_SUCCESS;
    2019             : }
    2020             : 
    2021           0 : DEFUN (ipv6_nd_adv_interval_config_option,
    2022             :        ipv6_nd_adv_interval_config_option_cmd,
    2023             :        "ipv6 nd adv-interval-option",
    2024             :        "Interface IPv6 config commands\n"
    2025             :        "Neighbor discovery\n"
    2026             :        "Advertisement Interval Option\n")
    2027             : {
    2028           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2029           0 :         struct zebra_if *zif = ifp->info;
    2030             : 
    2031           0 :         zif->rtadv.AdvIntervalOption = 1;
    2032             : 
    2033           0 :         return CMD_SUCCESS;
    2034             : }
    2035             : 
    2036           0 : DEFUN (no_ipv6_nd_adv_interval_config_option,
    2037             :        no_ipv6_nd_adv_interval_config_option_cmd,
    2038             :        "no ipv6 nd adv-interval-option",
    2039             :        NO_STR
    2040             :        "Interface IPv6 config commands\n"
    2041             :        "Neighbor discovery\n"
    2042             :        "Advertisement Interval Option\n")
    2043             : {
    2044           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2045           0 :         struct zebra_if *zif = ifp->info;
    2046             : 
    2047           0 :         zif->rtadv.AdvIntervalOption = 0;
    2048             : 
    2049           0 :         return CMD_SUCCESS;
    2050             : }
    2051             : 
    2052           0 : DEFUN (ipv6_nd_other_config_flag,
    2053             :        ipv6_nd_other_config_flag_cmd,
    2054             :        "ipv6 nd other-config-flag",
    2055             :        "Interface IPv6 config commands\n"
    2056             :        "Neighbor discovery\n"
    2057             :        "Other statefull configuration flag\n")
    2058             : {
    2059           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2060           0 :         struct zebra_if *zif = ifp->info;
    2061             : 
    2062           0 :         zif->rtadv.AdvOtherConfigFlag = 1;
    2063             : 
    2064           0 :         return CMD_SUCCESS;
    2065             : }
    2066             : 
    2067           0 : DEFUN (no_ipv6_nd_other_config_flag,
    2068             :        no_ipv6_nd_other_config_flag_cmd,
    2069             :        "no ipv6 nd other-config-flag",
    2070             :        NO_STR
    2071             :        "Interface IPv6 config commands\n"
    2072             :        "Neighbor discovery\n"
    2073             :        "Other statefull configuration flag\n")
    2074             : {
    2075           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2076           0 :         struct zebra_if *zif = ifp->info;
    2077             : 
    2078           0 :         zif->rtadv.AdvOtherConfigFlag = 0;
    2079             : 
    2080           0 :         return CMD_SUCCESS;
    2081             : }
    2082             : 
    2083           0 : DEFUN (ipv6_nd_prefix,
    2084             :        ipv6_nd_prefix_cmd,
    2085             :        "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
    2086             :        "Interface IPv6 config commands\n"
    2087             :        "Neighbor discovery\n"
    2088             :        "Prefix information\n"
    2089             :        "IPv6 prefix\n"
    2090             :        "Valid lifetime in seconds\n"
    2091             :        "Infinite valid lifetime\n"
    2092             :        "Preferred lifetime in seconds\n"
    2093             :        "Infinite preferred lifetime\n"
    2094             :        "Set Router Address flag\n"
    2095             :        "Do not use prefix for onlink determination\n"
    2096             :        "Do not use prefix for autoconfiguration\n"
    2097             :        "Do not use prefix for autoconfiguration\n"
    2098             :        "Do not use prefix for onlink determination\n")
    2099             : {
    2100             :         /* prelude */
    2101           0 :         char *prefix = argv[3]->arg;
    2102           0 :         int lifetimes = (argc > 4) && (argv[4]->type == RANGE_TKN
    2103           0 :                                        || strmatch(argv[4]->text, "infinite"));
    2104           0 :         int routeropts = lifetimes ? argc > 6 : argc > 4;
    2105             : 
    2106           0 :         int idx_routeropts = routeropts ? (lifetimes ? 6 : 4) : 0;
    2107             : 
    2108           0 :         char *lifetime = NULL, *preflifetime = NULL;
    2109           0 :         int routeraddr = 0, offlink = 0, noautoconf = 0;
    2110           0 :         if (lifetimes) {
    2111           0 :                 lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
    2112           0 :                                                       : argv[4]->text;
    2113           0 :                 preflifetime = argv[5]->type == RANGE_TKN ? argv[5]->arg
    2114           0 :                                                           : argv[5]->text;
    2115             :         }
    2116           0 :         if (routeropts) {
    2117           0 :                 routeraddr =
    2118           0 :                         strmatch(argv[idx_routeropts]->text, "router-address");
    2119           0 :                 if (!routeraddr) {
    2120           0 :                         offlink = (argc > idx_routeropts + 1
    2121           0 :                                    || strmatch(argv[idx_routeropts]->text,
    2122             :                                                "off-link"));
    2123           0 :                         noautoconf = (argc > idx_routeropts + 1
    2124           0 :                                       || strmatch(argv[idx_routeropts]->text,
    2125             :                                                   "no-autoconfig"));
    2126             :                 }
    2127             :         }
    2128             : 
    2129             :         /* business */
    2130           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2131           0 :         struct zebra_if *zebra_if = ifp->info;
    2132           0 :         int ret;
    2133           0 :         struct rtadv_prefix rp;
    2134             : 
    2135           0 :         ret = str2prefix_ipv6(prefix, &rp.prefix);
    2136           0 :         if (!ret) {
    2137           0 :                 vty_out(vty, "Malformed IPv6 prefix\n");
    2138           0 :                 return CMD_WARNING_CONFIG_FAILED;
    2139             :         }
    2140           0 :         apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */
    2141           0 :         rp.AdvOnLinkFlag = !offlink;
    2142           0 :         rp.AdvAutonomousFlag = !noautoconf;
    2143           0 :         rp.AdvRouterAddressFlag = routeraddr;
    2144           0 :         rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
    2145           0 :         rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
    2146           0 :         rp.AdvPrefixCreate = PREFIX_SRC_MANUAL;
    2147             : 
    2148           0 :         if (lifetimes) {
    2149           0 :                 rp.AdvValidLifetime = strmatch(lifetime, "infinite")
    2150             :                                               ? UINT32_MAX
    2151           0 :                                               : strtoll(lifetime, NULL, 10);
    2152           0 :                 rp.AdvPreferredLifetime =
    2153           0 :                         strmatch(preflifetime, "infinite")
    2154             :                                 ? UINT32_MAX
    2155           0 :                                 : strtoll(preflifetime, NULL, 10);
    2156           0 :                 if (rp.AdvPreferredLifetime > rp.AdvValidLifetime) {
    2157           0 :                         vty_out(vty, "Invalid preferred lifetime\n");
    2158           0 :                         return CMD_WARNING_CONFIG_FAILED;
    2159             :                 }
    2160             :         }
    2161             : 
    2162           0 :         rtadv_prefix_set(zebra_if, &rp);
    2163             : 
    2164           0 :         return CMD_SUCCESS;
    2165             : }
    2166             : 
    2167           0 : DEFUN (no_ipv6_nd_prefix,
    2168             :        no_ipv6_nd_prefix_cmd,
    2169             :        "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]>]",
    2170             :         NO_STR
    2171             :        "Interface IPv6 config commands\n"
    2172             :        "Neighbor discovery\n"
    2173             :        "Prefix information\n"
    2174             :        "IPv6 prefix\n"
    2175             :        "Valid lifetime in seconds\n"
    2176             :        "Infinite valid lifetime\n"
    2177             :        "Preferred lifetime in seconds\n"
    2178             :        "Infinite preferred lifetime\n"
    2179             :        "Set Router Address flag\n"
    2180             :        "Do not use prefix for onlink determination\n"
    2181             :        "Do not use prefix for autoconfiguration\n"
    2182             :        "Do not use prefix for autoconfiguration\n"
    2183             :        "Do not use prefix for onlink determination\n")
    2184             : {
    2185           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2186           0 :         struct zebra_if *zebra_if = ifp->info;
    2187           0 :         int ret;
    2188           0 :         struct rtadv_prefix rp;
    2189           0 :         char *prefix = argv[4]->arg;
    2190             : 
    2191           0 :         ret = str2prefix_ipv6(prefix, &rp.prefix);
    2192           0 :         if (!ret) {
    2193           0 :                 vty_out(vty, "Malformed IPv6 prefix\n");
    2194           0 :                 return CMD_WARNING_CONFIG_FAILED;
    2195             :         }
    2196           0 :         apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */
    2197           0 :         rp.AdvPrefixCreate = PREFIX_SRC_MANUAL;
    2198             : 
    2199           0 :         ret = rtadv_prefix_reset(zebra_if, &rp);
    2200           0 :         if (!ret) {
    2201           0 :                 vty_out(vty, "Non-existant IPv6 prefix\n");
    2202           0 :                 return CMD_WARNING_CONFIG_FAILED;
    2203             :         }
    2204             : 
    2205             :         return CMD_SUCCESS;
    2206             : }
    2207             : 
    2208           0 : DEFUN (ipv6_nd_router_preference,
    2209             :        ipv6_nd_router_preference_cmd,
    2210             :        "ipv6 nd router-preference <high|medium|low>",
    2211             :        "Interface IPv6 config commands\n"
    2212             :        "Neighbor discovery\n"
    2213             :        "Default router preference\n"
    2214             :        "High default router preference\n"
    2215             :        "Medium default router preference (default)\n"
    2216             :        "Low default router preference\n")
    2217             : {
    2218           0 :         int idx_high_medium_low = 3;
    2219           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2220           0 :         struct zebra_if *zif = ifp->info;
    2221           0 :         int i = 0;
    2222             : 
    2223           0 :         while (0 != rtadv_pref_strs[i]) {
    2224           0 :                 if (strncmp(argv[idx_high_medium_low]->arg, rtadv_pref_strs[i],
    2225             :                             1)
    2226             :                     == 0) {
    2227           0 :                         zif->rtadv.DefaultPreference = i;
    2228           0 :                         return CMD_SUCCESS;
    2229             :                 }
    2230           0 :                 i++;
    2231             :         }
    2232             : 
    2233             :         return CMD_ERR_NO_MATCH;
    2234             : }
    2235             : 
    2236           0 : DEFUN (no_ipv6_nd_router_preference,
    2237             :        no_ipv6_nd_router_preference_cmd,
    2238             :        "no ipv6 nd router-preference [<high|medium|low>]",
    2239             :        NO_STR
    2240             :        "Interface IPv6 config commands\n"
    2241             :        "Neighbor discovery\n"
    2242             :        "Default router preference\n"
    2243             :        "High default router preference\n"
    2244             :        "Medium default router preference (default)\n"
    2245             :        "Low default router preference\n")
    2246             : {
    2247           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2248           0 :         struct zebra_if *zif = ifp->info;
    2249             : 
    2250           0 :         zif->rtadv.DefaultPreference =
    2251             :                 RTADV_PREF_MEDIUM; /* Default per RFC4191. */
    2252             : 
    2253           0 :         return CMD_SUCCESS;
    2254             : }
    2255             : 
    2256           0 : DEFUN (ipv6_nd_mtu,
    2257             :        ipv6_nd_mtu_cmd,
    2258             :        "ipv6 nd mtu (1-65535)",
    2259             :        "Interface IPv6 config commands\n"
    2260             :        "Neighbor discovery\n"
    2261             :        "Advertised MTU\n"
    2262             :        "MTU in bytes\n")
    2263             : {
    2264           0 :         int idx_number = 3;
    2265           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2266           0 :         struct zebra_if *zif = ifp->info;
    2267           0 :         zif->rtadv.AdvLinkMTU = strtoul(argv[idx_number]->arg, NULL, 10);
    2268           0 :         return CMD_SUCCESS;
    2269             : }
    2270             : 
    2271           0 : DEFUN (no_ipv6_nd_mtu,
    2272             :        no_ipv6_nd_mtu_cmd,
    2273             :        "no ipv6 nd mtu [(1-65535)]",
    2274             :        NO_STR
    2275             :        "Interface IPv6 config commands\n"
    2276             :        "Neighbor discovery\n"
    2277             :        "Advertised MTU\n"
    2278             :        "MTU in bytes\n")
    2279             : {
    2280           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2281           0 :         struct zebra_if *zif = ifp->info;
    2282           0 :         zif->rtadv.AdvLinkMTU = 0;
    2283           0 :         return CMD_SUCCESS;
    2284             : }
    2285             : 
    2286           0 : static struct rtadv_rdnss *rtadv_rdnss_new(void)
    2287             : {
    2288           0 :         return XCALLOC(MTYPE_RTADV_RDNSS, sizeof(struct rtadv_rdnss));
    2289             : }
    2290             : 
    2291           0 : static void rtadv_rdnss_free(struct rtadv_rdnss *rdnss)
    2292             : {
    2293           0 :         XFREE(MTYPE_RTADV_RDNSS, rdnss);
    2294             : }
    2295             : 
    2296           0 : static struct rtadv_rdnss *rtadv_rdnss_lookup(struct list *list,
    2297             :                                               struct rtadv_rdnss *rdnss)
    2298             : {
    2299           0 :         struct listnode *node;
    2300           0 :         struct rtadv_rdnss *p;
    2301             : 
    2302           0 :         for (ALL_LIST_ELEMENTS_RO(list, node, p))
    2303           0 :                 if (IPV6_ADDR_SAME(&p->addr, &rdnss->addr))
    2304           0 :                         return p;
    2305             :         return NULL;
    2306             : }
    2307             : 
    2308           0 : static struct rtadv_rdnss *rtadv_rdnss_get(struct list *list,
    2309             :                                            struct rtadv_rdnss *rdnss)
    2310             : {
    2311           0 :         struct rtadv_rdnss *p;
    2312             : 
    2313           0 :         p = rtadv_rdnss_lookup(list, rdnss);
    2314           0 :         if (p)
    2315             :                 return p;
    2316             : 
    2317           0 :         p = rtadv_rdnss_new();
    2318           0 :         memcpy(p, rdnss, sizeof(struct rtadv_rdnss));
    2319           0 :         listnode_add(list, p);
    2320             : 
    2321           0 :         return p;
    2322             : }
    2323             : 
    2324           0 : static void rtadv_rdnss_set(struct zebra_if *zif, struct rtadv_rdnss *rdnss)
    2325             : {
    2326           0 :         struct rtadv_rdnss *p;
    2327             : 
    2328           0 :         p = rtadv_rdnss_get(zif->rtadv.AdvRDNSSList, rdnss);
    2329           0 :         p->lifetime = rdnss->lifetime;
    2330           0 :         p->lifetime_set = rdnss->lifetime_set;
    2331           0 : }
    2332             : 
    2333           0 : static int rtadv_rdnss_reset(struct zebra_if *zif, struct rtadv_rdnss *rdnss)
    2334             : {
    2335           0 :         struct rtadv_rdnss *p;
    2336             : 
    2337           0 :         p = rtadv_rdnss_lookup(zif->rtadv.AdvRDNSSList, rdnss);
    2338           0 :         if (p) {
    2339           0 :                 listnode_delete(zif->rtadv.AdvRDNSSList, p);
    2340           0 :                 rtadv_rdnss_free(p);
    2341           0 :                 return 1;
    2342             :         }
    2343             : 
    2344             :         return 0;
    2345             : }
    2346             : 
    2347           0 : static struct rtadv_dnssl *rtadv_dnssl_new(void)
    2348             : {
    2349           0 :         return XCALLOC(MTYPE_RTADV_DNSSL, sizeof(struct rtadv_dnssl));
    2350             : }
    2351             : 
    2352           0 : static void rtadv_dnssl_free(struct rtadv_dnssl *dnssl)
    2353             : {
    2354           0 :         XFREE(MTYPE_RTADV_DNSSL, dnssl);
    2355             : }
    2356             : 
    2357           0 : static struct rtadv_dnssl *rtadv_dnssl_lookup(struct list *list,
    2358             :                                               struct rtadv_dnssl *dnssl)
    2359             : {
    2360           0 :         struct listnode *node;
    2361           0 :         struct rtadv_dnssl *p;
    2362             : 
    2363           0 :         for (ALL_LIST_ELEMENTS_RO(list, node, p))
    2364           0 :                 if (!strcasecmp(p->name, dnssl->name))
    2365           0 :                         return p;
    2366             :         return NULL;
    2367             : }
    2368             : 
    2369           0 : static struct rtadv_dnssl *rtadv_dnssl_get(struct list *list,
    2370             :                                            struct rtadv_dnssl *dnssl)
    2371             : {
    2372           0 :         struct rtadv_dnssl *p;
    2373             : 
    2374           0 :         p = rtadv_dnssl_lookup(list, dnssl);
    2375           0 :         if (p)
    2376             :                 return p;
    2377             : 
    2378           0 :         p = rtadv_dnssl_new();
    2379           0 :         memcpy(p, dnssl, sizeof(struct rtadv_dnssl));
    2380           0 :         listnode_add(list, p);
    2381             : 
    2382           0 :         return p;
    2383             : }
    2384             : 
    2385           0 : static void rtadv_dnssl_set(struct zebra_if *zif, struct rtadv_dnssl *dnssl)
    2386             : {
    2387           0 :         struct rtadv_dnssl *p;
    2388             : 
    2389           0 :         p = rtadv_dnssl_get(zif->rtadv.AdvDNSSLList, dnssl);
    2390           0 :         memcpy(p, dnssl, sizeof(struct rtadv_dnssl));
    2391           0 : }
    2392             : 
    2393           0 : static int rtadv_dnssl_reset(struct zebra_if *zif, struct rtadv_dnssl *dnssl)
    2394             : {
    2395           0 :         struct rtadv_dnssl *p;
    2396             : 
    2397           0 :         p = rtadv_dnssl_lookup(zif->rtadv.AdvDNSSLList, dnssl);
    2398           0 :         if (p) {
    2399           0 :                 listnode_delete(zif->rtadv.AdvDNSSLList, p);
    2400           0 :                 rtadv_dnssl_free(p);
    2401           0 :                 return 1;
    2402             :         }
    2403             : 
    2404             :         return 0;
    2405             : }
    2406             : 
    2407             : /*
    2408             :  * Convert dotted domain name (with or without trailing root zone dot) to
    2409             :  * sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
    2410             :  * to strlen(in) + 2 octets to out.
    2411             :  *
    2412             :  * Returns the number of octets written to out or -1 if in does not constitute
    2413             :  * a valid domain name.
    2414             :  */
    2415           0 : static int rtadv_dnssl_encode(uint8_t *out, const char *in)
    2416             : {
    2417           0 :         const char *label_start, *label_end;
    2418           0 :         size_t outp;
    2419             : 
    2420           0 :         outp = 0;
    2421           0 :         label_start = in;
    2422             : 
    2423           0 :         while (*label_start) {
    2424           0 :                 size_t label_len;
    2425             : 
    2426           0 :                 label_end = strchr(label_start, '.');
    2427           0 :                 if (label_end == NULL)
    2428           0 :                         label_end = label_start + strlen(label_start);
    2429             : 
    2430           0 :                 label_len = label_end - label_start;
    2431           0 :                 if (label_len >= 64)
    2432             :                         return -1; /* labels must be 63 octets or less */
    2433             : 
    2434           0 :                 out[outp++] = (uint8_t)label_len;
    2435           0 :                 memcpy(out + outp, label_start, label_len);
    2436           0 :                 outp += label_len;
    2437           0 :                 label_start += label_len;
    2438           0 :                 if (*label_start == '.')
    2439           0 :                         label_start++;
    2440             :         }
    2441             : 
    2442           0 :         out[outp++] = '\0';
    2443           0 :         return outp;
    2444             : }
    2445             : 
    2446           0 : DEFUN(ipv6_nd_rdnss,
    2447             :       ipv6_nd_rdnss_cmd,
    2448             :       "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
    2449             :       "Interface IPv6 config commands\n"
    2450             :       "Neighbor discovery\n"
    2451             :       "Recursive DNS server information\n"
    2452             :       "IPv6 address\n"
    2453             :       "Valid lifetime in seconds\n"
    2454             :       "Infinite valid lifetime\n")
    2455             : {
    2456           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2457           0 :         struct zebra_if *zif = ifp->info;
    2458           0 :         struct rtadv_rdnss rdnss = {};
    2459             : 
    2460           0 :         if (inet_pton(AF_INET6, argv[3]->arg, &rdnss.addr) != 1) {
    2461           0 :                 vty_out(vty, "Malformed IPv6 address\n");
    2462           0 :                 return CMD_WARNING_CONFIG_FAILED;
    2463             :         }
    2464           0 :         if (argc > 4) {
    2465           0 :                 char *lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
    2466           0 :                                                             : argv[4]->text;
    2467           0 :                 rdnss.lifetime = strmatch(lifetime, "infinite")
    2468             :                                          ? UINT32_MAX
    2469           0 :                                          : strtoll(lifetime, NULL, 10);
    2470           0 :                 rdnss.lifetime_set = 1;
    2471             :         }
    2472             : 
    2473           0 :         rtadv_rdnss_set(zif, &rdnss);
    2474             : 
    2475           0 :         return CMD_SUCCESS;
    2476             : }
    2477             : 
    2478           0 : DEFUN(no_ipv6_nd_rdnss,
    2479             :       no_ipv6_nd_rdnss_cmd,
    2480             :       "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
    2481             :       NO_STR
    2482             :       "Interface IPv6 config commands\n"
    2483             :       "Neighbor discovery\n"
    2484             :       "Recursive DNS server information\n"
    2485             :       "IPv6 address\n"
    2486             :       "Valid lifetime in seconds\n"
    2487             :       "Infinite valid lifetime\n")
    2488             : {
    2489           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2490           0 :         struct zebra_if *zif = ifp->info;
    2491           0 :         struct rtadv_rdnss rdnss = {};
    2492             : 
    2493           0 :         if (inet_pton(AF_INET6, argv[4]->arg, &rdnss.addr) != 1) {
    2494           0 :                 vty_out(vty, "Malformed IPv6 address\n");
    2495           0 :                 return CMD_WARNING_CONFIG_FAILED;
    2496             :         }
    2497           0 :         if (rtadv_rdnss_reset(zif, &rdnss) != 1) {
    2498           0 :                 vty_out(vty, "Non-existant RDNSS address\n");
    2499           0 :                 return CMD_WARNING_CONFIG_FAILED;
    2500             :         }
    2501             : 
    2502             :         return CMD_SUCCESS;
    2503             : }
    2504             : 
    2505           0 : DEFUN(ipv6_nd_dnssl,
    2506             :       ipv6_nd_dnssl_cmd,
    2507             :       "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
    2508             :       "Interface IPv6 config commands\n"
    2509             :       "Neighbor discovery\n"
    2510             :       "DNS search list information\n"
    2511             :       "Domain name suffix\n"
    2512             :       "Valid lifetime in seconds\n"
    2513             :       "Infinite valid lifetime\n")
    2514             : {
    2515           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2516           0 :         struct zebra_if *zif = ifp->info;
    2517           0 :         struct rtadv_dnssl dnssl = {};
    2518           0 :         size_t len;
    2519           0 :         int ret;
    2520             : 
    2521           0 :         len = strlcpy(dnssl.name, argv[3]->arg, sizeof(dnssl.name));
    2522           0 :         if (len == 0 || len >= sizeof(dnssl.name)) {
    2523           0 :                 vty_out(vty, "Malformed DNS search domain\n");
    2524           0 :                 return CMD_WARNING_CONFIG_FAILED;
    2525             :         }
    2526           0 :         if (dnssl.name[len - 1] == '.') {
    2527             :                 /*
    2528             :                  * Allow, but don't require, a trailing dot signifying the root
    2529             :                  * zone. Canonicalize by cutting it off if present.
    2530             :                  */
    2531           0 :                 dnssl.name[len - 1] = '\0';
    2532           0 :                 len--;
    2533             :         }
    2534           0 :         if (argc > 4) {
    2535           0 :                 char *lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
    2536           0 :                                                             : argv[4]->text;
    2537           0 :                 dnssl.lifetime = strmatch(lifetime, "infinite")
    2538             :                                          ? UINT32_MAX
    2539           0 :                                          : strtoll(lifetime, NULL, 10);
    2540           0 :                 dnssl.lifetime_set = 1;
    2541             :         }
    2542             : 
    2543           0 :         ret = rtadv_dnssl_encode(dnssl.encoded_name, dnssl.name);
    2544           0 :         if (ret < 0) {
    2545           0 :                 vty_out(vty, "Malformed DNS search domain\n");
    2546           0 :                 return CMD_WARNING_CONFIG_FAILED;
    2547             :         }
    2548           0 :         dnssl.encoded_len = ret;
    2549           0 :         rtadv_dnssl_set(zif, &dnssl);
    2550             : 
    2551           0 :         return CMD_SUCCESS;
    2552             : }
    2553             : 
    2554           0 : DEFUN(no_ipv6_nd_dnssl,
    2555             :       no_ipv6_nd_dnssl_cmd,
    2556             :       "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
    2557             :       NO_STR
    2558             :       "Interface IPv6 config commands\n"
    2559             :       "Neighbor discovery\n"
    2560             :       "DNS search list information\n"
    2561             :       "Domain name suffix\n"
    2562             :       "Valid lifetime in seconds\n"
    2563             :       "Infinite valid lifetime\n")
    2564             : {
    2565           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2566           0 :         struct zebra_if *zif = ifp->info;
    2567           0 :         struct rtadv_dnssl dnssl = {};
    2568           0 :         size_t len;
    2569             : 
    2570           0 :         len = strlcpy(dnssl.name, argv[4]->arg, sizeof(dnssl.name));
    2571           0 :         if (len == 0 || len >= sizeof(dnssl.name)) {
    2572           0 :                 vty_out(vty, "Malformed DNS search domain\n");
    2573           0 :                 return CMD_WARNING_CONFIG_FAILED;
    2574             :         }
    2575           0 :         if (dnssl.name[len - 1] == '.') {
    2576           0 :                 dnssl.name[len - 1] = '\0';
    2577           0 :                 len--;
    2578             :         }
    2579           0 :         if (rtadv_dnssl_reset(zif, &dnssl) != 1) {
    2580           0 :                 vty_out(vty, "Non-existant DNS search domain\n");
    2581           0 :                 return CMD_WARNING_CONFIG_FAILED;
    2582             :         }
    2583             : 
    2584             :         return CMD_SUCCESS;
    2585             : }
    2586             : 
    2587             : 
    2588             : /* Dump interface ND information to vty. */
    2589           0 : static int nd_dump_vty(struct vty *vty, struct interface *ifp)
    2590             : {
    2591           0 :         struct zebra_if *zif;
    2592           0 :         struct rtadvconf *rtadv;
    2593           0 :         int interval;
    2594             : 
    2595           0 :         zif = (struct zebra_if *)ifp->info;
    2596           0 :         rtadv = &zif->rtadv;
    2597             : 
    2598           0 :         if (rtadv->AdvSendAdvertisements) {
    2599           0 :                 vty_out(vty,
    2600             :                         "  ND advertised reachable time is %d milliseconds\n",
    2601             :                         rtadv->AdvReachableTime);
    2602           0 :                 vty_out(vty,
    2603             :                         "  ND advertised retransmit interval is %u milliseconds\n",
    2604             :                         rtadv->AdvRetransTimer);
    2605           0 :                 vty_out(vty, "  ND advertised hop-count limit is %d hops\n",
    2606             :                         rtadv->AdvCurHopLimit);
    2607           0 :                 vty_out(vty, "  ND router advertisements sent: %d rcvd: %d\n",
    2608             :                         zif->ra_sent, zif->ra_rcvd);
    2609           0 :                 interval = rtadv->MaxRtrAdvInterval;
    2610           0 :                 if (interval % 1000)
    2611           0 :                         vty_out(vty,
    2612             :                                 "  ND router advertisements are sent every %d milliseconds\n",
    2613             :                                 interval);
    2614             :                 else
    2615           0 :                         vty_out(vty,
    2616             :                                 "  ND router advertisements are sent every %d seconds\n",
    2617             :                                 interval / 1000);
    2618           0 :                 if (!rtadv->UseFastRexmit)
    2619           0 :                         vty_out(vty,
    2620             :                                 "  ND router advertisements do not use fast retransmit\n");
    2621             : 
    2622           0 :                 if (rtadv->AdvDefaultLifetime != -1)
    2623           0 :                         vty_out(vty,
    2624             :                                 "  ND router advertisements live for %d seconds\n",
    2625             :                                 rtadv->AdvDefaultLifetime);
    2626             :                 else
    2627           0 :                         vty_out(vty,
    2628             :                                 "  ND router advertisements lifetime tracks ra-interval\n");
    2629           0 :                 vty_out(vty,
    2630             :                         "  ND router advertisement default router preference is %s\n",
    2631           0 :                         rtadv_pref_strs[rtadv->DefaultPreference]);
    2632           0 :                 if (rtadv->AdvManagedFlag)
    2633           0 :                         vty_out(vty,
    2634             :                                 "  Hosts use DHCP to obtain routable addresses.\n");
    2635             :                 else
    2636           0 :                         vty_out(vty,
    2637             :                                 "  Hosts use stateless autoconfig for addresses.\n");
    2638           0 :                 if (rtadv->AdvHomeAgentFlag) {
    2639           0 :                         vty_out(vty,
    2640             :                                 "  ND router advertisements with Home Agent flag bit set.\n");
    2641           0 :                         if (rtadv->HomeAgentLifetime != -1)
    2642           0 :                                 vty_out(vty,
    2643             :                                         "  Home Agent lifetime is %u seconds\n",
    2644             :                                         rtadv->HomeAgentLifetime);
    2645             :                         else
    2646           0 :                                 vty_out(vty,
    2647             :                                         "  Home Agent lifetime tracks ra-lifetime\n");
    2648           0 :                         vty_out(vty, "  Home Agent preference is %u\n",
    2649             :                                 rtadv->HomeAgentPreference);
    2650             :                 }
    2651           0 :                 if (rtadv->AdvIntervalOption)
    2652           0 :                         vty_out(vty,
    2653             :                                 "  ND router advertisements with Adv. Interval option.\n");
    2654             :         }
    2655           0 :         return 0;
    2656             : }
    2657             : 
    2658             : 
    2659             : /* Write configuration about router advertisement. */
    2660           0 : static int rtadv_config_write(struct vty *vty, struct interface *ifp)
    2661             : {
    2662           0 :         struct zebra_if *zif;
    2663           0 :         struct listnode *node;
    2664           0 :         struct rtadv_prefix *rprefix;
    2665           0 :         struct rtadv_rdnss *rdnss;
    2666           0 :         struct rtadv_dnssl *dnssl;
    2667           0 :         int interval;
    2668             : 
    2669           0 :         zif = ifp->info;
    2670             : 
    2671           0 :         if (!if_is_loopback(ifp)) {
    2672           0 :                 if (zif->rtadv.AdvSendAdvertisements
    2673           0 :                     && CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED))
    2674           0 :                         vty_out(vty, " no ipv6 nd suppress-ra\n");
    2675             :         }
    2676             : 
    2677           0 :         interval = zif->rtadv.MaxRtrAdvInterval;
    2678           0 :         if (CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED)) {
    2679           0 :                 if (interval % 1000)
    2680           0 :                         vty_out(vty, " ipv6 nd ra-interval msec %d\n",
    2681             :                                 interval);
    2682           0 :                 else if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
    2683           0 :                         vty_out(vty, " ipv6 nd ra-interval %d\n",
    2684             :                                 interval / 1000);
    2685             :         }
    2686             : 
    2687           0 :         if (zif->rtadv.AdvIntervalOption)
    2688           0 :                 vty_out(vty, " ipv6 nd adv-interval-option\n");
    2689             : 
    2690           0 :         if (!zif->rtadv.UseFastRexmit)
    2691           0 :                 vty_out(vty, " no ipv6 nd ra-fast-retrans\n");
    2692             : 
    2693           0 :         if (zif->rtadv.AdvRetransTimer != 0)
    2694           0 :                 vty_out(vty, " ipv6 nd ra-retrans-interval %u\n",
    2695             :                         zif->rtadv.AdvRetransTimer);
    2696             : 
    2697           0 :         if (zif->rtadv.AdvCurHopLimit != RTADV_DEFAULT_HOPLIMIT)
    2698           0 :                 vty_out(vty, " ipv6 nd ra-hop-limit %d\n",
    2699             :                         zif->rtadv.AdvCurHopLimit);
    2700             : 
    2701           0 :         if (zif->rtadv.AdvDefaultLifetime != -1)
    2702           0 :                 vty_out(vty, " ipv6 nd ra-lifetime %d\n",
    2703             :                         zif->rtadv.AdvDefaultLifetime);
    2704             : 
    2705           0 :         if (zif->rtadv.HomeAgentPreference)
    2706           0 :                 vty_out(vty, " ipv6 nd home-agent-preference %u\n",
    2707             :                         zif->rtadv.HomeAgentPreference);
    2708             : 
    2709           0 :         if (zif->rtadv.HomeAgentLifetime != -1)
    2710           0 :                 vty_out(vty, " ipv6 nd home-agent-lifetime %u\n",
    2711             :                         zif->rtadv.HomeAgentLifetime);
    2712             : 
    2713           0 :         if (zif->rtadv.AdvHomeAgentFlag)
    2714           0 :                 vty_out(vty, " ipv6 nd home-agent-config-flag\n");
    2715             : 
    2716           0 :         if (zif->rtadv.AdvReachableTime)
    2717           0 :                 vty_out(vty, " ipv6 nd reachable-time %d\n",
    2718             :                         zif->rtadv.AdvReachableTime);
    2719             : 
    2720           0 :         if (zif->rtadv.AdvManagedFlag)
    2721           0 :                 vty_out(vty, " ipv6 nd managed-config-flag\n");
    2722             : 
    2723           0 :         if (zif->rtadv.AdvOtherConfigFlag)
    2724           0 :                 vty_out(vty, " ipv6 nd other-config-flag\n");
    2725             : 
    2726           0 :         if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
    2727           0 :                 vty_out(vty, " ipv6 nd router-preference %s\n",
    2728           0 :                         rtadv_pref_strs[zif->rtadv.DefaultPreference]);
    2729             : 
    2730           0 :         if (zif->rtadv.AdvLinkMTU)
    2731           0 :                 vty_out(vty, " ipv6 nd mtu %d\n", zif->rtadv.AdvLinkMTU);
    2732             : 
    2733           0 :         frr_each (rtadv_prefixes, zif->rtadv.prefixes, rprefix) {
    2734           0 :                 if ((rprefix->AdvPrefixCreate == PREFIX_SRC_MANUAL)
    2735           0 :                     || (rprefix->AdvPrefixCreate == PREFIX_SRC_BOTH)) {
    2736           0 :                         vty_out(vty, " ipv6 nd prefix %pFX", &rprefix->prefix);
    2737           0 :                         if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME)
    2738           0 :                             || (rprefix->AdvPreferredLifetime
    2739             :                                 != RTADV_PREFERRED_LIFETIME)) {
    2740           0 :                                 if (rprefix->AdvValidLifetime == UINT32_MAX)
    2741           0 :                                         vty_out(vty, " infinite");
    2742             :                                 else
    2743           0 :                                         vty_out(vty, " %u",
    2744             :                                                 rprefix->AdvValidLifetime);
    2745           0 :                                 if (rprefix->AdvPreferredLifetime == UINT32_MAX)
    2746           0 :                                         vty_out(vty, " infinite");
    2747             :                                 else
    2748           0 :                                         vty_out(vty, " %u",
    2749             :                                                 rprefix->AdvPreferredLifetime);
    2750             :                         }
    2751           0 :                         if (!rprefix->AdvOnLinkFlag)
    2752           0 :                                 vty_out(vty, " off-link");
    2753           0 :                         if (!rprefix->AdvAutonomousFlag)
    2754           0 :                                 vty_out(vty, " no-autoconfig");
    2755           0 :                         if (rprefix->AdvRouterAddressFlag)
    2756           0 :                                 vty_out(vty, " router-address");
    2757           0 :                         vty_out(vty, "\n");
    2758             :                 }
    2759             :         }
    2760             : 
    2761           0 :         for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvRDNSSList, node, rdnss)) {
    2762           0 :                 char buf[INET6_ADDRSTRLEN];
    2763             : 
    2764           0 :                 vty_out(vty, " ipv6 nd rdnss %s",
    2765           0 :                         inet_ntop(AF_INET6, &rdnss->addr, buf, sizeof(buf)));
    2766           0 :                 if (rdnss->lifetime_set) {
    2767           0 :                         if (rdnss->lifetime == UINT32_MAX)
    2768           0 :                                 vty_out(vty, " infinite");
    2769             :                         else
    2770           0 :                                 vty_out(vty, " %u", rdnss->lifetime);
    2771             :                 }
    2772           0 :                 vty_out(vty, "\n");
    2773             :         }
    2774           0 :         for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvDNSSLList, node, dnssl)) {
    2775           0 :                 vty_out(vty, " ipv6 nd dnssl %s", dnssl->name);
    2776           0 :                 if (dnssl->lifetime_set) {
    2777           0 :                         if (dnssl->lifetime == UINT32_MAX)
    2778           0 :                                 vty_out(vty, " infinite");
    2779             :                         else
    2780           0 :                                 vty_out(vty, " %u", dnssl->lifetime);
    2781             :                 }
    2782           0 :                 vty_out(vty, "\n");
    2783             :         }
    2784           0 :         return 0;
    2785             : }
    2786             : 
    2787             : 
    2788          14 : static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val)
    2789             : {
    2790          14 :         struct rtadv *rtadv;
    2791             : 
    2792          14 :         if (IS_ZEBRA_DEBUG_EVENT) {
    2793           0 :                 struct vrf *vrf = zvrf->vrf;
    2794             : 
    2795           0 :                 zlog_debug("%s(%s) with event: %d and val: %d", __func__,
    2796             :                            VRF_LOGNAME(vrf), event, val);
    2797             :         }
    2798             : 
    2799          14 :         rtadv = &zvrf->rtadv;
    2800             : 
    2801          14 :         switch (event) {
    2802           1 :         case RTADV_START:
    2803           1 :                 event_add_read(zrouter.master, rtadv_read, zvrf, rtadv->sock,
    2804             :                                &rtadv->ra_read);
    2805           1 :                 event_add_event(zrouter.master, rtadv_timer, zvrf, 0,
    2806             :                                 &rtadv->ra_timer);
    2807           1 :                 break;
    2808           2 :         case RTADV_STOP:
    2809           2 :                 EVENT_OFF(rtadv->ra_timer);
    2810           2 :                 EVENT_OFF(rtadv->ra_read);
    2811             :                 break;
    2812          11 :         case RTADV_TIMER:
    2813          11 :                 event_add_timer(zrouter.master, rtadv_timer, zvrf, val,
    2814             :                                 &rtadv->ra_timer);
    2815          11 :                 break;
    2816           0 :         case RTADV_TIMER_MSEC:
    2817           0 :                 event_add_timer_msec(zrouter.master, rtadv_timer, zvrf, val,
    2818             :                                      &rtadv->ra_timer);
    2819           0 :                 break;
    2820           0 :         case RTADV_READ:
    2821           0 :                 event_add_read(zrouter.master, rtadv_read, zvrf, rtadv->sock,
    2822             :                                &rtadv->ra_read);
    2823           0 :                 break;
    2824             :         default:
    2825             :                 break;
    2826             :         }
    2827          14 :         return;
    2828             : }
    2829             : 
    2830           6 : void rtadv_if_up(struct zebra_if *zif)
    2831             : {
    2832           6 :         struct zebra_vrf *zvrf = rtadv_interface_get_zvrf(zif->ifp);
    2833             : 
    2834             :         /* Enable fast tx of RA if enabled && RA interval is not in msecs */
    2835           6 :         if (zif->rtadv.AdvSendAdvertisements &&
    2836           0 :             (zif->rtadv.MaxRtrAdvInterval >= 1000) &&
    2837           0 :             zif->rtadv.UseFastRexmit) {
    2838           0 :                 zif->rtadv.inFastRexmit = 1;
    2839           0 :                 zif->rtadv.NumFastReXmitsRemain = RTADV_NUM_FAST_REXMITS;
    2840             :         }
    2841             : 
    2842             :         /*
    2843             :          * startup the state machine, if it hasn't been already
    2844             :          * due to a delayed ifindex on startup ordering
    2845             :          */
    2846           6 :         if (zif->rtadv.AdvSendAdvertisements)
    2847           0 :                 rtadv_start_interface_events(zvrf, zif);
    2848           6 : }
    2849             : 
    2850           8 : void rtadv_if_init(struct zebra_if *zif)
    2851             : {
    2852             :         /* Set default router advertise values. */
    2853           8 :         struct rtadvconf *rtadv;
    2854             : 
    2855           8 :         rtadv = &zif->rtadv;
    2856             : 
    2857           8 :         rtadv->AdvSendAdvertisements = 0;
    2858           8 :         rtadv->MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
    2859           8 :         rtadv->MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
    2860           8 :         rtadv->AdvIntervalTimer = 0;
    2861           8 :         rtadv->AdvManagedFlag = 0;
    2862           8 :         rtadv->AdvOtherConfigFlag = 0;
    2863           8 :         rtadv->AdvHomeAgentFlag = 0;
    2864           8 :         rtadv->AdvLinkMTU = 0;
    2865           8 :         rtadv->AdvReachableTime = 0;
    2866           8 :         rtadv->AdvRetransTimer = 0;
    2867           8 :         rtadv->AdvCurHopLimit = RTADV_DEFAULT_HOPLIMIT;
    2868           8 :         memset(&rtadv->lastadvcurhoplimit, 0,
    2869             :                sizeof(rtadv->lastadvcurhoplimit));
    2870           8 :         memset(&rtadv->lastadvmanagedflag, 0,
    2871             :                sizeof(rtadv->lastadvmanagedflag));
    2872           8 :         memset(&rtadv->lastadvotherconfigflag, 0,
    2873             :                sizeof(rtadv->lastadvotherconfigflag));
    2874           8 :         memset(&rtadv->lastadvreachabletime, 0,
    2875             :                sizeof(rtadv->lastadvreachabletime));
    2876           8 :         memset(&rtadv->lastadvretranstimer, 0,
    2877             :                sizeof(rtadv->lastadvretranstimer));
    2878           8 :         rtadv->AdvDefaultLifetime = -1; /* derive from MaxRtrAdvInterval */
    2879           8 :         rtadv->HomeAgentPreference = 0;
    2880           8 :         rtadv->HomeAgentLifetime = -1; /* derive from AdvDefaultLifetime */
    2881           8 :         rtadv->AdvIntervalOption = 0;
    2882           8 :         rtadv->UseFastRexmit = true;
    2883           8 :         rtadv->DefaultPreference = RTADV_PREF_MEDIUM;
    2884             : 
    2885           8 :         rtadv_prefixes_init(rtadv->prefixes);
    2886             : 
    2887           8 :         rtadv->AdvRDNSSList = list_new();
    2888           8 :         rtadv->AdvDNSSLList = list_new();
    2889           8 : }
    2890             : 
    2891           8 : void rtadv_if_fini(struct zebra_if *zif)
    2892             : {
    2893           8 :         struct rtadvconf *rtadv;
    2894           8 :         struct rtadv_prefix *rp;
    2895             : 
    2896           8 :         rtadv = &zif->rtadv;
    2897             : 
    2898           8 :         while ((rp = rtadv_prefixes_pop(rtadv->prefixes)))
    2899           0 :                 rtadv_prefix_free(rp);
    2900             : 
    2901           8 :         list_delete(&rtadv->AdvRDNSSList);
    2902           8 :         list_delete(&rtadv->AdvDNSSLList);
    2903           8 : }
    2904             : 
    2905           2 : void rtadv_vrf_init(struct zebra_vrf *zvrf)
    2906             : {
    2907           4 :         if (!vrf_is_backend_netns() && (zvrf_id(zvrf) != VRF_DEFAULT))
    2908             :                 return;
    2909             : 
    2910           2 :         zvrf->rtadv.sock = rtadv_make_socket(zvrf->zns->ns_id);
    2911             : }
    2912             : 
    2913           2 : void rtadv_vrf_terminate(struct zebra_vrf *zvrf)
    2914             : {
    2915           4 :         if (!vrf_is_backend_netns() && (zvrf_id(zvrf) != VRF_DEFAULT))
    2916             :                 return;
    2917             : 
    2918           2 :         rtadv_event(zvrf, RTADV_STOP, 0);
    2919           2 :         if (zvrf->rtadv.sock >= 0) {
    2920           2 :                 close(zvrf->rtadv.sock);
    2921           2 :                 zvrf->rtadv.sock = -1;
    2922             :         }
    2923             : 
    2924           2 :         adv_if_clean(zvrf);
    2925           2 :         adv_msec_if_clean(zvrf);
    2926             : }
    2927             : 
    2928           2 : void rtadv_cmd_init(void)
    2929             : {
    2930           2 :         interfaces_configured_for_ra_from_bgp = 0;
    2931             : 
    2932           2 :         hook_register(zebra_if_extra_info, nd_dump_vty);
    2933           2 :         hook_register(zebra_if_config_wr, rtadv_config_write);
    2934             : 
    2935           2 :         install_element(VIEW_NODE, &show_ipv6_nd_ra_if_cmd);
    2936             : 
    2937           2 :         install_element(INTERFACE_NODE, &ipv6_nd_ra_fast_retrans_cmd);
    2938           2 :         install_element(INTERFACE_NODE, &no_ipv6_nd_ra_fast_retrans_cmd);
    2939           2 :         install_element(INTERFACE_NODE, &ipv6_nd_ra_retrans_interval_cmd);
    2940           2 :         install_element(INTERFACE_NODE, &no_ipv6_nd_ra_retrans_interval_cmd);
    2941           2 :         install_element(INTERFACE_NODE, &ipv6_nd_ra_hop_limit_cmd);
    2942           2 :         install_element(INTERFACE_NODE, &no_ipv6_nd_ra_hop_limit_cmd);
    2943           2 :         install_element(INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
    2944           2 :         install_element(INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
    2945           2 :         install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
    2946           2 :         install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
    2947           2 :         install_element(INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
    2948           2 :         install_element(INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
    2949           2 :         install_element(INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
    2950           2 :         install_element(INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
    2951           2 :         install_element(INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
    2952           2 :         install_element(INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
    2953           2 :         install_element(INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
    2954           2 :         install_element(INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
    2955           2 :         install_element(INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
    2956           2 :         install_element(INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
    2957           2 :         install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
    2958           2 :         install_element(INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
    2959           2 :         install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
    2960           2 :         install_element(INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
    2961           2 :         install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
    2962           2 :         install_element(INTERFACE_NODE,
    2963             :                         &ipv6_nd_adv_interval_config_option_cmd);
    2964           2 :         install_element(INTERFACE_NODE,
    2965             :                         &no_ipv6_nd_adv_interval_config_option_cmd);
    2966           2 :         install_element(INTERFACE_NODE, &ipv6_nd_prefix_cmd);
    2967           2 :         install_element(INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
    2968           2 :         install_element(INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
    2969           2 :         install_element(INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
    2970           2 :         install_element(INTERFACE_NODE, &ipv6_nd_mtu_cmd);
    2971           2 :         install_element(INTERFACE_NODE, &no_ipv6_nd_mtu_cmd);
    2972           2 :         install_element(INTERFACE_NODE, &ipv6_nd_rdnss_cmd);
    2973           2 :         install_element(INTERFACE_NODE, &no_ipv6_nd_rdnss_cmd);
    2974           2 :         install_element(INTERFACE_NODE, &ipv6_nd_dnssl_cmd);
    2975           2 :         install_element(INTERFACE_NODE, &no_ipv6_nd_dnssl_cmd);
    2976           2 : }
    2977             : 
    2978           1 : static int if_join_all_router(int sock, struct interface *ifp)
    2979             : {
    2980           1 :         int ret;
    2981             : 
    2982           1 :         struct ipv6_mreq mreq;
    2983             : 
    2984           1 :         memset(&mreq, 0, sizeof(mreq));
    2985           1 :         inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
    2986           1 :         mreq.ipv6mr_interface = ifp->ifindex;
    2987             : 
    2988           1 :         ret = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mreq,
    2989             :                          sizeof(mreq));
    2990           1 :         if (ret < 0)
    2991           0 :                 flog_err_sys(EC_LIB_SOCKET,
    2992             :                              "%s(%u): Failed to join group, socket %u error %s",
    2993             :                              ifp->name, ifp->ifindex, sock,
    2994             :                              safe_strerror(errno));
    2995             : 
    2996           1 :         if (IS_ZEBRA_DEBUG_EVENT)
    2997           0 :                 zlog_debug(
    2998             :                         "%s(%s:%u): Join All-Routers multicast group, socket %u",
    2999             :                         ifp->name, ifp->vrf->name, ifp->ifindex, sock);
    3000             : 
    3001           1 :         return 0;
    3002             : }
    3003             : 
    3004           0 : static int if_leave_all_router(int sock, struct interface *ifp)
    3005             : {
    3006           0 :         int ret;
    3007             : 
    3008           0 :         struct ipv6_mreq mreq;
    3009             : 
    3010           0 :         memset(&mreq, 0, sizeof(mreq));
    3011           0 :         inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
    3012           0 :         mreq.ipv6mr_interface = ifp->ifindex;
    3013             : 
    3014           0 :         ret = setsockopt(sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, (char *)&mreq,
    3015             :                          sizeof(mreq));
    3016           0 :         if (ret < 0)
    3017           0 :                 flog_err_sys(
    3018             :                         EC_LIB_SOCKET,
    3019             :                         "%s(%s:%u): Failed to leave group, socket %u error %s",
    3020             :                         ifp->name, ifp->vrf->name, ifp->ifindex, sock,
    3021             :                         safe_strerror(errno));
    3022             : 
    3023           0 :         if (IS_ZEBRA_DEBUG_EVENT)
    3024           0 :                 zlog_debug(
    3025             :                         "%s(%s:%u): Leave All-Routers multicast group, socket %u",
    3026             :                         ifp->name, ifp->vrf->name, ifp->ifindex, sock);
    3027             : 
    3028           0 :         return 0;
    3029             : }
    3030             : 
    3031           0 : bool rtadv_compiled_in(void)
    3032             : {
    3033           0 :         return true;
    3034             : }
    3035             : 
    3036             : #else /* !HAVE_RTADV */
    3037             : /*
    3038             :  * If the end user does not have RADV enabled we should
    3039             :  * handle this better
    3040             :  */
    3041             : void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS)
    3042             : {
    3043             :         if (IS_ZEBRA_DEBUG_PACKET)
    3044             :                 zlog_debug(
    3045             :                         "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
    3046             :                         zserv_command_string(hdr->command));
    3047             : 
    3048             :         return;
    3049             : }
    3050             : 
    3051             : void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS)
    3052             : {
    3053             :         if (IS_ZEBRA_DEBUG_PACKET)
    3054             :                 zlog_debug(
    3055             :                         "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
    3056             :                         zserv_command_string(hdr->command));
    3057             : 
    3058             :         return;
    3059             : }
    3060             : 
    3061             : bool rtadv_compiled_in(void)
    3062             : {
    3063             :         return false;
    3064             : }
    3065             : 
    3066             : #endif /* HAVE_RTADV */
    3067             : 
    3068           0 : uint32_t rtadv_get_interfaces_configured_from_bgp(void)
    3069             : {
    3070           0 :         return interfaces_configured_for_ra_from_bgp;
    3071             : }

Generated by: LCOV version v1.16-topotato