Add support for IPv6 address scopes
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.
This commit is contained in:
committed by
sg
parent
1839153609
commit
29ddfd1d71
@@ -262,8 +262,10 @@ lowpan6_frag(struct netif *netif, struct pbuf *p, const struct ieee_802154_addr
|
||||
|
||||
/* Point to ip6 header and align copies of src/dest addresses. */
|
||||
ip6hdr = (struct ip6_hdr *)p->payload;
|
||||
ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest);
|
||||
ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src);
|
||||
ip_addr_copy_from_ip6_packed(ip_data.current_iphdr_dest, ip6hdr->dest);
|
||||
ip6_addr_assign_zone(ip_2_ip6(&ip_data.current_iphdr_dest), IP6_UNKNOWN, netif);
|
||||
ip_addr_copy_from_ip6_packed(ip_data.current_iphdr_src, ip6hdr->src);
|
||||
ip6_addr_assign_zone(ip_2_ip6(&ip_data.current_iphdr_src), IP6_UNKNOWN, netif);
|
||||
|
||||
/* Basic length of 6LowPAN header, set dispatch and clear fields. */
|
||||
lowpan6_header_len = 2;
|
||||
@@ -574,6 +576,8 @@ lowpan6_set_context(u8_t idx, const ip6_addr_t * context)
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
IP6_ADDR_ZONECHECK(context);
|
||||
|
||||
ip6_addr_set(&lowpan6_context[idx], context);
|
||||
|
||||
return ERR_OK;
|
||||
@@ -627,7 +631,8 @@ lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
|
||||
#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS
|
||||
/* Check if we can compress source address (use aligned copy) */
|
||||
ip6_hdr = (struct ip6_hdr *)q->payload;
|
||||
ip6_addr_set(&ip6_src, &ip6_hdr->src);
|
||||
ip6_addr_copy_from_packed(ip6_src, ip6_hdr->src);
|
||||
ip6_addr_assign_zone(&ip6_src, IP6_UNICAST, netif);
|
||||
if (lowpan6_get_address_mode(&ip6_src, &short_mac_addr) == 3) {
|
||||
src.addr_len = 2;
|
||||
src.addr[0] = short_mac_addr.addr[0];
|
||||
@@ -656,7 +661,7 @@ lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
|
||||
dest.addr_len = 2;
|
||||
dest.addr[0] = ((u8_t *)q->payload)[38];
|
||||
dest.addr[1] = ((u8_t *)q->payload)[39];
|
||||
if ((src.addr_len == 2) && (ip6_addr_netcmp(&ip6_hdr->src, &ip6_hdr->dest)) &&
|
||||
if ((src.addr_len == 2) && (ip6_addr_netcmp_zoneless(&ip6_hdr->src, &ip6_hdr->dest)) &&
|
||||
(lowpan6_get_address_mode(ip6addr, &dest) == 3)) {
|
||||
MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
|
||||
return lowpan6_frag(netif, q, &src, &dest);
|
||||
|
||||
Reference in New Issue
Block a user