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 $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" 29#include "pim_int.h" 30#include "pim_tlv.h" 31#include "pim_str.h" 32#include "pim_msg.h" 33 34uint8_t *pim_tlv_append_uint16(uint8_t *buf, 35 const uint8_t *buf_pastend, 36 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=%zd 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 58uint8_t *pim_tlv_append_2uint16(uint8_t *buf, 59 const uint8_t *buf_pastend, 60 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=%zd 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 85uint8_t *pim_tlv_append_uint32(uint8_t *buf, 86 const uint8_t *buf_pastend, 87 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=%zd 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; 103 pim_write_uint32(buf, option_value); 104 buf += option_len; 105 106 return buf; 107} 108 109#define ucast_ipv4_encoding_len (2 + sizeof(struct in_addr)) 110 111uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, 112 const uint8_t *buf_pastend, 113 struct list *ifconnected) 114{ 115 struct listnode *node; 116 uint16_t option_len = 0; 117 118 uint8_t *curr; 119 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=%zd needed=%zu", 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 memcpy(curr, &p->u.prefix4, sizeof(struct in_addr)); 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: %zu", 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 uint8_t *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 uint8_t *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 uint8_t *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); 327 328 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 uint8_t *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 uint8_t *buf, 361 int buf_size) 362{ 363 const int ucast_encoding_min_len = 3; /* 1 family + 1 type + 1 addr */ 364 const uint8_t *addr; 365 const uint8_t *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 = *addr++; 383 type = *addr++; 384 385 switch (family) { 386 case PIM_MSG_ADDRESS_FAMILY_IPV4: 387 if (type) { 388 char src_str[100]; 389 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); 390 zlog_warn("%s: unknown unicast address encoding type=%d from %s on %s", 391 __PRETTY_FUNCTION__, 392 type, src_str, ifname); 393 return -2; 394 } 395 396 if ((addr + sizeof(struct in_addr)) > pastend) { 397 char src_str[100]; 398 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); 399 zlog_warn("%s: IPv4 unicast address overflow: left=%zd needed=%zu from %s on %s", 400 __PRETTY_FUNCTION__, 401 pastend - addr, sizeof(struct in_addr), 402 src_str, ifname); 403 return -3; 404 } 405 406 p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */ 407 memcpy(&p->u.prefix4, addr, sizeof(struct in_addr)); 408 409 addr += sizeof(struct in_addr); 410 411 break; 412 default: 413 { 414 char src_str[100]; 415 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); 416 zlog_warn("%s: unknown unicast address encoding family=%d from %s on %s", 417 __PRETTY_FUNCTION__, 418 family, src_str, ifname); 419 return -4; 420 } 421 } 422 423 return addr - buf; 424} 425 426int pim_parse_addr_group(const char *ifname, struct in_addr src_addr, 427 struct prefix *p, 428 const uint8_t *buf, 429 int buf_size) 430{ 431 const int grp_encoding_min_len = 4; /* 1 family + 1 type + 1 reserved + 1 addr */ 432 const uint8_t *addr; 433 const uint8_t *pastend; 434 int family; 435 int type; 436 int mask_len; 437 438 if (buf_size < grp_encoding_min_len) { 439 char src_str[100]; 440 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); 441 zlog_warn("%s: group address encoding overflow: left=%d needed=%d from %s on %s", 442 __PRETTY_FUNCTION__, 443 buf_size, grp_encoding_min_len, 444 src_str, ifname); 445 return -1; 446 } 447 448 addr = buf; 449 pastend = buf + buf_size; 450 451 family = *addr++; 452 type = *addr++; 453 //++addr; 454 ++addr; /* skip b_reserved_z fields */ 455 mask_len = *addr++; 456 457 switch (family) { 458 case PIM_MSG_ADDRESS_FAMILY_IPV4: 459 if (type) { 460 char src_str[100]; 461 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); 462 zlog_warn("%s: unknown group address encoding type=%d from %s on %s", 463 __PRETTY_FUNCTION__, 464 type, src_str, ifname); 465 return -2; 466 } 467 468 if ((addr + sizeof(struct in_addr)) > pastend) { 469 char src_str[100]; 470 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); 471 zlog_warn("%s: IPv4 group address overflow: left=%zd needed=%zu from %s on %s", 472 __PRETTY_FUNCTION__, 473 pastend - addr, sizeof(struct in_addr), 474 src_str, ifname); 475 return -3; 476 } 477 478 p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */ 479 memcpy(&p->u.prefix4, addr, sizeof(struct in_addr)); 480 p->prefixlen = mask_len; 481 482 addr += sizeof(struct in_addr); 483 484 break; 485 default: 486 { 487 char src_str[100]; 488 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); 489 zlog_warn("%s: unknown group address encoding family=%d from %s on %s", 490 __PRETTY_FUNCTION__, 491 family, src_str, ifname); 492 return -4; 493 } 494 } 495 496 return addr - buf; 497} 498 499int pim_parse_addr_source(const char *ifname, 500 struct in_addr src_addr, 501 struct prefix *p, 502 uint8_t *flags, 503 const uint8_t *buf, 504 int buf_size) 505{ 506 const int src_encoding_min_len = 4; /* 1 family + 1 type + 1 reserved + 1 addr */ 507 const uint8_t *addr; 508 const uint8_t *pastend; 509 int family; 510 int type; 511 int mask_len; 512 513 if (buf_size < src_encoding_min_len) { 514 char src_str[100]; 515 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); 516 zlog_warn("%s: source address encoding overflow: left=%d needed=%d from %s on %s", 517 __PRETTY_FUNCTION__, 518 buf_size, src_encoding_min_len, 519 src_str, ifname); 520 return -1; 521 } 522 523 addr = buf; 524 pastend = buf + buf_size; 525 526 family = *addr++; 527 type = *addr++; 528 *flags = *addr++; 529 mask_len = *addr++; 530 531 switch (family) { 532 case PIM_MSG_ADDRESS_FAMILY_IPV4: 533 if (type) { 534 char src_str[100]; 535 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); 536 zlog_warn("%s: unknown source address encoding type=%d from %s on %s: %02x%02x%02x%02x%02x%02x%02x%02x", 537 __PRETTY_FUNCTION__, 538 type, src_str, ifname, 539 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); 540 return -2; 541 } 542 543 if ((addr + sizeof(struct in_addr)) > pastend) { 544 char src_str[100]; 545 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); 546 zlog_warn("%s: IPv4 source address overflow: left=%zd needed=%zu from %s on %s", 547 __PRETTY_FUNCTION__, 548 pastend - addr, sizeof(struct in_addr), 549 src_str, ifname); 550 return -3; 551 } 552 553 p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */ 554 memcpy(&p->u.prefix4, addr, sizeof(struct in_addr)); 555 p->prefixlen = mask_len; 556 557 /* 558 RFC 4601: 4.9.1 Encoded Source and Group Address Formats 559 560 Encoded-Source Address 561 562 The mask length MUST be equal to the mask length in bits for 563 the given Address Family and Encoding Type (32 for IPv4 native 564 and 128 for IPv6 native). A router SHOULD ignore any messages 565 received with any other mask length. 566 */ 567 if (p->prefixlen != 32) { 568 char src_str[100]; 569 pim_inet4_dump("<src?>", p->u.prefix4, src_str, sizeof(src_str)); 570 zlog_warn("%s: IPv4 bad source address mask: %s/%d", 571 __PRETTY_FUNCTION__, src_str, p->prefixlen); 572 return -4; 573 } 574 575 addr += sizeof(struct in_addr); 576 577 break; 578 default: 579 { 580 char src_str[100]; 581 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); 582 zlog_warn("%s: unknown source address encoding family=%d from %s on %s: %02x%02x%02x%02x%02x%02x%02x%02x", 583 __PRETTY_FUNCTION__, 584 family, src_str, ifname, 585 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); 586 return -5; 587 } 588 } 589 590 return addr - buf; 591} 592 593#define FREE_ADDR_LIST(hello_option_addr_list) \ 594{ \ 595 if (hello_option_addr_list) { \ 596 list_delete(hello_option_addr_list); \ 597 hello_option_addr_list = 0; \ 598 } \ 599} 600 601int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, 602 pim_hello_options *hello_options, 603 struct list **hello_option_addr_list, 604 uint16_t option_len, 605 const uint8_t *tlv_curr) 606{ 607 const uint8_t *addr; 608 const uint8_t *pastend; 609 610 zassert(hello_option_addr_list); 611 612 /* 613 Scan addr list 614 */ 615 addr = tlv_curr; 616 pastend = tlv_curr + option_len; 617 while (addr < pastend) { 618 struct prefix tmp; 619 int addr_offset; 620 621 /* 622 Parse ucast addr 623 */ 624 addr_offset = pim_parse_addr_ucast(ifname, src_addr, &tmp, 625 addr, pastend - addr); 626 if (addr_offset < 1) { 627 char src_str[100]; 628 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); 629 zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s", 630 __PRETTY_FUNCTION__, 631 src_str, ifname); 632 FREE_ADDR_LIST(*hello_option_addr_list); 633 return -1; 634 } 635 addr += addr_offset; 636 637 /* 638 Debug 639 */ 640 if (PIM_DEBUG_PIM_TRACE) { 641 switch (tmp.family) { 642 case AF_INET: 643 { 644 char addr_str[100]; 645 char src_str[100]; 646 pim_inet4_dump("<addr?>", tmp.u.prefix4, addr_str, sizeof(addr_str)); 647 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); 648 zlog_debug("%s: PIM hello TLV option: list_old_size=%d IPv4 address %s from %s on %s", 649 __PRETTY_FUNCTION__, 650 *hello_option_addr_list ? 651 ((int) listcount(*hello_option_addr_list)) : -1, 652 addr_str, src_str, ifname); 653 } 654 break; 655 default: 656 { 657 char src_str[100]; 658 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); 659 zlog_debug("%s: PIM hello TLV option: list_old_size=%d UNKNOWN address family from %s on %s", 660 __PRETTY_FUNCTION__, 661 *hello_option_addr_list ? 662 ((int) listcount(*hello_option_addr_list)) : -1, 663 src_str, ifname); 664 } 665 } 666 } 667 668 /* 669 Exclude neighbor's primary address if incorrectly included in 670 the secondary address list 671 */ 672 if (tmp.family == AF_INET) { 673 if (tmp.u.prefix4.s_addr == src_addr.s_addr) { 674 char src_str[100]; 675 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); 676 zlog_warn("%s: ignoring primary address in secondary list from %s on %s", 677 __PRETTY_FUNCTION__, 678 src_str, ifname); 679 continue; 680 } 681 } 682 683 /* 684 Allocate list if needed 685 */ 686 if (!*hello_option_addr_list) { 687 *hello_option_addr_list = list_new(); 688 if (!*hello_option_addr_list) { 689 zlog_err("%s %s: failure: hello_option_addr_list=list_new()", 690 __FILE__, __PRETTY_FUNCTION__); 691 return -2; 692 } 693 (*hello_option_addr_list)->del = (void (*)(void *)) prefix_free; 694 } 695 696 /* 697 Attach addr to list 698 */ 699 { 700 struct prefix *p; 701 p = prefix_new(); 702 if (!p) { 703 zlog_err("%s %s: failure: prefix_new()", 704 __FILE__, __PRETTY_FUNCTION__); 705 FREE_ADDR_LIST(*hello_option_addr_list); 706 return -3; 707 } 708 p->family = tmp.family; 709 p->u.prefix4 = tmp.u.prefix4; 710 listnode_add(*hello_option_addr_list, p); 711 } 712 713 } /* while (addr < pastend) */ 714 715 /* 716 Mark hello option 717 */ 718 PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_ADDRESS_LIST); 719 720 return 0; 721} 722