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