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

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

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