Coverage Report

Created: 2026-05-04 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/zebra/rtadv.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/* Router advertisement
3
 * Copyright (C) 2016 Cumulus Networks
4
 * Copyright (C) 2005 6WIND <jean-mickael.guerin@6wind.com>
5
 * Copyright (C) 1999 Kunihiro Ishiguro
6
 */
7
8
#include <zebra.h>
9
10
#include "memory.h"
11
#include "sockopt.h"
12
#include "frrevent.h"
13
#include "if.h"
14
#include "stream.h"
15
#include "log.h"
16
#include "prefix.h"
17
#include "linklist.h"
18
#include "command.h"
19
#include "privs.h"
20
#include "vrf.h"
21
#include "ns.h"
22
#include "lib_errors.h"
23
24
#include "zebra/interface.h"
25
#include "zebra/rtadv.h"
26
#include "zebra/debug.h"
27
#include "zebra/rib.h"
28
#include "zebra/zapi_msg.h"
29
#include "zebra/zebra_vrf.h"
30
#include "zebra/zebra_errors.h"
31
#include "zebra/zebra_router.h"
32
33
extern struct zebra_privs_t zserv_privs;
34
35
static uint32_t interfaces_configured_for_ra_from_bgp;
36
37
#if defined(HAVE_RTADV)
38
39
#include "zebra/rtadv_clippy.c"
40
41
2
DEFINE_MTYPE_STATIC(ZEBRA, RTADV_PREFIX, "Router Advertisement Prefix");
42
2
DEFINE_MTYPE_STATIC(ZEBRA, ADV_IF, "Advertised Interface");
43
2
44
2
#ifdef OPEN_BSD
45
2
#include <netinet/icmp6.h>
46
2
#endif
47
2
48
2
/* If RFC2133 definition is used. */
49
2
#ifndef IPV6_JOIN_GROUP
50
2
#define IPV6_JOIN_GROUP  IPV6_ADD_MEMBERSHIP
51
2
#endif
52
2
#ifndef IPV6_LEAVE_GROUP
53
2
#define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
54
2
#endif
55
2
56
2
#define ALLNODE   "ff02::1"
57
2
#define ALLROUTER "ff02::2"
58
59
/* adv list node */
60
struct adv_if {
61
  char name[INTERFACE_NAMSIZ];
62
  struct adv_if_list_item list_item;
63
};
64
65
static int adv_if_cmp(const struct adv_if *a, const struct adv_if *b)
66
0
{
67
0
  return if_cmp_name_func(a->name, b->name);
68
0
}
69
70
0
DECLARE_SORTLIST_UNIQ(adv_if_list, struct adv_if, list_item, adv_if_cmp);
71
0
72
0
static int rtadv_prefix_cmp(const struct rtadv_prefix *a,
73
0
          const struct rtadv_prefix *b)
74
0
{
75
0
  return prefix_cmp(&a->prefix, &b->prefix);
76
0
}
77
78
DECLARE_RBTREE_UNIQ(rtadv_prefixes, struct rtadv_prefix, item,
79
        rtadv_prefix_cmp);
80
81
2
DEFINE_MTYPE_STATIC(ZEBRA, RTADV_RDNSS, "Router Advertisement RDNSS");
82
2
DEFINE_MTYPE_STATIC(ZEBRA, RTADV_DNSSL, "Router Advertisement DNSSL");
83
2
84
2
/* Order is intentional.  Matches RFC4191.  This array is also used for
85
2
   command matching, so only modify with care. */
86
2
static const char *const rtadv_pref_strs[] = {
87
2
  "medium", "high", "INVALID", "low", 0
88
2
};
89
2
90
2
enum rtadv_event {
91
2
  RTADV_START,
92
2
  RTADV_STOP,
93
2
  RTADV_TIMER,
94
2
  RTADV_TIMER_MSEC,
95
2
  RTADV_READ
96
2
};
97
2
98
2
static void rtadv_event(struct zebra_vrf *, enum rtadv_event, int);
99
2
100
2
static int if_join_all_router(int, struct interface *);
101
2
static int if_leave_all_router(int, struct interface *);
102
2
103
2
static struct zebra_vrf *rtadv_interface_get_zvrf(const struct interface *ifp)
104
2
{
105
  /* We use the default vrf for rtadv handling except in netns */
106
0
  if (!vrf_is_backend_netns())
107
0
    return vrf_info_lookup(VRF_DEFAULT);
108
109
0
  return ifp->vrf->info;
110
0
}
111
112
static int rtadv_increment_received(struct zebra_vrf *zvrf, ifindex_t *ifindex)
113
0
{
114
0
  int ret = -1;
115
0
  struct interface *iface;
116
0
  struct zebra_if *zif;
117
0
118
0
  iface = if_lookup_by_index(*ifindex, zvrf->vrf->vrf_id);
119
0
  if (iface && iface->info) {
120
0
    zif = iface->info;
121
0
    zif->ra_rcvd++;
122
0
    ret = 0;
123
0
  }
124
0
  return ret;
125
0
}
126
127
static int rtadv_recv_packet(struct zebra_vrf *zvrf, int sock, uint8_t *buf,
128
           int buflen, struct sockaddr_in6 *from,
129
           ifindex_t *ifindex, int *hoplimit)
130
0
{
131
0
  int ret;
132
0
  struct msghdr msg;
133
0
  struct iovec iov;
134
0
  struct cmsghdr *cmsgptr;
135
0
  struct in6_addr dst;
136
0
137
0
  char adata[1024];
138
0
139
0
  /* Fill in message and iovec. */
140
0
  memset(&msg, 0, sizeof(msg));
141
0
  msg.msg_name = (void *)from;
142
0
  msg.msg_namelen = sizeof(struct sockaddr_in6);
143
0
  msg.msg_iov = &iov;
144
0
  msg.msg_iovlen = 1;
145
0
  msg.msg_control = (void *)adata;
146
0
  msg.msg_controllen = sizeof(adata);
147
0
  iov.iov_base = buf;
148
0
  iov.iov_len = buflen;
149
0
150
0
  /* If recvmsg fail return minus value. */
151
0
  ret = recvmsg(sock, &msg, 0);
152
0
  if (ret < 0)
153
0
    return ret;
154
0
155
0
  for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
156
0
       cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
157
0
    /* I want interface index which this packet comes from. */
158
0
    if (cmsgptr->cmsg_level == IPPROTO_IPV6
159
0
        && cmsgptr->cmsg_type == IPV6_PKTINFO) {
160
0
      struct in6_pktinfo *ptr;
161
0
162
0
      ptr = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
163
0
      *ifindex = ptr->ipi6_ifindex;
164
0
      memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr));
165
0
    }
166
0
167
0
    /* Incoming packet's hop limit. */
168
0
    if (cmsgptr->cmsg_level == IPPROTO_IPV6
169
0
        && cmsgptr->cmsg_type == IPV6_HOPLIMIT) {
170
0
      int *hoptr = (int *)CMSG_DATA(cmsgptr);
171
0
      *hoplimit = *hoptr;
172
0
    }
173
0
  }
174
0
175
0
  rtadv_increment_received(zvrf, ifindex);
176
0
  return ret;
177
0
}
178
179
#define RTADV_MSG_SIZE 4096
180
181
/* Send router advertisement packet. */
182
static void rtadv_send_packet(int sock, struct interface *ifp,
183
            enum ipv6_nd_suppress_ra_status stop)
184
0
{
185
0
  struct msghdr msg;
186
0
  struct iovec iov;
187
0
  struct cmsghdr *cmsgptr;
188
0
  struct in6_pktinfo *pkt;
189
0
  struct sockaddr_in6 addr;
190
0
  static void *adata = NULL;
191
0
  unsigned char buf[RTADV_MSG_SIZE];
192
0
  struct nd_router_advert *rtadv;
193
0
  int ret;
194
0
  int len = 0;
195
0
  struct zebra_if *zif;
196
0
  struct rtadv_prefix *rprefix;
197
0
  uint8_t all_nodes_addr[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0,
198
0
            0,    0,    0, 0, 0, 0, 0, 1};
199
0
  struct listnode *node;
200
0
  uint16_t pkt_RouterLifetime;
201
202
  /*
203
   * Allocate control message bufffer.  This is dynamic because
204
   * CMSG_SPACE is not guaranteed not to call a function.  Note that
205
   * the size will be different on different architectures due to
206
   * differing alignment rules.
207
   */
208
0
  if (adata == NULL) {
209
    /* XXX Free on shutdown. */
210
0
    adata = calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo)));
211
212
0
    if (adata == NULL) {
213
0
      zlog_debug("%s: can't malloc control data", __func__);
214
0
      exit(-1);
215
0
    }
216
0
  }
217
218
  /* Logging of packet. */
219
0
  if (IS_ZEBRA_DEBUG_PACKET)
220
0
    zlog_debug("%s(%s:%u): Tx RA, socket %u", ifp->name,
221
0
         ifp->vrf->name, ifp->ifindex, sock);
222
223
  /* Fill in sockaddr_in6. */
224
0
  memset(&addr, 0, sizeof(struct sockaddr_in6));
225
0
  addr.sin6_family = AF_INET6;
226
#ifdef SIN6_LEN
227
  addr.sin6_len = sizeof(struct sockaddr_in6);
228
#endif /* SIN6_LEN */
229
0
  addr.sin6_port = htons(IPPROTO_ICMPV6);
230
0
  IPV6_ADDR_COPY(&addr.sin6_addr, all_nodes_addr);
231
232
  /* Fetch interface information. */
233
0
  zif = ifp->info;
234
235
  /* Make router advertisement message. */
236
0
  rtadv = (struct nd_router_advert *)buf;
237
238
0
  rtadv->nd_ra_type = ND_ROUTER_ADVERT;
239
0
  rtadv->nd_ra_code = 0;
240
0
  rtadv->nd_ra_cksum = 0;
241
242
0
  rtadv->nd_ra_curhoplimit = zif->rtadv.AdvCurHopLimit;
243
244
  /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
245
0
  rtadv->nd_ra_flags_reserved = zif->rtadv.AdvDefaultLifetime == 0
246
0
                ? 0
247
0
                : zif->rtadv.DefaultPreference;
248
0
  rtadv->nd_ra_flags_reserved <<= 3;
249
250
0
  if (zif->rtadv.AdvManagedFlag)
251
0
    rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
252
0
  if (zif->rtadv.AdvOtherConfigFlag)
253
0
    rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
254
0
  if (zif->rtadv.AdvHomeAgentFlag)
255
0
    rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;
256
  /* Note that according to Neighbor Discovery (RFC 4861 [18]),
257
   * AdvDefaultLifetime is by default based on the value of
258
   * MaxRtrAdvInterval.  AdvDefaultLifetime is used in the Router Lifetime
259
   * field of Router Advertisements.  Given that this field is expressed
260
   * in seconds, a small MaxRtrAdvInterval value can result in a zero
261
   * value for this field.  To prevent this, routers SHOULD keep
262
   * AdvDefaultLifetime in at least one second, even if the use of
263
   * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
264
0
  pkt_RouterLifetime =
265
0
    zif->rtadv.AdvDefaultLifetime != -1
266
0
      ? zif->rtadv.AdvDefaultLifetime
267
0
      : MAX(1, 0.003 * zif->rtadv.MaxRtrAdvInterval);
268
269
  /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
270
0
  rtadv->nd_ra_router_lifetime =
271
0
    (stop == RA_SUPPRESS) ? htons(0) : htons(pkt_RouterLifetime);
272
0
  rtadv->nd_ra_reachable = htonl(zif->rtadv.AdvReachableTime);
273
0
  rtadv->nd_ra_retransmit = htonl(zif->rtadv.AdvRetransTimer);
274
275
0
  len = sizeof(struct nd_router_advert);
276
277
  /* If both the Home Agent Preference and Home Agent Lifetime are set to
278
   * their default values specified above, this option SHOULD NOT be
279
   * included in the Router Advertisement messages sent by this home
280
   * agent. -- RFC6275, 7.4 */
281
0
  if (zif->rtadv.AdvHomeAgentFlag
282
0
      && (zif->rtadv.HomeAgentPreference
283
0
    || zif->rtadv.HomeAgentLifetime != -1)) {
284
0
    struct nd_opt_homeagent_info *ndopt_hai =
285
0
      (struct nd_opt_homeagent_info *)(buf + len);
286
0
    ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
287
0
    ndopt_hai->nd_opt_hai_len = 1;
288
0
    ndopt_hai->nd_opt_hai_reserved = 0;
289
0
    ndopt_hai->nd_opt_hai_preference =
290
0
      htons(zif->rtadv.HomeAgentPreference);
291
    /* 16-bit unsigned integer.  The lifetime associated with the
292
     * home
293
     * agent in units of seconds.  The default value is the same as
294
     * the
295
     * Router Lifetime, as specified in the main body of the Router
296
     * Advertisement.  The maximum value corresponds to 18.2 hours.
297
     * A
298
     * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
299
0
    ndopt_hai->nd_opt_hai_lifetime =
300
0
      htons(zif->rtadv.HomeAgentLifetime != -1
301
0
              ? zif->rtadv.HomeAgentLifetime
302
0
              : MAX(1, pkt_RouterLifetime) /* 0 is OK
303
                      for RL,
304
                      but not
305
                      for HAL*/
306
0
            );
307
0
    len += sizeof(struct nd_opt_homeagent_info);
308
0
  }
309
310
0
  if (zif->rtadv.AdvIntervalOption) {
311
0
    struct nd_opt_adv_interval *ndopt_adv =
312
0
      (struct nd_opt_adv_interval *)(buf + len);
313
0
    ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL;
314
0
    ndopt_adv->nd_opt_ai_len = 1;
315
0
    ndopt_adv->nd_opt_ai_reserved = 0;
316
0
    ndopt_adv->nd_opt_ai_interval =
317
0
      htonl(zif->rtadv.MaxRtrAdvInterval);
318
0
    len += sizeof(struct nd_opt_adv_interval);
319
0
  }
320
321
  /* Fill in prefix. */
322
0
  frr_each (rtadv_prefixes, zif->rtadv.prefixes, rprefix) {
323
0
    struct nd_opt_prefix_info *pinfo;
324
325
0
    pinfo = (struct nd_opt_prefix_info *)(buf + len);
326
327
0
    pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
328
0
    pinfo->nd_opt_pi_len = 4;
329
0
    pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
330
331
0
    pinfo->nd_opt_pi_flags_reserved = 0;
332
0
    if (rprefix->AdvOnLinkFlag)
333
0
      pinfo->nd_opt_pi_flags_reserved |=
334
0
        ND_OPT_PI_FLAG_ONLINK;
335
0
    if (rprefix->AdvAutonomousFlag)
336
0
      pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
337
0
    if (rprefix->AdvRouterAddressFlag)
338
0
      pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
339
340
0
    pinfo->nd_opt_pi_valid_time = htonl(rprefix->AdvValidLifetime);
341
0
    pinfo->nd_opt_pi_preferred_time =
342
0
      htonl(rprefix->AdvPreferredLifetime);
343
0
    pinfo->nd_opt_pi_reserved2 = 0;
344
345
0
    IPV6_ADDR_COPY(&pinfo->nd_opt_pi_prefix,
346
0
             &rprefix->prefix.prefix);
347
348
0
    len += sizeof(struct nd_opt_prefix_info);
349
0
  }
350
351
  /* Hardware address. */
352
0
  if (ifp->hw_addr_len != 0) {
353
0
    buf[len++] = ND_OPT_SOURCE_LINKADDR;
354
355
    /* Option length should be rounded up to next octet if
356
       the link address does not end on an octet boundary. */
357
0
    buf[len++] = (ifp->hw_addr_len + 9) >> 3;
358
359
0
    memcpy(buf + len, ifp->hw_addr, ifp->hw_addr_len);
360
0
    len += ifp->hw_addr_len;
361
362
    /* Pad option to end on an octet boundary. */
363
0
    memset(buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7);
364
0
    len += -(ifp->hw_addr_len + 2) & 0x7;
365
0
  }
366
367
  /* MTU */
368
0
  if (zif->rtadv.AdvLinkMTU) {
369
0
    struct nd_opt_mtu *opt = (struct nd_opt_mtu *)(buf + len);
370
0
    opt->nd_opt_mtu_type = ND_OPT_MTU;
371
0
    opt->nd_opt_mtu_len = 1;
372
0
    opt->nd_opt_mtu_reserved = 0;
373
0
    opt->nd_opt_mtu_mtu = htonl(zif->rtadv.AdvLinkMTU);
374
0
    len += sizeof(struct nd_opt_mtu);
375
0
  }
376
377
  /*
378
   * There is no limit on the number of configurable recursive DNS
379
   * servers or search list entries. We don't want the RA message
380
   * to exceed the link's MTU (risking fragmentation) or even
381
   * blow the stack buffer allocated for it.
382
   */
