1 /* Router advertisement
2 * Copyright (C) 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
34 #include "zebra/interface.h"
35 #include "zebra/rtadv.h"
36 #include "zebra/debug.h"
37 #include "zebra/zserv.h"
39 extern struct zebra_privs_t zserv_privs
;
41 #if defined (HAVE_IPV6) && defined (RTADV)
43 /* If RFC2133 definition is used. */
44 #ifndef IPV6_JOIN_GROUP
45 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
47 #ifndef IPV6_LEAVE_GROUP
48 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
51 #define ALLNODE "ff02::1"
52 #define ALLROUTER "ff02::2"
54 extern struct zebra_t zebrad
;
56 enum rtadv_event
{RTADV_START
, RTADV_STOP
, RTADV_TIMER
, RTADV_READ
};
58 void rtadv_event (enum rtadv_event
, int);
60 int if_join_all_router (int, struct interface
*);
61 int if_leave_all_router (int, struct interface
*);
63 /* Structure which hold status of router advertisement. */
70 struct thread
*ra_read
;
71 struct thread
*ra_timer
;
74 struct rtadv
*rtadv
= NULL
;
80 new = XMALLOC (MTYPE_TMP
, sizeof (struct rtadv
));
81 memset (new, 0, sizeof (struct rtadv
));
86 rtadv_free (struct rtadv
*rtadv
)
88 XFREE (MTYPE_TMP
, rtadv
);
92 rtadv_recv_packet (int sock
, u_char
*buf
, int buflen
,
93 struct sockaddr_in6
*from
, unsigned int *ifindex
,
99 struct cmsghdr
*cmsgptr
;
104 /* Fill in message and iovec. */
105 msg
.msg_name
= (void *) from
;
106 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
109 msg
.msg_control
= (void *) adata
;
110 msg
.msg_controllen
= sizeof adata
;
112 iov
.iov_len
= buflen
;
114 /* If recvmsg fail return minus value. */
115 ret
= recvmsg (sock
, &msg
, 0);
119 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
120 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
))
122 /* I want interface index which this packet comes from. */
123 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
&&
124 cmsgptr
->cmsg_type
== IPV6_PKTINFO
)
126 struct in6_pktinfo
*ptr
;
128 ptr
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
129 *ifindex
= ptr
->ipi6_ifindex
;
130 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
133 /* Incoming packet's hop limit. */
134 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
&&
135 cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
)
136 *hoplimit
= *((int *) CMSG_DATA (cmsgptr
));
141 #define RTADV_MSG_SIZE 4096
143 /* Send router advertisement packet. */
145 rtadv_send_packet (int sock
, struct interface
*ifp
)
149 struct cmsghdr
*cmsgptr
;
150 struct in6_pktinfo
*pkt
;
151 struct sockaddr_in6 addr
;
152 #ifdef HAVE_SOCKADDR_DL
153 struct sockaddr_dl
*sdl
;
154 #endif /* HAVE_SOCKADDR_DL */
155 char adata
[sizeof (struct cmsghdr
) + sizeof (struct in6_pktinfo
)];
156 unsigned char buf
[RTADV_MSG_SIZE
];
157 struct nd_router_advert
*rtadv
;
160 struct zebra_if
*zif
;
161 u_char all_nodes_addr
[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
164 /* Logging of packet. */
165 if (IS_ZEBRA_DEBUG_PACKET
)
166 zlog_info ("Router advertisement send to %s", ifp
->name
);
168 /* Fill in sockaddr_in6. */
169 memset (&addr
, 0, sizeof (struct sockaddr_in6
));
170 addr
.sin6_family
= AF_INET6
;
172 addr
.sin6_len
= sizeof (struct sockaddr_in6
);
173 #endif /* SIN6_LEN */
174 addr
.sin6_port
= htons (IPPROTO_ICMPV6
);
175 memcpy (&addr
.sin6_addr
, all_nodes_addr
, sizeof (struct in6_addr
));
177 /* Fetch interface information. */
180 /* Make router advertisement message. */
181 rtadv
= (struct nd_router_advert
*) buf
;
183 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
184 rtadv
->nd_ra_code
= 0;
185 rtadv
->nd_ra_cksum
= 0;
187 rtadv
->nd_ra_curhoplimit
= 64;
188 rtadv
->nd_ra_flags_reserved
= 0;
189 if (zif
->rtadv
.AdvManagedFlag
)
190 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
191 if (zif
->rtadv
.AdvOtherConfigFlag
)
192 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
193 rtadv
->nd_ra_router_lifetime
= htons (zif
->rtadv
.AdvDefaultLifetime
);
194 rtadv
->nd_ra_reachable
= htonl (zif
->rtadv
.AdvReachableTime
);
195 rtadv
->nd_ra_retransmit
= htonl (0);
197 len
= sizeof (struct nd_router_advert
);
199 /* Fill in prefix. */
200 for (node
= listhead (zif
->rtadv
.AdvPrefixList
); node
; node
= nextnode (node
))
202 struct nd_opt_prefix_info
*pinfo
;
203 struct rtadv_prefix
*rprefix
;
205 rprefix
= getdata (node
);
207 pinfo
= (struct nd_opt_prefix_info
*) (buf
+ len
);
209 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
210 pinfo
->nd_opt_pi_len
= 4;
211 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
213 pinfo
->nd_opt_pi_flags_reserved
= 0;
214 if (rprefix
->AdvOnLinkFlag
)
215 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_ONLINK
;
216 if (rprefix
->AdvAutonomousFlag
)
217 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
219 pinfo
->nd_opt_pi_valid_time
= htonl (rprefix
->AdvValidLifetime
);
220 pinfo
->nd_opt_pi_preferred_time
= htonl (rprefix
->AdvPreferredLifetime
);
221 pinfo
->nd_opt_pi_reserved2
= 0;
223 memcpy (&pinfo
->nd_opt_pi_prefix
, &rprefix
->prefix
.u
.prefix6
,
224 sizeof (struct in6_addr
));
228 u_char buf
[INET6_ADDRSTRLEN
];
230 zlog_info ("DEBUG %s", inet_ntop (AF_INET6
, &pinfo
->nd_opt_pi_prefix
, buf
, INET6_ADDRSTRLEN
));
235 len
+= sizeof (struct nd_opt_prefix_info
);
238 /* Hardware address. */
239 #ifdef HAVE_SOCKADDR_DL
241 if (sdl
!= NULL
&& sdl
->sdl_alen
!= 0)
243 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
244 buf
[len
++] = (sdl
->sdl_alen
+ 2) >> 3;
246 memcpy (buf
+ len
, LLADDR (sdl
), sdl
->sdl_alen
);
247 len
+= sdl
->sdl_alen
;
250 if (ifp
->hw_addr_len
!= 0)
252 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
253 buf
[len
++] = (ifp
->hw_addr_len
+ 2) >> 3;
255 memcpy (buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
256 len
+= ifp
->hw_addr_len
;
258 #endif /* HAVE_SOCKADDR_DL */
260 msg
.msg_name
= (void *) &addr
;
261 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
264 msg
.msg_control
= (void *) adata
;
265 msg
.msg_controllen
= sizeof adata
;
269 cmsgptr
= (struct cmsghdr
*)adata
;
270 cmsgptr
->cmsg_len
= sizeof adata
;
271 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
272 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
273 pkt
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
274 memset (&pkt
->ipi6_addr
, 0, sizeof (struct in6_addr
));
275 pkt
->ipi6_ifindex
= ifp
->ifindex
;
277 ret
= sendmsg (sock
, &msg
, 0);
283 rtadv_timer (struct thread
*thread
)
286 struct interface
*ifp
;
287 struct zebra_if
*zif
;
289 rtadv
->ra_timer
= NULL
;
290 rtadv_event (RTADV_TIMER
, 1);
292 for (node
= listhead (iflist
); node
; nextnode (node
))
294 ifp
= getdata (node
);
296 if (if_is_loopback (ifp
))
301 if (zif
->rtadv
.AdvSendAdvertisements
)
302 if (--zif
->rtadv
.AdvIntervalTimer
<= 0)
304 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
305 rtadv_send_packet (rtadv
->sock
, ifp
);
312 rtadv_process_solicit (struct interface
*ifp
)
314 zlog_info ("Router solicitation received on %s", ifp
->name
);
316 rtadv_send_packet (rtadv
->sock
, ifp
);
320 rtadv_process_advert ()
322 zlog_info ("Router advertisement received");
326 rtadv_process_packet (u_char
*buf
, int len
, unsigned int ifindex
, int hoplimit
)
328 struct icmp6_hdr
*icmph
;
329 struct interface
*ifp
;
330 struct zebra_if
*zif
;
332 /* Interface search. */
333 ifp
= if_lookup_by_index (ifindex
);
336 zlog_warn ("Unknown interface index: %d", ifindex
);
340 if (if_is_loopback (ifp
))
343 /* Check interface configuration. */
345 if (! zif
->rtadv
.AdvSendAdvertisements
)
348 /* ICMP message length check. */
349 if (len
< sizeof (struct icmp6_hdr
))
351 zlog_warn ("Invalid ICMPV6 packet length: %d", len
);
355 icmph
= (struct icmp6_hdr
*) buf
;
357 /* ICMP message type check. */
358 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
&&
359 icmph
->icmp6_type
!= ND_ROUTER_ADVERT
)
361 zlog_warn ("Unwanted ICMPV6 message type: %d", icmph
->icmp6_type
);
365 /* Hoplimit check. */
366 if (hoplimit
>= 0 && hoplimit
!= 255)
368 zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
373 /* Check ICMP message type. */
374 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
375 rtadv_process_solicit (ifp
);
376 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
377 rtadv_process_advert ();
383 rtadv_read (struct thread
*thread
)
387 u_char buf
[RTADV_MSG_SIZE
];
388 struct sockaddr_in6 from
;
389 unsigned int ifindex
;
392 sock
= THREAD_FD (thread
);
393 rtadv
->ra_read
= NULL
;
395 /* Register myself. */
396 rtadv_event (RTADV_READ
, sock
);
398 len
= rtadv_recv_packet (sock
, buf
, BUFSIZ
, &from
, &ifindex
, &hoplimit
);
402 zlog_warn ("router solicitation recv failed: %s.", strerror (errno
));
406 rtadv_process_packet (buf
, len
, ifindex
, hoplimit
);
412 rtadv_make_socket (void)
416 struct icmp6_filter filter
;
418 if ( zserv_privs
.change (ZPRIVS_RAISE
) )
419 zlog_err ("rtadv_make_socket: could not raise privs, %s",
422 sock
= socket (AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
);
424 if ( zserv_privs
.change (ZPRIVS_LOWER
) )
425 zlog_err ("rtadv_make_socket: could not lower privs, %s",
428 /* When we can't make ICMPV6 socket simply back. Router
429 advertisement feature will not be supported. */
433 ret
= setsockopt_ipv6_pktinfo (sock
, 1);
436 ret
= setsockopt_ipv6_multicast_loop (sock
, 0);
439 ret
= setsockopt_ipv6_unicast_hops (sock
, 255);
442 ret
= setsockopt_ipv6_multicast_hops (sock
, 255);
445 ret
= setsockopt_ipv6_hoplimit (sock
, 1);
449 ICMP6_FILTER_SETBLOCKALL(&filter
);
450 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT
, &filter
);
451 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT
, &filter
);
453 ret
= setsockopt (sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
454 sizeof (struct icmp6_filter
));
457 zlog_info ("ICMP6_FILTER set fail: %s", strerror (errno
));
464 struct rtadv_prefix
*
467 struct rtadv_prefix
*new;
469 new = XMALLOC (MTYPE_RTADV_PREFIX
, sizeof (struct rtadv_prefix
));
470 memset (new, 0, sizeof (struct rtadv_prefix
));
476 rtadv_prefix_free (struct rtadv_prefix
*rtadv_prefix
)
478 XFREE (MTYPE_RTADV_PREFIX
, rtadv_prefix
);
481 struct rtadv_prefix
*
482 rtadv_prefix_lookup (list rplist
, struct prefix
*p
)
485 struct rtadv_prefix
*rprefix
;
487 for (node
= listhead (rplist
); node
; node
= nextnode (node
))
489 rprefix
= getdata (node
);
490 if (prefix_same (&rprefix
->prefix
, p
))
496 struct rtadv_prefix
*
497 rtadv_prefix_get (list rplist
, struct prefix
*p
)
499 struct rtadv_prefix
*rprefix
;
501 rprefix
= rtadv_prefix_lookup (rplist
, p
);
505 rprefix
= rtadv_prefix_new ();
506 memcpy (&rprefix
->prefix
, p
, sizeof (struct prefix
));
507 listnode_add (rplist
, rprefix
);
513 rtadv_prefix_set (struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
515 struct rtadv_prefix
*rprefix
;
517 rprefix
= rtadv_prefix_get (zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
519 /* Set parameters. */
520 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
521 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
522 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
523 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
527 rtadv_prefix_reset (struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
529 struct rtadv_prefix
*rprefix
;
531 rprefix
= rtadv_prefix_lookup (zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
534 listnode_delete (zif
->rtadv
.AdvPrefixList
, (void *) rprefix
);
535 rtadv_prefix_free (rprefix
);
542 DEFUN (ipv6_nd_suppress_ra
,
543 ipv6_nd_suppress_ra_cmd
,
544 "ipv6 nd suppress-ra",
546 "Neighbor discovery\n"
547 "Suppress Router Advertisement\n")
549 struct interface
*ifp
;
550 struct zebra_if
*zif
;
555 if (if_is_loopback (ifp
))
557 vty_out (vty
, "Invalid interface%s", VTY_NEWLINE
);
561 if (zif
->rtadv
.AdvSendAdvertisements
)
563 zif
->rtadv
.AdvSendAdvertisements
= 0;
564 zif
->rtadv
.AdvIntervalTimer
= 0;
565 rtadv
->adv_if_count
--;
567 if_leave_all_router (rtadv
->sock
, ifp
);
569 if (rtadv
->adv_if_count
== 0)
570 rtadv_event (RTADV_STOP
, 0);
576 ALIAS (ipv6_nd_suppress_ra
,
577 no_ipv6_nd_send_ra_cmd
,
578 "no ipv6 nd send-ra",
581 "Neighbor discovery\n"
582 "Send Router Advertisement\n")
584 DEFUN (no_ipv6_nd_suppress_ra
,
585 no_ipv6_nd_suppress_ra_cmd
,
586 "no ipv6 nd suppress-ra",
589 "Neighbor discovery\n"
590 "Suppress Router Advertisement\n")
592 struct interface
*ifp
;
593 struct zebra_if
*zif
;
598 if (if_is_loopback (ifp
))
600 vty_out (vty
, "Invalid interface%s", VTY_NEWLINE
);
604 if (! zif
->rtadv
.AdvSendAdvertisements
)
606 zif
->rtadv
.AdvSendAdvertisements
= 1;
607 zif
->rtadv
.AdvIntervalTimer
= 0;
608 rtadv
->adv_if_count
++;
610 if_join_all_router (rtadv
->sock
, ifp
);
612 if (rtadv
->adv_if_count
== 1)
613 rtadv_event (RTADV_START
, rtadv
->sock
);
619 ALIAS (no_ipv6_nd_suppress_ra
,
623 "Neighbor discovery\n"
624 "Send Router Advertisement\n")
626 DEFUN (ipv6_nd_ra_interval
,
627 ipv6_nd_ra_interval_cmd
,
628 "ipv6 nd ra-interval SECONDS",
630 "Neighbor discovery\n"
631 "Router Advertisement interval\n"
632 "Router Advertisement interval in seconds\n")
635 struct interface
*ifp
;
636 struct zebra_if
*zif
;
638 ifp
= (struct interface
*) vty
->index
;
641 interval
= atoi (argv
[0]);
645 vty_out (vty
, "Invalid Router Advertisement Interval%s", VTY_NEWLINE
);
649 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
650 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
651 zif
->rtadv
.AdvIntervalTimer
= 0;
656 DEFUN (no_ipv6_nd_ra_interval
,
657 no_ipv6_nd_ra_interval_cmd
,
658 "no ipv6 nd ra-interval",
661 "Neighbor discovery\n"
662 "Router Advertisement interval\n")
664 struct interface
*ifp
;
665 struct zebra_if
*zif
;
667 ifp
= (struct interface
*) vty
->index
;
670 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
671 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
672 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
677 DEFUN (ipv6_nd_ra_lifetime
,
678 ipv6_nd_ra_lifetime_cmd
,
679 "ipv6 nd ra-lifetime SECONDS",
681 "Neighbor discovery\n"
683 "Router lifetime in seconds\n")
686 struct interface
*ifp
;
687 struct zebra_if
*zif
;
689 ifp
= (struct interface
*) vty
->index
;
692 lifetime
= atoi (argv
[0]);
694 if (lifetime
< 0 || lifetime
> 0xffff)
696 vty_out (vty
, "Invalid Router Lifetime%s", VTY_NEWLINE
);
700 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
705 DEFUN (no_ipv6_nd_ra_lifetime
,
706 no_ipv6_nd_ra_lifetime_cmd
,
707 "no ipv6 nd ra-lifetime",
710 "Neighbor discovery\n"
713 struct interface
*ifp
;
714 struct zebra_if
*zif
;
716 ifp
= (struct interface
*) vty
->index
;
719 zif
->rtadv
.AdvDefaultLifetime
= RTADV_ADV_DEFAULT_LIFETIME
;
724 DEFUN (ipv6_nd_reachable_time
,
725 ipv6_nd_reachable_time_cmd
,
726 "ipv6 nd reachable-time MILLISECONDS",
728 "Neighbor discovery\n"
730 "Reachable time in milliseconds\n")
733 struct interface
*ifp
;
734 struct zebra_if
*zif
;
736 ifp
= (struct interface
*) vty
->index
;
739 rtime
= (u_int32_t
) atol (argv
[0]);
741 if (rtime
> RTADV_MAX_REACHABLE_TIME
)
743 vty_out (vty
, "Invalid Reachable time%s", VTY_NEWLINE
);
747 zif
->rtadv
.AdvReachableTime
= rtime
;
752 DEFUN (no_ipv6_nd_reachable_time
,
753 no_ipv6_nd_reachable_time_cmd
,
754 "no ipv6 nd reachable-time",
757 "Neighbor discovery\n"
760 struct interface
*ifp
;
761 struct zebra_if
*zif
;
763 ifp
= (struct interface
*) vty
->index
;
766 zif
->rtadv
.AdvReachableTime
= 0;
771 DEFUN (ipv6_nd_managed_config_flag
,
772 ipv6_nd_managed_config_flag_cmd
,
773 "ipv6 nd managed-config-flag",
775 "Neighbor discovery\n"
776 "Managed address configuration flag\n")
778 struct interface
*ifp
;
779 struct zebra_if
*zif
;
781 ifp
= (struct interface
*) vty
->index
;
784 zif
->rtadv
.AdvManagedFlag
= 1;
789 DEFUN (no_ipv6_nd_managed_config_flag
,
790 no_ipv6_nd_managed_config_flag_cmd
,
791 "no ipv6 nd managed-config-flag",
794 "Neighbor discovery\n"
795 "Managed address configuration flag\n")
797 struct interface
*ifp
;
798 struct zebra_if
*zif
;
800 ifp
= (struct interface
*) vty
->index
;
803 zif
->rtadv
.AdvManagedFlag
= 0;
808 DEFUN (ipv6_nd_other_config_flag
,
809 ipv6_nd_other_config_flag_cmd
,
810 "ipv6 nd other-config-flag",
812 "Neighbor discovery\n"
813 "Other statefull configuration flag\n")
815 struct interface
*ifp
;
816 struct zebra_if
*zif
;
818 ifp
= (struct interface
*) vty
->index
;
821 zif
->rtadv
.AdvOtherConfigFlag
= 1;
826 DEFUN (no_ipv6_nd_other_config_flag
,
827 no_ipv6_nd_other_config_flag_cmd
,
828 "no ipv6 nd other-config-flag",
831 "Neighbor discovery\n"
832 "Other statefull configuration flag\n")
834 struct interface
*ifp
;
835 struct zebra_if
*zif
;
837 ifp
= (struct interface
*) vty
->index
;
840 zif
->rtadv
.AdvOtherConfigFlag
= 0;
845 DEFUN (ipv6_nd_prefix_advertisement
,
846 ipv6_nd_prefix_advertisement_cmd
,
847 "ipv6 nd prefix-advertisement IPV6PREFIX VALID PREFERRED [onlink] [autoconfig]",
849 "Neighbor discovery\n"
850 "Prefix information\n"
852 "Valid lifetime in seconds\n"
853 "Preferred lifetime in seconds\n"
855 "Autonomous address-configuration flag\n")
859 struct interface
*ifp
;
860 struct zebra_if
*zebra_if
;
861 struct rtadv_prefix rp
;
863 ifp
= (struct interface
*) vty
->index
;
864 zebra_if
= ifp
->info
;
866 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*) &rp
.prefix
);
869 vty_out (vty
, "Malformed IPv6 prefix%s", VTY_NEWLINE
);
875 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
876 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
877 rp
.AdvOnLinkFlag
= 1;
878 rp
.AdvAutonomousFlag
= 1;
882 rp
.AdvValidLifetime
= (u_int32_t
) atol (argv
[1]);
883 rp
.AdvPreferredLifetime
= (u_int32_t
) atol (argv
[2]);
884 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
)
886 vty_out (vty
, "Invalid preferred lifetime%s", VTY_NEWLINE
);
890 rp
.AdvOnLinkFlag
= 0;
891 rp
.AdvAutonomousFlag
= 0;
892 for (i
= 3; i
< argc
; i
++)
894 if (! strcmp (argv
[i
], "onlink"))
895 rp
.AdvOnLinkFlag
= 1;
896 else if (! strcmp (argv
[i
], "autoconfig"))
897 rp
.AdvAutonomousFlag
= 1;
901 rtadv_prefix_set (zebra_if
, &rp
);
906 ALIAS (ipv6_nd_prefix_advertisement
,
907 ipv6_nd_prefix_advertisement_no_val_cmd
,
908 "ipv6 nd prefix-advertisement IPV6PREFIX",
910 "Neighbor discovery\n"
911 "Prefix information\n"
914 DEFUN (no_ipv6_nd_prefix_advertisement
,
915 no_ipv6_nd_prefix_advertisement_cmd
,
916 "no ipv6 nd prefix-advertisement IPV6PREFIX",
919 "Neighbor discovery\n"
920 "Prefix information\n"
924 struct interface
*ifp
;
925 struct zebra_if
*zebra_if
;
926 struct rtadv_prefix rp
;
928 ifp
= (struct interface
*) vty
->index
;
929 zebra_if
= ifp
->info
;
931 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*) &rp
.prefix
);
934 vty_out (vty
, "Malformed IPv6 prefix%s", VTY_NEWLINE
);
938 ret
= rtadv_prefix_reset (zebra_if
, &rp
);
941 vty_out (vty
, "Non-exist IPv6 prefix%s", VTY_NEWLINE
);
948 /* Write configuration about router advertisement. */
950 rtadv_config_write (struct vty
*vty
, struct interface
*ifp
)
952 struct zebra_if
*zif
;
954 struct rtadv_prefix
*rprefix
;
955 u_char buf
[INET6_ADDRSTRLEN
];
962 if (! if_is_loopback (ifp
))
964 if (zif
->rtadv
.AdvSendAdvertisements
)
965 vty_out (vty
, " no ipv6 nd suppress-ra%s", VTY_NEWLINE
);
967 vty_out (vty
, " ipv6 nd suppress-ra%s", VTY_NEWLINE
);
970 if (zif
->rtadv
.MaxRtrAdvInterval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
971 vty_out (vty
, " ipv6 nd ra-interval %d%s", zif
->rtadv
.MaxRtrAdvInterval
,
974 if (zif
->rtadv
.AdvDefaultLifetime
!= RTADV_ADV_DEFAULT_LIFETIME
)
975 vty_out (vty
, " ipv6 nd ra-lifetime %d%s", zif
->rtadv
.AdvDefaultLifetime
,
978 if (zif
->rtadv
.AdvReachableTime
)
979 vty_out (vty
, " ipv6 nd reachable-time %d%s", zif
->rtadv
.AdvReachableTime
,
982 if (zif
->rtadv
.AdvManagedFlag
)
983 vty_out (vty
, " ipv6 nd managed-config-flag%s", VTY_NEWLINE
);
985 if (zif
->rtadv
.AdvOtherConfigFlag
)
986 vty_out (vty
, " ipv6 nd other-config-flag%s", VTY_NEWLINE
);
988 for (node
= listhead(zif
->rtadv
.AdvPrefixList
); node
; node
= nextnode (node
))
990 rprefix
= getdata (node
);
991 vty_out (vty
, " ipv6 nd prefix-advertisement %s/%d %d %d",
992 inet_ntop (AF_INET6
, &rprefix
->prefix
.u
.prefix6
,
993 buf
, INET6_ADDRSTRLEN
),
994 rprefix
->prefix
.prefixlen
,
995 rprefix
->AdvValidLifetime
,
996 rprefix
->AdvPreferredLifetime
);
997 if (rprefix
->AdvOnLinkFlag
)
998 vty_out (vty
, " onlink");
999 if (rprefix
->AdvAutonomousFlag
)
1000 vty_out (vty
, " autoconfig");
1001 vty_out (vty
, "%s", VTY_NEWLINE
);
1007 rtadv_event (enum rtadv_event event
, int val
)
1012 if (! rtadv
->ra_read
)
1013 rtadv
->ra_read
= thread_add_read (zebrad
.master
, rtadv_read
, NULL
, val
);
1014 if (! rtadv
->ra_timer
)
1015 rtadv
->ra_timer
= thread_add_event (zebrad
.master
, rtadv_timer
, NULL
, 0);
1018 if (rtadv
->ra_timer
)
1020 thread_cancel (rtadv
->ra_timer
);
1021 rtadv
->ra_timer
= NULL
;
1025 thread_cancel (rtadv
->ra_read
);
1026 rtadv
->ra_read
= NULL
;
1030 if (! rtadv
->ra_timer
)
1031 rtadv
->ra_timer
= thread_add_timer (zebrad
.master
, rtadv_timer
, NULL
, val
);
1034 if (! rtadv
->ra_read
)
1035 rtadv
->ra_read
= thread_add_read (zebrad
.master
, rtadv_read
, NULL
, val
);
1048 sock
= rtadv_make_socket ();
1052 rtadv
= rtadv_new ();
1055 install_element (INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
1056 install_element (INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
1057 install_element (INTERFACE_NODE
, &ipv6_nd_send_ra_cmd
);
1058 install_element (INTERFACE_NODE
, &no_ipv6_nd_send_ra_cmd
);
1059 install_element (INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
1060 install_element (INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
1061 install_element (INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
1062 install_element (INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
1063 install_element (INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
1064 install_element (INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
1065 install_element (INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
1066 install_element (INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
1067 install_element (INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
1068 install_element (INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
1069 install_element (INTERFACE_NODE
, &ipv6_nd_prefix_advertisement_cmd
);
1070 install_element (INTERFACE_NODE
, &ipv6_nd_prefix_advertisement_no_val_cmd
);
1071 install_element (INTERFACE_NODE
, &no_ipv6_nd_prefix_advertisement_cmd
);
1075 if_join_all_router (int sock
, struct interface
*ifp
)
1079 struct ipv6_mreq mreq
;
1081 memset (&mreq
, 0, sizeof (struct ipv6_mreq
));
1082 inet_pton (AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1083 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1085 ret
= setsockopt (sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
,
1086 (char *) &mreq
, sizeof mreq
);
1088 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", strerror (errno
));
1090 zlog_info ("rtadv: %s join to all-routers multicast group", ifp
->name
);
1096 if_leave_all_router (int sock
, struct interface
*ifp
)
1100 struct ipv6_mreq mreq
;
1102 memset (&mreq
, 0, sizeof (struct ipv6_mreq
));
1103 inet_pton (AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1104 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1106 ret
= setsockopt (sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
,
1107 (char *) &mreq
, sizeof mreq
);
1109 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", strerror (errno
));
1111 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp
->name
);
1122 #endif /* RTADV && HAVE_IPV6 */