Coverage Report

Created: 2025-08-28 06:29

/src/frr/pimd/pim_iface.c
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 * PIM for Quagga
4
 * Copyright (C) 2008  Everton da Silva Marques
5
 */
6
7
#include <zebra.h>
8
9
#include "if.h"
10
#include "log.h"
11
#include "vty.h"
12
#include "memory.h"
13
#include "prefix.h"
14
#include "vrf.h"
15
#include "linklist.h"
16
#include "plist.h"
17
#include "hash.h"
18
#include "ferr.h"
19
#include "network.h"
20
21
#include "pimd.h"
22
#include "pim_instance.h"
23
#include "pim_zebra.h"
24
#include "pim_iface.h"
25
#include "pim_igmp.h"
26
#include "pim_mroute.h"
27
#include "pim_oil.h"
28
#include "pim_str.h"
29
#include "pim_pim.h"
30
#include "pim_neighbor.h"
31
#include "pim_ifchannel.h"
32
#include "pim_sock.h"
33
#include "pim_time.h"
34
#include "pim_ssmpingd.h"
35
#include "pim_rp.h"
36
#include "pim_nht.h"
37
#include "pim_jp_agg.h"
38
#include "pim_igmp_join.h"
39
#include "pim_vxlan.h"
40
41
#include "pim6_mld.h"
42
43
static void pim_if_gm_join_del_all(struct interface *ifp);
44
45
static int gm_join_sock(const char *ifname, ifindex_t ifindex,
46
      pim_addr group_addr, pim_addr source_addr,
47
      struct pim_interface *pim_ifp);
48
49
void pim_if_init(struct pim_instance *pim)
50
1
{
51
1
  int i;
52
53
33
  for (i = 0; i < MAXVIFS; i++)
54
32
    pim->iface_vif_index[i] = 0;
55
1
}
56
57
void pim_if_terminate(struct pim_instance *pim)
58
0
{
59
0
  struct interface *ifp;
60
61
0
  FOR_ALL_INTERFACES (pim->vrf, ifp) {
62
0
    struct pim_interface *pim_ifp = ifp->info;
63
64
0
    if (!pim_ifp)
65
0
      continue;
66
67
0
    pim_if_delete(ifp);
68
0
  }
69
0
  return;
70
0
}
71
72
static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr)
73
0
{
74
0
  XFREE(MTYPE_PIM_SEC_ADDR, sec_addr);
75
0
}
76
77
__attribute__((unused))
78
static int pim_sec_addr_comp(const void *p1, const void *p2)
79
0
{
80
0
  const struct pim_secondary_addr *sec1 = p1;
81
0
  const struct pim_secondary_addr *sec2 = p2;
82
83
0
  if (sec1->addr.family == AF_INET && sec2->addr.family == AF_INET6)
84
0
    return -1;
85
86
0
  if (sec1->addr.family == AF_INET6 && sec2->addr.family == AF_INET)
87
0
    return 1;
88
89
0
  if (sec1->addr.family == AF_INET) {
90
0
    if (ntohl(sec1->addr.u.prefix4.s_addr)
91
0
        < ntohl(sec2->addr.u.prefix4.s_addr))
92
0
      return -1;
93
94
0
    if (ntohl(sec1->addr.u.prefix4.s_addr)
95
0
        > ntohl(sec2->addr.u.prefix4.s_addr))
96
0
      return 1;
97
0
  } else {
98
0
    return memcmp(&sec1->addr.u.prefix6, &sec2->addr.u.prefix6,
99
0
            sizeof(struct in6_addr));
100
0
  }
101
102
0
  return 0;
103
0
}
104
105
struct pim_interface *pim_if_new(struct interface *ifp, bool gm, bool pim,
106
         bool ispimreg, bool is_vxlan_term)
107
2
{
108
2
  struct pim_interface *pim_ifp;
109
110
2
  assert(ifp);
111
2
  assert(!ifp->info);
112
113
2
  pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp));
114
115
2
  pim_ifp->pim = ifp->vrf->info;
116
2
  pim_ifp->mroute_vif_index = -1;
117
118
2
  pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
119
2
  pim_ifp->mld_version = MLD_DEFAULT_VERSION;
120
2
  pim_ifp->gm_default_robustness_variable =
121
2
    GM_DEFAULT_ROBUSTNESS_VARIABLE;
122
2
  pim_ifp->gm_default_query_interval = GM_GENERAL_QUERY_INTERVAL;
123
2
  pim_ifp->gm_query_max_response_time_dsec =
124
2
    GM_QUERY_MAX_RESPONSE_TIME_DSEC;
125
2
  pim_ifp->gm_specific_query_max_response_time_dsec =
126
2
    GM_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC;
127
2
  pim_ifp->gm_last_member_query_count = GM_DEFAULT_ROBUSTNESS_VARIABLE;
128
129
  /* BSM config on interface: true by default */
130
2
  pim_ifp->bsm_enable = true;
131
2
  pim_ifp->ucast_bsm_accept = true;
132
2
  pim_ifp->am_i_dr = false;
133
134
  /*
135
    RFC 3376: 8.3. Query Response Interval
136
    The number of seconds represented by the [Query Response Interval]
137
    must be less than the [Query Interval].
138
   */
139
2
  assert(pim_ifp->gm_query_max_response_time_dsec <
140
2
         pim_ifp->gm_default_query_interval);
141
142
2
  pim_ifp->pim_enable = pim;
143
2
  pim_ifp->pim_passive_enable = false;
144
2
  pim_ifp->gm_enable = gm;
145
146
2
  pim_ifp->gm_join_list = NULL;
147
2
  pim_ifp->pim_neighbor_list = NULL;
148
2
  pim_ifp->upstream_switch_list = NULL;
149
2
  pim_ifp->pim_generation_id = 0;
150
151
  /* list of struct gm_sock */
152
2
  pim_igmp_if_init(pim_ifp, ifp);
153
154
  /* list of struct pim_neighbor */
155
2
  pim_ifp->pim_neighbor_list = list_new();
156
2
  pim_ifp->pim_neighbor_list->del = (void (*)(void *))pim_neighbor_free;
157
158
2
  pim_ifp->upstream_switch_list = list_new();
159
2
  pim_ifp->upstream_switch_list->del =
160
2
    (void (*)(void *))pim_jp_agg_group_list_free;
161
2
  pim_ifp->upstream_switch_list->cmp = pim_jp_agg_group_list_cmp;
162
163
2
  pim_ifp->sec_addr_list = list_new();
164
2
  pim_ifp->sec_addr_list->del = (void (*)(void *))pim_sec_addr_free;
165
2
  pim_ifp->sec_addr_list->cmp =
166
2
    (int (*)(void *, void *))pim_sec_addr_comp;
167
168
2
  pim_ifp->activeactive = false;
169
170
2
  RB_INIT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
171
172
2
  ifp->info = pim_ifp;
173
174
2
  pim_sock_reset(ifp);
175
176
2
  pim_if_add_vif(ifp, ispimreg, is_vxlan_term);
177
2
  pim_ifp->pim->mcast_if_count++;
178
179
2
  return pim_ifp;
180
2
}
181
182
void pim_if_delete(struct interface *ifp)
183
0
{
184
0
  struct pim_interface *pim_ifp;
185
186
0
  assert(ifp);
187
0
  pim_ifp = ifp->info;
188
0
  assert(pim_ifp);
189
190
0
  pim_ifp->pim->mcast_if_count--;
191
0
  if (pim_ifp->gm_join_list) {
192
0
    pim_if_gm_join_del_all(ifp);
193
0
  }
194
195
0
  pim_ifchannel_delete_all(ifp);
196
0
#if PIM_IPV == 4
197
0
  igmp_sock_delete_all(ifp);
198
0
#endif
199
0
  if (pim_ifp->pim_sock_fd >= 0)
200
0
    pim_sock_delete(ifp, "Interface removed from configuration");
201
202
0
  pim_if_del_vif(ifp);
203
204
0
  pim_igmp_if_fini(pim_ifp);
205
206
0
  list_delete(&pim_ifp->pim_neighbor_list);
207
0
  list_delete(&pim_ifp->upstream_switch_list);
208
0
  list_delete(&pim_ifp->sec_addr_list);
209
210
0
  if (pim_ifp->bfd_config.profile)
211
0
    XFREE(MTYPE_TMP, pim_ifp->bfd_config.profile);
212
213
0
  XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
214
0
  XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
215
216
0
  ifp->info = NULL;
217
0
}
218
219
void pim_if_update_could_assert(struct interface *ifp)
220
3
{
221
3
  struct pim_interface *pim_ifp;
222
3
  struct pim_ifchannel *ch;
223
224
3
  pim_ifp = ifp->info;
225
3
  assert(pim_ifp);
226
227
3
  RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
228
0
    pim_ifchannel_update_could_assert(ch);
229
0
  }
