Annotation of embedaddon/quagga/zebra/rtadv.c, revision 1.1.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>