1 /* Router advertisement
2 * Copyright (C) 2005 6WIND <jean-mickael.guerin@6wind.com>
3 * Copyright (C) 1999 Kunihiro Ishiguro
5 * This file is part of GNU Zebra.
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
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.
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
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"
41 extern struct zebra_privs_t zserv_privs
;
43 #if defined (HAVE_IPV6) && defined (RTADV)
46 #include <netinet/icmp6.h>
49 /* If RFC2133 definition is used. */
50 #ifndef IPV6_JOIN_GROUP
51 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
53 #ifndef IPV6_LEAVE_GROUP
54 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
57 #define ALLNODE "ff02::1"
58 #define ALLROUTER "ff02::2"
60 extern struct zebra_t zebrad
;
62 enum rtadv_event
{RTADV_START
, RTADV_STOP
, RTADV_TIMER
,
63 RTADV_TIMER_MSEC
, RTADV_READ
};
65 static void rtadv_event (enum rtadv_event
, int);
67 static int if_join_all_router (int, struct interface
*);
68 static int if_leave_all_router (int, struct interface
*);
70 /* Structure which hold status of router advertisement. */
76 int adv_msec_if_count
;
78 struct thread
*ra_read
;
79 struct thread
*ra_timer
;
82 struct rtadv
*rtadv
= NULL
;
87 return XCALLOC (MTYPE_TMP
, sizeof (struct rtadv
));
91 rtadv_recv_packet (int sock
, u_char
*buf
, int buflen
,
92 struct sockaddr_in6
*from
, unsigned int *ifindex
,
98 struct cmsghdr
*cmsgptr
;
103 /* Fill in message and iovec. */
104 msg
.msg_name
= (void *) from
;
105 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
108 msg
.msg_control
= (void *) adata
;
109 msg
.msg_controllen
= sizeof adata
;
111 iov
.iov_len
= buflen
;
113 /* If recvmsg fail return minus value. */
114 ret
= recvmsg (sock
, &msg
, 0);
118 for (cmsgptr
= ZCMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
119 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
))
121 /* I want interface index which this packet comes from. */
122 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
&&
123 cmsgptr
->cmsg_type
== IPV6_PKTINFO
)
125 struct in6_pktinfo
*ptr
;
127 ptr
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
128 *ifindex
= ptr
->ipi6_ifindex
;
129 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
132 /* Incoming packet's hop limit. */
133 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
&&
134 cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
)
136 int *hoptr
= (int *) CMSG_DATA (cmsgptr
);
143 #define RTADV_MSG_SIZE 4096
145 /* Send router advertisement packet. */
147 rtadv_send_packet (int sock
, struct interface
*ifp
)
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
;
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 u_int16_t pkt_RouterLifetime
;
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.
176 /* XXX Free on shutdown. */
177 adata
= malloc(CMSG_SPACE(sizeof(struct in6_pktinfo
)));
180 zlog_err("rtadv_send_packet: can't malloc control data\n");
183 /* Logging of packet. */
184 if (IS_ZEBRA_DEBUG_PACKET
)
185 zlog_debug ("Router advertisement send to %s", ifp
->name
);
187 /* Fill in sockaddr_in6. */
188 memset (&addr
, 0, sizeof (struct sockaddr_in6
));
189 addr
.sin6_family
= AF_INET6
;
191 addr
.sin6_len
= sizeof (struct sockaddr_in6
);
192 #endif /* SIN6_LEN */
193 addr
.sin6_port
= htons (IPPROTO_ICMPV6
);
194 IPV6_ADDR_COPY (&addr
.sin6_addr
, all_nodes_addr
);
196 /* Fetch interface information. */
199 /* Make router advertisement message. */
200 rtadv
= (struct nd_router_advert
*) buf
;
202 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
203 rtadv
->nd_ra_code
= 0;
204 rtadv
->nd_ra_cksum
= 0;
206 rtadv
->nd_ra_curhoplimit
= 64;
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;
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
;
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
);
231 rtadv
->nd_ra_reachable
= htonl (zif
->rtadv
.AdvReachableTime
);
232 rtadv
->nd_ra_retransmit
= htonl (0);
234 len
= sizeof (struct nd_router_advert
);
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 */
242 zif
->rtadv
.AdvHomeAgentFlag
&&
243 (zif
->rtadv
.HomeAgentPreference
|| zif
->rtadv
.HomeAgentLifetime
!= -1)
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
);
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
259 zif
->rtadv
.HomeAgentLifetime
!= -1 ?
260 zif
->rtadv
.HomeAgentLifetime
:
261 MAX (1, pkt_RouterLifetime
) /* 0 is OK for RL, but not for HAL*/
263 len
+= sizeof(struct nd_opt_homeagent_info
);
266 if (zif
->rtadv
.AdvIntervalOption
)
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
);
277 /* Fill in prefix. */
278 for (ALL_LIST_ELEMENTS_RO (zif
->rtadv
.AdvPrefixList
, node
, rprefix
))
280 struct nd_opt_prefix_info
*pinfo
;
282 pinfo
= (struct nd_opt_prefix_info
*) (buf
+ len
);
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
;
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
;
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;
300 IPV6_ADDR_COPY (&pinfo
->nd_opt_pi_prefix
, &rprefix
->prefix
.prefix
);
304 u_char buf
[INET6_ADDRSTRLEN
];
306 zlog_debug ("DEBUG %s", inet_ntop (AF_INET6
, &pinfo
->nd_opt_pi_prefix
,
307 buf
, INET6_ADDRSTRLEN
));
312 len
+= sizeof (struct nd_opt_prefix_info
);
315 /* Hardware address. */
316 #ifdef HAVE_STRUCT_SOCKADDR_DL
318 if (sdl
!= NULL
&& sdl
->sdl_alen
!= 0)
320 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
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;
326 memcpy (buf
+ len
, LLADDR (sdl
), sdl
->sdl_alen
);
327 len
+= sdl
->sdl_alen
;
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;
334 if (ifp
->hw_addr_len
!= 0)
336 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
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;
342 memcpy (buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
343 len
+= ifp
->hw_addr_len
;
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;
349 #endif /* HAVE_STRUCT_SOCKADDR_DL */
352 if (zif
->rtadv
.AdvLinkMTU
)
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
);
362 msg
.msg_name
= (void *) &addr
;
363 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
366 msg
.msg_control
= (void *) adata
;
367 msg
.msg_controllen
= CMSG_SPACE(sizeof(struct in6_pktinfo
));
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
;
377 pkt
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
378 memset (&pkt
->ipi6_addr
, 0, sizeof (struct in6_addr
));
379 pkt
->ipi6_ifindex
= ifp
->ifindex
;
381 ret
= sendmsg (sock
, &msg
, 0);
384 zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
385 errno
, safe_strerror(errno
));
390 rtadv_timer (struct thread
*thread
)
392 struct listnode
*node
, *nnode
;
393 struct interface
*ifp
;
394 struct zebra_if
*zif
;
397 rtadv
->ra_timer
= NULL
;
398 if (rtadv
->adv_msec_if_count
== 0)
400 period
= 1000; /* 1 s */
401 rtadv_event (RTADV_TIMER
, 1 /* 1 s */);
405 period
= 10; /* 10 ms */
406 rtadv_event (RTADV_TIMER_MSEC
, 10 /* 10 ms */);
409 for (ALL_LIST_ELEMENTS (iflist
, node
, nnode
, ifp
))
411 if (if_is_loopback (ifp
) || ! if_is_operative (ifp
))
416 if (zif
->rtadv
.AdvSendAdvertisements
)
418 zif
->rtadv
.AdvIntervalTimer
-= period
;
419 if (zif
->rtadv
.AdvIntervalTimer
<= 0)
421 /* FIXME: using MaxRtrAdvInterval each time isn't what section
422 6.2.4 of RFC4861 tells to do. */
423 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
424 rtadv_send_packet (rtadv
->sock
, ifp
);
432 rtadv_process_solicit (struct interface
*ifp
)
434 zlog_info ("Router solicitation received on %s", ifp
->name
);
436 rtadv_send_packet (rtadv
->sock
, ifp
);
440 rtadv_process_advert (void)
442 zlog_info ("Router advertisement received");
446 rtadv_process_packet (u_char
*buf
, unsigned int len
, unsigned int ifindex
, int hoplimit
)
448 struct icmp6_hdr
*icmph
;
449 struct interface
*ifp
;
450 struct zebra_if
*zif
;
452 /* Interface search. */
453 ifp
= if_lookup_by_index (ifindex
);
456 zlog_warn ("Unknown interface index: %d", ifindex
);
460 if (if_is_loopback (ifp
))
463 /* Check interface configuration. */
465 if (! zif
->rtadv
.AdvSendAdvertisements
)
468 /* ICMP message length check. */
469 if (len
< sizeof (struct icmp6_hdr
))
471 zlog_warn ("Invalid ICMPV6 packet length: %d", len
);
475 icmph
= (struct icmp6_hdr
*) buf
;
477 /* ICMP message type check. */
478 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
&&
479 icmph
->icmp6_type
!= ND_ROUTER_ADVERT
)
481 zlog_warn ("Unwanted ICMPV6 message type: %d", icmph
->icmp6_type
);
485 /* Hoplimit check. */
486 if (hoplimit
>= 0 && hoplimit
!= 255)
488 zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
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 ();
503 rtadv_read (struct thread
*thread
)
507 u_char buf
[RTADV_MSG_SIZE
];
508 struct sockaddr_in6 from
;
509 unsigned int ifindex
= 0;
512 sock
= THREAD_FD (thread
);
513 rtadv
->ra_read
= NULL
;
515 /* Register myself. */
516 rtadv_event (RTADV_READ
, sock
);
518 len
= rtadv_recv_packet (sock
, buf
, BUFSIZ
, &from
, &ifindex
, &hoplimit
);
522 zlog_warn ("router solicitation recv failed: %s.", safe_strerror (errno
));
526 rtadv_process_packet (buf
, (unsigned)len
, ifindex
, hoplimit
);
532 rtadv_make_socket (void)
536 struct icmp6_filter filter
;
538 if ( zserv_privs
.change (ZPRIVS_RAISE
) )
539 zlog_err ("rtadv_make_socket: could not raise privs, %s",
540 safe_strerror (errno
) );
542 sock
= socket (AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
);
544 if ( zserv_privs
.change (ZPRIVS_LOWER
) )
545 zlog_err ("rtadv_make_socket: could not lower privs, %s",
546 safe_strerror (errno
) );
548 /* When we can't make ICMPV6 socket simply back. Router
549 advertisement feature will not be supported. */
553 ret
= setsockopt_ipv6_pktinfo (sock
, 1);
556 ret
= setsockopt_ipv6_multicast_loop (sock
, 0);
559 ret
= setsockopt_ipv6_unicast_hops (sock
, 255);
562 ret
= setsockopt_ipv6_multicast_hops (sock
, 255);
565 ret
= setsockopt_ipv6_hoplimit (sock
, 1);
569 ICMP6_FILTER_SETBLOCKALL(&filter
);
570 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT
, &filter
);
571 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT
, &filter
);
573 ret
= setsockopt (sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
574 sizeof (struct icmp6_filter
));
577 zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno
));
584 static struct rtadv_prefix
*
585 rtadv_prefix_new (void)
587 return XCALLOC (MTYPE_RTADV_PREFIX
, sizeof (struct rtadv_prefix
));
591 rtadv_prefix_free (struct rtadv_prefix
*rtadv_prefix
)
593 XFREE (MTYPE_RTADV_PREFIX
, rtadv_prefix
);
596 static struct rtadv_prefix
*
597 rtadv_prefix_lookup (struct list
*rplist
, struct prefix_ipv6
*p
)
599 struct listnode
*node
;
600 struct rtadv_prefix
*rprefix
;
602 for (ALL_LIST_ELEMENTS_RO (rplist
, node
, rprefix
))
603 if (prefix_same ((struct prefix
*) &rprefix
->prefix
, (struct prefix
*) p
))
608 static struct rtadv_prefix
*
609 rtadv_prefix_get (struct list
*rplist
, struct prefix_ipv6
*p
)
611 struct rtadv_prefix
*rprefix
;
613 rprefix
= rtadv_prefix_lookup (rplist
, p
);
617 rprefix
= rtadv_prefix_new ();
618 memcpy (&rprefix
->prefix
, p
, sizeof (struct prefix_ipv6
));
619 listnode_add (rplist
, rprefix
);
625 rtadv_prefix_set (struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
627 struct rtadv_prefix
*rprefix
;
629 rprefix
= rtadv_prefix_get (zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
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
;
640 rtadv_prefix_reset (struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
642 struct rtadv_prefix
*rprefix
;
644 rprefix
= rtadv_prefix_lookup (zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
647 listnode_delete (zif
->rtadv
.AdvPrefixList
, (void *) rprefix
);
648 rtadv_prefix_free (rprefix
);
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")
662 struct interface
*ifp
;
663 struct zebra_if
*zif
;
668 if (if_is_loopback (ifp
))
670 vty_out (vty
, "Invalid interface%s", VTY_NEWLINE
);
674 if (zif
->rtadv
.AdvSendAdvertisements
)
676 zif
->rtadv
.AdvSendAdvertisements
= 0;
677 zif
->rtadv
.AdvIntervalTimer
= 0;
678 rtadv
->adv_if_count
--;
680 if_leave_all_router (rtadv
->sock
, ifp
);
682 if (rtadv
->adv_if_count
== 0)
683 rtadv_event (RTADV_STOP
, 0);
689 DEFUN (no_ipv6_nd_suppress_ra
,
690 no_ipv6_nd_suppress_ra_cmd
,
691 "no ipv6 nd suppress-ra",
693 "Interface IPv6 config commands\n"
694 "Neighbor discovery\n"
695 "Suppress Router Advertisement\n")
697 struct interface
*ifp
;
698 struct zebra_if
*zif
;
703 if (if_is_loopback (ifp
))
705 vty_out (vty
, "Invalid interface%s", VTY_NEWLINE
);
709 if (! zif
->rtadv
.AdvSendAdvertisements
)
711 zif
->rtadv
.AdvSendAdvertisements
= 1;
712 zif
->rtadv
.AdvIntervalTimer
= 0;
713 rtadv
->adv_if_count
++;
715 if_join_all_router (rtadv
->sock
, ifp
);
717 if (rtadv
->adv_if_count
== 1)
718 rtadv_event (RTADV_START
, rtadv
->sock
);
724 DEFUN (ipv6_nd_ra_interval_msec
,
725 ipv6_nd_ra_interval_msec_cmd
,
726 "ipv6 nd ra-interval msec <70-1800000>",
727 "Interface IPv6 config commands\n"
728 "Neighbor discovery\n"
729 "Router Advertisement interval\n"
730 "Router Advertisement interval in milliseconds\n")
733 struct interface
*ifp
= (struct interface
*) vty
->index
;
734 struct zebra_if
*zif
= ifp
->info
;
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))
739 vty_out (vty
, "This ra-interval would conflict with configured ra-lifetime!%s", VTY_NEWLINE
);
743 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
744 rtadv
->adv_msec_if_count
--;
747 rtadv
->adv_msec_if_count
++;
749 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
750 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
751 zif
->rtadv
.AdvIntervalTimer
= 0;
756 DEFUN (ipv6_nd_ra_interval
,
757 ipv6_nd_ra_interval_cmd
,
758 "ipv6 nd ra-interval <1-1800>",
759 "Interface IPv6 config commands\n"
760 "Neighbor discovery\n"
761 "Router Advertisement interval\n"
762 "Router Advertisement interval in seconds\n")
765 struct interface
*ifp
= (struct interface
*) vty
->index
;
766 struct zebra_if
*zif
= ifp
->info
;
768 VTY_GET_INTEGER_RANGE ("router advertisement interval", interval
, argv
[0], 1, 1800);
769 if ((zif
->rtadv
.AdvDefaultLifetime
!= -1 && interval
> (unsigned)zif
->rtadv
.AdvDefaultLifetime
))
771 vty_out (vty
, "This ra-interval would conflict with configured ra-lifetime!%s", VTY_NEWLINE
);
775 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
776 rtadv
->adv_msec_if_count
--;
778 /* convert to milliseconds */
779 interval
= interval
* 1000;
781 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
782 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
783 zif
->rtadv
.AdvIntervalTimer
= 0;
788 DEFUN (no_ipv6_nd_ra_interval
,
789 no_ipv6_nd_ra_interval_cmd
,
790 "no ipv6 nd ra-interval",
792 "Interface IPv6 config commands\n"
793 "Neighbor discovery\n"
794 "Router Advertisement interval\n")
796 struct interface
*ifp
;
797 struct zebra_if
*zif
;
799 ifp
= (struct interface
*) vty
->index
;
802 if (zif
->rtadv
.MaxRtrAdvInterval
% 1000)
803 rtadv
->adv_msec_if_count
--;
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
;
812 ALIAS (no_ipv6_nd_ra_interval
,
813 no_ipv6_nd_ra_interval_val_cmd
,
814 "no ipv6 nd ra-interval <1-1800>",
816 "Interface IPv6 config commands\n"
817 "Neighbor discovery\n"
818 "Router Advertisement interval\n")
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>",
824 "Interface IPv6 config commands\n"
825 "Neighbor discovery\n"
826 "Router Advertisement interval\n"
827 "Router Advertisement interval in milliseconds\n")
829 DEFUN (ipv6_nd_ra_lifetime
,
830 ipv6_nd_ra_lifetime_cmd
,
831 "ipv6 nd ra-lifetime <0-9000>",
832 "Interface IPv6 config commands\n"
833 "Neighbor discovery\n"
835 "Router lifetime in seconds (0 stands for a non-default gw)\n")
838 struct interface
*ifp
;
839 struct zebra_if
*zif
;
841 ifp
= (struct interface
*) vty
->index
;
844 VTY_GET_INTEGER_RANGE ("router lifetime", lifetime
, argv
[0], 0, 9000);
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
))
852 vty_out (vty
, "This ra-lifetime would conflict with configured ra-interval%s", VTY_NEWLINE
);
856 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
861 DEFUN (no_ipv6_nd_ra_lifetime
,
862 no_ipv6_nd_ra_lifetime_cmd
,
863 "no ipv6 nd ra-lifetime",
865 "Interface IPv6 config commands\n"
866 "Neighbor discovery\n"
869 struct interface
*ifp
;
870 struct zebra_if
*zif
;
872 ifp
= (struct interface
*) vty
->index
;
875 zif
->rtadv
.AdvDefaultLifetime
= -1;
880 ALIAS (no_ipv6_nd_ra_lifetime
,
881 no_ipv6_nd_ra_lifetime_val_cmd
,
882 "no ipv6 nd ra-lifetime <0-9000>",
884 "Interface IPv6 config commands\n"
885 "Neighbor discovery\n"
887 "Router lifetime in seconds (0 stands for a non-default gw)\n")
889 DEFUN (ipv6_nd_reachable_time
,
890 ipv6_nd_reachable_time_cmd
,
891 "ipv6 nd reachable-time <1-3600000>",
892 "Interface IPv6 config commands\n"
893 "Neighbor discovery\n"
895 "Reachable time in milliseconds\n")
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
);
903 DEFUN (no_ipv6_nd_reachable_time
,
904 no_ipv6_nd_reachable_time_cmd
,
905 "no ipv6 nd reachable-time",
907 "Interface IPv6 config commands\n"
908 "Neighbor discovery\n"
911 struct interface
*ifp
;
912 struct zebra_if
*zif
;
914 ifp
= (struct interface
*) vty
->index
;
917 zif
->rtadv
.AdvReachableTime
= 0;
922 ALIAS (no_ipv6_nd_reachable_time
,
923 no_ipv6_nd_reachable_time_val_cmd
,
924 "no ipv6 nd reachable-time <1-3600000>",
926 "Interface IPv6 config commands\n"
927 "Neighbor discovery\n"
929 "Reachable time in milliseconds\n")
931 DEFUN (ipv6_nd_homeagent_preference
,
932 ipv6_nd_homeagent_preference_cmd
,
933 "ipv6 nd home-agent-preference <0-65535>",
934 "Interface IPv6 config commands\n"
935 "Neighbor discovery\n"
936 "Home Agent preference\n"
937 "preference value (default is 0, least preferred)\n")
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);
945 DEFUN (no_ipv6_nd_homeagent_preference
,
946 no_ipv6_nd_homeagent_preference_cmd
,
947 "no ipv6 nd home-agent-preference",
949 "Interface IPv6 config commands\n"
950 "Neighbor discovery\n"
951 "Home Agent preference\n")
953 struct interface
*ifp
;
954 struct zebra_if
*zif
;
956 ifp
= (struct interface
*) vty
->index
;
959 zif
->rtadv
.HomeAgentPreference
= 0;
964 ALIAS (no_ipv6_nd_homeagent_preference
,
965 no_ipv6_nd_homeagent_preference_val_cmd
,
966 "no ipv6 nd home-agent-preference <0-65535>",
968 "Interface IPv6 config commands\n"
969 "Neighbor discovery\n"
970 "Home Agent preference\n"
971 "preference value (default is 0, least preferred)\n")
973 DEFUN (ipv6_nd_homeagent_lifetime
,
974 ipv6_nd_homeagent_lifetime_cmd
,
975 "ipv6 nd home-agent-lifetime <0-65520>",
976 "Interface IPv6 config commands\n"
977 "Neighbor discovery\n"
978 "Home Agent lifetime\n"
979 "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
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
);
987 DEFUN (no_ipv6_nd_homeagent_lifetime
,
988 no_ipv6_nd_homeagent_lifetime_cmd
,
989 "no ipv6 nd home-agent-lifetime",
991 "Interface IPv6 config commands\n"
992 "Neighbor discovery\n"
993 "Home Agent lifetime\n")
995 struct interface
*ifp
;
996 struct zebra_if
*zif
;
998 ifp
= (struct interface
*) vty
->index
;
1001 zif
->rtadv
.HomeAgentLifetime
= -1;
1006 ALIAS (no_ipv6_nd_homeagent_lifetime
,
1007 no_ipv6_nd_homeagent_lifetime_val_cmd
,
1008 "no ipv6 nd home-agent-lifetime <0-65520>",
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")
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")
1022 struct interface
*ifp
;
1023 struct zebra_if
*zif
;
1025 ifp
= (struct interface
*) vty
->index
;
1028 zif
->rtadv
.AdvManagedFlag
= 1;
1033 DEFUN (no_ipv6_nd_managed_config_flag
,
1034 no_ipv6_nd_managed_config_flag_cmd
,
1035 "no ipv6 nd managed-config-flag",
1037 "Interface IPv6 config commands\n"
1038 "Neighbor discovery\n"
1039 "Managed address configuration flag\n")
1041 struct interface
*ifp
;
1042 struct zebra_if
*zif
;
1044 ifp
= (struct interface
*) vty
->index
;
1047 zif
->rtadv
.AdvManagedFlag
= 0;
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")
1059 struct interface
*ifp
;
1060 struct zebra_if
*zif
;
1062 ifp
= (struct interface
*) vty
->index
;
1065 zif
->rtadv
.AdvHomeAgentFlag
= 1;
1070 DEFUN (no_ipv6_nd_homeagent_config_flag
,
1071 no_ipv6_nd_homeagent_config_flag_cmd
,
1072 "no ipv6 nd home-agent-config-flag",
1074 "Interface IPv6 config commands\n"
1075 "Neighbor discovery\n"
1076 "Home Agent configuration flag\n")
1078 struct interface
*ifp
;
1079 struct zebra_if
*zif
;
1081 ifp
= (struct interface
*) vty
->index
;
1084 zif
->rtadv
.AdvHomeAgentFlag
= 0;
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")
1096 struct interface
*ifp
;
1097 struct zebra_if
*zif
;
1099 ifp
= (struct interface
*) vty
->index
;
1102 zif
->rtadv
.AdvIntervalOption
= 1;
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",
1111 "Interface IPv6 config commands\n"
1112 "Neighbor discovery\n"
1113 "Advertisement Interval Option\n")
1115 struct interface
*ifp
;
1116 struct zebra_if
*zif
;
1118 ifp
= (struct interface
*) vty
->index
;
1121 zif
->rtadv
.AdvIntervalOption
= 0;
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")
1133 struct interface
*ifp
;
1134 struct zebra_if
*zif
;
1136 ifp
= (struct interface
*) vty
->index
;
1139 zif
->rtadv
.AdvOtherConfigFlag
= 1;
1144 DEFUN (no_ipv6_nd_other_config_flag
,
1145 no_ipv6_nd_other_config_flag_cmd
,
1146 "no ipv6 nd other-config-flag",
1148 "Interface IPv6 config commands\n"
1149 "Neighbor discovery\n"
1150 "Other statefull configuration flag\n")
1152 struct interface
*ifp
;
1153 struct zebra_if
*zif
;
1155 ifp
= (struct interface
*) vty
->index
;
1158 zif
->rtadv
.AdvOtherConfigFlag
= 0;
1163 DEFUN (ipv6_nd_prefix
,
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"
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")
1182 struct interface
*ifp
;
1183 struct zebra_if
*zebra_if
;
1184 struct rtadv_prefix rp
;
1186 ifp
= (struct interface
*) vty
->index
;
1187 zebra_if
= ifp
->info
;
1189 ret
= str2prefix_ipv6 (argv
[0], &rp
.prefix
);
1192 vty_out (vty
, "Malformed IPv6 prefix%s", VTY_NEWLINE
);
1195 apply_mask_ipv6 (&rp
.prefix
); /* RFC4861 4.6.2 */
1196 rp
.AdvOnLinkFlag
= 1;
1197 rp
.AdvAutonomousFlag
= 1;
1198 rp
.AdvRouterAddressFlag
= 0;
1199 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
1200 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
1204 if ((isdigit(argv
[1][0])) || strncmp (argv
[1], "i", 1) == 0)
1206 if ( strncmp (argv
[1], "i", 1) == 0)
1207 rp
.AdvValidLifetime
= UINT32_MAX
;
1209 rp
.AdvValidLifetime
= (u_int32_t
) strtoll (argv
[1],
1212 if ( strncmp (argv
[2], "i", 1) == 0)
1213 rp
.AdvPreferredLifetime
= UINT32_MAX
;
1215 rp
.AdvPreferredLifetime
= (u_int32_t
) strtoll (argv
[2],
1218 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
)
1220 vty_out (vty
, "Invalid preferred lifetime%s", VTY_NEWLINE
);
1223 cursor
= cursor
+ 2;
1227 for (i
= cursor
; i
< argc
; i
++)
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;
1239 rtadv_prefix_set (zebra_if
, &rp
);
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"
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")
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"
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")
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"
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")
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"
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")
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"
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")
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"
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")
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"
1340 "Valid lifetime in seconds\n"
1341 "Infinite valid lifetime\n"
1342 "Preferred lifetime in seconds\n"
1343 "Infinite preferred lifetime\n")
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"
1352 "Do not use prefix for autoconfiguration\n"
1353 "Do not use prefix for onlink determination\n")
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"
1362 "Do not use prefix for onlink determination\n"
1363 "Do not use prefix for autoconfiguration\n")
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"
1372 "Do not use prefix for autoconfiguration\n")
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"
1381 "Do not use prefix for onlink determination\n")
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"
1390 "Set Router Address flag\n")
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"
1400 DEFUN (no_ipv6_nd_prefix
,
1401 no_ipv6_nd_prefix_cmd
,
1402 "no ipv6 nd prefix IPV6PREFIX",
1404 "Interface IPv6 config commands\n"
1405 "Neighbor discovery\n"
1406 "Prefix information\n"
1410 struct interface
*ifp
;
1411 struct zebra_if
*zebra_if
;
1412 struct rtadv_prefix rp
;
1414 ifp
= (struct interface
*) vty
->index
;
1415 zebra_if
= ifp
->info
;
1417 ret
= str2prefix_ipv6 (argv
[0], &rp
.prefix
);
1420 vty_out (vty
, "Malformed IPv6 prefix%s", VTY_NEWLINE
);
1423 apply_mask_ipv6 (&rp
.prefix
); /* RFC4861 4.6.2 */
1425 ret
= rtadv_prefix_reset (zebra_if
, &rp
);
1428 vty_out (vty
, "Non-exist IPv6 prefix%s", VTY_NEWLINE
);
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")
1445 struct interface
*ifp
;
1446 struct zebra_if
*zif
;
1449 ifp
= (struct interface
*) vty
->index
;
1452 while (0 != rtadv_pref_strs
[i
])
1454 if (strncmp (argv
[0], rtadv_pref_strs
[i
], 1) == 0)
1456 zif
->rtadv
.DefaultPreference
= i
;
1462 return CMD_ERR_NO_MATCH
;
1465 DEFUN (no_ipv6_nd_router_preference
,
1466 no_ipv6_nd_router_preference_cmd
,
1467 "no ipv6 nd router-preference",
1469 "Interface IPv6 config commands\n"
1470 "Neighbor discovery\n"
1471 "Default router preference\n")
1473 struct interface
*ifp
;
1474 struct zebra_if
*zif
;
1476 ifp
= (struct interface
*) vty
->index
;
1479 zif
->rtadv
.DefaultPreference
= RTADV_PREF_MEDIUM
; /* Default per RFC4191. */
1484 ALIAS (no_ipv6_nd_router_preference
,
1485 no_ipv6_nd_router_preference_val_cmd
,
1486 "no ipv6 nd router-preference (high|medium|low",
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")
1497 "ipv6 nd mtu <1-65535>",
1498 "Interface IPv6 config commands\n"
1499 "Neighbor discovery\n"
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);
1509 DEFUN (no_ipv6_nd_mtu
,
1513 "Interface IPv6 config commands\n"
1514 "Neighbor discovery\n"
1517 struct interface
*ifp
= (struct interface
*) vty
->index
;
1518 struct zebra_if
*zif
= ifp
->info
;
1519 zif
->rtadv
.AdvLinkMTU
= 0;
1523 ALIAS (no_ipv6_nd_mtu
,
1524 no_ipv6_nd_mtu_val_cmd
,
1525 "no ipv6 nd mtu <1-65535>",
1527 "Interface IPv6 config commands\n"
1528 "Neighbor discovery\n"
1532 /* Write configuration about router advertisement. */
1534 rtadv_config_write (struct vty
*vty
, struct interface
*ifp
)
1536 struct zebra_if
*zif
;
1537 struct listnode
*node
;
1538 struct rtadv_prefix
*rprefix
;
1539 u_char buf
[INET6_ADDRSTRLEN
];
1547 if (! if_is_loopback (ifp
))
1549 if (zif
->rtadv
.AdvSendAdvertisements
)
1550 vty_out (vty
, " no ipv6 nd suppress-ra%s", VTY_NEWLINE
);
1552 vty_out (vty
, " ipv6 nd suppress-ra%s", VTY_NEWLINE
);
1556 interval
= zif
->rtadv
.MaxRtrAdvInterval
;
1557 if (interval
% 1000)
1558 vty_out (vty
, " ipv6 nd ra-interval msec %d%s", interval
,
1561 if (interval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
1562 vty_out (vty
, " ipv6 nd ra-interval %d%s", interval
/ 1000,
1565 if (zif
->rtadv
.AdvIntervalOption
)
1566 vty_out (vty
, " ipv6 nd adv-interval-option%s", VTY_NEWLINE
);
1568 if (zif
->rtadv
.AdvDefaultLifetime
!= -1)
1569 vty_out (vty
, " ipv6 nd ra-lifetime %d%s", zif
->rtadv
.AdvDefaultLifetime
,
1572 if (zif
->rtadv
.HomeAgentPreference
)
1573 vty_out (vty
, " ipv6 nd home-agent-preference %u%s",
1574 zif
->rtadv
.HomeAgentPreference
, VTY_NEWLINE
);
1576 if (zif
->rtadv
.HomeAgentLifetime
!= -1)
1577 vty_out (vty
, " ipv6 nd home-agent-lifetime %u%s",
1578 zif
->rtadv
.HomeAgentLifetime
, VTY_NEWLINE
);
1580 if (zif
->rtadv
.AdvHomeAgentFlag
)
1581 vty_out (vty
, " ipv6 nd home-agent-config-flag%s", VTY_NEWLINE
);
1583 if (zif
->rtadv
.AdvReachableTime
)
1584 vty_out (vty
, " ipv6 nd reachable-time %d%s", zif
->rtadv
.AdvReachableTime
,
1587 if (zif
->rtadv
.AdvManagedFlag
)
1588 vty_out (vty
, " ipv6 nd managed-config-flag%s", VTY_NEWLINE
);
1590 if (zif
->rtadv
.AdvOtherConfigFlag
)
1591 vty_out (vty
, " ipv6 nd other-config-flag%s", VTY_NEWLINE
);
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
],
1598 if (zif
->rtadv
.AdvLinkMTU
)
1599 vty_out (vty
, " ipv6 nd mtu %d%s", zif
->rtadv
.AdvLinkMTU
, VTY_NEWLINE
);
1601 for (ALL_LIST_ELEMENTS_RO (zif
->rtadv
.AdvPrefixList
, node
, rprefix
))
1603 vty_out (vty
, " ipv6 nd prefix %s/%d",
1604 inet_ntop (AF_INET6
, &rprefix
->prefix
.prefix
,
1605 (char *) buf
, INET6_ADDRSTRLEN
),
1606 rprefix
->prefix
.prefixlen
);
1607 if ((rprefix
->AdvValidLifetime
!= RTADV_VALID_LIFETIME
) ||
1608 (rprefix
->AdvPreferredLifetime
!= RTADV_PREFERRED_LIFETIME
))
1610 if (rprefix
->AdvValidLifetime
== UINT32_MAX
)
1611 vty_out (vty
, " infinite");
1613 vty_out (vty
, " %u", rprefix
->AdvValidLifetime
);
1614 if (rprefix
->AdvPreferredLifetime
== UINT32_MAX
)
1615 vty_out (vty
, " infinite");
1617 vty_out (vty
, " %u", rprefix
->AdvPreferredLifetime
);
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
);
1631 rtadv_event (enum rtadv_event event
, int val
)
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
,
1643 if (rtadv
->ra_timer
)
1645 thread_cancel (rtadv
->ra_timer
);
1646 rtadv
->ra_timer
= NULL
;
1650 thread_cancel (rtadv
->ra_read
);
1651 rtadv
->ra_read
= NULL
;
1655 if (! rtadv
->ra_timer
)
1656 rtadv
->ra_timer
= thread_add_timer (zebrad
.master
, rtadv_timer
, NULL
,
1659 case RTADV_TIMER_MSEC
:
1660 if (! rtadv
->ra_timer
)
1661 rtadv
->ra_timer
= thread_add_timer_msec (zebrad
.master
, rtadv_timer
,
1665 if (! rtadv
->ra_read
)
1666 rtadv
->ra_read
= thread_add_read (zebrad
.master
, rtadv_read
, NULL
, val
);
1679 sock
= rtadv_make_socket ();
1683 rtadv
= rtadv_new ();
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
);
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
);
1693 install_element (INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
1694 install_element (INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
1695 install_element (INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_val_cmd
);
1696 install_element (INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
1697 install_element (INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
1698 install_element (INTERFACE_NODE
, &no_ipv6_nd_reachable_time_val_cmd
);
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
);
1707 install_element (INTERFACE_NODE
, &no_ipv6_nd_homeagent_preference_val_cmd
);
1708 install_element (INTERFACE_NODE
, &ipv6_nd_homeagent_lifetime_cmd
);
1709 install_element (INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_cmd
);
1710 install_element (INTERFACE_NODE
, &no_ipv6_nd_homeagent_lifetime_val_cmd
);
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
);
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
);
1737 if_join_all_router (int sock
, struct interface
*ifp
)
1741 struct ipv6_mreq mreq
;
1743 memset (&mreq
, 0, sizeof (struct ipv6_mreq
));
1744 inet_pton (AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1745 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1747 ret
= setsockopt (sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
,
1748 (char *) &mreq
, sizeof mreq
);
1750 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", safe_strerror (errno
));
1752 zlog_info ("rtadv: %s join to all-routers multicast group", ifp
->name
);
1758 if_leave_all_router (int sock
, struct interface
*ifp
)
1762 struct ipv6_mreq mreq
;
1764 memset (&mreq
, 0, sizeof (struct ipv6_mreq
));
1765 inet_pton (AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1766 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1768 ret
= setsockopt (sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
,
1769 (char *) &mreq
, sizeof mreq
);
1771 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", safe_strerror (errno
));
1773 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp
->name
);
1784 #endif /* RTADV && HAVE_IPV6 */