LCOV - code coverage report
Current view: top level - zebra - rtadv.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 76 643 11.8 %
Date: 2015-11-19 Functions: 3 47 6.4 %

          Line data    Source code
       1             : /* Router advertisement
       2             :  * Copyright (C) 2005 6WIND <jean-mickael.guerin@6wind.com>
       3             :  * Copyright (C) 1999 Kunihiro Ishiguro
       4             :  *
       5             :  * This file is part of GNU Zebra.
       6             :  *
       7             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       8             :  * under the terms of the GNU General Public License as published by the
       9             :  * Free Software Foundation; either version 2, or (at your option) any
      10             :  * later version.
      11             :  *
      12             :  * GNU Zebra is distributed in the hope that it will be useful, but
      13             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
      19             :  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      20             :  * 02111-1307, 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 "log.h"
      30             : #include "prefix.h"
      31             : #include "linklist.h"
      32             : #include "command.h"
      33             : #include "privs.h"
      34             : 
      35             : #include "zebra/interface.h"
      36             : #include "zebra/rtadv.h"
      37             : #include "zebra/debug.h"
      38             : #include "zebra/rib.h"
      39             : #include "zebra/zserv.h"
      40             : 
      41             : extern struct zebra_privs_t zserv_privs;
      42             : 
      43             : #if defined (HAVE_IPV6) && defined (RTADV)
      44             : 
      45             : #ifdef OPEN_BSD
      46             : #include <netinet/icmp6.h>
      47             : #endif
      48             : 
      49             : /* If RFC2133 definition is used. */
      50             : #ifndef IPV6_JOIN_GROUP
      51             : #define IPV6_JOIN_GROUP  IPV6_ADD_MEMBERSHIP 
      52             : #endif
      53             : #ifndef IPV6_LEAVE_GROUP
      54             : #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP 
      55             : #endif
      56             : 
      57             : #define ALLNODE   "ff02::1"
      58             : #define ALLROUTER "ff02::2"
      59             : 
      60             : extern struct zebra_t zebrad;
      61             : 
      62             : enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER, 
      63             :                   RTADV_TIMER_MSEC, RTADV_READ};
      64             : 
      65             : static void rtadv_event (enum rtadv_event, int);
      66             : 
      67             : static int if_join_all_router (int, struct interface *);
      68             : static int if_leave_all_router (int, struct interface *);
      69             : 
      70             : /* Structure which hold status of router advertisement. */
      71             : struct rtadv
      72             : {
      73             :   int sock;
      74             : 
      75             :   int adv_if_count;
      76             :   int adv_msec_if_count;
      77             : 
      78             :   struct thread *ra_read;
      79             :   struct thread *ra_timer;
      80             : };
      81             : 
      82             : struct rtadv *rtadv = NULL;
      83             : 
      84             : static struct rtadv *
      85          45 : rtadv_new (void)
      86             : {
      87          45 :   return XCALLOC (MTYPE_TMP, sizeof (struct rtadv));
      88             : }
      89             : 
      90             : static int
      91           0 : rtadv_recv_packet (int sock, u_char *buf, int buflen,
      92             :                    struct sockaddr_in6 *from, unsigned int *ifindex,
      93             :                    int *hoplimit)
      94             : {
      95             :   int ret;
      96             :   struct msghdr msg;
      97             :   struct iovec iov;
      98             :   struct cmsghdr  *cmsgptr;
      99             :   struct in6_addr dst;
     100             : 
     101             :   char adata[1024];
     102             : 
     103             :   /* Fill in message and iovec. */
     104           0 :   msg.msg_name = (void *) from;
     105           0 :   msg.msg_namelen = sizeof (struct sockaddr_in6);
     106           0 :   msg.msg_iov = &iov;
     107           0 :   msg.msg_iovlen = 1;
     108           0 :   msg.msg_control = (void *) adata;
     109           0 :   msg.msg_controllen = sizeof adata;
     110           0 :   iov.iov_base = buf;
     111           0 :   iov.iov_len = buflen;
     112             : 
     113             :   /* If recvmsg fail return minus value. */
     114           0 :   ret = recvmsg (sock, &msg, 0);
     115           0 :   if (ret < 0)
     116           0 :     return ret;
     117             : 
     118           0 :   for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
     119           0 :        cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) 
     120             :     {
     121             :       /* I want interface index which this packet comes from. */
     122           0 :       if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
     123           0 :           cmsgptr->cmsg_type == IPV6_PKTINFO) 
     124             :         {
     125             :           struct in6_pktinfo *ptr;
     126             :           
     127           0 :           ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
     128           0 :           *ifindex = ptr->ipi6_ifindex;
     129           0 :           memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr));
     130             :         }
     131             : 
     132             :       /* Incoming packet's hop limit. */
     133           0 :       if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
     134           0 :           cmsgptr->cmsg_type == IPV6_HOPLIMIT)
     135             :         {
     136           0 :           int *hoptr = (int *) CMSG_DATA (cmsgptr);
     137           0 :           *hoplimit = *hoptr;
     138             :         }
     139             :     }
     140           0 :   return ret;
     141             : }
     142             : 
     143             : #define RTADV_MSG_SIZE 4096
     144             : 
     145             : /* Send router advertisement packet. */
     146             : static void
     147           0 : rtadv_send_packet (int sock, struct interface *ifp)
     148             : {
     149             :   struct msghdr msg;
     150             :   struct iovec iov;
     151             :   struct cmsghdr  *cmsgptr;
     152             :   struct in6_pktinfo *pkt;
     153             :   struct sockaddr_in6 addr;
     154             : #ifdef HAVE_STRUCT_SOCKADDR_DL
     155             :   struct sockaddr_dl *sdl;
     156             : #endif /* HAVE_STRUCT_SOCKADDR_DL */
     157             :   static void *adata = NULL;
     158             :   unsigned char buf[RTADV_MSG_SIZE];
     159             :   struct nd_router_advert *rtadv;
     160             :   int ret;
     161           0 :   int len = 0;
     162             :   struct zebra_if *zif;
     163             :   struct rtadv_prefix *rprefix;
     164           0 :   u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
     165             :   struct listnode *node;
     166             :   u_int16_t pkt_RouterLifetime;
     167             : 
     168             :   /*
     169             :    * Allocate control message bufffer.  This is dynamic because
     170             :    * CMSG_SPACE is not guaranteed not to call a function.  Note that
     171             :    * the size will be different on different architectures due to
     172             :    * differing alignment rules.
     173             :    */
     174           0 :   if (adata == NULL)
     175             :     {
     176             :       /* XXX Free on shutdown. */
     177           0 :       adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo)));
     178             :            
     179           0 :       if (adata == NULL)
     180           0 :         zlog_err("rtadv_send_packet: can't malloc control data\n");
     181             :     }
     182             : 
     183             :   /* Logging of packet. */
     184           0 :   if (IS_ZEBRA_DEBUG_PACKET)
     185           0 :     zlog_debug ("Router advertisement send to %s", ifp->name);
     186             : 
     187             :   /* Fill in sockaddr_in6. */
     188           0 :   memset (&addr, 0, sizeof (struct sockaddr_in6));
     189           0 :   addr.sin6_family = AF_INET6;
     190             : #ifdef SIN6_LEN
     191             :   addr.sin6_len = sizeof (struct sockaddr_in6);
     192             : #endif /* SIN6_LEN */
     193           0 :   addr.sin6_port = htons (IPPROTO_ICMPV6);
     194           0 :   IPV6_ADDR_COPY (&addr.sin6_addr, all_nodes_addr);
     195             : 
     196             :   /* Fetch interface information. */
     197           0 :   zif = ifp->info;
     198             : 
     199             :   /* Make router advertisement message. */
     200           0 :   rtadv = (struct nd_router_advert *) buf;
     201             : 
     202           0 :   rtadv->nd_ra_type = ND_ROUTER_ADVERT;
     203           0 :   rtadv->nd_ra_code = 0;
     204           0 :   rtadv->nd_ra_cksum = 0;
     205             : 
     206           0 :   rtadv->nd_ra_curhoplimit = 64;
     207             : 
     208             :   /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
     209           0 :   rtadv->nd_ra_flags_reserved =
     210           0 :     zif->rtadv.AdvDefaultLifetime == 0 ? 0 : zif->rtadv.DefaultPreference;
     211           0 :   rtadv->nd_ra_flags_reserved <<= 3;
     212             : 
     213           0 :   if (zif->rtadv.AdvManagedFlag)
     214           0 :     rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
     215           0 :   if (zif->rtadv.AdvOtherConfigFlag)
     216           0 :     rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
     217           0 :   if (zif->rtadv.AdvHomeAgentFlag)
     218           0 :     rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;
     219             :   /* Note that according to Neighbor Discovery (RFC 4861 [18]),
     220             :    * AdvDefaultLifetime is by default based on the value of
     221             :    * MaxRtrAdvInterval.  AdvDefaultLifetime is used in the Router Lifetime
     222             :    * field of Router Advertisements.  Given that this field is expressed
     223             :    * in seconds, a small MaxRtrAdvInterval value can result in a zero
     224             :    * value for this field.  To prevent this, routers SHOULD keep
     225             :    * AdvDefaultLifetime in at least one second, even if the use of
     226             :    * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
     227           0 :   pkt_RouterLifetime = zif->rtadv.AdvDefaultLifetime != -1 ?
     228           0 :     zif->rtadv.AdvDefaultLifetime :
     229           0 :     MAX (1, 0.003 * zif->rtadv.MaxRtrAdvInterval);
     230           0 :   rtadv->nd_ra_router_lifetime = htons (pkt_RouterLifetime);
     231           0 :   rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);
     232           0 :   rtadv->nd_ra_retransmit = htonl (0);
     233             : 
     234           0 :   len = sizeof (struct nd_router_advert);
     235             : 
     236             :   /* If both the Home Agent Preference and Home Agent Lifetime are set to
     237             :    * their default values specified above, this option SHOULD NOT be
     238             :    * included in the Router Advertisement messages sent by this home
     239             :    * agent. -- RFC6275, 7.4 */
     240             :   if
     241           0 :   (
     242           0 :     zif->rtadv.AdvHomeAgentFlag &&
     243           0 :     (zif->rtadv.HomeAgentPreference || zif->rtadv.HomeAgentLifetime != -1)
     244             :   )
     245             :     {
     246           0 :       struct nd_opt_homeagent_info *ndopt_hai = 
     247           0 :         (struct nd_opt_homeagent_info *)(buf + len);
     248           0 :       ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
     249           0 :       ndopt_hai->nd_opt_hai_len = 1;
     250           0 :       ndopt_hai->nd_opt_hai_reserved = 0;
     251           0 :       ndopt_hai->nd_opt_hai_preference = htons(zif->rtadv.HomeAgentPreference);
     252             :       /* 16-bit unsigned integer.  The lifetime associated with the home
     253             :        * agent in units of seconds.  The default value is the same as the
     254             :        * Router Lifetime, as specified in the main body of the Router
     255             :        * Advertisement.  The maximum value corresponds to 18.2 hours.  A
     256             :        * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
     257           0 :       ndopt_hai->nd_opt_hai_lifetime = htons
     258             :       (
     259           0 :         zif->rtadv.HomeAgentLifetime != -1 ?
     260           0 :         zif->rtadv.HomeAgentLifetime :
     261             :         MAX (1, pkt_RouterLifetime) /* 0 is OK for RL, but not for HAL*/
     262             :       );
     263           0 :       len += sizeof(struct nd_opt_homeagent_info);
     264             :     }
     265             : 
     266           0 :   if (zif->rtadv.AdvIntervalOption)
     267             :     {
     268           0 :       struct nd_opt_adv_interval *ndopt_adv = 
     269           0 :         (struct nd_opt_adv_interval *)(buf + len);
     270           0 :       ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL;
     271           0 :       ndopt_adv->nd_opt_ai_len = 1;
     272           0 :       ndopt_adv->nd_opt_ai_reserved = 0;
     273           0 :       ndopt_adv->nd_opt_ai_interval = htonl(zif->rtadv.MaxRtrAdvInterval);
     274           0 :       len += sizeof(struct nd_opt_adv_interval);
     275             :     }
     276             : 
     277             :   /* Fill in prefix. */
     278           0 :   for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
     279             :     {
     280             :       struct nd_opt_prefix_info *pinfo;
     281             : 
     282           0 :       pinfo = (struct nd_opt_prefix_info *) (buf + len);
     283             : 
     284           0 :       pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
     285           0 :       pinfo->nd_opt_pi_len = 4;
     286           0 :       pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
     287             : 
     288           0 :       pinfo->nd_opt_pi_flags_reserved = 0;
     289           0 :       if (rprefix->AdvOnLinkFlag)
     290           0 :         pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
     291           0 :       if (rprefix->AdvAutonomousFlag)
     292           0 :         pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
     293           0 :       if (rprefix->AdvRouterAddressFlag)
     294           0 :         pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
     295             : 
     296           0 :       pinfo->nd_opt_pi_valid_time = htonl (rprefix->AdvValidLifetime);
     297           0 :       pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime);
     298           0 :       pinfo->nd_opt_pi_reserved2 = 0;
     299             : 
     300           0 :       IPV6_ADDR_COPY (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.prefix);
     301             : 
     302             : #ifdef DEBUG
     303             :       {
     304             :         u_char buf[INET6_ADDRSTRLEN];
     305             : 
     306             :         zlog_debug ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix, 
     307             :                    buf, INET6_ADDRSTRLEN));
     308             : 
     309             :       }
     310             : #endif /* DEBUG */
     311             : 
     312           0 :       len += sizeof (struct nd_opt_prefix_info);
     313             :     }
     314             : 
     315             :   /* Hardware address. */
     316             : #ifdef HAVE_STRUCT_SOCKADDR_DL
     317             :   sdl = &ifp->sdl;
     318             :   if (sdl != NULL && sdl->sdl_alen != 0)
     319             :     {
     320             :       buf[len++] = ND_OPT_SOURCE_LINKADDR;
     321             : 
     322             :       /* Option length should be rounded up to next octet if
     323             :          the link address does not end on an octet boundary. */
     324             :       buf[len++] = (sdl->sdl_alen + 9) >> 3;
     325             : 
     326             :       memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen);
     327             :       len += sdl->sdl_alen;
     328             : 
     329             :       /* Pad option to end on an octet boundary. */
     330             :       memset (buf + len, 0, -(sdl->sdl_alen + 2) & 0x7);
     331             :       len += -(sdl->sdl_alen + 2) & 0x7;
     332             :     }
     333             : #else
     334           0 :   if (ifp->hw_addr_len != 0)
     335             :     {
     336           0 :       buf[len++] = ND_OPT_SOURCE_LINKADDR;
     337             : 
     338             :       /* Option length should be rounded up to next octet if
     339             :          the link address does not end on an octet boundary. */
     340           0 :       buf[len++] = (ifp->hw_addr_len + 9) >> 3;
     341             : 
     342           0 :       memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len);
     343           0 :       len += ifp->hw_addr_len;
     344             : 
     345             :       /* Pad option to end on an octet boundary. */
     346           0 :       memset (buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7);
     347           0 :       len += -(ifp->hw_addr_len + 2) & 0x7;
     348             :     }
     349             : #endif /* HAVE_STRUCT_SOCKADDR_DL */
     350             : 
     351             :   /* MTU */
     352           0 :   if (zif->rtadv.AdvLinkMTU)
     353             :     {
     354           0 :       struct nd_opt_mtu * opt = (struct nd_opt_mtu *) (buf + len);
     355           0 :       opt->nd_opt_mtu_type = ND_OPT_MTU;
     356           0 :       opt->nd_opt_mtu_len = 1;
     357           0 :       opt->nd_opt_mtu_reserved = 0;
     358           0 :       opt->nd_opt_mtu_mtu = htonl (zif->rtadv.AdvLinkMTU);
     359           0 :       len += sizeof (struct nd_opt_mtu);
     360             :     }
     361             : 
     362           0 :   msg.msg_name = (void *) &addr;
     363           0 :   msg.msg_namelen = sizeof (struct sockaddr_in6);
     364           0 :   msg.msg_iov = &iov;
     365           0 :   msg.msg_iovlen = 1;
     366           0 :   msg.msg_control = (void *) adata;
     367           0 :   msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
     368           0 :   msg.msg_flags = 0;
     369           0 :   iov.iov_base = buf;
     370           0 :   iov.iov_len = len;
     371             : 
     372           0 :   cmsgptr = ZCMSG_FIRSTHDR(&msg);
     373           0 :   cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
     374           0 :   cmsgptr->cmsg_level = IPPROTO_IPV6;
     375           0 :   cmsgptr->cmsg_type = IPV6_PKTINFO;
     376             : 
     377           0 :   pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
     378           0 :   memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
     379           0 :   pkt->ipi6_ifindex = ifp->ifindex;
     380             : 
     381           0 :   ret = sendmsg (sock, &msg, 0);
     382           0 :   if (ret < 0)
     383             :     {
     384           0 :       zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
     385           0 :                 errno, safe_strerror(errno));
     386             :     }
     387           0 : }
     388             : 
     389             : static int
     390           0 : rtadv_timer (struct thread *thread)
     391             : {
     392             :   struct listnode *node, *nnode;
     393             :   struct interface *ifp;
     394             :   struct zebra_if *zif;
     395             :   int period;
     396             : 
     397           0 :   rtadv->ra_timer = NULL;
     398           0 :   if (rtadv->adv_msec_if_count == 0)
     399             :     {
     400           0 :       period = 1000; /* 1 s */
     401           0 :       rtadv_event (RTADV_TIMER, 1 /* 1 s */);
     402             :     } 
     403             :   else
     404             :     {
     405           0 :       period = 10; /* 10 ms */
     406           0 :       rtadv_event (RTADV_TIMER_MSEC, 10 /* 10 ms */);
     407             :     }
     408             : 
     409           0 :   for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
     410             :     {
     411           0 :       if (if_is_loopback (ifp) || ! if_is_operative (ifp))
     412           0 :         continue;
     413             : 
     414           0 :       zif = ifp->info;
     415             : 
     416           0 :       if (zif->rtadv.AdvSendAdvertisements)
     417             :         { 
     418           0 :           zif->rtadv.AdvIntervalTimer -= period;
     419           0 :           if (zif->rtadv.AdvIntervalTimer <= 0)
     420             :             {
     421             :               /* FIXME: using MaxRtrAdvInterval each time isn't what section
     422             :                  6.2.4 of RFC4861 tells to do. */
     423           0 :               zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
     424           0 :               rtadv_send_packet (rtadv->sock, ifp);
     425             :             }
     426             :         }
     427             :     }
     428           0 :   return 0;
     429             : }
     430             : 
     431             : static void
     432           0 : rtadv_process_solicit (struct interface *ifp)
     433             : {
     434           0 :   zlog_info ("Router solicitation received on %s", ifp->name);
     435             : 
     436           0 :   rtadv_send_packet (rtadv->sock, ifp);
     437           0 : }
     438             : 
     439             : static void
     440           0 : rtadv_process_advert (void)
     441             : {
     442           0 :   zlog_info ("Router advertisement received");
     443           0 : }
     444             : 
     445             : static void
     446           0 : rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit)
     447             : {
     448             :   struct icmp6_hdr *icmph;
     449             :   struct interface *ifp;
     450             :   struct zebra_if *zif;
     451             : 
     452             :   /* Interface search. */
     453           0 :   ifp = if_lookup_by_index (ifindex);
     454           0 :   if (ifp == NULL)
     455             :     {
     456           0 :       zlog_warn ("Unknown interface index: %d", ifindex);
     457           0 :       return;
     458             :     }
     459             : 
     460           0 :   if (if_is_loopback (ifp))
     461           0 :     return;
     462             : 
     463             :   /* Check interface configuration. */
     464           0 :   zif = ifp->info;
     465           0 :   if (! zif->rtadv.AdvSendAdvertisements)
     466           0 :     return;
     467             : 
     468             :   /* ICMP message length check. */
     469           0 :   if (len < sizeof (struct icmp6_hdr))
     470             :     {
     471           0 :       zlog_warn ("Invalid ICMPV6 packet length: %d", len);
     472           0 :       return;
     473             :     }
     474             : 
     475           0 :   icmph = (struct icmp6_hdr *) buf;
     476             : 
     477             :   /* ICMP message type check. */
     478           0 :   if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
     479           0 :       icmph->icmp6_type != ND_ROUTER_ADVERT)
     480             :     {
     481           0 :       zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type);
     482           0 :       return;
     483             :     }
     484             : 
     485             :   /* Hoplimit check. */
     486           0 :   if (hoplimit >= 0 && hoplimit != 255)
     487             :     {
     488           0 :       zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
     489             :                  hoplimit);
     490           0 :       return;
     491             :     }
     492             : 
     493             :   /* Check ICMP message type. */
     494           0 :   if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
     495           0 :     rtadv_process_solicit (ifp);
     496           0 :   else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
     497           0 :     rtadv_process_advert ();
     498             : 
     499           0 :   return;
     500             : }
     501             : 
     502             : static int
     503           0 : rtadv_read (struct thread *thread)
     504             : {
     505             :   int sock;
     506             :   int len;
     507             :   u_char buf[RTADV_MSG_SIZE];
     508             :   struct sockaddr_in6 from;
     509           0 :   unsigned int ifindex = 0;
     510           0 :   int hoplimit = -1;
     511             : 
     512           0 :   sock = THREAD_FD (thread);
     513           0 :   rtadv->ra_read = NULL;
     514             : 
     515             :   /* Register myself. */
     516           0 :   rtadv_event (RTADV_READ, sock);
     517             : 
     518           0 :   len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
     519             : 
     520           0 :   if (len < 0) 
     521             :     {
     522           0 :       zlog_warn ("router solicitation recv failed: %s.", safe_strerror (errno));
     523           0 :       return len;
     524             :     }
     525             : 
     526           0 :   rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit);
     527             : 
     528           0 :   return 0;
     529             : }
     530             : 
     531             : static int
     532          45 : rtadv_make_socket (void)
     533             : {
     534             :   int sock;
     535             :   int ret;
     536             :   struct icmp6_filter filter;
     537             : 
     538          45 :   if ( zserv_privs.change (ZPRIVS_RAISE) )
     539           0 :        zlog_err ("rtadv_make_socket: could not raise privs, %s",
     540           0 :                   safe_strerror (errno) );
     541             :                   
     542          45 :   sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
     543             : 
     544          45 :   if ( zserv_privs.change (ZPRIVS_LOWER) )
     545           0 :        zlog_err ("rtadv_make_socket: could not lower privs, %s",
     546           0 :                          safe_strerror (errno) );
     547             : 
     548             :   /* When we can't make ICMPV6 socket simply back.  Router
     549             :      advertisement feature will not be supported. */
     550          45 :   if (sock < 0)
     551           0 :     return -1;
     552             : 
     553          45 :   ret = setsockopt_ipv6_pktinfo (sock, 1);
     554          45 :   if (ret < 0)
     555           0 :     return ret;
     556          45 :   ret = setsockopt_ipv6_multicast_loop (sock, 0);
     557          45 :   if (ret < 0)
     558           0 :     return ret;
     559          45 :   ret = setsockopt_ipv6_unicast_hops (sock, 255);
     560          45 :   if (ret < 0)
     561           0 :     return ret;
     562          45 :   ret = setsockopt_ipv6_multicast_hops (sock, 255);
     563          45 :   if (ret < 0)
     564           0 :     return ret;
     565          45 :   ret = setsockopt_ipv6_hoplimit (sock, 1);
     566          45 :   if (ret < 0)
     567           0 :     return ret;
     568             : 
     569          45 :   ICMP6_FILTER_SETBLOCKALL(&filter);
     570          45 :   ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
     571          45 :   ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter);
     572             : 
     573          45 :   ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
     574             :                     sizeof (struct icmp6_filter));
     575          45 :   if (ret < 0)
     576             :     {
     577           0 :       zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno));
     578           0 :       return ret;
     579             :     }
     580             : 
     581          45 :   return sock;
     582             : }
     583             : 
     584             : static struct rtadv_prefix *
     585           0 : rtadv_prefix_new (void)
     586             : {
     587           0 :   return XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix));
     588             : }
     589             : 
     590             : static void
     591           0 : rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
     592             : {
     593           0 :   XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
     594           0 : }
     595             : 
     596             : static struct rtadv_prefix *
     597           0 : rtadv_prefix_lookup (struct list *rplist, struct prefix_ipv6 *p)
     598             : {
     599             :   struct listnode *node;
     600             :   struct rtadv_prefix *rprefix;
     601             : 
     602           0 :   for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))
     603           0 :     if (prefix_same ((struct prefix *) &rprefix->prefix, (struct prefix *) p))
     604           0 :       return rprefix;
     605           0 :   return NULL;
     606             : }
     607             : 
     608             : static struct rtadv_prefix *
     609           0 : rtadv_prefix_get (struct list *rplist, struct prefix_ipv6 *p)
     610             : {
     611             :   struct rtadv_prefix *rprefix;
     612             :   
     613           0 :   rprefix = rtadv_prefix_lookup (rplist, p);
     614           0 :   if (rprefix)
     615           0 :     return rprefix;
     616             : 
     617           0 :   rprefix = rtadv_prefix_new ();
     618           0 :   memcpy (&rprefix->prefix, p, sizeof (struct prefix_ipv6));
     619           0 :   listnode_add (rplist, rprefix);
     620             : 
     621           0 :   return rprefix;
     622             : }
     623             : 
     624             : static void
     625           0 : rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp)
     626             : {
     627             :   struct rtadv_prefix *rprefix;
     628             :   
     629           0 :   rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix);
     630             : 
     631             :   /* Set parameters. */
     632           0 :   rprefix->AdvValidLifetime = rp->AdvValidLifetime;
     633           0 :   rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
     634           0 :   rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
     635           0 :   rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
     636           0 :   rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
     637           0 : }
     638             : 
     639             : static int
     640           0 : rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp)
     641             : {
     642             :   struct rtadv_prefix *rprefix;
     643             :   
     644           0 :   rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix);
     645           0 :   if (rprefix != NULL)
     646             :     {
     647           0 :       listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix);
     648           0 :       rtadv_prefix_free (rprefix);
     649           0 :       return 1;
     650             :     }
     651             :   else
     652           0 :     return 0;
     653             : }
     654             : 
     655           0 : DEFUN (ipv6_nd_suppress_ra,
     656             :        ipv6_nd_suppress_ra_cmd,
     657             :        "ipv6 nd suppress-ra",
     658             :        "Interface IPv6 config commands\n"
     659             :        "Neighbor discovery\n"
     660             :        "Suppress Router Advertisement\n")
     661             : {
     662             :   struct interface *ifp;
     663             :   struct zebra_if *zif;
     664             : 
     665           0 :   ifp = vty->index;
     666           0 :   zif = ifp->info;
     667             : 
     668           0 :   if (if_is_loopback (ifp))
     669             :     {
     670           0 :       vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
     671           0 :       return CMD_WARNING;
     672             :     }
     673             : 
     674           0 :   if (zif->rtadv.AdvSendAdvertisements)
     675             :     {
     676           0 :       zif->rtadv.AdvSendAdvertisements = 0;
     677           0 :       zif->rtadv.AdvIntervalTimer = 0;
     678           0 :       rtadv->adv_if_count--;
     679             : 
     680           0 :       if_leave_all_router (rtadv->sock, ifp);
     681             : 
     682           0 :       if (rtadv->adv_if_count == 0)
     683           0 :         rtadv_event (RTADV_STOP, 0);
     684             :     }
     685             : 
     686           0 :   return CMD_SUCCESS;
     687             : }
     688             : 
     689           0 : DEFUN (no_ipv6_nd_suppress_ra,
     690             :        no_ipv6_nd_suppress_ra_cmd,
     691             :        "no ipv6 nd suppress-ra",
     692             :        NO_STR
     693             :        "Interface IPv6 config commands\n"
     694             :        "Neighbor discovery\n"
     695             :        "Suppress Router Advertisement\n")
     696             : {
     697             :   struct interface *ifp;
     698             :   struct zebra_if *zif;
     699             : 
     700           0 :   ifp = vty->index;
     701           0 :   zif = ifp->info;
     702             : 
     703           0 :   if (if_is_loopback (ifp))
     704             :     {
     705           0 :       vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
     706           0 :       return CMD_WARNING;
     707             :     }
     708             : 
     709           0 :   if (! zif->rtadv.AdvSendAdvertisements)
     710             :     {
     711           0 :       zif->rtadv.AdvSendAdvertisements = 1;
     712           0 :       zif->rtadv.AdvIntervalTimer = 0;
     713           0 :       rtadv->adv_if_count++;
     714             : 
     715           0 :       if_join_all_router (rtadv->sock, ifp);
     716             : 
     717           0 :       if (rtadv->adv_if_count == 1)
     718           0 :         rtadv_event (RTADV_START, rtadv->sock);
     719             :     }
     720             : 
     721           0 :   return CMD_SUCCESS;
     722             : }
     723             : 
     724           0 : DEFUN (ipv6_nd_ra_interval_msec,
     725             :        ipv6_nd_ra_interval_msec_cmd,
     726             :        "ipv6 nd ra-interval msec <70-1800000>",
     727             :        "Interface IPv6 config commands\n"
     728             :        "Neighbor discovery\n"
     729             :        "Router Advertisement interval\n"
     730             :        "Router Advertisement interval in milliseconds\n")
     731             : {
     732             :   unsigned interval;
     733           0 :   struct interface *ifp = (struct interface *) vty->index;
     734           0 :   struct zebra_if *zif = ifp->info;
     735             : 
     736           0 :   VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 70, 1800000);
     737           0 :   if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000))
     738             :   {
     739           0 :     vty_out (vty, "This ra-interval would conflict with configured ra-lifetime!%s", VTY_NEWLINE);
     740           0 :     return CMD_WARNING;
     741             :   }
     742             : 
     743           0 :   if (zif->rtadv.MaxRtrAdvInterval % 1000)
     744           0 :     rtadv->adv_msec_if_count--;
     745             : 
     746           0 :   if (interval % 1000)
     747           0 :     rtadv->adv_msec_if_count++;
     748             :   
     749           0 :   zif->rtadv.MaxRtrAdvInterval = interval;
     750           0 :   zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
     751           0 :   zif->rtadv.AdvIntervalTimer = 0;
     752             : 
     753           0 :   return CMD_SUCCESS;
     754             : }
     755             : 
     756           0 : DEFUN (ipv6_nd_ra_interval,
     757             :        ipv6_nd_ra_interval_cmd,
     758             :        "ipv6 nd ra-interval <1-1800>",
     759             :        "Interface IPv6 config commands\n"
     760             :        "Neighbor discovery\n"
     761             :        "Router Advertisement interval\n"
     762             :        "Router Advertisement interval in seconds\n")
     763             : {
     764             :   unsigned interval;
     765           0 :   struct interface *ifp = (struct interface *) vty->index;
     766           0 :   struct zebra_if *zif = ifp->info;
     767             : 
     768           0 :   VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 1, 1800);
     769           0 :   if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime))
     770             :   {
     771           0 :     vty_out (vty, "This ra-interval would conflict with configured ra-lifetime!%s", VTY_NEWLINE);
     772           0 :     return CMD_WARNING;
     773             :   }
     774             : 
     775           0 :   if (zif->rtadv.MaxRtrAdvInterval % 1000)
     776           0 :     rtadv->adv_msec_if_count--;
     777             :         
     778             :   /* convert to milliseconds */
     779           0 :   interval = interval * 1000; 
     780             :         
     781           0 :   zif->rtadv.MaxRtrAdvInterval = interval;
     782           0 :   zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
     783           0 :   zif->rtadv.AdvIntervalTimer = 0;
     784             : 
     785           0 :   return CMD_SUCCESS;
     786             : }
     787             : 
     788           0 : DEFUN (no_ipv6_nd_ra_interval,
     789             :        no_ipv6_nd_ra_interval_cmd,
     790             :        "no ipv6 nd ra-interval",
     791             :        NO_STR
     792             :        "Interface IPv6 config commands\n"
     793             :        "Neighbor discovery\n"
     794             :        "Router Advertisement interval\n")
     795             : {
     796             :   struct interface *ifp;
     797             :   struct zebra_if *zif;
     798             : 
     799           0 :   ifp = (struct interface *) vty->index;
     800           0 :   zif = ifp->info;
     801             : 
     802           0 :   if (zif->rtadv.MaxRtrAdvInterval % 1000)
     803           0 :     rtadv->adv_msec_if_count--;
     804             :   
     805           0 :   zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
     806           0 :   zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
     807           0 :   zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
     808             : 
     809           0 :   return CMD_SUCCESS;
     810             : }
     811             : 
     812             : ALIAS (no_ipv6_nd_ra_interval,
     813             :        no_ipv6_nd_ra_interval_val_cmd,
     814             :        "no ipv6 nd ra-interval <1-1800>",
     815             :        NO_STR
     816             :        "Interface IPv6 config commands\n"
     817             :        "Neighbor discovery\n"
     818             :        "Router Advertisement interval\n")
     819             : 
     820             : ALIAS (no_ipv6_nd_ra_interval,
     821             :        no_ipv6_nd_ra_interval_msec_val_cmd,
     822             :        "no ipv6 nd ra-interval msec <1-1800000>",
     823             :        NO_STR
     824             :        "Interface IPv6 config commands\n"
     825             :        "Neighbor discovery\n"
     826             :        "Router Advertisement interval\n"
     827             :        "Router Advertisement interval in milliseconds\n")
     828             : 
     829           0 : DEFUN (ipv6_nd_ra_lifetime,
     830             :        ipv6_nd_ra_lifetime_cmd,
     831             :        "ipv6 nd ra-lifetime <0-9000>",
     832             :        "Interface IPv6 config commands\n"
     833             :        "Neighbor discovery\n"
     834             :        "Router lifetime\n"
     835             :        "Router lifetime in seconds (0 stands for a non-default gw)\n")
     836             : {
     837             :   int lifetime;
     838             :   struct interface *ifp;
     839             :   struct zebra_if *zif;
     840             : 
     841           0 :   ifp = (struct interface *) vty->index;
     842           0 :   zif = ifp->info;
     843             : 
     844           0 :   VTY_GET_INTEGER_RANGE ("router lifetime", lifetime, argv[0], 0, 9000);
     845             : 
     846             :   /* The value to be placed in the Router Lifetime field
     847             :    * of Router Advertisements sent from the interface,
     848             :    * in seconds.  MUST be either zero or between
     849             :    * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
     850           0 :   if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval))
     851             :     {
     852           0 :       vty_out (vty, "This ra-lifetime would conflict with configured ra-interval%s", VTY_NEWLINE);
     853           0 :       return CMD_WARNING;
     854             :     }
     855             : 
     856           0 :   zif->rtadv.AdvDefaultLifetime = lifetime;
     857             : 
     858           0 :   return CMD_SUCCESS;
     859             : }
     860             : 
     861           0 : DEFUN (no_ipv6_nd_ra_lifetime,
     862             :        no_ipv6_nd_ra_lifetime_cmd,
     863             :        "no ipv6 nd ra-lifetime",
     864             :        NO_STR
     865             :        "Interface IPv6 config commands\n"
     866             :        "Neighbor discovery\n"
     867             :        "Router lifetime\n")
     868             : {
     869             :   struct interface *ifp;
     870             :   struct zebra_if *zif;
     871             : 
     872           0 :   ifp = (struct interface *) vty->index;
     873           0 :   zif = ifp->info;
     874             : 
     875           0 :   zif->rtadv.AdvDefaultLifetime = -1;
     876             : 
     877           0 :   return CMD_SUCCESS;
     878             : }
     879             : 
     880             : ALIAS (no_ipv6_nd_ra_lifetime,
     881             :        no_ipv6_nd_ra_lifetime_val_cmd,
     882             :        "no ipv6 nd ra-lifetime <0-9000>",
     883             :        NO_STR
     884             :        "Interface IPv6 config commands\n"
     885             :        "Neighbor discovery\n"
     886             :        "Router lifetime\n"
     887             :        "Router lifetime in seconds (0 stands for a non-default gw)\n")
     888             : 
     889           0 : DEFUN (ipv6_nd_reachable_time,
     890             :        ipv6_nd_reachable_time_cmd,
     891             :        "ipv6 nd reachable-time <1-3600000>",
     892             :        "Interface IPv6 config commands\n"
     893             :        "Neighbor discovery\n"
     894             :        "Reachable time\n"
     895             :        "Reachable time in milliseconds\n")
     896             : {
     897           0 :   struct interface *ifp = (struct interface *) vty->index;
     898           0 :   struct zebra_if *zif = ifp->info;
     899           0 :   VTY_GET_INTEGER_RANGE ("reachable time", zif->rtadv.AdvReachableTime, argv[0], 1, RTADV_MAX_REACHABLE_TIME);
     900           0 :   return CMD_SUCCESS;
     901             : }
     902             : 
     903           0 : DEFUN (no_ipv6_nd_reachable_time,
     904             :        no_ipv6_nd_reachable_time_cmd,
     905             :        "no ipv6 nd reachable-time",
     906             :        NO_STR
     907             :        "Interface IPv6 config commands\n"
     908             :        "Neighbor discovery\n"
     909             :        "Reachable time\n")
     910             : {
     911             :   struct interface *ifp;
     912             :   struct zebra_if *zif;
     913             : 
     914           0 :   ifp = (struct interface *) vty->index;
     915           0 :   zif = ifp->info;
     916             : 
     917           0 :   zif->rtadv.AdvReachableTime = 0;
     918             : 
     919           0 :   return CMD_SUCCESS;
     920             : }
     921             : 
     922             : ALIAS (no_ipv6_nd_reachable_time,
     923             :        no_ipv6_nd_reachable_time_val_cmd,
     924             :        "no ipv6 nd reachable-time <1-3600000>",
     925             :        NO_STR
     926             :        "Interface IPv6 config commands\n"
     927             :        "Neighbor discovery\n"
     928             :        "Reachable time\n"
     929             :        "Reachable time in milliseconds\n")
     930             : 
     931           0 : DEFUN (ipv6_nd_homeagent_preference,
     932             :        ipv6_nd_homeagent_preference_cmd,
     933             :        "ipv6 nd home-agent-preference <0-65535>",
     934             :        "Interface IPv6 config commands\n"
     935             :        "Neighbor discovery\n"
     936             :        "Home Agent preference\n"
     937             :        "preference value (default is 0, least preferred)\n")
     938             : {
     939           0 :   struct interface *ifp = (struct interface *) vty->index;
     940           0 :   struct zebra_if *zif = ifp->info;
     941           0 :   VTY_GET_INTEGER_RANGE ("home agent preference", zif->rtadv.HomeAgentPreference, argv[0], 0, 65535);
     942           0 :   return CMD_SUCCESS;
     943             : }
     944             : 
     945           0 : DEFUN (no_ipv6_nd_homeagent_preference,
     946             :        no_ipv6_nd_homeagent_preference_cmd,
     947             :        "no ipv6 nd home-agent-preference",
     948             :        NO_STR
     949             :        "Interface IPv6 config commands\n"
     950             :        "Neighbor discovery\n"
     951             :        "Home Agent preference\n")
     952             : {
     953             :   struct interface *ifp;
     954             :   struct zebra_if *zif;
     955             : 
     956           0 :   ifp = (struct interface *) vty->index;
     957           0 :   zif = ifp->info;
     958             : 
     959           0 :   zif->rtadv.HomeAgentPreference = 0;
     960             : 
     961           0 :   return CMD_SUCCESS;
     962             : }
     963             : 
     964             : ALIAS (no_ipv6_nd_homeagent_preference,
     965             :        no_ipv6_nd_homeagent_preference_val_cmd,
     966             :        "no ipv6 nd home-agent-preference <0-65535>",
     967             :        NO_STR
     968             :        "Interface IPv6 config commands\n"
     969             :        "Neighbor discovery\n"
     970             :        "Home Agent preference\n"
     971             :        "preference value (default is 0, least preferred)\n")
     972             : 
     973           0 : DEFUN (ipv6_nd_homeagent_lifetime,
     974             :        ipv6_nd_homeagent_lifetime_cmd,
     975             :        "ipv6 nd home-agent-lifetime <0-65520>",
     976             :        "Interface IPv6 config commands\n"
     977             :        "Neighbor discovery\n"
     978             :        "Home Agent lifetime\n"
     979             :        "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
     980             : {
     981           0 :   struct interface *ifp = (struct interface *) vty->index;
     982           0 :   struct zebra_if *zif = ifp->info;
     983           0 :   VTY_GET_INTEGER_RANGE ("home agent lifetime", zif->rtadv.HomeAgentLifetime, argv[0], 0, RTADV_MAX_HALIFETIME);
     984           0 :   return CMD_SUCCESS;
     985             : }
     986             : 
     987           0 : DEFUN (no_ipv6_nd_homeagent_lifetime,
     988             :        no_ipv6_nd_homeagent_lifetime_cmd,
     989             :        "no ipv6 nd home-agent-lifetime",
     990             :        NO_STR
     991             :        "Interface IPv6 config commands\n"
     992             :        "Neighbor discovery\n"
     993             :        "Home Agent lifetime\n")
     994             : {
     995             :   struct interface *ifp;
     996             :   struct zebra_if *zif;
     997             : 
     998           0 :   ifp = (struct interface *) vty->index;
     999           0 :   zif = ifp->info;
    1000             : 
    1001           0 :   zif->rtadv.HomeAgentLifetime = -1;
    1002             : 
    1003           0 :   return CMD_SUCCESS;
    1004             : }
    1005             : 
    1006             : ALIAS (no_ipv6_nd_homeagent_lifetime,
    1007             :        no_ipv6_nd_homeagent_lifetime_val_cmd,
    1008             :        "no ipv6 nd home-agent-lifetime <0-65520>",
    1009             :        NO_STR
    1010             :        "Interface IPv6 config commands\n"
    1011             :        "Neighbor discovery\n"
    1012             :        "Home Agent lifetime\n"
    1013             :        "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
    1014             : 
    1015           0 : DEFUN (ipv6_nd_managed_config_flag,
    1016             :        ipv6_nd_managed_config_flag_cmd,
    1017             :        "ipv6 nd managed-config-flag",
    1018             :        "Interface IPv6 config commands\n"
    1019             :        "Neighbor discovery\n"
    1020             :        "Managed address configuration flag\n")
    1021             : {
    1022             :   struct interface *ifp;
    1023             :   struct zebra_if *zif;
    1024             : 
    1025           0 :   ifp = (struct interface *) vty->index;
    1026           0 :   zif = ifp->info;
    1027             : 
    1028           0 :   zif->rtadv.AdvManagedFlag = 1;
    1029             : 
    1030           0 :   return CMD_SUCCESS;
    1031             : }
    1032             : 
    1033           0 : DEFUN (no_ipv6_nd_managed_config_flag,
    1034             :        no_ipv6_nd_managed_config_flag_cmd,
    1035             :        "no ipv6 nd managed-config-flag",
    1036             :        NO_STR
    1037             :        "Interface IPv6 config commands\n"
    1038             :        "Neighbor discovery\n"
    1039             :        "Managed address configuration flag\n")
    1040             : {
    1041             :   struct interface *ifp;
    1042             :   struct zebra_if *zif;
    1043             : 
    1044           0 :   ifp = (struct interface *) vty->index;
    1045           0 :   zif = ifp->info;
    1046             : 
    1047           0 :   zif->rtadv.AdvManagedFlag = 0;
    1048             : 
    1049           0 :   return CMD_SUCCESS;
    1050             : }
    1051             : 
    1052           0 : DEFUN (ipv6_nd_homeagent_config_flag,
    1053             :        ipv6_nd_homeagent_config_flag_cmd,
    1054             :        "ipv6 nd home-agent-config-flag",
    1055             :        "Interface IPv6 config commands\n"
    1056             :        "Neighbor discovery\n"
    1057             :        "Home Agent configuration flag\n")
    1058             : {
    1059             :   struct interface *ifp;
    1060             :   struct zebra_if *zif;
    1061             : 
    1062           0 :   ifp = (struct interface *) vty->index;
    1063           0 :   zif = ifp->info;
    1064             : 
    1065           0 :   zif->rtadv.AdvHomeAgentFlag = 1;
    1066             : 
    1067           0 :   return CMD_SUCCESS;
    1068             : }
    1069             : 
    1070           0 : DEFUN (no_ipv6_nd_homeagent_config_flag,
    1071             :        no_ipv6_nd_homeagent_config_flag_cmd,
    1072             :        "no ipv6 nd home-agent-config-flag",
    1073             :        NO_STR
    1074             :        "Interface IPv6 config commands\n"
    1075             :        "Neighbor discovery\n"
    1076             :        "Home Agent configuration flag\n")
    1077             : {
    1078             :   struct interface *ifp;
    1079             :   struct zebra_if *zif;
    1080             : 
    1081           0 :   ifp = (struct interface *) vty->index;
    1082           0 :   zif = ifp->info;
    1083             : 
    1084           0 :   zif->rtadv.AdvHomeAgentFlag = 0;
    1085             : 
    1086           0 :   return CMD_SUCCESS;
    1087             : }
    1088             : 
    1089           0 : DEFUN (ipv6_nd_adv_interval_config_option,
    1090             :        ipv6_nd_adv_interval_config_option_cmd,
    1091             :        "ipv6 nd adv-interval-option",
    1092             :        "Interface IPv6 config commands\n"
    1093             :        "Neighbor discovery\n"
    1094             :        "Advertisement Interval Option\n")
    1095             : {
    1096             :   struct interface *ifp;
    1097             :   struct zebra_if *zif;
    1098             : 
    1099           0 :   ifp = (struct interface *) vty->index;
    1100           0 :   zif = ifp->info;
    1101             : 
    1102           0 :   zif->rtadv.AdvIntervalOption = 1;
    1103             : 
    1104           0 :   return CMD_SUCCESS;
    1105             : }
    1106             : 
    1107           0 : DEFUN (no_ipv6_nd_adv_interval_config_option,
    1108             :        no_ipv6_nd_adv_interval_config_option_cmd,
    1109             :        "no ipv6 nd adv-interval-option",
    1110             :        NO_STR
    1111             :        "Interface IPv6 config commands\n"
    1112             :        "Neighbor discovery\n"
    1113             :        "Advertisement Interval Option\n")
    1114             : {
    1115             :   struct interface *ifp;
    1116             :   struct zebra_if *zif;
    1117             : 
    1118           0 :   ifp = (struct interface *) vty->index;
    1119           0 :   zif = ifp->info;
    1120             : 
    1121           0 :   zif->rtadv.AdvIntervalOption = 0;
    1122             : 
    1123           0 :   return CMD_SUCCESS;
    1124             : }
    1125             : 
    1126           0 : DEFUN (ipv6_nd_other_config_flag,
    1127             :        ipv6_nd_other_config_flag_cmd,
    1128             :        "ipv6 nd other-config-flag",
    1129             :        "Interface IPv6 config commands\n"
    1130             :        "Neighbor discovery\n"
    1131             :        "Other statefull configuration flag\n")
    1132             : {
    1133             :   struct interface *ifp;
    1134             :   struct zebra_if *zif;
    1135             : 
    1136           0 :   ifp = (struct interface *) vty->index;
    1137           0 :   zif = ifp->info;
    1138             : 
    1139           0 :   zif->rtadv.AdvOtherConfigFlag = 1;
    1140             : 
    1141           0 :   return CMD_SUCCESS;
    1142             : }
    1143             : 
    1144           0 : DEFUN (no_ipv6_nd_other_config_flag,
    1145             :        no_ipv6_nd_other_config_flag_cmd,
    1146             :        "no ipv6 nd other-config-flag",
    1147             :        NO_STR
    1148             :        "Interface IPv6 config commands\n"
    1149             :        "Neighbor discovery\n"
    1150             :        "Other statefull configuration flag\n")
    1151             : {
    1152             :   struct interface *ifp;
    1153             :   struct zebra_if *zif;
    1154             : 
    1155           0 :   ifp = (struct interface *) vty->index;
    1156           0 :   zif = ifp->info;
    1157             : 
    1158           0 :   zif->rtadv.AdvOtherConfigFlag = 0;
    1159             : 
    1160           0 :   return CMD_SUCCESS;
    1161             : }
    1162             : 
    1163           0 : DEFUN (ipv6_nd_prefix,
    1164             :        ipv6_nd_prefix_cmd,
    1165             :        "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
    1166             :        "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|) (router-address|)",
    1167             :        "Interface IPv6 config commands\n"
    1168             :        "Neighbor discovery\n"
    1169             :        "Prefix information\n"
    1170             :        "IPv6 prefix\n"
    1171             :        "Valid lifetime in seconds\n"
    1172             :        "Infinite valid lifetime\n"
    1173             :        "Preferred lifetime in seconds\n"
    1174             :        "Infinite preferred lifetime\n"
    1175             :        "Do not use prefix for onlink determination\n"
    1176             :        "Do not use prefix for autoconfiguration\n"
    1177             :        "Set Router Address flag\n")
    1178             : {
    1179             :   int i;
    1180             :   int ret;
    1181           0 :   int cursor = 1;
    1182             :   struct interface *ifp;
    1183             :   struct zebra_if *zebra_if;
    1184             :   struct rtadv_prefix rp;
    1185             : 
    1186           0 :   ifp = (struct interface *) vty->index;
    1187           0 :   zebra_if = ifp->info;
    1188             : 
    1189           0 :   ret = str2prefix_ipv6 (argv[0], &rp.prefix);
    1190           0 :   if (!ret)
    1191             :     {
    1192           0 :       vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
    1193           0 :       return CMD_WARNING;
    1194             :     }
    1195           0 :   apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */
    1196           0 :   rp.AdvOnLinkFlag = 1;
    1197           0 :   rp.AdvAutonomousFlag = 1;
    1198           0 :   rp.AdvRouterAddressFlag = 0;
    1199           0 :   rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
    1200           0 :   rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
    1201             : 
    1202           0 :   if (argc > 1)
    1203             :     {
    1204           0 :       if ((isdigit(argv[1][0])) || strncmp (argv[1], "i", 1) == 0)
    1205             :         {
    1206           0 :           if ( strncmp (argv[1], "i", 1) == 0)
    1207           0 :             rp.AdvValidLifetime = UINT32_MAX;
    1208             :           else
    1209           0 :             rp.AdvValidLifetime = (u_int32_t) strtoll (argv[1],
    1210             :                 (char **)NULL, 10);
    1211             :       
    1212           0 :           if ( strncmp (argv[2], "i", 1) == 0)
    1213           0 :             rp.AdvPreferredLifetime = UINT32_MAX;
    1214             :           else
    1215           0 :             rp.AdvPreferredLifetime = (u_int32_t) strtoll (argv[2],
    1216             :                 (char **)NULL, 10);
    1217             : 
    1218           0 :           if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
    1219             :             {
    1220           0 :               vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
    1221           0 :               return CMD_WARNING;
    1222             :             }
    1223           0 :           cursor = cursor + 2;
    1224             :         }
    1225           0 :       if (argc > cursor)
    1226             :         {
    1227           0 :           for (i = cursor; i < argc; i++)
    1228             :             {
    1229           0 :               if (strncmp (argv[i], "of", 2) == 0)
    1230           0 :                 rp.AdvOnLinkFlag = 0;
    1231           0 :               if (strncmp (argv[i], "no", 2) == 0)
    1232           0 :                 rp.AdvAutonomousFlag = 0;
    1233           0 :               if (strncmp (argv[i], "ro", 2) == 0)
    1234           0 :                 rp.AdvRouterAddressFlag = 1;
    1235             :             }
    1236             :         }
    1237             :     }
    1238             : 
    1239           0 :   rtadv_prefix_set (zebra_if, &rp);
    1240             : 
    1241           0 :   return CMD_SUCCESS;
    1242             : }
    1243             : 
    1244             : ALIAS (ipv6_nd_prefix,
    1245             :        ipv6_nd_prefix_val_nortaddr_cmd,
    1246             :        "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
    1247             :        "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
    1248             :        "Interface IPv6 config commands\n"
    1249             :        "Neighbor discovery\n"
    1250             :        "Prefix information\n"
    1251             :        "IPv6 prefix\n"
    1252             :        "Valid lifetime in seconds\n"
    1253             :        "Infinite valid lifetime\n"
    1254             :        "Preferred lifetime in seconds\n"
    1255             :        "Infinite preferred lifetime\n"
    1256             :        "Do not use prefix for onlink determination\n"
    1257             :        "Do not use prefix for autoconfiguration\n")
    1258             : 
    1259             : ALIAS (ipv6_nd_prefix,
    1260             :        ipv6_nd_prefix_val_rev_cmd,
    1261             :        "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
    1262             :        "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
    1263             :        "Interface IPv6 config commands\n"
    1264             :        "Neighbor discovery\n"
    1265             :        "Prefix information\n"
    1266             :        "IPv6 prefix\n"
    1267             :        "Valid lifetime in seconds\n"
    1268             :        "Infinite valid lifetime\n"
    1269             :        "Preferred lifetime in seconds\n"
    1270             :        "Infinite preferred lifetime\n"
    1271             :        "Do not use prefix for autoconfiguration\n"
    1272             :        "Do not use prefix for onlink determination\n")
    1273             : 
    1274             : ALIAS (ipv6_nd_prefix,
    1275             :        ipv6_nd_prefix_val_rev_rtaddr_cmd,
    1276             :        "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
    1277             :        "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|) (router-address|)",
    1278             :        "Interface IPv6 config commands\n"
    1279             :        "Neighbor discovery\n"
    1280             :        "Prefix information\n"
    1281             :        "IPv6 prefix\n"
    1282             :        "Valid lifetime in seconds\n"
    1283             :        "Infinite valid lifetime\n"
    1284             :        "Preferred lifetime in seconds\n"
    1285             :        "Infinite preferred lifetime\n"
    1286             :        "Do not use prefix for autoconfiguration\n"
    1287             :        "Do not use prefix for onlink determination\n"
    1288             :        "Set Router Address flag\n")
    1289             : 
    1290             : ALIAS (ipv6_nd_prefix,
    1291             :        ipv6_nd_prefix_val_noauto_cmd,
    1292             :        "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
    1293             :        "(<0-4294967295>|infinite) (no-autoconfig|)",
    1294             :        "Interface IPv6 config commands\n"
    1295             :        "Neighbor discovery\n"
    1296             :        "Prefix information\n"
    1297             :        "IPv6 prefix\n"
    1298             :        "Valid lifetime in seconds\n"
    1299             :        "Infinite valid lifetime\n"
    1300             :        "Preferred lifetime in seconds\n"
    1301             :        "Infinite preferred lifetime\n"
    1302             :        "Do not use prefix for autoconfiguration")
    1303             : 
    1304             : ALIAS (ipv6_nd_prefix,
    1305             :        ipv6_nd_prefix_val_offlink_cmd,
    1306             :        "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
    1307             :        "(<0-4294967295>|infinite) (off-link|)",
    1308             :        "Interface IPv6 config commands\n"
    1309             :        "Neighbor discovery\n"
    1310             :        "Prefix information\n"
    1311             :        "IPv6 prefix\n"
    1312             :        "Valid lifetime in seconds\n"
    1313             :        "Infinite valid lifetime\n"
    1314             :        "Preferred lifetime in seconds\n"
    1315             :        "Infinite preferred lifetime\n"
    1316             :        "Do not use prefix for onlink determination\n")
    1317             : 
    1318             : ALIAS (ipv6_nd_prefix,
    1319             :        ipv6_nd_prefix_val_rtaddr_cmd,
    1320             :        "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
    1321             :        "(<0-4294967295>|infinite) (router-address|)",
    1322             :        "Interface IPv6 config commands\n"
    1323             :        "Neighbor discovery\n"
    1324             :        "Prefix information\n"
    1325             :        "IPv6 prefix\n"
    1326             :        "Valid lifetime in seconds\n"
    1327             :        "Infinite valid lifetime\n"
    1328             :        "Preferred lifetime in seconds\n"
    1329             :        "Infinite preferred lifetime\n"
    1330             :        "Set Router Address flag\n")
    1331             : 
    1332             : ALIAS (ipv6_nd_prefix,
    1333             :        ipv6_nd_prefix_val_cmd,
    1334             :        "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
    1335             :        "(<0-4294967295>|infinite)",
    1336             :        "Interface IPv6 config commands\n"
    1337             :        "Neighbor discovery\n"
    1338             :        "Prefix information\n"
    1339             :        "IPv6 prefix\n"
    1340             :        "Valid lifetime in seconds\n"
    1341             :        "Infinite valid lifetime\n"
    1342             :        "Preferred lifetime in seconds\n"
    1343             :        "Infinite preferred lifetime\n")
    1344             : 
    1345             : ALIAS (ipv6_nd_prefix,
    1346             :        ipv6_nd_prefix_noval_cmd,
    1347             :        "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
    1348             :        "Interface IPv6 config commands\n"
    1349             :        "Neighbor discovery\n"
    1350             :        "Prefix information\n"
    1351             :        "IPv6 prefix\n"
    1352             :        "Do not use prefix for autoconfiguration\n"
    1353             :        "Do not use prefix for onlink determination\n")
    1354             : 
    1355             : ALIAS (ipv6_nd_prefix,
    1356             :        ipv6_nd_prefix_noval_rev_cmd,
    1357             :        "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
    1358             :        "Interface IPv6 config commands\n"
    1359             :        "Neighbor discovery\n"
    1360             :        "Prefix information\n"
    1361             :        "IPv6 prefix\n"
    1362             :        "Do not use prefix for onlink determination\n"
    1363             :        "Do not use prefix for autoconfiguration\n")
    1364             : 
    1365             : ALIAS (ipv6_nd_prefix,
    1366             :        ipv6_nd_prefix_noval_noauto_cmd,
    1367             :        "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
    1368             :        "Interface IPv6 config commands\n"
    1369             :        "Neighbor discovery\n"
    1370             :        "Prefix information\n"
    1371             :        "IPv6 prefix\n"
    1372             :        "Do not use prefix for autoconfiguration\n")
    1373             : 
    1374             : ALIAS (ipv6_nd_prefix,
    1375             :        ipv6_nd_prefix_noval_offlink_cmd,
    1376             :        "ipv6 nd prefix X:X::X:X/M (off-link|)",
    1377             :        "Interface IPv6 config commands\n"
    1378             :        "Neighbor discovery\n"
    1379             :        "Prefix information\n"
    1380             :        "IPv6 prefix\n"
    1381             :        "Do not use prefix for onlink determination\n")
    1382             : 
    1383             : ALIAS (ipv6_nd_prefix,
    1384             :        ipv6_nd_prefix_noval_rtaddr_cmd,
    1385             :        "ipv6 nd prefix X:X::X:X/M (router-address|)",
    1386             :        "Interface IPv6 config commands\n"
    1387             :        "Neighbor discovery\n"
    1388             :        "Prefix information\n"
    1389             :        "IPv6 prefix\n"
    1390             :        "Set Router Address flag\n")
    1391             : 
    1392             : ALIAS (ipv6_nd_prefix,
    1393             :        ipv6_nd_prefix_prefix_cmd,
    1394             :        "ipv6 nd prefix X:X::X:X/M",
    1395             :        "Interface IPv6 config commands\n"
    1396             :        "Neighbor discovery\n"
    1397             :        "Prefix information\n"
    1398             :        "IPv6 prefix\n")
    1399             : 
    1400           0 : DEFUN (no_ipv6_nd_prefix,
    1401             :        no_ipv6_nd_prefix_cmd,
    1402             :        "no ipv6 nd prefix IPV6PREFIX",
    1403             :        NO_STR
    1404             :        "Interface IPv6 config commands\n"
    1405             :        "Neighbor discovery\n"
    1406             :        "Prefix information\n"
    1407             :        "IPv6 prefix\n")
    1408             : {
    1409             :   int ret;
    1410             :   struct interface *ifp;
    1411             :   struct zebra_if *zebra_if;
    1412             :   struct rtadv_prefix rp;
    1413             : 
    1414           0 :   ifp = (struct interface *) vty->index;
    1415           0 :   zebra_if = ifp->info;
    1416             : 
    1417           0 :   ret = str2prefix_ipv6 (argv[0], &rp.prefix);
    1418           0 :   if (!ret)
    1419             :     {
    1420           0 :       vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
    1421           0 :       return CMD_WARNING;
    1422             :     }
    1423           0 :   apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */
    1424             : 
    1425           0 :   ret = rtadv_prefix_reset (zebra_if, &rp);
    1426           0 :   if (!ret)
    1427             :     {
    1428           0 :       vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
    1429           0 :       return CMD_WARNING;
    1430             :     }
    1431             : 
    1432           0 :   return CMD_SUCCESS;
    1433             : }
    1434             : 
    1435           0 : DEFUN (ipv6_nd_router_preference,
    1436             :        ipv6_nd_router_preference_cmd,
    1437             :        "ipv6 nd router-preference (high|medium|low)",
    1438             :        "Interface IPv6 config commands\n"
    1439             :        "Neighbor discovery\n"
    1440             :        "Default router preference\n"
    1441             :        "High default router preference\n"
    1442             :        "Low default router preference\n"
    1443             :        "Medium default router preference (default)\n")
    1444             : {
    1445             :   struct interface *ifp;
    1446             :   struct zebra_if *zif;
    1447           0 :   int i = 0;
    1448             : 
    1449           0 :   ifp = (struct interface *) vty->index;
    1450           0 :   zif = ifp->info;
    1451             : 
    1452           0 :   while (0 != rtadv_pref_strs[i])
    1453             :     {
    1454           0 :       if (strncmp (argv[0], rtadv_pref_strs[i], 1) == 0)
    1455             :         {
    1456           0 :           zif->rtadv.DefaultPreference = i;
    1457           0 :           return CMD_SUCCESS;
    1458             :         }
    1459           0 :       i++;
    1460             :     }
    1461             : 
    1462           0 :   return CMD_ERR_NO_MATCH;
    1463             : }
    1464             : 
    1465           0 : DEFUN (no_ipv6_nd_router_preference,
    1466             :        no_ipv6_nd_router_preference_cmd,
    1467             :        "no ipv6 nd router-preference",
    1468             :        NO_STR
    1469             :        "Interface IPv6 config commands\n"
    1470             :        "Neighbor discovery\n"
    1471             :        "Default router preference\n")
    1472             : {
    1473             :   struct interface *ifp;
    1474             :   struct zebra_if *zif;
    1475             : 
    1476           0 :   ifp = (struct interface *) vty->index;
    1477           0 :   zif = ifp->info;
    1478             : 
    1479           0 :   zif->rtadv.DefaultPreference = RTADV_PREF_MEDIUM; /* Default per RFC4191. */
    1480             : 
    1481           0 :   return CMD_SUCCESS;
    1482             : }
    1483             : 
    1484             : ALIAS (no_ipv6_nd_router_preference,
    1485             :        no_ipv6_nd_router_preference_val_cmd,
    1486             :        "no ipv6 nd router-preference (high|medium|low)",
    1487             :        NO_STR
    1488             :        "Interface IPv6 config commands\n"
    1489             :        "Neighbor discovery\n"
    1490             :        "Default router preference\n"
    1491             :        "High default router preference\n"
    1492             :        "Low default router preference\n"
    1493             :        "Medium default router preference (default)\n")
    1494             : 
    1495           0 : DEFUN (ipv6_nd_mtu,
    1496             :        ipv6_nd_mtu_cmd,
    1497             :        "ipv6 nd mtu <1-65535>",
    1498             :        "Interface IPv6 config commands\n"
    1499             :        "Neighbor discovery\n"
    1500             :        "Advertised MTU\n"
    1501             :        "MTU in bytes\n")
    1502             : {
    1503           0 :   struct interface *ifp = (struct interface *) vty->index;
    1504           0 :   struct zebra_if *zif = ifp->info;
    1505           0 :   VTY_GET_INTEGER_RANGE ("MTU", zif->rtadv.AdvLinkMTU, argv[0], 1, 65535);
    1506           0 :   return CMD_SUCCESS;
    1507             : }
    1508             : 
    1509           0 : DEFUN (no_ipv6_nd_mtu,
    1510             :        no_ipv6_nd_mtu_cmd,
    1511             :        "no ipv6 nd mtu",
    1512             :        NO_STR
    1513             :        "Interface IPv6 config commands\n"
    1514             :        "Neighbor discovery\n"
    1515             :        "Advertised MTU\n")
    1516             : {
    1517           0 :   struct interface *ifp = (struct interface *) vty->index;
    1518           0 :   struct zebra_if *zif = ifp->info;
    1519           0 :   zif->rtadv.AdvLinkMTU = 0;
    1520           0 :   return CMD_SUCCESS;
    1521             : }
    1522             : 
    1523             : ALIAS (no_ipv6_nd_mtu,
    1524             :        no_ipv6_nd_mtu_val_cmd,
    1525             :        "no ipv6 nd mtu <1-65535>",
    1526             :        NO_STR
    1527             :        "Interface IPv6 config commands\n"
    1528             :        "Neighbor discovery\n"
    1529             :        "Advertised MTU\n"
    1530             :        "MTU in bytes\n")
    1531             : 
    1532             : /* Write configuration about router advertisement. */
    1533             : void
    1534           0 : rtadv_config_write (struct vty *vty, struct interface *ifp)
    1535             : {
    1536             :   struct zebra_if *zif;
    1537             :   struct listnode *node;
    1538             :   struct rtadv_prefix *rprefix;
    1539             :   u_char buf[INET6_ADDRSTRLEN];
    1540             :   int interval;
    1541             : 
    1542           0 :   if (! rtadv)
    1543           0 :     return;
    1544             : 
    1545           0 :   zif = ifp->info;
    1546             : 
    1547           0 :   if (! if_is_loopback (ifp))
    1548             :     {
    1549           0 :       if (zif->rtadv.AdvSendAdvertisements)
    1550           0 :         vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
    1551             :       else
    1552           0 :         vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE);
    1553             :     }
    1554             : 
    1555             :   
    1556           0 :   interval = zif->rtadv.MaxRtrAdvInterval;
    1557           0 :   if (interval % 1000)
    1558           0 :     vty_out (vty, " ipv6 nd ra-interval msec %d%s", interval,
    1559           0 :              VTY_NEWLINE);
    1560             :   else
    1561           0 :     if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
    1562           0 :       vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,
    1563           0 :              VTY_NEWLINE);
    1564             : 
    1565           0 :   if (zif->rtadv.AdvIntervalOption)
    1566           0 :     vty_out (vty, " ipv6 nd adv-interval-option%s", VTY_NEWLINE);
    1567             : 
    1568           0 :   if (zif->rtadv.AdvDefaultLifetime != -1)
    1569           0 :     vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
    1570           0 :              VTY_NEWLINE);
    1571             : 
    1572           0 :   if (zif->rtadv.HomeAgentPreference)
    1573           0 :     vty_out (vty, " ipv6 nd home-agent-preference %u%s",
    1574           0 :              zif->rtadv.HomeAgentPreference, VTY_NEWLINE);
    1575             : 
    1576           0 :   if (zif->rtadv.HomeAgentLifetime != -1)
    1577           0 :     vty_out (vty, " ipv6 nd home-agent-lifetime %u%s",
    1578           0 :              zif->rtadv.HomeAgentLifetime, VTY_NEWLINE);
    1579             : 
    1580           0 :   if (zif->rtadv.AdvHomeAgentFlag)
    1581           0 :     vty_out (vty, " ipv6 nd home-agent-config-flag%s", VTY_NEWLINE);
    1582             : 
    1583           0 :   if (zif->rtadv.AdvReachableTime)
    1584           0 :     vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
    1585           0 :              VTY_NEWLINE);
    1586             : 
    1587           0 :   if (zif->rtadv.AdvManagedFlag)
    1588           0 :     vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
    1589             : 
    1590           0 :   if (zif->rtadv.AdvOtherConfigFlag)
    1591           0 :     vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
    1592             : 
    1593           0 :   if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
    1594           0 :     vty_out (vty, " ipv6 nd router-preference %s%s",
    1595           0 :              rtadv_pref_strs[zif->rtadv.DefaultPreference],
    1596           0 :              VTY_NEWLINE);
    1597             : 
    1598           0 :   if (zif->rtadv.AdvLinkMTU)
    1599           0 :     vty_out (vty, " ipv6 nd mtu %d%s", zif->rtadv.AdvLinkMTU, VTY_NEWLINE);
    1600             : 
    1601           0 :   for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
    1602             :     {
    1603           0 :       vty_out (vty, " ipv6 nd prefix %s/%d",
    1604           0 :                inet_ntop (AF_INET6, &rprefix->prefix.prefix,
    1605             :                           (char *) buf, INET6_ADDRSTRLEN),
    1606           0 :                rprefix->prefix.prefixlen);
    1607           0 :       if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) || 
    1608           0 :           (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
    1609             :         {
    1610           0 :           if (rprefix->AdvValidLifetime == UINT32_MAX)
    1611           0 :             vty_out (vty, " infinite");
    1612             :           else
    1613           0 :             vty_out (vty, " %u", rprefix->AdvValidLifetime);
    1614           0 :           if (rprefix->AdvPreferredLifetime == UINT32_MAX)
    1615           0 :             vty_out (vty, " infinite");
    1616             :           else
    1617           0 :             vty_out (vty, " %u", rprefix->AdvPreferredLifetime);
    1618             :         }
    1619           0 :       if (!rprefix->AdvOnLinkFlag)
    1620           0 :         vty_out (vty, " off-link");
    1621           0 :       if (!rprefix->AdvAutonomousFlag)
    1622           0 :         vty_out (vty, " no-autoconfig");
    1623           0 :       if (rprefix->AdvRouterAddressFlag)
    1624           0 :         vty_out (vty, " router-address");
    1625           0 :       vty_out (vty, "%s", VTY_NEWLINE);
    1626             :     }
    1627             : }
    1628             : 
    1629             : 
    1630             : static void
    1631           0 : rtadv_event (enum rtadv_event event, int val)
    1632             : {
    1633           0 :   switch (event)
    1634             :     {
    1635             :     case RTADV_START:
    1636           0 :       if (! rtadv->ra_read)
    1637           0 :         rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
    1638           0 :       if (! rtadv->ra_timer)
    1639           0 :         rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
    1640             :                                             NULL, 0);
    1641           0 :       break;
    1642             :     case RTADV_STOP:
    1643           0 :       if (rtadv->ra_timer)
    1644             :         {
    1645           0 :           thread_cancel (rtadv->ra_timer);
    1646           0 :           rtadv->ra_timer = NULL;
    1647             :         }
    1648           0 :       if (rtadv->ra_read)
    1649             :         {
    1650           0 :           thread_cancel (rtadv->ra_read);
    1651           0 :           rtadv->ra_read = NULL;
    1652             :         }
    1653           0 :       break;
    1654             :     case RTADV_TIMER:
    1655           0 :       if (! rtadv->ra_timer)
    1656           0 :         rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL,
    1657             :                                             val);
    1658           0 :       break;
    1659             :     case RTADV_TIMER_MSEC:
    1660           0 :       if (! rtadv->ra_timer)
    1661           0 :         rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer, 
    1662             :                                             NULL, val);
    1663           0 :       break;
    1664             :     case RTADV_READ:
    1665           0 :       if (! rtadv->ra_read)
    1666           0 :         rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
    1667           0 :       break;
    1668             :     default:
    1669           0 :       break;
    1670             :     }
    1671           0 :   return;
    1672             : }
    1673             : 
    1674             : void
    1675          45 : rtadv_init (void)
    1676             : {
    1677             :   int sock;
    1678             : 
    1679          45 :   sock = rtadv_make_socket ();
    1680          45 :   if (sock < 0)
    1681           0 :     return;
    1682             : 
    1683          45 :   rtadv = rtadv_new ();
    1684          45 :   rtadv->sock = sock;
    1685             : 
    1686          45 :   install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
    1687          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
    1688          45 :   install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
    1689          45 :   install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
    1690          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
    1691          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_val_cmd);
    1692          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_msec_val_cmd);
    1693          45 :   install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
    1694          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
    1695          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_val_cmd);
    1696          45 :   install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
    1697          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
    1698          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_val_cmd);
    1699          45 :   install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
    1700          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
    1701          45 :   install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
    1702          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
    1703          45 :   install_element (INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
    1704          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
    1705          45 :   install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
    1706          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
    1707          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_val_cmd);
    1708          45 :   install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
    1709          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
    1710          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_val_cmd);
    1711          45 :   install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
    1712          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);
    1713          45 :   install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
    1714          45 :   install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_rtaddr_cmd);
    1715          45 :   install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_nortaddr_cmd);
    1716          45 :   install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_cmd);
    1717          45 :   install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_noauto_cmd);
    1718          45 :   install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_offlink_cmd);
    1719          45 :   install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rtaddr_cmd);
    1720          45 :   install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_cmd);
    1721          45 :   install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_cmd);
    1722          45 :   install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rev_cmd);
    1723          45 :   install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_noauto_cmd);
    1724          45 :   install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_offlink_cmd);
    1725          45 :   install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd);
    1726          45 :   install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
    1727          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
    1728          45 :   install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
    1729          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
    1730          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_val_cmd);
    1731          45 :   install_element (INTERFACE_NODE, &ipv6_nd_mtu_cmd);
    1732          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_cmd);
    1733          45 :   install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_val_cmd);
    1734             : }
    1735             : 
    1736             : static int
    1737           0 : if_join_all_router (int sock, struct interface *ifp)
    1738             : {
    1739             :   int ret;
    1740             : 
    1741             :   struct ipv6_mreq mreq;
    1742             : 
    1743           0 :   memset (&mreq, 0, sizeof (struct ipv6_mreq));
    1744           0 :   inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
    1745           0 :   mreq.ipv6mr_interface = ifp->ifindex;
    1746             : 
    1747           0 :   ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, 
    1748             :                     (char *) &mreq, sizeof mreq);
    1749           0 :   if (ret < 0)
    1750           0 :     zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", safe_strerror (errno));
    1751             : 
    1752           0 :   zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
    1753             : 
    1754           0 :   return 0;
    1755             : }
    1756             : 
    1757             : static int
    1758           0 : if_leave_all_router (int sock, struct interface *ifp)
    1759             : {
    1760             :   int ret;
    1761             : 
    1762             :   struct ipv6_mreq mreq;
    1763             : 
    1764           0 :   memset (&mreq, 0, sizeof (struct ipv6_mreq));
    1765           0 :   inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
    1766           0 :   mreq.ipv6mr_interface = ifp->ifindex;
    1767             : 
    1768           0 :   ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, 
    1769             :                     (char *) &mreq, sizeof mreq);
    1770           0 :   if (ret < 0)
    1771           0 :     zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", safe_strerror (errno));
    1772             : 
    1773           0 :   zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
    1774             : 
    1775           0 :   return 0;
    1776             : }
    1777             : 
    1778             : #else
    1779             : void
    1780             : rtadv_init (void)
    1781             : {
    1782             :   /* Empty.*/;
    1783             : }
    1784             : #endif /* RTADV && HAVE_IPV6 */

Generated by: LCOV version 1.10