blob: 16b7e93e516c48e70e780cfd98359b837f530240 [file] [log] [blame]
Everton Marques871dbcf2009-08-11 15:43:05 -03001/*
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 $QuaggaId: $Format:%an, %ai, %h$ $
21*/
22
23#include <zebra.h>
24
25#include "log.h"
26#include "prefix.h"
27
28#include "pimd.h"
Everton Marques7c5f5012009-11-19 17:00:23 -020029#include "pim_int.h"
Everton Marques871dbcf2009-08-11 15:43:05 -030030#include "pim_tlv.h"
31#include "pim_str.h"
32#include "pim_msg.h"
33
Everton Marques7c5f5012009-11-19 17:00:23 -020034char *pim_tlv_append_uint16(uint8_t *buf,
35 const uint8_t *buf_pastend,
Everton Marques871dbcf2009-08-11 15:43:05 -030036 uint16_t option_type,
37 uint16_t option_value)
38{
39 uint16_t option_len = 2;
40
41 if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) {
42 zlog_warn("%s: buffer overflow: left=%d needed=%d",
43 __PRETTY_FUNCTION__,
44 buf_pastend - buf, PIM_TLV_OPTION_SIZE(option_len));
45 return 0;
46 }
47
48 *(uint16_t *) buf = htons(option_type);
49 buf += 2;
50 *(uint16_t *) buf = htons(option_len);
51 buf += 2;
52 *(uint16_t *) buf = htons(option_value);
53 buf += option_len;
54
55 return buf;
56}
57
Everton Marques7c5f5012009-11-19 17:00:23 -020058char *pim_tlv_append_2uint16(uint8_t *buf,
59 const uint8_t *buf_pastend,
Everton Marques871dbcf2009-08-11 15:43:05 -030060 uint16_t option_type,
61 uint16_t option_value1,
62 uint16_t option_value2)
63{
64 uint16_t option_len = 4;
65
66 if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) {
67 zlog_warn("%s: buffer overflow: left=%d needed=%d",
68 __PRETTY_FUNCTION__,
69 buf_pastend - buf, PIM_TLV_OPTION_SIZE(option_len));
70 return 0;
71 }
72
73 *(uint16_t *) buf = htons(option_type);
74 buf += 2;
75 *(uint16_t *) buf = htons(option_len);
76 buf += 2;
77 *(uint16_t *) buf = htons(option_value1);
78 buf += 2;
79 *(uint16_t *) buf = htons(option_value2);
80 buf += 2;
81
82 return buf;
83}
84
Everton Marques7c5f5012009-11-19 17:00:23 -020085char *pim_tlv_append_uint32(uint8_t *buf,
86 const uint8_t *buf_pastend,
Everton Marques871dbcf2009-08-11 15:43:05 -030087 uint16_t option_type,
88 uint32_t option_value)
89{
90 uint16_t option_len = 4;
91
92 if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) {
93 zlog_warn("%s: buffer overflow: left=%d needed=%d",
94 __PRETTY_FUNCTION__,
95 buf_pastend - buf, PIM_TLV_OPTION_SIZE(option_len));
96 return 0;
97 }
98
99 *(uint16_t *) buf = htons(option_type);
100 buf += 2;
101 *(uint16_t *) buf = htons(option_len);
102 buf += 2;
Everton Marques7c5f5012009-11-19 17:00:23 -0200103 pim_write_uint32(buf, option_value);
Everton Marques871dbcf2009-08-11 15:43:05 -0300104 buf += option_len;
105
106 return buf;
107}
108
109#define ucast_ipv4_encoding_len (2 + sizeof(struct in_addr))
110
Everton Marques7c5f5012009-11-19 17:00:23 -0200111char *pim_tlv_append_addrlist_ucast(uint8_t *buf,
112 const uint8_t *buf_pastend,
Everton Marques871dbcf2009-08-11 15:43:05 -0300113 struct list *ifconnected)
114{
115 struct listnode *node;
116 uint16_t option_len = 0;
117
Everton Marques7c5f5012009-11-19 17:00:23 -0200118 uint8_t *curr;
Everton Marques871dbcf2009-08-11 15:43:05 -0300119
120 node = listhead(ifconnected);
121
122 /* Empty address list ? */
123 if (!node) {
124 return buf;
125 }
126
127 /* Skip first address (primary) */
128 node = listnextnode(node);
129
130 /* Scan secondary address list */
131 curr = buf + 4; /* skip T and L */
132 for (; node; node = listnextnode(node)) {
133 struct connected *ifc = listgetdata(node);
134 struct prefix *p = ifc->address;
135
136 if (p->family != AF_INET)
137 continue;
138
139 if ((curr + ucast_ipv4_encoding_len) > buf_pastend) {
140 zlog_warn("%s: buffer overflow: left=%d needed=%d",
141 __PRETTY_FUNCTION__,
142 buf_pastend - curr, ucast_ipv4_encoding_len);
143 return 0;
144 }
145
146 /* Write encoded unicast IPv4 address */
147 *(uint8_t *) curr = PIM_MSG_ADDRESS_FAMILY_IPV4; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */
148 ++curr;
149 *(uint8_t *) curr = 0; /* ucast IPv4 native encoding type (RFC 4601: 4.9.1) */
150 ++curr;
151 *(struct in_addr *) curr = p->u.prefix4;
152 curr += sizeof(struct in_addr);
153
154 option_len += ucast_ipv4_encoding_len;
155 }
156
157 if (PIM_DEBUG_PIM_TRACE) {
158 zlog_warn("%s: number of encoded secondary unicast IPv4 addresses: %d",
159 __PRETTY_FUNCTION__,
160 option_len / ucast_ipv4_encoding_len);
161 }
162
163 if (option_len < 1) {
164 /* Empty secondary unicast IPv4 address list */
165 return buf;
166 }
167
168 /*
169 * Write T and L
170 */
171 *(uint16_t *) buf = htons(PIM_MSG_OPTION_TYPE_ADDRESS_LIST);
172 *(uint16_t *) (buf + 2) = htons(option_len);
173
174 return curr;
175}
176
177static int check_tlv_length(const char *label, const char *tlv_name,
178 const char *ifname, struct in_addr src_addr,
179 int correct_len, int option_len)
180{
181 if (option_len != correct_len) {
182 char src_str[100];
183 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
184 zlog_warn("%s: PIM hello %s TLV with incorrect value size=%d correct=%d from %s on interface %s",
185 label, tlv_name,
186 option_len, correct_len,
187 src_str, ifname);
188 return -1;
189 }
190
191 return 0;
192}
193
194static void check_tlv_redefinition_uint16(const char *label, const char *tlv_name,
195 const char *ifname, struct in_addr src_addr,
196 pim_hello_options options,
197 pim_hello_options opt_mask,
198 uint16_t new, uint16_t old)
199{
200 if (PIM_OPTION_IS_SET(options, opt_mask)) {
201 char src_str[100];
202 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
203 zlog_warn("%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s",
204 label, tlv_name,
205 new, old,
206 src_str, ifname);
207 }
208}
209
210static void check_tlv_redefinition_uint32(const char *label, const char *tlv_name,
211 const char *ifname, struct in_addr src_addr,
212 pim_hello_options options,
213 pim_hello_options opt_mask,
214 uint32_t new, uint32_t old)
215{
216 if (PIM_OPTION_IS_SET(options, opt_mask)) {
217 char src_str[100];
218 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
219 zlog_warn("%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s",
220 label, tlv_name,
221 new, old,
222 src_str, ifname);
223 }
224}
225
226static void check_tlv_redefinition_uint32_hex(const char *label, const char *tlv_name,
227 const char *ifname, struct in_addr src_addr,
228 pim_hello_options options,
229 pim_hello_options opt_mask,
230 uint32_t new, uint32_t old)
231{
232 if (PIM_OPTION_IS_SET(options, opt_mask)) {
233 char src_str[100];
234 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
235 zlog_warn("%s: PIM hello TLV redefined %s=%08x old=%08x from %s on interface %s",
236 label, tlv_name,
237 new, old,
238 src_str, ifname);
239 }
240}
241
242int pim_tlv_parse_holdtime(const char *ifname, struct in_addr src_addr,
243 pim_hello_options *hello_options,
244 uint16_t *hello_option_holdtime,
245 uint16_t option_len,
246 const char *tlv_curr)
247{
248 const char *label = "holdtime";
249
250 if (check_tlv_length(__PRETTY_FUNCTION__, label,
251 ifname, src_addr,
252 sizeof(uint16_t), option_len)) {
253 return -1;
254 }
255
256 check_tlv_redefinition_uint16(__PRETTY_FUNCTION__, label,
257 ifname, src_addr,
258 *hello_options, PIM_OPTION_MASK_HOLDTIME,
259 PIM_TLV_GET_HOLDTIME(tlv_curr),
260 *hello_option_holdtime);
261
262 PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_HOLDTIME);
263
264 *hello_option_holdtime = PIM_TLV_GET_HOLDTIME(tlv_curr);
265
266 return 0;
267}
268
269int pim_tlv_parse_lan_prune_delay(const char *ifname, struct in_addr src_addr,
270 pim_hello_options *hello_options,
271 uint16_t *hello_option_propagation_delay,
272 uint16_t *hello_option_override_interval,
273 uint16_t option_len,
274 const char *tlv_curr)
275{
276 if (check_tlv_length(__PRETTY_FUNCTION__, "lan_prune_delay",
277 ifname, src_addr,
278 sizeof(uint32_t), option_len)) {
279 return -1;
280 }
281
282 check_tlv_redefinition_uint16(__PRETTY_FUNCTION__, "propagation_delay",
283 ifname, src_addr,
284 *hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY,
285 PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr),
286 *hello_option_propagation_delay);
287
288 PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY);
289
290 *hello_option_propagation_delay = PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr);
291 if (PIM_TLV_GET_CAN_DISABLE_JOIN_SUPPRESSION(tlv_curr)) {
292 PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION);
293 }
294 else {
295 PIM_OPTION_UNSET(*hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION);
296 }
297 ++tlv_curr;
298 ++tlv_curr;
299 *hello_option_override_interval = PIM_TLV_GET_OVERRIDE_INTERVAL(tlv_curr);
300
301 return 0;
302}
303
304int pim_tlv_parse_dr_priority(const char *ifname, struct in_addr src_addr,
305 pim_hello_options *hello_options,
306 uint32_t *hello_option_dr_priority,
307 uint16_t option_len,
308 const char *tlv_curr)
309{
310 const char *label = "dr_priority";
311
312 if (check_tlv_length(__PRETTY_FUNCTION__, label,
313 ifname, src_addr,
314 sizeof(uint32_t), option_len)) {
315 return -1;
316 }
317
318 check_tlv_redefinition_uint32(__PRETTY_FUNCTION__, label,
319 ifname, src_addr,
320 *hello_options, PIM_OPTION_MASK_DR_PRIORITY,
321 PIM_TLV_GET_DR_PRIORITY(tlv_curr),
322 *hello_option_dr_priority);
323
324 PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_DR_PRIORITY);
325
326 *hello_option_dr_priority = PIM_TLV_GET_DR_PRIORITY(tlv_curr);
Everton Marques7c5f5012009-11-19 17:00:23 -0200327
Everton Marques871dbcf2009-08-11 15:43:05 -0300328 return 0;
329}
330
331int pim_tlv_parse_generation_id(const char *ifname, struct in_addr src_addr,
332 pim_hello_options *hello_options,
333 uint32_t *hello_option_generation_id,
334 uint16_t option_len,
335 const char *tlv_curr)
336{
337 const char *label = "generation_id";
338
339 if (check_tlv_length(__PRETTY_FUNCTION__, label,
340 ifname, src_addr,
341 sizeof(uint32_t), option_len)) {
342 return -1;
343 }
344
345 check_tlv_redefinition_uint32_hex(__PRETTY_FUNCTION__, label,
346 ifname, src_addr,
347 *hello_options, PIM_OPTION_MASK_GENERATION_ID,
348 PIM_TLV_GET_GENERATION_ID(tlv_curr),
349 *hello_option_generation_id);
350
351 PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_GENERATION_ID);
352
353 *hello_option_generation_id = PIM_TLV_GET_GENERATION_ID(tlv_curr);
354
355 return 0;
356}
357
358int pim_parse_addr_ucast(const char *ifname, struct in_addr src_addr,
359 struct prefix *p,
360 const char *buf,
361 int buf_size)
362{
363 const int ucast_encoding_min_len = 3; /* 1 family + 1 type + 1 addr */
364 const char *addr;
365 const char *pastend;
366 int family;
367 int type;
368
369 if (buf_size < ucast_encoding_min_len) {
370 char src_str[100];
371 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
372 zlog_warn("%s: unicast address encoding overflow: left=%d needed=%d from %s on %s",
373 __PRETTY_FUNCTION__,
374 buf_size, ucast_encoding_min_len,
375 src_str, ifname);
376 return -1;
377 }
378
379 addr = buf;
380 pastend = buf + buf_size;
381
382 family = *(const uint8_t *) addr;
383 ++addr;
384 type = *(const uint8_t *) addr;
385 ++addr;
386
387 switch (family) {
388 case PIM_MSG_ADDRESS_FAMILY_IPV4:
389 if (type) {
390 char src_str[100];
391 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
392 zlog_warn("%s: unknown unicast address encoding type=%d from %s on %s",
393 __PRETTY_FUNCTION__,
394 type, src_str, ifname);
395 return -2;
396 }
397
398 if ((addr + sizeof(struct in_addr)) > pastend) {
399 char src_str[100];
400 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
401 zlog_warn("%s: IPv4 unicast address overflow: left=%d needed=%d from %s on %s",
402 __PRETTY_FUNCTION__,
403 pastend - addr, sizeof(struct in_addr),
404 src_str, ifname);
405 return -3;
406 }
407
408 p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */
409 p->u.prefix4 = *(const struct in_addr *) addr;
410 addr += sizeof(struct in_addr);
411
412 break;
413 default:
414 {
415 char src_str[100];
416 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
417 zlog_warn("%s: unknown unicast address encoding family=%d from %s on %s",
418 __PRETTY_FUNCTION__,
419 family, src_str, ifname);
420 return -4;
421 }
422 }
423
424 return addr - buf;
425}
426
427int pim_parse_addr_group(const char *ifname, struct in_addr src_addr,
428 struct prefix *p,
429 const char *buf,
430 int buf_size)
431{
432 const int grp_encoding_min_len = 4; /* 1 family + 1 type + 1 reserved + 1 addr */
433 const char *addr;
434 const char *pastend;
435 int family;
436 int type;
437 int mask_len;
438
439 if (buf_size < grp_encoding_min_len) {
440 char src_str[100];
441 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
442 zlog_warn("%s: group address encoding overflow: left=%d needed=%d from %s on %s",
443 __PRETTY_FUNCTION__,
444 buf_size, grp_encoding_min_len,
445 src_str, ifname);
446 return -1;
447 }
448
449 addr = buf;
450 pastend = buf + buf_size;
451
452 family = *(const uint8_t *) addr;
453 ++addr;
454 type = *(const uint8_t *) addr;
455 ++addr;
456 ++addr; /* skip b_reserved_z fields */
457 mask_len = *(const uint8_t *) addr;
458 ++addr;
459
460 switch (family) {
461 case PIM_MSG_ADDRESS_FAMILY_IPV4:
462 if (type) {
463 char src_str[100];
464 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
465 zlog_warn("%s: unknown group address encoding type=%d from %s on %s",
466 __PRETTY_FUNCTION__,
467 type, src_str, ifname);
468 return -2;
469 }
470
471 if ((addr + sizeof(struct in_addr)) > pastend) {
472 char src_str[100];
473 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
474 zlog_warn("%s: IPv4 group address overflow: left=%d needed=%d from %s on %s",
475 __PRETTY_FUNCTION__,
476 pastend - addr, sizeof(struct in_addr),
477 src_str, ifname);
478 return -3;
479 }
480
481 p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */
482 p->u.prefix4 = *(const struct in_addr *) addr;
483 p->prefixlen = mask_len;
484
485 addr += sizeof(struct in_addr);
486
487 break;
488 default:
489 {
490 char src_str[100];
491 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
492 zlog_warn("%s: unknown group address encoding family=%d from %s on %s",
493 __PRETTY_FUNCTION__,
494 family, src_str, ifname);
495 return -4;
496 }
497 }
498
499 return addr - buf;
500}
501
502int pim_parse_addr_source(const char *ifname,
503 struct in_addr src_addr,
504 struct prefix *p,
505 uint8_t *flags,
506 const char *buf,
507 int buf_size)
508{
509 const int src_encoding_min_len = 4; /* 1 family + 1 type + 1 reserved + 1 addr */
510 const char *addr;
511 const char *pastend;
512 int family;
513 int type;
514 int mask_len;
515
516 if (buf_size < src_encoding_min_len) {
517 char src_str[100];
518 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
519 zlog_warn("%s: source address encoding overflow: left=%d needed=%d from %s on %s",
520 __PRETTY_FUNCTION__,
521 buf_size, src_encoding_min_len,
522 src_str, ifname);
523 return -1;
524 }
525
526 addr = buf;
527 pastend = buf + buf_size;
528
529 family = *(const uint8_t *) addr;
530 ++addr;
531 type = *(const uint8_t *) addr;
532 ++addr;
533 *flags = *(const uint8_t *) addr;
534 ++addr;
535 mask_len = *(const uint8_t *) addr;
536 ++addr;
537
538 switch (family) {
539 case PIM_MSG_ADDRESS_FAMILY_IPV4:
540 if (type) {
541 char src_str[100];
542 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
543 zlog_warn("%s: unknown source address encoding type=%d from %s on %s",
544 __PRETTY_FUNCTION__,
545 type, src_str, ifname);
546 return -2;
547 }
548
549 if ((addr + sizeof(struct in_addr)) > pastend) {
550 char src_str[100];
551 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
552 zlog_warn("%s: IPv4 source address overflow: left=%d needed=%d from %s on %s",
553 __PRETTY_FUNCTION__,
554 pastend - addr, sizeof(struct in_addr),
555 src_str, ifname);
556 return -3;
557 }
558
559 p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */
560 p->u.prefix4 = *(const struct in_addr *) addr;
561 p->prefixlen = mask_len;
562
Everton Marquesd12beab2009-08-12 10:52:22 -0300563 /*
564 RFC 4601: 4.9.1 Encoded Source and Group Address Formats
565
566 Encoded-Source Address
567
568 The mask length MUST be equal to the mask length in bits for
569 the given Address Family and Encoding Type (32 for IPv4 native
570 and 128 for IPv6 native). A router SHOULD ignore any messages
571 received with any other mask length.
572 */
573 if (p->prefixlen != 32) {
574 char src_str[100];
575 pim_inet4_dump("<src?>", p->u.prefix4, src_str, sizeof(src_str));
576 zlog_warn("%s: IPv4 bad source address mask: %s/%d",
577 __PRETTY_FUNCTION__, src_str, p->prefixlen);
578 return -4;
579 }
580
Everton Marques871dbcf2009-08-11 15:43:05 -0300581 addr += sizeof(struct in_addr);
582
583 break;
584 default:
585 {
586 char src_str[100];
587 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
588 zlog_warn("%s: unknown source address encoding family=%d from %s on %s",
589 __PRETTY_FUNCTION__,
590 family, src_str, ifname);
Everton Marquesd12beab2009-08-12 10:52:22 -0300591 return -5;
Everton Marques871dbcf2009-08-11 15:43:05 -0300592 }
593 }
594
595 return addr - buf;
596}
597
598#define FREE_ADDR_LIST(hello_option_addr_list) \
599{ \
600 if (hello_option_addr_list) { \
601 list_delete(hello_option_addr_list); \
602 hello_option_addr_list = 0; \
603 } \
604}
605
606int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr,
607 pim_hello_options *hello_options,
608 struct list **hello_option_addr_list,
609 uint16_t option_len,
610 const char *tlv_curr)
611{
612 const char *addr;
613 const char *pastend;
614
615 zassert(hello_option_addr_list);
616
617 /*
618 Scan addr list
619 */
620 addr = tlv_curr;
621 pastend = tlv_curr + option_len;
622 while (addr < pastend) {
623 struct prefix tmp;
624 int addr_offset;
625
626 /*
627 Parse ucast addr
628 */
629 addr_offset = pim_parse_addr_ucast(ifname, src_addr, &tmp,
630 addr, pastend - addr);
631 if (addr_offset < 1) {
632 char src_str[100];
633 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
634 zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s",
635 __PRETTY_FUNCTION__,
636 src_str, ifname);
637 FREE_ADDR_LIST(*hello_option_addr_list);
638 return -1;
639 }
640 addr += addr_offset;
641
642 /*
643 Debug
644 */
645 if (PIM_DEBUG_PIM_TRACE) {
646 switch (tmp.family) {
647 case AF_INET:
648 {
649 char addr_str[100];
650 char src_str[100];
651 pim_inet4_dump("<addr?>", tmp.u.prefix4, addr_str, sizeof(addr_str));
652 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
653 zlog_debug("%s: PIM hello TLV option: list_old_size=%d IPv4 address %s from %s on %s",
654 __PRETTY_FUNCTION__,
655 *hello_option_addr_list ?
656 ((int) listcount(*hello_option_addr_list)) : -1,
657 addr_str, src_str, ifname);
658 }
659 break;
660 default:
661 {
662 char src_str[100];
663 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
664 zlog_debug("%s: PIM hello TLV option: list_old_size=%d UNKNOWN address family from %s on %s",
665 __PRETTY_FUNCTION__,
666 *hello_option_addr_list ?
667 ((int) listcount(*hello_option_addr_list)) : -1,
668 src_str, ifname);
669 }
670 }
671 }
672
673 /*
674 Exclude neighbor's primary address if incorrectly included in
675 the secondary address list
676 */
677 if (tmp.family == AF_INET) {
678 if (tmp.u.prefix4.s_addr == src_addr.s_addr) {
679 char src_str[100];
680 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
681 zlog_warn("%s: ignoring primary address in secondary list from %s on %s",
682 __PRETTY_FUNCTION__,
683 src_str, ifname);
684 continue;
685 }
686 }
687
688 /*
689 Allocate list if needed
690 */
691 if (!*hello_option_addr_list) {
692 *hello_option_addr_list = list_new();
693 if (!*hello_option_addr_list) {
694 zlog_err("%s %s: failure: hello_option_addr_list=list_new()",
695 __FILE__, __PRETTY_FUNCTION__);
696 return -2;
697 }
698 (*hello_option_addr_list)->del = (void (*)(void *)) prefix_free;
699 }
700
701 /*
702 Attach addr to list
703 */
704 {
705 struct prefix *p;
706 p = prefix_new();
707 if (!p) {
708 zlog_err("%s %s: failure: prefix_new()",
709 __FILE__, __PRETTY_FUNCTION__);
710 FREE_ADDR_LIST(*hello_option_addr_list);
711 return -3;
712 }
713 p->family = tmp.family;
714 p->u.prefix4 = tmp.u.prefix4;
715 listnode_add(*hello_option_addr_list, p);
716 }
717
718 } /* while (addr < pastend) */
719
720 /*
721 Mark hello option
722 */
723 PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_ADDRESS_LIST);
724
725 return 0;
726}