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