383
0
  size_t max_len = MIN(ifp->mtu6 - 40, sizeof(buf));
384
385
  /* Recursive DNS servers */
386
0
  struct rtadv_rdnss *rdnss;
387
388
0
  for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvRDNSSList, node, rdnss)) {
389
0
    size_t opt_len =
390
0
      sizeof(struct nd_opt_rdnss) + sizeof(struct in6_addr);
391
392
0
    if (len + opt_len > max_len) {
393
0
      zlog_warn(
394
0
        "%s(%s:%u): Tx RA: RDNSS option would exceed MTU, omitting it",
395
0
        ifp->name, ifp->vrf->name, ifp->ifindex);
396
0
      goto no_more_opts;
397
0
    }
398
0
    struct nd_opt_rdnss *opt = (struct nd_opt_rdnss *)(buf + len);
399
400
0
    opt->nd_opt_rdnss_type = ND_OPT_RDNSS;
401
0
    opt->nd_opt_rdnss_len = opt_len / 8;
402
0
    opt->nd_opt_rdnss_reserved = 0;
403
0
    opt->nd_opt_rdnss_lifetime = htonl(
404
0
      rdnss->lifetime_set
405
0
        ? rdnss->lifetime
406
0
        : MAX(1, 0.003 * zif->rtadv.MaxRtrAdvInterval));
407
408
0
    len += sizeof(struct nd_opt_rdnss);
409
410
0
    IPV6_ADDR_COPY(buf + len, &rdnss->addr);
411
0
    len += sizeof(struct in6_addr);
412
0
  }
413
414
  /* DNS search list */
415
0
  struct rtadv_dnssl *dnssl;
416
417
0
  for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvDNSSLList, node, dnssl)) {
418
0
    size_t opt_len = sizeof(struct nd_opt_dnssl)
419
0
         + ((dnssl->encoded_len + 7) & ~7);
420
421
0
    if (len + opt_len > max_len) {
422
0
      zlog_warn(
423
0
        "%s(%u): Tx RA: DNSSL option would exceed MTU, omitting it",
424
0
        ifp->name, ifp->ifindex);
425
0
      goto no_more_opts;
426
0
    }
427
0
    struct nd_opt_dnssl *opt = (struct nd_opt_dnssl *)(buf + len);
428
429
0
    opt->nd_opt_dnssl_type = ND_OPT_DNSSL;
430
0
    opt->nd_opt_dnssl_len = opt_len / 8;
431
0
    opt->nd_opt_dnssl_reserved = 0;
432
0
    opt->nd_opt_dnssl_lifetime = htonl(
433
0
      dnssl->lifetime_set
434
0
        ? dnssl->lifetime
435
0
        : MAX(1, 0.003 * zif->rtadv.MaxRtrAdvInterval));
436
437
0
    len += sizeof(struct nd_opt_dnssl);
438
439
0
    memcpy(buf + len, dnssl->encoded_name, dnssl->encoded_len);
440
0
    len += dnssl->encoded_len;
441
442
    /* Zero-pad to 8-octet boundary */
443
0
    while (len % 8)
444
0
      buf[len++] = '\0';
445
0
  }
446
447
0
no_more_opts:
448
449
0
  msg.msg_name = (void *)&addr;
450
0
  msg.msg_namelen = sizeof(struct sockaddr_in6);
451
0
  msg.msg_iov = &iov;
452
0
  msg.msg_iovlen = 1;
453
0
  msg.msg_control = (void *)adata;
454
0
  msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
455
0
  msg.msg_flags = 0;
456
0
  iov.iov_base = buf;
457
0
  iov.iov_len = len;
458
459
0
  cmsgptr = CMSG_FIRSTHDR(&msg);
460
0
  cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
461
0
  cmsgptr->cmsg_level = IPPROTO_IPV6;
462
0
  cmsgptr->cmsg_type = IPV6_PKTINFO;
463
464
0
  pkt = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
465
0
  memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr));
466
0
  pkt->ipi6_ifindex = ifp->ifindex;
467
468
0
  ret = sendmsg(sock, &msg, 0);
469
0
  if (ret < 0) {
470
0
    flog_err_sys(EC_LIB_SOCKET,
471
0
           "%s(%u): Tx RA failed, socket %u error %d (%s)",
472
0
           ifp->name, ifp->ifindex, sock, errno,
473
0
           safe_strerror(errno));
474
0
  } else
475
0
    zif->ra_sent++;
476
0
}
477
478
static void rtadv_timer(struct event *thread)
479
0
{
480
0
  struct zebra_vrf *zvrf = EVENT_ARG(thread);
481
0
  struct vrf *vrf;
482
0
  struct interface *ifp;
483
0
  struct zebra_if *zif;
484
0
  int period;
485
0
486
0
  zvrf->rtadv.ra_timer = NULL;
487
0
  if (adv_if_list_count(&zvrf->rtadv.adv_msec_if) == 0) {
488
0
    period = 1000; /* 1 s */
489
0
    rtadv_event(zvrf, RTADV_TIMER, 1 /* 1 s */);
490
0
  } else {
491
0
    period = 10; /* 10 ms */
492
0
    rtadv_event(zvrf, RTADV_TIMER_MSEC, 10 /* 10 ms */);
493
0
  }
494
0
495
0
  RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
496
0
    FOR_ALL_INTERFACES (vrf, ifp) {
497
0
      if (if_is_loopback(ifp) || !if_is_operative(ifp) ||
498
0
          IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) ||
499
0
          !connected_get_linklocal(ifp) ||
500
0
          (vrf_is_backend_netns() &&
501
0
           ifp->vrf->vrf_id != zvrf->vrf->vrf_id))
502
0
        continue;
503
0
504
0
      zif = ifp->info;
505
0
506
0
      if (zif->rtadv.AdvSendAdvertisements) {
507
0
        if (zif->rtadv.inFastRexmit
508
0
            && zif->rtadv.UseFastRexmit) {
509
0
          /* We assume we fast rexmit every sec so
510
0
           * no
511
0
           * additional vars */
512
0
          if (--zif->rtadv.NumFastReXmitsRemain
513
0
              <= 0)
514
0
            zif->rtadv.inFastRexmit = 0;
515
0
516
0
          if (IS_ZEBRA_DEBUG_SEND)
517
0
            zlog_debug(
518
0
              "Fast RA Rexmit on interface %s(%s:%u)",
519
0
              ifp->name,
520
0
              ifp->vrf->name,
521
0
              ifp->ifindex);
522
0
523
0
          rtadv_send_packet(zvrf->rtadv.sock, ifp,
524
0
                RA_ENABLE);
525
0
        } else {
526
0
          zif->rtadv.AdvIntervalTimer -= period;
527
0
          if (zif->rtadv.AdvIntervalTimer <= 0) {
528
0
            /* FIXME: using
529
0
               MaxRtrAdvInterval each
530
0
               time isn't what section
531
0
               6.2.4 of RFC4861 tells to do.
532
0
               */
533
0
            zif->rtadv.AdvIntervalTimer =
534
0
              zif->rtadv
535
0
                .MaxRtrAdvInterval;
536
0
            rtadv_send_packet(
537
0
              zvrf->rtadv.sock, ifp,
538
0
              RA_ENABLE);
539
0
          }
540
0
        }
541
0
      }
542
0
    }
543
0
}
544
545
static void rtadv_process_solicit(struct interface *ifp)
546
0
{
547
0
  struct zebra_vrf *zvrf;
548
0
  struct zebra_if *zif;
549
0
550
0
  zvrf = rtadv_interface_get_zvrf(ifp);
551
0
  assert(zvrf);
552
0
  zif = ifp->info;
553
0
554
0
  /*
555
0
   * If FastRetransmit is enabled, send the RA immediately.
556
0
   * If not enabled but it has been more than MIN_DELAY_BETWEEN_RAS
557
0
   * (3 seconds) since the last RA was sent, send it now and reset
558
0
   * the timer to start at the max (configured) again.
559
0
   * If not enabled and it is less than 3 seconds since the last
560
0
   * RA packet was sent, set the timer for 3 seconds so the next
561
0
   * one will be sent with a minimum of 3 seconds between RAs.
562
0
   * RFC4861 sec 6.2.6
563
0
   */
564
0
  if ((zif->rtadv.UseFastRexmit)
565
0
      || (zif->rtadv.AdvIntervalTimer <=
566
0
    (zif->rtadv.MaxRtrAdvInterval - MIN_DELAY_BETWEEN_RAS))) {
567
0
    rtadv_send_packet(zvrf->rtadv.sock, ifp, RA_ENABLE);
568
0
    zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
569
0
  } else
570
0
    zif->rtadv.AdvIntervalTimer = MIN_DELAY_BETWEEN_RAS;
571
0
}
572
573
static const char *rtadv_optionalhdr2str(uint8_t opt_type)
574
0
{
575
0
  switch (opt_type) {
576
0
  case ND_OPT_SOURCE_LINKADDR:
577
0
    return "Optional Source Link Address";
578
0
  case ND_OPT_TARGET_LINKADDR:
579
0
    return "Optional Target Link Address";
580
0
  case ND_OPT_PREFIX_INFORMATION:
581
0
    return "Optional Prefix Information";
582
0
  case ND_OPT_REDIRECTED_HEADER:
583
0
    return "Optional Redirected Header";
584
0
  case ND_OPT_MTU:
585
0
    return "Optional MTU";
586
0
  case ND_OPT_RTR_ADV_INTERVAL:
587
0
    return "Optional Advertisement Interval";
588
0
  case ND_OPT_HOME_AGENT_INFO:
589
0
    return "Optional Home Agent Information";
590
0
  }
591
0
592
0
  return "Unknown Optional Type";
593
0
}
594
595
/*
596
 * This function processes optional attributes off of
597
 * end of a RA packet received.  At this point in
598
 * time we only care about this in one situation
599
 * which is when a interface does not have a LL
600
 * v6 address.  We still need to be able to install
601
 * the mac address for v4 to v6 resolution
602
 */
603
static void rtadv_process_optional(uint8_t *optional, unsigned int len,
604
           struct interface *ifp,
605
           struct sockaddr_in6 *addr)
606
0
{
607
0
  char *mac;
608
0
609
0
  while (len > 0) {
610
0
    struct nd_opt_hdr *opt_hdr = (struct nd_opt_hdr *)optional;
611
0
612
0
    switch(opt_hdr->nd_opt_type) {
613
0
    case ND_OPT_SOURCE_LINKADDR:
614
0
      mac = (char *)(optional+2);
615
0
      if_nbr_mac_to_ipv4ll_neigh_update(ifp, mac,
616
0
                &addr->sin6_addr, 1);
617
0
      break;
618
0
    default:
619
0
      if (IS_ZEBRA_DEBUG_PACKET)
620
0
        zlog_debug(
621
0
          "%s:Received Packet with optional Header type %s(%u) that is being ignored",
622
0
          __func__,
623
0
          rtadv_optionalhdr2str(
624
0
            opt_hdr->nd_opt_type),
625
0
          opt_hdr->nd_opt_type);
626
0
      break;
627
0
    }
628
0
629
0
    len -= 8 * opt_hdr->nd_opt_len;
630
0
    optional += 8 * opt_hdr->nd_opt_len;
631
0
  }
632
0
}
633
634
static void rtadv_process_advert(uint8_t *msg, unsigned int len,
635
         struct interface *ifp,
636
         struct sockaddr_in6 *addr)
637
0
{
638
0
  struct nd_router_advert *radvert;
639
0
  char addr_str[INET6_ADDRSTRLEN];
640
0
  struct zebra_if *zif;
641
0
  struct prefix p;
642
0
643
0
  zif = ifp->info;
644
0
645
0
  inet_ntop(AF_INET6, &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN);
646
0
647
0
  if (len < sizeof(struct nd_router_advert)) {
648
0
    if (IS_ZEBRA_DEBUG_PACKET)
649
0
      zlog_debug(
650
0
        "%s(%s:%u): Rx RA with invalid length %d from %s",
651
0
        ifp->name, ifp->vrf->name, ifp->ifindex, len,
652
0
        addr_str);
653
0
    return;
654
0
  }
655
0
656
0
  if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) {
657
0
    rtadv_process_optional(msg + sizeof(struct nd_router_advert),
658
0
               len - sizeof(struct nd_router_advert),
659
0
               ifp, addr);
660
0
    if (IS_ZEBRA_DEBUG_PACKET)
661
0
      zlog_debug(
662
0
        "%s(%s:%u): Rx RA with non-linklocal source address from %s",
663
0
        ifp->name, ifp->vrf->name, ifp->ifindex,
664
0
        addr_str);
665
0
    return;
666
0
  }
667
0
668
0
  radvert = (struct nd_router_advert *)msg;
669
0
670
0
#define SIXHOUR2USEC (int64_t)6 * 60 * 60 * 1000000
671
0
672
0
  if ((radvert->nd_ra_curhoplimit && zif->rtadv.AdvCurHopLimit) &&
673
0
      (radvert->nd_ra_curhoplimit != zif->rtadv.AdvCurHopLimit) &&
674
0
      (monotime_since(&zif->rtadv.lastadvcurhoplimit, NULL) >
675
0
         SIXHOUR2USEC ||
676
0
       zif->rtadv.lastadvcurhoplimit.tv_sec == 0)) {
677
0
    flog_warn(
678
0
      EC_ZEBRA_RA_PARAM_MISMATCH,
679
0
      "%s(%u): Rx RA - our AdvCurHopLimit (%u) doesn't agree with %s (%u)",
680
0
      ifp->name, ifp->ifindex, zif->rtadv.AdvCurHopLimit,
681
0
      addr_str, radvert->nd_ra_curhoplimit);
682
0
    monotime(&zif->rtadv.lastadvcurhoplimit);
683
0
  }
684
0
685
0
  if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) &&
686
0
      !zif->rtadv.AdvManagedFlag &&
687
0
      (monotime_since(&zif->rtadv.lastadvmanagedflag, NULL) >
688
0
         SIXHOUR2USEC ||
689
0
       zif->rtadv.lastadvmanagedflag.tv_sec == 0)) {
690
0
    flog_warn(
691
0
      EC_ZEBRA_RA_PARAM_MISMATCH,
692
0
      "%s(%u): Rx RA - our AdvManagedFlag (%u) doesn't agree with %s (%u)",
693
0
      ifp->name, ifp->ifindex, zif->rtadv.AdvManagedFlag,
694
0
      addr_str,
695
0
      !!CHECK_FLAG(radvert->nd_ra_flags_reserved,
696
0
             ND_RA_FLAG_MANAGED));
697
0
    monotime(&zif->rtadv.lastadvmanagedflag);
698
0
  }
699
0
700
0
  if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) &&
701
0
      !zif->rtadv.AdvOtherConfigFlag &&
702
0
      (monotime_since(&zif->rtadv.lastadvotherconfigflag, NULL) >
703
0
         SIXHOUR2USEC ||
704
0
       zif->rtadv.lastadvotherconfigflag.tv_sec == 0)) {
705
0
    flog_warn(
706
0
      EC_ZEBRA_RA_PARAM_MISMATCH,
707
0
      "%s(%u): Rx RA - our AdvOtherConfigFlag (%u) doesn't agree with %s (%u)",
708
0
      ifp->name, ifp->ifindex, zif->rtadv.AdvOtherConfigFlag,
709
0
      addr_str,
710
0
      !!CHECK_FLAG(radvert->nd_ra_flags_reserved,
711
0
             ND_RA_FLAG_OTHER));
712
0
    monotime(&zif->rtadv.lastadvotherconfigflag);
713
0
  }
714
0
715
0
  if ((radvert->nd_ra_reachable && zif->rtadv.AdvReachableTime) &&
716
0
      (ntohl(radvert->nd_ra_reachable) != zif->rtadv.AdvReachableTime) &&
717
0
      (monotime_since(&zif->rtadv.lastadvreachabletime, NULL) >
718
0
         SIXHOUR2USEC ||
719
0
       zif->rtadv.lastadvreachabletime.tv_sec == 0)) {
720
0
    flog_warn(
721
0
      EC_ZEBRA_RA_PARAM_MISMATCH,
722
0
      "%s(%u): Rx RA - our AdvReachableTime (%u) doesn't agree with %s (%u)",
723
0
      ifp->name, ifp->ifindex, zif->rtadv.AdvReachableTime,
724
0
      addr_str, ntohl(radvert->nd_ra_reachable));
725
0
    monotime(&zif->rtadv.lastadvreachabletime);
726
0
  }
