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