diff options
Diffstat (limited to 'pimd/pim_tlv.c')
| -rw-r--r-- | pimd/pim_tlv.c | 228 |
1 files changed, 118 insertions, 110 deletions
diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c index a4f60e5198..86403dd54a 100644 --- a/pimd/pim_tlv.c +++ b/pimd/pim_tlv.c @@ -29,6 +29,12 @@ #include "pim_str.h" #include "pim_msg.h" +#if PIM_IPV == 4 +#define PIM_MSG_ADDRESS_FAMILY PIM_MSG_ADDRESS_FAMILY_IPV4 +#else +#define PIM_MSG_ADDRESS_FAMILY PIM_MSG_ADDRESS_FAMILY_IPV6 +#endif + uint8_t *pim_tlv_append_uint16(uint8_t *buf, const uint8_t *buf_pastend, uint16_t option_type, uint16_t option_value) { @@ -117,7 +123,23 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf, const uint8_t *buf_pastend, * The unicast address as represented by the given Address Family * and Encoding Type. */ -int pim_encode_addr_ucast(uint8_t *buf, struct prefix *p) +int pim_encode_addr_ucast(uint8_t *buf, pim_addr addr) +{ + uint8_t *start = buf; + +#if PIM_IPV == 4 + *buf++ = PIM_MSG_ADDRESS_FAMILY_IPV4; +#else + *buf++ = PIM_MSG_ADDRESS_FAMILY_IPV6; +#endif + *buf++ = 0; + memcpy(buf, &addr, sizeof(addr)); + buf += sizeof(addr); + + return buf - start; +} + +int pim_encode_addr_ucast_prefix(uint8_t *buf, struct prefix *p) { switch (p->family) { case AF_INET: @@ -188,28 +210,22 @@ int pim_encode_addr_ucast(uint8_t *buf, struct prefix *p) * Contains the group address. */ int pim_encode_addr_group(uint8_t *buf, afi_t afi, int bidir, int scope, - struct in_addr group) + pim_addr group) { + uint8_t *start = buf; uint8_t flags = 0; flags |= bidir << 8; flags |= scope; - switch (afi) { - case AFI_IP: - *buf = PIM_MSG_ADDRESS_FAMILY_IPV4; - ++buf; - *buf = 0; - ++buf; - *buf = flags; - ++buf; - *buf = 32; - ++buf; - memcpy(buf, &group, sizeof(struct in_addr)); - return group_ipv4_encoding_len; - default: - return 0; - } + *buf++ = PIM_MSG_ADDRESS_FAMILY; + *buf++ = 0; + *buf++ = flags; + *buf++ = sizeof(group) / 8; + memcpy(buf, &group, sizeof(group)); + buf += sizeof(group); + + return buf - start; } uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend, @@ -248,7 +264,7 @@ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend, if (p->family != family) continue; - l_encode = pim_encode_addr_ucast(curr, p); + l_encode = pim_encode_addr_ucast_prefix(curr, p); curr += l_encode; option_len += l_encode; } @@ -274,15 +290,13 @@ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend, } static int check_tlv_length(const char *label, const char *tlv_name, - const char *ifname, struct in_addr src_addr, + const char *ifname, pim_addr src_addr, int correct_len, int option_len) { if (option_len != correct_len) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); zlog_warn( - "%s: PIM hello %s TLV with incorrect value size=%d correct=%d from %s on interface %s", - label, tlv_name, option_len, correct_len, src_str, + "%s: PIM hello %s TLV with incorrect value size=%d correct=%d from %pPAs on interface %s", + label, tlv_name, option_len, correct_len, &src_addr, ifname); return -1; } @@ -290,49 +304,44 @@ static int check_tlv_length(const char *label, const char *tlv_name, return 0; } -static void check_tlv_redefinition_uint16( - const char *label, const char *tlv_name, const char *ifname, - struct in_addr src_addr, pim_hello_options options, - pim_hello_options opt_mask, uint16_t new, uint16_t old) +static void check_tlv_redefinition_uint16(const char *label, + const char *tlv_name, + const char *ifname, pim_addr src_addr, + pim_hello_options options, + pim_hello_options opt_mask, + uint16_t new, uint16_t old) { - if (PIM_OPTION_IS_SET(options, opt_mask)) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); + if (PIM_OPTION_IS_SET(options, opt_mask)) zlog_warn( - "%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s", - label, tlv_name, new, old, src_str, ifname); - } + "%s: PIM hello TLV redefined %s=%u old=%u from %pPAs on interface %s", + label, tlv_name, new, old, &src_addr, ifname); } -static void check_tlv_redefinition_uint32( - const char *label, const char *tlv_name, const char *ifname, - struct in_addr src_addr, pim_hello_options options, - pim_hello_options opt_mask, uint32_t new, uint32_t old) +static void check_tlv_redefinition_uint32(const char *label, + const char *tlv_name, + const char *ifname, pim_addr src_addr, + pim_hello_options options, + pim_hello_options opt_mask, + uint32_t new, uint32_t old) { - if (PIM_OPTION_IS_SET(options, opt_mask)) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); + if (PIM_OPTION_IS_SET(options, opt_mask)) zlog_warn( - "%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s", - label, tlv_name, new, old, src_str, ifname); - } + "%s: PIM hello TLV redefined %s=%u old=%u from %pPAs on interface %s", + label, tlv_name, new, old, &src_addr, ifname); } static void check_tlv_redefinition_uint32_hex( const char *label, const char *tlv_name, const char *ifname, - struct in_addr src_addr, pim_hello_options options, + pim_addr src_addr, pim_hello_options options, pim_hello_options opt_mask, uint32_t new, uint32_t old) { - if (PIM_OPTION_IS_SET(options, opt_mask)) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str)); + if (PIM_OPTION_IS_SET(options, opt_mask)) zlog_warn( - "%s: PIM hello TLV redefined %s=%08x old=%08x from %s on interface %s", - label, tlv_name, new, old, src_str, ifname); - } + "%s: PIM hello TLV redefined %s=%08x old=%08x from %pPAs on interface %s", + label, tlv_name, new, old, &src_addr, ifname); } -int pim_tlv_parse_holdtime(const char *ifname, struct in_addr src_addr, +int pim_tlv_parse_holdtime(const char *ifname, pim_addr src_addr, pim_hello_options *hello_options, uint16_t *hello_option_holdtime, uint16_t option_len, const uint8_t *tlv_curr) @@ -356,7 +365,7 @@ int pim_tlv_parse_holdtime(const char *ifname, struct in_addr src_addr, return 0; } -int pim_tlv_parse_lan_prune_delay(const char *ifname, struct in_addr src_addr, +int pim_tlv_parse_lan_prune_delay(const char *ifname, pim_addr src_addr, pim_hello_options *hello_options, uint16_t *hello_option_propagation_delay, uint16_t *hello_option_override_interval, @@ -392,7 +401,7 @@ int pim_tlv_parse_lan_prune_delay(const char *ifname, struct in_addr src_addr, return 0; } -int pim_tlv_parse_dr_priority(const char *ifname, struct in_addr src_addr, +int pim_tlv_parse_dr_priority(const char *ifname, pim_addr src_addr, pim_hello_options *hello_options, uint32_t *hello_option_dr_priority, uint16_t option_len, const uint8_t *tlv_curr) @@ -416,7 +425,7 @@ int pim_tlv_parse_dr_priority(const char *ifname, struct in_addr src_addr, return 0; } -int pim_tlv_parse_generation_id(const char *ifname, struct in_addr src_addr, +int pim_tlv_parse_generation_id(const char *ifname, pim_addr src_addr, pim_hello_options *hello_options, uint32_t *hello_option_generation_id, uint16_t option_len, const uint8_t *tlv_curr) @@ -441,7 +450,8 @@ int pim_tlv_parse_generation_id(const char *ifname, struct in_addr src_addr, return 0; } -int pim_parse_addr_ucast(struct prefix *p, const uint8_t *buf, int buf_size) +int pim_parse_addr_ucast_prefix(struct prefix *p, const uint8_t *buf, + int buf_size) { const int ucast_encoding_min_len = 3; /* 1 family + 1 type + 1 addr */ const uint8_t *addr; @@ -510,6 +520,25 @@ int pim_parse_addr_ucast(struct prefix *p, const uint8_t *buf, int buf_size) return addr - buf; } +int pim_parse_addr_ucast(pim_addr *out, const uint8_t *buf, int buf_size, + bool *wrong_af) +{ + struct prefix p; + int ret; + + ret = pim_parse_addr_ucast_prefix(&p, buf, buf_size); + if (ret < 0) + return ret; + + if (p.family != PIM_AF) { + *wrong_af = true; + return -5; + } + + memcpy(out, &p.u.val, sizeof(*out)); + return ret; +} + int pim_parse_addr_group(pim_sgaddr *sg, const uint8_t *buf, int buf_size) { const int grp_encoding_min_len = @@ -532,40 +561,32 @@ int pim_parse_addr_group(pim_sgaddr *sg, const uint8_t *buf, int buf_size) family = *addr++; type = *addr++; - //++addr; ++addr; /* skip b_reserved_z fields */ mask_len = *addr++; - switch (family) { - case PIM_MSG_ADDRESS_FAMILY_IPV4: - if (type) { - zlog_warn( - "%s: unknown group address encoding type=%d from", - __func__, type); - return -2; - } - - if ((addr + sizeof(struct in_addr)) > pastend) { - zlog_warn( - "%s: IPv4 group address overflow: left=%td needed=%zu from", - __func__, pastend - addr, - sizeof(struct in_addr)); - return -3; - } - - memcpy(&sg->grp.s_addr, addr, sizeof(struct in_addr)); - - addr += sizeof(struct in_addr); + if (type) { + zlog_warn("%s: unknown group address encoding type=%d from", + __func__, type); + return -2; + } - break; - default: { + if (family != PIM_MSG_ADDRESS_FAMILY) { zlog_warn( "%s: unknown group address encoding family=%d mask_len=%d from", __func__, family, mask_len); return -4; } + + if ((addr + sizeof(sg->grp)) > pastend) { + zlog_warn( + "%s: group address overflow: left=%td needed=%zu from", + __func__, pastend - addr, sizeof(sg->grp)); + return -3; } + memcpy(&sg->grp, addr, sizeof(sg->grp)); + addr += sizeof(sg->grp); + return addr - buf; } @@ -654,7 +675,7 @@ int pim_parse_addr_source(pim_sgaddr *sg, uint8_t *flags, const uint8_t *buf, } \ } -int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, +int pim_tlv_parse_addr_list(const char *ifname, pim_addr src_addr, pim_hello_options *hello_options, struct list **hello_option_addr_list, uint16_t option_len, const uint8_t *tlv_curr) @@ -670,20 +691,18 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, addr = tlv_curr; pastend = tlv_curr + option_len; while (addr < pastend) { - struct prefix tmp; + struct prefix tmp, src_pfx; int addr_offset; /* Parse ucast addr */ - addr_offset = pim_parse_addr_ucast(&tmp, addr, pastend - addr); + addr_offset = + pim_parse_addr_ucast_prefix(&tmp, addr, pastend - addr); if (addr_offset < 1) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, - sizeof(src_str)); zlog_warn( - "%s: pim_parse_addr_ucast() failure: from %s on %s", - __func__, src_str, ifname); + "%s: pim_parse_addr_ucast() failure: from %pPAs on %s", + __func__, &src_addr, ifname); FREE_ADDR_LIST(*hello_option_addr_list); return -1; } @@ -696,35 +715,28 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, switch (tmp.family) { case AF_INET: { char addr_str[INET_ADDRSTRLEN]; - char src_str[INET_ADDRSTRLEN]; pim_inet4_dump("<addr?>", tmp.u.prefix4, addr_str, sizeof(addr_str)); - pim_inet4_dump("<src?>", src_addr, src_str, - sizeof(src_str)); zlog_debug( - "%s: PIM hello TLV option: list_old_size=%d IPv4 address %s from %s on %s", + "%s: PIM hello TLV option: list_old_size=%d IPv4 address %s from %pPAs on %s", __func__, *hello_option_addr_list ? ((int)listcount( - *hello_option_addr_list)) + *hello_option_addr_list)) : -1, - addr_str, src_str, ifname); + addr_str, &src_addr, ifname); } break; case AF_INET6: break; - default: { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, - sizeof(src_str)); + default: zlog_debug( - "%s: PIM hello TLV option: list_old_size=%d UNKNOWN address family from %s on %s", + "%s: PIM hello TLV option: list_old_size=%d UNKNOWN address family from %pPAs on %s", __func__, *hello_option_addr_list ? ((int)listcount( - *hello_option_addr_list)) + *hello_option_addr_list)) : -1, - src_str, ifname); - } + &src_addr, ifname); } } @@ -732,16 +744,12 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, Exclude neighbor's primary address if incorrectly included in the secondary address list */ - if (tmp.family == AF_INET) { - if (tmp.u.prefix4.s_addr == src_addr.s_addr) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", src_addr, src_str, - sizeof(src_str)); - zlog_warn( - "%s: ignoring primary address in secondary list from %s on %s", - __func__, src_str, ifname); - continue; - } + pim_addr_to_prefix(&src_pfx, src_addr); + if (!prefix_cmp(&tmp, &src_pfx)) { + zlog_warn( + "%s: ignoring primary address in secondary list from %pPAs on %s", + __func__, &src_addr, ifname); + continue; } /* |
