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