back to topotato report
topotato coverage report
Current view: top level - zebra - rtadv.c (source / functions) Hit Total Coverage
Test: test_bgp_set_aspath_replace.py::BGPSetAspathReplace Lines: 220 1444 15.2 %
Date: 2023-02-24 18:37:49 Functions: 28 109 25.7 %

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

Generated by: LCOV version v1.16-topotato