727
0
728
0
  if ((radvert->nd_ra_retransmit && zif->rtadv.AdvRetransTimer) &&
729
0
      (ntohl(radvert->nd_ra_retransmit) !=
730
0
       (unsigned int)zif->rtadv.AdvRetransTimer) &&
731
0
      (monotime_since(&zif->rtadv.lastadvretranstimer, NULL) >
732
0
         SIXHOUR2USEC ||
733
0
       zif->rtadv.lastadvretranstimer.tv_sec == 0)) {
734
0
    flog_warn(
735
0
      EC_ZEBRA_RA_PARAM_MISMATCH,
736
0
      "%s(%u): Rx RA - our AdvRetransTimer (%u) doesn't agree with %s (%u)",
737
0
      ifp->name, ifp->ifindex, zif->rtadv.AdvRetransTimer,
738
0
      addr_str, ntohl(radvert->nd_ra_retransmit));
739
0
    monotime(&zif->rtadv.lastadvretranstimer);
740
0
  }
741
0
742
0
  /* Create entry for neighbor if not known. */
743
0
  p.family = AF_INET6;
744
0
  IPV6_ADDR_COPY(&p.u.prefix6, &addr->sin6_addr);
745
0
  p.prefixlen = IPV6_MAX_BITLEN;
746
0
747
0
  if (!nbr_connected_check(ifp, &p))
748
0
    nbr_connected_add_ipv6(ifp, &addr->sin6_addr);
749
0
}
750
751
752
static void rtadv_process_packet(uint8_t *buf, unsigned int len,
753
         ifindex_t ifindex, int hoplimit,
754
         struct sockaddr_in6 *from,
755
         struct zebra_vrf *zvrf)
756
0
{
757
0
  struct icmp6_hdr *icmph;
758
0
  struct interface *ifp;
759
0
  struct zebra_if *zif;
760
0
  char addr_str[INET6_ADDRSTRLEN];
761
0
762
0
  inet_ntop(AF_INET6, &from->sin6_addr, addr_str, INET6_ADDRSTRLEN);
763
0
764
0
  /* Interface search. */
765
0
  ifp = if_lookup_by_index(ifindex, zvrf->vrf->vrf_id);
766
0
  if (ifp == NULL) {
767
0
    flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
768
0
        "RA/RS received on unknown IF %u from %s", ifindex,
769
0
        addr_str);
770
0
    return;
771
0
  }
772
0
773
0
  if (IS_ZEBRA_DEBUG_PACKET)
774
0
    zlog_debug("%s(%s:%u): Rx RA/RS len %d from %s", ifp->name,
775
0
         ifp->vrf->name, ifp->ifindex, len, addr_str);
776
0
777
0
  if (if_is_loopback(ifp))
778
0
    return;
779
0
780
0
  /* Check interface configuration. */
781
0
  zif = ifp->info;
782
0
  if (!zif->rtadv.AdvSendAdvertisements)
783
0
    return;
784
0
785
0
  /* ICMP message length check. */
786
0
  if (len < sizeof(struct icmp6_hdr)) {
787
0
    zlog_debug(
788
0
      "%s(%s:%u): Rx RA with Invalid ICMPV6 packet length %d",
789
0
      ifp->name, ifp->vrf->name, ifp->ifindex, len);
790
0
    return;
791
0
  }
792
0
793
0
  icmph = (struct icmp6_hdr *)buf;
794
0
795
0
  /* ICMP message type check. */
796
0
  if (icmph->icmp6_type != ND_ROUTER_SOLICIT
797
0
      && icmph->icmp6_type != ND_ROUTER_ADVERT) {
798
0
    zlog_debug("%s(%s:%u): Rx RA - Unwanted ICMPV6 message type %d",
799
0
         ifp->name, ifp->vrf->name, ifp->ifindex,
800
0
         icmph->icmp6_type);
801
0
    return;
802
0
  }
803
0
804
0
  /* Hoplimit check. */
805
0
  if (hoplimit >= 0 && hoplimit != 255) {
806
0
    zlog_debug("%s(%s:%u): Rx RA - Invalid hoplimit %d", ifp->name,
807
0
         ifp->vrf->name, ifp->ifindex, hoplimit);
808
0
    return;
809
0
  }
810
0
811
0
  /* Check ICMP message type. */
812
0
  if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
813
0
    rtadv_process_solicit(ifp);
814
0
  else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
815
0
    rtadv_process_advert(buf, len, ifp, from);
816
0
817
0
  return;
818
0
}
819
820
static void rtadv_read(struct event *thread)
821
0
{
822
0
  int sock;
823
0
  int len;
824
0
  uint8_t buf[RTADV_MSG_SIZE];
825
0
  struct sockaddr_in6 from;
826
0
  ifindex_t ifindex = 0;
827
0
  int hoplimit = -1;
828
0
  struct zebra_vrf *zvrf = EVENT_ARG(thread);
829
0
830
0
  sock = EVENT_FD(thread);
831
0
  zvrf->rtadv.ra_read = NULL;
832
0
833
0
  /* Register myself. */
834
0
  rtadv_event(zvrf, RTADV_READ, 0);
835
0
836
0
  len = rtadv_recv_packet(zvrf, sock, buf, sizeof(buf), &from, &ifindex,
837
0
        &hoplimit);
838
0
839
0
  if (len < 0) {
840
0
    flog_err_sys(EC_LIB_SOCKET,
841
0
           "RA/RS recv failed, socket %u error %s", sock,
842
0
           safe_strerror(errno));
843
0
    return;
844
0
  }
845
0
846
0
  rtadv_process_packet(buf, (unsigned)len, ifindex, hoplimit, &from, zvrf);
847
0
}
848
849
static int rtadv_make_socket(ns_id_t ns_id)
850
1
{
851
1
  int sock = -1;
852
1
  int ret = 0;
853
1
  struct icmp6_filter filter;
854
1
  int error;
855
856
1
  frr_with_privs(&zserv_privs) {
857
858
1
    sock = ns_socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, ns_id);
859
    /*
860
     * with privs might set errno too if it fails save
861
     * to the side
862
     */
863
1
    error = errno;
864
1
  }
865
866
1
  if (sock < 0) {
867
0
    zlog_warn("RTADV socket for ns: %u failure to create: %s(%u)",
868
0
        ns_id, safe_strerror(error), error);
869
0
    return -1;
870
0
  }
871
872
1
  ret = setsockopt_ipv6_pktinfo(sock, 1);
873
1
  if (ret < 0) {
874
0
    zlog_warn("RTADV failure to set Packet Information");
875
0
    close(sock);
876
0
    return ret;
877
0
  }
878
1
  ret = setsockopt_ipv6_multicast_loop(sock, 0);
879
1
  if (ret < 0) {
880
0
    zlog_warn("RTADV failure to set multicast Loop detection");
881
0
    close(sock);
882
0
    return ret;
883
0
  }
884
1
  ret = setsockopt_ipv6_unicast_hops(sock, 255);
885
1
  if (ret < 0) {
886
0
    zlog_warn("RTADV failure to set maximum unicast hops");
887
0
    close(sock);
888
0
    return ret;
889
0
  }
890
1
  ret = setsockopt_ipv6_multicast_hops(sock, 255);
891
1
  if (ret < 0) {
892
0
    zlog_warn("RTADV failure to set maximum multicast hops");
893
0
    close(sock);
894
0
    return ret;
895
0
  }
896
1
  ret = setsockopt_ipv6_hoplimit(sock, 1);
897
1
  if (ret < 0) {
898
0
    zlog_warn("RTADV failure to set maximum incoming hop limit");
899
0
    close(sock);
900
0
    return ret;
901
0
  }
902
903
1
  ICMP6_FILTER_SETBLOCKALL(&filter);
904
1
  ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
905
1
  ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
906
907
1
  ret = setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
908
1
       sizeof(struct icmp6_filter));
909
1
  if (ret < 0) {
910
0
    zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno));
911
0
    close(sock);
912
0
    return ret;
913
0
  }
914
915
1
  return sock;
916
1
}
917
918
static struct adv_if *adv_if_new(const char *name)
919
0
{
920
0
  struct adv_if *new;
921
922
0
  new = XCALLOC(MTYPE_ADV_IF, sizeof(struct adv_if));
923
924
0
  strlcpy(new->name, name, sizeof(new->name));
925
926
0
  return new;
927
0
}
928
929
static void adv_if_free(struct adv_if *adv_if)
930
0
{
931
0
  XFREE(MTYPE_ADV_IF, adv_if);
932
0
}
933
934
static bool adv_if_is_empty_internal(const struct adv_if_list_head *adv_if_head)
935
0
{
936
0
  return adv_if_list_count(adv_if_head) ? false : true;
937
0
}
938
939
static struct adv_if *adv_if_add_internal(struct adv_if_list_head *adv_if_head,
940
            const char *name)
941
0
{
942
0
  struct adv_if adv_if_lookup = {};
943
0
  struct adv_if *adv_if = NULL;
944
945
0
  strlcpy(adv_if_lookup.name, name, sizeof(adv_if_lookup.name));
946
0
  adv_if = adv_if_list_find(adv_if_head, &adv_if_lookup);
947
948
0
  if (adv_if != NULL)
949
0
    return adv_if;
950
951
0
  adv_if = adv_if_new(adv_if_lookup.name);
952
0
  adv_if_list_add(adv_if_head, adv_if);
953
954
0
  return NULL;
955
0
}
956
957
static struct adv_if *adv_if_del_internal(struct adv_if_list_head *adv_if_head,
958
            const char *name)
959
0
{
960
0
  struct adv_if adv_if_lookup = {};
961
0
  struct adv_if *adv_if = NULL;
962
963
0
  strlcpy(adv_if_lookup.name, name, sizeof(adv_if_lookup.name));
964
0
  adv_if = adv_if_list_find(adv_if_head, &adv_if_lookup);
965
966
0
  if (adv_if == NULL)
967
0
    return NULL;
968
969
0
  adv_if_list_del(adv_if_head, adv_if);
970
971
0
  return adv_if;
972
0
}
973
974
static void adv_if_clean_internal(struct adv_if_list_head *adv_if_head)
975
0
{
976
0
  struct adv_if *node = NULL;
977
978
0
  if (!adv_if_is_empty_internal(adv_if_head)) {
979
0
    frr_each_safe (adv_if_list, adv_if_head, node) {
980
0
      adv_if_list_del(adv_if_head, node);
981
0
      adv_if_free(node);
982
0
    }
983
0
  }
984
985
0
  adv_if_list_fini(adv_if_head);
986
0
}
987
988
989
/*
990
 * Add to list. On Success, return NULL, otherwise return already existing
991
 * adv_if.
992
 */
993
static struct adv_if *adv_if_add(struct zebra_vrf *zvrf, const char *name)
994
0
{
995
0
  struct adv_if *adv_if = NULL;
996
997
0
  adv_if = adv_if_add_internal(&zvrf->rtadv.adv_if, name);
998
999
0
  if (adv_if != NULL)
1000
0
    return adv_if;
1001
1002
0
  if (IS_ZEBRA_DEBUG_EVENT) {
1003
0
    struct vrf *vrf = zvrf->vrf;
1004
1005
0
    zlog_debug("%s: %s:%u IF %s count: %zu", __func__,
1006
0
         VRF_LOGNAME(vrf), zvrf_id(zvrf), name,
1007
0
         adv_if_list_count(&zvrf->rtadv.adv_if));
1008
0
  }
1009
1010
0
  return NULL;
1011
0
}
1012
1013
/*
1014
 * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
1015
 * frees.
1016
 */
1017
static struct adv_if *adv_if_del(struct zebra_vrf *zvrf, const char *name)
1018
0
{
1019
0
  struct adv_if *adv_if = NULL;
1020
1021
0
  adv_if = adv_if_del_internal(&zvrf->rtadv.adv_if, name);
1022
1023
0
  if (adv_if == NULL)
1024
0
    return NULL;
1025
1026
0
  if (IS_ZEBRA_DEBUG_EVENT) {
1027
0
    struct vrf *vrf = zvrf->vrf;
1028
1029
0
    zlog_debug("%s: %s:%u IF %s count: %zu", __func__,
1030
0
         VRF_LOGNAME(vrf), zvrf_id(zvrf), name,
1031
0
         adv_if_list_count(&zvrf->rtadv.adv_if));
1032
0
  }
1033
1034
0
  return adv_if;
1035
0
}
1036
1037
/*
1038
 * Add to list. On Success, return NULL, otherwise return already existing
1039
 * adv_if.
1040
 */
1041
static struct adv_if *adv_msec_if_add(struct zebra_vrf *zvrf, const char *name)
1042
0
{
1043
0
  struct adv_if *adv_if = NULL;
1044
1045
0
  adv_if = adv_if_add_internal(&zvrf->rtadv.adv_msec_if, name);
1046
1047
0
  if (adv_if != NULL)
1048
0
    return adv_if;
1049
1050
0
  if (IS_ZEBRA_DEBUG_EVENT) {
1051
0
    struct vrf *vrf = zvrf->vrf;
1052
1053
0
    zlog_debug("%s: %s:%u IF %s count: %zu", __func__,
1054
0
         VRF_LOGNAME(vrf), zvrf_id(zvrf), name,
1055
0
         adv_if_list_count(&zvrf->rtadv.adv_msec_if));
1056
0
  }
1057
1058
0
  return NULL;
1059
0
}
1060
1061
/*
1062
 * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
1063
 * frees.
1064
 */
1065
static struct adv_if *adv_msec_if_del(struct zebra_vrf *zvrf, const char *name)
1066
0
{
1067
0
  struct adv_if *adv_if = NULL;
1068
1069
0
  adv_if = adv_if_del_internal(&zvrf->rtadv.adv_msec_if, name);
1070
1071
0
  if (adv_if == NULL)
1072
0
    return NULL;
1073
1074
0
  if (IS_ZEBRA_DEBUG_EVENT) {
1075
0
    struct vrf *vrf = zvrf->vrf;
1076
1077
0
    zlog_debug("%s: %s:%u IF %s count: %zu", __func__,
1078
0
         VRF_LOGNAME(vrf), zvrf_id(zvrf), name,
1079
0
         adv_if_list_count(&zvrf->rtadv.adv_msec_if));
1080
0
  }
1081
1082
0
  return adv_if;
1083
0
}
1084
1085
/* Clean adv_if list, called on vrf terminate */
1086
static void adv_if_clean(struct zebra_vrf *zvrf)
1087
0
{
1088
0
  if (IS_ZEBRA_DEBUG_EVENT) {
1089
0
    struct vrf *vrf = zvrf->vrf;
1090
1091
0
    zlog_debug("%s: %s:%u count: %zu -> 0", __func__,
1092
0
         VRF_LOGNAME(vrf), zvrf_id(zvrf),
1093
0
         adv_if_list_count(&zvrf->rtadv.adv_if));
1094
0
  }
1095
1096
0
  adv_if_clean_internal(&zvrf->rtadv.adv_if);
1097
0
}
1098
1099
/* Clean adv_msec_if list, called on vrf terminate */
1100
static void adv_msec_if_clean(struct zebra_vrf *zvrf)
1101
0
{
1102
0
  if (IS_ZEBRA_DEBUG_EVENT) {
1103
0
    struct vrf *vrf = zvrf->vrf;
1104
1105
0
    zlog_debug("%s: %s:%u count: %zu -> 0", __func__,
1106
0
         VRF_LOGNAME(vrf), zvrf_id(zvrf),
1107
0
         adv_if_list_count(&zvrf->rtadv.adv_msec_if));
1108
0
  }
1109
1110
0
  adv_if_clean_internal(&zvrf->rtadv.adv_msec_if);
1111
0
}
1112
1113
static struct rtadv_prefix *rtadv_prefix_new(void)
1114
0
{
1115
0
  return XCALLOC(MTYPE_RTADV_PREFIX, sizeof(struct rtadv_prefix));
1116
0
}
1117
1118
static void rtadv_prefix_free(struct rtadv_prefix *rtadv_prefix)
1119
0
{
1120
0
  XFREE(MTYPE_RTADV_PREFIX, rtadv_prefix);
1121
0
}
1122
1123
static struct rtadv_prefix *rtadv_prefix_get(struct rtadv_prefixes_head *list,
1124
               struct prefix_ipv6 *p)
