pim6d: IPv6-adjust Hello/TLV processing

Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
David Lamparter 2022-01-14 18:03:21 +01:00
parent 9bb93fa04e
commit 11928ecf19
4 changed files with 109 additions and 186 deletions

View File

@ -33,81 +33,62 @@
#include "pim_upstream.h"
#include "pim_bsm.h"
static void on_trace(const char *label, struct interface *ifp,
struct in_addr src)
static void on_trace(const char *label, struct interface *ifp, pim_addr src)
{
if (PIM_DEBUG_PIM_TRACE) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src, src_str, sizeof(src_str));
zlog_debug("%s: from %s on %s", label, src_str, ifp->name);
}
if (PIM_DEBUG_PIM_TRACE)
zlog_debug("%s: from %pPAs on %s", label, &src, ifp->name);
}
static void tlv_trace_bool(const char *label, const char *tlv_name,
const char *ifname, struct in_addr src_addr,
int isset, int value)
const char *ifname, pim_addr src_addr, int isset,
int value)
{
if (isset) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
if (isset)
zlog_debug(
"%s: PIM hello option from %s on interface %s: %s=%d",
label, src_str, ifname, tlv_name, value);
}
"%s: PIM hello option from %pPAs on interface %s: %s=%d",
label, &src_addr, ifname, tlv_name, value);
}
static void tlv_trace_uint16(const char *label, const char *tlv_name,
const char *ifname, struct in_addr src_addr,
int isset, uint16_t value)
const char *ifname, pim_addr src_addr, int isset,
uint16_t value)
{
if (isset) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
if (isset)
zlog_debug(
"%s: PIM hello option from %s on interface %s: %s=%u",
label, src_str, ifname, tlv_name, value);
}
"%s: PIM hello option from %pPAs on interface %s: %s=%u",
label, &src_addr, ifname, tlv_name, value);
}
static void tlv_trace_uint32(const char *label, const char *tlv_name,
const char *ifname, struct in_addr src_addr,
int isset, uint32_t value)
const char *ifname, pim_addr src_addr, int isset,
uint32_t value)
{
if (isset) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
if (isset)
zlog_debug(
"%s: PIM hello option from %s on interface %s: %s=%u",
label, src_str, ifname, tlv_name, value);
}
"%s: PIM hello option from %pPAs on interface %s: %s=%u",
label, &src_addr, ifname, tlv_name, value);
}
static void tlv_trace_uint32_hex(const char *label, const char *tlv_name,
const char *ifname, struct in_addr src_addr,
const char *ifname, pim_addr src_addr,
int isset, uint32_t value)
{
if (isset) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
if (isset)
zlog_debug(
"%s: PIM hello option from %s on interface %s: %s=%08x",
label, src_str, ifname, tlv_name, value);
}
"%s: PIM hello option from %pPAs on interface %s: %s=%08x",
label, &src_addr, ifname, tlv_name, value);
}
static void tlv_trace_list(const char *label, const char *tlv_name,
const char *ifname, struct in_addr src_addr,
int isset, struct list *addr_list)
const char *ifname, pim_addr src_addr, int isset,
struct list *addr_list)
{
if (isset) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
if (isset)
zlog_debug(
"%s: PIM hello option from %s on interface %s: %s size=%d list=%p",
label, src_str, ifname, tlv_name,
"%s: PIM hello option from %pPAs on interface %s: %s size=%d list=%p",
label, &src_addr, ifname, tlv_name,
addr_list ? ((int)listcount(addr_list)) : -1,
(void *)addr_list);
}
}
#define FREE_ADDR_LIST \
@ -121,8 +102,8 @@ static void tlv_trace_list(const char *label, const char *tlv_name,
return (code); \
}
int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
uint8_t *tlv_buf, int tlv_buf_size)
int pim_hello_recv(struct interface *ifp, pim_addr src_addr, uint8_t *tlv_buf,
int tlv_buf_size)
{
struct pim_interface *pim_ifp;
struct pim_neighbor *neigh;
@ -158,15 +139,11 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
int remain = tlv_pastend - tlv_curr;
if (remain < PIM_TLV_MIN_SIZE) {
if (PIM_DEBUG_PIM_HELLO) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str,
sizeof(src_str));
if (PIM_DEBUG_PIM_HELLO)
zlog_debug(
"%s: short PIM hello TLV size=%d < min=%d from %s on interface %s",
"%s: short PIM hello TLV size=%d < min=%d from %pPAs on interface %s",
__func__, remain, PIM_TLV_MIN_SIZE,
src_str, ifp->name);
}
&src_addr, ifp->name);
FREE_ADDR_LIST_THEN_RETURN(-1);
}
@ -176,28 +153,20 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
tlv_curr += PIM_TLV_LENGTH_SIZE;
if ((tlv_curr + option_len) > tlv_pastend) {
if (PIM_DEBUG_PIM_HELLO) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str,
sizeof(src_str));
if (PIM_DEBUG_PIM_HELLO)
zlog_debug(
"%s: long PIM hello TLV type=%d length=%d > left=%td from %s on interface %s",
"%s: long PIM hello TLV type=%d length=%d > left=%td from %pPAs on interface %s",
__func__, option_type, option_len,
tlv_pastend - tlv_curr, src_str,
tlv_pastend - tlv_curr, &src_addr,
ifp->name);
}
FREE_ADDR_LIST_THEN_RETURN(-2);
}
if (PIM_DEBUG_PIM_HELLO) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str,
sizeof(src_str));
if (PIM_DEBUG_PIM_HELLO)
zlog_debug(
"%s: parse left_size=%d: PIM hello TLV type=%d length=%d from %s on %s",
"%s: parse left_size=%d: PIM hello TLV type=%d length=%d from %pPAs on %s",
__func__, remain, option_type, option_len,
src_str, ifp->name);
}
&src_addr, ifp->name);
switch (option_type) {
case PIM_MSG_OPTION_TYPE_HOLDTIME:
@ -242,26 +211,18 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
}
break;
case PIM_MSG_OPTION_TYPE_DM_STATE_REFRESH:
if (PIM_DEBUG_PIM_HELLO) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str,
sizeof(src_str));
if (PIM_DEBUG_PIM_HELLO)
zlog_debug(
"%s: ignoring PIM hello dense-mode state refresh TLV option type=%d length=%d from %s on interface %s",
"%s: ignoring PIM hello dense-mode state refresh TLV option type=%d length=%d from %pPAs on interface %s",
__func__, option_type, option_len,
src_str, ifp->name);
}
&src_addr, ifp->name);
break;
default:
if (PIM_DEBUG_PIM_HELLO) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str,
sizeof(src_str));
if (PIM_DEBUG_PIM_HELLO)
zlog_debug(
"%s: ignoring unknown PIM hello TLV type=%d length=%d from %s on interface %s",
"%s: ignoring unknown PIM hello TLV type=%d length=%d from %pPAs on interface %s",
__func__, option_type, option_len,
src_str, ifp->name);
}
&src_addr, ifp->name);
}
tlv_curr += option_len;
@ -310,14 +271,10 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
}
if (!PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) {
if (PIM_DEBUG_PIM_HELLO) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str,
sizeof(src_str));
if (PIM_DEBUG_PIM_HELLO)
zlog_debug(
"%s: PIM hello missing holdtime from %s on interface %s",
__func__, src_str, ifp->name);
}
"%s: PIM hello missing holdtime from %pPAs on interface %s",
__func__, &src_addr, ifp->name);
}
/*
@ -335,14 +292,10 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
hello_option_dr_priority, hello_option_generation_id,
hello_option_addr_list, PIM_NEIGHBOR_SEND_DELAY);
if (!neigh) {
if (PIM_DEBUG_PIM_HELLO) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str,
sizeof(src_str));
if (PIM_DEBUG_PIM_HELLO)
zlog_warn(
"%s: failure creating PIM neighbor %s on interface %s",
__func__, src_str, ifp->name);
}
"%s: failure creating PIM neighbor %pPAs on interface %s",
__func__, &src_addr, ifp->name);
FREE_ADDR_LIST_THEN_RETURN(-8);
}
/* Forward BSM if required */
@ -368,16 +321,12 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
|| (hello_option_generation_id != neigh->generation_id)) {
/* GenID mismatch, then replace neighbor */
if (PIM_DEBUG_PIM_HELLO) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr, src_str,
sizeof(src_str));
if (PIM_DEBUG_PIM_HELLO)
zlog_debug(
"%s: GenId mismatch new=%08x old=%08x: replacing neighbor %s on %s",
"%s: GenId mismatch new=%08x old=%08x: replacing neighbor %pPAs on %s",
__func__, hello_option_generation_id,
neigh->generation_id, src_str,
neigh->generation_id, &src_addr,
ifp->name);
}
pim_upstream_rpf_genid_changed(pim_ifp->pim,
neigh->source_addr);
@ -392,15 +341,10 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
hello_option_addr_list,
PIM_NEIGHBOR_SEND_NOW);
if (!neigh) {
if (PIM_DEBUG_PIM_HELLO) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<src?>", src_addr,
src_str,
sizeof(src_str));
if (PIM_DEBUG_PIM_HELLO)
zlog_debug(
"%s: failure re-creating PIM neighbor %s on interface %s",
__func__, src_str, ifp->name);
}
"%s: failure re-creating PIM neighbor %pPAs on interface %s",
__func__, &src_addr, ifp->name);
FREE_ADDR_LIST_THEN_RETURN(-9);
}
/* Forward BSM if required */

View File

@ -24,8 +24,8 @@
#include "if.h"
int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
uint8_t *tlv_buf, int tlv_buf_size);
int pim_hello_recv(struct interface *ifp, pim_addr src_addr, uint8_t *tlv_buf,
int tlv_buf_size);
int pim_hello_build_tlv(struct interface *ifp, uint8_t *tlv_buf,
int tlv_buf_size, uint16_t holdtime,

View File

@ -290,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;
}
@ -306,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)
@ -372,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,
@ -408,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)
@ -432,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)
@ -682,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)
@ -698,7 +691,7 @@ 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;
/*
@ -707,12 +700,9 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_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;
}
@ -725,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);
}
}
@ -761,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;
}
/*

View File

@ -84,24 +84,24 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf, const uint8_t *buf_pastend,
uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend,
struct list *ifconnected, int family);
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);
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,
uint16_t option_len, const uint8_t *tlv_curr);
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);
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);
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);