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