230
3
}
231
232
static void pim_if_update_my_assert_metric(struct interface *ifp)
233
0
{
234
0
  struct pim_interface *pim_ifp;
235
0
  struct pim_ifchannel *ch;
236
237
0
  pim_ifp = ifp->info;
238
0
  assert(pim_ifp);
239
240
0
  RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
241
0
    pim_ifchannel_update_my_assert_metric(ch);
242
0
  }
243
0
}
244
245
static void pim_addr_change(struct interface *ifp)
246
0
{
247
0
  struct pim_interface *pim_ifp;
248
249
0
  pim_ifp = ifp->info;
250
0
  assert(pim_ifp);
251
252
0
  pim_if_dr_election(ifp); /* router's own DR Priority (addr) changes --
253
            Done TODO T30 */
254
0
  pim_if_update_join_desired(pim_ifp); /* depends on DR */
255
0
  pim_if_update_could_assert(ifp);     /* depends on DR */
256
0
  pim_if_update_my_assert_metric(ifp); /* depends on could_assert */
257
0
  pim_if_update_assert_tracking_desired(
258
0
    ifp); /* depends on DR, join_desired */
259
260
  /*
261
    RFC 4601: 4.3.1.  Sending Hello Messages
262
263
    1) Before an interface goes down or changes primary IP address, a
264
    Hello message with a zero HoldTime should be sent immediately
265
    (with the old IP address if the IP address changed).
266
    -- Done at the caller of the function as new ip already updated here
267
268
    2) After an interface has changed its IP address, it MUST send a
269
    Hello message with its new IP address.
270
    -- DONE below
271
272
    3) If an interface changes one of its secondary IP addresses, a
273
    Hello message with an updated Address_List option and a non-zero
274
    HoldTime should be sent immediately.
275
    -- FIXME See TODO T31
276
   */
277
0
  PIM_IF_FLAG_UNSET_HELLO_SENT(pim_ifp->flags);
278
0
  if (pim_ifp->pim_sock_fd < 0)
279
0
    return;
280
0
  pim_hello_restart_now(ifp); /* send hello and restart timer */
281
0
}
282
283
static int detect_primary_address_change(struct interface *ifp,
284
           int force_prim_as_any,
285
           const char *caller)
286
0
{
287
0
  struct pim_interface *pim_ifp = ifp->info;
288
0
  pim_addr new_prim_addr;
289
0
  int changed;
290
291
0
  if (force_prim_as_any)
292
0
    new_prim_addr = PIMADDR_ANY;
293
0
  else
294
0
    new_prim_addr = pim_find_primary_addr(ifp);
295
296
0
  changed = pim_addr_cmp(new_prim_addr, pim_ifp->primary_address);
297
298
0
  if (PIM_DEBUG_ZEBRA)
299
0
    zlog_debug("%s: old=%pPA new=%pPA on interface %s: %s",
300
0
         __func__, &pim_ifp->primary_address, &new_prim_addr,
301
0
         ifp->name, changed ? "changed" : "unchanged");
302
303
0
  if (changed) {
304
    /* Before updating pim_ifp send Hello time with 0 hold time */
305
0
    if (pim_ifp->pim_enable) {
306
0
      pim_hello_send(ifp, 0 /* zero-sec holdtime */);
307
0
    }
308
0
    pim_ifp->primary_address = new_prim_addr;
309
0
  }
310
311
0
  return changed;
312
0
}
313
314
static struct pim_secondary_addr *
315
pim_sec_addr_find(struct pim_interface *pim_ifp, struct prefix *addr)
316
0
{
317
0
  struct pim_secondary_addr *sec_addr;
318
0
  struct listnode *node;
319
320
0
  for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) {
321
0
    if (prefix_cmp(&sec_addr->addr, addr) == 0) {
322
0
      return sec_addr;
323
0
    }
324
0
  }
325
326
0
  return NULL;
327
0
}
328
329
static void pim_sec_addr_del(struct pim_interface *pim_ifp,
330
           struct pim_secondary_addr *sec_addr)
331
0
{
332
0
  listnode_delete(pim_ifp->sec_addr_list, sec_addr);
333
0
  pim_sec_addr_free(sec_addr);
334
0
}
335
336
static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct prefix *addr)
337
0
{
338
0
  int changed = 0;
339
0
  struct pim_secondary_addr *sec_addr;
340
341
0
  sec_addr = pim_sec_addr_find(pim_ifp, addr);
342
0
  if (sec_addr) {
343
0
    sec_addr->flags &= ~PIM_SEC_ADDRF_STALE;
344
0
    return changed;
345
0
  }
346
347
0
  sec_addr = XCALLOC(MTYPE_PIM_SEC_ADDR, sizeof(*sec_addr));
348
349
0
  changed = 1;
350
0
  sec_addr->addr = *addr;
351
0
  listnode_add_sort(pim_ifp->sec_addr_list, sec_addr);
352
353
0
  return changed;
354
0
}
355
356
static int pim_sec_addr_del_all(struct pim_interface *pim_ifp)
357
0
{
358
0
  int changed = 0;
359
360
0
  if (!list_isempty(pim_ifp->sec_addr_list)) {
361
0
    changed = 1;
362
    /* remove all nodes and free up the list itself */
363
0
    list_delete_all_node(pim_ifp->sec_addr_list);
364
0
  }
365
366
0
  return changed;
367
0
}
368
369
static int pim_sec_addr_update(struct interface *ifp)
370
0
{
371
0
  struct pim_interface *pim_ifp = ifp->info;
372
0
  struct connected *ifc;
373
0
  struct listnode *node;
374
0
  struct listnode *nextnode;
375
0
  struct pim_secondary_addr *sec_addr;
376
0
  int changed = 0;
377
378
0
  for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) {
379
0
    sec_addr->flags |= PIM_SEC_ADDRF_STALE;
380
0
  }
381
382
0
  for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
383
0
    pim_addr addr = pim_addr_from_prefix(ifc->address);
384
385
0
    if (pim_addr_is_any(addr))
386
0
      continue;
387
388
0
    if (!pim_addr_cmp(addr, pim_ifp->primary_address)) {
389
      /* don't add the primary address into the secondary
390
       * address list */
391
0
      continue;
392
0
    }
393
394
0
    if (pim_sec_addr_add(pim_ifp, ifc->address)) {
395
0
      changed = 1;
396
0
    }
397
0
  }
398
399
  /* Drop stale entries */
400
0
  for (ALL_LIST_ELEMENTS(pim_ifp->sec_addr_list, node, nextnode,
401
0
             sec_addr)) {
402
0
    if (sec_addr->flags & PIM_SEC_ADDRF_STALE) {
403
0
      pim_sec_addr_del(pim_ifp, sec_addr);
404
0
      changed = 1;
405
0
    }
406
0
  }
407
408
0
  return changed;
409
0
}
410
411
static int detect_secondary_address_change(struct interface *ifp,
412
             int force_prim_as_any,
413
             const char *caller)
414
0
{
415
0
  struct pim_interface *pim_ifp = ifp->info;
416
0
  int changed = 0;
417
418
0
  if (force_prim_as_any) {
419
    /* if primary address is being forced to zero just flush the
420
     * secondary address list */
421
0
    changed = pim_sec_addr_del_all(pim_ifp);
422
0
  } else {
423
    /* re-evaluate the secondary address list */
424
0
    changed = pim_sec_addr_update(ifp);
425
0
  }
426
427
0
  return changed;
428
0
}
429
430
static void detect_address_change(struct interface *ifp, int force_prim_as_any,
431
          const char *caller)