1125
0
{
1126
0
  struct rtadv_prefix *rprefix, ref;
1127
1128
0
  ref.prefix = *p;
1129
1130
0
  rprefix = rtadv_prefixes_find(list, &ref);
1131
0
  if (rprefix)
1132
0
    return rprefix;
1133
1134
0
  rprefix = rtadv_prefix_new();
1135
0
  memcpy(&rprefix->prefix, p, sizeof(struct prefix_ipv6));
1136
0
  rtadv_prefixes_add(list, rprefix);
1137
1138
0
  return rprefix;
1139
0
}
1140
1141
static void rtadv_prefix_set_defaults(struct rtadv_prefix *rp)
1142
0
{
1143
0
  rp->AdvAutonomousFlag = 1;
1144
0
  rp->AdvOnLinkFlag = 1;
1145
0
  rp->AdvRouterAddressFlag = 0;
1146
0
  rp->AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
1147
0
  rp->AdvValidLifetime = RTADV_VALID_LIFETIME;
1148
0
}
1149
1150
static void rtadv_prefix_set(struct zebra_if *zif, struct rtadv_prefix *rp)
1151
0
{
1152
0
  struct rtadv_prefix *rprefix;
1153
1154
0
  rprefix = rtadv_prefix_get(zif->rtadv.prefixes, &rp->prefix);
1155
1156
  /*
1157
   * Set parameters based on where the prefix is created.
1158
   * If auto-created based on kernel address addition, set the
1159
   * default values.  If created from a manual "ipv6 nd prefix"
1160
   * command, take the parameters from the manual command. Note
1161
   * that if the manual command exists, the default values will
1162
   * not overwrite the manual values.
1163
   */
1164
0
  if (rp->AdvPrefixCreate == PREFIX_SRC_MANUAL) {
1165
0
    if (rprefix->AdvPrefixCreate == PREFIX_SRC_AUTO)
1166
0
      rprefix->AdvPrefixCreate = PREFIX_SRC_BOTH;
1167
0
    else
1168
0
      rprefix->AdvPrefixCreate = PREFIX_SRC_MANUAL;
1169
1170
0
    rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
1171
0
    rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
1172
0
    rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
1173
0
    rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
1174
0
    rprefix->AdvValidLifetime = rp->AdvValidLifetime;
1175
0
  } else if (rp->AdvPrefixCreate == PREFIX_SRC_AUTO) {
1176
0
    if (rprefix->AdvPrefixCreate == PREFIX_SRC_MANUAL)
1177
0
      rprefix->AdvPrefixCreate = PREFIX_SRC_BOTH;
1178
0
    else {
1179
0
      rprefix->AdvPrefixCreate = PREFIX_SRC_AUTO;
1180
0
      rtadv_prefix_set_defaults(rprefix);
1181
0
    }
1182
0
  }
1183
0
}
1184
1185
static int rtadv_prefix_reset(struct zebra_if *zif, struct rtadv_prefix *rp)
1186
0
{
1187
0
  struct rtadv_prefix *rprefix;
1188
1189
0
  rprefix = rtadv_prefixes_find(zif->rtadv.prefixes, rp);
1190
0
  if (rprefix != NULL) {
1191
1192
    /*
1193
     * When deleting an address from the list, need to take care
1194
     * it wasn't defined both automatically via kernel
1195
     * address addition as well as manually by vtysh cli. If both,
1196
     * we don't actually delete but may change the parameters
1197
     * back to default if a manually defined entry is deleted.
1198
     */
1199
0
    if (rp->AdvPrefixCreate == PREFIX_SRC_MANUAL) {
1200
0
      if (rprefix->AdvPrefixCreate == PREFIX_SRC_BOTH) {
1201
0
        rprefix->AdvPrefixCreate = PREFIX_SRC_AUTO;
1202
0
        rtadv_prefix_set_defaults(rprefix);
1203
0
        return 1;
1204
0
      }
1205
0
    } else if (rp->AdvPrefixCreate == PREFIX_SRC_AUTO) {
1206
0
      if (rprefix->AdvPrefixCreate == PREFIX_SRC_BOTH) {
1207
0
        rprefix->AdvPrefixCreate = PREFIX_SRC_MANUAL;
1208
0
        return 1;
1209
0
      }
1210
0
    }
1211
1212
0
    rtadv_prefixes_del(zif->rtadv.prefixes, rprefix);
1213
0
    rtadv_prefix_free(rprefix);
1214
0
    return 1;
1215
0
  } else
1216
0
    return 0;
1217
0
}
1218
1219
/* Add IPv6 prefixes learned from the kernel to the RA prefix list */
1220
void rtadv_add_prefix(struct zebra_if *zif, const struct prefix_ipv6 *p)
1221
0
{
1222
0
  struct rtadv_prefix rp;
1223
1224
0
  rp.prefix = *p;
1225
0
  apply_mask_ipv6(&rp.prefix);
1226
0
  rp.AdvPrefixCreate = PREFIX_SRC_AUTO;
1227
0
  rtadv_prefix_set(zif, &rp);
1228
0
}
1229
1230
/* Delete IPv6 prefixes removed by the kernel from the RA prefix list */
1231
void rtadv_delete_prefix(struct zebra_if *zif, const struct prefix *p)
1232
0
{
1233
0
  struct rtadv_prefix rp;
1234
1235
0
  rp.prefix = *((struct prefix_ipv6 *)p);
1236
0
  apply_mask_ipv6(&rp.prefix);
1237
0
  rp.AdvPrefixCreate = PREFIX_SRC_AUTO;
1238
0
  rtadv_prefix_reset(zif, &rp);
1239
0
}
1240
1241
static void rtadv_start_interface_events(struct zebra_vrf *zvrf,
1242
           struct zebra_if *zif)
1243
0
{
1244
0
  struct adv_if *adv_if = NULL;
1245
1246
0
  if (zif->ifp->ifindex == IFINDEX_INTERNAL) {
1247
0
    if (IS_ZEBRA_DEBUG_EVENT)
1248
0
      zlog_debug(
1249
0
        "%s(%s) has not configured an ifindex yet, delaying until we have one",
1250
0
        zif->ifp->name, zvrf->vrf->name);
1251
0
    return;
1252
0
  }
1253
1254
0
  adv_if = adv_if_add(zvrf, zif->ifp->name);
1255
0
  if (adv_if != NULL)
1256
0
    return; /* Already added */
1257
1258
0
  if_join_all_router(zvrf->rtadv.sock, zif->ifp);
1259
1260
0
  if (adv_if_list_count(&zvrf->rtadv.adv_if) == 1)
1261
0
    rtadv_event(zvrf, RTADV_START, 0);
1262
0
}
1263
1264
static void ipv6_nd_suppress_ra_set(struct interface *ifp,
1265
            enum ipv6_nd_suppress_ra_status status)
1266
0
{
1267
0
  struct zebra_if *zif;
1268
0
  struct zebra_vrf *zvrf;
1269
0
  struct adv_if *adv_if = NULL;
1270
1271
0
  zif = ifp->info;
1272
1273
0
  zvrf = rtadv_interface_get_zvrf(ifp);
1274
1275
0
  if (status == RA_SUPPRESS) {
1276
    /* RA is currently enabled */
1277
0
    if (zif->rtadv.AdvSendAdvertisements) {
1278
0
      rtadv_send_packet(zvrf->rtadv.sock, ifp, RA_SUPPRESS);
1279
0
      zif->rtadv.AdvSendAdvertisements = 0;
1280
0
      zif->rtadv.AdvIntervalTimer = 0;
1281
1282
0
      adv_if = adv_if_del(zvrf, ifp->name);
1283
0
      if (adv_if == NULL)
1284
0
        return; /* Nothing to delete */
1285
1286
0
      adv_if_free(adv_if);
1287
1288
0
      if_leave_all_router(zvrf->rtadv.sock, ifp);
1289
1290
0
      if (adv_if_list_count(&zvrf->rtadv.adv_if) == 0)
1291
0
        rtadv_event(zvrf, RTADV_STOP, 0);
1292
0
    }
1293
0
  } else {
1294
0
    if (!zif->rtadv.AdvSendAdvertisements) {
1295
0
      zif->rtadv.AdvSendAdvertisements = 1;
1296
0
      zif->rtadv.AdvIntervalTimer = 0;
1297
0
      if ((zif->rtadv.MaxRtrAdvInterval >= 1000)
1298
0
          && zif->rtadv.UseFastRexmit) {
1299
        /*
1300
         * Enable Fast RA only when RA interval is in
1301
         * secs and Fast RA retransmit is enabled
1302
         */
1303
0
        zif->rtadv.inFastRexmit = 1;
1304
0
        zif->rtadv.NumFastReXmitsRemain =
1305
0
          RTADV_NUM_FAST_REXMITS;
1306
0
      }
1307
1308
0
      rtadv_start_interface_events(zvrf, zif);
1309
0
    }
1310
0
  }
1311
0
}
1312
1313
/*
1314
 * Handle client (BGP) message to enable or disable IPv6 RA on an interface.
1315
 * Note that while the client could request RA on an interface on which the
1316
 * operator has not enabled RA, RA won't be disabled upon client request
1317
 * if the operator has explicitly enabled RA. The enable request can also
1318
 * specify a RA interval (in seconds).
1319
 */
1320
static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
1321
0
{
1322
0
  struct stream *s;
1323
0
  ifindex_t ifindex;
1324
0
  struct interface *ifp;
1325
0
  struct zebra_if *zif;
1326
0
  uint32_t ra_interval;
1327
1328
0
  s = msg;
1329
1330
  /* Get interface index and RA interval. */
1331
0
  STREAM_GETL(s, ifindex);
1332
0
  STREAM_GETL(s, ra_interval);
1333
1334
0
  if (IS_ZEBRA_DEBUG_EVENT) {
1335
0
    struct vrf *vrf = zvrf->vrf;
1336
1337
0
    zlog_debug("%s:%u: IF %u RA %s from client %s, interval %ums",
1338
0
         VRF_LOGNAME(vrf), zvrf_id(zvrf), ifindex,
1339
0
         enable ? "enable" : "disable",
1340
0
         zebra_route_string(client->proto), ra_interval);
1341
0
  }
1342
1343
  /* Locate interface and check VRF match. */
1344
0
  ifp = if_lookup_by_index(ifindex, zvrf->vrf->vrf_id);
1345
0
  if (!ifp) {
1346
0
    struct vrf *vrf = zvrf->vrf;
1347
1348
0
    flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
1349
0
        "%s:%u: IF %u RA %s client %s - interface unknown",
1350
0
        VRF_LOGNAME(vrf), zvrf_id(zvrf), ifindex,
1351
0
        enable ? "enable" : "disable",
1352
0
        zebra_route_string(client->proto));
1353
0
    return;
1354
0
  }
1355
0
  if (vrf_is_backend_netns() && ifp->vrf->vrf_id != zvrf_id(zvrf)) {
1356
0
    zlog_debug(
1357
0
      "%s:%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
1358
0
      ifp->vrf->name, zvrf_id(zvrf), ifindex,
1359
0
      enable ? "enable" : "disable",
1360
0
      zebra_route_string(client->proto), ifp->vrf->vrf_id);
1361
0
    return;
1362
0
  }
1363
1364
0
  zif = ifp->info;
1365
0
  if (enable) {
1366
0
    if (!CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
1367
0
      interfaces_configured_for_ra_from_bgp++;
1368
1369
0
    SET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED);
1370
0
    ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
1371
0
    if (ra_interval
1372
0
        && (ra_interval * 1000) < (unsigned int) zif->rtadv.MaxRtrAdvInterval
1373
0
        && !CHECK_FLAG(zif->rtadv.ra_configured,
1374
0
           VTY_RA_INTERVAL_CONFIGURED))
1375
0
      zif->rtadv.MaxRtrAdvInterval = ra_interval * 1000;
1376
0
  } else {
1377
0
    if (CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
1378
0
      interfaces_configured_for_ra_from_bgp--;
1379
1380
0
    UNSET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED);
1381
0
    if (!CHECK_FLAG(zif->rtadv.ra_configured,
1382
0
        VTY_RA_INTERVAL_CONFIGURED))
1383
0
      zif->rtadv.MaxRtrAdvInterval =
1384
0
        RTADV_MAX_RTR_ADV_INTERVAL;
1385
0
    if (!CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED))
1386
0
      ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
1387
0
  }
1388
0
stream_failure:
1389
0
  return;
1390
0
}
1391
1392
/*
1393
 * send router lifetime value of zero in RAs on this interface since we're
1394
 * ceasing to advertise and want to let our neighbors know.
1395
 * RFC 4861 secion 6.2.5
1396
 */
1397
void rtadv_stop_ra(struct interface *ifp)
1398
0
{
1399
0
  struct zebra_if *zif;
1400
0
  struct zebra_vrf *zvrf;
1401
1402
0
  zif = ifp->info;
1403
0
  zvrf = rtadv_interface_get_zvrf(ifp);
1404
1405
0
  if (zif->rtadv.AdvSendAdvertisements)
1406
0
    rtadv_send_packet(zvrf->rtadv.sock, ifp, RA_SUPPRESS);
1407
0
}
1408
1409
/*
1410
 * Send router lifetime value of zero in RAs on all interfaces since we're
1411
 * ceasing to advertise globally and want to let all of our neighbors know
1412
 * RFC 4861 secion 6.2.5
1413
 *
1414
 * Delete all ipv6 global prefixes added to the router advertisement prefix
1415
 * lists prior to ceasing.
1416
 */
1417
void rtadv_stop_ra_all(void)
1418
0
{
1419
0
  struct vrf *vrf;
1420
0
  struct interface *ifp;
1421
0
  struct zebra_if *zif;
1422
0
  struct rtadv_prefix *rprefix;
1423
1424
0
  RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
1425
0
    FOR_ALL_INTERFACES (vrf, ifp) {
1426
0
      zif = ifp->info;
1427
1428
0
      frr_each_safe (rtadv_prefixes, zif->rtadv.prefixes,
1429
0
               rprefix)
1430
0
        rtadv_prefix_reset(zif, rprefix);
1431
1432
0
      rtadv_stop_ra(ifp);
1433
0
    }
1434
0
}
1435
1436
void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS)
1437
0
{
1438
0
  zebra_interface_radv_set(client, hdr, msg, zvrf, 0);
1439
0
}
1440
void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS)
1441
0
{
1442
0
  zebra_interface_radv_set(client, hdr, msg, zvrf, 1);
1443
0
}
1444
1445
static void show_zvrf_rtadv_adv_if_helper(struct vty *vty,
1446
            struct adv_if_list_head *adv_if_head)
1447
0
{
1448
0
  struct adv_if *node = NULL;
1449
1450
0
  if (!adv_if_is_empty_internal(adv_if_head)) {
1451
0
    frr_each (adv_if_list, adv_if_head, node) {
1452
0
      vty_out(vty, "    %s\n", node->name);
1453
0
    }
1454
0
  }
1455
1456
0
  vty_out(vty, "\n");
1457
0
}
1458
1459
static void show_zvrf_rtadv_helper(struct vty *vty, struct zebra_vrf *zvrf)
1460
0
{
1461
0
  vty_out(vty, "VRF: %s\n", zvrf_name(zvrf));
1462
0
  vty_out(vty, "  Interfaces:\n");
1463
0
  show_zvrf_rtadv_adv_if_helper(vty, &zvrf->rtadv.adv_if);
1464
1465
0
  vty_out(vty, "  Interfaces(msec):\n");
1466
0
  show_zvrf_rtadv_adv_if_helper(vty, &zvrf->rtadv.adv_msec_if);
1467
0
}
1468
1469
DEFPY(show_ipv6_nd_ra_if, show_ipv6_nd_ra_if_cmd,
1470
      "show ipv6 nd ra-interfaces [vrf<NAME$vrf_name|all$vrf_all>]",
1471
      SHOW_STR IP6_STR
1472
      "Neighbor discovery\n"
1473
      "Route Advertisement Interfaces\n" VRF_FULL_CMD_HELP_STR)
1474
0
{
1475
0
  struct zebra_vrf *zvrf = NULL;
1476
1477
0
  if (!vrf_is_backend_netns() && (vrf_name || vrf_all)) {
1478
0
    vty_out(vty,
1479
0
      "%% VRF subcommand only applicable for netns-based vrfs.\n");
1480
0
    return CMD_WARNING;
1481
0
  }
1482
1483
0
  if (vrf_all) {
1484
0
    struct vrf *vrf;
1485
1486
0
    RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1487
0
      struct zebra_vrf *zvrf;
1488
1489
0
      zvrf = vrf->info;
1490
0
      if (!zvrf)
1491
0
        continue;
1492
1493
0
      show_zvrf_rtadv_helper(vty, zvrf);
1494
0
    }
1495
1496
0
    return CMD_SUCCESS;
1497
0
  }
1498
1499
0
  if (vrf_name)
1500
0
    zvrf = zebra_vrf_lookup_by_name(vrf_name);
1501
0
  else
1502
0
    zvrf = zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME);
1503
1504
0
  if (!zvrf) {
1505
0
    vty_out(vty, "%% VRF '%s' specified does not exist\n",
1506
0
      vrf_name);
1507
0
    return CMD_WARNING;
1508
0
  }
1509
1510
0
  show_zvrf_rtadv_helper(vty, zvrf);
1511
1512
0
  return CMD_SUCCESS;
