]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_mroute.c
*: auto-convert to SPDX License IDs
[mirror_frr.git] / pimd / pim_mroute.c
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 #include "log.h"
9 #include "privs.h"
10 #include "if.h"
11 #include "prefix.h"
12 #include "vty.h"
13 #include "plist.h"
14 #include "sockopt.h"
15 #include "lib_errors.h"
16 #include "lib/network.h"
17
18 #include "pimd.h"
19 #include "pim_rpf.h"
20 #include "pim_mroute.h"
21 #include "pim_oil.h"
22 #include "pim_str.h"
23 #include "pim_time.h"
24 #include "pim_iface.h"
25 #include "pim_macro.h"
26 #include "pim_rp.h"
27 #include "pim_oil.h"
28 #include "pim_register.h"
29 #include "pim_ifchannel.h"
30 #include "pim_zlookup.h"
31 #include "pim_ssm.h"
32 #include "pim_sock.h"
33 #include "pim_vxlan.h"
34 #include "pim_msg.h"
35
36 static void mroute_read_on(struct pim_instance *pim);
37
38 int pim_mroute_set(struct pim_instance *pim, int enable)
39 {
40 int err;
41 int opt, data;
42 socklen_t data_len = sizeof(data);
43
44 /*
45 * We need to create the VRF table for the pim mroute_socket
46 */
47 if (pim->vrf->vrf_id != VRF_DEFAULT) {
48 frr_with_privs (&pimd_privs) {
49
50 data = pim->vrf->data.l.table_id;
51 err = setsockopt(pim->mroute_socket, PIM_IPPROTO,
52 MRT_TABLE, &data, data_len);
53 if (err) {
54 zlog_warn(
55 "%s %s: failure: setsockopt(fd=%d,PIM_IPPROTO, MRT_TABLE=%d): errno=%d: %s",
56 __FILE__, __func__, pim->mroute_socket,
57 data, errno, safe_strerror(errno));
58 return -1;
59 }
60 }
61 }
62
63 frr_with_privs (&pimd_privs) {
64 opt = enable ? MRT_INIT : MRT_DONE;
65 /*
66 * *BSD *cares* about what value we pass down
67 * here
68 */
69 data = 1;
70 err = setsockopt(pim->mroute_socket, PIM_IPPROTO, opt, &data,
71 data_len);
72 if (err) {
73 zlog_warn(
74 "%s %s: failure: setsockopt(fd=%d,PIM_IPPROTO,%s=%d): errno=%d: %s",
75 __FILE__, __func__, pim->mroute_socket,
76 enable ? "MRT_INIT" : "MRT_DONE", data, errno,
77 safe_strerror(errno));
78 return -1;
79 }
80 }
81
82 #if defined(HAVE_IP_PKTINFO)
83 if (enable) {
84 /* Linux and Solaris IP_PKTINFO */
85 data = 1;
86 if (setsockopt(pim->mroute_socket, PIM_IPPROTO, IP_PKTINFO,
87 &data, data_len)) {
88 zlog_warn(
89 "Could not set IP_PKTINFO on socket fd=%d: errno=%d: %s",
90 pim->mroute_socket, errno,
91 safe_strerror(errno));
92 }
93 }
94 #endif
95
96 #if PIM_IPV == 6
97 if (enable) {
98 /* Linux and Solaris IPV6_PKTINFO */
99 data = 1;
100 if (setsockopt(pim->mroute_socket, PIM_IPPROTO,
101 IPV6_RECVPKTINFO, &data, data_len)) {
102 zlog_warn(
103 "Could not set IPV6_RECVPKTINFO on socket fd=%d: errno=%d: %s",
104 pim->mroute_socket, errno,
105 safe_strerror(errno));
106 }
107 }
108 #endif
109 setsockopt_so_recvbuf(pim->mroute_socket, 1024 * 1024 * 8);
110
111 if (set_nonblocking(pim->mroute_socket) < 0) {
112 zlog_warn(
113 "Could not set non blocking on socket fd=%d: errno=%d: %s",
114 pim->mroute_socket, errno, safe_strerror(errno));
115 return -1;
116 }
117
118 if (enable) {
119 #if defined linux
120 int upcalls = GMMSG_WRVIFWHOLE;
121 opt = MRT_PIM;
122
123 err = setsockopt(pim->mroute_socket, PIM_IPPROTO, opt, &upcalls,
124 sizeof(upcalls));
125 if (err) {
126 zlog_warn(
127 "Failure to register for VIFWHOLE and WRONGVIF upcalls %d %s",
128 errno, safe_strerror(errno));
129 return -1;
130 }
131 #else
132 zlog_warn(
133 "PIM-SM will not work properly on this platform, until the ability to receive the WRVIFWHOLE upcall");
134 #endif
135 }
136
137 return 0;
138 }
139
140 static const char *const gmmsgtype2str[GMMSG_WRVIFWHOLE + 1] = {
141 "<unknown_upcall?>", "NOCACHE", "WRONGVIF", "WHOLEPKT", "WRVIFWHOLE"};
142
143
144 int pim_mroute_msg_nocache(int fd, struct interface *ifp, const kernmsg *msg)
145 {
146 struct pim_interface *pim_ifp = ifp->info;
147 struct pim_upstream *up;
148 struct pim_rpf *rpg;
149 pim_sgaddr sg;
150
151 rpg = pim_ifp ? RP(pim_ifp->pim, msg->msg_im_dst) : NULL;
152 /*
153 * If the incoming interface is unknown OR
154 * the Interface type is SSM we don't need to
155 * do anything here
156 */
157 if (!rpg || pim_rpf_addr_is_inaddr_any(rpg)) {
158 if (PIM_DEBUG_MROUTE_DETAIL)
159 zlog_debug(
160 "%s: Interface is not configured correctly to handle incoming packet: Could be !pim_ifp, !SM, !RP",
161 __func__);
162
163 return 0;
164 }
165
166 /*
167 * If we've received a multicast packet that isn't connected to
168 * us
169 */
170 if (!pim_if_connected_to_source(ifp, msg->msg_im_src)) {
171 if (PIM_DEBUG_MROUTE_DETAIL)
172 zlog_debug(
173 "%s: Received incoming packet that doesn't originate on our seg",
174 __func__);
175 return 0;
176 }
177
178 memset(&sg, 0, sizeof(sg));
179 sg.src = msg->msg_im_src;
180 sg.grp = msg->msg_im_dst;
181
182 if (!(PIM_I_am_DR(pim_ifp))) {
183 if (PIM_DEBUG_MROUTE_DETAIL)
184 zlog_debug(
185 "%s: Interface is not the DR blackholing incoming traffic for %pSG",
186 __func__, &sg);
187
188 /*
189 * We are not the DR, but we are still receiving packets
190 * Let's blackhole those packets for the moment
191 * As that they will be coming up to the cpu
192 * and causing us to consider them.
193 *
194 * This *will* create a dangling channel_oil
195 * that I see no way to get rid of. Just noting
196 * this for future reference.
197 */
198 up = pim_upstream_find_or_add(
199 &sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_NOCACHE, __func__);
200 pim_upstream_mroute_add(up->channel_oil, __func__);
201
202 return 0;
203 }
204
205 up = pim_upstream_find_or_add(&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR,
206 __func__);
207
208 /*
209 * I moved this debug till after the actual add because
210 * I want to take advantage of the up->sg_str being filled in.
211 */
212 if (PIM_DEBUG_MROUTE) {
213 zlog_debug("%s: Adding a Route %s for WHOLEPKT consumption",
214 __func__, up->sg_str);
215 }
216
217 PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags);
218 pim_upstream_keep_alive_timer_start(up, pim_ifp->pim->keep_alive_time);
219
220 up->channel_oil->cc.pktcnt++;
221 // resolve mfcc_parent prior to mroute_add in channel_add_oif
222 if (up->rpf.source_nexthop.interface &&
223 *oil_parent(up->channel_oil) >= MAXVIFS) {
224 pim_upstream_mroute_iif_update(up->channel_oil, __func__);
225 }
226 pim_register_join(up);
227 /* if we have receiver, inherit from parent */
228 pim_upstream_inherited_olist_decide(pim_ifp->pim, up);
229
230 return 0;
231 }
232
233 int pim_mroute_msg_wholepkt(int fd, struct interface *ifp, const char *buf,
234 size_t len)
235 {
236 struct pim_interface *pim_ifp;
237 pim_sgaddr sg;
238 struct pim_rpf *rpg;
239 const ipv_hdr *ip_hdr;
240 struct pim_upstream *up;
241
242 pim_ifp = ifp->info;
243
244 ip_hdr = (const ipv_hdr *)buf;
245
246 memset(&sg, 0, sizeof(sg));
247 sg.src = IPV_SRC(ip_hdr);
248 sg.grp = IPV_DST(ip_hdr);
249
250 up = pim_upstream_find(pim_ifp->pim, &sg);
251 if (!up) {
252 pim_sgaddr star = sg;
253 star.src = PIMADDR_ANY;
254
255 up = pim_upstream_find(pim_ifp->pim, &star);
256
257 if (up && PIM_UPSTREAM_FLAG_TEST_CAN_BE_LHR(up->flags)) {
258 up = pim_upstream_add(pim_ifp->pim, &sg, ifp,
259 PIM_UPSTREAM_FLAG_MASK_SRC_LHR,
260 __func__, NULL);
261 if (!up) {
262 if (PIM_DEBUG_MROUTE)
263 zlog_debug(
264 "%s: Unable to create upstream information for %pSG",
265 __func__, &sg);
266 return 0;
267 }
268 pim_upstream_keep_alive_timer_start(
269 up, pim_ifp->pim->keep_alive_time);
270 pim_upstream_inherited_olist(pim_ifp->pim, up);
271 pim_upstream_update_join_desired(pim_ifp->pim, up);
272
273 if (PIM_DEBUG_MROUTE)
274 zlog_debug("%s: Creating %s upstream on LHR",
275 __func__, up->sg_str);
276 return 0;
277 }
278 if (PIM_DEBUG_MROUTE_DETAIL) {
279 zlog_debug(
280 "%s: Unable to find upstream channel WHOLEPKT%pSG",
281 __func__, &sg);
282 }
283 return 0;
284 }
285
286 if (!up->rpf.source_nexthop.interface) {
287 if (PIM_DEBUG_PIM_TRACE)
288 zlog_debug("%s: up %s RPF is not present", __func__,
289 up->sg_str);
290 return 0;
291 }
292
293 pim_ifp = up->rpf.source_nexthop.interface->info;
294
295 rpg = pim_ifp ? RP(pim_ifp->pim, sg.grp) : NULL;
296
297 if ((pim_rpf_addr_is_inaddr_any(rpg)) || (!pim_ifp) ||
298 (!(PIM_I_am_DR(pim_ifp)))) {
299 if (PIM_DEBUG_MROUTE) {
300 zlog_debug("%s: Failed Check send packet", __func__);
301 }
302 return 0;
303 }
304
305 /*
306 * If we've received a register suppress
307 */
308 if (!up->t_rs_timer) {
309 if (pim_is_grp_ssm(pim_ifp->pim, sg.grp)) {
310 if (PIM_DEBUG_PIM_REG)
311 zlog_debug(
312 "%pSG register forward skipped as group is SSM",
313 &sg);
314 return 0;
315 }
316
317 if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) {
318 if (PIM_DEBUG_PIM_REG)
319 zlog_debug(
320 "%s register forward skipped, not FHR",
321 up->sg_str);
322 return 0;
323 }
324
325 pim_register_send((uint8_t *)buf + sizeof(ipv_hdr),
326 len - sizeof(ipv_hdr),
327 pim_ifp->primary_address, rpg, 0, up);
328 }
329 return 0;
330 }
331
332 int pim_mroute_msg_wrongvif(int fd, struct interface *ifp, const kernmsg *msg)
333 {
334 struct pim_ifchannel *ch;
335 struct pim_interface *pim_ifp;
336 pim_sgaddr sg;
337
338 memset(&sg, 0, sizeof(sg));
339 sg.src = msg->msg_im_src;
340 sg.grp = msg->msg_im_dst;
341
342 /*
343 Send Assert(S,G) on iif as response to WRONGVIF kernel upcall.
344
345 RFC 4601 4.8.2. PIM-SSM-Only Routers
346
347 iif is the incoming interface of the packet.
348 if (iif is in inherited_olist(S,G)) {
349 send Assert(S,G) on iif
350 }
351 */
352
353 if (!ifp) {
354 if (PIM_DEBUG_MROUTE)
355 zlog_debug(
356 "%s: WRONGVIF (S,G)=%pSG could not find input interface for input_vif_index=%d",
357 __func__, &sg, msg->msg_im_vif);
358 return -1;
359 }
360
361 pim_ifp = ifp->info;
362 if (!pim_ifp) {
363 if (PIM_DEBUG_MROUTE)
364 zlog_debug(
365 "%s: WRONGVIF (S,G)=%pSG multicast not enabled on interface %s",
366 __func__, &sg, ifp->name);
367 return -2;
368 }
369
370 ch = pim_ifchannel_find(ifp, &sg);
371 if (!ch) {
372 pim_sgaddr star_g = sg;
373 if (PIM_DEBUG_MROUTE)
374 zlog_debug(
375 "%s: WRONGVIF (S,G)=%pSG could not find channel on interface %s",
376 __func__, &sg, ifp->name);
377
378 star_g.src = PIMADDR_ANY;
379 ch = pim_ifchannel_find(ifp, &star_g);
380 if (!ch) {
381 if (PIM_DEBUG_MROUTE)
382 zlog_debug(
383 "%s: WRONGVIF (*,G)=%pSG could not find channel on interface %s",
384 __func__, &star_g, ifp->name);
385 return -3;
386 }
387 }
388
389 /*
390 RFC 4601: 4.6.1. (S,G) Assert Message State Machine
391
392 Transitions from NoInfo State
393
394 An (S,G) data packet arrives on interface I, AND
395 CouldAssert(S,G,I)==TRUE An (S,G) data packet arrived on an
396 downstream interface that is in our (S,G) outgoing interface
397 list. We optimistically assume that we will be the assert
398 winner for this (S,G), and so we transition to the "I am Assert
399 Winner" state and perform Actions A1 (below), which will
400 initiate the assert negotiation for (S,G).
401 */
402
403 if (ch->ifassert_state != PIM_IFASSERT_NOINFO) {
404 if (PIM_DEBUG_MROUTE) {
405 zlog_debug(
406 "%s: WRONGVIF (S,G)=%s channel is not on Assert NoInfo state for interface %s",
407 __func__, ch->sg_str, ifp->name);
408 }
409 return -4;
410 }
411
412 if (!PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) {
413 if (PIM_DEBUG_MROUTE) {
414 zlog_debug(
415 "%s: WRONGVIF (S,G)=%s interface %s is not downstream for channel",
416 __func__, ch->sg_str, ifp->name);
417 }
418 return -5;
419 }
420
421 if (assert_action_a1(ch)) {
422 if (PIM_DEBUG_MROUTE) {
423 zlog_debug(
424 "%s: WRONGVIF (S,G)=%s assert_action_a1 failure on interface %s",
425 __func__, ch->sg_str, ifp->name);
426 }
427 return -6;
428 }
429
430 return 0;
431 }
432
433 int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp, const char *buf,
434 size_t len)
435 {
436 const ipv_hdr *ip_hdr = (const ipv_hdr *)buf;
437 struct pim_interface *pim_ifp;
438 struct pim_instance *pim;
439 struct pim_ifchannel *ch;
440 struct pim_upstream *up;
441 pim_sgaddr star_g;
442 pim_sgaddr sg;
443
444 pim_ifp = ifp->info;
445
446 memset(&sg, 0, sizeof(sg));
447 sg.src = IPV_SRC(ip_hdr);
448 sg.grp = IPV_DST(ip_hdr);
449
450 ch = pim_ifchannel_find(ifp, &sg);
451 if (ch) {
452 if (PIM_DEBUG_MROUTE)
453 zlog_debug(
454 "WRVIFWHOLE (S,G)=%s found ifchannel on interface %s",
455 ch->sg_str, ifp->name);
456 return -1;
457 }
458
459 star_g = sg;
460 star_g.src = PIMADDR_ANY;
461
462 pim = pim_ifp->pim;
463 /*
464 * If the incoming interface is the pimreg, then
465 * we know the callback is associated with a pim register
466 * packet and there is nothing to do here as that
467 * normal pim processing will see the packet and allow
468 * us to do the right thing.
469 */
470 if (ifp == pim->regiface) {
471 return 0;
472 }
473
474 up = pim_upstream_find(pim_ifp->pim, &sg);
475 if (up) {
476 struct pim_upstream *parent;
477 struct pim_nexthop source;
478 struct pim_rpf *rpf = RP(pim_ifp->pim, sg.grp);
479
480 /* No RPF or No RPF interface or No mcast on RPF interface */
481 if (!rpf || !rpf->source_nexthop.interface ||
482 !rpf->source_nexthop.interface->info)
483 return 0;
484
485 /*
486 * If we have received a WRVIFWHOLE and are at this
487 * point, we could be receiving the packet on the *,G
488 * tree, let's check and if so we can safely drop
489 * it.
490 */
491 parent = pim_upstream_find(pim_ifp->pim, &star_g);
492 if (parent && parent->rpf.source_nexthop.interface == ifp)
493 return 0;
494
495 pim_ifp = rpf->source_nexthop.interface->info;
496
497 memset(&source, 0, sizeof(source));
498 /*
499 * If we are the fhr that means we are getting a callback during
500 * the pimreg period, so I believe we can ignore this packet
501 */
502 if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) {
503 /*
504 * No if channel, but upstream we are at the RP.
505 *
506 * This could be a anycast RP too and we may
507 * not have received a register packet from
508 * the source here at all. So gracefully
509 * bow out of doing a nexthop lookup and
510 * setting the SPTBIT to true
511 */
512 if (!(pim_addr_is_any(up->upstream_register)) &&
513 pim_nexthop_lookup(pim_ifp->pim, &source,
514 up->upstream_register, 0)) {
515 pim_register_stop_send(source.interface, &sg,
516 pim_ifp->primary_address,
517 up->upstream_register);
518 up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE;
519 }
520
521 pim_upstream_inherited_olist(pim_ifp->pim, up);
522 if (!up->channel_oil->installed)
523 pim_upstream_mroute_add(up->channel_oil,
524 __func__);
525 } else {
526 if (I_am_RP(pim_ifp->pim, up->sg.grp)) {
527 if (pim_nexthop_lookup(pim_ifp->pim, &source,
528 up->upstream_register,
529 0))
530 pim_register_stop_send(
531 source.interface, &sg,
532 pim_ifp->primary_address,
533 up->upstream_register);
534 up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE;
535 } else {
536 /*
537 * At this point pimd is connected to
538 * the source, it has a parent, we are not
539 * the RP and the SPTBIT should be set
540 * since we know *the* S,G is on the SPT.
541 * The first time this happens, let's cause
542 * an immediate join to go out so that
543 * the RP can trim this guy immediately
544 * if necessary, instead of waiting
545 * one join/prune send cycle
546 */
547 if (up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE &&
548 up->parent &&
549 up->rpf.source_nexthop.interface !=
550 up->parent->rpf.source_nexthop
551 .interface) {
552 up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE;
553 pim_jp_agg_single_upstream_send(
554 &up->parent->rpf, up->parent,
555 true);
556 }
557 }
558 pim_upstream_keep_alive_timer_start(
559 up, pim_ifp->pim->keep_alive_time);
560 pim_upstream_inherited_olist(pim_ifp->pim, up);
561 pim_mroute_msg_wholepkt(fd, ifp, buf, len);
562 }
563 return 0;
564 }
565
566 pim_ifp = ifp->info;
567 if (pim_if_connected_to_source(ifp, sg.src)) {
568 up = pim_upstream_add(pim_ifp->pim, &sg, ifp,
569 PIM_UPSTREAM_FLAG_MASK_FHR, __func__,
570 NULL);
571 if (!up) {
572 if (PIM_DEBUG_MROUTE)
573 zlog_debug(
574 "%pSG: WRONGVIF%s unable to create upstream on interface",
575 &sg, ifp->name);
576 return -2;
577 }
578 PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags);
579 pim_upstream_keep_alive_timer_start(
580 up, pim_ifp->pim->keep_alive_time);
581 up->channel_oil->cc.pktcnt++;
582 pim_register_join(up);
583 pim_upstream_inherited_olist(pim_ifp->pim, up);
584 if (!up->channel_oil->installed)
585 pim_upstream_mroute_add(up->channel_oil, __func__);
586
587 // Send the packet to the RP
588 pim_mroute_msg_wholepkt(fd, ifp, buf, len);
589 } else {
590 up = pim_upstream_add(pim_ifp->pim, &sg, ifp,
591 PIM_UPSTREAM_FLAG_MASK_SRC_NOCACHE,
592 __func__, NULL);
593 if (!up->channel_oil->installed)
594 pim_upstream_mroute_add(up->channel_oil, __func__);
595 }
596
597 return 0;
598 }
599
600 #if PIM_IPV == 4
601 static int process_igmp_packet(struct pim_instance *pim, const char *buf,
602 size_t buf_size, ifindex_t ifindex)
603 {
604 struct interface *ifp;
605 struct pim_interface *pim_ifp;
606 struct in_addr ifaddr;
607 struct gm_sock *igmp;
608 const struct prefix *connected_src;
609 const struct ip *ip_hdr = (const struct ip *)buf;
610
611 /* We have the IP packet but we do not know which interface this
612 * packet was
613 * received on. Find the interface that is on the same subnet as
614 * the source
615 * of the IP packet.
616 */
617 ifp = if_lookup_by_index(ifindex, pim->vrf->vrf_id);
618
619 if (!ifp || !ifp->info)
620 return 0;
621
622 connected_src = pim_if_connected_to_source(ifp, ip_hdr->ip_src);
623
624 if (!connected_src && !pim_addr_is_any(ip_hdr->ip_src)) {
625 if (PIM_DEBUG_GM_PACKETS) {
626 zlog_debug(
627 "Recv IGMP packet on interface: %s from a non-connected source: %pI4",
628 ifp->name, &ip_hdr->ip_src);
629 }
630 return 0;
631 }
632
633 pim_ifp = ifp->info;
634 ifaddr = connected_src ? connected_src->u.prefix4
635 : pim_ifp->primary_address;
636 igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list, ifaddr);
637
638 if (PIM_DEBUG_GM_PACKETS) {
639 zlog_debug(
640 "%s(%s): igmp kernel upcall on %s(%p) for %pI4 -> %pI4",
641 __func__, pim->vrf->name, ifp->name, igmp,
642 &ip_hdr->ip_src, &ip_hdr->ip_dst);
643 }
644 if (igmp)
645 pim_igmp_packet(igmp, (char *)buf, buf_size);
646 else if (PIM_DEBUG_GM_PACKETS)
647 zlog_debug(
648 "No IGMP socket on interface: %s with connected source: %pI4",
649 ifp->name, &ifaddr);
650
651 return 0;
652 }
653 #endif
654
655 int pim_mroute_msg(struct pim_instance *pim, const char *buf, size_t buf_size,
656 ifindex_t ifindex)
657 {
658 struct interface *ifp;
659 const ipv_hdr *ip_hdr;
660 const kernmsg *msg;
661
662 if (buf_size < (int)sizeof(ipv_hdr))
663 return 0;
664
665 ip_hdr = (const ipv_hdr *)buf;
666
667 #if PIM_IPV == 4
668 if (ip_hdr->ip_p == IPPROTO_IGMP) {
669 process_igmp_packet(pim, buf, buf_size, ifindex);
670 } else if (ip_hdr->ip_p) {
671 if (PIM_DEBUG_MROUTE_DETAIL) {
672 zlog_debug(
673 "%s: no kernel upcall proto=%d src: %pI4 dst: %pI4 msg_size=%ld",
674 __func__, ip_hdr->ip_p, &ip_hdr->ip_src,
675 &ip_hdr->ip_dst, (long int)buf_size);
676 }
677
678 } else {
679 #else
680
681 if ((ip_hdr->ip6_vfc & 0xf) == 0) {
682 #endif
683 msg = (const kernmsg *)buf;
684
685 ifp = pim_if_find_by_vif_index(pim, msg->msg_im_vif);
686
687 if (!ifp)
688 return 0;
689 if (PIM_DEBUG_MROUTE) {
690 #if PIM_IPV == 4
691 zlog_debug(
692 "%s: pim kernel upcall %s type=%d ip_p=%d from fd=%d for (S,G)=(%pI4,%pI4) on %s vifi=%d size=%ld",
693 __func__, gmmsgtype2str[msg->msg_im_msgtype],
694 msg->msg_im_msgtype, ip_hdr->ip_p,
695 pim->mroute_socket, &msg->msg_im_src,
696 &msg->msg_im_dst, ifp->name, msg->msg_im_vif,
697 (long int)buf_size);
698 #else
699 zlog_debug(
700 "%s: pim kernel upcall %s type=%d ip_p=%d from fd=%d for (S,G)=(%pI6,%pI6) on %s vifi=%d size=%ld",
701 __func__, gmmsgtype2str[msg->msg_im_msgtype],
702 msg->msg_im_msgtype, ip_hdr->ip6_nxt,
703 pim->mroute_socket, &msg->msg_im_src,
704 &msg->msg_im_dst, ifp->name, msg->msg_im_vif,
705 (long int)buf_size);
706 #endif
707 }
708
709 switch (msg->msg_im_msgtype) {
710 case GMMSG_WRONGVIF:
711 return pim_mroute_msg_wrongvif(pim->mroute_socket, ifp,
712 msg);
713 case GMMSG_NOCACHE:
714 return pim_mroute_msg_nocache(pim->mroute_socket, ifp,
715 msg);
716 case GMMSG_WHOLEPKT:
717 return pim_mroute_msg_wholepkt(pim->mroute_socket, ifp,
718 (const char *)msg,
719 buf_size);
720 case GMMSG_WRVIFWHOLE:
721 return pim_mroute_msg_wrvifwhole(pim->mroute_socket,
722 ifp, (const char *)msg,
723 buf_size);
724 default:
725 break;
726 }
727 }
728
729 return 0;
730 }
731
732 static void mroute_read(struct thread *t)
733 {
734 struct pim_instance *pim;
735 static long long count;
736 char buf[10000];
737 int cont = 1;
738 int rd;
739 ifindex_t ifindex;
740 pim = THREAD_ARG(t);
741
742 while (cont) {
743 rd = pim_socket_recvfromto(pim->mroute_socket, (uint8_t *)buf,
744 sizeof(buf), NULL, NULL, NULL, NULL,
745 &ifindex);
746 if (rd <= 0) {
747 if (errno == EINTR)
748 continue;
749 if (errno == EWOULDBLOCK || errno == EAGAIN)
750 break;
751
752 zlog_warn(
753 "%s: failure reading rd=%d: fd=%d: errno=%d: %s",
754 __func__, rd, pim->mroute_socket, errno,
755 safe_strerror(errno));
756 goto done;
757 }
758
759 pim_mroute_msg(pim, buf, rd, ifindex);
760
761 count++;
762 if (count % router->packet_process == 0)
763 cont = 0;
764 }
765 /* Keep reading */
766 done:
767 mroute_read_on(pim);
768
769 return;
770 }
771
772 static void mroute_read_on(struct pim_instance *pim)
773 {
774 thread_add_read(router->master, mroute_read, pim, pim->mroute_socket,
775 &pim->thread);
776 }
777
778 static void mroute_read_off(struct pim_instance *pim)
779 {
780 THREAD_OFF(pim->thread);
781 }
782
783 int pim_mroute_socket_enable(struct pim_instance *pim)
784 {
785 int fd;
786
787 frr_with_privs(&pimd_privs) {
788
789 #if PIM_IPV == 4
790 fd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP);
791 #else
792 fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
793 #endif
794 if (fd < 0) {
795 zlog_warn("Could not create mroute socket: errno=%d: %s",
796 errno,
797 safe_strerror(errno));
798 return -2;
799 }
800
801 #if PIM_IPV == 6
802 struct icmp6_filter filter[1];
803 int ret;
804
805 /* Unlike IPv4, this socket is not used for MLD, so just drop
806 * everything with an empty ICMP6 filter. Otherwise we get
807 * all kinds of garbage here, possibly even non-multicast
808 * related ICMPv6 traffic (e.g. ping)
809 *
810 * (mroute kernel upcall "packets" are injected directly on the
811 * socket, this sockopt -or any other- has no effect on them)
812 */
813 ICMP6_FILTER_SETBLOCKALL(filter);
814 ret = setsockopt(fd, SOL_ICMPV6, ICMP6_FILTER, filter,
815 sizeof(filter));
816 if (ret)
817 zlog_err(
818 "(VRF %s) failed to set mroute control filter: %m",
819 pim->vrf->name);
820 #endif
821
822 #ifdef SO_BINDTODEVICE
823 if (pim->vrf->vrf_id != VRF_DEFAULT
824 && setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
825 pim->vrf->name, strlen(pim->vrf->name))) {
826 zlog_warn("Could not setsockopt SO_BINDTODEVICE: %s",
827 safe_strerror(errno));
828 close(fd);
829 return -3;
830 }
831 #endif
832
833 }
834
835 pim->mroute_socket = fd;
836 if (pim_mroute_set(pim, 1)) {
837 zlog_warn(
838 "Could not enable mroute on socket fd=%d: errno=%d: %s",
839 fd, errno, safe_strerror(errno));
840 close(fd);
841 pim->mroute_socket = -1;
842 return -3;
843 }
844
845 pim->mroute_socket_creation = pim_time_monotonic_sec();
846
847 mroute_read_on(pim);
848
849 return 0;
850 }
851
852 int pim_mroute_socket_disable(struct pim_instance *pim)
853 {
854 if (pim_mroute_set(pim, 0)) {
855 zlog_warn(
856 "Could not disable mroute on socket fd=%d: errno=%d: %s",
857 pim->mroute_socket, errno, safe_strerror(errno));
858 return -2;
859 }
860
861 if (close(pim->mroute_socket)) {
862 zlog_warn("Failure closing mroute socket: fd=%d errno=%d: %s",
863 pim->mroute_socket, errno, safe_strerror(errno));
864 return -3;
865 }
866
867 mroute_read_off(pim);
868 pim->mroute_socket = -1;
869
870 return 0;
871 }
872
873 /*
874 For each network interface (e.g., physical or a virtual tunnel) that
875 would be used for multicast forwarding, a corresponding multicast
876 interface must be added to the kernel.
877 */
878 int pim_mroute_add_vif(struct interface *ifp, pim_addr ifaddr,
879 unsigned char flags)
880 {
881 struct pim_interface *pim_ifp = ifp->info;
882 pim_vifctl vc;
883 int err;
884
885 if (PIM_DEBUG_MROUTE)
886 zlog_debug("%s: Add Vif %d (%s[%s])", __func__,
887 pim_ifp->mroute_vif_index, ifp->name,
888 pim_ifp->pim->vrf->name);
889
890 memset(&vc, 0, sizeof(vc));
891 vc.vc_vifi = pim_ifp->mroute_vif_index;
892 #if PIM_IPV == 4
893 #ifdef VIFF_USE_IFINDEX
894 vc.vc_lcl_ifindex = ifp->ifindex;
895 #else
896 if (ifaddr.s_addr == INADDR_ANY) {
897 zlog_warn(
898 "%s: unnumbered interfaces are not supported on this platform",
899 __func__);
900 return -1;
901 }
902 memcpy(&vc.vc_lcl_addr, &ifaddr, sizeof(vc.vc_lcl_addr));
903 #endif
904 #else
905 vc.vc_pifi = ifp->ifindex;
906 #endif
907 vc.vc_flags = flags;
908 vc.vc_threshold = PIM_MROUTE_MIN_TTL;
909 vc.vc_rate_limit = 0;
910
911 #if PIM_IPV == 4
912 #ifdef PIM_DVMRP_TUNNEL
913 if (vc.vc_flags & VIFF_TUNNEL) {
914 memcpy(&vc.vc_rmt_addr, &vif_remote_addr,
915 sizeof(vc.vc_rmt_addr));
916 }
917 #endif
918 #endif
919
920 err = setsockopt(pim_ifp->pim->mroute_socket, PIM_IPPROTO, MRT_ADD_VIF,
921 (void *)&vc, sizeof(vc));
922 if (err) {
923 zlog_warn(
924 "%s: failure: setsockopt(fd=%d,PIM_IPPROTO,MRT_ADD_VIF,vif_index=%d,ifaddr=%pPAs,flag=%d): errno=%d: %s",
925 __func__, pim_ifp->pim->mroute_socket, ifp->ifindex,
926 &ifaddr, flags, errno, safe_strerror(errno));
927 return -2;
928 }
929
930 return 0;
931 }
932
933 int pim_mroute_del_vif(struct interface *ifp)
934 {
935 struct pim_interface *pim_ifp = ifp->info;
936 pim_vifctl vc;
937 int err;
938
939 if (PIM_DEBUG_MROUTE)
940 zlog_debug("%s: Del Vif %d (%s[%s])", __func__,
941 pim_ifp->mroute_vif_index, ifp->name,
942 pim_ifp->pim->vrf->name);
943
944 memset(&vc, 0, sizeof(vc));
945 vc.vc_vifi = pim_ifp->mroute_vif_index;
946
947 err = setsockopt(pim_ifp->pim->mroute_socket, PIM_IPPROTO, MRT_DEL_VIF,
948 (void *)&vc, sizeof(vc));
949 if (err) {
950 zlog_warn(
951 "%s %s: failure: setsockopt(fd=%d,PIM_IPPROTO,MRT_DEL_VIF,vif_index=%d): errno=%d: %s",
952 __FILE__, __func__, pim_ifp->pim->mroute_socket,
953 pim_ifp->mroute_vif_index, errno, safe_strerror(errno));
954 return -2;
955 }
956
957 return 0;
958 }
959
960 /*
961 * Prevent creating MFC entry with OIF=IIF.
962 *
963 * This is a protection against implementation mistakes.
964 *
965 * PIM protocol implicitely ensures loopfree multicast topology.
966 *
967 * IGMP must be protected against adding looped MFC entries created
968 * by both source and receiver attached to the same interface. See
969 * TODO T22.
970 * We shall allow igmp to create upstream when it is DR for the intf.
971 * Assume RP reachable via non DR.
972 */
973 bool pim_mroute_allow_iif_in_oil(struct channel_oil *c_oil,
974 int oif_index)
975 {
976 #ifdef PIM_ENFORCE_LOOPFREE_MFC
977 struct interface *ifp_out;
978 struct pim_interface *pim_ifp;
979
980 if (c_oil->up &&
981 PIM_UPSTREAM_FLAG_TEST_ALLOW_IIF_IN_OIL(c_oil->up->flags))
982 return true;
983
984 ifp_out = pim_if_find_by_vif_index(c_oil->pim, oif_index);
985 if (!ifp_out)
986 return false;
987 pim_ifp = ifp_out->info;
988 if (!pim_ifp)
989 return false;
990 if ((c_oil->oif_flags[oif_index] & PIM_OIF_FLAG_PROTO_GM) &&
991 PIM_I_am_DR(pim_ifp))
992 return true;
993
994 return false;
995 #else
996 return true;
997 #endif
998 }
999
1000 static inline void pim_mroute_copy(struct channel_oil *out,
1001 struct channel_oil *in)
1002 {
1003 int i;
1004
1005 *oil_origin(out) = *oil_origin(in);
1006 *oil_mcastgrp(out) = *oil_mcastgrp(in);
1007 *oil_parent(out) = *oil_parent(in);
1008
1009 for (i = 0; i < MAXVIFS; ++i) {
1010 if (*oil_parent(out) == i &&
1011 !pim_mroute_allow_iif_in_oil(in, i)) {
1012 oil_if_set(out, i, 0);
1013 continue;
1014 }
1015
1016 if (in->oif_flags[i] & PIM_OIF_FLAG_MUTE)
1017 oil_if_set(out, i, 0);
1018 else
1019 oil_if_set(out, i, oil_if_has(in, i));
1020 }
1021 }
1022
1023 /* This function must not be called directly 0
1024 * use pim_upstream_mroute_add or pim_static_mroute_add instead
1025 */
1026 static int pim_mroute_add(struct channel_oil *c_oil, const char *name)
1027 {
1028 struct pim_instance *pim = c_oil->pim;
1029 struct channel_oil tmp_oil[1] = { };
1030 int err;
1031
1032 pim->mroute_add_last = pim_time_monotonic_sec();
1033 ++pim->mroute_add_events;
1034
1035 /* Copy the oil to a temporary structure to fixup (without need to
1036 * later restore) before sending the mroute add to the dataplane
1037 */
1038 pim_mroute_copy(tmp_oil, c_oil);
1039
1040 /* The linux kernel *expects* the incoming
1041 * vif to be part of the outgoing list
1042 * in the case of a (*,G).
1043 */
1044 if (pim_addr_is_any(*oil_origin(c_oil))) {
1045 oil_if_set(tmp_oil, *oil_parent(c_oil), 1);
1046 }
1047
1048 /*
1049 * If we have an unresolved cache entry for the S,G
1050 * it is owned by the pimreg for the incoming IIF
1051 * So set pimreg as the IIF temporarily to cause
1052 * the packets to be forwarded. Then set it
1053 * to the correct IIF afterwords.
1054 */
1055 if (!c_oil->installed && !pim_addr_is_any(*oil_origin(c_oil))
1056 && *oil_parent(c_oil) != 0) {
1057 *oil_parent(tmp_oil) = 0;
1058 }
1059 /* For IPv6 MRT_ADD_MFC is defined to MRT6_ADD_MFC */
1060 err = setsockopt(pim->mroute_socket, PIM_IPPROTO, MRT_ADD_MFC,
1061 &tmp_oil->oil, sizeof(tmp_oil->oil));
1062
1063 if (!err && !c_oil->installed
1064 && !pim_addr_is_any(*oil_origin(c_oil))
1065 && *oil_parent(c_oil) != 0) {
1066 *oil_parent(tmp_oil) = *oil_parent(c_oil);
1067 err = setsockopt(pim->mroute_socket, PIM_IPPROTO, MRT_ADD_MFC,
1068 &tmp_oil->oil, sizeof(tmp_oil->oil));
1069 }
1070
1071 if (err) {
1072 zlog_warn(
1073 "%s %s: failure: setsockopt(fd=%d,PIM_IPPROTO,MRT_ADD_MFC): errno=%d: %s",
1074 __FILE__, __func__, pim->mroute_socket, errno,
1075 safe_strerror(errno));
1076 return -2;
1077 }
1078
1079 if (PIM_DEBUG_MROUTE) {
1080 char buf[1000];
1081 zlog_debug("%s(%s), vrf %s Added Route: %s", __func__, name,
1082 pim->vrf->name,
1083 pim_channel_oil_dump(c_oil, buf, sizeof(buf)));
1084 }
1085
1086 if (!c_oil->installed) {
1087 c_oil->installed = 1;
1088 c_oil->mroute_creation = pim_time_monotonic_sec();
1089 }
1090
1091 return 0;
1092 }
1093
1094 static int pim_upstream_get_mroute_iif(struct channel_oil *c_oil,
1095 const char *name)
1096 {
1097 vifi_t iif = MAXVIFS;
1098 struct interface *ifp = NULL;
1099 struct pim_interface *pim_ifp;
1100 struct pim_upstream *up = c_oil->up;
1101
1102 if (up) {
1103 if (PIM_UPSTREAM_FLAG_TEST_USE_RPT(up->flags)) {
1104 if (up->parent)
1105 ifp = up->parent->rpf.source_nexthop.interface;
1106 } else {
1107 ifp = up->rpf.source_nexthop.interface;
1108 }
1109 if (ifp) {
1110 pim_ifp = (struct pim_interface *)ifp->info;
1111 if (pim_ifp)
1112 iif = pim_ifp->mroute_vif_index;
1113 }
1114 }
1115 return iif;
1116 }
1117
1118 static int pim_upstream_mroute_update(struct channel_oil *c_oil,
1119 const char *name)
1120 {
1121 char buf[1000];
1122
1123 if (*oil_parent(c_oil) >= MAXVIFS) {
1124 /* the c_oil cannot be installed as a mroute yet */
1125 if (PIM_DEBUG_MROUTE)
1126 zlog_debug(
1127 "%s(%s) %s mroute not ready to be installed; %s",
1128 __func__, name,
1129 pim_channel_oil_dump(c_oil, buf,
1130 sizeof(buf)),
1131 c_oil->installed ?
1132 "uninstall" : "skip");
1133 /* if already installed flush it out as we are going to stop
1134 * updates to it leaving it in a stale state
1135 */
1136 if (c_oil->installed)
1137 pim_mroute_del(c_oil, name);
1138 /* return success (skipped) */
1139 return 0;
1140 }
1141
1142 return pim_mroute_add(c_oil, name);
1143 }
1144
1145 /* IIF associated with SGrpt entries are re-evaluated when the parent
1146 * (*,G) entries IIF changes
1147 */
1148 static void pim_upstream_all_sources_iif_update(struct pim_upstream *up)
1149 {
1150 struct listnode *listnode;
1151 struct pim_upstream *child;
1152
1153 for (ALL_LIST_ELEMENTS_RO(up->sources, listnode,
1154 child)) {
1155 if (PIM_UPSTREAM_FLAG_TEST_USE_RPT(child->flags))
1156 pim_upstream_mroute_iif_update(child->channel_oil,
1157 __func__);
1158 }
1159 }
1160
1161 /* In the case of "PIM state machine" added mroutes an upstream entry
1162 * must be present to decide on the SPT-forwarding vs. RPT-forwarding.
1163 */
1164 int pim_upstream_mroute_add(struct channel_oil *c_oil, const char *name)
1165 {
1166 vifi_t iif;
1167
1168 iif = pim_upstream_get_mroute_iif(c_oil, name);
1169
1170 if (*oil_parent(c_oil) != iif) {
1171 *oil_parent(c_oil) = iif;
1172 if (pim_addr_is_any(*oil_origin(c_oil)) &&
1173 c_oil->up)
1174 pim_upstream_all_sources_iif_update(c_oil->up);
1175 } else {
1176 *oil_parent(c_oil) = iif;
1177 }
1178
1179 return pim_upstream_mroute_update(c_oil, name);
1180 }
1181
1182 /* Look for IIF changes and update the dateplane entry only if the IIF
1183 * has changed.
1184 */
1185 int pim_upstream_mroute_iif_update(struct channel_oil *c_oil, const char *name)
1186 {
1187 vifi_t iif;
1188 char buf[1000];
1189
1190 iif = pim_upstream_get_mroute_iif(c_oil, name);
1191 if (*oil_parent(c_oil) == iif) {
1192 /* no change */
1193 return 0;
1194 }
1195 *oil_parent(c_oil) = iif;
1196
1197 if (pim_addr_is_any(*oil_origin(c_oil)) &&
1198 c_oil->up)
1199 pim_upstream_all_sources_iif_update(c_oil->up);
1200
1201 if (PIM_DEBUG_MROUTE_DETAIL)
1202 zlog_debug("%s(%s) %s mroute iif update %d",
1203 __func__, name,
1204 pim_channel_oil_dump(c_oil, buf,
1205 sizeof(buf)), iif);
1206 /* XXX: is this hack needed? */
1207 c_oil->oil_inherited_rescan = 1;
1208 return pim_upstream_mroute_update(c_oil, name);
1209 }
1210
1211 int pim_static_mroute_add(struct channel_oil *c_oil, const char *name)
1212 {
1213 return pim_mroute_add(c_oil, name);
1214 }
1215
1216 void pim_static_mroute_iif_update(struct channel_oil *c_oil,
1217 int input_vif_index,
1218 const char *name)
1219 {
1220 if (*oil_parent(c_oil) == input_vif_index)
1221 return;
1222
1223 *oil_parent(c_oil) = input_vif_index;
1224 if (input_vif_index == MAXVIFS)
1225 pim_mroute_del(c_oil, name);
1226 else
1227 pim_static_mroute_add(c_oil, name);
1228 }
1229
1230 int pim_mroute_del(struct channel_oil *c_oil, const char *name)
1231 {
1232 struct pim_instance *pim = c_oil->pim;
1233 int err;
1234
1235 pim->mroute_del_last = pim_time_monotonic_sec();
1236 ++pim->mroute_del_events;
1237
1238 if (!c_oil->installed) {
1239 if (PIM_DEBUG_MROUTE) {
1240 char buf[1000];
1241 zlog_debug(
1242 "%s %s: vifi %d for route is %s not installed, do not need to send del req. ",
1243 __FILE__, __func__, *oil_parent(c_oil),
1244 pim_channel_oil_dump(c_oil, buf, sizeof(buf)));
1245 }
1246 return -2;
1247 }
1248
1249 err = setsockopt(pim->mroute_socket, PIM_IPPROTO, MRT_DEL_MFC,
1250 &c_oil->oil, sizeof(c_oil->oil));
1251 if (err) {
1252 if (PIM_DEBUG_MROUTE)
1253 zlog_warn(
1254 "%s %s: failure: setsockopt(fd=%d,PIM_IPPROTO,MRT_DEL_MFC): errno=%d: %s",
1255 __FILE__, __func__, pim->mroute_socket, errno,
1256 safe_strerror(errno));
1257 return -2;
1258 }
1259
1260 if (PIM_DEBUG_MROUTE) {
1261 char buf[1000];
1262 zlog_debug("%s(%s), vrf %s Deleted Route: %s", __func__, name,
1263 pim->vrf->name,
1264 pim_channel_oil_dump(c_oil, buf, sizeof(buf)));
1265 }
1266
1267 // Reset kernel installed flag
1268 c_oil->installed = 0;
1269
1270 return 0;
1271 }
1272
1273 void pim_mroute_update_counters(struct channel_oil *c_oil)
1274 {
1275 struct pim_instance *pim = c_oil->pim;
1276 pim_sioc_sg_req sgreq;
1277
1278 c_oil->cc.oldpktcnt = c_oil->cc.pktcnt;
1279 c_oil->cc.oldbytecnt = c_oil->cc.bytecnt;
1280 c_oil->cc.oldwrong_if = c_oil->cc.wrong_if;
1281
1282 if (!c_oil->installed) {
1283 c_oil->cc.lastused = 100 * pim->keep_alive_time;
1284 if (PIM_DEBUG_MROUTE) {
1285 pim_sgaddr sg;
1286
1287 sg.src = *oil_origin(c_oil);
1288 sg.grp = *oil_mcastgrp(c_oil);
1289 zlog_debug("Channel%pSG is not installed no need to collect data from kernel",
1290 &sg);
1291 }
1292 return;
1293 }
1294
1295
1296 memset(&sgreq, 0, sizeof(sgreq));
1297
1298 pim_zlookup_sg_statistics(c_oil);
1299
1300 #if PIM_IPV == 4
1301 sgreq.src = *oil_origin(c_oil);
1302 sgreq.grp = *oil_mcastgrp(c_oil);
1303 #else
1304 sgreq.src = c_oil->oil.mf6cc_origin;
1305 sgreq.grp = c_oil->oil.mf6cc_mcastgrp;
1306 #endif
1307 if (ioctl(pim->mroute_socket, PIM_SIOCGETSGCNT, &sgreq)) {
1308 pim_sgaddr sg;
1309
1310 sg.src = *oil_origin(c_oil);
1311 sg.grp = *oil_mcastgrp(c_oil);
1312
1313 zlog_warn(
1314 "ioctl(PIM_SIOCGETSGCNT=%lu) failure for (S,G)=%pSG: errno=%d: %s",
1315 (unsigned long)PIM_SIOCGETSGCNT, &sg, errno,
1316 safe_strerror(errno));
1317 return;
1318 }
1319
1320 c_oil->cc.pktcnt = sgreq.pktcnt;
1321 c_oil->cc.bytecnt = sgreq.bytecnt;
1322 c_oil->cc.wrong_if = sgreq.wrong_if;
1323 return;
1324 }