]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_join.c
Merge remote-tracking branch 'origin/master' into EIGRP
[mirror_frr.git] / pimd / pim_join.c
CommitLineData
12e41d03
DL
1/*
2 PIM for Quagga
3 Copyright (C) 2008 Everton da Silva Marques
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING; if not, write to the
17 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
18 MA 02110-1301 USA
12e41d03
DL
19*/
20
21#include <zebra.h>
22
23#include "log.h"
24#include "prefix.h"
744d91b3 25#include "if.h"
dfe43e25
DW
26#include "vty.h"
27#include "plist.h"
12e41d03
DL
28
29#include "pimd.h"
30#include "pim_str.h"
31#include "pim_tlv.h"
32#include "pim_msg.h"
33#include "pim_pim.h"
34#include "pim_join.h"
3667b0bc 35#include "pim_oil.h"
12e41d03
DL
36#include "pim_iface.h"
37#include "pim_hello.h"
38#include "pim_ifchannel.h"
6c629103
DS
39#include "pim_rpf.h"
40#include "pim_rp.h"
982bff89 41#include "pim_jp_agg.h"
12e41d03 42
4950938e
DS
43static void
44on_trace (const char *label,
45 struct interface *ifp, struct in_addr src)
12e41d03
DL
46{
47 if (PIM_DEBUG_PIM_TRACE) {
eaa54bdb 48 char src_str[INET_ADDRSTRLEN];
12e41d03
DL
49 pim_inet4_dump("<src?>", src, src_str, sizeof(src_str));
50 zlog_debug("%s: from %s on %s",
51 label, src_str, ifp->name);
52 }
53}
54
55static void recv_join(struct interface *ifp,
56 struct pim_neighbor *neigh,
57 uint16_t holdtime,
58 struct in_addr upstream,
cf4ea1c4 59 struct prefix_sg *sg,
12e41d03
DL
60 uint8_t source_flags)
61{
62 if (PIM_DEBUG_PIM_TRACE) {
eaa54bdb
DW
63 char up_str[INET_ADDRSTRLEN];
64 char neigh_str[INET_ADDRSTRLEN];
12e41d03 65 pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str));
12e41d03 66 pim_inet4_dump("<neigh?>", neigh->source_addr, neigh_str, sizeof(neigh_str));
ee1a477a 67 zlog_warn("%s: join (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s",
12e41d03 68 __PRETTY_FUNCTION__,
cf4ea1c4 69 pim_str_sg_dump (sg),
12e41d03
DL
70 source_flags & PIM_RPT_BIT_MASK,
71 source_flags & PIM_WILDCARD_BIT_MASK,
72 up_str, holdtime, neigh_str, ifp->name);
73 }
346cffe3
DS
74
75 /*
76 * If the RPT and WC are set it's a (*,G)
77 * and the source is the RP
78 */
79 if ((source_flags & PIM_RPT_BIT_MASK) &&
80 (source_flags & PIM_WILDCARD_BIT_MASK))
81 {
cf4ea1c4 82 struct pim_rpf *rp = RP (sg->grp);
346cffe3
DS
83
84 /*
85 * If the RP sent in the message is not
86 * our RP for the group, drop the message
87 */
cf4ea1c4 88 if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr)
346cffe3
DS
89 return;
90
cf4ea1c4 91 sg->src.s_addr = INADDR_ANY;
346cffe3
DS
92 }
93
12e41d03
DL
94 /* Restart join expiry timer */
95 pim_ifchannel_join_add(ifp, neigh->source_addr, upstream,
cf4ea1c4 96 sg, source_flags, holdtime);
6c629103 97
12e41d03
DL
98}
99
100static void recv_prune(struct interface *ifp,
101 struct pim_neighbor *neigh,
102 uint16_t holdtime,
103 struct in_addr upstream,
cf4ea1c4 104 struct prefix_sg *sg,
12e41d03
DL
105 uint8_t source_flags)
106{
107 if (PIM_DEBUG_PIM_TRACE) {
eaa54bdb
DW
108 char up_str[INET_ADDRSTRLEN];
109 char neigh_str[INET_ADDRSTRLEN];
12e41d03 110 pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str));
12e41d03 111 pim_inet4_dump("<neigh?>", neigh->source_addr, neigh_str, sizeof(neigh_str));
7bd2c6fa 112 zlog_warn("%s: prune (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s",
12e41d03 113 __PRETTY_FUNCTION__,
cf4ea1c4 114 pim_str_sg_dump (sg),
12e41d03
DL
115 source_flags & PIM_RPT_BIT_MASK,
116 source_flags & PIM_WILDCARD_BIT_MASK,
117 up_str, holdtime, neigh_str, ifp->name);
118 }
035f28f6
DS
119
120 if ((source_flags & PIM_RPT_BIT_MASK) &&
121 (source_flags & PIM_WILDCARD_BIT_MASK))
122 {
cf4ea1c4 123 struct pim_rpf *rp = RP (sg->grp);
035f28f6
DS
124
125 // Ignoring Prune *,G's at the moment.
cf4ea1c4 126 if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr)
035f28f6
DS
127 return;
128
cf4ea1c4 129 sg->src.s_addr = INADDR_ANY;
035f28f6 130 }
dc686f82 131
cf4ea1c4 132 pim_ifchannel_prune(ifp, upstream, sg, source_flags, holdtime);
6c629103 133
12e41d03
DL
134}
135
136int pim_joinprune_recv(struct interface *ifp,
137 struct pim_neighbor *neigh,
138 struct in_addr src_addr,
139 uint8_t *tlv_buf, int tlv_buf_size)
140{
141 struct prefix msg_upstream_addr;
142 uint8_t msg_num_groups;
143 uint16_t msg_holdtime;
144 int addr_offset;
145 uint8_t *buf;
146 uint8_t *pastend;
147 int remain;
148 int group;
149
12e41d03
DL
150 buf = tlv_buf;
151 pastend = tlv_buf + tlv_buf_size;
152
153 /*
154 Parse ucast addr
155 */
4416b1f6
DS
156 addr_offset = pim_parse_addr_ucast (&msg_upstream_addr,
157 buf, pastend - buf);
12e41d03 158 if (addr_offset < 1) {
eaa54bdb 159 char src_str[INET_ADDRSTRLEN];
12e41d03
DL
160 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
161 zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s",
162 __PRETTY_FUNCTION__,
163 src_str, ifp->name);
164 return -1;
165 }
166 buf += addr_offset;
167
168 /*
169 Check upstream address family
170 */
171 if (msg_upstream_addr.family != AF_INET) {
4950938e 172 if (PIM_DEBUG_PIM_J_P) {
eaa54bdb 173 char src_str[INET_ADDRSTRLEN];
12e41d03
DL
174 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
175 zlog_warn("%s: ignoring join/prune directed to unexpected addr family=%d from %s on %s",
176 __PRETTY_FUNCTION__,
177 msg_upstream_addr.family, src_str, ifp->name);
178 }
179 return -2;
180 }
181
182 remain = pastend - buf;
183 if (remain < 4) {
eaa54bdb 184 char src_str[INET_ADDRSTRLEN];
12e41d03
DL
185 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
186 zlog_warn("%s: short join/prune message buffer for group list: size=%d minimum=%d from %s on %s",
187 __PRETTY_FUNCTION__,
188 remain, 4, src_str, ifp->name);
189 return -4;
190 }
191
192 ++buf; /* skip reserved byte */
193 msg_num_groups = *(const uint8_t *) buf;
194 ++buf;
195 msg_holdtime = ntohs(*(const uint16_t *) buf);
196 ++buf;
197 ++buf;
198
4950938e 199 if (PIM_DEBUG_PIM_J_P) {
eaa54bdb
DW
200 char src_str[INET_ADDRSTRLEN];
201 char upstream_str[INET_ADDRSTRLEN];
12e41d03
DL
202 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
203 pim_inet4_dump("<addr?>", msg_upstream_addr.u.prefix4,
204 upstream_str, sizeof(upstream_str));
4950938e
DS
205 zlog_debug ("%s: join/prune upstream=%s groups=%d holdtime=%d from %s on %s",
206 __PRETTY_FUNCTION__,
207 upstream_str, msg_num_groups, msg_holdtime,
208 src_str, ifp->name);
12e41d03
DL
209 }
210
211 /* Scan groups */
212 for (group = 0; group < msg_num_groups; ++group) {
bce0e645 213 struct prefix_sg sg;
12e41d03
DL
214 uint8_t msg_source_flags;
215 uint16_t msg_num_joined_sources;
216 uint16_t msg_num_pruned_sources;
217 int source;
220d8a49 218 struct pim_ifchannel *ch = NULL;
12e41d03 219
53e39e14 220 memset (&sg, 0, sizeof (struct prefix_sg));
bce0e645 221 addr_offset = pim_parse_addr_group (&sg,
4416b1f6 222 buf, pastend - buf);
12e41d03
DL
223 if (addr_offset < 1) {
224 return -5;
225 }
226 buf += addr_offset;
227
228 remain = pastend - buf;
229 if (remain < 4) {
eaa54bdb 230 char src_str[INET_ADDRSTRLEN];
12e41d03
DL
231 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
232 zlog_warn("%s: short join/prune buffer for source list: size=%d minimum=%d from %s on %s",
233 __PRETTY_FUNCTION__,
234 remain, 4, src_str, ifp->name);
235 return -6;
236 }
237
238 msg_num_joined_sources = ntohs(*(const uint16_t *) buf);
239 buf += 2;
240 msg_num_pruned_sources = ntohs(*(const uint16_t *) buf);
241 buf += 2;
242
4950938e 243 if (PIM_DEBUG_PIM_J_P) {
eaa54bdb
DW
244 char src_str[INET_ADDRSTRLEN];
245 char upstream_str[INET_ADDRSTRLEN];
246 char group_str[INET_ADDRSTRLEN];
12e41d03
DL
247 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
248 pim_inet4_dump("<addr?>", msg_upstream_addr.u.prefix4,
249 upstream_str, sizeof(upstream_str));
bce0e645 250 pim_inet4_dump("<grp?>", sg.grp,
12e41d03 251 group_str, sizeof(group_str));
bce0e645 252 zlog_warn("%s: join/prune upstream=%s group=%s/32 join_src=%d prune_src=%d from %s on %s",
12e41d03 253 __PRETTY_FUNCTION__,
bce0e645 254 upstream_str, group_str,
12e41d03
DL
255 msg_num_joined_sources, msg_num_pruned_sources,
256 src_str, ifp->name);
257 }
258
259 /* Scan joined sources */
260 for (source = 0; source < msg_num_joined_sources; ++source) {
a7762e07 261 addr_offset = pim_parse_addr_source (&sg,
4416b1f6
DS
262 &msg_source_flags,
263 buf, pastend - buf);
12e41d03
DL
264 if (addr_offset < 1) {
265 return -7;
266 }
267
268 buf += addr_offset;
269
270 recv_join(ifp, neigh, msg_holdtime,
271 msg_upstream_addr.u.prefix4,
cf4ea1c4 272 &sg,
12e41d03 273 msg_source_flags);
220d8a49
DS
274
275 if (sg.src.s_addr == INADDR_ANY)
276 {
277 ch = pim_ifchannel_find (ifp, &sg);
1405c852
DS
278 if (ch)
279 pim_ifchannel_set_star_g_join_state (ch, 0);
220d8a49 280 }
12e41d03
DL
281 }
282
283 /* Scan pruned sources */
284 for (source = 0; source < msg_num_pruned_sources; ++source) {
a7762e07 285 addr_offset = pim_parse_addr_source (&sg,
4416b1f6
DS
286 &msg_source_flags,
287 buf, pastend - buf);
12e41d03
DL
288 if (addr_offset < 1) {
289 return -8;
290 }
291
292 buf += addr_offset;
293
294 recv_prune(ifp, neigh, msg_holdtime,
295 msg_upstream_addr.u.prefix4,
cf4ea1c4 296 &sg,
12e41d03
DL
297 msg_source_flags);
298 }
220d8a49
DS
299 if (ch)
300 pim_ifchannel_set_star_g_join_state (ch, 1);
301 ch = NULL;
12e41d03
DL
302 } /* scan groups */
303
304 return 0;
305}
306
982bff89
DS
307/*
308 * J/P Message Format
309 *
310 * While the RFC clearly states that this is 32 bits wide, it
311 * is cheating. These fields:
312 * Encoded-Unicast format (6 bytes MIN)
313 * Encoded-Group format (8 bytes MIN)
314 * Encoded-Source format (8 bytes MIN)
315 * are *not* 32 bits wide.
316 *
317 * Nor does the RFC explicitly call out the size for:
318 * Reserved (1 byte)
319 * Num Groups (1 byte)
320 * Holdtime (2 bytes)
321 * Number of Joined Sources (2 bytes)
322 * Number of Pruned Sources (2 bytes)
323 *
324 * This leads to a missleading representation from casual
325 * reading and making assumptions. Be careful!
326 *
327 * 0 1 2 3
328 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
329 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
330 * |PIM Ver| Type | Reserved | Checksum |
331 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
332 * | Upstream Neighbor Address (Encoded-Unicast format) |
333 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
334 * | Reserved | Num groups | Holdtime |
335 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
336 * | Multicast Group Address 1 (Encoded-Group format) |
337 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
338 * | Number of Joined Sources | Number of Pruned Sources |
339 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
340 * | Joined Source Address 1 (Encoded-Source format) |
341 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
342 * | . |
343 * | . |
344 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
345 * | Joined Source Address n (Encoded-Source format) |
346 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
347 * | Pruned Source Address 1 (Encoded-Source format) |
348 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
349 * | . |
350 * | . |
351 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
352 * | Pruned Source Address n (Encoded-Source format) |
353 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
354 * | Multicast Group Address m (Encoded-Group format) |
355 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
356 * | Number of Joined Sources | Number of Pruned Sources |
357 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
358 * | Joined Source Address 1 (Encoded-Source format) |
359 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
360 * | . |
361 * | . |
362 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
363 * | Joined Source Address n (Encoded-Source format) |
364 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
365 * | Pruned Source Address 1 (Encoded-Source format) |
366 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
367 * | . |
368 * | . |
369 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
370 * | Pruned Source Address n (Encoded-Source format) |
371 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
372 */
b5e2377c 373int pim_joinprune_send(struct pim_rpf *rpf,
982bff89 374 struct list *groups)
12e41d03 375{
982bff89 376 struct pim_jp_agg_group *group;
12e41d03 377 struct pim_interface *pim_ifp;
982bff89
DS
378 struct pim_jp_groups *grp = NULL;
379 struct pim_jp *msg;
380 struct listnode *node, *nnode;
381 uint8_t pim_msg[10000];
382 uint8_t *curr_ptr = pim_msg;
383 bool new_packet = true;
384 size_t packet_left = 0;
385 size_t packet_size = 0;
386 size_t group_size = 0;
12e41d03 387
b5e2377c 388 on_trace (__PRETTY_FUNCTION__, rpf->source_nexthop.interface, rpf->rpf_addr.u.prefix4);
4950938e 389
b5e2377c 390 pim_ifp = rpf->source_nexthop.interface->info;
12e41d03
DL
391
392 if (!pim_ifp) {
393 zlog_warn("%s: multicast not enabled on interface %s",
b5e2377c
DS
394 __PRETTY_FUNCTION__,
395 rpf->source_nexthop.interface->name);
12e41d03
DL
396 return -1;
397 }
398
982bff89
DS
399 if (PIM_INADDR_IS_ANY(rpf->rpf_addr.u.prefix4))
400 {
401 if (PIM_DEBUG_PIM_J_P) {
402 char dst_str[INET_ADDRSTRLEN];
403 pim_inet4_dump("<dst?>", rpf->rpf_addr.u.prefix4, dst_str, sizeof(dst_str));
404 zlog_debug("%s: upstream=%s is myself on interface %s",
405 __PRETTY_FUNCTION__,
406 dst_str, rpf->source_nexthop.interface->name);
407 }
408 return 0;
12e41d03 409 }
12e41d03
DL
410
411 /*
412 RFC 4601: 4.3.1. Sending Hello Messages
413
414 Thus, if a router needs to send a Join/Prune or Assert message on
415 an interface on which it has not yet sent a Hello message with the
416 currently configured IP address, then it MUST immediately send the
417 relevant Hello message without waiting for the Hello Timer to
418 expire, followed by the Join/Prune or Assert message.
419 */
b5e2377c 420 pim_hello_require(rpf->source_nexthop.interface);
12e41d03 421
982bff89
DS
422 for (ALL_LIST_ELEMENTS(groups, node, nnode, group))
423 {
424 if (new_packet)
425 {
426 msg = (struct pim_jp *)pim_msg;
12e41d03 427
982bff89 428 memset(msg, 0, sizeof (*msg));
12e41d03 429
982bff89
DS
430 pim_msg_addr_encode_ipv4_ucast ((uint8_t *)&msg->addr, rpf->rpf_addr.u.prefix4);
431 msg->reserved = 0;
432 msg->holdtime = htons(PIM_JP_HOLDTIME);
48f6dc2d 433
982bff89
DS
434 new_packet = false;
435
436 grp = &msg->groups[0];
437 curr_ptr = (uint8_t *)grp;
438 packet_size = sizeof (struct pim_msg_header);
439 packet_size += sizeof (struct pim_encoded_ipv4_unicast);
440 packet_size += 4; // reserved (1) + groups (1) + holdtime (2)
441
442 packet_left = rpf->source_nexthop.interface->mtu - 24;
443 packet_left -= packet_size;
444 }
445 if (PIM_DEBUG_PIM_J_P) {
446 char dst_str[INET_ADDRSTRLEN];
447 char grp_str[INET_ADDRSTRLEN];
448 pim_inet4_dump("<dst?>", rpf->rpf_addr.u.prefix4, dst_str, sizeof(dst_str));
449 pim_inet4_dump("<grp?>", group->group, grp_str, sizeof(grp_str));
450 zlog_debug("%s: sending (G)=%s to upstream=%s on interface %s",
451 __PRETTY_FUNCTION__,
452 grp_str, dst_str, rpf->source_nexthop.interface->name);
453 }
454
455 group_size = pim_msg_get_jp_group_size (group->sources);
456 if (group_size > packet_left)
457 {
458 pim_msg_build_header (pim_msg, packet_size, PIM_MSG_TYPE_JOIN_PRUNE);
459 if (pim_msg_send(pim_ifp->pim_sock_fd,
460 pim_ifp->primary_address,
461 qpim_all_pim_routers_addr,
462 pim_msg,
463 packet_size,
464 rpf->source_nexthop.interface->name)) {
465 zlog_warn("%s: could not send PIM message on interface %s",
466 __PRETTY_FUNCTION__, rpf->source_nexthop.interface->name);
467 }
468
469 msg = (struct pim_jp *)pim_msg;
470 memset(msg, 0, sizeof (*msg));
471
472 pim_msg_addr_encode_ipv4_ucast ((uint8_t *)&msg->addr, rpf->rpf_addr.u.prefix4);
473 msg->reserved = 0;
474 msg->holdtime = htons(PIM_JP_HOLDTIME);
475
476 new_packet = false;
477
478 grp = &msg->groups[0];
479 curr_ptr = (uint8_t *)grp;
480 packet_size = sizeof (struct pim_msg_header);
481 packet_size += sizeof (struct pim_encoded_ipv4_unicast);
482 packet_size += 4; // reserved (1) + groups (1) + holdtime (2)
483
484 packet_left = rpf->source_nexthop.interface->mtu - 24;
485 packet_left -= packet_size;
486 }
12e41d03 487
982bff89
DS
488 msg->num_groups++;
489 /*
490 Build PIM message
491 */
492
493 curr_ptr += group_size;
494 packet_left -= group_size;
495 packet_size += group_size;
e7eefda4 496 pim_msg_build_jp_groups (grp, group, group_size);
982bff89
DS
497
498 grp = (struct pim_jp_groups *)curr_ptr;
499 if (packet_left < sizeof (struct pim_jp_groups) || msg->num_groups == 255)
500 {
501 pim_msg_build_header (pim_msg, packet_size, PIM_MSG_TYPE_JOIN_PRUNE);
502 if (pim_msg_send(pim_ifp->pim_sock_fd,
503 pim_ifp->primary_address,
504 qpim_all_pim_routers_addr,
505 pim_msg,
506 packet_size,
507 rpf->source_nexthop.interface->name)) {
508 zlog_warn("%s: could not send PIM message on interface %s",
509 __PRETTY_FUNCTION__, rpf->source_nexthop.interface->name);
510 }
511
512 new_packet = true;
513 }
514 }
515
516
517 if (!new_packet)
518 {
519 //msg->num_groups = htons (msg->num_groups);
520 pim_msg_build_header (pim_msg, packet_size, PIM_MSG_TYPE_JOIN_PRUNE);
521 if (pim_msg_send(pim_ifp->pim_sock_fd,
522 pim_ifp->primary_address,
523 qpim_all_pim_routers_addr,
524 pim_msg,
525 packet_size,
526 rpf->source_nexthop.interface->name)) {
527 zlog_warn("%s: could not send PIM message on interface %s",
528 __PRETTY_FUNCTION__, rpf->source_nexthop.interface->name);
529 }
530 }
12e41d03
DL
531 return 0;
532}