1513
0
}
1514
1515
DEFUN (ipv6_nd_ra_fast_retrans,
1516
  ipv6_nd_ra_fast_retrans_cmd,
1517
  "ipv6 nd ra-fast-retrans",
1518
  "Interface IPv6 config commands\n"
1519
  "Neighbor discovery\n"
1520
  "Fast retransmit of RA packets\n")
1521
0
{
1522
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1523
0
  struct zebra_if *zif = ifp->info;
1524
1525
0
  if (if_is_loopback(ifp)) {
1526
0
    vty_out(vty,
1527
0
      "Cannot configure IPv6 Router Advertisements on this  interface\n");
1528
0
    return CMD_WARNING_CONFIG_FAILED;
1529
0
  }
1530
1531
0
  zif->rtadv.UseFastRexmit = true;
1532
1533
0
  return CMD_SUCCESS;
1534
0
}
1535
1536
DEFUN (no_ipv6_nd_ra_fast_retrans,
1537
  no_ipv6_nd_ra_fast_retrans_cmd,
1538
  "no ipv6 nd ra-fast-retrans",
1539
  NO_STR
1540
  "Interface IPv6 config commands\n"
1541
  "Neighbor discovery\n"
1542
  "Fast retransmit of RA packets\n")
1543
0
{
1544
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1545
0
  struct zebra_if *zif = ifp->info;
1546
1547
0
  if (if_is_loopback(ifp)) {
1548
0
    vty_out(vty,
1549
0
      "Cannot configure IPv6 Router Advertisements on this  interface\n");
1550
0
    return CMD_WARNING_CONFIG_FAILED;
1551
0
  }
1552
1553
0
  zif->rtadv.UseFastRexmit = false;
1554
1555
0
  return CMD_SUCCESS;
1556
0
}
1557
1558
DEFPY (ipv6_nd_ra_hop_limit,
1559
       ipv6_nd_ra_hop_limit_cmd,
1560
       "ipv6 nd ra-hop-limit (0-255)$hopcount",
1561
       "Interface IPv6 config commands\n"
1562
       "Neighbor discovery\n"
1563
       "Advertisement Hop Limit\n"
1564
       "Advertisement Hop Limit in hops (default:64)\n")
1565
0
{
1566
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1567
0
  struct zebra_if *zif = ifp->info;
1568
1569
0
  if (if_is_loopback(ifp)) {
1570
0
    vty_out(vty,
1571
0
      "Cannot configure IPv6 Router Advertisements on this interface\n");
1572
0
    return CMD_WARNING_CONFIG_FAILED;
1573
0
  }
1574
1575
0
  zif->rtadv.AdvCurHopLimit = hopcount;
1576
1577
0
  return CMD_SUCCESS;
1578
0
}
1579
1580
DEFPY (no_ipv6_nd_ra_hop_limit,
1581
       no_ipv6_nd_ra_hop_limit_cmd,
1582
       "no ipv6 nd ra-hop-limit [(0-255)]",
1583
       NO_STR
1584
       "Interface IPv6 config commands\n"
1585
       "Neighbor discovery\n"
1586
       "Advertisement Hop Limit\n"
1587
       "Advertisement Hop Limit in hops\n")
1588
0
{
1589
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1590
0
  struct zebra_if *zif = ifp->info;
1591
1592
0
  if (if_is_loopback(ifp)) {
1593
0
    vty_out(vty,
1594
0
      "Cannot configure IPv6 Router Advertisements on this interface\n");
1595
0
    return CMD_WARNING_CONFIG_FAILED;
1596
0
  }
1597
1598
0
  zif->rtadv.AdvCurHopLimit = RTADV_DEFAULT_HOPLIMIT;
1599
1600
0
  return CMD_SUCCESS;
1601
0
}
1602
1603
DEFPY (ipv6_nd_ra_retrans_interval,
1604
       ipv6_nd_ra_retrans_interval_cmd,
1605
       "ipv6 nd ra-retrans-interval (0-4294967295)$interval",
1606
       "Interface IPv6 config commands\n"
1607
       "Neighbor discovery\n"
1608
       "Advertisement Retransmit Interval\n"
1609
       "Advertisement Retransmit Interval in msec\n")
1610
0
{
1611
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1612
0
  struct zebra_if *zif = ifp->info;
1613
1614
0
  if (if_is_loopback(ifp)) {
1615
0
    vty_out(vty,
1616
0
      "Cannot configure IPv6 Router Advertisements on loopback interface\n");
1617
0
    return CMD_WARNING_CONFIG_FAILED;
1618
0
  }
1619
1620
0
  zif->rtadv.AdvRetransTimer = interval;
1621
1622
0
  return CMD_SUCCESS;
1623
0
}
1624
1625
DEFPY (no_ipv6_nd_ra_retrans_interval,
1626
       no_ipv6_nd_ra_retrans_interval_cmd,
1627
       "no ipv6 nd ra-retrans-interval [(0-4294967295)]",
1628
       NO_STR
1629
       "Interface IPv6 config commands\n"
1630
       "Neighbor discovery\n"
1631
       "Advertisement Retransmit Interval\n"
1632
       "Advertisement Retransmit Interval in msec\n")
1633
0
{
1634
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1635
0
  struct zebra_if *zif = ifp->info;
1636
1637
0
  if (if_is_loopback(ifp)) {
1638
0
    vty_out(vty,
1639
0
      "Cannot remove IPv6 Router Advertisements on loopback interface\n");
1640
0
    return CMD_WARNING_CONFIG_FAILED;
1641
0
  }
1642
1643
0
  zif->rtadv.AdvRetransTimer = 0;
1644
1645
0
  return CMD_SUCCESS;
1646
0
}
1647
1648
DEFUN (ipv6_nd_suppress_ra,
1649
       ipv6_nd_suppress_ra_cmd,
1650
       "ipv6 nd suppress-ra",
1651
       "Interface IPv6 config commands\n"
1652
       "Neighbor discovery\n"
1653
       "Suppress Router Advertisement\n")
