Previously, on netifs with unrestricted MTUs (typically loopback
interfaces), it was possible to give a packet to the UDP/RAW API
calls that is so large that when prepending headers, the pbuf's
tot_len field would overflow. This could easily result in
undesirable behavior at lower layers, e.g. a crash when copying
the packet for later delivery.
This patch models such overflows as memory allocation errors, thus
resulting in clean failures. Checks have to be added in multiple
places to cover (hopefully) all cases.
This patch adds full support for IPv6 address scopes, thereby aiming
to be compliant with IPv6 standards in general and RFC 4007 in
particular. The high-level summary is that link-local addresses are
now meaningful only in the context of their own link, guaranteeing
full isolation between links (and their addresses) in this respect.
This isolation even allows multiple interfaces to have the same
link-local addresses locally assigned.
The implementation achieves this by extending the lwIP IPv6 address
structure with a zone field that, for addresses that have a scope,
carries the scope's zone in which that address has meaning. The zone
maps to one or more interfaces. By default, lwIP uses a policy that
provides a 1:1 mapping between links and interfaces, and considers
all other addresses unscoped, corresponding to the default policy
sketched in RFC 4007 Sec. 6. The implementation allows for replacing
the default policy with a custom policy if desired, though.
The lwIP core implementation has been changed to provide somewhat of
a balance between correctness and efficiency on on side, and backward
compatibility on the other. In particular, while the application would
ideally always provide a zone for a scoped address, putting this in as
a requirement would likely break many applications. Instead, the API
accepts both "properly zoned" IPv6 addresses and addresses that, while
scoped, "lack" a zone. lwIP will try to add a zone as soon as possible
for efficiency reasons, in particular from TCP/UDP/RAW PCB bind and
connect calls, but this may fail, and sendto calls may bypass that
anyway. Ultimately, a zone is always added when an IP packet is sent
when needed, because the link-layer lwIP code (and ND6 in particualar)
requires that all addresses be properly zoned for correctness: for
example, to provide isolation between links in the ND6 destination
cache. All this applies to packet output only, because on packet
input, all scoped addresses will be given a zone automatically.
It is also worth remarking that on output, no attempt is made to stop
outgoing packets with addresses for a zone not matching the outgoing
interface. However, unless the application explicitly provides
addresses that will result in such zone violations, the core API
implementation (and the IPv6 routing algorithm in particular) itself
will never take decisions that result in zone violations itself.
This patch adds a new header file, ip6_zone.h, which contains comments
that explain several implementation aspects in a bit more detail.
For now, it is possible to disable scope support by changing the new
LWIP_IPV6_SCOPES configuration option. For users of the core API, it
is important to note that scoped addresses that are locally assigned
to a netif must always have a zone set; the standard netif address
assignment functions always do this on behalf of the caller, though.
Also, core API users will want to enable LWIP_IPV6_SCOPES_DEBUG at
least initially when upgrading, to ensure that all addresses are
properly initialized.
The tests were in to catch user errors, but they seem to get in the way of application programming :-)
The checks in *_send() remain active to catch when PCB source and destination address types do not match
Change lwIP UDP API to match socket behavior. Multicast traffic is now only received on a UDP PCB (and therefore on a UDP socket/netconn) when the PCB is bound to IP_ADDR_ANY.
bind() may change IP type when previous type is IPADDR_TYPE_ANY
connect() IP type must exactly match bind IP type
Use correct IPADDRx_ANY type when calling ip_route()
Let lwip use functions/macros prefixed by lwip_ internally to avoid naming clashes with external #includes.
Remove over-complicated #define handling in def.h
Make functions easier to override in cc.h. The following is sufficient now (no more LWIP_PLATFORM_BYTESWAP):
#define lwip_htons(x) <your_htons>
#define lwip_htonl(x) <your_htonl>
Sockets bound to a multicast address could not transmit multicast
packets because the pcb local address did not match the netif address
even if the outgoing netif was resolved correctly.
To correct the issue, pcbs with a multicast local address will use
the outgoing netif address as the source address in IPv4.
The old approach called udp_bind() on each of the PCBs, which puts them into udp_pcbs list. The PCBs were iterated on all non-DHCP udp_inputs() with no effect.
My cleanup removes the special handling in udp.c, and uses only one DHCP UDP PCB to catch all DHCP messages from all netifs. The dhcp_recv function then checks whether ip_current_input_netif() has DHCP enabled - if not, the message is ignored. The PCB is only created/registered when one or more PCBs have DHCP enabled.
Create special IP address type "IPADDR_TYPE_ANY" for it.
SNMP uses new feature in non-netconn mode.
TODO: Same for TCP & RAW, adapt NETCONN to use this feature
- Move local PCB matching code in a function that can be reused in SO_REUSE && SO_REUSE_RXTOALL case.
- Some checks have been written in the dual-stack version and then repeated with the ipv6-only version. Example:
IPv6 only: ip6_addr_ismulticast(ip6_current_dest_addr())
IPv4 AND IPv6: ip_addr_ismulticast(ip_current_dest_addr())