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