]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_tlv.c
80d60b862833f3f45319400ccda79dc00d7f6507
[mirror_frr.git] / pimd / pim_tlv.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
9 #include "log.h"
10 #include "prefix.h"
11 #include "if.h"
12
13 #include "pimd.h"
14 #include "pim_instance.h"
15 #include "pim_int.h"
16 #include "pim_tlv.h"
17 #include "pim_str.h"
18 #include "pim_msg.h"
19 #include "pim_iface.h"
20 #include "pim_addr.h"
21
22 #if PIM_IPV == 4
23 #define PIM_MSG_ADDRESS_FAMILY PIM_MSG_ADDRESS_FAMILY_IPV4
24 #else
25 #define PIM_MSG_ADDRESS_FAMILY PIM_MSG_ADDRESS_FAMILY_IPV6
26 #endif
27
28 uint8_t *pim_tlv_append_uint16(uint8_t *buf, const uint8_t *buf_pastend,
29 uint16_t option_type, uint16_t option_value)
30 {
31 uint16_t option_len = 2;
32
33 if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend)
34 return NULL;
35
36 *(uint16_t *)buf = htons(option_type);
37 buf += 2;
38 *(uint16_t *)buf = htons(option_len);
39 buf += 2;
40 *(uint16_t *)buf = htons(option_value);
41 buf += option_len;
42
43 return buf;
44 }
45
46 uint8_t *pim_tlv_append_2uint16(uint8_t *buf, const uint8_t *buf_pastend,
47 uint16_t option_type, uint16_t option_value1,
48 uint16_t option_value2)
49 {
50 uint16_t option_len = 4;
51
52 if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend)
53 return NULL;
54
55 *(uint16_t *)buf = htons(option_type);
56 buf += 2;
57 *(uint16_t *)buf = htons(option_len);
58 buf += 2;
59 *(uint16_t *)buf = htons(option_value1);
60 buf += 2;
61 *(uint16_t *)buf = htons(option_value2);
62 buf += 2;
63
64 return buf;
65 }
66
67 uint8_t *pim_tlv_append_uint32(uint8_t *buf, const uint8_t *buf_pastend,
68 uint16_t option_type, uint32_t option_value)
69 {
70 uint16_t option_len = 4;
71
72 if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend)
73 return NULL;
74
75 *(uint16_t *)buf = htons(option_type);
76 buf += 2;
77 *(uint16_t *)buf = htons(option_len);
78 buf += 2;
79 pim_write_uint32(buf, option_value);
80 buf += option_len;
81
82 return buf;
83 }
84
85 #define ucast_ipv4_encoding_len (2 + sizeof(struct in_addr))
86 #define ucast_ipv6_encoding_len (2 + sizeof(struct in6_addr))
87
88 /*
89 * An Encoded-Unicast address takes the following format:
90 *
91 * 0 1 2 3
92 * 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
93 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
94 * | Addr Family | Encoding Type | Unicast Address
95 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+...
96 *
97 * Addr Family
98 * The PIM address family of the 'Unicast Address' field of this
99 * address.
100 *
101 * Values 0-127 are as assigned by the IANA for Internet Address *
102 * Families in [7]. Values 128-250 are reserved to be assigned by
103 * the IANA for PIM-specific Address Families. Values 251 though
104 * 255 are designated for private use. As there is no assignment
105 * authority for this space, collisions should be expected.
106 *
107 * Encoding Type
108 * The type of encoding used within a specific Address Family. The
109 * value '0' is reserved for this field and represents the native
110 * encoding of the Address Family.
111 *
112 * Unicast Address
113 * The unicast address as represented by the given Address Family
114 * and Encoding Type.
115 */
116 int pim_encode_addr_ucast(uint8_t *buf, pim_addr addr)
117 {
118 uint8_t *start = buf;
119
120 *buf++ = PIM_MSG_ADDRESS_FAMILY;
121 *buf++ = 0;
122 memcpy(buf, &addr, sizeof(addr));
123 buf += sizeof(addr);
124
125 return buf - start;
126 }
127
128 int pim_encode_addr_ucast_prefix(uint8_t *buf, struct prefix *p)
129 {
130 switch (p->family) {
131 case AF_INET:
132 *buf = PIM_MSG_ADDRESS_FAMILY_IPV4; /* notice: AF_INET !=
133 PIM_MSG_ADDRESS_FAMILY_IPV4
134 */
135 ++buf;
136 *buf = 0; /* ucast IPv4 native encoding type (RFC
137 4601: 4.9.1) */
138 ++buf;
139 memcpy(buf, &p->u.prefix4, sizeof(struct in_addr));
140 return ucast_ipv4_encoding_len;
141 case AF_INET6:
142 *buf = PIM_MSG_ADDRESS_FAMILY_IPV6;
143 ++buf;
144 *buf = 0;
145 ++buf;
146 memcpy(buf, &p->u.prefix6, sizeof(struct in6_addr));
147 return ucast_ipv6_encoding_len;
148 default:
149 return 0;
150 }
151 }
152
153 #define group_ipv4_encoding_len (4 + sizeof(struct in_addr))
154
155 /*
156 * Encoded-Group addresses take the following format:
157 *
158 * 0 1 2 3
159 * 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
160 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
161 * | Addr Family | Encoding Type |B| Reserved |Z| Mask Len |
162 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
163 * | Group multicast Address
164 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+...
165 *
166 * Addr Family
167 * Described above.
168 *
169 * Encoding Type
170 * Described above.
171 *
172 * [B]idirectional PIM
173 * Indicates the group range should use Bidirectional PIM [13].
174 * For PIM-SM defined in this specification, this bit MUST be zero.
175 *
176 * Reserved
177 * Transmitted as zero. Ignored upon receipt.
178 *
179 * Admin Scope [Z]one
180 * indicates the group range is an admin scope zone. This is used
181 * in the Bootstrap Router Mechanism [11] only. For all other
182 * purposes, this bit is set to zero and ignored on receipt.
183 *
184 * Mask Len
185 * The Mask length field is 8 bits. The value is the number of
186 * contiguous one bits that are left justified and used as a mask;
187 * when combined with the group address, it describes a range of
188 * groups. It is less than or equal to the address length in bits
189 * for the given Address Family and Encoding Type. If the message
190 * is sent for a single group, then the Mask length must equal the
191 * address length in bits for the given Address Family and Encoding
192 * Type (e.g., 32 for IPv4 native encoding, 128 for IPv6 native
193 * encoding).
194 *
195 * Group multicast Address
196 * Contains the group address.
197 */
198 int pim_encode_addr_group(uint8_t *buf, afi_t afi, int bidir, int scope,
199 pim_addr group)
200 {
201 uint8_t *start = buf;
202 uint8_t flags = 0;
203
204 flags |= bidir << 8;
205 flags |= scope;
206
207 *buf++ = PIM_MSG_ADDRESS_FAMILY;
208 *buf++ = 0;
209 *buf++ = flags;
210 *buf++ = sizeof(group) * 8;
211 memcpy(buf, &group, sizeof(group));
212 buf += sizeof(group);
213
214 return buf - start;
215 }
216
217 uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend,
218 struct interface *ifp, int family)
219 {
220 struct listnode *node;
221 uint16_t option_len = 0;
222 uint8_t *curr;
223 size_t uel;
224 struct list *ifconnected = ifp->connected;
225 struct pim_interface *pim_ifp = ifp->info;
226 pim_addr addr;
227
228 node = listhead(ifconnected);
229
230 /* Empty address list ? */
231 if (!node) {
232 return buf;
233 }
234
235 if (family == AF_INET)
236 uel = ucast_ipv4_encoding_len;
237 else
238 uel = ucast_ipv6_encoding_len;
239
240 /* Scan secondary address list */
241 curr = buf + 4; /* skip T and L */
242 for (; node; node = listnextnode(node)) {
243 struct connected *ifc = listgetdata(node);
244 struct prefix *p = ifc->address;
245 int l_encode;
246
247 addr = pim_addr_from_prefix(p);
248 if (!pim_addr_cmp(pim_ifp->primary_address, addr))
249 /* don't add the primary address
250 * into the secondary address list */
251 continue;
252
253 if ((curr + uel) > buf_pastend)
254 return 0;
255
256 if (p->family != family)
257 continue;
258
259 l_encode = pim_encode_addr_ucast_prefix(curr, p);
260 curr += l_encode;
261 option_len += l_encode;
262 }
263
264 if (PIM_DEBUG_PIM_TRACE_DETAIL) {
265 zlog_debug(
266 "%s: number of encoded secondary unicast IPv4 addresses: %zu",
267 __func__, option_len / uel);
268 }
269
270 if (option_len < 1) {
271 /* Empty secondary unicast IPv4 address list */
272 return buf;
273 }
274
275 /*
276 * Write T and L
277 */
278 *(uint16_t *)buf = htons(PIM_MSG_OPTION_TYPE_ADDRESS_LIST);
279 *(uint16_t *)(buf + 2) = htons(option_len);
280
281 return curr;
282 }
283
284 static int check_tlv_length(const char *label, const char *tlv_name,
285 const char *ifname, pim_addr src_addr,
286 int correct_len, int option_len)
287 {
288 if (option_len != correct_len) {
289 zlog_warn(
290 "%s: PIM hello %s TLV with incorrect value size=%d correct=%d from %pPAs on interface %s",
291 label, tlv_name, option_len, correct_len, &src_addr,
292 ifname);
293 return -1;
294 }
295
296 return 0;
297 }
298
299 static void check_tlv_redefinition_uint16(const char *label,
300 const char *tlv_name,
301 const char *ifname, pim_addr src_addr,
302 pim_hello_options options,
303 pim_hello_options opt_mask,
304 uint16_t new, uint16_t old)
305 {
306 if (PIM_OPTION_IS_SET(options, opt_mask))
307 zlog_warn(
308 "%s: PIM hello TLV redefined %s=%u old=%u from %pPAs on interface %s",
309 label, tlv_name, new, old, &src_addr, ifname);
310 }
311
312 static void check_tlv_redefinition_uint32(const char *label,
313 const char *tlv_name,
314 const char *ifname, pim_addr src_addr,
315 pim_hello_options options,
316 pim_hello_options opt_mask,
317 uint32_t new, uint32_t old)
318 {
319 if (PIM_OPTION_IS_SET(options, opt_mask))
320 zlog_warn(
321 "%s: PIM hello TLV redefined %s=%u old=%u from %pPAs on interface %s",
322 label, tlv_name, new, old, &src_addr, ifname);
323 }
324
325 static void check_tlv_redefinition_uint32_hex(
326 const char *label, const char *tlv_name, const char *ifname,
327 pim_addr src_addr, pim_hello_options options,
328 pim_hello_options opt_mask, uint32_t new, uint32_t old)
329 {
330 if (PIM_OPTION_IS_SET(options, opt_mask))
331 zlog_warn(
332 "%s: PIM hello TLV redefined %s=%08x old=%08x from %pPAs on interface %s",
333 label, tlv_name, new, old, &src_addr, ifname);
334 }
335
336 int pim_tlv_parse_holdtime(const char *ifname, pim_addr src_addr,
337 pim_hello_options *hello_options,
338 uint16_t *hello_option_holdtime, uint16_t option_len,
339 const uint8_t *tlv_curr)
340 {
341 const char *label = "holdtime";
342
343 if (check_tlv_length(__func__, label, ifname, src_addr,
344 sizeof(uint16_t), option_len)) {
345 return -1;
346 }
347
348 check_tlv_redefinition_uint16(__func__, label, ifname, src_addr,
349 *hello_options, PIM_OPTION_MASK_HOLDTIME,
350 PIM_TLV_GET_HOLDTIME(tlv_curr),
351 *hello_option_holdtime);
352
353 PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_HOLDTIME);
354
355 *hello_option_holdtime = PIM_TLV_GET_HOLDTIME(tlv_curr);
356
357 return 0;
358 }
359
360 int pim_tlv_parse_lan_prune_delay(const char *ifname, pim_addr src_addr,
361 pim_hello_options *hello_options,
362 uint16_t *hello_option_propagation_delay,
363 uint16_t *hello_option_override_interval,
364 uint16_t option_len, const uint8_t *tlv_curr)
365 {
366 if (check_tlv_length(__func__, "lan_prune_delay", ifname, src_addr,
367 sizeof(uint32_t), option_len)) {
368 return -1;
369 }
370
371 check_tlv_redefinition_uint16(__func__, "propagation_delay", ifname,
372 src_addr, *hello_options,
373 PIM_OPTION_MASK_LAN_PRUNE_DELAY,
374 PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr),
375 *hello_option_propagation_delay);
376
377 PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY);
378
379 *hello_option_propagation_delay =
380 PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr);
381 if (PIM_TLV_GET_CAN_DISABLE_JOIN_SUPPRESSION(tlv_curr)) {
382 PIM_OPTION_SET(*hello_options,
383 PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION);
384 } else {
385 PIM_OPTION_UNSET(*hello_options,
386 PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION);
387 }
388 ++tlv_curr;
389 ++tlv_curr;
390 *hello_option_override_interval =
391 PIM_TLV_GET_OVERRIDE_INTERVAL(tlv_curr);
392
393 return 0;
394 }
395
396 int pim_tlv_parse_dr_priority(const char *ifname, pim_addr src_addr,
397 pim_hello_options *hello_options,
398 uint32_t *hello_option_dr_priority,
399 uint16_t option_len, const uint8_t *tlv_curr)
400 {
401 const char *label = "dr_priority";
402
403 if (check_tlv_length(__func__, label, ifname, src_addr,
404 sizeof(uint32_t), option_len)) {
405 return -1;
406 }
407
408 check_tlv_redefinition_uint32(
409 __func__, label, ifname, src_addr, *hello_options,
410 PIM_OPTION_MASK_DR_PRIORITY, PIM_TLV_GET_DR_PRIORITY(tlv_curr),
411 *hello_option_dr_priority);
412
413 PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_DR_PRIORITY);
414
415 *hello_option_dr_priority = PIM_TLV_GET_DR_PRIORITY(tlv_curr);
416
417 return 0;
418 }
419
420 int pim_tlv_parse_generation_id(const char *ifname, pim_addr src_addr,
421 pim_hello_options *hello_options,
422 uint32_t *hello_option_generation_id,
423 uint16_t option_len, const uint8_t *tlv_curr)
424 {
425 const char *label = "generation_id";
426
427 if (check_tlv_length(__func__, label, ifname, src_addr,
428 sizeof(uint32_t), option_len)) {
429 return -1;
430 }
431
432 check_tlv_redefinition_uint32_hex(__func__, label, ifname, src_addr,
433 *hello_options,
434 PIM_OPTION_MASK_GENERATION_ID,
435 PIM_TLV_GET_GENERATION_ID(tlv_curr),
436 *hello_option_generation_id);
437
438 PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_GENERATION_ID);
439
440 *hello_option_generation_id = PIM_TLV_GET_GENERATION_ID(tlv_curr);
441
442 return 0;
443 }
444
445 int pim_parse_addr_ucast_prefix(struct prefix *p, const uint8_t *buf,
446 int buf_size)
447 {
448 const int ucast_encoding_min_len = 3; /* 1 family + 1 type + 1 addr */
449 const uint8_t *addr;
450 const uint8_t *pastend;
451 int family;
452 int type;
453
454 if (buf_size < ucast_encoding_min_len) {
455 zlog_warn(
456 "%s: unicast address encoding overflow: left=%d needed=%d",
457 __func__, buf_size, ucast_encoding_min_len);
458 return -1;
459 }
460
461 addr = buf;
462 pastend = buf + buf_size;
463
464 family = *addr++;
465 type = *addr++;
466
467 if (type) {
468 zlog_warn("%s: unknown unicast address encoding type=%d",
469 __func__, type);
470 return -2;
471 }
472
473 switch (family) {
474 case PIM_MSG_ADDRESS_FAMILY_IPV4:
475 if ((addr + sizeof(struct in_addr)) > pastend) {
476 zlog_warn(
477 "%s: IPv4 unicast address overflow: left=%td needed=%zu",
478 __func__, pastend - addr,
479 sizeof(struct in_addr));
480 return -3;
481 }
482
483 p->family = AF_INET; /* notice: AF_INET !=
484 PIM_MSG_ADDRESS_FAMILY_IPV4 */
485 memcpy(&p->u.prefix4, addr, sizeof(struct in_addr));
486 p->prefixlen = IPV4_MAX_BITLEN;
487 addr += sizeof(struct in_addr);
488
489 break;
490 case PIM_MSG_ADDRESS_FAMILY_IPV6:
491 if ((addr + sizeof(struct in6_addr)) > pastend) {
492 zlog_warn(
493 "%s: IPv6 unicast address overflow: left=%td needed %zu",
494 __func__, pastend - addr,
495 sizeof(struct in6_addr));
496 return -3;
497 }
498
499 p->family = AF_INET6;
500 p->prefixlen = IPV6_MAX_BITLEN;
501 memcpy(&p->u.prefix6, addr, sizeof(struct in6_addr));
502 addr += sizeof(struct in6_addr);
503
504 break;
505 default: {
506 zlog_warn("%s: unknown unicast address encoding family=%d from",
507 __func__, family);
508 return -4;
509 }
510 }
511
512 return addr - buf;
513 }
514
515 int pim_parse_addr_ucast(pim_addr *out, const uint8_t *buf, int buf_size,
516 bool *wrong_af)
517 {
518 struct prefix p;
519 int ret;
520
521 ret = pim_parse_addr_ucast_prefix(&p, buf, buf_size);
522 if (ret < 0)
523 return ret;
524
525 if (p.family != PIM_AF) {
526 *wrong_af = true;
527 return -5;
528 }
529
530 memcpy(out, &p.u.val, sizeof(*out));
531 return ret;
532 }
533
534 int pim_parse_addr_group(pim_sgaddr *sg, const uint8_t *buf, int buf_size)
535 {
536 const int grp_encoding_min_len =
537 4; /* 1 family + 1 type + 1 reserved + 1 addr */
538 const uint8_t *addr;
539 const uint8_t *pastend;
540 int family;
541 int type;
542 int mask_len;
543
544 if (buf_size < grp_encoding_min_len) {
545 zlog_warn(
546 "%s: group address encoding overflow: left=%d needed=%d",
547 __func__, buf_size, grp_encoding_min_len);
548 return -1;
549 }
550
551 addr = buf;
552 pastend = buf + buf_size;
553
554 family = *addr++;
555 type = *addr++;
556 ++addr; /* skip b_reserved_z fields */
557 mask_len = *addr++;
558
559 if (type) {
560 zlog_warn("%s: unknown group address encoding type=%d from",
561 __func__, type);
562 return -2;
563 }
564
565 if (family != PIM_MSG_ADDRESS_FAMILY) {
566 zlog_warn(
567 "%s: unknown group address encoding family=%d mask_len=%d from",
568 __func__, family, mask_len);
569 return -4;
570 }
571
572 if ((addr + sizeof(sg->grp)) > pastend) {
573 zlog_warn(
574 "%s: group address overflow: left=%td needed=%zu from",
575 __func__, pastend - addr, sizeof(sg->grp));
576 return -3;
577 }
578
579 memcpy(&sg->grp, addr, sizeof(sg->grp));
580 addr += sizeof(sg->grp);
581
582 return addr - buf;
583 }
584
585 int pim_parse_addr_source(pim_sgaddr *sg, uint8_t *flags, const uint8_t *buf,
586 int buf_size)
587 {
588 const int src_encoding_min_len =
589 4; /* 1 family + 1 type + 1 reserved + 1 addr */
590 const uint8_t *addr;
591 const uint8_t *pastend;
592 int family;
593 int type;
594 int mask_len;
595
596 if (buf_size < src_encoding_min_len) {
597 zlog_warn(
598 "%s: source address encoding overflow: left=%d needed=%d",
599 __func__, buf_size, src_encoding_min_len);
600 return -1;
601 }
602
603 addr = buf;
604 pastend = buf + buf_size;
605
606 family = *addr++;
607 type = *addr++;
608 *flags = *addr++;
609 mask_len = *addr++;
610
611 if (type) {
612 zlog_warn(
613 "%s: unknown source address encoding type=%d: %02x%02x%02x%02x",
614 __func__, type, buf[0], buf[1], buf[2], buf[3]);
615 return -2;
616 }
617
618 switch (family) {
619 case PIM_MSG_ADDRESS_FAMILY:
620 if ((addr + sizeof(sg->src)) > pastend) {
621 zlog_warn(
622 "%s: IP source address overflow: left=%td needed=%zu",
623 __func__, pastend - addr, sizeof(sg->src));
624 return -3;
625 }
626
627 memcpy(&sg->src, addr, sizeof(sg->src));
628
629 /*
630 RFC 4601: 4.9.1 Encoded Source and Group Address Formats
631
632 Encoded-Source Address
633
634 The mask length MUST be equal to the mask length in bits for
635 the given Address Family and Encoding Type (32 for IPv4
636 native and 128 for IPv6 native). A router SHOULD ignore any
637 messages received with any other mask length.
638 */
639 if (mask_len != PIM_MAX_BITLEN) {
640 zlog_warn("%s: IP bad source address mask: %d",
641 __func__, mask_len);
642 return -4;
643 }
644
645 addr += sizeof(sg->src);
646
647 break;
648 default:
649 zlog_warn(
650 "%s: unknown source address encoding family=%d: %02x%02x%02x%02x",
651 __func__, family, buf[0], buf[1], buf[2], buf[3]);
652 return -5;
653 }
654
655 return addr - buf;
656 }
657
658 #define FREE_ADDR_LIST(hello_option_addr_list) \
659 { \
660 if (hello_option_addr_list) { \
661 list_delete(&hello_option_addr_list); \
662 hello_option_addr_list = 0; \
663 } \
664 }
665
666 int pim_tlv_parse_addr_list(const char *ifname, pim_addr src_addr,
667 pim_hello_options *hello_options,
668 struct list **hello_option_addr_list,
669 uint16_t option_len, const uint8_t *tlv_curr)
670 {
671 const uint8_t *addr;
672 const uint8_t *pastend;
673
674 assert(hello_option_addr_list);
675
676 /*
677 Scan addr list
678 */
679 addr = tlv_curr;
680 pastend = tlv_curr + option_len;
681 while (addr < pastend) {
682 struct prefix tmp, src_pfx;
683 int addr_offset;
684
685 /*
686 Parse ucast addr
687 */
688 addr_offset =
689 pim_parse_addr_ucast_prefix(&tmp, addr, pastend - addr);
690 if (addr_offset < 1) {
691 zlog_warn(
692 "%s: pim_parse_addr_ucast() failure: from %pPAs on %s",
693 __func__, &src_addr, ifname);
694 FREE_ADDR_LIST(*hello_option_addr_list);
695 return -1;
696 }
697 addr += addr_offset;
698
699 /*
700 Debug
701 */
702 if (PIM_DEBUG_PIM_TRACE) {
703 switch (tmp.family) {
704 case AF_INET: {
705 char addr_str[INET_ADDRSTRLEN];
706 pim_inet4_dump("<addr?>", tmp.u.prefix4,
707 addr_str, sizeof(addr_str));
708 zlog_debug(
709 "%s: PIM hello TLV option: list_old_size=%d IPv4 address %s from %pPAs on %s",
710 __func__,
711 *hello_option_addr_list
712 ? ((int)listcount(
713 *hello_option_addr_list))
714 : -1,
715 addr_str, &src_addr, ifname);
716 } break;
717 case AF_INET6:
718 break;
719 default:
720 zlog_debug(
721 "%s: PIM hello TLV option: list_old_size=%d UNKNOWN address family from %pPAs on %s",
722 __func__,
723 *hello_option_addr_list
724 ? ((int)listcount(
725 *hello_option_addr_list))
726 : -1,
727 &src_addr, ifname);
728 }
729 }
730
731 /*
732 Exclude neighbor's primary address if incorrectly included in
733 the secondary address list
734 */
735 pim_addr_to_prefix(&src_pfx, src_addr);
736 if (!prefix_cmp(&tmp, &src_pfx)) {
737 zlog_warn(
738 "%s: ignoring primary address in secondary list from %pPAs on %s",
739 __func__, &src_addr, ifname);
740 continue;
741 }
742
743 /*
744 Allocate list if needed
745 */
746 if (!*hello_option_addr_list) {
747 *hello_option_addr_list = list_new();
748 (*hello_option_addr_list)->del = prefix_free_lists;
749 }
750
751 /*
752 Attach addr to list
753 */
754 {
755 struct prefix *p;
756 p = prefix_new();
757 prefix_copy(p, &tmp);
758 listnode_add(*hello_option_addr_list, p);
759 }
760
761 } /* while (addr < pastend) */
762
763 /*
764 Mark hello option
765 */
766 PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_ADDRESS_LIST);
767
768 return 0;
769 }