Skip to content

Commit

Permalink
ospf6d: Limit the number of interface addresses being supported
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
lynne-volta committed May 4, 2021
1 parent 4ae7bb1 commit 7216887
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 7 deletions.
13 changes: 13 additions & 0 deletions ospf6d/ospf6_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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,
Expand Down
1 change: 1 addition & 0 deletions ospf6d/ospf6_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand Down
32 changes: 26 additions & 6 deletions ospf6d/ospf6_intra.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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)) {
Expand Down
19 changes: 19 additions & 0 deletions ospf6d/ospf6_top.c
Original file line number Diff line number Diff line change
Expand Up @@ -740,11 +740,13 @@ DEFUN (ospf6_interface_area,
struct ospf6_area *oa;
struct ospf6_interface *oi;
struct interface *ifp;
int ipv6_count = 0;

VTY_DECLVAR_CONTEXT(ospf6, ospf6);

/* find/create ospf6 interface */
ifp = if_get_by_name(argv[idx_ifname]->arg, VRF_DEFAULT);

oi = (struct ospf6_interface *)ifp->info;
if (oi == NULL)
oi = ospf6_interface_create(ifp);
Expand All @@ -754,6 +756,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);

Expand Down
4 changes: 4 additions & 0 deletions ospf6d/ospf6_top.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
23 changes: 22 additions & 1 deletion ospf6d/ospf6_zebra.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 7216887

Please sign in to comment.