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