Annotation of embedaddon/quagga/zebra/rtadv.c, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>