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