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