Coverage Report

Created: 2026-02-21 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/pimd/pim_register.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 * PIM for Quagga
4
 * Copyright (C) 2015 Cumulus Networks, Inc.
5
 * Donald Sharp
6
 */
7
8
#include <zebra.h>
9
10
#include "log.h"
11
#include "if.h"
12
#include "frrevent.h"
13
#include "prefix.h"
14
#include "vty.h"
15
#include "plist.h"
16
17
#include "pimd.h"
18
#include "pim_mroute.h"
19
#include "pim_iface.h"
20
#include "pim_msg.h"
21
#include "pim_pim.h"
22
#include "pim_str.h"
23
#include "pim_rp.h"
24
#include "pim_register.h"
25
#include "pim_upstream.h"
26
#include "pim_rpf.h"
27
#include "pim_oil.h"
28
#include "pim_zebra.h"
29
#include "pim_join.h"
30
#include "pim_util.h"
31
#include "pim_ssm.h"
32
#include "pim_vxlan.h"
33
#include "pim_addr.h"
34
35
struct event *send_test_packet_timer = NULL;
36
37
void pim_register_join(struct pim_upstream *up)
38
0
{
39
0
  struct pim_instance *pim = up->channel_oil->pim;
40
41
0
  if (pim_is_grp_ssm(pim, up->sg.grp)) {
42
0
    if (PIM_DEBUG_PIM_EVENTS)
43
0
      zlog_debug("%s register setup skipped as group is SSM",
44
0
           up->sg_str);
45
0
    return;
46
0
  }
47
48
0
  pim_channel_add_oif(up->channel_oil, pim->regiface,
49
0
          PIM_OIF_FLAG_PROTO_PIM, __func__);
50
0
  up->reg_state = PIM_REG_JOIN;
51
0
  pim_vxlan_update_sg_reg_state(pim, up, true);
52
0
}
53
54
void pim_register_stop_send(struct interface *ifp, pim_sgaddr *sg, pim_addr src,
55
          pim_addr originator)
56
6
{
57
6
  struct pim_interface *pinfo;
58
6
  unsigned char buffer[10000];
59
6
  unsigned int b1length = 0;
60
6
  unsigned int length;
61
6
  uint8_t *b1;
62
63
6
  if (PIM_DEBUG_PIM_REG) {
64
0
    zlog_debug("Sending Register stop for %pSG to %pPA on %s", sg,
65
0
         &originator, ifp->name);
66
0
  }
67
68
6
  memset(buffer, 0, 10000);
69
6
  b1 = (uint8_t *)buffer + PIM_MSG_REGISTER_STOP_LEN;
70
71
6
  length = pim_encode_addr_group(b1, AFI_IP, 0, 0, sg->grp);
72
6
  b1length += length;
73
6
  b1 += length;
74
75
6
  length = pim_encode_addr_ucast(b1, sg->src);
76
6
  b1length += length;
77
78
6
  pim_msg_build_header(src, originator, buffer,
79
6
           b1length + PIM_MSG_REGISTER_STOP_LEN,
80
6
           PIM_MSG_TYPE_REG_STOP, false);
81
82
6
  pinfo = (struct pim_interface *)ifp->info;
83
6
  if (!pinfo) {
84
0
    if (PIM_DEBUG_PIM_TRACE)
85
0
      zlog_debug("%s: No pinfo!", __func__);
86
0
    return;
87
0
  }
88
6
  if (pim_msg_send(pinfo->pim_sock_fd, src, originator, buffer,
89
6
       b1length + PIM_MSG_REGISTER_STOP_LEN, ifp)) {
90
0
    if (PIM_DEBUG_PIM_TRACE) {
91
0
      zlog_debug(
92
0
        "%s: could not send PIM register stop message on interface %s",
93
0
        __func__, ifp->name);
94
0
    }
95
0
  }
96
97
6
  if (!pinfo->pim_passive_enable)
98
6
    ++pinfo->pim_ifstat_reg_stop_send;
99
6
}
100
101
static void pim_reg_stop_upstream(struct pim_instance *pim,
102
          struct pim_upstream *up)
