]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_register.c
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / pimd / pim_register.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
01d68c9b
DS
2/*
3 * PIM for Quagga
4 * Copyright (C) 2015 Cumulus Networks, Inc.
5 * Donald Sharp
01d68c9b
DS
6 */
7
8#include <zebra.h>
9
10#include "log.h"
11#include "if.h"
24a58196 12#include "frrevent.h"
13c2408c 13#include "prefix.h"
dfe43e25
DW
14#include "vty.h"
15#include "plist.h"
01d68c9b
DS
16
17#include "pimd.h"
998af219
DS
18#include "pim_mroute.h"
19#include "pim_iface.h"
20#include "pim_msg.h"
21#include "pim_pim.h"
01d68c9b
DS
22#include "pim_str.h"
23#include "pim_rp.h"
24#include "pim_register.h"
80c0d168 25#include "pim_upstream.h"
2ca35b3d
DS
26#include "pim_rpf.h"
27#include "pim_oil.h"
28#include "pim_zebra.h"
29#include "pim_join.h"
13c2408c 30#include "pim_util.h"
15a5dafe 31#include "pim_ssm.h"
b9f3a51c 32#include "pim_vxlan.h"
30b277e1 33#include "pim_addr.h"
01d68c9b 34
e6685141 35struct event *send_test_packet_timer = NULL;
01d68c9b 36
d62a17ae 37void pim_register_join(struct pim_upstream *up)
15a5dafe 38{
ac7eaeb4
DS
39 struct pim_instance *pim = up->channel_oil->pim;
40
6f439a70 41 if (pim_is_grp_ssm(pim, up->sg.grp)) {
d62a17ae 42 if (PIM_DEBUG_PIM_EVENTS)
43 zlog_debug("%s register setup skipped as group is SSM",
44 up->sg_str);
45 return;
46 }
47
ac7eaeb4 48 pim_channel_add_oif(up->channel_oil, pim->regiface,
1b249e70 49 PIM_OIF_FLAG_PROTO_PIM, __func__);
d62a17ae 50 up->reg_state = PIM_REG_JOIN;
03f9d812 51 pim_vxlan_update_sg_reg_state(pim, up, true);
15a5dafe 52}
53
30b277e1 54void pim_register_stop_send(struct interface *ifp, pim_sgaddr *sg, pim_addr src,
55 pim_addr originator)
01d68c9b 56{
d62a17ae 57 struct pim_interface *pinfo;
58 unsigned char buffer[10000];
59 unsigned int b1length = 0;
60 unsigned int length;
61 uint8_t *b1;
d62a17ae 62
63 if (PIM_DEBUG_PIM_REG) {
30b277e1 64 zlog_debug("Sending Register stop for %pSG to %pPA on %s", sg,
98a81d2b 65 &originator, ifp->name);
d62a17ae 66 }
67
68 memset(buffer, 0, 10000);
69 b1 = (uint8_t *)buffer + PIM_MSG_REGISTER_STOP_LEN;
70
71 length = pim_encode_addr_group(b1, AFI_IP, 0, 0, sg->grp);
72 b1length += length;
73 b1 += length;
74
0d360092 75 length = pim_encode_addr_ucast(b1, sg->src);
d62a17ae 76 b1length += length;
77
145e4c38
DL
78 pim_msg_build_header(src, originator, buffer,
79 b1length + PIM_MSG_REGISTER_STOP_LEN,
d57a8bbf 80 PIM_MSG_TYPE_REG_STOP, false);
d62a17ae 81
82 pinfo = (struct pim_interface *)ifp->info;
83 if (!pinfo) {
84 if (PIM_DEBUG_PIM_TRACE)
15569c58 85 zlog_debug("%s: No pinfo!", __func__);
d62a17ae 86 return;
13c2408c 87 }
d62a17ae 88 if (pim_msg_send(pinfo->pim_sock_fd, src, originator, buffer,
6dd493b8 89 b1length + PIM_MSG_REGISTER_STOP_LEN, ifp)) {
d62a17ae 90 if (PIM_DEBUG_PIM_TRACE) {
91 zlog_debug(
92 "%s: could not send PIM register stop message on interface %s",
15569c58 93 __func__, ifp->name);
d62a17ae 94 }
95 }
6dd493b8 96
97 if (!pinfo->pim_passive_enable)
98 ++pinfo->pim_ifstat_reg_stop_send;
01d68c9b
DS
99}
100
03f9d812 101static void pim_reg_stop_upstream(struct pim_instance *pim,
102 struct pim_upstream *up)
103{
104 switch (up->reg_state) {
105 case PIM_REG_NOINFO:
106 case PIM_REG_PRUNE:
107 return;
108 case PIM_REG_JOIN:
109 up->reg_state = PIM_REG_PRUNE;
110 pim_channel_del_oif(up->channel_oil, pim->regiface,
111 PIM_OIF_FLAG_PROTO_PIM, __func__);
112 pim_upstream_start_register_stop_timer(up, 0);
113 pim_vxlan_update_sg_reg_state(pim, up, false);
114 break;
115 case PIM_REG_JOIN_PENDING:
116 up->reg_state = PIM_REG_PRUNE;
117 pim_upstream_start_register_stop_timer(up, 0);
118 return;
119 }
120}
121
b206566b 122int pim_register_stop_recv(struct interface *ifp, uint8_t *buf, int buf_size)
4dffc880 123{
b206566b
DS
124 struct pim_interface *pim_ifp = ifp->info;
125 struct pim_instance *pim = pim_ifp->pim;
03f9d812 126 struct pim_upstream *up = NULL;
127 struct pim_rpf *rp;
6fff2cc6 128 pim_sgaddr sg;
03f9d812 129 struct listnode *up_node;
130 struct pim_upstream *child;
0d360092 131 bool wrong_af = false;
03f9d812 132 bool handling_star = false;
d62a17ae 133 int l;
134
1e8f260c 135 if (pim_ifp->pim_passive_enable) {
136 if (PIM_DEBUG_PIM_PACKETS)
137 zlog_debug(
138 "skip receiving PIM message on passive interface %s",
139 ifp->name);
140 return 0;
141 }
142
25ed72fe
SP
143 ++pim_ifp->pim_ifstat_reg_stop_recv;
144
6fff2cc6 145 memset(&sg, 0, sizeof(sg));
d62a17ae 146 l = pim_parse_addr_group(&sg, buf, buf_size);
147 buf += l;
148 buf_size -= l;
0d360092
DL
149 pim_parse_addr_ucast(&sg.src, buf, buf_size, &wrong_af);
150
151 if (wrong_af) {
152 zlog_err("invalid AF in Register-Stop on %s", ifp->name);
1aa3f6b1 153 return -1;
0d360092 154 }
d62a17ae 155
d62a17ae 156
157 if (PIM_DEBUG_PIM_REG)
03f9d812 158 zlog_debug("Received Register stop for %pSG", &sg);
159
160 rp = RP(pim_ifp->pim, sg.grp);
161 if (rp) {
e502ecad
MR
162 /* As per RFC 7761, Section 4.9.4:
163 * A special wildcard value consisting of an address field of
164 * all zeros can be used to indicate any source.
165 */
5d58abc1 166 if ((pim_addr_cmp(sg.src, rp->rpf_addr) == 0) ||
e502ecad 167 pim_addr_is_any(sg.src)) {
03f9d812 168 handling_star = true;
169 sg.src = PIMADDR_ANY;
170 }
171 }
d62a17ae 172
03f9d812 173 /*
174 * RFC 7761 Sec 4.4.1
175 * Handling Register-Stop(*,G) Messages at the DR:
176 * A Register-Stop(*,G) should be treated as a
177 * Register-Stop(S,G) for all (S,G) Register state
178 * machines that are not in the NoInfo state.
179 */
180 up = pim_upstream_find(pim, &sg);
181 if (up) {
182 /*
183 * If the upstream find actually found a particular
184 * S,G then we *know* that the following for loop
185 * is not going to execute and this is ok
186 */
187 for (ALL_LIST_ELEMENTS_RO(up->sources, up_node, child)) {
188 if (PIM_DEBUG_PIM_REG)
189 zlog_debug("Executing Reg stop for %s",
190 child->sg_str);
191
192 pim_reg_stop_upstream(pim, child);
193 }
194
195 if (PIM_DEBUG_PIM_REG)
196 zlog_debug("Executing Reg stop for %s", up->sg_str);
197 pim_reg_stop_upstream(pim, up);
198 } else {
199 if (!handling_star)
200 return 0;
201 /*
202 * Unfortunately pim was unable to find a *,G
203 * but pim may still actually have individual
204 * S,G's that need to be processed. In that
205 * case pim must do the expensive walk to find
206 * and stop
207 */
208 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
209 if (pim_addr_cmp(up->sg.grp, sg.grp) == 0) {
210 if (PIM_DEBUG_PIM_REG)
211 zlog_debug("Executing Reg stop for %s",
212 up->sg_str);
213 pim_reg_stop_upstream(pim, up);
214 }
215 }
d62a17ae 216 }
217
218 return 0;
4dffc880
DS
219}
220
4b603761
MR
221#if PIM_IPV == 6
222struct in6_addr pim_register_get_unicast_v6_addr(struct pim_interface *p_ifp)
223{
224 struct listnode *node;
225 struct listnode *nextnode;
226 struct pim_secondary_addr *sec_addr;
227 struct pim_interface *pim_ifp;
228 struct interface *ifp;
229 struct pim_instance *pim = p_ifp->pim;
230
231 /* Trying to get the unicast address from the RPF interface first */
232 for (ALL_LIST_ELEMENTS(p_ifp->sec_addr_list, node, nextnode,
233 sec_addr)) {
234 if (!is_ipv6_global_unicast(&sec_addr->addr.u.prefix6))
235 continue;
236
237 return sec_addr->addr.u.prefix6;
238 }
239
240 /* Loop through all the pim interface and try to return a global
241 * unicast ipv6 address
242 */
243 FOR_ALL_INTERFACES (pim->vrf, ifp) {
244 pim_ifp = ifp->info;
245
246 if (!pim_ifp)
247 continue;
248
249 for (ALL_LIST_ELEMENTS(pim_ifp->sec_addr_list, node, nextnode,
250 sec_addr)) {
251 if (!is_ipv6_global_unicast(&sec_addr->addr.u.prefix6))
252 continue;
253
254 return sec_addr->addr.u.prefix6;
255 }
256 }
257
258 zlog_warn("No global address found for use to send register message");
259 return PIMADDR_ANY;
260}
261#endif
262
30b277e1 263void pim_register_send(const uint8_t *buf, int buf_size, pim_addr src,
d62a17ae 264 struct pim_rpf *rpg, int null_register,
265 struct pim_upstream *up)
998af219 266{
d62a17ae 267 unsigned char buffer[10000];
268 unsigned char *b1;
269 struct pim_interface *pinfo;
270 struct interface *ifp;
271
272 if (PIM_DEBUG_PIM_REG) {
30b277e1 273 zlog_debug("Sending %s %sRegister Packet to %pPA", up->sg_str,
5d58abc1 274 null_register ? "NULL " : "", &rpg->rpf_addr);
d62a17ae 275 }
276
277 ifp = rpg->source_nexthop.interface;
278 if (!ifp) {
279 if (PIM_DEBUG_PIM_REG)
280 zlog_debug("%s: No interface to transmit register on",
15569c58 281 __func__);
d62a17ae 282 return;
283 }
284 pinfo = (struct pim_interface *)ifp->info;
285 if (!pinfo) {
286 if (PIM_DEBUG_PIM_REG)
287 zlog_debug(
63efca0e 288 "%s: Interface: %s not configured for pim to transmit on!",
15569c58 289 __func__, ifp->name);
d62a17ae 290 return;
291 }
292
293 if (PIM_DEBUG_PIM_REG) {
30b277e1 294 zlog_debug("%s: Sending %s %sRegister Packet to %pPA on %s",
15569c58 295 __func__, up->sg_str, null_register ? "NULL " : "",
5d58abc1 296 &rpg->rpf_addr, ifp->name);
d62a17ae 297 }
298
299 memset(buffer, 0, 10000);
300 b1 = buffer + PIM_MSG_HEADER_LEN;
301 *b1 |= null_register << 6;
302 b1 = buffer + PIM_MSG_REGISTER_LEN;
303
304 memcpy(b1, (const unsigned char *)buf, buf_size);
305
4b603761
MR
306#if PIM_IPV == 6
307 /* While sending Register message to RP, we cannot use link-local
308 * address therefore using unicast ipv6 address here, choosing it
309 * from the RPF Interface
310 */
311 src = pim_register_get_unicast_v6_addr(pinfo);
312#endif
5d58abc1 313 pim_msg_build_header(src, rpg->rpf_addr, buffer,
314 buf_size + PIM_MSG_REGISTER_LEN,
d57a8bbf 315 PIM_MSG_TYPE_REGISTER, false);
d62a17ae 316
6dd493b8 317 if (!pinfo->pim_passive_enable)
318 ++pinfo->pim_ifstat_reg_send;
d62a17ae 319
94619539 320 if (pim_msg_send(pinfo->pim->reg_sock, src, rpg->rpf_addr, buffer,
6dd493b8 321 buf_size + PIM_MSG_REGISTER_LEN, ifp)) {
d62a17ae 322 if (PIM_DEBUG_PIM_TRACE) {
323 zlog_debug(
324 "%s: could not send PIM register message on interface %s",
15569c58 325 __func__, ifp->name);
d62a17ae 326 }
327 return;
328 }
998af219
DS
329}
330
30b277e1 331#if PIM_IPV == 4
aea1f845
AK
332void pim_null_register_send(struct pim_upstream *up)
333{
334 struct ip ip_hdr;
335 struct pim_interface *pim_ifp;
336 struct pim_rpf *rpg;
30b277e1 337 pim_addr src;
aea1f845
AK
338
339 pim_ifp = up->rpf.source_nexthop.interface->info;
340 if (!pim_ifp) {
23fc858a 341 if (PIM_DEBUG_PIM_TRACE)
aea1f845
AK
342 zlog_debug(
343 "%s: Cannot send null-register for %s no valid iif",
15569c58 344 __func__, up->sg_str);
aea1f845
AK
345 return;
346 }
347
348 rpg = RP(pim_ifp->pim, up->sg.grp);
349 if (!rpg) {
23fc858a 350 if (PIM_DEBUG_PIM_TRACE)
aea1f845
AK
351 zlog_debug(
352 "%s: Cannot send null-register for %s no RPF to the RP",
15569c58 353 __func__, up->sg_str);
aea1f845
AK
354 return;
355 }
356
6006b807 357 memset(&ip_hdr, 0, sizeof(ip_hdr));
aea1f845
AK
358 ip_hdr.ip_p = PIM_IP_PROTO_PIM;
359 ip_hdr.ip_hl = 5;
360 ip_hdr.ip_v = 4;
361 ip_hdr.ip_src = up->sg.src;
362 ip_hdr.ip_dst = up->sg.grp;
363 ip_hdr.ip_len = htons(20);
364
365 /* checksum is broken */
366 src = pim_ifp->primary_address;
d9e75668
AK
367 if (PIM_UPSTREAM_FLAG_TEST_SRC_VXLAN_ORIG(up->flags)) {
368 if (!pim_vxlan_get_register_src(pim_ifp->pim, up, &src)) {
23fc858a 369 if (PIM_DEBUG_PIM_TRACE)
d9e75668
AK
370 zlog_debug(
371 "%s: Cannot send null-register for %s vxlan-aa PIP unavailable",
15569c58 372 __func__, up->sg_str);
d9e75668
AK
373 return;
374 }
375 }
30b277e1 376 pim_register_send((uint8_t *)&ip_hdr, sizeof(struct ip), src, rpg, 1,
377 up);
aea1f845 378}
30b277e1 379#else
380void pim_null_register_send(struct pim_upstream *up)
381{
382 struct ip6_hdr ip6_hdr;
383 struct pim_msg_header pim_msg_header;
384 struct pim_interface *pim_ifp;
385 struct pim_rpf *rpg;
386 pim_addr src;
387 unsigned char buffer[sizeof(ip6_hdr) + sizeof(pim_msg_header)];
388 struct ipv6_ph ph;
389
390 pim_ifp = up->rpf.source_nexthop.interface->info;
391 if (!pim_ifp) {
392 if (PIM_DEBUG_PIM_TRACE)
393 zlog_debug(
394 "Cannot send null-register for %s no valid iif",
395 up->sg_str);
396 return;
397 }
398
399 rpg = RP(pim_ifp->pim, up->sg.grp);
400 if (!rpg) {
401 if (PIM_DEBUG_PIM_TRACE)
402 zlog_debug(
403 "Cannot send null-register for %s no RPF to the RP",
404 up->sg_str);
405 return;
406 }
407
408 memset(&ip6_hdr, 0, sizeof(ip6_hdr));
409 ip6_hdr.ip6_nxt = PIM_IP_PROTO_PIM;
410 ip6_hdr.ip6_plen = PIM_MSG_HEADER_LEN;
411 ip6_hdr.ip6_vfc = 6 << 4;
412 ip6_hdr.ip6_hlim = MAXTTL;
413 ip6_hdr.ip6_src = up->sg.src;
414 ip6_hdr.ip6_dst = up->sg.grp;
415
416 memset(buffer, 0, (sizeof(ip6_hdr) + sizeof(pim_msg_header)));
417 memcpy(buffer, &ip6_hdr, sizeof(ip6_hdr));
418
419 pim_msg_header.ver = 0;
420 pim_msg_header.type = 0;
421 pim_msg_header.reserved = 0;
422
423 pim_msg_header.checksum = 0;
424
425 ph.src = up->sg.src;
426 ph.dst = up->sg.grp;
427 ph.ulpl = htonl(PIM_MSG_HEADER_LEN);
428 ph.next_hdr = IPPROTO_PIM;
429 pim_msg_header.checksum =
430 in_cksum_with_ph6(&ph, &pim_msg_header, PIM_MSG_HEADER_LEN);
431
432 memcpy(buffer + sizeof(ip6_hdr), &pim_msg_header, PIM_MSG_HEADER_LEN);
433
434
435 src = pim_ifp->primary_address;
436 pim_register_send((uint8_t *)buffer,
437 sizeof(ip6_hdr) + PIM_MSG_HEADER_LEN, src, rpg, 1,
438 up);
439}
440#endif
aea1f845 441
01d68c9b
DS
442/*
443 * 4.4.2 Receiving Register Messages at the RP
444 *
445 * When an RP receives a Register message, the course of action is
446 * decided according to the following pseudocode:
447 *
448 * packet_arrives_on_rp_tunnel( pkt ) {
449 * if( outer.dst is not one of my addresses ) {
450 * drop the packet silently.
451 * # Note: this may be a spoofing attempt
452 * }
453 * if( I_am_RP(G) AND outer.dst == RP(G) ) {
2951a7a4
QY
454 * sentRegisterStop = false;
455 * if ( register.borderbit == true ) {
01d68c9b
DS
456 * if ( PMBR(S,G) == unknown ) {
457 * PMBR(S,G) = outer.src
458 * } else if ( outer.src != PMBR(S,G) ) {
459 * send Register-Stop(S,G) to outer.src
460 * drop the packet silently.
461 * }
462 * }
463 * if ( SPTbit(S,G) OR
464 * ( SwitchToSptDesired(S,G) AND
465 * ( inherited_olist(S,G) == NULL ))) {
466 * send Register-Stop(S,G) to outer.src
2951a7a4 467 * sentRegisterStop = true;
01d68c9b
DS
468 * }
469 * if ( SPTbit(S,G) OR SwitchToSptDesired(S,G) ) {
2951a7a4 470 * if ( sentRegisterStop == true ) {
01d68c9b
DS
471 * set KeepaliveTimer(S,G) to RP_Keepalive_Period;
472 * } else {
473 * set KeepaliveTimer(S,G) to Keepalive_Period;
474 * }
475 * }
476 * if( !SPTbit(S,G) AND ! pkt.NullRegisterBit ) {
477 * decapsulate and forward the inner packet to
478 * inherited_olist(S,G,rpt) # Note (+)
479 * }
480 * } else {
481 * send Register-Stop(S,G) to outer.src
482 * # Note (*)
483 * }
484 * }
485 */
c7842d24
MR
486int pim_register_recv(struct interface *ifp, pim_addr dest_addr,
487 pim_addr src_addr, uint8_t *tlv_buf, int tlv_buf_size)
01d68c9b 488{
d62a17ae 489 int sentRegisterStop = 0;
c7842d24 490 const void *ip_hdr;
6fff2cc6 491 pim_sgaddr sg;
d62a17ae 492 uint32_t *bits;
493 int i_am_rp = 0;
2ca35b64
DS
494 struct pim_interface *pim_ifp = ifp->info;
495 struct pim_instance *pim = pim_ifp->pim;
c7842d24 496 pim_addr rp_addr;
fec883d9 497
b4afc283 498 if (pim_ifp->pim_passive_enable) {
499 if (PIM_DEBUG_PIM_PACKETS)
500 zlog_debug(
501 "skip receiving PIM message on passive interface %s",
502 ifp->name);
503 return 0;
504 }
505
75a26779 506#define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4
c7842d24 507 ip_hdr = (tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN);
d62a17ae 508
c7842d24
MR
509 if (!if_address_is_local(&dest_addr, PIM_AF, pim->vrf->vrf_id)) {
510 if (PIM_DEBUG_PIM_REG)
d62a17ae 511 zlog_debug(
c7842d24
MR
512 "%s: Received Register message for destination address: %pPA that I do not own",
513 __func__, &dest_addr);
d62a17ae 514 return 0;
515 }
516
d62a17ae 517 ++pim_ifp->pim_ifstat_reg_recv;
518
519 /*
520 * Please note this is not drawn to get the correct bit/data size
521 *
522 * The entirety of the REGISTER packet looks like this:
523 * -------------------------------------------------------------
524 * | Ver | Type | Reserved | Checksum |
525 * |-----------------------------------------------------------|
526 * |B|N| Reserved 2 |
527 * |-----------------------------------------------------------|
528 * | Encap | IP HDR |
529 * | Mcast | |
530 * | Packet |--------------------------------------------------|
531 * | | Mcast Data |
532 * | | |
533 * ...
534 *
535 * tlv_buf when received from the caller points at the B bit
536 * We need to know the inner source and dest
537 */
538 bits = (uint32_t *)tlv_buf;
539
540 /*
541 * tlv_buf points to the start of the |B|N|... Reserved
542 * Line above. So we need to add 4 bytes to get to the
543 * start of the actual Encapsulated data.
544 */
6fff2cc6 545 memset(&sg, 0, sizeof(sg));
c7842d24 546 sg = pim_sgaddr_from_iphdr(ip_hdr);
d62a17ae 547
30b277e1 548#if PIM_IPV == 6
549 /*
550 * According to RFC section 4.9.3, If Dummy PIM Header is included
551 * in NULL Register as a payload there would be two PIM headers.
552 * The inner PIM Header's checksum field should also be validated
553 * in addition to the outer PIM Header's checksum. Validation of
554 * inner PIM header checksum is done here.
555 */
556 if ((*bits & PIM_REGISTER_NR_BIT) &&
557 ((tlv_buf_size - PIM_MSG_REGISTER_BIT_RESERVED_LEN) >
558 (int)sizeof(struct ip6_hdr))) {
559 uint16_t computed_checksum;
560 uint16_t received_checksum;
561 struct ipv6_ph ph;
562 struct pim_msg_header *header;
563
564 header = (struct pim_msg_header
565 *)(tlv_buf +
566 PIM_MSG_REGISTER_BIT_RESERVED_LEN +
567 sizeof(struct ip6_hdr));
568 ph.src = sg.src;
569 ph.dst = sg.grp;
570 ph.ulpl = htonl(PIM_MSG_HEADER_LEN);
571 ph.next_hdr = IPPROTO_PIM;
572
573 received_checksum = header->checksum;
574
575 header->checksum = 0;
576 computed_checksum = in_cksum_with_ph6(
577 &ph, header, htonl(PIM_MSG_HEADER_LEN));
578
579 if (computed_checksum != received_checksum) {
580 if (PIM_DEBUG_PIM_PACKETS)
581 zlog_debug(
582 "Ignoring Null Register message%pSG from %pPA due to bad checksum in Encapsulated dummy PIM header",
583 &sg, &src_addr);
584 return 0;
585 }
586 }
587#endif
2ca35b64 588 i_am_rp = I_am_RP(pim, sg.grp);
d62a17ae 589
c7842d24
MR
590 if (PIM_DEBUG_PIM_REG)
591 zlog_debug(
592 "Received Register message%pSG from %pPA on %s, rp: %d",
593 &sg, &src_addr, ifp->name, i_am_rp);
d62a17ae 594
34abbcc4 595 if (pim_is_grp_ssm(pim_ifp->pim, sg.grp)) {
2a27f13b 596 if (pim_addr_is_any(sg.src)) {
34abbcc4 597 zlog_warn(
6d7bf748 598 "%s: Received Register message for Group(%pPA) is now in SSM, dropping the packet",
38c848c9 599 __func__, &sg.grp);
34abbcc4
SG
600 /* Drop Packet Silently */
601 return 0;
602 }
603 }
604
5d58abc1 605 rp_addr = (RP(pim, sg.grp))->rpf_addr;
c7842d24 606 if (i_am_rp && (!pim_addr_cmp(dest_addr, rp_addr))) {
d62a17ae 607 sentRegisterStop = 0;
608
f4e74bd0
DS
609 if (pim->register_plist) {
610 struct prefix_list *plist;
611 struct prefix src;
612
c631920c
DL
613 plist = prefix_list_lookup(PIM_AFI,
614 pim->register_plist);
f4e74bd0 615
c631920c 616 pim_addr_to_prefix(&src, sg.src);
f4e74bd0 617
ab2f9e89
DL
618 if (prefix_list_apply_ext(plist, NULL, &src, true) ==
619 PREFIX_DENY) {
f4e74bd0
DS
620 pim_register_stop_send(ifp, &sg, dest_addr,
621 src_addr);
c7842d24 622 if (PIM_DEBUG_PIM_PACKETS)
d51f8b0f 623 zlog_debug(
c7842d24
MR
624 "%s: Sending register-stop to %pPA for %pSG due to prefix-list denial, dropping packet",
625 __func__, &src_addr, &sg);
f4e74bd0
DS
626
627 return 0;
628 }
629 }
630
d62a17ae 631 if (*bits & PIM_REGISTER_BORDER_BIT) {
d62a17ae 632 if (PIM_DEBUG_PIM_PACKETS)
633 zlog_debug(
d139e9e8 634 "%s: Received Register message with Border bit set, ignoring",
d62a17ae 635 __func__);
636
d62a17ae 637 /* Drop Packet Silently */
d139e9e8 638 return 0;
d62a17ae 639 }
640
2ca35b64 641 struct pim_upstream *upstream = pim_upstream_find(pim, &sg);
d62a17ae 642 /*
643 * If we don't have a place to send ignore the packet
644 */
645 if (!upstream) {
646 upstream = pim_upstream_add(
2ca35b64 647 pim, &sg, ifp,
15569c58
DA
648 PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, __func__,
649 NULL);
d62a17ae 650 if (!upstream) {
651 zlog_warn("Failure to create upstream state");
652 return 1;
653 }
654
655 upstream->upstream_register = src_addr;
cc61055f
DS
656 } else {
657 /*
658 * If the FHR has set a very very fast register timer
659 * there exists a possibility that the incoming NULL
660 * register
661 * is happening before we set the spt bit. If so
662 * Do a quick check to update the counters and
663 * then set the spt bit as appropriate
664 */
665 if (upstream->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) {
666 pim_mroute_update_counters(
667 upstream->channel_oil);
668 /*
669 * Have we seen packets?
670 */
671 if (upstream->channel_oil->cc.oldpktcnt
672 < upstream->channel_oil->cc.pktcnt)
673 pim_upstream_set_sptbit(
674 upstream,
675 upstream->rpf.source_nexthop
676 .interface);
677 }
d62a17ae 678 }
679
680 if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
2ca35b64
DS
681 || ((SwitchToSptDesiredOnRp(pim, &sg))
682 && pim_upstream_inherited_olist(pim, upstream) == 0)) {
d62a17ae 683 pim_register_stop_send(ifp, &sg, dest_addr, src_addr);
684 sentRegisterStop = 1;
685 } else {
686 if (PIM_DEBUG_PIM_REG)
687 zlog_debug("(%s) sptbit: %d", upstream->sg_str,
688 upstream->sptbit);
689 }
690 if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
2ca35b64 691 || (SwitchToSptDesiredOnRp(pim, &sg))) {
d62a17ae 692 if (sentRegisterStop) {
693 pim_upstream_keep_alive_timer_start(
2ca35b64 694 upstream, pim->rp_keep_alive_time);
d62a17ae 695 } else {
696 pim_upstream_keep_alive_timer_start(
2ca35b64 697 upstream, pim->keep_alive_time);
d62a17ae 698 }
699 }
700
701 if (!(upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
702 && !(*bits & PIM_REGISTER_NR_BIT)) {
703 // decapsulate and forward the iner packet to
704 // inherited_olist(S,G,rpt)
705 // This is taken care of by the kernel for us
706 }
707 pim_upstream_msdp_reg_timer_start(upstream);
708 } else {
709 if (PIM_DEBUG_PIM_REG) {
710 if (!i_am_rp)
98a81d2b
DL
711 zlog_debug("Received Register packet for %pSG, Rejecting packet because I am not the RP configured for group",
712 &sg);
d62a17ae 713 else
98a81d2b
DL
714 zlog_debug("Received Register packet for %pSG, Rejecting packet because the dst ip address is not the actual RP",
715 &sg);
d62a17ae 716 }
717 pim_register_stop_send(ifp, &sg, dest_addr, src_addr);
718 }
719
8dc60b69 720 return 0;
01d68c9b 721}
46a9ea8b 722
723/*
724 * This routine scan all upstream and update register state and remove pimreg
725 * when couldreg becomes false.
726 */
727void pim_reg_del_on_couldreg_fail(struct interface *ifp)
728{
729 struct pim_interface *pim_ifp = ifp->info;
730 struct pim_instance *pim;
731 struct pim_upstream *up;
732
733 if (!pim_ifp)
734 return;
735
736 pim = pim_ifp->pim;
737
738 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
739 if (ifp != up->rpf.source_nexthop.interface)
740 continue;
741
742 if (!pim_upstream_could_register(up)
743 && (up->reg_state != PIM_REG_NOINFO)) {
744 pim_channel_del_oif(up->channel_oil, pim->regiface,
745 PIM_OIF_FLAG_PROTO_PIM, __func__);
e16d030c 746 EVENT_OFF(up->t_rs_timer);
46a9ea8b 747 up->reg_state = PIM_REG_NOINFO;
748 }
749 }
750}