432
0
{
433
0
  int changed = 0;
434
0
  struct pim_interface *pim_ifp;
435
436
0
  pim_ifp = ifp->info;
437
0
  if (!pim_ifp)
438
0
    return;
439
440
0
  if (detect_primary_address_change(ifp, force_prim_as_any, caller)) {
441
0
    changed = 1;
442
0
  }
443
444
0
  if (detect_secondary_address_change(ifp, force_prim_as_any, caller)) {
445
0
    changed = 1;
446
0
  }
447
448
449
0
  if (changed) {
450
0
    if (!pim_ifp->pim_enable) {
451
0
      return;
452
0
    }
453
454
0
    pim_addr_change(ifp);
455
0
  }
456
457
  /* XXX: if we have unnumbered interfaces we need to run detect address
458
   * address change on all of them when the lo address changes */
459
0
}
460
461
int pim_update_source_set(struct interface *ifp, pim_addr source)
462
0
{
463
0
  struct pim_interface *pim_ifp = ifp->info;
464
465
0
  if (!pim_ifp) {
466
0
    return PIM_IFACE_NOT_FOUND;
467
0
  }
468
469
0
  if (!pim_addr_cmp(pim_ifp->update_source, source)) {
470
0
    return PIM_UPDATE_SOURCE_DUP;
471
0
  }
472
473
0
  pim_ifp->update_source = source;
474
0
  detect_address_change(ifp, 0 /* force_prim_as_any */, __func__);
475
476
0
  return PIM_SUCCESS;
477
0
}
478
479
void pim_if_addr_add(struct connected *ifc)
480
0
{
481
0
  struct pim_interface *pim_ifp;
482
0
  struct interface *ifp;
483
0
  bool vxlan_term;
484
485
0
  assert(ifc);
486
487
0
  ifp = ifc->ifp;
488
0
  assert(ifp);
489
0
  pim_ifp = ifp->info;
490
0
  if (!pim_ifp)
491
0
    return;
492
493
0
  if (!if_is_operative(ifp))
494
0
    return;
495
496
0
  if (PIM_DEBUG_ZEBRA)
497
0
    zlog_debug("%s: %s ifindex=%d connected IP address %pFX %s",
498
0
         __func__, ifp->name, ifp->ifindex, ifc->address,
499
0
         CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
500
0
           ? "secondary"
501
0
           : "primary");
502
#if PIM_IPV != 4
503
  if (IN6_IS_ADDR_LINKLOCAL(&ifc->address->u.prefix6) ||
504
      IN6_IS_ADDR_LOOPBACK(&ifc->address->u.prefix6)) {
505
    if (IN6_IS_ADDR_UNSPECIFIED(&pim_ifp->ll_lowest))
506
      pim_ifp->ll_lowest = ifc->address->u.prefix6;
507
    else if (IPV6_ADDR_CMP(&ifc->address->u.prefix6,
508
               &pim_ifp->ll_lowest) < 0)
509
      pim_ifp->ll_lowest = ifc->address->u.prefix6;
510
511
    if (IPV6_ADDR_CMP(&ifc->address->u.prefix6,
512
          &pim_ifp->ll_highest) > 0)
513
      pim_ifp->ll_highest = ifc->address->u.prefix6;
514
515
    if (PIM_DEBUG_ZEBRA)
516
      zlog_debug(
517
        "%s: new link-local %pI6, lowest now %pI6, highest %pI6",
518
        ifc->ifp->name, &ifc->address->u.prefix6,
519
        &pim_ifp->ll_lowest, &pim_ifp->ll_highest);
520
  }
521
#endif
522
523
0
  detect_address_change(ifp, 0, __func__);
524
525
  // if (ifc->address->family != AF_INET)
526
  //  return;
527
528
0
#if PIM_IPV == 4
529
0
  struct in_addr ifaddr = ifc->address->u.prefix4;
530
531
0
  if (pim_ifp->gm_enable) {
532
0
    struct gm_sock *igmp;
533
534
    /* lookup IGMP socket */
535
0
    igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list,
536
0
               ifaddr);
537
0
    if (!igmp) {
538
      /* if addr new, add IGMP socket */
539
0
      if (ifc->address->family == AF_INET)
540
0
        pim_igmp_sock_add(pim_ifp->gm_socket_list,
541
0
              ifaddr, ifp, false);
542
0
    } else if (igmp->mtrace_only) {
543
0
      igmp_sock_delete(igmp);
544
0
      pim_igmp_sock_add(pim_ifp->gm_socket_list, ifaddr, ifp,
545
0
            false);
546
0
    }
547
548
    /* Replay Static IGMP groups */
549
0
    if (pim_ifp->gm_join_list) {
550
0
      struct listnode *node;
551
0
      struct listnode *nextnode;
552
0
      struct gm_join *ij;
553
0
      int join_fd;
554
555
0
      for (ALL_LIST_ELEMENTS(pim_ifp->gm_join_list, node,
556
0
                 nextnode, ij)) {
557
        /* Close socket and reopen with Source and Group
558
         */
559
0
        close(ij->sock_fd);
560
0
        join_fd = gm_join_sock(
561
0
          ifp->name, ifp->ifindex, ij->group_addr,
562
0
          ij->source_addr, pim_ifp);
563
0
        if (join_fd < 0) {
564
0
          char group_str[INET_ADDRSTRLEN];
565
0
          char source_str[INET_ADDRSTRLEN];
566
0
          pim_inet4_dump("<grp?>", ij->group_addr,
567
0
                   group_str,
568
0
                   sizeof(group_str));
569
0
          pim_inet4_dump(
570
0
            "<src?>", ij->source_addr,
571
0
            source_str, sizeof(source_str));
572
0
          zlog_warn(
573
0
            "%s: gm_join_sock() failure for IGMP group %s source %s on interface %s",
574
0
            __func__, group_str, source_str,
575
0
            ifp->name);
576
          /* warning only */
577
0
        } else
578
0
          ij->sock_fd = join_fd;
579
0
      }
580
0
    }
581
0
  } /* igmp */
582
0
  else {
583
0
    struct gm_sock *igmp;
584
585
    /* lookup IGMP socket */
586
0
    igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list,
587
0
               ifaddr);
588
0
    if (ifc->address->family == AF_INET) {
589
0
      if (igmp)
590
0
        igmp_sock_delete(igmp);
591
      /* if addr new, add IGMP socket */
592
0
      pim_igmp_sock_add(pim_ifp->gm_socket_list, ifaddr, ifp,
593
0
            true);
594
0
    }
595
0
  } /* igmp mtrace only */
596
0
#endif
597
598
0
  if (pim_ifp->pim_enable) {
599
600
0
    if (!pim_addr_is_any(pim_ifp->primary_address)) {
601
602
      /* Interface has a valid socket ? */
603
0
      if (pim_ifp->pim_sock_fd < 0) {
604
0
        if (pim_sock_add(ifp)) {
605
0
          zlog_warn(
606
0
            "Failure creating PIM socket for interface %s",
607
0
            ifp->name);
608
0
        }
609
0
      }
610
0
      struct pim_nexthop_cache *pnc = NULL;
611
0
      struct pim_rpf rpf;
612
0
      struct zclient *zclient = NULL;
613
614
0
      zclient = pim_zebra_zclient_get();
615
      /* RP config might come prior to (local RP's interface)
616
         IF UP event.
617
         In this case, pnc would not have pim enabled
618
         nexthops.
619
         Once Interface is UP and pim info is available,
620
         reregister
621
         with RNH address to receive update and add the
622
         interface as nexthop. */
623
0
      memset(&rpf, 0, sizeof(struct pim_rpf));
624
0
      rpf.rpf_addr = pim_addr_from_prefix(ifc->address);
625
0
      pnc = pim_nexthop_cache_find(pim_ifp->pim, &rpf);
626
0
      if (pnc)
627
0
        pim_sendmsg_zebra_rnh(pim_ifp->pim, zclient,
628
0
                  pnc,
629
0
                  ZEBRA_NEXTHOP_REGISTER);
630
0
    }
631
0
  } /* pim */
632
633
  /*
634
    PIM or IGMP is enabled on interface, and there is at least one
635
    address assigned, then try to create a vif_index.
636
  */
637
0
  if (pim_ifp->mroute_vif_index < 0) {
638
0
    vxlan_term = pim_vxlan_is_term_dev_cfg(pim_ifp->pim, ifp);
639
0
    pim_if_add_vif(ifp, false, vxlan_term);
640
0
  }
641
0
  gm_ifp_update(ifp);
642
0
  pim_ifchannel_scan_forward_start(ifp);
643
0
}
644
645
static void pim_if_addr_del_igmp(struct connected *ifc)
646
0
{
647
0
#if PIM_IPV == 4
648
0
  struct pim_interface *pim_ifp = ifc->ifp->info;
649
0
  struct gm_sock *igmp;
650
0
  struct in_addr ifaddr;
651
652
0
  if (ifc->address->family != AF_INET) {
653
    /* non-IPv4 address */
654
0
    return;
655
0
  }
656
657
0
  if (!pim_ifp) {
658
    /* IGMP not enabled on interface */
659
0
    return;
660
0
  }
661
662
0
  ifaddr = ifc->address->u.prefix4;
663
664
  /* lookup IGMP socket */
665
0
  igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list, ifaddr);
