From d0366de57c11a7698945acc1dfaf8a6bead1f6f5 Mon Sep 17 00:00:00 2001 From: Andrew Cooks Date: Thu, 18 Jul 2024 12:56:14 +1000 Subject: [PATCH] ospf6d: replace TLV_HDR_TOP macro with lsdesc_start function The original TLV_HDR_TOP implementation only worked for Graceful Restart LSAs, because they had no "LSA body". This change introduces a body size lookup table and changes the macro to a function that accounts for the LSA body for all LSA types, and provides type checking on the provided pointer before arithmetic. It also removes the open type casting and pointer arithmetic. The introduced lsdesc_start() is used to find the start of a descriptor, and will be used for TLVs in E-LSAs as well as old LSA. Signed-off-by: Andrew Cooks --- ospf6d/ospf6_gr_helper.c | 4 ++-- ospf6d/ospf6_intra.c | 35 ++++++++++++----------------------- ospf6d/ospf6_lsa.c | 31 +++++++++++++++++++++++++++++++ ospf6d/ospf6_lsa.h | 7 ++++++- ospf6d/ospf6_tlv.h | 3 --- 5 files changed, 51 insertions(+), 29 deletions(-) diff --git a/ospf6d/ospf6_gr_helper.c b/ospf6d/ospf6_gr_helper.c index e02a841d00..639d56e273 100644 --- a/ospf6d/ospf6_gr_helper.c +++ b/ospf6d/ospf6_gr_helper.c @@ -145,7 +145,7 @@ static int ospf6_extract_grace_lsa_fields(struct ospf6_lsa *lsa, length = ntohs(lsah->length) - OSPF6_LSA_HEADER_SIZE; - for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh; + for (tlvh = lsdesc_start(lsah); sum < length && tlvh; tlvh = TLV_HDR_NEXT(tlvh)) { /* Check TLV len against overall LSA */ @@ -1241,7 +1241,7 @@ static int ospf6_grace_lsa_show_info(struct vty *vty, struct ospf6_lsa *lsa, zlog_debug(" TLV info:"); } - for (tlvh = TLV_HDR_TOP(lsah); sum < length && tlvh; + for (tlvh = lsdesc_start(lsah); sum < length && tlvh; tlvh = TLV_HDR_NEXT(tlvh)) { /* Check TLV len */ diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index f12f125b7b..470fc66084 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -246,9 +246,7 @@ void ospf6_router_lsa_originate(struct event *thread) ospf6_router_lsa_options_set(oa, router_lsa); /* describe links for each interfaces */ - lsdesc = (struct ospf6_router_lsdesc - *)((caddr_t)router_lsa - + sizeof(struct ospf6_router_lsa)); + lsdesc = lsdesc_start_lsa_type(lsa_header, OSPF6_LSTYPE_ROUTER); for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) { /* Interfaces in state Down or Loopback are not described */ @@ -271,9 +269,9 @@ void ospf6_router_lsa_originate(struct event *thread) && ((size_t)((char *)lsdesc - buffer) + sizeof(struct ospf6_router_lsdesc) > oa->router_lsa_size_limit)) { - if ((caddr_t)lsdesc - == (caddr_t)router_lsa - + sizeof(struct ospf6_router_lsa)) { + if (lsdesc == + lsdesc_start_lsa_type(lsa_header, + OSPF6_LSTYPE_ROUTER)) { zlog_warn( "Size limit setting for Router-LSA too short"); return; @@ -307,9 +305,8 @@ void ospf6_router_lsa_originate(struct event *thread) ospf6_router_lsa_options_set(oa, router_lsa); /* describe links for each interfaces */ - lsdesc = (struct ospf6_router_lsdesc - *)((caddr_t)router_lsa - + sizeof(struct ospf6_router_lsa)); + lsdesc = lsdesc_start_lsa_type(lsa_header, + OSPF6_LSTYPE_ROUTER); link_state_id++; } @@ -571,9 +568,7 @@ void ospf6_network_lsa_originate(struct event *thread) network_lsa->options[2] |= link_lsa->options[2]; } - lsdesc = (struct ospf6_network_lsdesc - *)((caddr_t)network_lsa - + sizeof(struct ospf6_network_lsa)); + lsdesc = lsdesc_start_lsa_type(lsa_header, OSPF6_LSTYPE_NETWORK); /* set Link Description to the router itself */ lsdesc->router_id = oi->area->ospf6->router_id; @@ -797,8 +792,7 @@ void ospf6_link_lsa_originate(struct event *thread) sizeof(struct in6_addr)); link_lsa->prefix_num = htonl(oi->route_connected->count); - op = (struct ospf6_prefix *)((caddr_t)link_lsa - + sizeof(struct ospf6_link_lsa)); + op = lsdesc_start_lsa_type(lsa_header, OSPF6_LSTYPE_LINK); /* connected prefix to advertise */ for (route = ospf6_route_head(oi->route_connected); route; @@ -1109,12 +1103,10 @@ void ospf6_intra_prefix_lsa_originate_stub(struct event *thread) /* put prefixes to advertise */ prefix_num = 0; - op = (struct ospf6_prefix *)((caddr_t)intra_prefix_lsa - + sizeof(struct ospf6_intra_prefix_lsa)); + op = lsdesc_start_lsa_type(lsa_header, OSPF6_LSTYPE_INTRA_PREFIX); for (route = ospf6_route_head(route_advertise); route; route = ospf6_route_best_next(route)) { if (((caddr_t)op - (caddr_t)lsa_header) > MAX_LSA_PAYLOAD) { - intra_prefix_lsa->prefix_num = htons(prefix_num); /* Fill LSA Header */ @@ -1149,10 +1141,8 @@ void ospf6_intra_prefix_lsa_originate_stub(struct event *thread) /* Put next set of prefixes to advertise */ prefix_num = 0; - op = (struct ospf6_prefix - *)((caddr_t)intra_prefix_lsa - + sizeof(struct - ospf6_intra_prefix_lsa)); + op = lsdesc_start_lsa_type(lsa_header, + OSPF6_LSTYPE_INTRA_PREFIX); } op->prefix_length = route->prefix.prefixlen; @@ -1339,8 +1329,7 @@ void ospf6_intra_prefix_lsa_originate_transit(struct event *thread) zlog_debug("Trailing garbage in %s", lsa->name); } - op = (struct ospf6_prefix *)((caddr_t)intra_prefix_lsa - + sizeof(struct ospf6_intra_prefix_lsa)); + op = lsdesc_start_lsa_type(lsa_header, OSPF6_LSTYPE_INTRA_PREFIX); prefix_num = 0; for (route = ospf6_route_head(route_advertise); route; diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c index d8d13d4b4b..de04391b6b 100644 --- a/ospf6d/ospf6_lsa.c +++ b/ospf6d/ospf6_lsa.c @@ -37,6 +37,37 @@ DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA, "OSPF6 LSA"); DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA_HEADER, "OSPF6 LSA header"); DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA_SUMMARY, "OSPF6 LSA summary"); +const uint8_t ospf6_lsa_min_size[OSPF6_LSTYPE_SIZE] = { + [OSPF6_LSTYPE_UNKNOWN] = 0, + [0x00ff & OSPF6_LSTYPE_ROUTER] = OSPF6_ROUTER_LSA_MIN_SIZE, + [0x00ff & OSPF6_LSTYPE_NETWORK] = OSPF6_NETWORK_LSA_MIN_SIZE, + [0x00ff & OSPF6_LSTYPE_INTER_PREFIX] = OSPF6_INTER_PREFIX_LSA_MIN_SIZE, + [0x00ff & OSPF6_LSTYPE_INTER_ROUTER] = OSPF6_INTER_ROUTER_LSA_FIX_SIZE, + [0x00ff & OSPF6_LSTYPE_AS_EXTERNAL] = OSPF6_AS_EXTERNAL_LSA_MIN_SIZE, + [0x00ff & OSPF6_LSTYPE_GROUP_MEMBERSHIP] = 0, /* Unused */ + [0x00ff & OSPF6_LSTYPE_TYPE_7] = OSPF6_AS_EXTERNAL_LSA_MIN_SIZE, + [0x00ff & OSPF6_LSTYPE_LINK] = OSPF6_LINK_LSA_MIN_SIZE, + [0x00ff & OSPF6_LSTYPE_INTRA_PREFIX] = OSPF6_INTRA_PREFIX_LSA_MIN_SIZE, + [0x00ff & OSPF6_LSTYPE_GRACE_LSA] = 0 +}; + +void *lsdesc_start_lsa_type(struct ospf6_lsa_header *header, int lsa_type) +{ + uint8_t t = (0x00ff & lsa_type); + + if (t == OSPF6_LSTYPE_UNKNOWN || t >= OSPF6_LSTYPE_SIZE) { + zlog_debug("Cannot get descriptor offset for unknown lsa type 0x%x", + t); + return ospf6_lsa_end(header); + } + return (char *)lsa_after_header(header) + ospf6_lsa_min_size[t]; +} + +void *lsdesc_start(struct ospf6_lsa_header *header) +{ + return lsdesc_start_lsa_type(header, ntohs(header->type)); +} + static struct ospf6_lsa_handler *lsa_handlers[OSPF6_LSTYPE_SIZE]; struct ospf6 *ospf6_get_by_lsdb(struct ospf6_lsa *lsa) diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h index 9a8b9b0dcd..2f443603c2 100644 --- a/ospf6d/ospf6_lsa.h +++ b/ospf6d/ospf6_lsa.h @@ -87,6 +87,8 @@ struct ospf6_lsa_header { uint16_t length; /* LSA length */ }; + + static inline char *ospf6_lsa_header_end(struct ospf6_lsa_header *header) { return (char *)header + sizeof(struct ospf6_lsa_header); @@ -121,7 +123,6 @@ static inline uint16_t ospf6_lsa_size(struct ospf6_lsa_header *header) #define OSPF6_LSA_IS_CHANGED(L1, L2) ospf6_lsa_is_changed (L1, L2) #define OSPF6_LSA_IS_SEQWRAP(L) ((L)->header->seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER + 1)) - /* Router-LSA */ #define OSPF6_ROUTER_LSA_MIN_SIZE 4U struct ospf6_router_lsa { @@ -369,4 +370,8 @@ extern void ospf6_flush_self_originated_lsas_now(struct ospf6 *ospf6); extern struct ospf6 *ospf6_get_by_lsdb(struct ospf6_lsa *lsa); struct ospf6_lsa *ospf6_find_external_lsa(struct ospf6 *ospf6, struct prefix *p); + +void *lsdesc_start_lsa_type(struct ospf6_lsa_header *header, int lsa_type); +void *lsdesc_start(struct ospf6_lsa_header *header); + #endif /* OSPF6_LSA_H */ diff --git a/ospf6d/ospf6_tlv.h b/ospf6d/ospf6_tlv.h index f94d7f2621..a687a05939 100644 --- a/ospf6d/ospf6_tlv.h +++ b/ospf6d/ospf6_tlv.h @@ -27,9 +27,6 @@ struct tlv_header { #define TLV_SIZE(tlvh) ((uint32_t)(TLV_HDR_SIZE + TLV_BODY_SIZE(tlvh))) -#define TLV_HDR_TOP(lsah) \ - ((struct tlv_header *)((char *)(lsah) + OSPF6_LSA_HEADER_SIZE)) - #define TLV_HDR_NEXT(tlvh) \ ((struct tlv_header *)((char *)(tlvh) + TLV_SIZE(tlvh)))