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

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

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