103
118
{
104
118
  switch (up->reg_state) {
105
118
  case PIM_REG_NOINFO:
106
118
  case PIM_REG_PRUNE:
107
118
    return;
108
0
  case PIM_REG_JOIN:
109
0
    up->reg_state = PIM_REG_PRUNE;
110
0
    pim_channel_del_oif(up->channel_oil, pim->regiface,
111
0
            PIM_OIF_FLAG_PROTO_PIM, __func__);
112
0
    pim_upstream_start_register_stop_timer(up, 0);
113
0
    pim_vxlan_update_sg_reg_state(pim, up, false);
114
0
    break;
115
0
  case PIM_REG_JOIN_PENDING:
116
0
    up->reg_state = PIM_REG_PRUNE;
117
0
    pim_upstream_start_register_stop_timer(up, 0);
118
0
    return;
119
118
  }
120
118
}
121
122
int pim_register_stop_recv(struct interface *ifp, uint8_t *buf, int buf_size)
123
144
{
124
144
  struct pim_interface *pim_ifp = ifp->info;
125
144
  struct pim_instance *pim = pim_ifp->pim;
126
144
  struct pim_upstream *up = NULL;
127
144
  struct pim_rpf *rp;
128
144
  pim_sgaddr sg;
129
144
  struct listnode *up_node;
130
144
  struct pim_upstream *child;
131
144
  bool wrong_af = false;
132
144
  bool handling_star = false;
133
144
  int l;
134
135
144
  if (pim_ifp->pim_passive_enable) {
136
0
    if (PIM_DEBUG_PIM_PACKETS)
137
0
      zlog_debug(
138
0
        "skip receiving PIM message on passive interface %s",
139
0
        ifp->name);
140
0
    return 0;
141
0
  }
142
143
144
  ++pim_ifp->pim_ifstat_reg_stop_recv;
144
145
144
  memset(&sg, 0, sizeof(sg));
146
144
  l = pim_parse_addr_group(&sg, buf, buf_size);
147
144
  buf += l;
148
144
  buf_size -= l;
149
144
  pim_parse_addr_ucast(&sg.src, buf, buf_size, &wrong_af);
150
151
144
  if (wrong_af) {
152
1
    zlog_err("invalid AF in Register-Stop on %s", ifp->name);
153
1
    return -1;
154
1
  }
155
156
157
143
  if (PIM_DEBUG_PIM_REG)
158
0
    zlog_debug("Received Register stop for %pSG", &sg);
159
160
143
  rp = RP(pim_ifp->pim, sg.grp);
161
143
  if (rp) {
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
     */
166
17
    if ((pim_addr_cmp(sg.src, rp->rpf_addr) == 0) ||
167
15
        pim_addr_is_any(sg.src)) {
168
15
      handling_star = true;
169
15
      sg.src = PIMADDR_ANY;
170
15
    }
171
17
  }
172
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
143
  up = pim_upstream_find(pim, &sg);
181
143
  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
90
    for (ALL_LIST_ELEMENTS_RO(up->sources, up_node, child)) {
188
90
      if (PIM_DEBUG_PIM_REG)
189
0
        zlog_debug("Executing Reg stop for %s",
190
90
             child->sg_str);
191
192
90
      pim_reg_stop_upstream(pim, child);
193
90
    }
194
195
24
    if (PIM_DEBUG_PIM_REG)
196
0
      zlog_debug("Executing Reg stop for %s", up->sg_str);
197
24
    pim_reg_stop_upstream(pim, up);
198
119
  } else {
199
119
    if (!handling_star)
200
111
      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
383
    frr_each (rb_pim_upstream, &pim->upstream_head, up) {
209
383
      if (pim_addr_cmp(up->sg.grp, sg.grp) == 0) {
210
4
        if (PIM_DEBUG_PIM_REG)
211
0
          zlog_debug("Executing Reg stop for %s",
212
4
               up->sg_str);
213
4
        pim_reg_stop_upstream(pim, up);
214
4
      }
215
383
    }
216
8
  }
217
218
32
  return 0;
219
143
}
220
221
#if PIM_IPV == 6
222
struct 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
263
void pim_register_send(const uint8_t *buf, int buf_size, pim_addr src,
264
           struct pim_rpf *rpg, int null_register,
265
           struct pim_upstream *up)
