From 0c2fdfcf428fb6c0d9659c1927e92cf4b89a5d42 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 17 May 2018 21:51:46 +0200 Subject: [PATCH] Fix bug #53667: ARP table max size is to small arp table functions, nd6 destination cache and struct netif_hint can now be u16_t or u8_t depending on table size, so up to 32K entries can be used in these tables (s16_t) Signed-off-by: Simon Goldschmidt --- src/core/ipv4/etharp.c | 82 ++++++++++++++++++++-------------------- src/core/ipv6/nd6.c | 14 +++---- src/include/lwip/netif.h | 8 +++- 3 files changed, 55 insertions(+), 49 deletions(-) diff --git a/src/core/ipv4/etharp.c b/src/core/ipv4/etharp.c index 732be864..e5361b3e 100644 --- a/src/core/ipv4/etharp.c +++ b/src/core/ipv4/etharp.c @@ -105,7 +105,7 @@ struct etharp_entry { static struct etharp_entry arp_table[ARP_TABLE_SIZE]; #if !LWIP_NETIF_HWADDRHINT -static u8_t etharp_cached_entry; +static netif_addr_idx_t etharp_cached_entry; #endif /* !LWIP_NETIF_HWADDRHINT */ /** Try hard to create a new entry - we want the IP address to appear in @@ -196,7 +196,7 @@ etharp_free_entry(int i) void etharp_tmr(void) { - u8_t i; + int i; LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n")); /* remove expired entries from the ARP table */ @@ -212,8 +212,8 @@ etharp_tmr(void) ((arp_table[i].state == ETHARP_STATE_PENDING) && (arp_table[i].ctime >= ARP_MAXPENDING))) { /* pending or stable entry has become old! */ - LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n", - arp_table[i].state >= ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i)); + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %d.\n", + arp_table[i].state >= ETHARP_STATE_STABLE ? "stable" : "pending", i)); /* clean up entries that have just been expired */ etharp_free_entry(i); } else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_1) { @@ -252,14 +252,14 @@ etharp_tmr(void) * @return The ARP entry index that matched or is created, ERR_MEM if no * entry is found or could be recycled. */ -static s8_t +static s16_t etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif *netif) { - s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE; - s8_t empty = ARP_TABLE_SIZE; - u8_t i = 0; + s16_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE; + s16_t empty = ARP_TABLE_SIZE; + s16_t i = 0; /* oldest entry with packets on queue */ - s8_t old_queue = ARP_TABLE_SIZE; + s16_t old_queue = ARP_TABLE_SIZE; /* its age */ u16_t age_queue = 0, age_pending = 0, age_stable = 0; @@ -284,9 +284,9 @@ etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif *netif) u8_t state = arp_table[i].state; /* no empty entry found yet and now we do find one? */ if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) { - LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_find_entry: found empty entry %"U16_F"\n", (u16_t)i)); + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_find_entry: found empty entry %d\n", (int)i)); /* remember first empty entry */ - empty = (s8_t)i; + empty = i; } else if (state != ETHARP_STATE_EMPTY) { LWIP_ASSERT("state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE", state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE); @@ -296,23 +296,23 @@ etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif *netif) && ((netif == NULL) || (netif == arp_table[i].netif)) #endif /* ETHARP_TABLE_MATCH_NETIF */ ) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: found matching entry %"U16_F"\n", (u16_t)i)); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: found matching entry %d\n", (int)i)); /* found exact IP address match, simply bail out */ - return (s8_t)i; + return i; } /* pending entry? */ if (state == ETHARP_STATE_PENDING) { /* pending with queued packets? */ if (arp_table[i].q != NULL) { if (arp_table[i].ctime >= age_queue) { - old_queue = (s8_t)i; + old_queue = i; age_queue = arp_table[i].ctime; } } else /* pending without queued packets? */ { if (arp_table[i].ctime >= age_pending) { - old_pending = (s8_t)i; + old_pending = i; age_pending = arp_table[i].ctime; } } @@ -325,7 +325,7 @@ etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif *netif) { /* remember entry with oldest stable entry in oldest, its age in maxtime */ if (arp_table[i].ctime >= age_stable) { - old_stable = (s8_t)i; + old_stable = i; age_stable = arp_table[i].ctime; } } @@ -339,7 +339,7 @@ etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif *netif) /* or no empty entry found and not allowed to recycle? */ ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) { LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty entry found and not allowed to recycle\n")); - return (s8_t)ERR_MEM; + return (s16_t)ERR_MEM; } /* b) choose the least destructive entry to recycle: @@ -353,30 +353,30 @@ etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif *netif) /* 1) empty entry available? */ if (empty < ARP_TABLE_SIZE) { - i = (u8_t)empty; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting empty entry %"U16_F"\n", (u16_t)i)); + i = empty; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting empty entry %d\n", (int)i)); } else { /* 2) found recyclable stable entry? */ if (old_stable < ARP_TABLE_SIZE) { /* recycle oldest stable*/ - i = (u8_t)old_stable; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i)); + i = old_stable; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest stable entry %d\n", (int)i)); /* no queued packets should exist on stable entries */ LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL); /* 3) found recyclable pending entry without queued packets? */ } else if (old_pending < ARP_TABLE_SIZE) { /* recycle oldest pending */ - i = (u8_t)old_pending; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i)); + i = old_pending; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %d (without queue)\n", (int)i)); /* 4) found recyclable pending entry with queued packets? */ } else if (old_queue < ARP_TABLE_SIZE) { /* recycle oldest pending (queued packets are free in etharp_free_entry) */ - i = (u8_t)old_queue; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q))); + i = old_queue; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %d, freeing packet queue %p\n", (int)i, (void *)(arp_table[i].q))); /* no empty or recyclable entries found */ } else { LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty or recyclable entries found\n")); - return (s8_t)ERR_MEM; + return (s16_t)ERR_MEM; } /* { empty or recyclable entry found } */ @@ -397,7 +397,7 @@ etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif *netif) #if ETHARP_TABLE_MATCH_NETIF arp_table[i].netif = netif; #endif /* ETHARP_TABLE_MATCH_NETIF */ - return (s8_t)i; + return (s16_t)i; } /** @@ -421,7 +421,7 @@ etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif *netif) static err_t etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags) { - s8_t i; + s16_t i; LWIP_ASSERT("netif->hwaddr_len == ETH_HWADDR_LEN", netif->hwaddr_len == ETH_HWADDR_LEN); LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), @@ -460,7 +460,7 @@ etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct et /* insert in SNMP ARP index tree */ mib2_add_arp_entry(netif, &arp_table[i].ipaddr); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i)); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: updating stable entry %"S16_F"\n", i)); /* update address */ SMEMCPY(&arp_table[i].ethaddr, ethaddr, ETH_HWADDR_LEN); /* reset time stamp */ @@ -528,7 +528,7 @@ etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr) err_t etharp_remove_static_entry(const ip4_addr_t *ipaddr) { - s8_t i; + s16_t i; LWIP_ASSERT_CORE_LOCKED(); LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); @@ -558,7 +558,7 @@ etharp_remove_static_entry(const ip4_addr_t *ipaddr) void etharp_cleanup_netif(struct netif *netif) { - u8_t i; + int i; for (i = 0; i < ARP_TABLE_SIZE; ++i) { u8_t state = arp_table[i].state; @@ -583,7 +583,7 @@ ssize_t etharp_find_addr(struct netif *netif, const ip4_addr_t *ipaddr, struct eth_addr **eth_ret, const ip4_addr_t **ip_ret) { - s8_t i; + s16_t i; LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL", eth_ret != NULL && ip_ret != NULL); @@ -745,7 +745,7 @@ etharp_input(struct pbuf *p, struct netif *netif) * in the arp_table specified by the index 'arp_idx'. */ static err_t -etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, u8_t arp_idx) +etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, netif_addr_idx_t arp_idx) { LWIP_ASSERT("arp_table[arp_idx].state >= ETHARP_STATE_STABLE", arp_table[arp_idx].state >= ETHARP_STATE_STABLE); @@ -819,7 +819,7 @@ etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) dest = &mcastaddr; /* unicast destination IP address? */ } else { - u8_t i; + u16_t i; /* outside local network? if so, this can neither be a global broadcast nor a subnet broadcast. */ if (!ip4_addr_netcmp(ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) && @@ -855,7 +855,7 @@ etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) #if LWIP_NETIF_HWADDRHINT if (netif->hints != NULL) { /* per-pcb cached entry was given */ - u8_t etharp_cached_entry = netif->hints->addr_hint; + netif_addr_idx_t etharp_cached_entry = netif->hints->addr_hint; if (etharp_cached_entry < ARP_TABLE_SIZE) { #endif /* LWIP_NETIF_HWADDRHINT */ if ((arp_table[etharp_cached_entry].state >= ETHARP_STATE_STABLE) && @@ -935,8 +935,8 @@ etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q) struct eth_addr *srcaddr = (struct eth_addr *)netif->hwaddr; err_t result = ERR_MEM; int is_new_entry = 0; - s8_t i_err; - u8_t i; + s16_t i_err; + u16_t i; /* non-unicast address? */ if (ip4_addr_isbroadcast(ipaddr, netif) || @@ -958,7 +958,7 @@ etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q) } return (err_t)i_err; } - i = (u8_t)i_err; + i = (u16_t)i_err; /* mark a fresh entry as pending (we just sent a request) */ if (arp_table[i].state == ETHARP_STATE_EMPTY) { @@ -1054,7 +1054,7 @@ etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q) memp_free(MEMP_ARP_QUEUE, old); } #endif - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"U16_F"\n", (void *)q, i)); result = ERR_OK; } else { /* the pool MEMP_ARP_QUEUE is empty */ @@ -1065,12 +1065,12 @@ etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q) #else /* ARP_QUEUEING */ /* always queue one packet per ARP request only, freeing a previously queued packet */ if (arp_table[i].q != NULL) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"U16_F"\n", (void *)q, i)); pbuf_free(arp_table[i].q); } arp_table[i].q = p; result = ERR_OK; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"U16_F"\n", (void *)q, i)); #endif /* ARP_QUEUEING */ } else { ETHARP_STATS_INC(etharp.memerr); diff --git a/src/core/ipv6/nd6.c b/src/core/ipv6/nd6.c index 4de4a7c3..4836867f 100644 --- a/src/core/ipv6/nd6.c +++ b/src/core/ipv6/nd6.c @@ -85,7 +85,7 @@ u32_t retrans_timer = LWIP_ND6_RETRANS_TIMER; /* @todo implement this value in t /* Index for cache entries. */ static u8_t nd6_cached_neighbor_index; -static u8_t nd6_cached_destination_index; +static netif_addr_idx_t nd6_cached_destination_index; /* Multicast address holder. */ static ip6_addr_t multicast_address; @@ -105,9 +105,9 @@ static union ra_options nd6_ra_buffer; static s8_t nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr); static s8_t nd6_new_neighbor_cache_entry(void); static void nd6_free_neighbor_cache_entry(s8_t i); -static s8_t nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr); -static s8_t nd6_new_destination_cache_entry(void); -static s8_t nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif); +static s16_t nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr); +static s16_t nd6_new_destination_cache_entry(void); +static int nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif); static s8_t nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif); static s8_t nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif); static s8_t nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif); @@ -1561,7 +1561,7 @@ nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr) * @return The destination cache entry index that was created, -1 if no * entry was created */ -static s8_t +static s16_t nd6_new_destination_cache_entry(void) { s8_t i, j; @@ -1609,7 +1609,7 @@ nd6_clear_destination_cache(void) * @param ip6addr the IPv6 address to match * @return 1 if the address is on-link, 0 otherwise */ -static s8_t +static int nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif) { s8_t i; @@ -1916,7 +1916,7 @@ nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif) #if LWIP_NETIF_HWADDRHINT if (netif->hints != NULL) { /* per-pcb cached entry was given */ - u8_t addr_hint = netif->hints->addr_hint; + netif_addr_idx_t addr_hint = netif->hints->addr_hint; if (addr_hint < LWIP_ND6_NUM_DESTINATIONS) { nd6_cached_destination_index = addr_hint; } diff --git a/src/include/lwip/netif.h b/src/include/lwip/netif.h index 32d48f79..b4ea76cd 100644 --- a/src/include/lwip/netif.h +++ b/src/include/lwip/netif.h @@ -237,10 +237,16 @@ u8_t netif_alloc_client_data_id(void); #define netif_get_client_data(netif, id) (netif)->client_data[(id)] #endif +#if (LWIP_IPV4 && LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) || (LWIP_IPV6 && (LWIP_ND6_NUM_DESTINATIONS > 0x7f)) +typedef u16_t netif_addr_idx_t; +#else +typedef u8_t netif_addr_idx_t; +#endif + #if LWIP_NETIF_HWADDRHINT #define LWIP_NETIF_USE_HINTS 1 struct netif_hint { - u8_t addr_hint; + netif_addr_idx_t addr_hint; }; #else /* LWIP_NETIF_HWADDRHINT */ #define LWIP_NETIF_USE_HINTS 0