666
0
  if (igmp) {
667
    /* if addr found, del IGMP socket */
668
0
    igmp_sock_delete(igmp);
669
0
  }
670
0
#endif
671
0
}
672
673
static void pim_if_addr_del_pim(struct connected *ifc)
674
0
{
675
0
  struct pim_interface *pim_ifp = ifc->ifp->info;
676
677
0
  if (ifc->address->family != PIM_AF) {
678
    /* non-IPv4 address */
679
0
    return;
680
0
  }
681
682
0
  if (!pim_ifp) {
683
    /* PIM not enabled on interface */
684
0
    return;
685
0
  }
686
687
0
  if (!pim_addr_is_any(pim_ifp->primary_address)) {
688
    /* Interface keeps a valid primary address */
689
0
    return;
690
0
  }
691
692
0
  if (pim_ifp->pim_sock_fd < 0) {
693
    /* Interface does not hold a valid socket any longer */
694
0
    return;
695
0
  }
696
697
  /*
698
    pim_sock_delete() closes the socket, stops read and timer threads,
699
    and kills all neighbors.
700
   */
701
0
  pim_sock_delete(ifc->ifp,
702
0
      "last address has been removed from interface");
703
0
}
704
705
void pim_if_addr_del(struct connected *ifc, int force_prim_as_any)
706
0
{
707
0
  struct interface *ifp;
708
709
0
  assert(ifc);
710
0
  ifp = ifc->ifp;
711
0
  assert(ifp);
712
713
0
  if (PIM_DEBUG_ZEBRA)
714
0
    zlog_debug("%s: %s ifindex=%d disconnected IP address %pFX %s",
715
0
         __func__, ifp->name, ifp->ifindex, ifc->address,
716
0
         CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
717
0
           ? "secondary"
718
0
           : "primary");
719
720
#if PIM_IPV == 6
721
  struct pim_interface *pim_ifp = ifc->ifp->info;
722
723
  if (pim_ifp &&
724
      (!IPV6_ADDR_CMP(&ifc->address->u.prefix6, &pim_ifp->ll_lowest) ||
725
       !IPV6_ADDR_CMP(&ifc->address->u.prefix6, &pim_ifp->ll_highest))) {
726
    struct listnode *cnode;
727
    struct connected *cc;
728
729
    memset(&pim_ifp->ll_lowest, 0xff, sizeof(pim_ifp->ll_lowest));
730
    memset(&pim_ifp->ll_highest, 0, sizeof(pim_ifp->ll_highest));
731
732
    for (ALL_LIST_ELEMENTS_RO(ifc->ifp->connected, cnode, cc)) {
733
      if (!IN6_IS_ADDR_LINKLOCAL(&cc->address->u.prefix6) &&
734
          !IN6_IS_ADDR_LOOPBACK(&cc->address->u.prefix6))
735
        continue;
736
737
      if (IPV6_ADDR_CMP(&cc->address->u.prefix6,
738
            &pim_ifp->ll_lowest) < 0)
739
        pim_ifp->ll_lowest = cc->address->u.prefix6;
740
      if (IPV6_ADDR_CMP(&cc->address->u.prefix6,
741
            &pim_ifp->ll_highest) > 0)
742
        pim_ifp->ll_highest = cc->address->u.prefix6;
743
    }
744
745
    if (pim_ifp->ll_lowest.s6_addr[0] == 0xff)
746
      memset(&pim_ifp->ll_lowest, 0,
747
             sizeof(pim_ifp->ll_lowest));
748
749
    if (PIM_DEBUG_ZEBRA)
750
      zlog_debug(
751
        "%s: removed link-local %pI6, lowest now %pI6, highest %pI6",
752
        ifc->ifp->name, &ifc->address->u.prefix6,
753
        &pim_ifp->ll_lowest, &pim_ifp->ll_highest);
754
755
    gm_ifp_update(ifp);
756
  }
757
#endif
758
759
0
  detect_address_change(ifp, force_prim_as_any, __func__);
760
761
0
  pim_if_addr_del_igmp(ifc);
762
0
  pim_if_addr_del_pim(ifc);
763
0
}
764
765
void pim_if_addr_add_all(struct interface *ifp)
766
0
{
767
0
  struct connected *ifc;
768
0
  struct listnode *node;
769
0
  struct listnode *nextnode;
770
0
  int v4_addrs = 0;
771
0
  int v6_addrs = 0;
772
0
  struct pim_interface *pim_ifp = ifp->info;
773
0
  bool vxlan_term;
774
775
776
  /* PIM/IGMP enabled ? */
777
0
  if (!pim_ifp)
778
0
    return;
779
780
0
  for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
781
0
    struct prefix *p = ifc->address;
782
783
0
    if (p->family != AF_INET)
784
0
      v6_addrs++;
785
0
    else
786
0
      v4_addrs++;
787
0
    pim_if_addr_add(ifc);
788
0
  }
789
790
0
  if (!v4_addrs && v6_addrs && !if_is_loopback(ifp) &&
791
0
      pim_ifp->pim_enable && !pim_addr_is_any(pim_ifp->primary_address) &&
792
0
      pim_ifp->pim_sock_fd < 0 && pim_sock_add(ifp)) {
793
    /* Interface has a valid primary address ? */
794
    /* Interface has a valid socket ? */
795
0
    zlog_warn("Failure creating PIM socket for interface %s",
796
0
        ifp->name);
797
0
  }
798
  /*
799
   * PIM or IGMP/MLD is enabled on interface, and there is at least one
800
   * address assigned, then try to create a vif_index.
801
   */
802
0
  if (pim_ifp->mroute_vif_index < 0) {
803
0
    vxlan_term = pim_vxlan_is_term_dev_cfg(pim_ifp->pim, ifp);
804
0
    pim_if_add_vif(ifp, false, vxlan_term);
805
0
  }
806
0
  gm_ifp_update(ifp);
807
0
  pim_ifchannel_scan_forward_start(ifp);
808
809
0
  pim_rp_setup(pim_ifp->pim);
810
0
  pim_rp_check_on_if_add(pim_ifp);
811
0
}
812
813
void pim_if_addr_del_all(struct interface *ifp)
814
0
{
815
0
  struct connected *ifc;
816
0
  struct listnode *node;
817
0
  struct listnode *nextnode;
818
0
  struct pim_instance *pim;
819
820
0
  pim = ifp->vrf->info;
821
0
  if (!pim)
822
0
    return;
823
824
  /* PIM/IGMP enabled ? */
825
0
  if (!ifp->info)
826
0
    return;
827
828
0
  for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
829
0
    struct prefix *p = ifc->address;
830
831
0
    if (p->family != PIM_AF)
832
0
      continue;
833
834
0
    pim_if_addr_del(ifc, 1 /* force_prim_as_any=true */);
835
0
  }
836
837
0
  pim_rp_setup(pim);
838
0
  pim_i_am_rp_re_evaluate(pim);
839
0
}
840
841
void pim_if_addr_del_all_igmp(struct interface *ifp)
842
0
{
843
0
  struct connected *ifc;
844
0
  struct listnode *node;
845
0
  struct listnode *nextnode;
846
847
  /* PIM/IGMP enabled ? */
848
0
  if (!ifp->info)
849
0
    return;
850
851
0
  for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
852
0
    struct prefix *p = ifc->address;
853
854
0
    if (p->family != AF_INET)
855
0
      continue;
856
857
0
    pim_if_addr_del_igmp(ifc);
858
0
  }
859
0
}
860
861
pim_addr pim_find_primary_addr(struct interface *ifp)
862
2
{
863
2
  struct connected *ifc;
864
2
  struct listnode *node;
865
2
  struct pim_interface *pim_ifp = ifp->info;
866
867
2
  if (pim_ifp && !pim_addr_is_any(pim_ifp->update_source))
868
0
    return pim_ifp->update_source;
869
870
#if PIM_IPV == 6
871
  if (pim_ifp && !pim_addr_is_any(pim_ifp->ll_highest))
872
    return pim_ifp->ll_highest;
873
874
  pim_addr best_addr = PIMADDR_ANY;
875
876
  for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
877
    pim_addr addr;
878
879
    if (ifc->address->family != AF_INET6)
880
      continue;
881
882
    addr = pim_addr_from_prefix(ifc->address);
883
    if (!IN6_IS_ADDR_LINKLOCAL(&addr))
884
      continue;
885
    if (pim_addr_cmp(addr, best_addr) > 0)
886
      best_addr = addr;
887
  }