1654
0
{
1655
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1656
0
  struct zebra_if *zif = ifp->info;
1657
1658
0
  if (if_is_loopback(ifp)) {
1659
0
    vty_out(vty,
1660
0
      "Cannot configure IPv6 Router Advertisements on this  interface\n");
1661
0
    return CMD_WARNING_CONFIG_FAILED;
1662
0
  }
1663
1664
0
  if (!CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
1665
0
    ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
1666
1667
0
  UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
1668
0
  return CMD_SUCCESS;
1669
0
}
1670
1671
DEFUN (no_ipv6_nd_suppress_ra,
1672
       no_ipv6_nd_suppress_ra_cmd,
1673
       "no ipv6 nd suppress-ra",
1674
       NO_STR
1675
       "Interface IPv6 config commands\n"
1676
       "Neighbor discovery\n"
1677
       "Suppress Router Advertisement\n")
1678
0
{
1679
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1680
0
  struct zebra_if *zif = ifp->info;
1681
1682
0
  if (if_is_loopback(ifp)) {
1683
0
    vty_out(vty,
1684
0
      "Cannot configure IPv6 Router Advertisements on this interface\n");
1685
0
    return CMD_WARNING_CONFIG_FAILED;
1686
0
  }
1687
1688
0
  ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
1689
0
  SET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
1690
0
  return CMD_SUCCESS;
1691
0
}
1692
1693
DEFUN (ipv6_nd_ra_interval_msec,
1694
       ipv6_nd_ra_interval_msec_cmd,
1695
       "ipv6 nd ra-interval msec (70-1800000)",
1696
       "Interface IPv6 config commands\n"
1697
       "Neighbor discovery\n"
1698
       "Router Advertisement interval\n"
1699
       "Router Advertisement interval in milliseconds\n"
1700
       "Router Advertisement interval in milliseconds\n")
1701
0
{
1702
0
  int idx_number = 4;
1703
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1704
0
  unsigned interval;
1705
0
  struct zebra_if *zif = ifp->info;
1706
0
  struct zebra_vrf *zvrf;
1707
0
  struct adv_if *adv_if;
1708
1709
0
  zvrf = rtadv_interface_get_zvrf(ifp);
1710
1711
0
  interval = strtoul(argv[idx_number]->arg, NULL, 10);
1712
0
  if ((zif->rtadv.AdvDefaultLifetime != -1
1713
0
       && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000)) {
1714
0
    vty_out(vty,
1715
0
      "This ra-interval would conflict with configured ra-lifetime!\n");
1716
0
    return CMD_WARNING_CONFIG_FAILED;
1717
0
  }
1718
1719
0
  if (zif->rtadv.MaxRtrAdvInterval % 1000) {
1720
0
    adv_if = adv_msec_if_del(zvrf, ifp->name);
1721
0
    if (adv_if != NULL)
1722
0
      adv_if_free(adv_if);
1723
0
  }
1724
1725
0
  if (interval % 1000)
1726
0
    (void)adv_msec_if_add(zvrf, ifp->name);
1727
1728
0
  SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
1729
0
  zif->rtadv.MaxRtrAdvInterval = interval;
1730
0
  zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
1731
0
  zif->rtadv.AdvIntervalTimer = 0;
1732
1733
0
  return CMD_SUCCESS;
1734
0
}
1735
1736
DEFUN (ipv6_nd_ra_interval,
1737
       ipv6_nd_ra_interval_cmd,
1738
       "ipv6 nd ra-interval (1-1800)",
1739
       "Interface IPv6 config commands\n"
1740
       "Neighbor discovery\n"
1741
       "Router Advertisement interval\n"
1742
       "Router Advertisement interval in seconds\n")
1743
0
{
1744
0
  int idx_number = 3;
1745
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1746
0
  unsigned interval;
1747
0
  struct zebra_if *zif = ifp->info;
1748
0
  struct zebra_vrf *zvrf;
1749
0
  struct adv_if *adv_if;
1750
1751
0
  zvrf = rtadv_interface_get_zvrf(ifp);
1752
1753
0
  interval = strtoul(argv[idx_number]->arg, NULL, 10);
1754
0
  if ((zif->rtadv.AdvDefaultLifetime != -1
1755
0
       && interval > (unsigned)zif->rtadv.AdvDefaultLifetime)) {
1756
0
    vty_out(vty,
1757
0
      "This ra-interval would conflict with configured ra-lifetime!\n");
1758
0
    return CMD_WARNING_CONFIG_FAILED;
1759
0
  }
1760
1761
0
  if (zif->rtadv.MaxRtrAdvInterval % 1000) {
1762
0
    adv_if = adv_msec_if_del(zvrf, ifp->name);
1763
0
    if (adv_if != NULL)
1764
0
      adv_if_free(adv_if);
1765
0
  }
1766
1767
  /* convert to milliseconds */
1768
0
  interval = interval * 1000;
1769
1770
0
  SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
1771
0
  zif->rtadv.MaxRtrAdvInterval = interval;
1772
0
  zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
1773
0
  zif->rtadv.AdvIntervalTimer = 0;
1774
1775
0
  return CMD_SUCCESS;
1776
0
}
1777
1778
DEFUN (no_ipv6_nd_ra_interval,
1779
       no_ipv6_nd_ra_interval_cmd,
1780
       "no ipv6 nd ra-interval [<(1-1800)|msec (1-1800000)>]",
1781
       NO_STR
1782
       "Interface IPv6 config commands\n"
1783
       "Neighbor discovery\n"
1784
       "Router Advertisement interval\n"
1785
       "Router Advertisement interval in seconds\n"
1786
       "Specify millisecond router advertisement interval\n"
1787
       "Router Advertisement interval in milliseconds\n")
1788
0
{
1789
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1790
0
  struct zebra_if *zif = ifp->info;
1791
0
  struct zebra_vrf *zvrf = NULL;
1792
0
  struct adv_if *adv_if;
1793
1794
0
  zvrf = rtadv_interface_get_zvrf(ifp);
1795
1796
0
  if (zif->rtadv.MaxRtrAdvInterval % 1000) {
1797
0
    adv_if = adv_msec_if_del(zvrf, ifp->name);
1798
0
    if (adv_if != NULL)
1799
0
      adv_if_free(adv_if);
1800
0
  }
1801
1802
0
  UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
1803
1804
0
  if (CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
1805
0
    zif->rtadv.MaxRtrAdvInterval = 10000;
1806
0
  else
1807
0
    zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
1808
1809
0
  zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
1810
0
  zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
1811
1812
0
  return CMD_SUCCESS;
1813
0
}
1814
1815
DEFUN (ipv6_nd_ra_lifetime,
1816
       ipv6_nd_ra_lifetime_cmd,
1817
       "ipv6 nd ra-lifetime (0-9000)",
1818
       "Interface IPv6 config commands\n"
1819
       "Neighbor discovery\n"
1820
       "Router lifetime\n"
1821
       "Router lifetime in seconds (0 stands for a non-default gw)\n")
1822
0
{
1823
0
  int idx_number = 3;
1824
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1825
0
  struct zebra_if *zif = ifp->info;
1826
0
  int lifetime;
1827
1828
0
  lifetime = strtoul(argv[idx_number]->arg, NULL, 10);
1829
1830
  /* The value to be placed in the Router Lifetime field
1831
   * of Router Advertisements sent from the interface,
1832
   * in seconds.  MUST be either zero or between
1833
   * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
1834
0
  if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval)) {
1835
0
    vty_out(vty,
1836
0
      "This ra-lifetime would conflict with configured ra-interval\n");
1837
0
    return CMD_WARNING_CONFIG_FAILED;
1838
0
  }
1839
1840
0
  zif->rtadv.AdvDefaultLifetime = lifetime;
1841
1842
0
  return CMD_SUCCESS;
1843
0
}
1844
1845
DEFUN (no_ipv6_nd_ra_lifetime,
1846
       no_ipv6_nd_ra_lifetime_cmd,
1847
       "no ipv6 nd ra-lifetime [(0-9000)]",
1848
       NO_STR
1849
       "Interface IPv6 config commands\n"
1850
       "Neighbor discovery\n"
1851
       "Router lifetime\n"
1852
       "Router lifetime in seconds (0 stands for a non-default gw)\n")
1853
0
{
1854
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1855
0
  struct zebra_if *zif = ifp->info;
1856
1857
0
  zif->rtadv.AdvDefaultLifetime = -1;
1858
1859
0
  return CMD_SUCCESS;
1860
0
}
1861
1862
DEFUN (ipv6_nd_reachable_time,
1863
       ipv6_nd_reachable_time_cmd,
1864
       "ipv6 nd reachable-time (1-3600000)",
1865
       "Interface IPv6 config commands\n"
1866
       "Neighbor discovery\n"
1867
       "Reachable time\n"
1868
       "Reachable time in milliseconds\n")
1869
0
{
1870
0
  int idx_number = 3;
1871
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1872
0
  struct zebra_if *zif = ifp->info;
1873
0
  zif->rtadv.AdvReachableTime = strtoul(argv[idx_number]->arg, NULL, 10);
1874
0
  return CMD_SUCCESS;
1875
0
}
1876
1877
DEFUN (no_ipv6_nd_reachable_time,
1878
       no_ipv6_nd_reachable_time_cmd,
1879
       "no ipv6 nd reachable-time [(1-3600000)]",
1880
       NO_STR
1881
       "Interface IPv6 config commands\n"
1882
       "Neighbor discovery\n"
1883
       "Reachable time\n"
1884
       "Reachable time in milliseconds\n")
1885
0
{
1886
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1887
0
  struct zebra_if *zif = ifp->info;
1888
1889
0
  zif->rtadv.AdvReachableTime = 0;
1890
1891
0
  return CMD_SUCCESS;
1892
0
}
1893
1894
DEFUN (ipv6_nd_homeagent_preference,
1895
       ipv6_nd_homeagent_preference_cmd,
1896
       "ipv6 nd home-agent-preference (0-65535)",
1897
       "Interface IPv6 config commands\n"
1898
       "Neighbor discovery\n"
1899
       "Home Agent preference\n"
1900
       "preference value (default is 0, least preferred)\n")
1901
0
{
1902
0
  int idx_number = 3;
1903
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1904
0
  struct zebra_if *zif = ifp->info;
1905
0
  zif->rtadv.HomeAgentPreference =
1906
0
    strtoul(argv[idx_number]->arg, NULL, 10);
1907
0
  return CMD_SUCCESS;
1908
0
}
1909
1910
DEFUN (no_ipv6_nd_homeagent_preference,
1911
       no_ipv6_nd_homeagent_preference_cmd,
1912
       "no ipv6 nd home-agent-preference [(0-65535)]",
1913
       NO_STR
1914
       "Interface IPv6 config commands\n"
1915
       "Neighbor discovery\n"
1916
       "Home Agent preference\n"
1917
       "preference value (default is 0, least preferred)\n")
1918
0
{
1919
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1920
0
  struct zebra_if *zif = ifp->info;
1921
1922
0
  zif->rtadv.HomeAgentPreference = 0;
1923
1924
0
  return CMD_SUCCESS;
1925
0
}
1926
1927
DEFUN (ipv6_nd_homeagent_lifetime,
1928
       ipv6_nd_homeagent_lifetime_cmd,
1929
       "ipv6 nd home-agent-lifetime (0-65520)",
1930
       "Interface IPv6 config commands\n"
1931
       "Neighbor discovery\n"
1932
       "Home Agent lifetime\n"
1933
       "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1934
0
{
1935
0
  int idx_number = 3;
1936
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1937
0
  struct zebra_if *zif = ifp->info;
1938
0
  zif->rtadv.HomeAgentLifetime = strtoul(argv[idx_number]->arg, NULL, 10);
1939
0
  return CMD_SUCCESS;
1940
0
}
1941
1942
DEFUN (no_ipv6_nd_homeagent_lifetime,
1943
       no_ipv6_nd_homeagent_lifetime_cmd,
1944
       "no ipv6 nd home-agent-lifetime [(0-65520)]",
1945
       NO_STR
1946
       "Interface IPv6 config commands\n"
1947
       "Neighbor discovery\n"
1948
       "Home Agent lifetime\n"
1949
       "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
1950
0
{
1951
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1952
0
  struct zebra_if *zif = ifp->info;
1953
1954
0
  zif->rtadv.HomeAgentLifetime = -1;
1955
1956
0
  return CMD_SUCCESS;
1957
0
}
1958
1959
DEFUN (ipv6_nd_managed_config_flag,
1960
       ipv6_nd_managed_config_flag_cmd,
1961
       "ipv6 nd managed-config-flag",
1962
       "Interface IPv6 config commands\n"
1963
       "Neighbor discovery\n"
1964
       "Managed address configuration flag\n")
1965
0
{
1966
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1967
0
  struct zebra_if *zif = ifp->info;
1968
1969
0
  zif->rtadv.AdvManagedFlag = 1;
1970
1971
0
  return CMD_SUCCESS;
1972
0
}
1973
1974
DEFUN (no_ipv6_nd_managed_config_flag,
1975
       no_ipv6_nd_managed_config_flag_cmd,
1976
       "no ipv6 nd managed-config-flag",
1977
       NO_STR
1978
       "Interface IPv6 config commands\n"
1979
       "Neighbor discovery\n"
1980
       "Managed address configuration flag\n")
1981
0
{
1982
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1983
0
  struct zebra_if *zif = ifp->info;
1984
1985
0
  zif->rtadv.AdvManagedFlag = 0;
1986
1987
0
  return CMD_SUCCESS;
1988
0
}
1989
1990
DEFUN (ipv6_nd_homeagent_config_flag,
1991
       ipv6_nd_homeagent_config_flag_cmd,
1992
       "ipv6 nd home-agent-config-flag",
1993
       "Interface IPv6 config commands\n"
1994
       "Neighbor discovery\n"
1995
       "Home Agent configuration flag\n")
1996
0
{
1997
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
1998
0
  struct zebra_if *zif = ifp->info;
1999
2000
0
  zif->rtadv.AdvHomeAgentFlag = 1;
2001
2002
0
  return CMD_SUCCESS;
2003
0
}
2004
2005
DEFUN (no_ipv6_nd_homeagent_config_flag,
2006
       no_ipv6_nd_homeagent_config_flag_cmd,
2007
       "no ipv6 nd home-agent-config-flag",
2008
       NO_STR
2009
       "Interface IPv6 config commands\n"
2010
       "Neighbor discovery\n"
2011
       "Home Agent configuration flag\n")
2012
0
{
2013
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
2014
0
  struct zebra_if *zif = ifp->info;
2015
2016
0
  zif->rtadv.AdvHomeAgentFlag = 0;
2017
2018
0
  return CMD_SUCCESS;
2019
0
}
2020
2021
DEFUN (ipv6_nd_adv_interval_config_option,
2022
       ipv6_nd_adv_interval_config_option_cmd,
2023
       "ipv6 nd adv-interval-option",
2024
       "Interface IPv6 config commands\n"
2025
       "Neighbor discovery\n"
2026
       "Advertisement Interval Option\n")
2027
0
{
2028
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
2029
0
  struct zebra_if *zif = ifp->info;
2030
2031
0
  zif->rtadv.AdvIntervalOption = 1;
2032
2033
0
  return CMD_SUCCESS;
2034
0
}
2035
2036
DEFUN (no_ipv6_nd_adv_interval_config_option,
2037
       no_ipv6_nd_adv_interval_config_option_cmd,
2038
       "no ipv6 nd adv-interval-option",
2039
       NO_STR
2040
       "Interface IPv6 config commands\n"
2041
       "Neighbor discovery\n"
2042
       "Advertisement Interval Option\n")
2043
0
{
2044
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
2045
0
  struct zebra_if *zif = ifp->info;
2046
2047
0
  zif->rtadv.AdvIntervalOption = 0;
2048
2049
0
  return CMD_SUCCESS;
2050
0
}
2051
2052
DEFUN (ipv6_nd_other_config_flag,
2053
       ipv6_nd_other_config_flag_cmd,
2054
       "ipv6 nd other-config-flag",
2055
       "Interface IPv6 config commands\n"
2056
       "Neighbor discovery\n"
2057
       "Other statefull configuration flag\n")
2058
0
{
2059
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
2060
0
  struct zebra_if *zif = ifp->info;
2061
2062
0
  zif->rtadv.AdvOtherConfigFlag = 1;
2063
2064
0
  return CMD_SUCCESS;
2065
0
}
2066
2067
DEFUN (no_ipv6_nd_other_config_flag,
2068
       no_ipv6_nd_other_config_flag_cmd,
2069
       "no ipv6 nd other-config-flag",
2070
       NO_STR
2071
       "Interface IPv6 config commands\n"
2072
       "Neighbor discovery\n"
2073
       "Other statefull configuration flag\n")
2074
0
{
2075
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
2076
0
  struct zebra_if *zif = ifp->info;
2077
2078
0
  zif->rtadv.AdvOtherConfigFlag = 0;
2079
2080
0
  return CMD_SUCCESS;
2081
0
}
2082
2083
DEFUN (ipv6_nd_prefix,
2084
       ipv6_nd_prefix_cmd,
2085
       "ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
2086
       "Interface IPv6 config commands\n"
2087
       "Neighbor discovery\n"
2088
       "Prefix information\n"
2089
       "IPv6 prefix\n"
2090
       "Valid lifetime in seconds\n"
2091
       "Infinite valid lifetime\n"
2092
       "Preferred lifetime in seconds\n"
2093
       "Infinite preferred lifetime\n"
2094
       "Set Router Address flag\n"
2095
       "Do not use prefix for onlink determination\n"
2096
       "Do not use prefix for autoconfiguration\n"
2097
       "Do not use prefix for autoconfiguration\n"
2098
       "Do not use prefix for onlink determination\n")
2099
0
{
2100
  /* prelude */
2101
0
  char *prefix = argv[3]->arg;
2102
0
  int lifetimes = (argc > 4) && (argv[4]->type == RANGE_TKN
2103
0
               || strmatch(argv[4]->text, "infinite"));
2104
0
  int routeropts = lifetimes ? argc > 6 : argc > 4;
2105
2106
0
  int idx_routeropts = routeropts ? (lifetimes ? 6 : 4) : 0;
2107
2108
0
  char *lifetime = NULL, *preflifetime = NULL;
2109
0
  int routeraddr = 0, offlink = 0, noautoconf = 0;
2110
0
  if (lifetimes) {
2111
0
    lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
2112
0
                  : argv[4]->text;
2113
0
    preflifetime = argv[5]->type == RANGE_TKN ? argv[5]->arg
2114
0
                : argv[5]->text;
2115
0
  }
2116
0
  if (routeropts) {
2117
0
    routeraddr =
2118
0
      strmatch(argv[idx_routeropts]->text, "router-address");
2119
0
    if (!routeraddr) {
2120
0
      offlink = (argc > idx_routeropts + 1
2121
0
           || strmatch(argv[idx_routeropts]->text,
2122
0
                 "off-link"));
2123
0
      noautoconf = (argc > idx_routeropts + 1
2124
0
              || strmatch(argv[idx_routeropts]->text,
2125
0
              "no-autoconfig"));
2126
0
    }
2127
0
  }
2128
2129
  /* business */
2130
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
2131
0
  struct zebra_if *zebra_if = ifp->info;
2132
0
  int ret;
2133
0
  struct rtadv_prefix rp;
2134
2135
0
  ret = str2prefix_ipv6(prefix, &rp.prefix);
2136
0
  if (!ret) {
2137
0
    vty_out(vty, "Malformed IPv6 prefix\n");
2138
0
    return CMD_WARNING_CONFIG_FAILED;
2139
0
  }
2140
0
  apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */
2141
0
  rp.AdvOnLinkFlag = !offlink;
2142
0
  rp.AdvAutonomousFlag = !noautoconf;
2143
0
  rp.AdvRouterAddressFlag = routeraddr;
2144
0
  rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
2145
0
  rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
2146
0
  rp.AdvPrefixCreate = PREFIX_SRC_MANUAL;
2147
2148
0
  if (lifetimes) {
2149
0
    rp.AdvValidLifetime = strmatch(lifetime, "infinite")
2150
0
                ? UINT32_MAX
2151
0
                : strtoll(lifetime, NULL, 10);
2152
0
    rp.AdvPreferredLifetime =
2153
0
      strmatch(preflifetime, "infinite")
2154
0
        ? UINT32_MAX
2155
0
        : strtoll(preflifetime, NULL, 10);
2156
0
    if (rp.AdvPreferredLifetime > rp.AdvValidLifetime) {
2157
0
      vty_out(vty, "Invalid preferred lifetime\n");
2158
0
      return CMD_WARNING_CONFIG_FAILED;
2159
0
    }
2160
0
  }
2161
2162
0
  rtadv_prefix_set(zebra_if, &rp);
2163
2164
0
  return CMD_SUCCESS;
2165
0
}
2166
2167
DEFUN (no_ipv6_nd_prefix,
2168
       no_ipv6_nd_prefix_cmd,
2169
       "no ipv6 nd prefix X:X::X:X/M [<(0-4294967295)|infinite> <(0-4294967295)|infinite>] [<router-address|off-link [no-autoconfig]|no-autoconfig [off-link]>]",
2170
        NO_STR
2171
       "Interface IPv6 config commands\n"
2172
       "Neighbor discovery\n"
2173
       "Prefix information\n"
2174
       "IPv6 prefix\n"
2175
       "Valid lifetime in seconds\n"
2176
       "Infinite valid lifetime\n"
2177
       "Preferred lifetime in seconds\n"
2178
       "Infinite preferred lifetime\n"
2179
       "Set Router Address flag\n"
2180
       "Do not use prefix for onlink determination\n"
2181
       "Do not use prefix for autoconfiguration\n"
2182
       "Do not use prefix for autoconfiguration\n"
2183
       "Do not use prefix for onlink determination\n")
2184
0
{
2185
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
2186
0
  struct zebra_if *zebra_if = ifp->info;
2187
0
  int ret;
2188
0
  struct rtadv_prefix rp;
2189
0
  char *prefix = argv[4]->arg;
2190
2191
0
  ret = str2prefix_ipv6(prefix, &rp.prefix);
2192
0
  if (!ret) {
2193
0
    vty_out(vty, "Malformed IPv6 prefix\n");
2194
0
    return CMD_WARNING_CONFIG_FAILED;
2195
0
  }
2196
0
  apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */
2197
0
  rp.AdvPrefixCreate = PREFIX_SRC_MANUAL;
2198
2199
0
  ret = rtadv_prefix_reset(zebra_if, &rp);
2200
0
  if (!ret) {
2201
0
    vty_out(vty, "Non-existant IPv6 prefix\n");
2202
0
    return CMD_WARNING_CONFIG_FAILED;
2203
0
  }
2204
2205
0
  return CMD_SUCCESS;
2206
0
}
2207
2208
DEFUN (ipv6_nd_router_preference,
2209
       ipv6_nd_router_preference_cmd,
2210
       "ipv6 nd router-preference <high|medium|low>",
2211
       "Interface IPv6 config commands\n"
2212
       "Neighbor discovery\n"
2213
       "Default router preference\n"
2214
       "High default router preference\n"
2215
       "Medium default router preference (default)\n"
2216
       "Low default router preference\n")
2217
0
{
2218
0
  int idx_high_medium_low = 3;
2219
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
2220
0
  struct zebra_if *zif = ifp->info;
2221
0
  int i = 0;
2222
2223
0
  while (0 != rtadv_pref_strs[i]) {
2224
0
    if (strncmp(argv[idx_high_medium_low]->arg, rtadv_pref_strs[i],
2225
0
          1)
2226
0
        == 0) {
2227
0
      zif->rtadv.DefaultPreference = i;
2228
0
      return CMD_SUCCESS;
2229
0
    }
2230
0
    i++;
2231
0
  }
2232
2233
0
  return CMD_ERR_NO_MATCH;
2234
0
}
2235
2236
DEFUN (no_ipv6_nd_router_preference,
2237
       no_ipv6_nd_router_preference_cmd,
2238
       "no ipv6 nd router-preference [<high|medium|low>]",
2239
       NO_STR
2240
       "Interface IPv6 config commands\n"
2241
       "Neighbor discovery\n"
2242
       "Default router preference\n"
2243
       "High default router preference\n"
2244
       "Medium default router preference (default)\n"
2245
       "Low default router preference\n")
2246
0
{
2247
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
2248
0
  struct zebra_if *zif = ifp->info;
2249
2250
0
  zif->rtadv.DefaultPreference =
2251
0
    RTADV_PREF_MEDIUM; /* Default per RFC4191. */
2252
2253
0
  return CMD_SUCCESS;
2254
0
}
2255
2256
DEFUN (ipv6_nd_mtu,
2257
       ipv6_nd_mtu_cmd,
2258
       "ipv6 nd mtu (1-65535)",
2259
       "Interface IPv6 config commands\n"
2260
       "Neighbor discovery\n"
2261
       "Advertised MTU\n"
2262
       "MTU in bytes\n")
2263
0
{
2264
0
  int idx_number = 3;
2265
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
2266
0
  struct zebra_if *zif = ifp->info;
2267
0
  zif->rtadv.AdvLinkMTU = strtoul(argv[idx_number]->arg, NULL, 10);
2268
0
  return CMD_SUCCESS;
2269
0
}
2270
2271
DEFUN (no_ipv6_nd_mtu,
2272
       no_ipv6_nd_mtu_cmd,
2273
       "no ipv6 nd mtu [(1-65535)]",
2274
       NO_STR
2275
       "Interface IPv6 config commands\n"
2276
       "Neighbor discovery\n"
2277
       "Advertised MTU\n"
2278
       "MTU in bytes\n")
2279
0
{
2280
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
2281
0
  struct zebra_if *zif = ifp->info;
2282
0
  zif->rtadv.AdvLinkMTU = 0;
2283
0
  return CMD_SUCCESS;
2284
0
}
2285
2286
static struct rtadv_rdnss *rtadv_rdnss_new(void)
2287
0
{
2288
0
  return XCALLOC(MTYPE_RTADV_RDNSS, sizeof(struct rtadv_rdnss));
2289
0
}
2290
2291
static void rtadv_rdnss_free(struct rtadv_rdnss *rdnss)
2292
0
{
2293
0
  XFREE(MTYPE_RTADV_RDNSS, rdnss);
2294
0
}
2295
2296
static struct rtadv_rdnss *rtadv_rdnss_lookup(struct list *list,
2297
                struct rtadv_rdnss *rdnss)
2298
0
{
2299
0
  struct listnode *node;
2300
0
  struct rtadv_rdnss *p;
2301
2302
0
  for (ALL_LIST_ELEMENTS_RO(list, node, p))
2303
0
    if (IPV6_ADDR_SAME(&p->addr, &rdnss->addr))
2304
0
      return p;
2305
0
  return NULL;
2306
0
}
2307
2308
static struct rtadv_rdnss *rtadv_rdnss_get(struct list *list,
2309
             struct rtadv_rdnss *rdnss)
2310
0
{
2311
0
  struct rtadv_rdnss *p;
2312
2313
0
  p = rtadv_rdnss_lookup(list, rdnss);
2314
0
  if (p)
2315
0
    return p;
2316
2317
0
  p = rtadv_rdnss_new();
2318
0
  memcpy(p, rdnss, sizeof(struct rtadv_rdnss));
2319
0
  listnode_add(list, p);
2320
2321
0
  return p;
2322
0
}
2323
2324
static void rtadv_rdnss_set(struct zebra_if *zif, struct rtadv_rdnss *rdnss)
2325
0
{
2326
0
  struct rtadv_rdnss *p;
2327
2328
0
  p = rtadv_rdnss_get(zif->rtadv.AdvRDNSSList, rdnss);
2329
0
  p->lifetime = rdnss->lifetime;
2330
0
  p->lifetime_set = rdnss->lifetime_set;
2331
0
}
2332
2333
static int rtadv_rdnss_reset(struct zebra_if *zif, struct rtadv_rdnss *rdnss)
2334
0
{
2335
0
  struct rtadv_rdnss *p;
2336
2337
0
  p = rtadv_rdnss_lookup(zif->rtadv.AdvRDNSSList, rdnss);
2338
0
  if (p) {
2339
0
    listnode_delete(zif->rtadv.AdvRDNSSList, p);
2340
0
    rtadv_rdnss_free(p);
2341
0
    return 1;
2342
0
  }
2343
2344
0
  return 0;
2345
0
}
2346
2347
static struct rtadv_dnssl *rtadv_dnssl_new(void)
2348
0
{
2349
0
  return XCALLOC(MTYPE_RTADV_DNSSL, sizeof(struct rtadv_dnssl));
2350
0
}
2351
2352
static void rtadv_dnssl_free(struct rtadv_dnssl *dnssl)
2353
0
{
2354
0
  XFREE(MTYPE_RTADV_DNSSL, dnssl);
2355
0
}
2356
2357
static struct rtadv_dnssl *rtadv_dnssl_lookup(struct list *list,
2358
                struct rtadv_dnssl *dnssl)
2359
0
{
2360
0
  struct listnode *node;
2361
0
  struct rtadv_dnssl *p;
2362
2363
0
  for (ALL_LIST_ELEMENTS_RO(list, node, p))
2364
0
    if (!strcasecmp(p->name, dnssl->name))
2365
0
      return p;
2366
0
  return NULL;
2367
0
}
2368
2369
static struct rtadv_dnssl *rtadv_dnssl_get(struct list *list,
2370
             struct rtadv_dnssl *dnssl)
2371
0
{
2372
0
  struct rtadv_dnssl *p;
2373
2374
0
  p = rtadv_dnssl_lookup(list, dnssl);
2375
0
  if (p)
2376
0
    return p;
2377
2378
0
  p = rtadv_dnssl_new();
2379
0
  memcpy(p, dnssl, sizeof(struct rtadv_dnssl));
2380
0
  listnode_add(list, p);
2381
2382
0
  return p;
2383
0
}
2384
2385
static void rtadv_dnssl_set(struct zebra_if *zif, struct rtadv_dnssl *dnssl)
2386
0
{
2387
0
  struct rtadv_dnssl *p;
2388
2389
0
  p = rtadv_dnssl_get(zif->rtadv.AdvDNSSLList, dnssl);
2390
0
  memcpy(p, dnssl, sizeof(struct rtadv_dnssl));
2391
0
}
2392
2393
static int rtadv_dnssl_reset(struct zebra_if *zif, struct rtadv_dnssl *dnssl)
2394
0
{
2395
0
  struct rtadv_dnssl *p;
2396
2397
0
  p = rtadv_dnssl_lookup(zif->rtadv.AdvDNSSLList, dnssl);
2398
0
  if (p) {
2399
0
    listnode_delete(zif->rtadv.AdvDNSSLList, p);
2400
0
    rtadv_dnssl_free(p);
2401
0
    return 1;
2402
0
  }
2403
2404
0
  return 0;
2405
0
}
2406
2407
/*
2408
 * Convert dotted domain name (with or without trailing root zone dot) to
2409
 * sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
2410
 * to strlen(in) + 2 octets to out.
2411
 *
2412
 * Returns the number of octets written to out or -1 if in does not constitute
2413
 * a valid domain name.
2414
 */
2415
static int rtadv_dnssl_encode(uint8_t *out, const char *in)
2416
0
{
2417
0
  const char *label_start, *label_end;
2418
0
  size_t outp;
2419
2420
0
  outp = 0;
2421
0
  label_start = in;
2422
2423
0
  while (*label_start) {
2424
0
    size_t label_len;
2425
2426
0
    label_end = strchr(label_start, '.');
2427
0
    if (label_end == NULL)
2428
0
      label_end = label_start + strlen(label_start);
2429
2430
0
    label_len = label_end - label_start;
2431
0
    if (label_len >= 64)
2432
0
      return -1; /* labels must be 63 octets or less */
2433
2434
0
    out[outp++] = (uint8_t)label_len;
2435
0
    memcpy(out + outp, label_start, label_len);
2436
0
    outp += label_len;
2437
0
    label_start += label_len;
2438
0
    if (*label_start == '.')
2439
0
      label_start++;
2440
0
  }
2441
2442
0
  out[outp++] = '\0';
2443
0
  return outp;
2444
0
}
2445
2446
DEFUN(ipv6_nd_rdnss,
2447
      ipv6_nd_rdnss_cmd,
2448
      "ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2449
      "Interface IPv6 config commands\n"
2450
      "Neighbor discovery\n"
2451
      "Recursive DNS server information\n"
2452
      "IPv6 address\n"
2453
      "Valid lifetime in seconds\n"
2454
      "Infinite valid lifetime\n")
2455
0
{
2456
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
2457
0
  struct zebra_if *zif = ifp->info;
2458
0
  struct rtadv_rdnss rdnss = {};
2459
2460
0
  if (inet_pton(AF_INET6, argv[3]->arg, &rdnss.addr) != 1) {
2461
0
    vty_out(vty, "Malformed IPv6 address\n");
2462
0
    return CMD_WARNING_CONFIG_FAILED;
2463
0
  }
2464
0
  if (argc > 4) {
2465
0
    char *lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
2466
0
                  : argv[4]->text;
2467
0
    rdnss.lifetime = strmatch(lifetime, "infinite")
2468
0
           ? UINT32_MAX
2469
0
           : strtoll(lifetime, NULL, 10);
2470
0
    rdnss.lifetime_set = 1;
2471
0
  }
2472
2473
0
  rtadv_rdnss_set(zif, &rdnss);
2474
2475
0
  return CMD_SUCCESS;
2476
0
}
2477
2478
DEFUN(no_ipv6_nd_rdnss,
2479
      no_ipv6_nd_rdnss_cmd,
2480
      "no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
2481
      NO_STR
2482
      "Interface IPv6 config commands\n"
2483
      "Neighbor discovery\n"
2484
      "Recursive DNS server information\n"
2485
      "IPv6 address\n"
2486
      "Valid lifetime in seconds\n"
2487
      "Infinite valid lifetime\n")
2488
0
{
2489
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
2490
0
  struct zebra_if *zif = ifp->info;
2491
0
  struct rtadv_rdnss rdnss = {};
2492
2493
0
  if (inet_pton(AF_INET6, argv[4]->arg, &rdnss.addr) != 1) {
2494
0
    vty_out(vty, "Malformed IPv6 address\n");
2495
0
    return CMD_WARNING_CONFIG_FAILED;
2496
0
  }
2497
0
  if (rtadv_rdnss_reset(zif, &rdnss) != 1) {
2498
0
    vty_out(vty, "Non-existant RDNSS address\n");
2499
0
    return CMD_WARNING_CONFIG_FAILED;
2500
0
  }
2501
2502
0
  return CMD_SUCCESS;
2503
0
}
2504
2505
DEFUN(ipv6_nd_dnssl,
2506
      ipv6_nd_dnssl_cmd,
2507
      "ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2508
      "Interface IPv6 config commands\n"
2509
      "Neighbor discovery\n"
2510
      "DNS search list information\n"
2511
      "Domain name suffix\n"
2512
      "Valid lifetime in seconds\n"
2513
      "Infinite valid lifetime\n")
2514
0
{
2515
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
2516
0
  struct zebra_if *zif = ifp->info;
2517
0
  struct rtadv_dnssl dnssl = {};
2518
0
  size_t len;
2519
0
  int ret;
2520
2521
0
  len = strlcpy(dnssl.name, argv[3]->arg, sizeof(dnssl.name));
2522
0
  if (len == 0 || len >= sizeof(dnssl.name)) {
2523
0
    vty_out(vty, "Malformed DNS search domain\n");
2524
0
    return CMD_WARNING_CONFIG_FAILED;
2525
0
  }
2526
0
  if (dnssl.name[len - 1] == '.') {
2527
    /*
2528
     * Allow, but don't require, a trailing dot signifying the root
2529
     * zone. Canonicalize by cutting it off if present.
2530
     */
2531
0
    dnssl.name[len - 1] = '\0';
2532
0
    len--;
2533
0
  }
2534
0
  if (argc > 4) {
2535
0
    char *lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
2536
0
                  : argv[4]->text;
2537
0
    dnssl.lifetime = strmatch(lifetime, "infinite")
2538
0
           ? UINT32_MAX
2539
0
           : strtoll(lifetime, NULL, 10);
2540
0
    dnssl.lifetime_set = 1;
2541
0
  }
2542
2543
0
  ret = rtadv_dnssl_encode(dnssl.encoded_name, dnssl.name);
2544
0
  if (ret < 0) {
2545
0
    vty_out(vty, "Malformed DNS search domain\n");
2546
0
    return CMD_WARNING_CONFIG_FAILED;
2547
0
  }
2548
0
  dnssl.encoded_len = ret;
2549
0
  rtadv_dnssl_set(zif, &dnssl);
2550
2551
0
  return CMD_SUCCESS;
2552
0
}
2553
2554
DEFUN(no_ipv6_nd_dnssl,
2555
      no_ipv6_nd_dnssl_cmd,
2556
      "no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
2557
      NO_STR
2558
      "Interface IPv6 config commands\n"
2559
      "Neighbor discovery\n"
2560
      "DNS search list information\n"
2561
      "Domain name suffix\n"
2562
      "Valid lifetime in seconds\n"
2563
      "Infinite valid lifetime\n")
2564
0
{
2565
0
  VTY_DECLVAR_CONTEXT(interface, ifp);
2566
0
  struct zebra_if *zif = ifp->info;
2567
0
  struct rtadv_dnssl dnssl = {};
2568
0
  size_t len;
2569
2570
0
  len = strlcpy(dnssl.name, argv[4]->arg, sizeof(dnssl.name));
2571
0
  if (len == 0 || len >= sizeof(dnssl.name)) {
2572
0
    vty_out(vty, "Malformed DNS search domain\n");
2573
0
    return CMD_WARNING_CONFIG_FAILED;
2574
0
  }
2575
0
  if (dnssl.name[len - 1] == '.') {
2576
0
    dnssl.name[len - 1] = '\0';
2577
0
    len--;
2578
0
  }
2579
0
  if (rtadv_dnssl_reset(zif, &dnssl) != 1) {
2580
0
    vty_out(vty, "Non-existant DNS search domain\n");
2581
0
    return CMD_WARNING_CONFIG_FAILED;
2582
0
  }
2583
2584
0
  return CMD_SUCCESS;
2585
0
}
2586
2587
2588
/* Dump interface ND information to vty. */
2589
static int nd_dump_vty(struct vty *vty, struct interface *ifp)
2590
0
{
2591
0
  struct zebra_if *zif;
2592
0
  struct rtadvconf *rtadv;
2593
0
  int interval;
2594
2595
0
  zif = (struct zebra_if *)ifp->info;
2596
0
  rtadv = &zif->rtadv;
2597
2598
0
  if (rtadv->AdvSendAdvertisements) {
2599
0
    vty_out(vty,
2600
0
      "  ND advertised reachable time is %d milliseconds\n",
2601
0
      rtadv->AdvReachableTime);
2602
0
    vty_out(vty,
2603
0
      "  ND advertised retransmit interval is %u milliseconds\n",
2604
0
      rtadv->AdvRetransTimer);
2605
0
    vty_out(vty, "  ND advertised hop-count limit is %d hops\n",
2606
0
      rtadv->AdvCurHopLimit);
2607
0
    vty_out(vty, "  ND router advertisements sent: %d rcvd: %d\n",
2608
0
      zif->ra_sent, zif->ra_rcvd);
2609
0
    interval = rtadv->MaxRtrAdvInterval;
2610
0
    if (interval % 1000)
2611
0
      vty_out(vty,
2612
0
        "  ND router advertisements are sent every %d milliseconds\n",
2613
0
        interval);
2614
0
    else
2615
0
      vty_out(vty,
2616
0
        "  ND router advertisements are sent every %d seconds\n",
2617
0
        interval / 1000);
2618
0
    if (!rtadv->UseFastRexmit)
2619
0
      vty_out(vty,
2620
0
        "  ND router advertisements do not use fast retransmit\n");
2621
2622
0
    if (rtadv->AdvDefaultLifetime != -1)
2623
0
      vty_out(vty,
2624
0
        "  ND router advertisements live for %d seconds\n",
2625
0
        rtadv->AdvDefaultLifetime);
2626
0
    else
2627
0
      vty_out(vty,
2628
0
        "  ND router advertisements lifetime tracks ra-interval\n");
2629
0
    vty_out(vty,
2630
0
      "  ND router advertisement default router preference is %s\n",
2631
0
      rtadv_pref_strs[rtadv->DefaultPreference]);
2632
0
    if (rtadv->AdvManagedFlag)
2633
0
      vty_out(vty,
2634
0
        "  Hosts use DHCP to obtain routable addresses.\n");
2635
0
    else
2636
0
      vty_out(vty,
2637
0
        "  Hosts use stateless autoconfig for addresses.\n");
2638
0
    if (rtadv->AdvHomeAgentFlag) {
2639
0
      vty_out(vty,
2640
0
        "  ND router advertisements with Home Agent flag bit set.\n");
2641
0
      if (rtadv->HomeAgentLifetime != -1)
2642
0
        vty_out(vty,
2643
0
          "  Home Agent lifetime is %u seconds\n",
2644
0
          rtadv->HomeAgentLifetime);
2645
0
      else
2646
0
        vty_out(vty,
2647
0
          "  Home Agent lifetime tracks ra-lifetime\n");
2648
0
      vty_out(vty, "  Home Agent preference is %u\n",
2649
0
        rtadv->HomeAgentPreference);
2650
0
    }
2651
0
    if (rtadv->AdvIntervalOption)
2652
0
      vty_out(vty,
2653
0
        "  ND router advertisements with Adv. Interval option.\n");
2654
0
  }
2655
0
  return 0;
2656
0
}
2657
2658
2659
/* Write configuration about router advertisement. */
2660
static int rtadv_config_write(struct vty *vty, struct interface *ifp)
2661
0
{
2662
0
  struct zebra_if *zif;
2663
0
  struct listnode *node;
2664
0
  struct rtadv_prefix *rprefix;
2665
0
  struct rtadv_rdnss *rdnss;
2666
0
  struct rtadv_dnssl *dnssl;
2667
0
  int interval;
2668
2669
0
  zif = ifp->info;
2670
2671
0
  if (!if_is_loopback(ifp)) {
2672
0
    if (zif->rtadv.AdvSendAdvertisements
2673
0
        && CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED))
2674
0
      vty_out(vty, " no ipv6 nd suppress-ra\n");
2675
0
  }
2676
2677
0
  interval = zif->rtadv.MaxRtrAdvInterval;
2678
0
  if (CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED)) {
2679
0
    if (interval % 1000)
2680
0
      vty_out(vty, " ipv6 nd ra-interval msec %d\n",
2681
0
        interval);
2682
0
    else if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
2683
0
      vty_out(vty, " ipv6 nd ra-interval %d\n",
2684
0
        interval / 1000);
2685
0
  }
2686
2687
0
  if (zif->rtadv.AdvIntervalOption)
2688
0
    vty_out(vty, " ipv6 nd adv-interval-option\n");
2689
2690
0
  if (!zif->rtadv.UseFastRexmit)
2691
0
    vty_out(vty, " no ipv6 nd ra-fast-retrans\n");
2692
2693
0
  if (zif->rtadv.AdvRetransTimer != 0)
2694
0
    vty_out(vty, " ipv6 nd ra-retrans-interval %u\n",
2695
0
      zif->rtadv.AdvRetransTimer);
2696
2697
0
  if (zif->rtadv.AdvCurHopLimit != RTADV_DEFAULT_HOPLIMIT)
2698
0
    vty_out(vty, " ipv6 nd ra-hop-limit %d\n",
2699
0
      zif->rtadv.AdvCurHopLimit);
2700
2701
0
  if (zif->rtadv.AdvDefaultLifetime != -1)
2702
0
    vty_out(vty, " ipv6 nd ra-lifetime %d\n",
2703
0
      zif->rtadv.AdvDefaultLifetime);
2704
2705
0
  if (zif->rtadv.HomeAgentPreference)
2706
0
    vty_out(vty, " ipv6 nd home-agent-preference %u\n",
2707
0
      zif->rtadv.HomeAgentPreference);
2708
2709
0
  if (zif->rtadv.HomeAgentLifetime != -1)
2710
0
    vty_out(vty, " ipv6 nd home-agent-lifetime %u\n",
2711
0
      zif->rtadv.HomeAgentLifetime);
2712
2713
0
  if (zif->rtadv.AdvHomeAgentFlag)
2714
0
    vty_out(vty, " ipv6 nd home-agent-config-flag\n");
2715
2716
0
  if (zif->rtadv.AdvReachableTime)
2717
0
    vty_out(vty, " ipv6 nd reachable-time %d\n",
2718
0
      zif->rtadv.AdvReachableTime);
2719
2720
0
  if (zif->rtadv.AdvManagedFlag)
2721
0
    vty_out(vty, " ipv6 nd managed-config-flag\n");
2722
2723
0
  if (zif->rtadv.AdvOtherConfigFlag)
2724
0
    vty_out(vty, " ipv6 nd other-config-flag\n");
2725
2726
0
  if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
2727
0
    vty_out(vty, " ipv6 nd router-preference %s\n",
2728
0
      rtadv_pref_strs[zif->rtadv.DefaultPreference]);
2729
2730
0
  if (zif->rtadv.AdvLinkMTU)
2731
0
    vty_out(vty, " ipv6 nd mtu %d\n", zif->rtadv.AdvLinkMTU);
2732
2733
0
  frr_each (rtadv_prefixes, zif->rtadv.prefixes, rprefix) {
2734
0
    if ((rprefix->AdvPrefixCreate == PREFIX_SRC_MANUAL)
2735
0
        || (rprefix->AdvPrefixCreate == PREFIX_SRC_BOTH)) {
2736
0
      vty_out(vty, " ipv6 nd prefix %pFX", &rprefix->prefix);
2737
0
      if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME)
2738
0
          || (rprefix->AdvPreferredLifetime
2739
0
        != RTADV_PREFERRED_LIFETIME)) {
2740
0
        if (rprefix->AdvValidLifetime == UINT32_MAX)
2741
0
          vty_out(vty, " infinite");
2742
0
        else
2743
0
          vty_out(vty, " %u",
2744
0
            rprefix->AdvValidLifetime);
2745
0
        if (rprefix->AdvPreferredLifetime == UINT32_MAX)
2746
0
          vty_out(vty, " infinite");
2747
0
        else
2748
0
          vty_out(vty, " %u",
2749
0
            rprefix->AdvPreferredLifetime);
2750
0
      }
2751
0
      if (!rprefix->AdvOnLinkFlag)
2752
0
        vty_out(vty, " off-link");
2753
0
      if (!rprefix->AdvAutonomousFlag)
2754
0
        vty_out(vty, " no-autoconfig");
2755
0
      if (rprefix->AdvRouterAddressFlag)
2756
0
        vty_out(vty, " router-address");
2757
0
      vty_out(vty, "\n");
2758
0
    }
