diff options
| author | lynne <lynne@voltanet.io> | 2021-05-04 11:06:49 -0400 | 
|---|---|---|
| committer | lynne <lynne@voltanet.io> | 2021-05-11 09:43:07 -0400 | 
| commit | f85b76195aeeb80b6f834da32459a05e297a0a78 (patch) | |
| tree | d04aaa357a21c9a76c930813aaaa7850c85a4eb4 /ospf6d | |
| parent | 449e54fd12372273dcac68781eb77c1297aeb2ba (diff) | |
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 <lynne@voltanet.io>
Diffstat (limited to 'ospf6d')
| -rw-r--r-- | ospf6d/ospf6_interface.c | 13 | ||||
| -rw-r--r-- | ospf6d/ospf6_interface.h | 1 | ||||
| -rw-r--r-- | ospf6d/ospf6_intra.c | 32 | ||||
| -rw-r--r-- | ospf6d/ospf6_top.c | 18 | ||||
| -rw-r--r-- | ospf6d/ospf6_top.h | 4 | ||||
| -rw-r--r-- | 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 11bdd1e355..c2f9c3362e 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 a45a841406..48b2cbff74 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 61a438b04a..12d11d45c1 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 3ab0f1fbb6..a5c188c465 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 9ba5a0f9a4..238d6a40ce 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 76e7172870..170d545c49 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) {  | 