888
889
  return best_addr;
890
#else
891
2
  int v4_addrs = 0;
892
2
  int v6_addrs = 0;
893
894
2
  for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
895
1
    switch (ifc->address->family) {
896
1
    case AF_INET:
897
1
      v4_addrs++;
898
1
      break;
899
0
    case AF_INET6:
900
0
      v6_addrs++;
901
0
      break;
902
0
    default:
903
0
      continue;
904
1
    }
905
906
1
    if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
907
0
      continue;
908
909
1
    if (ifc->address->family != PIM_AF)
910
0
      continue;
911
912
1
    return pim_addr_from_prefix(ifc->address);
913
1
  }
914
915
  /*
916
   * If we have no v4_addrs and v6 is configured
917
   * We probably are using unnumbered
918
   * So let's grab the loopbacks v4 address
919
   * and use that as the primary address
920
   */
921
1
  if (!v4_addrs && v6_addrs) {
922
0
    struct interface *lo_ifp;
923
924
    // DBS - Come back and check here
925
0
    if (ifp->vrf->vrf_id == VRF_DEFAULT)
926
0
      lo_ifp = if_lookup_by_name("lo", ifp->vrf->vrf_id);
927
0
    else
928
0
      lo_ifp = if_lookup_by_name(ifp->vrf->name,
929
0
               ifp->vrf->vrf_id);
930
931
0
    if (lo_ifp && (lo_ifp != ifp))
932
0
      return pim_find_primary_addr(lo_ifp);
933
0
  }
934
1
  return PIMADDR_ANY;
935
1
#endif
936
1
}
937
938
static int pim_iface_next_vif_index(struct interface *ifp)
939
2
{
940
2
  struct pim_interface *pim_ifp = ifp->info;
941
2
  struct pim_instance *pim = pim_ifp->pim;
942
2
  int i;
943
944
  /*
945
   * The pimreg vif is always going to be in index 0
946
   * of the table.
947
   */
948
2
  if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF)
949
1
    return 0;
950
951
1
  for (i = 1; i < MAXVIFS; i++) {
952
1
    if (pim->iface_vif_index[i] == 0)
953
1
      return i;
954
1
  }
955
0
  return MAXVIFS;
956
1
}
957
958
/*
959
  pim_if_add_vif() uses ifindex as vif_index
960
961
  see also pim_if_find_vifindex_by_ifindex()
962
 */
963
int pim_if_add_vif(struct interface *ifp, bool ispimreg, bool is_vxlan_term)
964
2
{
965
2
  struct pim_interface *pim_ifp = ifp->info;
966
2
  pim_addr ifaddr;
967
2
  unsigned char flags = 0;
968
969
2
  assert(pim_ifp);
970
971
2
  if (pim_ifp->mroute_vif_index > 0) {
972
0
    zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d",
973
0
        __func__, pim_ifp->mroute_vif_index, ifp->name,
974
0
        ifp->ifindex);
975
0
    return -1;
976
0
  }
977
978
2
  if (ifp->ifindex < 0) {
979
0
    zlog_warn("%s: ifindex=%d < 0 on interface %s", __func__,
980
0
        ifp->ifindex, ifp->name);
981
0
    return -2;
982
2
  } else if ((ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) &&
983
2
       ((strncmp(ifp->name, "pimreg", 6)) &&
984
1
        (strncmp(ifp->name, "pim6reg", 7)))) {
985
0
    zlog_warn("%s: ifindex=%d on interface %s", __func__,
986
0
        ifp->ifindex, ifp->name);
987
0
    return -2;
988
0
  }
989
990
2
  ifaddr = pim_ifp->primary_address;
991
2
#if PIM_IPV != 6
992
  /* IPv6 API is always by interface index */
993
2
  if (!ispimreg && !is_vxlan_term && pim_addr_is_any(ifaddr)) {
994
0
    zlog_warn(
995
0
      "%s: could not get address for interface %s ifindex=%d",
996
0
      __func__, ifp->name, ifp->ifindex);
997
0
    return -4;
998
0
  }
999
2
#endif
1000
1001
2
  pim_ifp->mroute_vif_index = pim_iface_next_vif_index(ifp);
1002
1003
2
  if (pim_ifp->mroute_vif_index >= MAXVIFS) {
1004
0
    zlog_warn(
1005
0
      "%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s",
1006
0
      __func__, MAXVIFS, ifp->name);
1007
0
    return -3;
1008
0
  }
1009
1010
2
  if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF)
1011
1
    flags = VIFF_REGISTER;
1012
1
#ifdef VIFF_USE_IFINDEX
1013
1
  else
1014
1
    flags = VIFF_USE_IFINDEX;
1015
2
#endif
1016
1017
2
  if (pim_mroute_add_vif(ifp, ifaddr, flags)) {
1018
    /* pim_mroute_add_vif reported error */
1019
0
    return -5;
1020
0
  }
1021
1022
2
  pim_ifp->pim->iface_vif_index[pim_ifp->mroute_vif_index] = 1;
1023
1024
2
  if (!ispimreg)
1025
1
    gm_ifp_update(ifp);
1026
1027
  /* if the device qualifies as pim_vxlan iif/oif update vxlan entries */
1028
2
  pim_vxlan_add_vif(ifp);
1029
2
  return 0;
1030
2
}
1031
1032
int pim_if_del_vif(struct interface *ifp)
1033
0
{
1034
0
  struct pim_interface *pim_ifp = ifp->info;
1035
1036
0
  if (pim_ifp->mroute_vif_index < 1) {
1037
0
    zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d",
1038
0
        __func__, pim_ifp->mroute_vif_index, ifp->name,
1039
0
        ifp->ifindex);
1040
0
    return -1;
1041
0
  }
1042
1043
  /* if the device was a pim_vxlan iif/oif update vxlan mroute entries */
1044
0
  pim_vxlan_del_vif(ifp);
1045
1046
0
  gm_ifp_teardown(ifp);
1047
1048
0
  pim_mroute_del_vif(ifp);
1049
1050
  /*
1051
    Update vif_index
1052
   */
1053
0
  pim_ifp->pim->iface_vif_index[pim_ifp->mroute_vif_index] = 0;
1054
1055
0
  pim_ifp->mroute_vif_index = -1;
1056
0
  return 0;
1057
0
}
1058
1059
// DBS - VRF Revist
1060
struct interface *pim_if_find_by_vif_index(struct pim_instance *pim,
1061
             ifindex_t vif_index)
1062
0
{
1063
0
  struct interface *ifp;
1064
1065
0
  FOR_ALL_INTERFACES (pim->vrf, ifp) {
1066
0
    if (ifp->info) {
1067
0
      struct pim_interface *pim_ifp;
1068
0
      pim_ifp = ifp->info;
1069
1070
0
      if (vif_index == pim_ifp->mroute_vif_index)
1071
0
        return ifp;
1072
0
    }
1073
0
  }
1074
1075
0
  return 0;
1076
0
}
1077
1078
/*
1079
  pim_if_add_vif() uses ifindex as vif_index
1080
 */
