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
33 #include "zebra/interface.h"
34 #include "zebra/rtadv.h"
35 #include "zebra/debug.h"
37 #if defined (HAVE_IPV6) && defined (RTADV)
39 /* If RFC2133 definition is used. */
40 #ifndef IPV6_JOIN_GROUP
41 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
43 #ifndef IPV6_LEAVE_GROUP
44 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
47 #define ALLNODE "ff02::1"
48 #define ALLROUTER "ff02::2"
50 enum rtadv_event
{RTADV_START
, RTADV_STOP
, RTADV_TIMER
, RTADV_READ
};
52 void rtadv_event (enum rtadv_event
, int);
54 int if_join_all_router (int, struct interface
*);
55 int if_leave_all_router (int, struct interface
*);
57 /* Structure which hold status of router advertisement. */
64 struct thread
*ra_read
;
65 struct thread
*ra_timer
;
68 struct rtadv
*rtadv
= NULL
;
74 new = XMALLOC (MTYPE_TMP
, sizeof (struct rtadv
));
75 memset (new, 0, sizeof (struct rtadv
));
80 rtadv_free (struct rtadv
*rtadv
)
82 XFREE (MTYPE_TMP
, rtadv
);
86 rtadv_recv_packet (int sock
, u_char
*buf
, int buflen
,
87 struct sockaddr_in6
*from
, unsigned int *ifindex
,
93 struct cmsghdr
*cmsgptr
;
98 /* Fill in message and iovec. */
99 msg
.msg_name
= (void *) from
;
100 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
103 msg
.msg_control
= (void *) adata
;
104 msg
.msg_controllen
= sizeof adata
;
106 iov
.iov_len
= buflen
;
108 /* If recvmsg fail return minus value. */
109 ret
= recvmsg (sock
, &msg
, 0);
113 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
114 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
))
116 /* I want interface index which this packet comes from. */
117 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
&&
118 cmsgptr
->cmsg_type
== IPV6_PKTINFO
)
120 struct in6_pktinfo
*ptr
;
122 ptr
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
123 *ifindex
= ptr
->ipi6_ifindex
;
124 memcpy(&dst
, &ptr
->ipi6_addr
, sizeof(ptr
->ipi6_addr
));
127 /* Incoming packet's hop limit. */
128 if (cmsgptr
->cmsg_level
== IPPROTO_IPV6
&&
129 cmsgptr
->cmsg_type
== IPV6_HOPLIMIT
)
130 *hoplimit
= *((int *) CMSG_DATA (cmsgptr
));
135 #define RTADV_MSG_SIZE 4096
137 /* Send router advertisement packet. */
139 rtadv_send_packet (int sock
, struct interface
*ifp
)
143 struct cmsghdr
*cmsgptr
;
144 struct in6_pktinfo
*pkt
;
145 struct sockaddr_in6 addr
;
147 struct sockaddr_dl
*sdl
;
148 #endif /* HAVE_SOCKADDR_DL */
149 char adata
[sizeof (struct cmsghdr
) + sizeof (struct in6_pktinfo
)];
150 unsigned char buf
[RTADV_MSG_SIZE
];
151 struct nd_router_advert
*rtadv
;
154 struct zebra_if
*zif
;
155 u_char all_nodes_addr
[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
158 /* Logging of packet. */
159 if (IS_ZEBRA_DEBUG_PACKET
)
160 zlog_info ("Router advertisement send to %s", ifp
->name
);
162 /* Fill in sockaddr_in6. */
163 memset (&addr
, 0, sizeof (struct sockaddr_in6
));
164 addr
.sin6_family
= AF_INET6
;
166 addr
.sin6_len
= sizeof (struct sockaddr_in6
);
167 #endif /* SIN6_LEN */
168 addr
.sin6_port
= htons (IPPROTO_ICMPV6
);
169 memcpy (&addr
.sin6_addr
, all_nodes_addr
, sizeof (struct in6_addr
));
171 /* Fetch interface information. */
174 /* Make router advertisement message. */
175 rtadv
= (struct nd_router_advert
*) buf
;
177 rtadv
->nd_ra_type
= ND_ROUTER_ADVERT
;
178 rtadv
->nd_ra_code
= 0;
179 rtadv
->nd_ra_cksum
= 0;
181 rtadv
->nd_ra_curhoplimit
= 64;
182 rtadv
->nd_ra_flags_reserved
= 0;
183 if (zif
->rtadv
.AdvManagedFlag
)
184 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_MANAGED
;
185 if (zif
->rtadv
.AdvOtherConfigFlag
)
186 rtadv
->nd_ra_flags_reserved
|= ND_RA_FLAG_OTHER
;
187 rtadv
->nd_ra_router_lifetime
= htons (zif
->rtadv
.AdvDefaultLifetime
);
188 rtadv
->nd_ra_reachable
= htonl (zif
->rtadv
.AdvReachableTime
);
189 rtadv
->nd_ra_retransmit
= htonl (0);
191 len
= sizeof (struct nd_router_advert
);
193 /* Fill in prefix. */
194 for (node
= listhead (zif
->rtadv
.AdvPrefixList
); node
; node
= nextnode (node
))
196 struct nd_opt_prefix_info
*pinfo
;
197 struct rtadv_prefix
*rprefix
;
199 rprefix
= getdata (node
);
201 pinfo
= (struct nd_opt_prefix_info
*) (buf
+ len
);
203 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
204 pinfo
->nd_opt_pi_len
= 4;
205 pinfo
->nd_opt_pi_prefix_len
= rprefix
->prefix
.prefixlen
;
207 pinfo
->nd_opt_pi_flags_reserved
= 0;
208 if (rprefix
->AdvOnLinkFlag
)
209 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_ONLINK
;
210 if (rprefix
->AdvAutonomousFlag
)
211 pinfo
->nd_opt_pi_flags_reserved
|= ND_OPT_PI_FLAG_AUTO
;
213 pinfo
->nd_opt_pi_valid_time
= htonl (rprefix
->AdvValidLifetime
);
214 pinfo
->nd_opt_pi_preferred_time
= htonl (rprefix
->AdvPreferredLifetime
);
215 pinfo
->nd_opt_pi_reserved2
= 0;
217 memcpy (&pinfo
->nd_opt_pi_prefix
, &rprefix
->prefix
.u
.prefix6
,
218 sizeof (struct in6_addr
));
222 u_char buf
[INET6_ADDRSTRLEN
];
224 zlog_info ("DEBUG %s", inet_ntop (AF_INET6
, &pinfo
->nd_opt_pi_prefix
, buf
, INET6_ADDRSTRLEN
));
229 len
+= sizeof (struct nd_opt_prefix_info
);
232 /* Hardware address. */
233 #ifdef HAVE_SOCKADDR_DL
235 if (sdl
!= NULL
&& sdl
->sdl_alen
!= 0)
237 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
238 buf
[len
++] = (sdl
->sdl_alen
+ 2) >> 3;
240 memcpy (buf
+ len
, LLADDR (sdl
), sdl
->sdl_alen
);
241 len
+= sdl
->sdl_alen
;
244 if (ifp
->hw_addr_len
!= 0)
246 buf
[len
++] = ND_OPT_SOURCE_LINKADDR
;
247 buf
[len
++] = (ifp
->hw_addr_len
+ 2) >> 3;
249 memcpy (buf
+ len
, ifp
->hw_addr
, ifp
->hw_addr_len
);
250 len
+= ifp
->hw_addr_len
;
252 #endif /* HAVE_SOCKADDR_DL */
254 msg
.msg_name
= (void *) &addr
;
255 msg
.msg_namelen
= sizeof (struct sockaddr_in6
);
258 msg
.msg_control
= (void *) adata
;
259 msg
.msg_controllen
= sizeof adata
;
263 cmsgptr
= (struct cmsghdr
*)adata
;
264 cmsgptr
->cmsg_len
= sizeof adata
;
265 cmsgptr
->cmsg_level
= IPPROTO_IPV6
;
266 cmsgptr
->cmsg_type
= IPV6_PKTINFO
;
267 pkt
= (struct in6_pktinfo
*) CMSG_DATA (cmsgptr
);
268 memset (&pkt
->ipi6_addr
, 0, sizeof (struct in6_addr
));
269 pkt
->ipi6_ifindex
= ifp
->ifindex
;
271 ret
= sendmsg (sock
, &msg
, 0);
277 rtadv_timer (struct thread
*thread
)
280 struct interface
*ifp
;
281 struct zebra_if
*zif
;
283 rtadv
->ra_timer
= NULL
;
284 rtadv_event (RTADV_TIMER
, 1);
286 for (node
= listhead (iflist
); node
; nextnode (node
))
288 ifp
= getdata (node
);
290 if (if_is_loopback (ifp
))
295 if (zif
->rtadv
.AdvSendAdvertisements
)
296 if (--zif
->rtadv
.AdvIntervalTimer
<= 0)
298 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
299 rtadv_send_packet (rtadv
->sock
, ifp
);
306 rtadv_process_solicit (struct interface
*ifp
)
308 zlog_info ("Router solicitation received on %s", ifp
->name
);
310 rtadv_send_packet (rtadv
->sock
, ifp
);
314 rtadv_process_advert ()
316 zlog_info ("Router advertisement received");
320 rtadv_process_packet (u_char
*buf
, int len
, unsigned int ifindex
, int hoplimit
)
322 struct icmp6_hdr
*icmph
;
323 struct interface
*ifp
;
324 struct zebra_if
*zif
;
326 /* Interface search. */
327 ifp
= if_lookup_by_index (ifindex
);
330 zlog_warn ("Unknown interface index: %d", ifindex
);
334 if (if_is_loopback (ifp
))
337 /* Check interface configuration. */
339 if (! zif
->rtadv
.AdvSendAdvertisements
)
342 /* ICMP message length check. */
343 if (len
< sizeof (struct icmp6_hdr
))
345 zlog_warn ("Invalid ICMPV6 packet length: %d", len
);
349 icmph
= (struct icmp6_hdr
*) buf
;
351 /* ICMP message type check. */
352 if (icmph
->icmp6_type
!= ND_ROUTER_SOLICIT
&&
353 icmph
->icmp6_type
!= ND_ROUTER_ADVERT
)
355 zlog_warn ("Unwanted ICMPV6 message type: %d", icmph
->icmp6_type
);
359 /* Hoplimit check. */
360 if (hoplimit
>= 0 && hoplimit
!= 255)
362 zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
367 /* Check ICMP message type. */
368 if (icmph
->icmp6_type
== ND_ROUTER_SOLICIT
)
369 rtadv_process_solicit (ifp
);
370 else if (icmph
->icmp6_type
== ND_ROUTER_ADVERT
)
371 rtadv_process_advert ();
377 rtadv_read (struct thread
*thread
)
381 u_char buf
[RTADV_MSG_SIZE
];
382 struct sockaddr_in6 from
;
383 unsigned int ifindex
;
386 sock
= THREAD_FD (thread
);
387 rtadv
->ra_read
= NULL
;
389 /* Register myself. */
390 rtadv_event (RTADV_READ
, sock
);
392 len
= rtadv_recv_packet (sock
, buf
, BUFSIZ
, &from
, &ifindex
, &hoplimit
);
396 zlog_warn ("router solicitation recv failed: %s.", strerror (errno
));
400 rtadv_process_packet (buf
, len
, ifindex
, hoplimit
);
406 rtadv_make_socket (void)
410 struct icmp6_filter filter
;
412 sock
= socket (AF_INET6
, SOCK_RAW
, IPPROTO_ICMPV6
);
414 /* When we can't make ICMPV6 socket simply back. Router
415 advertisement feature will not be supported. */
419 ret
= setsockopt_ipv6_pktinfo (sock
, 1);
422 ret
= setsockopt_ipv6_checksum (sock
, 2);
425 ret
= setsockopt_ipv6_multicast_loop (sock
, 0);
428 ret
= setsockopt_ipv6_unicast_hops (sock
, 255);
431 ret
= setsockopt_ipv6_multicast_hops (sock
, 255);
434 ret
= setsockopt_ipv6_hoplimit (sock
, 1);
438 ICMP6_FILTER_SETBLOCKALL(&filter
);
439 ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT
, &filter
);
440 ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT
, &filter
);
442 ret
= setsockopt (sock
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
,
443 sizeof (struct icmp6_filter
));
446 zlog_info ("ICMP6_FILTER set fail: %s", strerror (errno
));
453 struct rtadv_prefix
*
456 struct rtadv_prefix
*new;
458 new = XMALLOC (MTYPE_RTADV_PREFIX
, sizeof (struct rtadv_prefix
));
459 memset (new, 0, sizeof (struct rtadv_prefix
));
465 rtadv_prefix_free (struct rtadv_prefix
*rtadv_prefix
)
467 XFREE (MTYPE_RTADV_PREFIX
, rtadv_prefix
);
470 struct rtadv_prefix
*
471 rtadv_prefix_lookup (list rplist
, struct prefix
*p
)
474 struct rtadv_prefix
*rprefix
;
476 for (node
= listhead (rplist
); node
; node
= nextnode (node
))
478 rprefix
= getdata (node
);
479 if (prefix_same (&rprefix
->prefix
, p
))
485 struct rtadv_prefix
*
486 rtadv_prefix_get (list rplist
, struct prefix
*p
)
488 struct rtadv_prefix
*rprefix
;
490 rprefix
= rtadv_prefix_lookup (rplist
, p
);
494 rprefix
= rtadv_prefix_new ();
495 memcpy (&rprefix
->prefix
, p
, sizeof (struct prefix
));
496 listnode_add (rplist
, rprefix
);
502 rtadv_prefix_set (struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
504 struct rtadv_prefix
*rprefix
;
506 rprefix
= rtadv_prefix_get (zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
508 /* Set parameters. */
509 rprefix
->AdvValidLifetime
= rp
->AdvValidLifetime
;
510 rprefix
->AdvPreferredLifetime
= rp
->AdvPreferredLifetime
;
511 rprefix
->AdvOnLinkFlag
= rp
->AdvOnLinkFlag
;
512 rprefix
->AdvAutonomousFlag
= rp
->AdvAutonomousFlag
;
516 rtadv_prefix_reset (struct zebra_if
*zif
, struct rtadv_prefix
*rp
)
518 struct rtadv_prefix
*rprefix
;
520 rprefix
= rtadv_prefix_lookup (zif
->rtadv
.AdvPrefixList
, &rp
->prefix
);
523 listnode_delete (zif
->rtadv
.AdvPrefixList
, (void *) rprefix
);
524 rtadv_prefix_free (rprefix
);
531 DEFUN (ipv6_nd_suppress_ra
,
532 ipv6_nd_suppress_ra_cmd
,
533 "ipv6 nd suppress-ra",
535 "Neighbor discovery\n"
536 "Suppress Router Advertisement\n")
538 struct interface
*ifp
;
539 struct zebra_if
*zif
;
544 if (if_is_loopback (ifp
))
546 vty_out (vty
, "Invalid interface%s", VTY_NEWLINE
);
550 if (zif
->rtadv
.AdvSendAdvertisements
)
552 zif
->rtadv
.AdvSendAdvertisements
= 0;
553 zif
->rtadv
.AdvIntervalTimer
= 0;
554 rtadv
->adv_if_count
--;
556 if_leave_all_router (rtadv
->sock
, ifp
);
558 if (rtadv
->adv_if_count
== 0)
559 rtadv_event (RTADV_STOP
, 0);
565 ALIAS (ipv6_nd_suppress_ra
,
566 no_ipv6_nd_send_ra_cmd
,
567 "no ipv6 nd send-ra",
570 "Neighbor discovery\n"
571 "Send Router Advertisement\n")
573 DEFUN (no_ipv6_nd_suppress_ra
,
574 no_ipv6_nd_suppress_ra_cmd
,
575 "no ipv6 nd suppress-ra",
578 "Neighbor discovery\n"
579 "Suppress Router Advertisement\n")
581 struct interface
*ifp
;
582 struct zebra_if
*zif
;
587 if (if_is_loopback (ifp
))
589 vty_out (vty
, "Invalid interface%s", VTY_NEWLINE
);
593 if (! zif
->rtadv
.AdvSendAdvertisements
)
595 zif
->rtadv
.AdvSendAdvertisements
= 1;
596 zif
->rtadv
.AdvIntervalTimer
= 0;
597 rtadv
->adv_if_count
++;
599 if_join_all_router (rtadv
->sock
, ifp
);
601 if (rtadv
->adv_if_count
== 1)
602 rtadv_event (RTADV_START
, rtadv
->sock
);
608 ALIAS (no_ipv6_nd_suppress_ra
,
612 "Neighbor discovery\n"
613 "Send Router Advertisement\n")
615 DEFUN (ipv6_nd_ra_interval
,
616 ipv6_nd_ra_interval_cmd
,
617 "ipv6 nd ra-interval SECONDS",
619 "Neighbor discovery\n"
620 "Router Advertisement interval\n"
621 "Router Advertisement interval in seconds\n")
624 struct interface
*ifp
;
625 struct zebra_if
*zif
;
627 ifp
= (struct interface
*) vty
->index
;
630 interval
= atoi (argv
[0]);
634 vty_out (vty
, "Invalid Router Advertisement Interval%s", VTY_NEWLINE
);
638 zif
->rtadv
.MaxRtrAdvInterval
= interval
;
639 zif
->rtadv
.MinRtrAdvInterval
= 0.33 * interval
;
640 zif
->rtadv
.AdvIntervalTimer
= 0;
645 DEFUN (no_ipv6_nd_ra_interval
,
646 no_ipv6_nd_ra_interval_cmd
,
647 "no ipv6 nd ra-interval",
650 "Neighbor discovery\n"
651 "Router Advertisement interval\n")
653 struct interface
*ifp
;
654 struct zebra_if
*zif
;
656 ifp
= (struct interface
*) vty
->index
;
659 zif
->rtadv
.MaxRtrAdvInterval
= RTADV_MAX_RTR_ADV_INTERVAL
;
660 zif
->rtadv
.MinRtrAdvInterval
= RTADV_MIN_RTR_ADV_INTERVAL
;
661 zif
->rtadv
.AdvIntervalTimer
= zif
->rtadv
.MaxRtrAdvInterval
;
666 DEFUN (ipv6_nd_ra_lifetime
,
667 ipv6_nd_ra_lifetime_cmd
,
668 "ipv6 nd ra-lifetime SECONDS",
670 "Neighbor discovery\n"
672 "Router lifetime in seconds\n")
675 struct interface
*ifp
;
676 struct zebra_if
*zif
;
678 ifp
= (struct interface
*) vty
->index
;
681 lifetime
= atoi (argv
[0]);
683 if (lifetime
< 0 || lifetime
> 0xffff)
685 vty_out (vty
, "Invalid Router Lifetime%s", VTY_NEWLINE
);
689 zif
->rtadv
.AdvDefaultLifetime
= lifetime
;
694 DEFUN (no_ipv6_nd_ra_lifetime
,
695 no_ipv6_nd_ra_lifetime_cmd
,
696 "no ipv6 nd ra-lifetime",
699 "Neighbor discovery\n"
702 struct interface
*ifp
;
703 struct zebra_if
*zif
;
705 ifp
= (struct interface
*) vty
->index
;
708 zif
->rtadv
.AdvDefaultLifetime
= RTADV_ADV_DEFAULT_LIFETIME
;
713 DEFUN (ipv6_nd_reachable_time
,
714 ipv6_nd_reachable_time_cmd
,
715 "ipv6 nd reachable-time MILLISECONDS",
717 "Neighbor discovery\n"
719 "Reachable time in milliseconds\n")
722 struct interface
*ifp
;
723 struct zebra_if
*zif
;
725 ifp
= (struct interface
*) vty
->index
;
728 rtime
= (u_int32_t
) atol (argv
[0]);
730 if (rtime
> RTADV_MAX_REACHABLE_TIME
)
732 vty_out (vty
, "Invalid Reachable time%s", VTY_NEWLINE
);
736 zif
->rtadv
.AdvReachableTime
= rtime
;
741 DEFUN (no_ipv6_nd_reachable_time
,
742 no_ipv6_nd_reachable_time_cmd
,
743 "no ipv6 nd reachable-time",
746 "Neighbor discovery\n"
749 struct interface
*ifp
;
750 struct zebra_if
*zif
;
752 ifp
= (struct interface
*) vty
->index
;
755 zif
->rtadv
.AdvReachableTime
= 0;
760 DEFUN (ipv6_nd_managed_config_flag
,
761 ipv6_nd_managed_config_flag_cmd
,
762 "ipv6 nd managed-config-flag",
764 "Neighbor discovery\n"
765 "Managed address configuration flag\n")
767 struct interface
*ifp
;
768 struct zebra_if
*zif
;
770 ifp
= (struct interface
*) vty
->index
;
773 zif
->rtadv
.AdvManagedFlag
= 1;
778 DEFUN (no_ipv6_nd_managed_config_flag
,
779 no_ipv6_nd_managed_config_flag_cmd
,
780 "no ipv6 nd managed-config-flag",
783 "Neighbor discovery\n"
784 "Managed address configuration flag\n")
786 struct interface
*ifp
;
787 struct zebra_if
*zif
;
789 ifp
= (struct interface
*) vty
->index
;
792 zif
->rtadv
.AdvManagedFlag
= 0;
797 DEFUN (ipv6_nd_other_config_flag
,
798 ipv6_nd_other_config_flag_cmd
,
799 "ipv6 nd other-config-flag",
801 "Neighbor discovery\n"
802 "Other statefull configuration flag\n")
804 struct interface
*ifp
;
805 struct zebra_if
*zif
;
807 ifp
= (struct interface
*) vty
->index
;
810 zif
->rtadv
.AdvOtherConfigFlag
= 1;
815 DEFUN (no_ipv6_nd_other_config_flag
,
816 no_ipv6_nd_other_config_flag_cmd
,
817 "no ipv6 nd other-config-flag",
820 "Neighbor discovery\n"
821 "Other statefull configuration flag\n")
823 struct interface
*ifp
;
824 struct zebra_if
*zif
;
826 ifp
= (struct interface
*) vty
->index
;
829 zif
->rtadv
.AdvOtherConfigFlag
= 0;
834 DEFUN (ipv6_nd_prefix_advertisement
,
835 ipv6_nd_prefix_advertisement_cmd
,
836 "ipv6 nd prefix-advertisement IPV6PREFIX VALID PREFERRED [onlink] [autoconfig]",
838 "Neighbor discovery\n"
839 "Prefix information\n"
841 "Valid lifetime in seconds\n"
842 "Preferred lifetime in seconds\n"
844 "Autonomous address-configuration flag\n")
848 struct interface
*ifp
;
849 struct zebra_if
*zebra_if
;
850 struct rtadv_prefix rp
;
852 ifp
= (struct interface
*) vty
->index
;
853 zebra_if
= ifp
->info
;
855 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*) &rp
.prefix
);
858 vty_out (vty
, "Malformed IPv6 prefix%s", VTY_NEWLINE
);
864 rp
.AdvValidLifetime
= RTADV_VALID_LIFETIME
;
865 rp
.AdvPreferredLifetime
= RTADV_PREFERRED_LIFETIME
;
866 rp
.AdvOnLinkFlag
= 1;
867 rp
.AdvAutonomousFlag
= 1;
871 rp
.AdvValidLifetime
= (u_int32_t
) atol (argv
[1]);
872 rp
.AdvPreferredLifetime
= (u_int32_t
) atol (argv
[2]);
873 if (rp
.AdvPreferredLifetime
> rp
.AdvValidLifetime
)
875 vty_out (vty
, "Invalid preferred lifetime%s", VTY_NEWLINE
);
879 rp
.AdvOnLinkFlag
= 0;
880 rp
.AdvAutonomousFlag
= 0;
881 for (i
= 3; i
< argc
; i
++)
883 if (! strcmp (argv
[i
], "onlink"))
884 rp
.AdvOnLinkFlag
= 1;
885 else if (! strcmp (argv
[i
], "autoconfig"))
886 rp
.AdvAutonomousFlag
= 1;
890 rtadv_prefix_set (zebra_if
, &rp
);
895 ALIAS (ipv6_nd_prefix_advertisement
,
896 ipv6_nd_prefix_advertisement_no_val_cmd
,
897 "ipv6 nd prefix-advertisement IPV6PREFIX",
899 "Neighbor discovery\n"
900 "Prefix information\n"
903 DEFUN (no_ipv6_nd_prefix_advertisement
,
904 no_ipv6_nd_prefix_advertisement_cmd
,
905 "no ipv6 nd prefix-advertisement IPV6PREFIX",
908 "Neighbor discovery\n"
909 "Prefix information\n"
913 struct interface
*ifp
;
914 struct zebra_if
*zebra_if
;
915 struct rtadv_prefix rp
;
917 ifp
= (struct interface
*) vty
->index
;
918 zebra_if
= ifp
->info
;
920 ret
= str2prefix_ipv6 (argv
[0], (struct prefix_ipv6
*) &rp
.prefix
);
923 vty_out (vty
, "Malformed IPv6 prefix%s", VTY_NEWLINE
);
927 ret
= rtadv_prefix_reset (zebra_if
, &rp
);
930 vty_out (vty
, "Non-exist IPv6 prefix%s", VTY_NEWLINE
);
937 /* Write configuration about router advertisement. */
939 rtadv_config_write (struct vty
*vty
, struct interface
*ifp
)
941 struct zebra_if
*zif
;
943 struct rtadv_prefix
*rprefix
;
944 u_char buf
[INET6_ADDRSTRLEN
];
951 if (! if_is_loopback (ifp
))
953 if (zif
->rtadv
.AdvSendAdvertisements
)
954 vty_out (vty
, " no ipv6 nd suppress-ra%s", VTY_NEWLINE
);
956 vty_out (vty
, " ipv6 nd suppress-ra%s", VTY_NEWLINE
);
959 if (zif
->rtadv
.MaxRtrAdvInterval
!= RTADV_MAX_RTR_ADV_INTERVAL
)
960 vty_out (vty
, " ipv6 nd ra-interval %d%s", zif
->rtadv
.MaxRtrAdvInterval
,
963 if (zif
->rtadv
.AdvDefaultLifetime
!= RTADV_ADV_DEFAULT_LIFETIME
)
964 vty_out (vty
, " ipv6 nd ra-lifetime %d%s", zif
->rtadv
.AdvDefaultLifetime
,
967 if (zif
->rtadv
.AdvReachableTime
)
968 vty_out (vty
, " ipv6 nd reachable-time %d%s", zif
->rtadv
.AdvReachableTime
,
971 if (zif
->rtadv
.AdvManagedFlag
)
972 vty_out (vty
, " ipv6 nd managed-config-flag%s", VTY_NEWLINE
);
974 if (zif
->rtadv
.AdvOtherConfigFlag
)
975 vty_out (vty
, " ipv6 nd other-config-flag%s", VTY_NEWLINE
);
977 for (node
= listhead(zif
->rtadv
.AdvPrefixList
); node
; node
= nextnode (node
))
979 rprefix
= getdata (node
);
980 vty_out (vty
, " ipv6 nd prefix-advertisement %s/%d %d %d",
981 inet_ntop (AF_INET6
, &rprefix
->prefix
.u
.prefix6
,
982 buf
, INET6_ADDRSTRLEN
),
983 rprefix
->prefix
.prefixlen
,
984 rprefix
->AdvValidLifetime
,
985 rprefix
->AdvPreferredLifetime
);
986 if (rprefix
->AdvOnLinkFlag
)
987 vty_out (vty
, " onlink");
988 if (rprefix
->AdvAutonomousFlag
)
989 vty_out (vty
, " autoconfig");
990 vty_out (vty
, "%s", VTY_NEWLINE
);
994 extern struct thread_master
*master
;
997 rtadv_event (enum rtadv_event event
, int val
)
1002 if (! rtadv
->ra_read
)
1003 rtadv
->ra_read
= thread_add_read (master
, rtadv_read
, NULL
, val
);
1004 if (! rtadv
->ra_timer
)
1005 rtadv
->ra_timer
= thread_add_event (master
, rtadv_timer
, NULL
, 0);
1008 if (rtadv
->ra_timer
)
1010 thread_cancel (rtadv
->ra_timer
);
1011 rtadv
->ra_timer
= NULL
;
1015 thread_cancel (rtadv
->ra_read
);
1016 rtadv
->ra_read
= NULL
;
1020 if (! rtadv
->ra_timer
)
1021 rtadv
->ra_timer
= thread_add_timer (master
, rtadv_timer
, NULL
, val
);
1024 if (! rtadv
->ra_read
)
1025 rtadv
->ra_read
= thread_add_read (master
, rtadv_read
, NULL
, val
);
1038 sock
= rtadv_make_socket ();
1042 rtadv
= rtadv_new ();
1045 install_element (INTERFACE_NODE
, &ipv6_nd_suppress_ra_cmd
);
1046 install_element (INTERFACE_NODE
, &no_ipv6_nd_suppress_ra_cmd
);
1047 install_element (INTERFACE_NODE
, &ipv6_nd_send_ra_cmd
);
1048 install_element (INTERFACE_NODE
, &no_ipv6_nd_send_ra_cmd
);
1049 install_element (INTERFACE_NODE
, &ipv6_nd_ra_interval_cmd
);
1050 install_element (INTERFACE_NODE
, &no_ipv6_nd_ra_interval_cmd
);
1051 install_element (INTERFACE_NODE
, &ipv6_nd_ra_lifetime_cmd
);
1052 install_element (INTERFACE_NODE
, &no_ipv6_nd_ra_lifetime_cmd
);
1053 install_element (INTERFACE_NODE
, &ipv6_nd_reachable_time_cmd
);
1054 install_element (INTERFACE_NODE
, &no_ipv6_nd_reachable_time_cmd
);
1055 install_element (INTERFACE_NODE
, &ipv6_nd_managed_config_flag_cmd
);
1056 install_element (INTERFACE_NODE
, &no_ipv6_nd_managed_config_flag_cmd
);
1057 install_element (INTERFACE_NODE
, &ipv6_nd_other_config_flag_cmd
);
1058 install_element (INTERFACE_NODE
, &no_ipv6_nd_other_config_flag_cmd
);
1059 install_element (INTERFACE_NODE
, &ipv6_nd_prefix_advertisement_cmd
);
1060 install_element (INTERFACE_NODE
, &ipv6_nd_prefix_advertisement_no_val_cmd
);
1061 install_element (INTERFACE_NODE
, &no_ipv6_nd_prefix_advertisement_cmd
);
1065 if_join_all_router (int sock
, struct interface
*ifp
)
1069 struct ipv6_mreq mreq
;
1071 memset (&mreq
, 0, sizeof (struct ipv6_mreq
));
1072 inet_pton (AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1073 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1075 ret
= setsockopt (sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
,
1076 (char *) &mreq
, sizeof mreq
);
1078 zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", strerror (errno
));
1080 zlog_info ("rtadv: %s join to all-routers multicast group", ifp
->name
);
1086 if_leave_all_router (int sock
, struct interface
*ifp
)
1090 struct ipv6_mreq mreq
;
1092 memset (&mreq
, 0, sizeof (struct ipv6_mreq
));
1093 inet_pton (AF_INET6
, ALLROUTER
, &mreq
.ipv6mr_multiaddr
);
1094 mreq
.ipv6mr_interface
= ifp
->ifindex
;
1096 ret
= setsockopt (sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
,
1097 (char *) &mreq
, sizeof mreq
);
1099 zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", strerror (errno
));
1101 zlog_info ("rtadv: %s leave from all-routers multicast group", ifp
->name
);
1112 #endif /* RTADV && HAVE_IPV6 */