2759
0
  }
2760
2761
0
  for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvRDNSSList, node, rdnss)) {
2762
0
    char buf[INET6_ADDRSTRLEN];
2763
2764
0
    vty_out(vty, " ipv6 nd rdnss %s",
2765
0
      inet_ntop(AF_INET6, &rdnss->addr, buf, sizeof(buf)));
2766
0
    if (rdnss->lifetime_set) {
2767
0
      if (rdnss->lifetime == UINT32_MAX)
2768
0
        vty_out(vty, " infinite");
2769
0
      else
2770
0
        vty_out(vty, " %u", rdnss->lifetime);
2771
0
    }
2772
0
    vty_out(vty, "\n");
2773
0
  }
2774
0
  for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvDNSSLList, node, dnssl)) {
2775
0
    vty_out(vty, " ipv6 nd dnssl %s", dnssl->name);
2776
0
    if (dnssl->lifetime_set) {
2777
0
      if (dnssl->lifetime == UINT32_MAX)
2778
0
        vty_out(vty, " infinite");
2779
0
      else
2780
0
        vty_out(vty, " %u", dnssl->lifetime);
2781
0
    }
2782
0
    vty_out(vty, "\n");
2783
0
  }
2784
0
  return 0;
2785
0
}
2786
2787
2788
static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val)
2789
0
{
2790
0
  struct rtadv *rtadv;
2791
2792
0
  if (IS_ZEBRA_DEBUG_EVENT) {
2793
0
    struct vrf *vrf = zvrf->vrf;
2794
2795
0
    zlog_debug("%s(%s) with event: %d and val: %d", __func__,
2796
0
         VRF_LOGNAME(vrf), event, val);
2797
0
  }
2798
2799
0
  rtadv = &zvrf->rtadv;
2800
2801
0
  switch (event) {
2802
0
  case RTADV_START:
2803
0
    event_add_read(zrouter.master, rtadv_read, zvrf, rtadv->sock,
2804
0
             &rtadv->ra_read);
2805
0
    event_add_event(zrouter.master, rtadv_timer, zvrf, 0,
2806
0
        &rtadv->ra_timer);
2807
0
    break;
2808
0
  case RTADV_STOP:
2809
0
    EVENT_OFF(rtadv->ra_timer);
2810
0
    EVENT_OFF(rtadv->ra_read);
2811
0
    break;
2812
0
  case RTADV_TIMER:
2813
0
    event_add_timer(zrouter.master, rtadv_timer, zvrf, val,
2814
0
        &rtadv->ra_timer);
2815
0
    break;
2816
0
  case RTADV_TIMER_MSEC:
2817
0
    event_add_timer_msec(zrouter.master, rtadv_timer, zvrf, val,
2818
0
             &rtadv->ra_timer);
2819
0
    break;
2820
0
  case RTADV_READ:
2821
0
    event_add_read(zrouter.master, rtadv_read, zvrf, rtadv->sock,
2822
0
             &rtadv->ra_read);
2823
0
    break;
2824
0
  default:
2825
0
    break;
2826
0
  }
2827
0
  return;
2828
0
}
2829
2830
void rtadv_if_up(struct zebra_if *zif)
2831
0
{
2832
0
  struct zebra_vrf *zvrf = rtadv_interface_get_zvrf(zif->ifp);
2833
2834
  /* Enable fast tx of RA if enabled && RA interval is not in msecs */
2835
0
  if (zif->rtadv.AdvSendAdvertisements &&
2836
0
      (zif->rtadv.MaxRtrAdvInterval >= 1000) &&
2837
0
      zif->rtadv.UseFastRexmit) {
2838
0
    zif->rtadv.inFastRexmit = 1;
2839
0
    zif->rtadv.NumFastReXmitsRemain = RTADV_NUM_FAST_REXMITS;
2840
0
  }
2841
2842
  /*
2843
   * startup the state machine, if it hasn't been already
2844
   * due to a delayed ifindex on startup ordering
2845
   */
2846
0
  if (zif->rtadv.AdvSendAdvertisements)
2847
0
    rtadv_start_interface_events(zvrf, zif);
2848
0
}
2849
2850
void rtadv_if_init(struct zebra_if *zif)
2851
0
{
2852
  /* Set default router advertise values. */
2853
0
  struct rtadvconf *rtadv;
2854
2855
0
  rtadv = &zif->rtadv;
2856
2857
0
  rtadv->AdvSendAdvertisements = 0;
2858
0
  rtadv->MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
2859
0
  rtadv->MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
2860
0
  rtadv->AdvIntervalTimer = 0;
2861
0
  rtadv->AdvManagedFlag = 0;
2862
0
  rtadv->AdvOtherConfigFlag = 0;
2863
0
  rtadv->AdvHomeAgentFlag = 0;
2864
0
  rtadv->AdvLinkMTU = 0;
2865
0
  rtadv->AdvReachableTime = 0;
2866
0
  rtadv->AdvRetransTimer = 0;
2867
0
  rtadv->AdvCurHopLimit = RTADV_DEFAULT_HOPLIMIT;
2868
0
  memset(&rtadv->lastadvcurhoplimit, 0,
2869
0
         sizeof(rtadv->lastadvcurhoplimit));
2870
0
  memset(&rtadv->lastadvmanagedflag, 0,
2871
0
         sizeof(rtadv->lastadvmanagedflag));
2872
0
  memset(&rtadv->lastadvotherconfigflag, 0,
2873
0
         sizeof(rtadv->lastadvotherconfigflag));
2874
0
  memset(&rtadv->lastadvreachabletime, 0,
2875
0
         sizeof(rtadv->lastadvreachabletime));
2876
0
  memset(&rtadv->lastadvretranstimer, 0,
2877
0
         sizeof(rtadv->lastadvretranstimer));
2878
0
  rtadv->AdvDefaultLifetime = -1; /* derive from MaxRtrAdvInterval */
2879
0
  rtadv->HomeAgentPreference = 0;
2880
0
  rtadv->HomeAgentLifetime = -1; /* derive from AdvDefaultLifetime */
2881
0
  rtadv->AdvIntervalOption = 0;
2882
0
  rtadv->UseFastRexmit = true;
2883
0
  rtadv->DefaultPreference = RTADV_PREF_MEDIUM;
2884
2885
0
  rtadv_prefixes_init(rtadv->prefixes);
2886
2887
0
  rtadv->AdvRDNSSList = list_new();
2888
0
  rtadv->AdvDNSSLList = list_new();
2889
0
}
2890
2891
void rtadv_if_fini(struct zebra_if *zif)
2892
0
{
2893
0
  struct rtadvconf *rtadv;
2894
0
  struct rtadv_prefix *rp;
2895
2896
0
  rtadv = &zif->rtadv;
2897
2898
0
  while ((rp = rtadv_prefixes_pop(rtadv->prefixes)))
2899
0
    rtadv_prefix_free(rp);
2900
2901
0
  list_delete(&rtadv->AdvRDNSSList);
2902
0
  list_delete(&rtadv->AdvDNSSLList);
2903
0
}
2904
2905
void rtadv_vrf_init(struct zebra_vrf *zvrf)
2906
1
{
2907
1
  if (!vrf_is_backend_netns() && (zvrf_id(zvrf) != VRF_DEFAULT))
2908
0
    return;
2909
2910
1
  zvrf->rtadv.sock = rtadv_make_socket(zvrf->zns->ns_id);
2911
1
}
2912
2913
void rtadv_vrf_terminate(struct zebra_vrf *zvrf)
2914
0
{
2915
0
  if (!vrf_is_backend_netns() && (zvrf_id(zvrf) != VRF_DEFAULT))
2916
0
    return;
2917
2918
0
  rtadv_event(zvrf, RTADV_STOP, 0);
2919
0
  if (zvrf->rtadv.sock >= 0) {
2920
0
    close(zvrf->rtadv.sock);
2921
0
    zvrf->rtadv.sock = -1;
2922
0
  }
2923
2924
0
  adv_if_clean(zvrf);
2925
0
  adv_msec_if_clean(zvrf);
2926
0
}
2927
2928
void rtadv_cmd_init(void)
2929
0
{
2930
0
  interfaces_configured_for_ra_from_bgp = 0;
2931
2932
0
  hook_register(zebra_if_extra_info, nd_dump_vty);
2933
0
  hook_register(zebra_if_config_wr, rtadv_config_write);
2934
2935
0
  install_element(VIEW_NODE, &show_ipv6_nd_ra_if_cmd);
2936
2937
0
  install_element(INTERFACE_NODE, &ipv6_nd_ra_fast_retrans_cmd);
2938
0
  install_element(INTERFACE_NODE, &no_ipv6_nd_ra_fast_retrans_cmd);
2939
0
  install_element(INTERFACE_NODE, &ipv6_nd_ra_retrans_interval_cmd);
2940
0
  install_element(INTERFACE_NODE, &no_ipv6_nd_ra_retrans_interval_cmd);
2941
0
  install_element(INTERFACE_NODE, &ipv6_nd_ra_hop_limit_cmd);
2942
0
  install_element(INTERFACE_NODE, &no_ipv6_nd_ra_hop_limit_cmd);
2943
0
  install_element(INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
2944
0
  install_element(INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
2945
0
  install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
2946
0
  install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
2947
0
  install_element(INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
2948
0
  install_element(INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
2949
0
  install_element(INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
2950
0
  install_element(INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
2951
0
  install_element(INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
2952
0
  install_element(INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
2953
0
  install_element(INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
2954
0
  install_element(INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
2955
0
  install_element(INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
2956
0
  install_element(INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
2957
0
  install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
2958
0
  install_element(INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
2959
0
  install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
2960
0
  install_element(INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
2961
0
  install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
2962
0
  install_element(INTERFACE_NODE,
2963
0
      &ipv6_nd_adv_interval_config_option_cmd);
2964
0
  install_element(INTERFACE_NODE,
2965
0
      &no_ipv6_nd_adv_interval_config_option_cmd);
2966
0
  install_element(INTERFACE_NODE, &ipv6_nd_prefix_cmd);
2967
0
  install_element(INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
2968
0
  install_element(INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
2969
0
  install_element(INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
2970
0
  install_element(INTERFACE_NODE, &ipv6_nd_mtu_cmd);
2971
0
  install_element(INTERFACE_NODE, &no_ipv6_nd_mtu_cmd);
2972
0
  install_element(INTERFACE_NODE, &ipv6_nd_rdnss_cmd);
2973
0
  install_element(INTERFACE_NODE, &no_ipv6_nd_rdnss_cmd);
2974
0
  install_element(INTERFACE_NODE, &ipv6_nd_dnssl_cmd);
2975
0
  install_element(INTERFACE_NODE, &no_ipv6_nd_dnssl_cmd);
2976
0
}
2977
2978
static int if_join_all_router(int sock, struct interface *ifp)
2979
0
{
2980
0
  int ret;
2981
2982
0
  struct ipv6_mreq mreq;
2983
2984
0
  memset(&mreq, 0, sizeof(mreq));
2985
0
  inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
2986
0
  mreq.ipv6mr_interface = ifp->ifindex;
2987
2988
0
  ret = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mreq,
2989
0
       sizeof(mreq));
2990
0
  if (ret < 0)
2991
0
    flog_err_sys(EC_LIB_SOCKET,
2992
0
           "%s(%u): Failed to join group, socket %u error %s",
2993
0
           ifp->name, ifp->ifindex, sock,
2994
0
           safe_strerror(errno));
2995
2996
0
  if (IS_ZEBRA_DEBUG_EVENT)
2997
0
    zlog_debug(
2998
0
      "%s(%s:%u): Join All-Routers multicast group, socket %u",
2999
0
      ifp->name, ifp->vrf->name, ifp->ifindex, sock);
3000
3001
0
  return 0;
3002
0
}
3003
3004
static int if_leave_all_router(int sock, struct interface *ifp)
3005
0
{
3006
0
  int ret;
3007
3008
0
  struct ipv6_mreq mreq;
3009
3010
0
  memset(&mreq, 0, sizeof(mreq));
3011
0
  inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
3012
0
  mreq.ipv6mr_interface = ifp->ifindex;
3013
3014
0
  ret = setsockopt(sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, (char *)&mreq,
3015
0
       sizeof(mreq));
3016
0
  if (ret < 0)
3017
0
    flog_err_sys(
3018
0
      EC_LIB_SOCKET,
3019
0
      "%s(%s:%u): Failed to leave group, socket %u error %s",
3020
0
      ifp->name, ifp->vrf->name, ifp->ifindex, sock,
3021
0
      safe_strerror(errno));
3022
3023
0
  if (IS_ZEBRA_DEBUG_EVENT)
3024
0
    zlog_debug(
3025
0
      "%s(%s:%u): Leave All-Routers multicast group, socket %u",
3026
0
      ifp->name, ifp->vrf->name, ifp->ifindex, sock);
3027
3028
0
  return 0;
3029
0
}
3030
3031
bool rtadv_compiled_in(void)
3032
0
{
3033
0
  return true;
3034
0
}
3035
3036
#else /* !HAVE_RTADV */
3037
/*
3038
 * If the end user does not have RADV enabled we should
3039
 * handle this better
3040
 */
3041
void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS)
3042
{
3043
  if (IS_ZEBRA_DEBUG_PACKET)
3044
    zlog_debug(
3045
      "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
3046
      zserv_command_string(hdr->command));
3047
3048
  return;
3049
}
3050
3051
void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS)
3052
{
3053
  if (IS_ZEBRA_DEBUG_PACKET)
3054
    zlog_debug(
3055
      "Received %s command, but ZEBRA is not compiled with Router Advertisements on",
3056
      zserv_command_string(hdr->command));
3057
3058
  return;
3059
}
3060
3061
bool rtadv_compiled_in(void)
3062
{
3063
  return false;
3064
}
3065
3066
#endif /* HAVE_RTADV */
3067
3068
uint32_t rtadv_get_interfaces_configured_from_bgp(void)
3069
0
{
3070
0
  return interfaces_configured_for_ra_from_bgp;
3071
0
}