From 944f286d87f625c82a340b800094503867a09a97 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 14 Jun 2018 12:55:18 +0200 Subject: [PATCH] fix bug in RA MTU validation Also fix that RA could change IPv4 MTU. See bug #53696 Signed-off-by: Simon Goldschmidt --- src/core/ipv6/ip6.c | 2 +- src/core/ipv6/nd6.c | 17 ++++++++++++----- src/core/netif.c | 6 ++++++ src/include/lwip/netif.h | 9 +++++++++ 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/core/ipv6/ip6.c b/src/core/ipv6/ip6.c index 16f3eea6..eda11dc8 100644 --- a/src/core/ipv6/ip6.c +++ b/src/core/ipv6/ip6.c @@ -1260,7 +1260,7 @@ ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, #endif /* ENABLE_LOOPBACK */ #if LWIP_IPV6_FRAG /* don't fragment if interface has mtu set to 0 [loopif] */ - if (netif->mtu && (p->tot_len > nd6_get_destination_mtu(dest, netif))) { + if (netif_mtu6(netif) && (p->tot_len > nd6_get_destination_mtu(dest, netif))) { return ip6_frag(p, netif, dest); } #endif /* LWIP_IPV6_FRAG */ diff --git a/src/core/ipv6/nd6.c b/src/core/ipv6/nd6.c index 05912df9..db0c132e 100644 --- a/src/core/ipv6/nd6.c +++ b/src/core/ipv6/nd6.c @@ -687,13 +687,20 @@ nd6_input(struct pbuf *p, struct netif *inp) case ND6_OPTION_TYPE_MTU: { struct mtu_option *mtu_opt; + u32_t mtu32; if (option_len < sizeof(struct mtu_option)) { goto lenerr_drop_free_return; } mtu_opt = (struct mtu_option *)buffer; - if (lwip_htonl(mtu_opt->mtu) >= 1280) { + mtu32 = lwip_htonl(mtu_opt->mtu); + if ((mtu32 >= 1280) && (mtu32 <= 0xffff)) { #if LWIP_ND6_ALLOW_RA_UPDATES - inp->mtu = (u16_t)lwip_htonl(mtu_opt->mtu); + if (inp->mtu) { + /* don't set the mtu for IPv6 higher than the netif driver supports */ + inp->mtu6 = LWIP_MIN(inp->mtu, (u16_t)mtu32); + } else { + inp->mtu6 = (u16_t)mtu32; + } #endif /* LWIP_ND6_ALLOW_RA_UPDATES */ } break; @@ -1965,7 +1972,7 @@ nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif) if (ip6_addr_islinklocal(ip6addr) || nd6_is_prefix_in_netif(ip6addr, netif)) { /* Destination in local link. */ - destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; + destination_cache[nd6_cached_destination_index].pmtu = netif_mtu6(netif); ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, destination_cache[nd6_cached_destination_index].destination_addr); #ifdef LWIP_HOOK_ND6_GET_GW } else if ((next_hop_addr = LWIP_HOOK_ND6_GET_GW(netif, ip6addr)) != NULL) { @@ -1981,7 +1988,7 @@ nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif) ip6_addr_set_any(&(destination_cache[nd6_cached_destination_index].destination_addr)); return ERR_RTE; } - destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; /* Start with netif mtu, correct through ICMPv6 if necessary */ + destination_cache[nd6_cached_destination_index].pmtu = netif_mtu6(netif); /* Start with netif mtu, correct through ICMPv6 if necessary */ ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, default_router_list[i].neighbor_entry->next_hop_address); } } @@ -2290,7 +2297,7 @@ nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif) } if (netif != NULL) { - return netif->mtu; + return netif_mtu6(netif); } return 1280; /* Minimum MTU */ diff --git a/src/core/netif.c b/src/core/netif.c index 5965bc5b..4563082c 100644 --- a/src/core/netif.c +++ b/src/core/netif.c @@ -324,6 +324,7 @@ netif_add(struct netif *netif, netif->output_ip6 = netif_null_output_ip6; #endif /* LWIP_IPV6 */ NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL); + netif->mtu = 0; netif->flags = 0; #ifdef netif_get_client_data memset(netif->client_data, 0, sizeof(netif->client_data)); @@ -370,6 +371,11 @@ netif_add(struct netif *netif, if (init(netif) != ERR_OK) { return NULL; } +#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES + /* Initialize the MTU for IPv6 to the one set by the netif driver. + This can be updated later by RA. */ + netif->mtu6 = netif->mtu; +#endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */ #if !LWIP_SINGLE_NETIF /* Assign a unique netif number in the range [0..254], so that (num+1) can diff --git a/src/include/lwip/netif.h b/src/include/lwip/netif.h index 14224f20..86d1485a 100644 --- a/src/include/lwip/netif.h +++ b/src/include/lwip/netif.h @@ -333,6 +333,10 @@ struct netif { #endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/ /** maximum transfer unit (in bytes) */ u16_t mtu; +#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES + /** maximum transfer unit (in bytes), updated by RA */ + u16_t mtu6; +#endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */ /** link level hardware address of this interface */ u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; /** number of bytes used in hwaddr */ @@ -529,6 +533,11 @@ err_t netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t #else /* !LWIP_IPV6_ADDRESS_LIFETIMES */ #define netif_ip6_addr_isstatic(netif, i) (1) /* all addresses are static */ #endif /* !LWIP_IPV6_ADDRESS_LIFETIMES */ +#if LWIP_ND6_ALLOW_RA_UPDATES +#define netif_mtu6(netif) ((netif)->mtu6) +#else /* LWIP_ND6_ALLOW_RA_UPDATES */ +#define netif_mtu6(netif) ((netif)->mtu) +#endif /* LWIP_ND6_ALLOW_RA_UPDATES */ #endif /* LWIP_IPV6 */ #if LWIP_NETIF_USE_HINTS