1081
int pim_if_find_vifindex_by_ifindex(struct pim_instance *pim, ifindex_t ifindex)
1082
0
{
1083
0
  struct pim_interface *pim_ifp;
1084
0
  struct interface *ifp;
1085
1086
0
  ifp = if_lookup_by_index(ifindex, pim->vrf->vrf_id);
1087
0
  if (!ifp || !ifp->info)
1088
0
    return -1;
1089
0
  pim_ifp = ifp->info;
1090
1091
0
  return pim_ifp->mroute_vif_index;
1092
0
}
1093
1094
int pim_if_lan_delay_enabled(struct interface *ifp)
1095
116k
{
1096
116k
  struct pim_interface *pim_ifp;
1097
1098
116k
  pim_ifp = ifp->info;
1099
116k
  assert(pim_ifp);
1100
116k
  assert(pim_ifp->pim_number_of_nonlandelay_neighbors >= 0);
1101
1102
116k
  return pim_ifp->pim_number_of_nonlandelay_neighbors == 0;
1103
116k
}
1104
1105
uint16_t pim_if_effective_propagation_delay_msec(struct interface *ifp)
1106
57.9k
{
1107
57.9k
  if (pim_if_lan_delay_enabled(ifp)) {
1108
0
    struct pim_interface *pim_ifp;
1109
0
    pim_ifp = ifp->info;
1110
0
    return pim_ifp->pim_neighbors_highest_propagation_delay_msec;
1111
57.9k
  } else {
1112
57.9k
    return PIM_DEFAULT_PROPAGATION_DELAY_MSEC;
1113
57.9k
  }
1114
57.9k
}
1115
1116
uint16_t pim_if_effective_override_interval_msec(struct interface *ifp)
1117
57.9k
{
1118
57.9k
  if (pim_if_lan_delay_enabled(ifp)) {
1119
0
    struct pim_interface *pim_ifp;
1120
0
    pim_ifp = ifp->info;
1121
0
    return pim_ifp->pim_neighbors_highest_override_interval_msec;
1122
57.9k
  } else {
1123
57.9k
    return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC;
1124
57.9k
  }
1125
57.9k
}
1126
1127
int pim_if_t_override_msec(struct interface *ifp)
1128
0
{
1129
0
  int effective_override_interval_msec;
1130
0
  int t_override_msec;
1131
1132
0
  effective_override_interval_msec =
1133
0
    pim_if_effective_override_interval_msec(ifp);
1134
1135
0
  t_override_msec =
1136
0
    frr_weak_random() % (effective_override_interval_msec + 1);
1137
1138
0
  return t_override_msec;
1139
0
}
1140
1141
uint16_t pim_if_jp_override_interval_msec(struct interface *ifp)
1142
57.9k
{
1143
57.9k
  return pim_if_effective_propagation_delay_msec(ifp)
1144
57.9k
         + pim_if_effective_override_interval_msec(ifp);
1145
57.9k
}
1146
1147
/*
1148
  RFC 4601: 4.1.6.  State Summarization Macros
1149
1150
  The function NBR( I, A ) uses information gathered through PIM Hello
1151
  messages to map the IP address A of a directly connected PIM
1152
  neighbor router on interface I to the primary IP address of the same
1153
  router (Section 4.3.4).  The primary IP address of a neighbor is the
1154
  address that it uses as the source of its PIM Hello messages.
1155
*/
1156
struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp, pim_addr addr)
1157
0
{
1158
0
  struct listnode *neighnode;
1159
0
  struct pim_neighbor *neigh;
1160
0
  struct pim_interface *pim_ifp;
1161
0
  struct prefix p;
1162
1163
0
  assert(ifp);
1164
1165
0
  pim_ifp = ifp->info;
1166
0
  if (!pim_ifp) {
1167
0
    zlog_warn("%s: multicast not enabled on interface %s", __func__,
1168
0
        ifp->name);
1169
0
    return 0;
1170
0
  }
1171
1172
0
  pim_addr_to_prefix(&p, addr);
1173
1174
0
  for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
1175
0
          neigh)) {
1176
1177
    /* primary address ? */
1178
0
    if (!pim_addr_cmp(neigh->source_addr, addr))
1179
0
      return neigh;
1180
1181
    /* secondary address ? */
1182
0
    if (pim_neighbor_find_secondary(neigh, &p))
1183
0
      return neigh;
1184
0
  }
1185
1186
0
  if (PIM_DEBUG_PIM_TRACE)
1187
0
    zlog_debug(
1188
0
      "%s: neighbor not found for address %pPA on interface %s",
1189
0
      __func__, &addr, ifp->name);
1190
1191
0
  return NULL;
1192
0
}
1193
1194
long pim_if_t_suppressed_msec(struct interface *ifp)
1195
0
{
1196
0
  struct pim_interface *pim_ifp;
1197
0
  long t_suppressed_msec;
1198
0
  uint32_t ramount = 0;
1199
1200
0
  pim_ifp = ifp->info;
1201
0
  assert(pim_ifp);
1202
1203
  /* join suppression disabled ? */
1204
0
  if (pim_ifp->pim_can_disable_join_suppression)
1205
0
    return 0;
1206
1207
  /* t_suppressed = t_periodic * rand(1.1, 1.4) */
1208
0
  ramount = 1100 + (frr_weak_random() % (1400 - 1100 + 1));
1209
0
  t_suppressed_msec = router->t_periodic * ramount;
1210
1211
0
  return t_suppressed_msec;
1212
0
}
1213
1214
static void gm_join_free(struct gm_join *ij)
1215
0
{
1216
0
  XFREE(MTYPE_PIM_IGMP_JOIN, ij);
1217
0
}
1218
1219
static struct gm_join *gm_join_find(struct list *join_list, pim_addr group_addr,
1220
            pim_addr source_addr)
1221
0
{
1222
0
  struct listnode *node;
1223
0
  struct gm_join *ij;
1224
1225
0
  assert(join_list);
1226
1227
0
  for (ALL_LIST_ELEMENTS_RO(join_list, node, ij)) {
1228
0
    if ((!pim_addr_cmp(group_addr, ij->group_addr)) &&
1229
0
        (!pim_addr_cmp(source_addr, ij->source_addr)))
1230
0
      return ij;
1231
0
  }
1232
1233
0
  return 0;
1234
0
}
1235
1236
static int gm_join_sock(const char *ifname, ifindex_t ifindex,
1237
      pim_addr group_addr, pim_addr source_addr,
1238
      struct pim_interface *pim_ifp)
1239
0
{
1240
0
  int join_fd;
1241
1242
0
  pim_ifp->igmp_ifstat_joins_sent++;
1243
1244
0
  join_fd = pim_socket_raw(IPPROTO_GM);
1245
0
  if (join_fd < 0) {
1246
0
    pim_ifp->igmp_ifstat_joins_failed++;
1247
0
    return -1;
1248
0
  }
1249
1250
0
  if (pim_gm_join_source(join_fd, ifindex, group_addr, source_addr)) {
1251
0
    zlog_warn(
1252
0
      "%s: setsockopt(fd=%d) failure for " GM
1253
0
      " group %pPAs source %pPAs ifindex %d on interface %s: errno=%d: %s",
1254
0
      __func__, join_fd, &group_addr, &source_addr, ifindex,
1255
0
      ifname, errno, safe_strerror(errno));
1256
1257
0
    pim_ifp->igmp_ifstat_joins_failed++;
1258
1259
0
    close(join_fd);
1260
0
    return -2;
1261
0
  }
1262
1263
0
  return join_fd;
1264
0
}
1265
1266
static struct gm_join *gm_join_new(struct interface *ifp, pim_addr group_addr,
1267
           pim_addr source_addr)
1268
0
{
1269
0
  struct pim_interface *pim_ifp;
1270
0
  struct gm_join *ij;
1271
0
  int join_fd;
1272
1273
0
  pim_ifp = ifp->info;
1274
0
  assert(pim_ifp);
1275
1276
0
  join_fd = gm_join_sock(ifp->name, ifp->ifindex, group_addr, source_addr,
1277
0
             pim_ifp);
1278
0
  if (join_fd < 0) {
1279
0
    zlog_warn("%s: gm_join_sock() failure for " GM
1280
0
        " group %pPAs source %pPAs on interface %s",
1281
0
        __func__, &group_addr, &source_addr, ifp->name);
1282
0
    return 0;
1283
0
  }
1284
1285
0
  ij = XCALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij));
1286
1287
0
  ij->sock_fd = join_fd;
1288
0
  ij->group_addr = group_addr;
1289
0
  ij->source_addr = source_addr;
1290
0
  ij->sock_creation = pim_time_monotonic_sec();
1291
1292
0
  listnode_add(pim_ifp->gm_join_list, ij);
1293
1294
0
  return ij;
1295
0
}
1296
1297
ferr_r pim_if_gm_join_add(struct interface *ifp, pim_addr group_addr,
1298
        pim_addr source_addr)
1299
0
{
1300
0
  struct pim_interface *pim_ifp;
1301
0
  struct gm_join *ij;
1302
1303
0
  pim_ifp = ifp->info;
1304
0
  if (!pim_ifp) {
1305
0
    return ferr_cfg_invalid("multicast not enabled on interface %s",
1306
0
          ifp->name);
1307
0
  }
1308
1309
0
  if (!pim_ifp->gm_join_list) {
1310
0
    pim_ifp->gm_join_list = list_new();
1311
0
    pim_ifp->gm_join_list->del = (void (*)(void *))gm_join_free;
1312
0
  }
1313
1314
0
  ij = gm_join_find(pim_ifp->gm_join_list, group_addr, source_addr);
1315
1316
  /* This interface has already been configured to join this IGMP/MLD
1317
   * group
1318
   */
1319
0
  if (ij) {
1320
0
    return ferr_ok();
1321
0
  }
1322
1323
0
  (void)gm_join_new(ifp, group_addr, source_addr);
1324
1325
0
  if (PIM_DEBUG_GM_EVENTS) {
1326
0
    zlog_debug(
1327
0
      "%s: issued static " GM
1328
0
      " join for channel (S,G)=(%pPA,%pPA) on interface %s",
1329
0
      __func__, &source_addr, &group_addr, ifp->name);
1330
0
  }
1331
1332
0
  return ferr_ok();
1333
0
}
1334
1335
int pim_if_gm_join_del(struct interface *ifp, pim_addr group_addr,
1336
           pim_addr source_addr)
