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