From f85b76195aeeb80b6f834da32459a05e297a0a78 Mon Sep 17 00:00:00 2001 From: lynne Date: Tue, 4 May 2021 11:06:49 -0400 Subject: [PATCH 1/2] ospf6d: Limit the number of interface addresses being supported The code had no limits on addresses configured on an interface running ospf6d. The code would crash when more than 100 addresses were added. This change limits the number of interface address to 100 if mtu is set to the default value. If the mtu is set to a jumbo packet size or larger we will support 200 interface addresses. Signed-off-by: Lynne Morrison --- ospf6d/ospf6_interface.c | 13 +++++++++++++ ospf6d/ospf6_interface.h | 1 + ospf6d/ospf6_intra.c | 32 ++++++++++++++++++++++++++------ ospf6d/ospf6_top.c | 18 ++++++++++++++++++ ospf6d/ospf6_top.h | 4 ++++ ospf6d/ospf6_zebra.c | 23 ++++++++++++++++++++++- 6 files changed, 84 insertions(+), 7 deletions(-) diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 11bdd1e3553a..c2f9c3362e9a 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -405,6 +405,7 @@ void ospf6_interface_connected_route_update(struct interface *ifp) struct connected *c; struct listnode *node, *nnode; struct in6_addr nh_addr; + int count = 0, max_addr_count; oi = (struct ospf6_interface *)ifp->info; if (oi == NULL) @@ -423,10 +424,22 @@ void ospf6_interface_connected_route_update(struct interface *ifp) /* update "route to advertise" interface route table */ ospf6_route_remove_all(oi->route_connected); + if (oi->ifmtu >= OSPF6_JUMBO_MTU) + max_addr_count = OSPF6_MAX_IF_ADDRS_JUMBO; + else + max_addr_count = OSPF6_MAX_IF_ADDRS; + for (ALL_LIST_ELEMENTS(oi->interface->connected, node, nnode, c)) { if (c->address->family != AF_INET6) continue; + /* number of interface addresses supported is based on MTU + * size of OSPFv3 packet + */ + count++; + if (count >= max_addr_count) + break; + CONTINUE_IF_ADDRESS_LINKLOCAL(IS_OSPF6_DEBUG_INTERFACE, c->address); CONTINUE_IF_ADDRESS_UNSPECIFIED(IS_OSPF6_DEBUG_INTERFACE, diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h index a45a841406da..48b2cbff7402 100644 --- a/ospf6d/ospf6_interface.h +++ b/ospf6d/ospf6_interface.h @@ -188,6 +188,7 @@ extern void ospf6_interface_disable(struct ospf6_interface *); extern void ospf6_interface_if_add(struct interface *); extern void ospf6_interface_state_update(struct interface *); extern void ospf6_interface_connected_route_update(struct interface *); +extern void ospf6_interface_connected_route_add(struct connected *); /* interface event */ extern int interface_up(struct thread *); diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index 61a438b04a12..12d11d45c1ca 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -757,6 +757,7 @@ int ospf6_link_lsa_originate(struct thread *thread) struct ospf6_link_lsa *link_lsa; struct ospf6_route *route; struct ospf6_prefix *op; + int count, max_addr_count; oi = (struct ospf6_interface *)THREAD_ARG(thread); oi->thread_link_lsa = NULL; @@ -800,14 +801,20 @@ int ospf6_link_lsa_originate(struct thread *thread) memcpy(link_lsa->options, oi->area->options, 3); memcpy(&link_lsa->linklocal_addr, oi->linklocal_addr, 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)); - /* connected prefix to advertise */ - for (route = ospf6_route_head(oi->route_connected); route; - route = ospf6_route_next(route)) { + /* connected prefix to advertise, number of interface addresses + * supported is based on MTU size of OSPFv3 packets + */ + if (oi->ifmtu >= OSPF6_JUMBO_MTU) + max_addr_count = OSPF6_MAX_IF_ADDRS_JUMBO; + else + max_addr_count = OSPF6_MAX_IF_ADDRS; + for (route = ospf6_route_head(oi->route_connected), count = 0; + route && count < max_addr_count; + route = ospf6_route_next(route), count++) { op->prefix_length = route->prefix.prefixlen; op->prefix_options = route->path.prefix_options; op->prefix_metric = htons(0); @@ -816,6 +823,8 @@ int ospf6_link_lsa_originate(struct thread *thread) op = OSPF6_PREFIX_NEXT(op); } + link_lsa->prefix_num = htonl(count); + /* Fill LSA Header */ lsa_header->age = 0; lsa_header->type = htons(OSPF6_LSTYPE_LINK); @@ -995,6 +1004,7 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread) unsigned short prefix_num = 0; struct ospf6_route_table *route_advertise; int ls_id = 0; + int count, max_addr_count; oa = (struct ospf6_area *)THREAD_ARG(thread); oa->thread_intra_prefix_lsa = NULL; @@ -1040,6 +1050,8 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread) intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id; route_advertise = ospf6_route_table_create(0, 0); + route_advertise->hook_add = NULL; + route_advertise->hook_remove = NULL; for (ALL_LIST_ELEMENTS_RO(oa->if_list, i, oi)) { if (oi->state == OSPF6_INTERFACE_DOWN) { @@ -1068,8 +1080,14 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread) zlog_debug(" Interface %s:", oi->interface->name); /* connected prefix to advertise */ - for (route = ospf6_route_head(oi->route_connected); route; - route = ospf6_route_best_next(route)) { + if (oi->ifmtu >= OSPF6_JUMBO_MTU) + max_addr_count = OSPF6_MAX_IF_ADDRS_JUMBO; + else + max_addr_count = OSPF6_MAX_IF_ADDRS; + + for (route = ospf6_route_head(oi->route_connected), count = 0; + route && count < max_addr_count; + route = ospf6_route_best_next(route), count++) { if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX)) zlog_debug(" include %pFX", &route->prefix); ospf6_route_add(ospf6_route_copy(route), @@ -1284,6 +1302,8 @@ int ospf6_intra_prefix_lsa_originate_transit(struct thread *thread) /* connected prefix to advertise */ route_advertise = ospf6_route_table_create(0, 0); + route_advertise->hook_add = NULL; + route_advertise->hook_remove = NULL; type = ntohs(OSPF6_LSTYPE_LINK); for (ALL_LSDB_TYPED(oi->lsdb, type, lsa)) { diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 3ab0f1fbb653..a5c188c465af 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -850,6 +850,7 @@ DEFUN (ospf6_interface_area, struct ospf6_interface *oi; struct interface *ifp; vrf_id_t vrf_id = VRF_DEFAULT; + int ipv6_count = 0; if (ospf6->vrf_id != VRF_UNKNOWN) vrf_id = ospf6->vrf_id; @@ -865,6 +866,23 @@ DEFUN (ospf6_interface_area, return CMD_SUCCESS; } + /* if more than OSPF6_MAX_IF_ADDRS are configured on this interface + * then don't allow ospfv3 to be configured + */ + ipv6_count = connected_count_by_family(ifp, AF_INET6); + if (oi->ifmtu == OSPF6_DEFAULT_MTU && ipv6_count > OSPF6_MAX_IF_ADDRS) { + vty_out(vty, + "can not configure OSPFv3 on if %s, must have less than %d interface addresses but has %d addresses\n", + ifp->name, OSPF6_MAX_IF_ADDRS, ipv6_count); + return CMD_WARNING_CONFIG_FAILED; + } else if (oi->ifmtu >= OSPF6_JUMBO_MTU + && ipv6_count > OSPF6_MAX_IF_ADDRS_JUMBO) { + vty_out(vty, + "can not configure OSPFv3 on if %s, must have less than %d interface addresses but has %d addresses\n", + ifp->name, OSPF6_MAX_IF_ADDRS_JUMBO, ipv6_count); + return CMD_WARNING_CONFIG_FAILED; + } + /* parse Area-ID */ OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa, ospf6); diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h index 9ba5a0f9a4aa..238d6a40ce23 100644 --- a/ospf6d/ospf6_top.h +++ b/ospf6d/ospf6_top.h @@ -153,6 +153,10 @@ DECLARE_QOBJ_TYPE(ospf6); #define OSPF6_DISABLED 0x01 #define OSPF6_STUB_ROUTER 0x02 #define OSPF6_FLAG_ASBR 0x04 +#define OSPF6_MAX_IF_ADDRS 100 +#define OSPF6_MAX_IF_ADDRS_JUMBO 200 +#define OSPF6_DEFAULT_MTU 1500 +#define OSPF6_JUMBO_MTU 9000 /* global pointer for OSPF top data structure */ extern struct ospf6 *ospf6; diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 76e717287040..170d545c49cd 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -130,17 +130,38 @@ void ospf6_zebra_no_redistribute(int type, vrf_id_t vrf_id) static int ospf6_zebra_if_address_update_add(ZAPI_CALLBACK_ARGS) { struct connected *c; + struct ospf6_interface *oi; + int ipv6_count = 0; c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, zclient->ibuf, vrf_id); if (c == NULL) return 0; + oi = (struct ospf6_interface *)c->ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(c->ifp); + assert(oi); + if (IS_OSPF6_DEBUG_ZEBRA(RECV)) zlog_debug("Zebra Interface address add: %s %5s %pFX", c->ifp->name, prefix_family_str(c->address), c->address); + ipv6_count = connected_count_by_family(c->ifp, AF_INET6); + if (oi->ifmtu == OSPF6_DEFAULT_MTU && ipv6_count > OSPF6_MAX_IF_ADDRS) { + zlog_warn( + "Zebra Interface : %s has too many interface addresses %d only support %d, increase MTU", + c->ifp->name, ipv6_count, OSPF6_MAX_IF_ADDRS); + return 0; + } else if (oi->ifmtu >= OSPF6_JUMBO_MTU + && ipv6_count > OSPF6_MAX_IF_ADDRS_JUMBO) { + zlog_warn( + "Zebra Interface : %s has too many interface addresses %d only support %d", + c->ifp->name, ipv6_count, OSPF6_MAX_IF_ADDRS_JUMBO); + return 0; + } + if (c->address->family == AF_INET6) { ospf6_interface_state_update(c->ifp); ospf6_interface_connected_route_update(c->ifp); @@ -303,7 +324,7 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request, struct prefix *dest; if (IS_OSPF6_DEBUG_ZEBRA(SEND)) - zlog_debug("Send %s route: %pFX", + zlog_debug("Zebra Send %s route: %pFX", (type == REM ? "remove" : "add"), &request->prefix); if (zclient->sock < 0) { From 9160389122d425a83fe2a6cf30d72f993b1d1b47 Mon Sep 17 00:00:00 2001 From: lynne Date: Tue, 11 May 2021 09:10:10 -0400 Subject: [PATCH 2/2] ospf6d: document the interface address limits for ospfv3 Signed-off-by: Lynne Morrison --- doc/user/ospf6d.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst index 573b9c8d7ee4..d7f4a3303ec3 100644 --- a/doc/user/ospf6d.rst +++ b/doc/user/ospf6d.rst @@ -305,3 +305,13 @@ Larger example with policy and various options set: ipv6 access-class access6 exec-timeout 0 0 ! + + +Configuration Limits +==================== + +Ospf6d currently supports 100 interfaces addresses if MTU is set to +default value, and 200 interface addresses if MTU is set to jumbo +packet size or larger. + +