1337
0
{
1338
0
  struct pim_interface *pim_ifp;
1339
0
  struct gm_join *ij;
1340
1341
0
  pim_ifp = ifp->info;
1342
0
  if (!pim_ifp) {
1343
0
    zlog_warn("%s: multicast not enabled on interface %s", __func__,
1344
0
        ifp->name);
1345
0
    return -1;
1346
0
  }
1347
1348
0
  if (!pim_ifp->gm_join_list) {
1349
0
    zlog_warn("%s: no " GM " join on interface %s", __func__,
1350
0
        ifp->name);
1351
0
    return -2;
1352
0
  }
1353
1354
0
  ij = gm_join_find(pim_ifp->gm_join_list, group_addr, source_addr);
1355
0
  if (!ij) {
1356
0
    zlog_warn("%s: could not find " GM
1357
0
        " group %pPAs source %pPAs on interface %s",
1358
0
        __func__, &group_addr, &source_addr, ifp->name);
1359
0
    return -3;
1360
0
  }
1361
1362
0
  if (close(ij->sock_fd)) {
1363
0
    zlog_warn(
1364
0
      "%s: failure closing sock_fd=%d for " GM
1365
0
      " group %pPAs source %pPAs on interface %s: errno=%d: %s",
1366
0
      __func__, ij->sock_fd, &group_addr, &source_addr,
1367
0
      ifp->name, errno, safe_strerror(errno));
1368
    /* warning only */
1369
0
  }
1370
0
  listnode_delete(pim_ifp->gm_join_list, ij);
1371
0
  gm_join_free(ij);
1372
0
  if (listcount(pim_ifp->gm_join_list) < 1) {
1373
0
    list_delete(&pim_ifp->gm_join_list);
1374
0
    pim_ifp->gm_join_list = 0;
1375
0
  }
1376
1377
0
  return 0;
1378
0
}
1379
1380
__attribute__((unused))
1381
static void pim_if_gm_join_del_all(struct interface *ifp)
1382
0
{
1383
0
  struct pim_interface *pim_ifp;
1384
0
  struct listnode *node;
1385
0
  struct listnode *nextnode;
1386
0
  struct gm_join *ij;
1387
1388
0
  pim_ifp = ifp->info;
1389
0
  if (!pim_ifp) {
1390
0
    zlog_warn("%s: multicast not enabled on interface %s", __func__,
1391
0
        ifp->name);
1392
0
    return;
1393
0
  }
1394
1395
0
  if (!pim_ifp->gm_join_list)
1396
0
    return;
1397
1398
0
  for (ALL_LIST_ELEMENTS(pim_ifp->gm_join_list, node, nextnode, ij))
1399
0
    pim_if_gm_join_del(ifp, ij->group_addr, ij->source_addr);
1400
0
}
1401
1402
/*
1403
  RFC 4601
1404
1405
  Transitions from "I am Assert Loser" State
1406
1407
  Current Winner's GenID Changes or NLT Expires
1408
1409
  The Neighbor Liveness Timer associated with the current winner
1410
  expires or we receive a Hello message from the current winner
1411
  reporting a different GenID from the one it previously reported.
1412
  This indicates that the current winner's interface or router has
1413
  gone down (and may have come back up), and so we must assume it no
1414
  longer knows it was the winner.
1415
 */
1416
void pim_if_assert_on_neighbor_down(struct interface *ifp, pim_addr neigh_addr)
1417
95
{
1418
95
  struct pim_interface *pim_ifp;
1419
95
  struct pim_ifchannel *ch;
1420
1421
95
  pim_ifp = ifp->info;
1422
95
  assert(pim_ifp);
1423
1424
13.7k
  RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1425
    /* Is (S,G,I) assert loser ? */
1426
13.7k
    if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER)
1427
13.7k
      continue;
1428
    /* Dead neighbor was winner ? */
1429
11
    if (pim_addr_cmp(ch->ifassert_winner, neigh_addr))
1430
11
      continue;
1431
1432
0
    assert_action_a5(ch);
1433
0
  }
1434
95
}
1435
1436
void pim_if_update_join_desired(struct pim_interface *pim_ifp)
1437
3
{
1438
3
  struct pim_ifchannel *ch;
1439
1440
  /* clear off flag from interface's upstreams */
1441
3
  RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1442
0
    PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(
1443
0
      ch->upstream->flags);
1444
0
  }
1445
1446
  /* scan per-interface (S,G,I) state on this I interface */
1447
3
  RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1448
0
    struct pim_upstream *up = ch->upstream;
1449
1450
0
    if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up->flags))
1451
0
      continue;
1452
1453
    /* update join_desired for the global (S,G) state */
1454
0
    pim_upstream_update_join_desired(pim_ifp->pim, up);
1455
0
    PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up->flags);
1456
0
  }
1457
3
}
1458
1459
void pim_if_update_assert_tracking_desired(struct interface *ifp)
1460
3
{
1461
3
  struct pim_interface *pim_ifp;
1462
3
  struct pim_ifchannel *ch;
1463
1464
3
  pim_ifp = ifp->info;
1465
3
  if (!pim_ifp)
1466
0
    return;
1467
1468
3
  RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1469
0
    pim_ifchannel_update_assert_tracking_desired(ch);
1470
0
  }
1471
3
}
1472
1473
/*
1474
 * PIM wants to have an interface pointer for everything it does.
1475
 * The pimreg is a special interface that we have that is not
1476
 * quite an interface but a VIF is created for it.
1477
 */
1478
void pim_if_create_pimreg(struct pim_instance *pim)
1479
1
{
1480
1
  char pimreg_name[INTERFACE_NAMSIZ];
1481
1482
1
  if (!pim->regiface) {
1483
1
    if (pim->vrf->vrf_id == VRF_DEFAULT)
1484
1
      strlcpy(pimreg_name, PIMREG, sizeof(pimreg_name));
1485
0
    else
1486
0
      snprintf(pimreg_name, sizeof(pimreg_name), PIMREG "%u",
1487
0
         pim->vrf->data.l.table_id);
1488
1489
1
    pim->regiface = if_get_by_name(pimreg_name, pim->vrf->vrf_id,
1490
1
                 pim->vrf->name);
1491
1
    pim->regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF;
1492
1493
1
    if (!pim->regiface->info)
1494
1
      pim_if_new(pim->regiface, false, false, true,
1495
1
           false /*vxlan_term*/);
1496
1497
    /*
1498
     * On vrf moves we delete the interface if there
1499
     * is nothing going on with it.  We cannot have
1500
     * the pimregiface deleted.
1501
     */
1502
1
    pim->regiface->configured = true;
1503
1504
1
  }
1505
1
}
1506
1507
struct prefix *pim_if_connected_to_source(struct interface *ifp, pim_addr src)
1508
19.3M
{
1509
19.3M
  struct listnode *cnode;
1510
19.3M
  struct connected *c;
1511
19.3M
  struct prefix p;
1512
1513
19.3M
  if (!ifp)
1514
19.3M
    return NULL;
1515
1516
0
  pim_addr_to_prefix(&p, src);
1517
1518
0
  for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
1519
0
    if (c->address->family != PIM_AF)
1520
0
      continue;
1521
0
    if (prefix_match(c->address, &p))
1522
0
      return c->address;
1523
0
    if (CONNECTED_PEER(c) && prefix_match(c->destination, &p))
1524
      /* this is not a typo, on PtP we need to return the
1525
       * *local* address that lines up with src.
1526
       */
1527
0
      return c->address;
1528
0
  }
1529
1530
0
  return NULL;
1531
0
}
1532
1533
bool pim_if_is_vrf_device(struct interface *ifp)
1534
0
{
1535
0
  if (if_is_vrf(ifp))
1536
0
    return true;
1537
1538
0
  return false;
1539
0
}
1540
1541
int pim_if_ifchannel_count(struct pim_interface *pim_ifp)
1542
0
{
1543
0
  struct pim_ifchannel *ch;
1544
0
  int count = 0;
1545
1546
0
  RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1547
0
    count++;
1548
0
  }
