/*
- PIM for Quagga
- Copyright (C) 2008 Everton da Silva Marques
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING; if not, write to the
- Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- MA 02110-1301 USA
-*/
+ * PIM for Quagga
+ * Copyright (C) 2008 Everton da Silva Marques
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
#include <zebra.h>
#include "pim_str.h"
#include "pim_msg.h"
-uint8_t *pim_tlv_append_uint16(uint8_t *buf,
- const uint8_t *buf_pastend,
- uint16_t option_type,
- uint16_t option_value)
+uint8_t *pim_tlv_append_uint16(uint8_t *buf, const uint8_t *buf_pastend,
+ uint16_t option_type, uint16_t option_value)
{
- uint16_t option_len = 2;
+ uint16_t option_len = 2;
- if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend)
- return NULL;
+ if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend)
+ return NULL;
- *(uint16_t *) buf = htons(option_type);
- buf += 2;
- *(uint16_t *) buf = htons(option_len);
- buf += 2;
- *(uint16_t *) buf = htons(option_value);
- buf += option_len;
+ *(uint16_t *)buf = htons(option_type);
+ buf += 2;
+ *(uint16_t *)buf = htons(option_len);
+ buf += 2;
+ *(uint16_t *)buf = htons(option_value);
+ buf += option_len;
- return buf;
+ return buf;
}
-uint8_t *pim_tlv_append_2uint16(uint8_t *buf,
- const uint8_t *buf_pastend,
- uint16_t option_type,
- uint16_t option_value1,
+uint8_t *pim_tlv_append_2uint16(uint8_t *buf, const uint8_t *buf_pastend,
+ uint16_t option_type, uint16_t option_value1,
uint16_t option_value2)
{
- uint16_t option_len = 4;
+ uint16_t option_len = 4;
- if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend)
- return NULL;
+ if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend)
+ return NULL;
- *(uint16_t *) buf = htons(option_type);
- buf += 2;
- *(uint16_t *) buf = htons(option_len);
- buf += 2;
- *(uint16_t *) buf = htons(option_value1);
- buf += 2;
- *(uint16_t *) buf = htons(option_value2);
- buf += 2;
+ *(uint16_t *)buf = htons(option_type);
+ buf += 2;
+ *(uint16_t *)buf = htons(option_len);
+ buf += 2;
+ *(uint16_t *)buf = htons(option_value1);
+ buf += 2;
+ *(uint16_t *)buf = htons(option_value2);
+ buf += 2;
- return buf;
+ return buf;
}
-uint8_t *pim_tlv_append_uint32(uint8_t *buf,
- const uint8_t *buf_pastend,
- uint16_t option_type,
- uint32_t option_value)
+uint8_t *pim_tlv_append_uint32(uint8_t *buf, const uint8_t *buf_pastend,
+ uint16_t option_type, uint32_t option_value)
{
- uint16_t option_len = 4;
+ uint16_t option_len = 4;
- if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend)
- return NULL;
+ if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend)
+ return NULL;
- *(uint16_t *) buf = htons(option_type);
- buf += 2;
- *(uint16_t *) buf = htons(option_len);
- buf += 2;
- pim_write_uint32(buf, option_value);
- buf += option_len;
+ *(uint16_t *)buf = htons(option_type);
+ buf += 2;
+ *(uint16_t *)buf = htons(option_len);
+ buf += 2;
+ pim_write_uint32(buf, option_value);
+ buf += option_len;
- return buf;
+ return buf;
}
#define ucast_ipv4_encoding_len (2 + sizeof(struct in_addr))
* The PIM address family of the 'Unicast Address' field of this
* address.
*
- * Values 0-127 are as assigned by the IANA for Internet Address * Families in [7]. Values 128-250 are reserved to be assigned by
+ * Values 0-127 are as assigned by the IANA for Internet Address *
+ * Families in [7]. Values 128-250 are reserved to be assigned by
* the IANA for PIM-specific Address Families. Values 251 though
* 255 are designated for private use. As there is no assignment
* authority for this space, collisions should be expected.
* 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, struct prefix *p)
{
- switch (p->family)
- {
- case AF_INET:
- *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV4; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */
- ++buf;
- *(uint8_t *)buf = 0; /* ucast IPv4 native encoding type (RFC 4601: 4.9.1) */
- ++buf;
- memcpy (buf, &p->u.prefix4, sizeof (struct in_addr));
- return ucast_ipv4_encoding_len;
- break;
- case AF_INET6:
- *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV6;
- ++buf;
- *(uint8_t *)buf = 0;
- ++buf;
- memcpy (buf, &p->u.prefix6, sizeof (struct in6_addr));
- return ucast_ipv6_encoding_len;
- break;
- default:
- return 0;
- break;
- }
+ switch (p->family) {
+ case AF_INET:
+ *(uint8_t *)buf =
+ PIM_MSG_ADDRESS_FAMILY_IPV4; /* notice: AF_INET !=
+ PIM_MSG_ADDRESS_FAMILY_IPV4
+ */
+ ++buf;
+ *(uint8_t *)buf = 0; /* ucast IPv4 native encoding type (RFC
+ 4601: 4.9.1) */
+ ++buf;
+ memcpy(buf, &p->u.prefix4, sizeof(struct in_addr));
+ return ucast_ipv4_encoding_len;
+ break;
+ case AF_INET6:
+ *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV6;
+ ++buf;
+ *(uint8_t *)buf = 0;
+ ++buf;
+ memcpy(buf, &p->u.prefix6, sizeof(struct in6_addr));
+ return ucast_ipv6_encoding_len;
+ break;
+ default:
+ return 0;
+ break;
+ }
}
#define group_ipv4_encoding_len (4 + sizeof (struct in_addr))
* Group multicast Address
* Contains the group address.
*/
-int
-pim_encode_addr_group (uint8_t *buf, afi_t afi, int bidir, int scope, struct in_addr group)
+int pim_encode_addr_group(uint8_t *buf, afi_t afi, int bidir, int scope,
+ struct in_addr group)
{
- uint8_t flags = 0;
-
- flags |= bidir << 8;
- flags |= scope;
-
- switch (afi)
- {
- case AFI_IP:
- *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV4;
- ++buf;
- *(uint8_t *)buf = 0;
- ++buf;
- *(uint8_t *)buf = flags;
- ++buf;
- *(uint8_t *)buf = 32;
- ++buf;
- memcpy (buf, &group, sizeof (struct in_addr));
- return group_ipv4_encoding_len;
- break;
- default:
- return 0;
- break;
- }
+ uint8_t flags = 0;
+
+ flags |= bidir << 8;
+ flags |= scope;
+
+ switch (afi) {
+ case AFI_IP:
+ *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV4;
+ ++buf;
+ *(uint8_t *)buf = 0;
+ ++buf;
+ *(uint8_t *)buf = flags;
+ ++buf;
+ *(uint8_t *)buf = 32;
+ ++buf;
+ memcpy(buf, &group, sizeof(struct in_addr));
+ return group_ipv4_encoding_len;
+ break;
+ default:
+ return 0;
+ break;
+ }
}
-uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf,
- const uint8_t *buf_pastend,
- struct list *ifconnected,
- int family)
+uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend,
+ struct list *ifconnected, int family)
{
- struct listnode *node;
- uint16_t option_len = 0;
- uint8_t *curr;
- size_t uel;
-
- node = listhead(ifconnected);
-
- /* Empty address list ? */
- if (!node) {
- return buf;
- }
-
- if (family == AF_INET)
- uel = ucast_ipv4_encoding_len;
- else
- uel = ucast_ipv6_encoding_len;
-
- /* Scan secondary address list */
- curr = buf + 4; /* skip T and L */
- for (; node; node = listnextnode(node)) {
- struct connected *ifc = listgetdata(node);
- struct prefix *p = ifc->address;
- int l_encode;
-
- if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
- continue;
-
- if ((curr + uel) > buf_pastend)
- return 0;
-
- if (p->family != family)
- continue;
-
- l_encode = pim_encode_addr_ucast (curr, p);
- curr += l_encode;
- option_len += l_encode;
- }
-
- if (PIM_DEBUG_PIM_TRACE_DETAIL) {
- zlog_debug("%s: number of encoded secondary unicast IPv4 addresses: %zu",
- __PRETTY_FUNCTION__,
- option_len / uel);
- }
-
- if (option_len < 1) {
- /* Empty secondary unicast IPv4 address list */
- return buf;
- }
-
- /*
- * Write T and L
- */
- *(uint16_t *) buf = htons(PIM_MSG_OPTION_TYPE_ADDRESS_LIST);
- *(uint16_t *) (buf + 2) = htons(option_len);
-
- return curr;
+ struct listnode *node;
+ uint16_t option_len = 0;
+ uint8_t *curr;
+ size_t uel;
+
+ node = listhead(ifconnected);
+
+ /* Empty address list ? */
+ if (!node) {
+ return buf;
+ }
+
+ if (family == AF_INET)
+ uel = ucast_ipv4_encoding_len;
+ else
+ uel = ucast_ipv6_encoding_len;
+
+ /* Scan secondary address list */
+ curr = buf + 4; /* skip T and L */
+ for (; node; node = listnextnode(node)) {
+ struct connected *ifc = listgetdata(node);
+ struct prefix *p = ifc->address;
+ int l_encode;
+
+ if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
+ continue;
+
+ if ((curr + uel) > buf_pastend)
+ return 0;
+
+ if (p->family != family)
+ continue;
+
+ l_encode = pim_encode_addr_ucast(curr, p);
+ curr += l_encode;
+ option_len += l_encode;
+ }
+
+ if (PIM_DEBUG_PIM_TRACE_DETAIL) {
+ zlog_debug(
+ "%s: number of encoded secondary unicast IPv4 addresses: %zu",
+ __PRETTY_FUNCTION__, option_len / uel);
+ }
+
+ if (option_len < 1) {
+ /* Empty secondary unicast IPv4 address list */
+ return buf;
+ }
+
+ /*
+ * Write T and L
+ */
+ *(uint16_t *)buf = htons(PIM_MSG_OPTION_TYPE_ADDRESS_LIST);
+ *(uint16_t *)(buf + 2) = htons(option_len);
+
+ return curr;
}
static int check_tlv_length(const char *label, const char *tlv_name,
const char *ifname, struct in_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, ifname);
- return -1;
- }
-
- return 0;
+ 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,
+ ifname);
+ return -1;
+ }
+
+ 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,
+ struct in_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));
- zlog_warn("%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s",
- label, tlv_name,
- new, old,
- src_str, ifname);
- }
+ if (PIM_OPTION_IS_SET(options, opt_mask)) {
+ char src_str[INET_ADDRSTRLEN];
+ pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
+ zlog_warn(
+ "%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s",
+ label, tlv_name, new, old, src_str, 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,
+ struct in_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));
- zlog_warn("%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s",
- label, tlv_name,
- new, old,
- src_str, ifname);
- }
+ if (PIM_OPTION_IS_SET(options, opt_mask)) {
+ char src_str[INET_ADDRSTRLEN];
+ pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
+ zlog_warn(
+ "%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s",
+ label, tlv_name, new, old, src_str, 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_hello_options opt_mask,
- uint32_t new, uint32_t old)
+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_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));
- zlog_warn("%s: PIM hello TLV redefined %s=%08x old=%08x from %s on interface %s",
- label, tlv_name,
- new, old,
- src_str, ifname);
- }
+ if (PIM_OPTION_IS_SET(options, opt_mask)) {
+ char src_str[INET_ADDRSTRLEN];
+ pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
+ zlog_warn(
+ "%s: PIM hello TLV redefined %s=%08x old=%08x from %s on interface %s",
+ label, tlv_name, new, old, src_str, ifname);
+ }
}
int pim_tlv_parse_holdtime(const char *ifname, struct in_addr src_addr,
pim_hello_options *hello_options,
- uint16_t *hello_option_holdtime,
- uint16_t option_len,
- const uint8_t *tlv_curr)
+ uint16_t *hello_option_holdtime, uint16_t option_len,
+ const uint8_t *tlv_curr)
{
- const char *label = "holdtime";
-
- if (check_tlv_length(__PRETTY_FUNCTION__, label,
- ifname, src_addr,
- sizeof(uint16_t), option_len)) {
- return -1;
- }
-
- check_tlv_redefinition_uint16(__PRETTY_FUNCTION__, label,
- ifname, src_addr,
- *hello_options, PIM_OPTION_MASK_HOLDTIME,
- PIM_TLV_GET_HOLDTIME(tlv_curr),
- *hello_option_holdtime);
-
- PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_HOLDTIME);
-
- *hello_option_holdtime = PIM_TLV_GET_HOLDTIME(tlv_curr);
-
- return 0;
+ const char *label = "holdtime";
+
+ if (check_tlv_length(__PRETTY_FUNCTION__, label, ifname, src_addr,
+ sizeof(uint16_t), option_len)) {
+ return -1;
+ }
+
+ check_tlv_redefinition_uint16(
+ __PRETTY_FUNCTION__, label, ifname, src_addr, *hello_options,
+ PIM_OPTION_MASK_HOLDTIME, PIM_TLV_GET_HOLDTIME(tlv_curr),
+ *hello_option_holdtime);
+
+ PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_HOLDTIME);
+
+ *hello_option_holdtime = PIM_TLV_GET_HOLDTIME(tlv_curr);
+
+ return 0;
}
int pim_tlv_parse_lan_prune_delay(const char *ifname, struct in_addr src_addr,
pim_hello_options *hello_options,
uint16_t *hello_option_propagation_delay,
uint16_t *hello_option_override_interval,
- uint16_t option_len,
- const uint8_t *tlv_curr)
+ uint16_t option_len, const uint8_t *tlv_curr)
{
- if (check_tlv_length(__PRETTY_FUNCTION__, "lan_prune_delay",
- ifname, src_addr,
- sizeof(uint32_t), option_len)) {
- return -1;
- }
-
- check_tlv_redefinition_uint16(__PRETTY_FUNCTION__, "propagation_delay",
- ifname, src_addr,
- *hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY,
- PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr),
- *hello_option_propagation_delay);
-
- PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY);
-
- *hello_option_propagation_delay = PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr);
- if (PIM_TLV_GET_CAN_DISABLE_JOIN_SUPPRESSION(tlv_curr)) {
- PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION);
- }
- else {
- PIM_OPTION_UNSET(*hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION);
- }
- ++tlv_curr;
- ++tlv_curr;
- *hello_option_override_interval = PIM_TLV_GET_OVERRIDE_INTERVAL(tlv_curr);
-
- return 0;
+ if (check_tlv_length(__PRETTY_FUNCTION__, "lan_prune_delay", ifname,
+ src_addr, sizeof(uint32_t), option_len)) {
+ return -1;
+ }
+
+ check_tlv_redefinition_uint16(__PRETTY_FUNCTION__, "propagation_delay",
+ ifname, src_addr, *hello_options,
+ PIM_OPTION_MASK_LAN_PRUNE_DELAY,
+ PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr),
+ *hello_option_propagation_delay);
+
+ PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY);
+
+ *hello_option_propagation_delay =
+ PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr);
+ if (PIM_TLV_GET_CAN_DISABLE_JOIN_SUPPRESSION(tlv_curr)) {
+ PIM_OPTION_SET(*hello_options,
+ PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION);
+ } else {
+ PIM_OPTION_UNSET(*hello_options,
+ PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION);
+ }
+ ++tlv_curr;
+ ++tlv_curr;
+ *hello_option_override_interval =
+ PIM_TLV_GET_OVERRIDE_INTERVAL(tlv_curr);
+
+ return 0;
}
int pim_tlv_parse_dr_priority(const char *ifname, struct in_addr src_addr,
pim_hello_options *hello_options,
uint32_t *hello_option_dr_priority,
- uint16_t option_len,
- const uint8_t *tlv_curr)
+ uint16_t option_len, const uint8_t *tlv_curr)
{
- const char *label = "dr_priority";
-
- if (check_tlv_length(__PRETTY_FUNCTION__, label,
- ifname, src_addr,
- sizeof(uint32_t), option_len)) {
- return -1;
- }
-
- check_tlv_redefinition_uint32(__PRETTY_FUNCTION__, label,
- ifname, src_addr,
- *hello_options, PIM_OPTION_MASK_DR_PRIORITY,
- PIM_TLV_GET_DR_PRIORITY(tlv_curr),
- *hello_option_dr_priority);
-
- PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_DR_PRIORITY);
-
- *hello_option_dr_priority = PIM_TLV_GET_DR_PRIORITY(tlv_curr);
-
- return 0;
+ const char *label = "dr_priority";
+
+ if (check_tlv_length(__PRETTY_FUNCTION__, label, ifname, src_addr,
+ sizeof(uint32_t), option_len)) {
+ return -1;
+ }
+
+ check_tlv_redefinition_uint32(
+ __PRETTY_FUNCTION__, label, ifname, src_addr, *hello_options,
+ PIM_OPTION_MASK_DR_PRIORITY, PIM_TLV_GET_DR_PRIORITY(tlv_curr),
+ *hello_option_dr_priority);
+
+ PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_DR_PRIORITY);
+
+ *hello_option_dr_priority = PIM_TLV_GET_DR_PRIORITY(tlv_curr);
+
+ return 0;
}
int pim_tlv_parse_generation_id(const char *ifname, struct in_addr src_addr,
pim_hello_options *hello_options,
uint32_t *hello_option_generation_id,
- uint16_t option_len,
- const uint8_t *tlv_curr)
+ uint16_t option_len, const uint8_t *tlv_curr)
{
- const char *label = "generation_id";
-
- if (check_tlv_length(__PRETTY_FUNCTION__, label,
- ifname, src_addr,
- sizeof(uint32_t), option_len)) {
- return -1;
- }
-
- check_tlv_redefinition_uint32_hex(__PRETTY_FUNCTION__, label,
- ifname, src_addr,
- *hello_options, PIM_OPTION_MASK_GENERATION_ID,
- PIM_TLV_GET_GENERATION_ID(tlv_curr),
- *hello_option_generation_id);
-
- PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_GENERATION_ID);
-
- *hello_option_generation_id = PIM_TLV_GET_GENERATION_ID(tlv_curr);
-
- return 0;
+ const char *label = "generation_id";
+
+ if (check_tlv_length(__PRETTY_FUNCTION__, label, ifname, src_addr,
+ sizeof(uint32_t), option_len)) {
+ return -1;
+ }
+
+ check_tlv_redefinition_uint32_hex(__PRETTY_FUNCTION__, label, ifname,
+ src_addr, *hello_options,
+ PIM_OPTION_MASK_GENERATION_ID,
+ PIM_TLV_GET_GENERATION_ID(tlv_curr),
+ *hello_option_generation_id);
+
+ PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_GENERATION_ID);
+
+ *hello_option_generation_id = PIM_TLV_GET_GENERATION_ID(tlv_curr);
+
+ return 0;
}
-int
-pim_parse_addr_ucast (struct prefix *p,
- const uint8_t *buf,
- int buf_size)
+int pim_parse_addr_ucast(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;
- const uint8_t *pastend;
- int family;
- int type;
-
- if (buf_size < ucast_encoding_min_len) {
- zlog_warn("%s: unicast address encoding overflow: left=%d needed=%d",
- __PRETTY_FUNCTION__,
- buf_size, ucast_encoding_min_len);
- return -1;
- }
-
- addr = buf;
- pastend = buf + buf_size;
-
- family = *addr++;
- type = *addr++;
-
- if (type) {
- zlog_warn("%s: unknown unicast address encoding type=%d",
- __PRETTY_FUNCTION__,
- type);
- return -2;
- }
-
- switch (family) {
- case PIM_MSG_ADDRESS_FAMILY_IPV4:
- if ((addr + sizeof(struct in_addr)) > pastend) {
- zlog_warn("%s: IPv4 unicast address overflow: left=%zd needed=%zu",
- __PRETTY_FUNCTION__,
- pastend - addr, sizeof(struct in_addr));
- return -3;
- }
-
- p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */
- memcpy(&p->u.prefix4, addr, sizeof(struct in_addr));
- p->prefixlen = IPV4_MAX_PREFIXLEN;
- addr += sizeof(struct in_addr);
-
- break;
- case PIM_MSG_ADDRESS_FAMILY_IPV6:
- if ((addr + sizeof(struct in6_addr)) > pastend) {
- zlog_warn ("%s: IPv6 unicast address overflow: left=%zd needed %zu",
- __PRETTY_FUNCTION__,
- pastend - addr, sizeof(struct in6_addr));
- return -3;
- }
-
- p->family = AF_INET6;
- p->prefixlen = IPV6_MAX_PREFIXLEN;
- memcpy(&p->u.prefix6, addr, sizeof(struct in6_addr));
- addr += sizeof(struct in6_addr);
-
- break;
- default:
- {
- zlog_warn("%s: unknown unicast address encoding family=%d from",
- __PRETTY_FUNCTION__,
- family);
- return -4;
- }
- }
-
- return addr - buf;
+ const int ucast_encoding_min_len = 3; /* 1 family + 1 type + 1 addr */
+ const uint8_t *addr;
+ const uint8_t *pastend;
+ int family;
+ int type;
+
+ if (buf_size < ucast_encoding_min_len) {
+ zlog_warn(
+ "%s: unicast address encoding overflow: left=%d needed=%d",
+ __PRETTY_FUNCTION__, buf_size, ucast_encoding_min_len);
+ return -1;
+ }
+
+ addr = buf;
+ pastend = buf + buf_size;
+
+ family = *addr++;
+ type = *addr++;
+
+ if (type) {
+ zlog_warn("%s: unknown unicast address encoding type=%d",
+ __PRETTY_FUNCTION__, type);
+ return -2;
+ }
+
+ switch (family) {
+ case PIM_MSG_ADDRESS_FAMILY_IPV4:
+ if ((addr + sizeof(struct in_addr)) > pastend) {
+ zlog_warn(
+ "%s: IPv4 unicast address overflow: left=%zd needed=%zu",
+ __PRETTY_FUNCTION__, pastend - addr,
+ sizeof(struct in_addr));
+ return -3;
+ }
+
+ p->family = AF_INET; /* notice: AF_INET !=
+ PIM_MSG_ADDRESS_FAMILY_IPV4 */
+ memcpy(&p->u.prefix4, addr, sizeof(struct in_addr));
+ p->prefixlen = IPV4_MAX_PREFIXLEN;
+ addr += sizeof(struct in_addr);
+
+ break;
+ case PIM_MSG_ADDRESS_FAMILY_IPV6:
+ if ((addr + sizeof(struct in6_addr)) > pastend) {
+ zlog_warn(
+ "%s: IPv6 unicast address overflow: left=%zd needed %zu",
+ __PRETTY_FUNCTION__, pastend - addr,
+ sizeof(struct in6_addr));
+ return -3;
+ }
+
+ p->family = AF_INET6;
+ p->prefixlen = IPV6_MAX_PREFIXLEN;
+ memcpy(&p->u.prefix6, addr, sizeof(struct in6_addr));
+ addr += sizeof(struct in6_addr);
+
+ break;
+ default: {
+ zlog_warn("%s: unknown unicast address encoding family=%d from",
+ __PRETTY_FUNCTION__, family);
+ return -4;
+ }
+ }
+
+ return addr - buf;
}
-int
-pim_parse_addr_group (struct prefix_sg *sg,
- const uint8_t *buf,
- int buf_size)
+int pim_parse_addr_group(struct prefix_sg *sg, const uint8_t *buf, int buf_size)
{
- const int grp_encoding_min_len = 4; /* 1 family + 1 type + 1 reserved + 1 addr */
- const uint8_t *addr;
- const uint8_t *pastend;
- int family;
- int type;
- int mask_len;
-
- if (buf_size < grp_encoding_min_len) {
- zlog_warn("%s: group address encoding overflow: left=%d needed=%d",
- __PRETTY_FUNCTION__,
- buf_size, grp_encoding_min_len);
- return -1;
- }
-
- addr = buf;
- pastend = buf + 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",
- __PRETTY_FUNCTION__, type);
- return -2;
- }
-
- if ((addr + sizeof(struct in_addr)) > pastend) {
- zlog_warn("%s: IPv4 group address overflow: left=%zd needed=%zu from",
- __PRETTY_FUNCTION__,
- pastend - addr, sizeof(struct in_addr));
- return -3;
- }
-
- memcpy(&sg->grp.s_addr, addr, sizeof(struct in_addr));
-
- addr += sizeof(struct in_addr);
-
- break;
- default:
- {
- zlog_warn("%s: unknown group address encoding family=%d mask_len=%d from",
- __PRETTY_FUNCTION__, family, mask_len);
- return -4;
- }
- }
-
- return addr - buf;
+ const int grp_encoding_min_len =
+ 4; /* 1 family + 1 type + 1 reserved + 1 addr */
+ const uint8_t *addr;
+ const uint8_t *pastend;
+ int family;
+ int type;
+ int mask_len;
+
+ if (buf_size < grp_encoding_min_len) {
+ zlog_warn(
+ "%s: group address encoding overflow: left=%d needed=%d",
+ __PRETTY_FUNCTION__, buf_size, grp_encoding_min_len);
+ return -1;
+ }
+
+ addr = buf;
+ pastend = buf + 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",
+ __PRETTY_FUNCTION__, type);
+ return -2;
+ }
+
+ if ((addr + sizeof(struct in_addr)) > pastend) {
+ zlog_warn(
+ "%s: IPv4 group address overflow: left=%zd needed=%zu from",
+ __PRETTY_FUNCTION__, pastend - addr,
+ sizeof(struct in_addr));
+ return -3;
+ }
+
+ memcpy(&sg->grp.s_addr, addr, sizeof(struct in_addr));
+
+ addr += sizeof(struct in_addr);
+
+ break;
+ default: {
+ zlog_warn(
+ "%s: unknown group address encoding family=%d mask_len=%d from",
+ __PRETTY_FUNCTION__, family, mask_len);
+ return -4;
+ }
+ }
+
+ return addr - buf;
}
-int
-pim_parse_addr_source(struct prefix_sg *sg,
- uint8_t *flags,
- const uint8_t *buf,
- int buf_size)
+int pim_parse_addr_source(struct prefix_sg *sg, uint8_t *flags,
+ const uint8_t *buf, int buf_size)
{
- const int src_encoding_min_len = 4; /* 1 family + 1 type + 1 reserved + 1 addr */
- const uint8_t *addr;
- const uint8_t *pastend;
- int family;
- int type;
- int mask_len;
-
- if (buf_size < src_encoding_min_len) {
- zlog_warn("%s: source address encoding overflow: left=%d needed=%d",
- __PRETTY_FUNCTION__,
- buf_size, src_encoding_min_len);
- return -1;
- }
-
- addr = buf;
- pastend = buf + buf_size;
-
- family = *addr++;
- type = *addr++;
- *flags = *addr++;
- mask_len = *addr++;
-
- if (type) {
- zlog_warn("%s: unknown source address encoding type=%d: %02x%02x%02x%02x%02x%02x%02x%02x",
- __PRETTY_FUNCTION__,
- type,
- buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
- return -2;
- }
-
- switch (family) {
- case PIM_MSG_ADDRESS_FAMILY_IPV4:
- if ((addr + sizeof(struct in_addr)) > pastend) {
- zlog_warn("%s: IPv4 source address overflow: left=%zd needed=%zu",
- __PRETTY_FUNCTION__,
- pastend - addr, sizeof(struct in_addr));
- return -3;
- }
-
- memcpy(&sg->src, addr, sizeof(struct in_addr));
-
- /*
- RFC 4601: 4.9.1 Encoded Source and Group Address Formats
-
- Encoded-Source Address
-
- The mask length MUST be equal to the mask length in bits for
- the given Address Family and Encoding Type (32 for IPv4 native
- and 128 for IPv6 native). A router SHOULD ignore any messages
- received with any other mask length.
- */
- if (mask_len != 32) {
- zlog_warn("%s: IPv4 bad source address mask: %d",
- __PRETTY_FUNCTION__, mask_len);
- return -4;
- }
-
- addr += sizeof(struct in_addr);
-
- break;
- default:
- {
- zlog_warn("%s: unknown source address encoding family=%d: %02x%02x%02x%02x%02x%02x%02x%02x",
- __PRETTY_FUNCTION__,
- family,
- buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
- return -5;
- }
- }
-
- return addr - buf;
-}
+ const int src_encoding_min_len =
+ 4; /* 1 family + 1 type + 1 reserved + 1 addr */
+ const uint8_t *addr;
+ const uint8_t *pastend;
+ int family;
+ int type;
+ int mask_len;
+
+ if (buf_size < src_encoding_min_len) {
+ zlog_warn(
+ "%s: source address encoding overflow: left=%d needed=%d",
+ __PRETTY_FUNCTION__, buf_size, src_encoding_min_len);
+ return -1;
+ }
+
+ addr = buf;
+ pastend = buf + buf_size;
+
+ family = *addr++;
+ type = *addr++;
+ *flags = *addr++;
+ mask_len = *addr++;
-#define FREE_ADDR_LIST(hello_option_addr_list) \
-{ \
- if (hello_option_addr_list) { \
- list_delete(hello_option_addr_list); \
- hello_option_addr_list = 0; \
- } \
+ if (type) {
+ zlog_warn(
+ "%s: unknown source address encoding type=%d: %02x%02x%02x%02x%02x%02x%02x%02x",
+ __PRETTY_FUNCTION__, type, buf[0], buf[1], buf[2],
+ buf[3], buf[4], buf[5], buf[6], buf[7]);
+ return -2;
+ }
+
+ switch (family) {
+ case PIM_MSG_ADDRESS_FAMILY_IPV4:
+ if ((addr + sizeof(struct in_addr)) > pastend) {
+ zlog_warn(
+ "%s: IPv4 source address overflow: left=%zd needed=%zu",
+ __PRETTY_FUNCTION__, pastend - addr,
+ sizeof(struct in_addr));
+ return -3;
+ }
+
+ memcpy(&sg->src, addr, sizeof(struct in_addr));
+
+ /*
+ RFC 4601: 4.9.1 Encoded Source and Group Address Formats
+
+ Encoded-Source Address
+
+ The mask length MUST be equal to the mask length in bits for
+ the given Address Family and Encoding Type (32 for IPv4
+ native
+ and 128 for IPv6 native). A router SHOULD ignore any
+ messages
+ received with any other mask length.
+ */
+ if (mask_len != 32) {
+ zlog_warn("%s: IPv4 bad source address mask: %d",
+ __PRETTY_FUNCTION__, mask_len);
+ return -4;
+ }
+
+ addr += sizeof(struct in_addr);
+
+ break;
+ default: {
+ zlog_warn(
+ "%s: unknown source address encoding family=%d: %02x%02x%02x%02x%02x%02x%02x%02x",
+ __PRETTY_FUNCTION__, family, buf[0], buf[1], buf[2],
+ buf[3], buf[4], buf[5], buf[6], buf[7]);
+ return -5;
+ }
+ }
+
+ return addr - buf;
}
+#define FREE_ADDR_LIST(hello_option_addr_list) \
+ { \
+ if (hello_option_addr_list) { \
+ list_delete(&hello_option_addr_list); \
+ hello_option_addr_list = 0; \
+ } \
+ }
+
int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr,
pim_hello_options *hello_options,
struct list **hello_option_addr_list,
- uint16_t option_len,
- const uint8_t *tlv_curr)
+ uint16_t option_len, const uint8_t *tlv_curr)
{
- const uint8_t *addr;
- const uint8_t *pastend;
-
- zassert(hello_option_addr_list);
-
- /*
- Scan addr list
- */
- addr = tlv_curr;
- pastend = tlv_curr + option_len;
- while (addr < pastend) {
- struct prefix tmp;
- int addr_offset;
-
- /*
- Parse ucast addr
- */
- addr_offset = pim_parse_addr_ucast(&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",
- __PRETTY_FUNCTION__,
- src_str, ifname);
- FREE_ADDR_LIST(*hello_option_addr_list);
- return -1;
- }
- addr += addr_offset;
-
- /*
- Debug
- */
- if (PIM_DEBUG_PIM_TRACE) {
- 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",
- __PRETTY_FUNCTION__,
- *hello_option_addr_list ?
- ((int) listcount(*hello_option_addr_list)) : -1,
- addr_str, src_str, ifname);
- }
- break;
- case AF_INET6:
- break;
- default:
- {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
- zlog_debug("%s: PIM hello TLV option: list_old_size=%d UNKNOWN address family from %s on %s",
- __PRETTY_FUNCTION__,
- *hello_option_addr_list ?
- ((int) listcount(*hello_option_addr_list)) : -1,
- src_str, ifname);
- }
- }
- }
-
- /*
- 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",
- __PRETTY_FUNCTION__,
- src_str, ifname);
- continue;
- }
- }
-
- /*
- Allocate list if needed
- */
- if (!*hello_option_addr_list) {
- *hello_option_addr_list = list_new();
- if (!*hello_option_addr_list) {
- zlog_err("%s %s: failure: hello_option_addr_list=list_new()",
- __FILE__, __PRETTY_FUNCTION__);
- return -2;
- }
- (*hello_option_addr_list)->del = (void (*)(void *)) prefix_free;
- }
-
- /*
- Attach addr to list
- */
- {
- struct prefix *p;
- p = prefix_new();
- if (!p) {
- zlog_err("%s %s: failure: prefix_new()",
- __FILE__, __PRETTY_FUNCTION__);
- FREE_ADDR_LIST(*hello_option_addr_list);
- return -3;
- }
- prefix_copy(p, &tmp);
- listnode_add(*hello_option_addr_list, p);
- }
-
- } /* while (addr < pastend) */
-
- /*
- Mark hello option
- */
- PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_ADDRESS_LIST);
-
- return 0;
+ const uint8_t *addr;
+ const uint8_t *pastend;
+
+ zassert(hello_option_addr_list);
+
+ /*
+ Scan addr list
+ */
+ addr = tlv_curr;
+ pastend = tlv_curr + option_len;
+ while (addr < pastend) {
+ struct prefix tmp;
+ int addr_offset;
+
+ /*
+ Parse ucast addr
+ */
+ addr_offset = pim_parse_addr_ucast(&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",
+ __PRETTY_FUNCTION__, src_str, ifname);
+ FREE_ADDR_LIST(*hello_option_addr_list);
+ return -1;
+ }
+ addr += addr_offset;
+
+ /*
+ Debug
+ */
+ if (PIM_DEBUG_PIM_TRACE) {
+ 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",
+ __PRETTY_FUNCTION__,
+ *hello_option_addr_list
+ ? ((int)listcount(
+ *hello_option_addr_list))
+ : -1,
+ addr_str, src_str, ifname);
+ } break;
+ case AF_INET6:
+ break;
+ default: {
+ char src_str[INET_ADDRSTRLEN];
+ pim_inet4_dump("<src?>", src_addr, src_str,
+ sizeof(src_str));
+ zlog_debug(
+ "%s: PIM hello TLV option: list_old_size=%d UNKNOWN address family from %s on %s",
+ __PRETTY_FUNCTION__,
+ *hello_option_addr_list
+ ? ((int)listcount(
+ *hello_option_addr_list))
+ : -1,
+ src_str, ifname);
+ }
+ }
+ }
+
+ /*
+ 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",
+ __PRETTY_FUNCTION__, src_str, ifname);
+ continue;
+ }
+ }
+
+ /*
+ Allocate list if needed
+ */
+ if (!*hello_option_addr_list) {
+ *hello_option_addr_list = list_new();
+ (*hello_option_addr_list)->del =
+ (void (*)(void *))prefix_free;
+ }
+
+ /*
+ Attach addr to list
+ */
+ {
+ struct prefix *p;
+ p = prefix_new();
+ prefix_copy(p, &tmp);
+ listnode_add(*hello_option_addr_list, p);
+ }
+
+ } /* while (addr < pastend) */
+
+ /*
+ Mark hello option
+ */
+ PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_ADDRESS_LIST);
+
+ return 0;
}