]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_iface.c
Merge pull request #2198 from LabNConsulting/working/master/bgpd-nht-crash
[mirror_frr.git] / pimd / pim_iface.c
1 /*
2 * PIM for Quagga
3 * Copyright (C) 2008 Everton da Silva Marques
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; see the file COPYING; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <zebra.h>
20
21 #include "if.h"
22 #include "log.h"
23 #include "vty.h"
24 #include "memory.h"
25 #include "prefix.h"
26 #include "vrf.h"
27 #include "linklist.h"
28 #include "plist.h"
29 #include "hash.h"
30 #include "ferr.h"
31
32 #include "pimd.h"
33 #include "pim_instance.h"
34 #include "pim_zebra.h"
35 #include "pim_iface.h"
36 #include "pim_igmp.h"
37 #include "pim_mroute.h"
38 #include "pim_oil.h"
39 #include "pim_str.h"
40 #include "pim_pim.h"
41 #include "pim_neighbor.h"
42 #include "pim_ifchannel.h"
43 #include "pim_sock.h"
44 #include "pim_time.h"
45 #include "pim_ssmpingd.h"
46 #include "pim_rp.h"
47 #include "pim_nht.h"
48 #include "pim_jp_agg.h"
49
50 static void pim_if_igmp_join_del_all(struct interface *ifp);
51 static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
52 struct in_addr group_addr,
53 struct in_addr source_addr);
54
55 void pim_if_init(struct pim_instance *pim)
56 {
57 int i;
58
59 for (i = 0; i < MAXVIFS; i++)
60 pim->iface_vif_index[i] = 0;
61 }
62
63 void pim_if_terminate(struct pim_instance *pim)
64 {
65 struct interface *ifp;
66
67 FOR_ALL_INTERFACES (pim->vrf, ifp) {
68 struct pim_interface *pim_ifp = ifp->info;
69
70 if (!pim_ifp)
71 continue;
72
73 pim_if_delete(ifp);
74 }
75 return;
76 }
77
78 static void *if_list_clean(struct pim_interface *pim_ifp)
79 {
80 struct pim_ifchannel *ch;
81
82 if (pim_ifp->igmp_join_list)
83 list_delete_and_null(&pim_ifp->igmp_join_list);
84
85 if (pim_ifp->igmp_socket_list)
86 list_delete_and_null(&pim_ifp->igmp_socket_list);
87
88 if (pim_ifp->pim_neighbor_list)
89 list_delete_and_null(&pim_ifp->pim_neighbor_list);
90
91 if (pim_ifp->upstream_switch_list)
92 list_delete_and_null(&pim_ifp->upstream_switch_list);
93
94 if (pim_ifp->sec_addr_list)
95 list_delete_and_null(&pim_ifp->sec_addr_list);
96
97 while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
98 ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
99
100 pim_ifchannel_delete(ch);
101 }
102
103 XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
104
105 return 0;
106 }
107
108 static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr)
109 {
110 XFREE(MTYPE_PIM_SEC_ADDR, sec_addr);
111 }
112
113 static int pim_sec_addr_comp(const void *p1, const void *p2)
114 {
115 const struct pim_secondary_addr *sec1 = p1;
116 const struct pim_secondary_addr *sec2 = p2;
117
118 if (sec1->addr.family == AF_INET && sec2->addr.family == AF_INET6)
119 return -1;
120
121 if (sec1->addr.family == AF_INET6 && sec2->addr.family == AF_INET)
122 return 1;
123
124 if (sec1->addr.family == AF_INET) {
125 if (ntohl(sec1->addr.u.prefix4.s_addr)
126 < ntohl(sec2->addr.u.prefix4.s_addr))
127 return -1;
128
129 if (ntohl(sec1->addr.u.prefix4.s_addr)
130 > ntohl(sec2->addr.u.prefix4.s_addr))
131 return 1;
132 } else {
133 return memcmp(&sec1->addr.u.prefix6, &sec2->addr.u.prefix6,
134 sizeof(struct in6_addr));
135 }
136
137 return 0;
138 }
139
140 struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
141 {
142 struct pim_interface *pim_ifp;
143
144 zassert(ifp);
145 zassert(!ifp->info);
146
147 pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp));
148 if (!pim_ifp) {
149 zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_ifp));
150 return 0;
151 }
152
153 pim_ifp->options = 0;
154 pim_ifp->pim = pim_get_pim_instance(ifp->vrf_id);
155 pim_ifp->mroute_vif_index = -1;
156
157 pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
158 pim_ifp->igmp_default_robustness_variable =
159 IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
160 pim_ifp->igmp_default_query_interval = IGMP_GENERAL_QUERY_INTERVAL;
161 pim_ifp->igmp_query_max_response_time_dsec =
162 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC;
163 pim_ifp->igmp_specific_query_max_response_time_dsec =
164 IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC;
165
166 /*
167 RFC 3376: 8.3. Query Response Interval
168 The number of seconds represented by the [Query Response Interval]
169 must be less than the [Query Interval].
170 */
171 zassert(pim_ifp->igmp_query_max_response_time_dsec
172 < pim_ifp->igmp_default_query_interval);
173
174 if (pim)
175 PIM_IF_DO_PIM(pim_ifp->options);
176 if (igmp)
177 PIM_IF_DO_IGMP(pim_ifp->options);
178
179 PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp->options);
180
181 pim_ifp->igmp_join_list = NULL;
182 pim_ifp->igmp_socket_list = NULL;
183 pim_ifp->pim_neighbor_list = NULL;
184 pim_ifp->upstream_switch_list = NULL;
185 pim_ifp->pim_generation_id = 0;
186
187 /* list of struct igmp_sock */
188 pim_ifp->igmp_socket_list = list_new();
189 if (!pim_ifp->igmp_socket_list) {
190 zlog_err("%s: failure: igmp_socket_list=list_new()",
191 __PRETTY_FUNCTION__);
192 return if_list_clean(pim_ifp);
193 }
194 pim_ifp->igmp_socket_list->del = (void (*)(void *))igmp_sock_free;
195
196 /* list of struct pim_neighbor */
197 pim_ifp->pim_neighbor_list = list_new();
198 if (!pim_ifp->pim_neighbor_list) {
199 zlog_err("%s: failure: pim_neighbor_list=list_new()",
200 __PRETTY_FUNCTION__);
201 return if_list_clean(pim_ifp);
202 }
203 pim_ifp->pim_neighbor_list->del = (void (*)(void *))pim_neighbor_free;
204
205 pim_ifp->upstream_switch_list = list_new();
206 if (!pim_ifp->upstream_switch_list) {
207 zlog_err("%s: failure: upstream_switch_list=list_new()",
208 __PRETTY_FUNCTION__);
209 return if_list_clean(pim_ifp);
210 }
211 pim_ifp->upstream_switch_list->del =
212 (void (*)(void *))pim_jp_agg_group_list_free;
213 pim_ifp->upstream_switch_list->cmp = pim_jp_agg_group_list_cmp;
214
215 pim_ifp->sec_addr_list = list_new();
216 if (!pim_ifp->sec_addr_list) {
217 zlog_err("%s: failure: secondary addresslist",
218 __PRETTY_FUNCTION__);
219 return if_list_clean(pim_ifp);
220 }
221 pim_ifp->sec_addr_list->del = (void (*)(void *))pim_sec_addr_free;
222 pim_ifp->sec_addr_list->cmp =
223 (int (*)(void *, void *))pim_sec_addr_comp;
224
225 RB_INIT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
226
227 ifp->info = pim_ifp;
228
229 pim_sock_reset(ifp);
230
231 pim_if_add_vif(ifp);
232
233 return pim_ifp;
234 }
235
236 void pim_if_delete(struct interface *ifp)
237 {
238 struct pim_interface *pim_ifp;
239 struct pim_ifchannel *ch;
240
241 zassert(ifp);
242 pim_ifp = ifp->info;
243 zassert(pim_ifp);
244
245 if (pim_ifp->igmp_join_list) {
246 pim_if_igmp_join_del_all(ifp);
247 }
248
249 pim_ifchannel_delete_all(ifp);
250 igmp_sock_delete_all(ifp);
251
252 pim_neighbor_delete_all(ifp, "Interface removed from configuration");
253
254 pim_if_del_vif(ifp);
255
256 list_delete_and_null(&pim_ifp->igmp_socket_list);
257 list_delete_and_null(&pim_ifp->pim_neighbor_list);
258 list_delete_and_null(&pim_ifp->upstream_switch_list);
259 list_delete_and_null(&pim_ifp->sec_addr_list);
260
261 if (pim_ifp->boundary_oil_plist)
262 XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
263
264 while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
265 ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
266
267 pim_ifchannel_delete(ch);
268 }
269
270 XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
271
272 ifp->info = NULL;
273 }
274
275 void pim_if_update_could_assert(struct interface *ifp)
276 {
277 struct pim_interface *pim_ifp;
278 struct pim_ifchannel *ch;
279
280 pim_ifp = ifp->info;
281 zassert(pim_ifp);
282
283 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
284 pim_ifchannel_update_could_assert(ch);
285 }
286 }
287
288 static void pim_if_update_my_assert_metric(struct interface *ifp)
289 {
290 struct pim_interface *pim_ifp;
291 struct pim_ifchannel *ch;
292
293 pim_ifp = ifp->info;
294 zassert(pim_ifp);
295
296 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
297 pim_ifchannel_update_my_assert_metric(ch);
298 }
299 }
300
301 static void pim_addr_change(struct interface *ifp)
302 {
303 struct pim_interface *pim_ifp;
304
305 pim_ifp = ifp->info;
306 zassert(pim_ifp);
307
308 pim_if_dr_election(ifp); /* router's own DR Priority (addr) changes --
309 Done TODO T30 */
310 pim_if_update_join_desired(pim_ifp); /* depends on DR */
311 pim_if_update_could_assert(ifp); /* depends on DR */
312 pim_if_update_my_assert_metric(ifp); /* depends on could_assert */
313 pim_if_update_assert_tracking_desired(
314 ifp); /* depends on DR, join_desired */
315
316 /*
317 RFC 4601: 4.3.1. Sending Hello Messages
318
319 1) Before an interface goes down or changes primary IP address, a
320 Hello message with a zero HoldTime should be sent immediately
321 (with the old IP address if the IP address changed).
322 -- FIXME See CAVEAT C13
323
324 2) After an interface has changed its IP address, it MUST send a
325 Hello message with its new IP address.
326 -- DONE below
327
328 3) If an interface changes one of its secondary IP addresses, a
329 Hello message with an updated Address_List option and a non-zero
330 HoldTime should be sent immediately.
331 -- FIXME See TODO T31
332 */
333 pim_ifp->pim_ifstat_hello_sent = 0; /* reset hello counter */
334 if (pim_ifp->pim_sock_fd < 0)
335 return;
336 pim_hello_restart_now(ifp); /* send hello and restart timer */
337 }
338
339 static int detect_primary_address_change(struct interface *ifp,
340 int force_prim_as_any,
341 const char *caller)
342 {
343 struct pim_interface *pim_ifp = ifp->info;
344 struct in_addr new_prim_addr;
345 int changed;
346
347 if (force_prim_as_any)
348 new_prim_addr.s_addr = INADDR_ANY;
349 else
350 new_prim_addr = pim_find_primary_addr(ifp);
351
352 changed = new_prim_addr.s_addr != pim_ifp->primary_address.s_addr;
353
354 if (PIM_DEBUG_ZEBRA) {
355 char new_prim_str[INET_ADDRSTRLEN];
356 char old_prim_str[INET_ADDRSTRLEN];
357 pim_inet4_dump("<new?>", new_prim_addr, new_prim_str,
358 sizeof(new_prim_str));
359 pim_inet4_dump("<old?>", pim_ifp->primary_address, old_prim_str,
360 sizeof(old_prim_str));
361 zlog_debug("%s: old=%s new=%s on interface %s: %s",
362 __PRETTY_FUNCTION__, old_prim_str, new_prim_str,
363 ifp->name, changed ? "changed" : "unchanged");
364 }
365
366 if (changed) {
367 pim_ifp->primary_address = new_prim_addr;
368 }
369
370 return changed;
371 }
372
373 static struct pim_secondary_addr *
374 pim_sec_addr_find(struct pim_interface *pim_ifp, struct prefix *addr)
375 {
376 struct pim_secondary_addr *sec_addr;
377 struct listnode *node;
378
379 for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) {
380 if (prefix_cmp(&sec_addr->addr, addr)) {
381 return sec_addr;
382 }
383 }
384
385 return NULL;
386 }
387
388 static void pim_sec_addr_del(struct pim_interface *pim_ifp,
389 struct pim_secondary_addr *sec_addr)
390 {
391 listnode_delete(pim_ifp->sec_addr_list, sec_addr);
392 pim_sec_addr_free(sec_addr);
393 }
394
395 static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct prefix *addr)
396 {
397 int changed = 0;
398 struct pim_secondary_addr *sec_addr;
399
400 sec_addr = pim_sec_addr_find(pim_ifp, addr);
401 if (sec_addr) {
402 sec_addr->flags &= ~PIM_SEC_ADDRF_STALE;
403 return changed;
404 }
405
406 sec_addr = XCALLOC(MTYPE_PIM_SEC_ADDR, sizeof(*sec_addr));
407 if (!sec_addr)
408 return changed;
409
410 changed = 1;
411 sec_addr->addr = *addr;
412 listnode_add_sort(pim_ifp->sec_addr_list, sec_addr);
413
414 return changed;
415 }
416
417 static int pim_sec_addr_del_all(struct pim_interface *pim_ifp)
418 {
419 int changed = 0;
420
421 if (!list_isempty(pim_ifp->sec_addr_list)) {
422 changed = 1;
423 /* remove all nodes and free up the list itself */
424 list_delete_all_node(pim_ifp->sec_addr_list);
425 }
426
427 return changed;
428 }
429
430 static int pim_sec_addr_update(struct interface *ifp)
431 {
432 struct pim_interface *pim_ifp = ifp->info;
433 struct connected *ifc;
434 struct listnode *node;
435 struct listnode *nextnode;
436 struct pim_secondary_addr *sec_addr;
437 int changed = 0;
438
439 for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) {
440 sec_addr->flags |= PIM_SEC_ADDRF_STALE;
441 }
442
443 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
444 struct prefix *p = ifc->address;
445
446 if (PIM_INADDR_IS_ANY(p->u.prefix4)) {
447 continue;
448 }
449
450 if (pim_ifp->primary_address.s_addr == p->u.prefix4.s_addr) {
451 /* don't add the primary address into the secondary
452 * address list */
453 continue;
454 }
455
456 if (pim_sec_addr_add(pim_ifp, p)) {
457 changed = 1;
458 }
459 }
460
461 /* Drop stale entries */
462 for (ALL_LIST_ELEMENTS(pim_ifp->sec_addr_list, node, nextnode,
463 sec_addr)) {
464 if (sec_addr->flags & PIM_SEC_ADDRF_STALE) {
465 pim_sec_addr_del(pim_ifp, sec_addr);
466 changed = 1;
467 }
468 }
469
470 return changed;
471 }
472
473 static int detect_secondary_address_change(struct interface *ifp,
474 int force_prim_as_any,
475 const char *caller)
476 {
477 struct pim_interface *pim_ifp = ifp->info;
478 int changed = 0;
479
480 if (force_prim_as_any) {
481 /* if primary address is being forced to zero just flush the
482 * secondary address list */
483 changed = pim_sec_addr_del_all(pim_ifp);
484 } else {
485 /* re-evaluate the secondary address list */
486 changed = pim_sec_addr_update(ifp);
487 }
488
489 return changed;
490 }
491
492 static void detect_address_change(struct interface *ifp, int force_prim_as_any,
493 const char *caller)
494 {
495 int changed = 0;
496 struct pim_interface *pim_ifp;
497
498 pim_ifp = ifp->info;
499 if (!pim_ifp)
500 return;
501
502 if (detect_primary_address_change(ifp, force_prim_as_any, caller)) {
503 changed = 1;
504 }
505
506 if (detect_secondary_address_change(ifp, force_prim_as_any, caller)) {
507 changed = 1;
508 }
509
510
511 if (changed) {
512 if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
513 return;
514 }
515
516 pim_addr_change(ifp);
517 }
518
519 /* XXX: if we have unnumbered interfaces we need to run detect address
520 * address change on all of them when the lo address changes */
521 }
522
523 int pim_update_source_set(struct interface *ifp, struct in_addr source)
524 {
525 struct pim_interface *pim_ifp = ifp->info;
526
527 if (!pim_ifp) {
528 return PIM_IFACE_NOT_FOUND;
529 }
530
531 if (pim_ifp->update_source.s_addr == source.s_addr) {
532 return PIM_UPDATE_SOURCE_DUP;
533 }
534
535 pim_ifp->update_source = source;
536 detect_address_change(ifp, 0 /* force_prim_as_any */,
537 __PRETTY_FUNCTION__);
538
539 return PIM_SUCCESS;
540 }
541
542 void pim_if_addr_add(struct connected *ifc)
543 {
544 struct pim_interface *pim_ifp;
545 struct interface *ifp;
546 struct in_addr ifaddr;
547
548 zassert(ifc);
549
550 ifp = ifc->ifp;
551 zassert(ifp);
552 pim_ifp = ifp->info;
553 if (!pim_ifp)
554 return;
555
556 if (!if_is_operative(ifp))
557 return;
558
559 if (PIM_DEBUG_ZEBRA) {
560 char buf[BUFSIZ];
561 prefix2str(ifc->address, buf, BUFSIZ);
562 zlog_debug("%s: %s ifindex=%d connected IP address %s %s",
563 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, buf,
564 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
565 ? "secondary"
566 : "primary");
567 }
568
569 ifaddr = ifc->address->u.prefix4;
570
571 detect_address_change(ifp, 0, __PRETTY_FUNCTION__);
572
573 // if (ifc->address->family != AF_INET)
574 // return;
575
576 if (PIM_IF_TEST_IGMP(pim_ifp->options)) {
577 struct igmp_sock *igmp;
578
579 /* lookup IGMP socket */
580 igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list,
581 ifaddr);
582 if (!igmp) {
583 /* if addr new, add IGMP socket */
584 if (ifc->address->family == AF_INET)
585 pim_igmp_sock_add(pim_ifp->igmp_socket_list,
586 ifaddr, ifp, false);
587 } else if (igmp->mtrace_only) {
588 igmp_sock_delete(igmp);
589 pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr,
590 ifp, false);
591 }
592
593 /* Replay Static IGMP groups */
594 if (pim_ifp->igmp_join_list) {
595 struct listnode *node;
596 struct listnode *nextnode;
597 struct igmp_join *ij;
598 int join_fd;
599
600 for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node,
601 nextnode, ij)) {
602 /* Close socket and reopen with Source and Group
603 */
604 close(ij->sock_fd);
605 join_fd = igmp_join_sock(
606 ifp->name, ifp->ifindex, ij->group_addr,
607 ij->source_addr);
608 if (join_fd < 0) {
609 char group_str[INET_ADDRSTRLEN];
610 char source_str[INET_ADDRSTRLEN];
611 pim_inet4_dump("<grp?>", ij->group_addr,
612 group_str,
613 sizeof(group_str));
614 pim_inet4_dump(
615 "<src?>", ij->source_addr,
616 source_str, sizeof(source_str));
617 zlog_warn(
618 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
619 __PRETTY_FUNCTION__, group_str,
620 source_str, ifp->name);
621 /* warning only */
622 } else
623 ij->sock_fd = join_fd;
624 }
625 }
626 } /* igmp */
627 else {
628 struct igmp_sock *igmp;
629
630 /* lookup IGMP socket */
631 igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list,
632 ifaddr);
633 if (ifc->address->family == AF_INET) {
634 if (igmp)
635 igmp_sock_delete(igmp);
636 /* if addr new, add IGMP socket */
637 pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr,
638 ifp, true);
639 }
640 } /* igmp mtrace only */
641
642 if (PIM_IF_TEST_PIM(pim_ifp->options)) {
643
644 if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
645
646 /* Interface has a valid socket ? */
647 if (pim_ifp->pim_sock_fd < 0) {
648 if (pim_sock_add(ifp)) {
649 zlog_warn(
650 "Failure creating PIM socket for interface %s",
651 ifp->name);
652 }
653 }
654 struct pim_nexthop_cache *pnc = NULL;
655 struct pim_rpf rpf;
656 struct zclient *zclient = NULL;
657
658 zclient = pim_zebra_zclient_get();
659 /* RP config might come prior to (local RP's interface)
660 IF UP event.
661 In this case, pnc would not have pim enabled
662 nexthops.
663 Once Interface is UP and pim info is available,
664 reregister
665 with RNH address to receive update and add the
666 interface as nexthop. */
667 memset(&rpf, 0, sizeof(struct pim_rpf));
668 rpf.rpf_addr.family = AF_INET;
669 rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN;
670 rpf.rpf_addr.u.prefix4 = ifc->address->u.prefix4;
671 pnc = pim_nexthop_cache_find(pim_ifp->pim, &rpf);
672 if (pnc)
673 pim_sendmsg_zebra_rnh(pim_ifp->pim, zclient,
674 pnc,
675 ZEBRA_NEXTHOP_REGISTER);
676 }
677 } /* pim */
678
679 /*
680 PIM or IGMP is enabled on interface, and there is at least one
681 address assigned, then try to create a vif_index.
682 */
683 if (pim_ifp->mroute_vif_index < 0) {
684 pim_if_add_vif(ifp);
685 }
686 pim_ifchannel_scan_forward_start(ifp);
687 }
688
689 static void pim_if_addr_del_igmp(struct connected *ifc)
690 {
691 struct pim_interface *pim_ifp = ifc->ifp->info;
692 struct igmp_sock *igmp;
693 struct in_addr ifaddr;
694
695 if (ifc->address->family != AF_INET) {
696 /* non-IPv4 address */
697 return;
698 }
699
700 if (!pim_ifp) {
701 /* IGMP not enabled on interface */
702 return;
703 }
704
705 ifaddr = ifc->address->u.prefix4;
706
707 /* lookup IGMP socket */
708 igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr);
709 if (igmp) {
710 /* if addr found, del IGMP socket */
711 igmp_sock_delete(igmp);
712 }
713 }
714
715 static void pim_if_addr_del_pim(struct connected *ifc)
716 {
717 struct pim_interface *pim_ifp = ifc->ifp->info;
718
719 if (ifc->address->family != AF_INET) {
720 /* non-IPv4 address */
721 return;
722 }
723
724 if (!pim_ifp) {
725 /* PIM not enabled on interface */
726 return;
727 }
728
729 if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
730 /* Interface keeps a valid primary address */
731 return;
732 }
733
734 if (pim_ifp->pim_sock_fd < 0) {
735 /* Interface does not hold a valid socket any longer */
736 return;
737 }
738
739 /*
740 pim_sock_delete() closes the socket, stops read and timer threads,
741 and kills all neighbors.
742 */
743 pim_sock_delete(ifc->ifp,
744 "last address has been removed from interface");
745 }
746
747 void pim_if_addr_del(struct connected *ifc, int force_prim_as_any)
748 {
749 struct interface *ifp;
750
751 zassert(ifc);
752 ifp = ifc->ifp;
753 zassert(ifp);
754
755 if (PIM_DEBUG_ZEBRA) {
756 char buf[BUFSIZ];
757 prefix2str(ifc->address, buf, BUFSIZ);
758 zlog_debug("%s: %s ifindex=%d disconnected IP address %s %s",
759 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, buf,
760 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
761 ? "secondary"
762 : "primary");
763 }
764
765 detect_address_change(ifp, force_prim_as_any, __PRETTY_FUNCTION__);
766
767 pim_if_addr_del_igmp(ifc);
768 pim_if_addr_del_pim(ifc);
769 }
770
771 void pim_if_addr_add_all(struct interface *ifp)
772 {
773 struct connected *ifc;
774 struct listnode *node;
775 struct listnode *nextnode;
776 int v4_addrs = 0;
777 int v6_addrs = 0;
778 struct pim_interface *pim_ifp = ifp->info;
779
780
781 /* PIM/IGMP enabled ? */
782 if (!pim_ifp)
783 return;
784
785 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
786 struct prefix *p = ifc->address;
787
788 if (p->family != AF_INET)
789 v6_addrs++;
790 else
791 v4_addrs++;
792 pim_if_addr_add(ifc);
793 }
794
795 if (!v4_addrs && v6_addrs && !if_is_loopback(ifp)) {
796 if (PIM_IF_TEST_PIM(pim_ifp->options)) {
797
798 /* Interface has a valid primary address ? */
799 if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
800
801 /* Interface has a valid socket ? */
802 if (pim_ifp->pim_sock_fd < 0) {
803 if (pim_sock_add(ifp)) {
804 zlog_warn(
805 "Failure creating PIM socket for interface %s",
806 ifp->name);
807 }
808 }
809 }
810 } /* pim */
811 }
812 /*
813 * PIM or IGMP is enabled on interface, and there is at least one
814 * address assigned, then try to create a vif_index.
815 */
816 if (pim_ifp->mroute_vif_index < 0) {
817 pim_if_add_vif(ifp);
818 }
819 pim_ifchannel_scan_forward_start(ifp);
820
821 pim_rp_setup(pim_ifp->pim);
822 pim_rp_check_on_if_add(pim_ifp);
823 }
824
825 void pim_if_addr_del_all(struct interface *ifp)
826 {
827 struct connected *ifc;
828 struct listnode *node;
829 struct listnode *nextnode;
830 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
831 struct pim_instance *pim;
832
833 if (!vrf)
834 return;
835 pim = vrf->info;
836
837 /* PIM/IGMP enabled ? */
838 if (!ifp->info)
839 return;
840
841 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
842 struct prefix *p = ifc->address;
843
844 if (p->family != AF_INET)
845 continue;
846
847 pim_if_addr_del(ifc, 1 /* force_prim_as_any=true */);
848 }
849
850 pim_rp_setup(pim);
851 pim_i_am_rp_re_evaluate(pim);
852 }
853
854 void pim_if_addr_del_all_igmp(struct interface *ifp)
855 {
856 struct connected *ifc;
857 struct listnode *node;
858 struct listnode *nextnode;
859
860 /* PIM/IGMP enabled ? */
861 if (!ifp->info)
862 return;
863
864 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
865 struct prefix *p = ifc->address;
866
867 if (p->family != AF_INET)
868 continue;
869
870 pim_if_addr_del_igmp(ifc);
871 }
872 }
873
874 void pim_if_addr_del_all_pim(struct interface *ifp)
875 {
876 struct connected *ifc;
877 struct listnode *node;
878 struct listnode *nextnode;
879
880 /* PIM/IGMP enabled ? */
881 if (!ifp->info)
882 return;
883
884 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
885 struct prefix *p = ifc->address;
886
887 if (p->family != AF_INET)
888 continue;
889
890 pim_if_addr_del_pim(ifc);
891 }
892 }
893
894 struct in_addr pim_find_primary_addr(struct interface *ifp)
895 {
896 struct connected *ifc;
897 struct listnode *node;
898 struct in_addr addr = {0};
899 int v4_addrs = 0;
900 int v6_addrs = 0;
901 struct pim_interface *pim_ifp = ifp->info;
902 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
903
904 if (!vrf)
905 return addr;
906
907 if (pim_ifp && PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) {
908 return pim_ifp->update_source;
909 }
910
911 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
912 struct prefix *p = ifc->address;
913
914 if (p->family != AF_INET) {
915 v6_addrs++;
916 continue;
917 }
918
919 if (PIM_INADDR_IS_ANY(p->u.prefix4)) {
920 zlog_warn(
921 "%s: null IPv4 address connected to interface %s",
922 __PRETTY_FUNCTION__, ifp->name);
923 continue;
924 }
925
926 v4_addrs++;
927
928 if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
929 continue;
930
931 return p->u.prefix4;
932 }
933
934 /*
935 * If we have no v4_addrs and v6 is configured
936 * We probably are using unnumbered
937 * So let's grab the loopbacks v4 address
938 * and use that as the primary address
939 */
940 if (!v4_addrs && v6_addrs && !if_is_loopback(ifp)) {
941 struct interface *lo_ifp;
942 // DBS - Come back and check here
943 if (ifp->vrf_id == VRF_DEFAULT)
944 lo_ifp = if_lookup_by_name("lo", vrf->vrf_id);
945 else
946 lo_ifp = if_lookup_by_name(vrf->name, vrf->vrf_id);
947
948 if (lo_ifp)
949 return pim_find_primary_addr(lo_ifp);
950 }
951
952 addr.s_addr = PIM_NET_INADDR_ANY;
953
954 return addr;
955 }
956
957 static int pim_iface_next_vif_index(struct interface *ifp)
958 {
959 struct pim_interface *pim_ifp = ifp->info;
960 struct pim_instance *pim = pim_ifp->pim;
961 int i;
962
963 /*
964 * The pimreg vif is always going to be in index 0
965 * of the table.
966 */
967 if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF)
968 return 0;
969
970 for (i = 1; i < MAXVIFS; i++) {
971 if (pim->iface_vif_index[i] == 0)
972 return i;
973 }
974 return MAXVIFS;
975 }
976
977 /*
978 pim_if_add_vif() uses ifindex as vif_index
979
980 see also pim_if_find_vifindex_by_ifindex()
981 */
982 int pim_if_add_vif(struct interface *ifp)
983 {
984 struct pim_interface *pim_ifp = ifp->info;
985 struct in_addr ifaddr;
986 unsigned char flags = 0;
987
988 zassert(pim_ifp);
989
990 if (pim_ifp->mroute_vif_index > 0) {
991 zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d",
992 __PRETTY_FUNCTION__, pim_ifp->mroute_vif_index,
993 ifp->name, ifp->ifindex);
994 return -1;
995 }
996
997 if (ifp->ifindex < 0) {
998 zlog_warn("%s: ifindex=%d < 1 on interface %s",
999 __PRETTY_FUNCTION__, ifp->ifindex, ifp->name);
1000 return -2;
1001 }
1002
1003 ifaddr = pim_ifp->primary_address;
1004 if (ifp->ifindex != PIM_OIF_PIM_REGISTER_VIF
1005 && PIM_INADDR_IS_ANY(ifaddr)) {
1006 zlog_warn(
1007 "%s: could not get address for interface %s ifindex=%d",
1008 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex);
1009 return -4;
1010 }
1011
1012 pim_ifp->mroute_vif_index = pim_iface_next_vif_index(ifp);
1013
1014 if (pim_ifp->mroute_vif_index >= MAXVIFS) {
1015 zlog_warn(
1016 "%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s",
1017 __PRETTY_FUNCTION__, MAXVIFS, ifp->name);
1018 return -3;
1019 }
1020
1021 if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF)
1022 flags = VIFF_REGISTER;
1023 #ifdef VIFF_USE_IFINDEX
1024 else
1025 flags = VIFF_USE_IFINDEX;
1026 #endif
1027
1028 if (pim_mroute_add_vif(ifp, ifaddr, flags)) {
1029 /* pim_mroute_add_vif reported error */
1030 return -5;
1031 }
1032
1033 pim_ifp->pim->iface_vif_index[pim_ifp->mroute_vif_index] = 1;
1034 return 0;
1035 }
1036
1037 int pim_if_del_vif(struct interface *ifp)
1038 {
1039 struct pim_interface *pim_ifp = ifp->info;
1040
1041 if (pim_ifp->mroute_vif_index < 1) {
1042 zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d",
1043 __PRETTY_FUNCTION__, pim_ifp->mroute_vif_index,
1044 ifp->name, ifp->ifindex);
1045 return -1;
1046 }
1047
1048 pim_mroute_del_vif(ifp);
1049
1050 /*
1051 Update vif_index
1052 */
1053 pim_ifp->pim->iface_vif_index[pim_ifp->mroute_vif_index] = 0;
1054
1055 pim_ifp->mroute_vif_index = -1;
1056
1057 return 0;
1058 }
1059
1060 // DBS - VRF Revist
1061 struct interface *pim_if_find_by_vif_index(struct pim_instance *pim,
1062 ifindex_t vif_index)
1063 {
1064 struct interface *ifp;
1065
1066 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1067 if (ifp->info) {
1068 struct pim_interface *pim_ifp;
1069 pim_ifp = ifp->info;
1070
1071 if (vif_index == pim_ifp->mroute_vif_index)
1072 return ifp;
1073 }
1074 }
1075
1076 return 0;
1077 }
1078
1079 /*
1080 pim_if_add_vif() uses ifindex as vif_index
1081 */
1082 int pim_if_find_vifindex_by_ifindex(struct pim_instance *pim, ifindex_t ifindex)
1083 {
1084 struct pim_interface *pim_ifp;
1085 struct interface *ifp;
1086
1087 ifp = if_lookup_by_index(ifindex, pim->vrf_id);
1088 if (!ifp || !ifp->info)
1089 return -1;
1090 pim_ifp = ifp->info;
1091
1092 return pim_ifp->mroute_vif_index;
1093 }
1094
1095 int pim_if_lan_delay_enabled(struct interface *ifp)
1096 {
1097 struct pim_interface *pim_ifp;
1098
1099 pim_ifp = ifp->info;
1100 zassert(pim_ifp);
1101 zassert(pim_ifp->pim_number_of_nonlandelay_neighbors >= 0);
1102
1103 return pim_ifp->pim_number_of_nonlandelay_neighbors == 0;
1104 }
1105
1106 uint16_t pim_if_effective_propagation_delay_msec(struct interface *ifp)
1107 {
1108 if (pim_if_lan_delay_enabled(ifp)) {
1109 struct pim_interface *pim_ifp;
1110 pim_ifp = ifp->info;
1111 return pim_ifp->pim_neighbors_highest_propagation_delay_msec;
1112 } else {
1113 return PIM_DEFAULT_PROPAGATION_DELAY_MSEC;
1114 }
1115 }
1116
1117 uint16_t pim_if_effective_override_interval_msec(struct interface *ifp)
1118 {
1119 if (pim_if_lan_delay_enabled(ifp)) {
1120 struct pim_interface *pim_ifp;
1121 pim_ifp = ifp->info;
1122 return pim_ifp->pim_neighbors_highest_override_interval_msec;
1123 } else {
1124 return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC;
1125 }
1126 }
1127
1128 int pim_if_t_override_msec(struct interface *ifp)
1129 {
1130 int effective_override_interval_msec;
1131 int t_override_msec;
1132
1133 effective_override_interval_msec =
1134 pim_if_effective_override_interval_msec(ifp);
1135
1136 t_override_msec = random() % (effective_override_interval_msec + 1);
1137
1138 return t_override_msec;
1139 }
1140
1141 uint16_t pim_if_jp_override_interval_msec(struct interface *ifp)
1142 {
1143 return pim_if_effective_propagation_delay_msec(ifp)
1144 + pim_if_effective_override_interval_msec(ifp);
1145 }
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,
1157 struct in_addr addr)
1158 {
1159 struct listnode *neighnode;
1160 struct pim_neighbor *neigh;
1161 struct pim_interface *pim_ifp;
1162 struct prefix p;
1163
1164 zassert(ifp);
1165
1166 pim_ifp = ifp->info;
1167 if (!pim_ifp) {
1168 zlog_warn("%s: multicast not enabled on interface %s",
1169 __PRETTY_FUNCTION__, ifp->name);
1170 return 0;
1171 }
1172
1173 p.family = AF_INET;
1174 p.u.prefix4 = addr;
1175 p.prefixlen = IPV4_MAX_PREFIXLEN;
1176
1177 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
1178 neigh)) {
1179
1180 /* primary address ? */
1181 if (neigh->source_addr.s_addr == addr.s_addr)
1182 return neigh;
1183
1184 /* secondary address ? */
1185 if (pim_neighbor_find_secondary(neigh, &p))
1186 return neigh;
1187 }
1188
1189 if (PIM_DEBUG_PIM_TRACE) {
1190 char addr_str[INET_ADDRSTRLEN];
1191 pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
1192 zlog_debug(
1193 "%s: neighbor not found for address %s on interface %s",
1194 __PRETTY_FUNCTION__, addr_str, ifp->name);
1195 }
1196
1197 return NULL;
1198 }
1199
1200 long pim_if_t_suppressed_msec(struct interface *ifp)
1201 {
1202 struct pim_interface *pim_ifp;
1203 long t_suppressed_msec;
1204 uint32_t ramount = 0;
1205
1206 pim_ifp = ifp->info;
1207 zassert(pim_ifp);
1208
1209 /* join suppression disabled ? */
1210 if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options))
1211 return 0;
1212
1213 /* t_suppressed = t_periodic * rand(1.1, 1.4) */
1214 ramount = 1100 + (random() % (1400 - 1100 + 1));
1215 t_suppressed_msec = qpim_t_periodic * ramount;
1216
1217 return t_suppressed_msec;
1218 }
1219
1220 static void igmp_join_free(struct igmp_join *ij)
1221 {
1222 XFREE(MTYPE_PIM_IGMP_JOIN, ij);
1223 }
1224
1225 static struct igmp_join *igmp_join_find(struct list *join_list,
1226 struct in_addr group_addr,
1227 struct in_addr source_addr)
1228 {
1229 struct listnode *node;
1230 struct igmp_join *ij;
1231
1232 zassert(join_list);
1233
1234 for (ALL_LIST_ELEMENTS_RO(join_list, node, ij)) {
1235 if ((group_addr.s_addr == ij->group_addr.s_addr)
1236 && (source_addr.s_addr == ij->source_addr.s_addr))
1237 return ij;
1238 }
1239
1240 return 0;
1241 }
1242
1243 static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
1244 struct in_addr group_addr, struct in_addr source_addr)
1245 {
1246 int join_fd;
1247
1248 join_fd = pim_socket_raw(IPPROTO_IGMP);
1249 if (join_fd < 0) {
1250 return -1;
1251 }
1252
1253 if (pim_socket_join_source(join_fd, ifindex, group_addr, source_addr,
1254 ifname)) {
1255 close(join_fd);
1256 return -2;
1257 }
1258
1259 return join_fd;
1260 }
1261
1262 static struct igmp_join *igmp_join_new(struct interface *ifp,
1263 struct in_addr group_addr,
1264 struct in_addr source_addr)
1265 {
1266 struct pim_interface *pim_ifp;
1267 struct igmp_join *ij;
1268 int join_fd;
1269
1270 pim_ifp = ifp->info;
1271 zassert(pim_ifp);
1272
1273 join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr,
1274 source_addr);
1275 if (join_fd < 0) {
1276 char group_str[INET_ADDRSTRLEN];
1277 char source_str[INET_ADDRSTRLEN];
1278 pim_inet4_dump("<grp?>", group_addr, group_str,
1279 sizeof(group_str));
1280 pim_inet4_dump("<src?>", source_addr, source_str,
1281 sizeof(source_str));
1282 zlog_warn(
1283 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
1284 __PRETTY_FUNCTION__, group_str, source_str, ifp->name);
1285 return 0;
1286 }
1287
1288 ij = XCALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij));
1289 if (!ij) {
1290 char group_str[INET_ADDRSTRLEN];
1291 char source_str[INET_ADDRSTRLEN];
1292 pim_inet4_dump("<grp?>", group_addr, group_str,
1293 sizeof(group_str));
1294 pim_inet4_dump("<src?>", source_addr, source_str,
1295 sizeof(source_str));
1296 zlog_err(
1297 "%s: XCALLOC(%zu) failure for IGMP group %s source %s on interface %s",
1298 __PRETTY_FUNCTION__, sizeof(*ij), group_str, source_str,
1299 ifp->name);
1300 close(join_fd);
1301 return 0;
1302 }
1303
1304 ij->sock_fd = join_fd;
1305 ij->group_addr = group_addr;
1306 ij->source_addr = source_addr;
1307 ij->sock_creation = pim_time_monotonic_sec();
1308
1309 listnode_add(pim_ifp->igmp_join_list, ij);
1310
1311 return ij;
1312 }
1313
1314 ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr,
1315 struct in_addr source_addr)
1316 {
1317 struct pim_interface *pim_ifp;
1318 struct igmp_join *ij;
1319
1320 pim_ifp = ifp->info;
1321 if (!pim_ifp) {
1322 return ferr_cfg_invalid("multicast not enabled on interface %s",
1323 ifp->name);
1324 }
1325
1326 if (!pim_ifp->igmp_join_list) {
1327 pim_ifp->igmp_join_list = list_new();
1328 if (!pim_ifp->igmp_join_list) {
1329 return ferr_cfg_invalid("Insufficient memory");
1330 }
1331 pim_ifp->igmp_join_list->del = (void (*)(void *))igmp_join_free;
1332 }
1333
1334 ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr);
1335
1336 /* This interface has already been configured to join this IGMP group
1337 */
1338 if (ij) {
1339 return ferr_ok();
1340 }
1341
1342 ij = igmp_join_new(ifp, group_addr, source_addr);
1343 if (!ij) {
1344 return ferr_cfg_invalid(
1345 "Failure to create new join data structure, see log file for more information");
1346 }
1347
1348 if (PIM_DEBUG_IGMP_EVENTS) {
1349 char group_str[INET_ADDRSTRLEN];
1350 char source_str[INET_ADDRSTRLEN];
1351 pim_inet4_dump("<grp?>", group_addr, group_str,
1352 sizeof(group_str));
1353 pim_inet4_dump("<src?>", source_addr, source_str,
1354 sizeof(source_str));
1355 zlog_debug(
1356 "%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s",
1357 __PRETTY_FUNCTION__, source_str, group_str, ifp->name);
1358 }
1359
1360 return ferr_ok();
1361 }
1362
1363
1364 int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr,
1365 struct in_addr source_addr)
1366 {
1367 struct pim_interface *pim_ifp;
1368 struct igmp_join *ij;
1369
1370 pim_ifp = ifp->info;
1371 if (!pim_ifp) {
1372 zlog_warn("%s: multicast not enabled on interface %s",
1373 __PRETTY_FUNCTION__, ifp->name);
1374 return -1;
1375 }
1376
1377 if (!pim_ifp->igmp_join_list) {
1378 zlog_warn("%s: no IGMP join on interface %s",
1379 __PRETTY_FUNCTION__, ifp->name);
1380 return -2;
1381 }
1382
1383 ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr);
1384 if (!ij) {
1385 char group_str[INET_ADDRSTRLEN];
1386 char source_str[INET_ADDRSTRLEN];
1387 pim_inet4_dump("<grp?>", group_addr, group_str,
1388 sizeof(group_str));
1389 pim_inet4_dump("<src?>", source_addr, source_str,
1390 sizeof(source_str));
1391 zlog_warn(
1392 "%s: could not find IGMP group %s source %s on interface %s",
1393 __PRETTY_FUNCTION__, group_str, source_str, ifp->name);
1394 return -3;
1395 }
1396
1397 if (close(ij->sock_fd)) {
1398 char group_str[INET_ADDRSTRLEN];
1399 char source_str[INET_ADDRSTRLEN];
1400 pim_inet4_dump("<grp?>", group_addr, group_str,
1401 sizeof(group_str));
1402 pim_inet4_dump("<src?>", source_addr, source_str,
1403 sizeof(source_str));
1404 zlog_warn(
1405 "%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s",
1406 __PRETTY_FUNCTION__, ij->sock_fd, group_str, source_str,
1407 ifp->name, errno, safe_strerror(errno));
1408 /* warning only */
1409 }
1410 listnode_delete(pim_ifp->igmp_join_list, ij);
1411 igmp_join_free(ij);
1412 if (listcount(pim_ifp->igmp_join_list) < 1) {
1413 list_delete_and_null(&pim_ifp->igmp_join_list);
1414 pim_ifp->igmp_join_list = 0;
1415 }
1416
1417 return 0;
1418 }
1419
1420 static void pim_if_igmp_join_del_all(struct interface *ifp)
1421 {
1422 struct pim_interface *pim_ifp;
1423 struct listnode *node;
1424 struct listnode *nextnode;
1425 struct igmp_join *ij;
1426
1427 pim_ifp = ifp->info;
1428 if (!pim_ifp) {
1429 zlog_warn("%s: multicast not enabled on interface %s",
1430 __PRETTY_FUNCTION__, ifp->name);
1431 return;
1432 }
1433
1434 if (!pim_ifp->igmp_join_list)
1435 return;
1436
1437 for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node, nextnode, ij))
1438 pim_if_igmp_join_del(ifp, ij->group_addr, ij->source_addr);
1439 }
1440
1441 /*
1442 RFC 4601
1443
1444 Transitions from "I am Assert Loser" State
1445
1446 Current Winner's GenID Changes or NLT Expires
1447
1448 The Neighbor Liveness Timer associated with the current winner
1449 expires or we receive a Hello message from the current winner
1450 reporting a different GenID from the one it previously reported.
1451 This indicates that the current winner's interface or router has
1452 gone down (and may have come back up), and so we must assume it no
1453 longer knows it was the winner.
1454 */
1455 void pim_if_assert_on_neighbor_down(struct interface *ifp,
1456 struct in_addr neigh_addr)
1457 {
1458 struct pim_interface *pim_ifp;
1459 struct pim_ifchannel *ch;
1460
1461 pim_ifp = ifp->info;
1462 zassert(pim_ifp);
1463
1464 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1465 /* Is (S,G,I) assert loser ? */
1466 if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER)
1467 continue;
1468 /* Dead neighbor was winner ? */
1469 if (ch->ifassert_winner.s_addr != neigh_addr.s_addr)
1470 continue;
1471
1472 assert_action_a5(ch);
1473 }
1474 }
1475
1476 void pim_if_update_join_desired(struct pim_interface *pim_ifp)
1477 {
1478 struct pim_ifchannel *ch;
1479
1480 /* clear off flag from interface's upstreams */
1481 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1482 PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(
1483 ch->upstream->flags);
1484 }
1485
1486 /* scan per-interface (S,G,I) state on this I interface */
1487 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1488 struct pim_upstream *up = ch->upstream;
1489
1490 if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up->flags))
1491 continue;
1492
1493 /* update join_desired for the global (S,G) state */
1494 pim_upstream_update_join_desired(pim_ifp->pim, up);
1495 PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up->flags);
1496 }
1497 }
1498
1499 void pim_if_update_assert_tracking_desired(struct interface *ifp)
1500 {
1501 struct pim_interface *pim_ifp;
1502 struct pim_ifchannel *ch;
1503
1504 pim_ifp = ifp->info;
1505 if (!pim_ifp)
1506 return;
1507
1508 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1509 pim_ifchannel_update_assert_tracking_desired(ch);
1510 }
1511 }
1512
1513 /*
1514 * PIM wants to have an interface pointer for everything it does.
1515 * The pimreg is a special interface that we have that is not
1516 * quite an inteface but a VIF is created for it.
1517 */
1518 void pim_if_create_pimreg(struct pim_instance *pim)
1519 {
1520 char pimreg_name[INTERFACE_NAMSIZ];
1521
1522 if (!pim->regiface) {
1523 if (pim->vrf_id == VRF_DEFAULT)
1524 strlcpy(pimreg_name, "pimreg", sizeof(pimreg_name));
1525 else
1526 snprintf(pimreg_name, sizeof(pimreg_name), "pimreg%u",
1527 pim->vrf->data.l.table_id);
1528
1529 pim->regiface = if_create(pimreg_name, pim->vrf_id);
1530 pim->regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF;
1531
1532 pim_if_new(pim->regiface, 0, 0);
1533 }
1534 }
1535
1536 int pim_if_connected_to_source(struct interface *ifp, struct in_addr src)
1537 {
1538 struct listnode *cnode;
1539 struct connected *c;
1540 struct prefix p;
1541
1542 if (!ifp)
1543 return 0;
1544
1545 p.family = AF_INET;
1546 p.u.prefix4 = src;
1547 p.prefixlen = IPV4_MAX_BITLEN;
1548
1549 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
1550 if ((c->address->family == AF_INET)
1551 && prefix_match(CONNECTED_PREFIX(c), &p)) {
1552 return 1;
1553 }
1554 }
1555
1556 return 0;
1557 }
1558
1559 bool pim_if_is_loopback(struct interface *ifp)
1560 {
1561 if (if_is_loopback(ifp) || if_is_vrf(ifp))
1562 return true;
1563
1564 return false;
1565 }
1566
1567 bool pim_if_is_vrf_device(struct interface *ifp)
1568 {
1569 if (if_is_vrf(ifp))
1570 return true;
1571
1572 return false;
1573 }
1574
1575 int pim_if_ifchannel_count(struct pim_interface *pim_ifp)
1576 {
1577 struct pim_ifchannel *ch;
1578 int count = 0;
1579
1580 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1581 count++;
1582 }
1583
1584 return count;
1585 }