1549
1550
0
  return count;
1551
0
}
1552
#ifndef FUZZING
1553
static
1554
#endif
1555
int pim_ifp_create(struct interface *ifp)
1556
0
{
1557
0
  struct pim_instance *pim;
1558
1559
0
  pim = ifp->vrf->info;
1560
0
  if (PIM_DEBUG_ZEBRA) {
1561
0
    zlog_debug(
1562
0
      "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
1563
0
      __func__, ifp->name, ifp->ifindex, ifp->vrf->name,
1564
0
      ifp->vrf->vrf_id, (long)ifp->flags, ifp->metric,
1565
0
      ifp->mtu, if_is_operative(ifp));
1566
0
  }
1567
1568
0
  if (if_is_operative(ifp)) {
1569
0
    struct pim_interface *pim_ifp;
1570
1571
0
    pim_ifp = ifp->info;
1572
    /*
1573
     * If we have a pim_ifp already and this is an if_add
1574
     * that means that we probably have a vrf move event
1575
     * If that is the case, set the proper vrfness.
1576
     */
1577
0
    if (pim_ifp)
1578
0
      pim_ifp->pim = pim;
1579
0
    pim_if_addr_add_all(ifp);
1580
1581
    /*
1582
     * Due to ordering issues based upon when
1583
     * a command is entered we should ensure that
1584
     * the pim reg is created for this vrf if we
1585
     * have configuration for it already.
1586
     *
1587
     * this is a no-op if it's already been done.
1588
     */
1589
0
    pim_if_create_pimreg(pim);
1590
0
  }
1591
1592
0
#if PIM_IPV == 4
1593
  /*
1594
   * If we are a vrf device that is up, open up the pim_socket for
1595
   * listening
1596
   * to incoming pim messages irrelevant if the user has configured us
1597
   * for pim or not.
1598
   */
1599
0
  if (pim_if_is_vrf_device(ifp)) {
1600
0
    struct pim_interface *pim_ifp;
1601
1602
0
    if (!ifp->info) {
1603
0
      pim_ifp = pim_if_new(ifp, false, false, false,
1604
0
               false /*vxlan_term*/);
1605
0
      ifp->info = pim_ifp;
1606
0
    }
1607
1608
0
    pim_sock_add(ifp);
1609
0
  }
1610
1611
0
  if (!strncmp(ifp->name, PIM_VXLAN_TERM_DEV_NAME,
1612
0
         sizeof(PIM_VXLAN_TERM_DEV_NAME))) {
1613
0
    if (pim->mcast_if_count < MAXVIFS)
1614
0
      pim_vxlan_add_term_dev(pim, ifp);
1615
0
    else
1616
0
      zlog_warn(
1617
0
        "%s: Cannot enable pim on %s. MAXVIFS(%d) reached. Deleting and readding the vxlan termimation device after unconfiguring pim from other interfaces may succeed.",
1618
0
        __func__, ifp->name, MAXVIFS);
1619
0
  }
1620
0
#endif
1621
1622
0
  return 0;
1623
0
}
1624
1625
#ifndef FUZZING
1626
static
1627
#endif
1628
int pim_ifp_up(struct interface *ifp)
1629
0
{
1630
0
  uint32_t table_id;
1631
0
  struct pim_interface *pim_ifp;
1632
0
  struct pim_instance *pim;
1633
1634
0
  if (PIM_DEBUG_ZEBRA) {
1635
0
    zlog_debug(
1636
0
      "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
1637
0
      __func__, ifp->name, ifp->ifindex, ifp->vrf->name,
1638
0
      ifp->vrf->vrf_id, (long)ifp->flags, ifp->metric,
1639
0
      ifp->mtu, if_is_operative(ifp));
1640
0
  }
1641
1642
0
  pim = ifp->vrf->info;
1643
1644
0
  pim_ifp = ifp->info;
1645
  /*
1646
   * If we have a pim_ifp already and this is an if_add
1647
   * that means that we probably have a vrf move event
1648
   * If that is the case, set the proper vrfness.
1649
   */
1650
0
  if (pim_ifp)
1651
0
    pim_ifp->pim = pim;
1652
1653
  /*
1654
    pim_if_addr_add_all() suffices for bringing up both IGMP and
1655
    PIM
1656
  */
1657
0
  pim_if_addr_add_all(ifp);
1658
1659
  /*
1660
   * If we have a pimreg device callback and it's for a specific
1661
   * table set the master appropriately
1662
   */
1663
0
  if (sscanf(ifp->name, "" PIMREG "%" SCNu32, &table_id) == 1) {
1664
0
    struct vrf *vrf;
1665
0
    RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1666
0
      if ((table_id == vrf->data.l.table_id)
1667
0
          && (ifp->vrf->vrf_id != vrf->vrf_id)) {
1668
0
        struct interface *master = if_lookup_by_name(
1669
0
          vrf->name, vrf->vrf_id);
1670
1671
0
        if (!master) {
1672
0
          zlog_debug(
1673
0
            "%s: Unable to find Master interface for %s",
1674
0
            __func__, vrf->name);
1675
0
          return 0;
1676
0
        }
1677
0
        pim_zebra_interface_set_master(master, ifp);
1678
0
      }
1679
0
    }
1680
0
  }
1681
0
  return 0;
1682
0
}
1683
1684
#ifndef FUZZING
1685
static
1686
#endif
1687
int pim_ifp_down(struct interface *ifp)
1688
0
{
1689
0
  if (PIM_DEBUG_ZEBRA) {
1690
0
    zlog_debug(
1691
0
      "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
1692
0
      __func__, ifp->name, ifp->ifindex, ifp->vrf->name,
1693
0
      ifp->vrf->vrf_id, (long)ifp->flags, ifp->metric,
1694
0
      ifp->mtu, if_is_operative(ifp));
1695
0
  }
1696
1697
0
  if (!if_is_operative(ifp)) {
1698
0
    pim_ifchannel_delete_all(ifp);
1699
    /*
1700
      pim_if_addr_del_all() suffices for shutting down IGMP,
1701
      but not for shutting down PIM
1702
    */
1703
0
    pim_if_addr_del_all(ifp);
1704
1705
    /*
1706
      pim_sock_delete() closes the socket, stops read and timer
1707
      threads,
1708
      and kills all neighbors.
1709
    */
1710
0
    if (ifp->info) {
1711
0
      pim_sock_delete(ifp, "link down");
1712
0
    }
1713
0
  }
1714
1715
0
  if (ifp->info) {
1716
0
    pim_if_del_vif(ifp);
1717
0
    pim_ifstat_reset(ifp);
1718
0
  }
1719
1720
0
  return 0;
1721
0
}
1722
#ifndef FUZZING
1723
static
1724
#endif
1725
int pim_ifp_destroy(struct interface *ifp)
1726
0
{
1727
0
  if (PIM_DEBUG_ZEBRA) {
1728
0
    zlog_debug(
1729
0
      "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
1730
0
      __func__, ifp->name, ifp->ifindex, ifp->vrf->name,
1731
0
      ifp->vrf->vrf_id, (long)ifp->flags, ifp->metric,
1732
0
      ifp->mtu, if_is_operative(ifp));
1733
0
  }
1734
1735
0
  if (!if_is_operative(ifp))
1736
0
    pim_if_addr_del_all(ifp);
1737
1738
0
#if PIM_IPV == 4
1739
0
  struct pim_instance *pim;
1740
1741
0
  pim = ifp->vrf->info;
1742
0
  if (pim && pim->vxlan.term_if == ifp)
1743
0
    pim_vxlan_del_term_dev(pim);
1744
0
#endif
1745
1746
0
  return 0;
1747
0
}
1748
1749
static int pim_if_new_hook(struct interface *ifp)
1750
0
{
1751
0
  return 0;
1752
0
}
1753
1754
static int pim_if_delete_hook(struct interface *ifp)
1755
0
{
1756
0
  if (ifp->info)
1757
0
    pim_if_delete(ifp);
1758
1759
0
  return 0;
1760
0
}
1761
1762
void pim_iface_init(void)
1763
0
{
1764
0
  hook_register_prio(if_add, 0, pim_if_new_hook);
1765
0
  hook_register_prio(if_del, 0, pim_if_delete_hook);
1766
1767
0
  if_zapi_callbacks(pim_ifp_create, pim_ifp_up, pim_ifp_down,
1768
0
        pim_ifp_destroy);
1769
0
}