summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pimd/pim_assert.c21
-rw-r--r--pimd/pim_join.c39
-rw-r--r--pimd/pim_register.c16
-rw-r--r--pimd/pim_tlv.c115
-rw-r--r--pimd/pim_tlv.h10
5 files changed, 113 insertions, 88 deletions
diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c
index 3c38ebd76..f4b6e81bd 100644
--- a/pimd/pim_assert.c
+++ b/pimd/pim_assert.c
@@ -216,7 +216,8 @@ int pim_assert_recv(struct interface *ifp, struct pim_neighbor *neigh,
struct in_addr src_addr, uint8_t *buf, int buf_size)
{
pim_sgaddr sg;
- struct prefix msg_source_addr;
+ pim_addr msg_source_addr;
+ bool wrong_af = false;
struct pim_assert_metric msg_metric;
int offset;
uint8_t *curr;
@@ -246,8 +247,9 @@ int pim_assert_recv(struct interface *ifp, struct pim_neighbor *neigh,
/*
Parse assert source addr
*/
- offset = pim_parse_addr_ucast(&msg_source_addr, curr, curr_size);
- if (offset < 1) {
+ offset = pim_parse_addr_ucast(&msg_source_addr, curr, curr_size,
+ &wrong_af);
+ if (offset < 1 || wrong_af) {
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",
@@ -286,15 +288,13 @@ int pim_assert_recv(struct interface *ifp, struct pim_neighbor *neigh,
if (PIM_DEBUG_PIM_TRACE) {
char neigh_str[INET_ADDRSTRLEN];
- char source_str[INET_ADDRSTRLEN];
pim_inet4_dump("<neigh?>", src_addr, neigh_str,
sizeof(neigh_str));
- pim_inet4_dump("<src?>", msg_source_addr.u.prefix4, source_str,
- sizeof(source_str));
zlog_debug(
- "%s: from %s on %s: (S,G)=(%s,%pPAs) pref=%u metric=%u rpt_bit=%u",
- __func__, neigh_str, ifp->name, source_str, &sg.grp,
- msg_metric.metric_preference, msg_metric.route_metric,
+ "%s: from %s on %s: (S,G)=(%pPAs,%pPAs) pref=%u metric=%u rpt_bit=%u",
+ __func__, neigh_str, ifp->name, &msg_source_addr,
+ &sg.grp, msg_metric.metric_preference,
+ msg_metric.route_metric,
PIM_FORCE_BOOLEAN(msg_metric.rpt_bit_flag));
}
@@ -304,8 +304,7 @@ int pim_assert_recv(struct interface *ifp, struct pim_neighbor *neigh,
assert(pim_ifp);
++pim_ifp->pim_ifstat_assert_recv;
- return dispatch_assert(ifp, msg_source_addr.u.prefix4, sg.grp,
- msg_metric);
+ return dispatch_assert(ifp, msg_source_addr, sg.grp, msg_metric);
}
/*
diff --git a/pimd/pim_join.c b/pimd/pim_join.c
index 22890dc37..a3a97f20e 100644
--- a/pimd/pim_join.c
+++ b/pimd/pim_join.c
@@ -165,7 +165,8 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
struct in_addr src_addr, uint8_t *tlv_buf,
int tlv_buf_size)
{
- struct prefix msg_upstream_addr;
+ pim_addr msg_upstream_addr;
+ bool wrong_af = false;
struct pim_interface *pim_ifp;
uint8_t msg_num_groups;
uint16_t msg_holdtime;
@@ -184,8 +185,8 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
/*
Parse ucast addr
*/
- addr_offset =
- pim_parse_addr_ucast(&msg_upstream_addr, buf, pastend - buf);
+ addr_offset = pim_parse_addr_ucast(&msg_upstream_addr, buf,
+ pastend - buf, &wrong_af);
if (addr_offset < 1) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
@@ -198,12 +199,12 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
/*
Check upstream address family
*/
- if (msg_upstream_addr.family != AF_INET) {
+ if (wrong_af) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
zlog_warn(
- "%s: ignoring join/prune directed to unexpected addr family=%d from %s on %s",
- __func__, msg_upstream_addr.family, src_str, ifp->name);
+ "%s: ignoring join/prune directed to unexpected addr family from %s on %s",
+ __func__, src_str, ifp->name);
return -2;
}
@@ -226,14 +227,11 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
if (PIM_DEBUG_PIM_J_P) {
char src_str[INET_ADDRSTRLEN];
- char upstream_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
- pim_inet4_dump("<addr?>", msg_upstream_addr.u.prefix4,
- upstream_str, sizeof(upstream_str));
zlog_debug(
- "%s: join/prune upstream=%s groups=%d holdtime=%d from %s on %s",
- __func__, upstream_str, msg_num_groups, msg_holdtime,
- src_str, ifp->name);
+ "%s: join/prune upstream=%pPAs groups=%d holdtime=%d from %s on %s",
+ __func__, &msg_upstream_addr, msg_num_groups,
+ msg_holdtime, src_str, ifp->name);
}
/* Scan groups */
@@ -271,14 +269,11 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
if (PIM_DEBUG_PIM_J_P) {
char src_str[INET_ADDRSTRLEN];
- char upstream_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str,
sizeof(src_str));
- pim_inet4_dump("<addr?>", msg_upstream_addr.u.prefix4,
- upstream_str, sizeof(upstream_str));
zlog_debug(
- "%s: join/prune upstream=%s group=%pPA/32 join_src=%d prune_src=%d from %s on %s",
- __func__, upstream_str, &sg.grp,
+ "%s: join/prune upstream=%pPAs group=%pPA/32 join_src=%d prune_src=%d from %s on %s",
+ __func__, &msg_upstream_addr, &sg.grp,
msg_num_joined_sources, msg_num_pruned_sources,
src_str, ifp->name);
}
@@ -300,9 +295,8 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
if (filtered)
continue;
- recv_join(ifp, neigh, msg_holdtime,
- msg_upstream_addr.u.prefix4, &sg,
- msg_source_flags);
+ recv_join(ifp, neigh, msg_holdtime, msg_upstream_addr,
+ &sg, msg_source_flags);
if (pim_addr_is_any(sg.src)) {
starg_ch = pim_ifchannel_find(ifp, &sg);
@@ -326,9 +320,8 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
if (filtered)
continue;
- recv_prune(ifp, neigh, msg_holdtime,
- msg_upstream_addr.u.prefix4, &sg,
- msg_source_flags);
+ recv_prune(ifp, neigh, msg_holdtime, msg_upstream_addr,
+ &sg, msg_source_flags);
/*
* So if we are receiving a S,G,RPT prune
* before we have any data for that S,G
diff --git a/pimd/pim_register.c b/pimd/pim_register.c
index 855d91256..a0def299f 100644
--- a/pimd/pim_register.c
+++ b/pimd/pim_register.c
@@ -72,7 +72,6 @@ void pim_register_stop_send(struct interface *ifp, pim_sgaddr *sg,
unsigned int b1length = 0;
unsigned int length;
uint8_t *b1;
- struct prefix p;
if (PIM_DEBUG_PIM_REG) {
zlog_debug("Sending Register stop for %pSG to %pI4 on %s", sg,
@@ -86,10 +85,7 @@ void pim_register_stop_send(struct interface *ifp, pim_sgaddr *sg,
b1length += length;
b1 += length;
- p.family = AF_INET;
- p.u.prefix4 = sg->src;
- p.prefixlen = IPV4_MAX_BITLEN;
- length = pim_encode_addr_ucast(b1, &p);
+ length = pim_encode_addr_ucast(b1, sg->src);
b1length += length;
pim_msg_build_header(buffer, b1length + PIM_MSG_REGISTER_STOP_LEN,
@@ -117,8 +113,8 @@ int pim_register_stop_recv(struct interface *ifp, uint8_t *buf, int buf_size)
struct pim_interface *pim_ifp = ifp->info;
struct pim_instance *pim = pim_ifp->pim;
struct pim_upstream *upstream = NULL;
- struct prefix source;
pim_sgaddr sg;
+ bool wrong_af = false;
int l;
++pim_ifp->pim_ifstat_reg_stop_recv;
@@ -127,8 +123,12 @@ int pim_register_stop_recv(struct interface *ifp, uint8_t *buf, int buf_size)
l = pim_parse_addr_group(&sg, buf, buf_size);
buf += l;
buf_size -= l;
- pim_parse_addr_ucast(&source, buf, buf_size);
- sg.src = source.u.prefix4;
+ pim_parse_addr_ucast(&sg.src, buf, buf_size, &wrong_af);
+
+ if (wrong_af) {
+ zlog_err("invalid AF in Register-Stop on %s", ifp->name);
+ return 0;
+ }
upstream = pim_upstream_find(pim, &sg);
if (!upstream) {
diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c
index a4f60e519..f38eed8cb 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;
}
@@ -441,7 +457,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 +527,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 +568,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;
}
@@ -676,7 +704,8 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr,
/*
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,
diff --git a/pimd/pim_tlv.h b/pimd/pim_tlv.h
index 1aa60d5db..614c30a48 100644
--- a/pimd/pim_tlv.h
+++ b/pimd/pim_tlv.h
@@ -106,11 +106,15 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr,
struct list **hello_option_addr_list,
uint16_t option_len, const uint8_t *tlv_curr);
-int pim_encode_addr_ucast(uint8_t *buf, struct prefix *p);
+int pim_encode_addr_ucast(uint8_t *buf, pim_addr addr);
+int pim_encode_addr_ucast_prefix(uint8_t *buf, struct prefix *p);
int pim_encode_addr_group(uint8_t *buf, afi_t afi, int bidir, int scope,
- struct in_addr group);
+ pim_addr group);
-int pim_parse_addr_ucast(struct prefix *p, const uint8_t *buf, int buf_size);
+int pim_parse_addr_ucast(pim_addr *out, const uint8_t *buf, int buf_size,
+ bool *wrong_af);
+int pim_parse_addr_ucast_prefix(struct prefix *out, const uint8_t *buf,
+ int buf_size);
int pim_parse_addr_group(pim_sgaddr *sg, const uint8_t *buf, int buf_size);
int pim_parse_addr_source(pim_sgaddr *sg, uint8_t *flags, const uint8_t *buf,
int buf_size);