diff options
-rw-r--r-- | pimd/pim_assert.c | 21 | ||||
-rw-r--r-- | pimd/pim_join.c | 39 | ||||
-rw-r--r-- | pimd/pim_register.c | 16 | ||||
-rw-r--r-- | pimd/pim_tlv.c | 115 | ||||
-rw-r--r-- | pimd/pim_tlv.h | 10 |
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); |