266
0
{
267
0
  unsigned char buffer[10000];
268
0
  unsigned char *b1;
269
0
  struct pim_interface *pinfo;
270
0
  struct interface *ifp;
271
272
0
  if (PIM_DEBUG_PIM_REG) {
273
0
    zlog_debug("Sending %s %sRegister Packet to %pPA", up->sg_str,
274
0
         null_register ? "NULL " : "", &rpg->rpf_addr);
275
0
  }
276
277
0
  ifp = rpg->source_nexthop.interface;
278
0
  if (!ifp) {
279
0
    if (PIM_DEBUG_PIM_REG)
280
0
      zlog_debug("%s: No interface to transmit register on",
281
0
           __func__);
282
0
    return;
283
0
  }
284
0
  pinfo = (struct pim_interface *)ifp->info;
285
0
  if (!pinfo) {
286
0
    if (PIM_DEBUG_PIM_REG)
287
0
      zlog_debug(
288
0
        "%s: Interface: %s not configured for pim to transmit on!",
289
0
        __func__, ifp->name);
290
0
    return;
291
0
  }
292
293
0
  if (PIM_DEBUG_PIM_REG) {
294
0
    zlog_debug("%s: Sending %s %sRegister Packet to %pPA on %s",
295
0
         __func__, up->sg_str, null_register ? "NULL " : "",
296
0
         &rpg->rpf_addr, ifp->name);
297
0
  }
298
299
0
  memset(buffer, 0, 10000);
300
0
  b1 = buffer + PIM_MSG_HEADER_LEN;
301
0
  *b1 |= null_register << 6;
302
0
  b1 = buffer + PIM_MSG_REGISTER_LEN;
303
304
0
  memcpy(b1, (const unsigned char *)buf, buf_size);
305
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
313
0
  pim_msg_build_header(src, rpg->rpf_addr, buffer,
314
0
           buf_size + PIM_MSG_REGISTER_LEN,
315
0
           PIM_MSG_TYPE_REGISTER, false);
316
317
0
  if (!pinfo->pim_passive_enable)
318
0
    ++pinfo->pim_ifstat_reg_send;
319
320
0
  if (pim_msg_send(pinfo->pim->reg_sock, src, rpg->rpf_addr, buffer,
321
0
       buf_size + PIM_MSG_REGISTER_LEN, ifp)) {
322
0
    if (PIM_DEBUG_PIM_TRACE) {
323
0
      zlog_debug(
324
0
        "%s: could not send PIM register message on interface %s",
325
0
        __func__, ifp->name);
326
0
    }
327
0
    return;
328
0
  }
329
0
}
330
331
#if PIM_IPV == 4
332
void pim_null_register_send(struct pim_upstream *up)
333
0
{
334
0
  struct ip ip_hdr;
335
0
  struct pim_interface *pim_ifp;
336
0
  struct pim_rpf *rpg;
337
0
  pim_addr src;
338
339
0
  pim_ifp = up->rpf.source_nexthop.interface->info;
340
0
  if (!pim_ifp) {
341
0
    if (PIM_DEBUG_PIM_TRACE)
342
0
      zlog_debug(
343
0
        "%s: Cannot send null-register for %s no valid iif",
344
0
        __func__, up->sg_str);
345
0
    return;
346
0
  }
347
348
0
  rpg = RP(pim_ifp->pim, up->sg.grp);
349
0
  if (!rpg) {
350
0
    if (PIM_DEBUG_PIM_TRACE)
351
0
      zlog_debug(
352
0
        "%s: Cannot send null-register for %s no RPF to the RP",
353
0
        __func__, up->sg_str);
354
0
    return;
355
0
  }
356
357
0
  memset(&ip_hdr, 0, sizeof(ip_hdr));
358
0
  ip_hdr.ip_p = PIM_IP_PROTO_PIM;
359
0
  ip_hdr.ip_hl = 5;
360
0
  ip_hdr.ip_v = 4;
361
0
  ip_hdr.ip_src = up->sg.src;
362
0
  ip_hdr.ip_dst = up->sg.grp;
363
0
  ip_hdr.ip_len = htons(20);
364
365
  /* checksum is broken */
366
0
  src = pim_ifp->primary_address;
367
0
  if (PIM_UPSTREAM_FLAG_TEST_SRC_VXLAN_ORIG(up->flags)) {
368
0
    if (!pim_vxlan_get_register_src(pim_ifp->pim, up, &src)) {
369
0
      if (PIM_DEBUG_PIM_TRACE)
370
0
        zlog_debug(
371
0
          "%s: Cannot send null-register for %s vxlan-aa PIP unavailable",
372
0
          __func__, up->sg_str);
373
0
      return;
374
0
    }
375
0
  }
376
0
  pim_register_send((uint8_t *)&ip_hdr, sizeof(struct ip), src, rpg, 1,
377
0
        up);
378
0
}
379
#else
380
void 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
441
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) ) {
454
 *            sentRegisterStop = false;
455
 *            if ( register.borderbit == true ) {
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
467
 *              sentRegisterStop = true;
468
 *            }
469
 *            if ( SPTbit(S,G) OR SwitchToSptDesired(S,G) ) {
470
 *                 if ( sentRegisterStop == true ) {
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
 */
486
int pim_register_recv(struct interface *ifp, pim_addr dest_addr,
487
          pim_addr src_addr, uint8_t *tlv_buf, int tlv_buf_size)
488
142
{
489
142
  int sentRegisterStop = 0;
490
142
  const void *ip_hdr;
491
142
  pim_sgaddr sg;
492
142
  uint32_t *bits;
493
142
  int i_am_rp = 0;
494
142
  struct pim_interface *pim_ifp = ifp->info;
495
142
  struct pim_instance *pim = pim_ifp->pim;
496
142
  pim_addr rp_addr;
497
142
  struct pim_rpf *rpg;
498
499
142
  if (pim_ifp->pim_passive_enable) {
500
0
    if (PIM_DEBUG_PIM_PACKETS)
501
0
      zlog_debug(
502
0
        "skip receiving PIM message on passive interface %s",
503
0
        ifp->name);
504
0
    return 0;
505
0
  }
506
507
201
#define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4
508
509
142
  if (tlv_buf_size
510
142
      < (int)(PIM_MSG_REGISTER_BIT_RESERVED_LEN + sizeof(struct ip))) {
511
83
    return 0;
512
83
  }
513
59
  ip_hdr = (tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN);
514
515
59
  if (!if_address_is_local(&dest_addr, PIM_AF, pim->vrf->vrf_id)) {
516
41
    if (PIM_DEBUG_PIM_REG)
517
0
      zlog_debug(
518
41
        "%s: Received Register message for destination address: %pPA that I do not own",
519
41
        __func__, &dest_addr);
520
41
    return 0;
521
41
  }
522
523
18
  ++pim_ifp->pim_ifstat_reg_recv;
524
525
  /*
526
   * Please note this is not drawn to get the correct bit/data size
527
   *
528
   * The entirety of the REGISTER packet looks like this:
529
   * -------------------------------------------------------------
530
   * | Ver  | Type | Reserved     |       Checksum               |
531
   * |-----------------------------------------------------------|
532
   * |B|N|     Reserved 2                                        |
533
   * |-----------------------------------------------------------|
534
   * | Encap  |                IP HDR                            |
535
   * | Mcast  |                                                  |
536
   * | Packet |--------------------------------------------------|
537
   * |        |               Mcast Data                         |
538
   * |        |                                                  |
539
   * ...
540
   *
541
   * tlv_buf when received from the caller points at the B bit
542
   * We need to know the inner source and dest
543
   */
544
18
  bits = (uint32_t *)tlv_buf;
545
546
  /*
547
   * tlv_buf points to the start of the |B|N|... Reserved
548
   * Line above.  So we need to add 4 bytes to get to the
549
   * start of the actual Encapsulated data.
550
   */
551
18
  memset(&sg, 0, sizeof(sg));
552
18
  sg = pim_sgaddr_from_iphdr(ip_hdr);
553
554
#if PIM_IPV == 6
555
  /*
556
   * According to RFC section 4.9.3, If Dummy PIM Header is included
557
   * in NULL Register as a payload there would be two PIM headers.
558
   * The inner PIM Header's checksum field should also be validated
559
   * in addition to the outer PIM Header's checksum. Validation of
560
   * inner PIM header checksum is done here.
561
   */
562
  if ((*bits & PIM_REGISTER_NR_BIT) &&
563
      ((tlv_buf_size - PIM_MSG_REGISTER_BIT_RESERVED_LEN) >
564
       (int)sizeof(struct ip6_hdr))) {
565
    uint16_t computed_checksum;
566
    uint16_t received_checksum;
567
    struct ipv6_ph ph;
568
    struct pim_msg_header *header;
569
570
    header = (struct pim_msg_header
571
          *)(tlv_buf +
572
             PIM_MSG_REGISTER_BIT_RESERVED_LEN +
573
             sizeof(struct ip6_hdr));
574
    ph.src = sg.src;
575
    ph.dst = sg.grp;
576
    ph.ulpl = htonl(PIM_MSG_HEADER_LEN);
577
    ph.next_hdr = IPPROTO_PIM;
578
579
    received_checksum = header->checksum;
580
581
    header->checksum = 0;
582
    computed_checksum = in_cksum_with_ph6(
583
      &ph, header, htonl(PIM_MSG_HEADER_LEN));
584
585
    if (computed_checksum != received_checksum) {
586
      if (PIM_DEBUG_PIM_PACKETS)
587
        zlog_debug(
588
          "Ignoring Null Register message%pSG from %pPA due to bad checksum in Encapsulated dummy PIM header",
589
          &sg, &src_addr);
590
      return 0;
591
    }
592
  }
593
#endif
594
18
  i_am_rp = I_am_RP(pim, sg.grp);
595
596
18
  if (PIM_DEBUG_PIM_REG)
597
0
    zlog_debug(
598
18
      "Received Register message%pSG from %pPA on %s, rp: %d",
599
18
      &sg, &src_addr, ifp->name, i_am_rp);
600
601
18
  if (pim_is_grp_ssm(pim_ifp->pim, sg.grp)) {
602
2
    if (pim_addr_is_any(sg.src)) {
603
1
      zlog_warn(
604
1
        "%s: Received Register message for Group(%pPA) is now in SSM, dropping the packet",
605
1
        __func__, &sg.grp);
606
      /* Drop Packet Silently */
607
1
      return 0;
608
1
    }
609
2
  }
610
611
17
  rpg = RP(pim, sg.grp);
612
17
  if (!rpg) {
613
11
    zlog_warn("%s: Received Register Message %pSG from %pPA on %s where the RP could not be looked up",
614
11
        __func__, &sg, &src_addr, ifp->name);
615
11
    return 0;
616
11
  }
617
618
6
  rp_addr = rpg->rpf_addr;
619
6
  if (i_am_rp && (!pim_addr_cmp(dest_addr, rp_addr))) {
620
0
    sentRegisterStop = 0;
621
622
0
    if (pim->register_plist) {
623
0
      struct prefix_list *plist;
624
0
      struct prefix src;
625
626
0
      plist = prefix_list_lookup(PIM_AFI,
627
0
               pim->register_plist);
628
629
0
      pim_addr_to_prefix(&src, sg.src);
630
631
0
      if (prefix_list_apply_ext(plist, NULL, &src, true) ==
632
0
          PREFIX_DENY) {
633
0
        pim_register_stop_send(ifp, &sg, dest_addr,
634
0
                   src_addr);
635
0
        if (PIM_DEBUG_PIM_PACKETS)
636
0
          zlog_debug(
637
0
            "%s: Sending register-stop to %pPA for %pSG due to prefix-list denial, dropping packet",
638
0
            __func__, &src_addr, &sg);
639
640
0
        return 0;
641
0
      }
642
0
    }
643
644
0
    if (*bits & PIM_REGISTER_BORDER_BIT) {
645
0
      if (PIM_DEBUG_PIM_PACKETS)
646
0
        zlog_debug(
647
0
          "%s: Received Register message with Border bit set, ignoring",
648
0
          __func__);
649
650
        /* Drop Packet Silently */
651
0
      return 0;
652
0
    }
653
654
0
    struct pim_upstream *upstream = pim_upstream_find(pim, &sg);
655
    /*
656
     * If we don't have a place to send ignore the packet
657
     */
658
0
    if (!upstream) {
659
0
      upstream = pim_upstream_add(
660
0
        pim, &sg, ifp,
661
0
        PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, __func__,
662
0
        NULL);
663
0
      if (!upstream) {
664
0
        zlog_warn("Failure to create upstream state");
665
0
        return 1;
666
0
      }
667
668
0
      upstream->upstream_register = src_addr;
669
0
    } else {
670
      /*
671
       * If the FHR has set a very very fast register timer
672
       * there exists a possibility that the incoming NULL
673
       * register
674
       * is happening before we set the spt bit.  If so
675
       * Do a quick check to update the counters and
676
       * then set the spt bit as appropriate
677
       */
678
0
      if (upstream->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) {
679
0
        pim_mroute_update_counters(
680
0
          upstream->channel_oil);
681
        /*
682
         * Have we seen packets?
683
         */
684
0
        if (upstream->channel_oil->cc.oldpktcnt
685
0
            < upstream->channel_oil->cc.pktcnt)
686
0
          pim_upstream_set_sptbit(
687
0
            upstream,
688
0
            upstream->rpf.source_nexthop
689
0
              .interface);
690
0
      }
691
0
    }
692
693
0
    if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
694
0
        || ((SwitchToSptDesiredOnRp(pim, &sg))
695
0
      && pim_upstream_inherited_olist(pim, upstream) == 0)) {
696
0
      pim_register_stop_send(ifp, &sg, dest_addr, src_addr);
697
0
      sentRegisterStop = 1;
698
0
    } else {
699
0
      if (PIM_DEBUG_PIM_REG)
700
0
        zlog_debug("(%s) sptbit: %d", upstream->sg_str,
701
0
             upstream->sptbit);
702
0
    }
703
0
    if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
704
0
        || (SwitchToSptDesiredOnRp(pim, &sg))) {
705
0
      if (sentRegisterStop) {
706
0
        pim_upstream_keep_alive_timer_start(
707
0
          upstream, pim->rp_keep_alive_time);
708
0
      } else {
709
0
        pim_upstream_keep_alive_timer_start(
710
0
          upstream, pim->keep_alive_time);
711
0
      }
712
0
    }
713
714
0
    if (!(upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
715
0
        && !(*bits & PIM_REGISTER_NR_BIT)) {
716
      // decapsulate and forward the iner packet to
717
      // inherited_olist(S,G,rpt)
718
      // This is taken care of by the kernel for us
719
0
    }
720
0
    pim_upstream_msdp_reg_timer_start(upstream);
721
6
  } else {
722
6
    if (PIM_DEBUG_PIM_REG) {
723
0
      if (!i_am_rp)
724
0
        zlog_debug("Received Register packet for %pSG, Rejecting packet because I am not the RP configured for group",
725
0
             &sg);
726
0
      else
727
0
        zlog_debug("Received Register packet for %pSG, Rejecting packet because the dst ip address is not the actual RP",
728
0
             &sg);
729
0
    }
730
6
    pim_register_stop_send(ifp, &sg, dest_addr, src_addr);
731
6
  }
732
733
6
  return 0;
734
6
}
735
736
/*
737
 * This routine scan all upstream and update register state and remove pimreg
738
 * when couldreg becomes false.
739
 */
740
void pim_reg_del_on_couldreg_fail(struct interface *ifp)
741
1
{
742
1
  struct pim_interface *pim_ifp = ifp->info;
743
1
  struct pim_instance *pim;
744
1
  struct pim_upstream *up;
745
746
1
  if (!pim_ifp)
747
0
    return;
748
749
1
  pim = pim_ifp->pim;
750
751
1
  frr_each (rb_pim_upstream, &pim->upstream_head, up) {
752
0
    if (ifp != up->rpf.source_nexthop.interface)
753
0
      continue;
754
755
0
    if (!pim_upstream_could_register(up)
756
0
        && (up->reg_state != PIM_REG_NOINFO)) {
757
0
      pim_channel_del_oif(up->channel_oil, pim->regiface,
758
0
              PIM_OIF_FLAG_PROTO_PIM, __func__);
759
0
      EVENT_OFF(up->t_rs_timer);
760
0
      up->reg_state = PIM_REG_NOINFO;
761
0
    }
762
0
  }
763
1
}