diff options
author | Jukka Rissanen <jukka.rissanen@linux.intel.com> | 2017-02-15 13:48:25 +0200 |
---|---|---|
committer | Anas Nashif <nashif@linux.intel.com> | 2017-02-28 11:59:56 +0000 |
commit | 2a2a05d0714b944202c713625caee259367255c5 (patch) | |
tree | 00d998ca4f90fe67634c84ead9702892b05fe74a | |
parent | 9c04bde3cb51c64d13574f5eebbdc45836da793b (diff) |
net: ipv6: Bluetooth address fix
If IPv6 address is generated from Bluetooth MAC address,
then the Universal/Local bit must not be toggled or touched
at all. See RFC 7668 ch 3.2.2 for details.
Because this change is not compatible with older Linux kernel
BT IPSP support, the old behavior can be enabled by setting
CONFIG_NET_L2_BLUETOOTH_ZEP1656 option.
Change-Id: I05d48723b70f1eb60fbd46107ef6a2a4e8f9154a
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
-rw-r--r-- | include/net/net_ip.h | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/include/net/net_ip.h b/include/net/net_ip.h index 48b712095..38887a5d9 100644 --- a/include/net/net_ip.h +++ b/include/net/net_ip.h @@ -678,13 +678,28 @@ static inline void net_ipv6_addr_create_iid(struct in6_addr *addr, break; case 6: + /* We do not toggle the Universal/Local bit + * in Bluetooth. See RFC 7668 ch 3.2.2 + */ memcpy(&addr->s6_addr[8], lladdr->addr, 3); addr->s6_addr[11] = 0xff; addr->s6_addr[12] = 0xfe; memcpy(&addr->s6_addr[13], lladdr->addr + 3, 3); - addr->s6_addr[8] ^= 0x02; - break; +#if defined(CONFIG_NET_L2_BLUETOOTH_ZEP1656) + /* Workaround against older Linux kernel BT IPSP code. + * This will be removed eventually. + */ + if (lladdr->type == NET_LINK_BLUETOOTH) { + addr->s6_addr[8] ^= 0x02; + } +#endif + + if (lladdr->type == NET_LINK_ETHERNET) { + addr->s6_addr[8] ^= 0x02; + } + + break; case 8: memcpy(&addr->s6_addr[8], lladdr->addr, lladdr->len); addr->s6_addr[8] ^= 0x02; @@ -717,12 +732,28 @@ static inline bool net_ipv6_addr_based_on_ll(const struct in6_addr *addr, break; case 6: - if (!memcmp(&addr->s6_addr[9], &lladdr->addr[1], 2) && - !memcmp(&addr->s6_addr[13], &lladdr->addr[3], 3) && - addr->s6_addr[11] == 0xff && - addr->s6_addr[12] == 0xfe && - (addr->s6_addr[8] ^ 0x02) == lladdr->addr[0]) { - return true; + if (lladdr->type == NET_LINK_ETHERNET) { + if (!memcmp(&addr->s6_addr[9], &lladdr->addr[1], 2) && + !memcmp(&addr->s6_addr[13], &lladdr->addr[3], 3) && + addr->s6_addr[11] == 0xff && + addr->s6_addr[12] == 0xfe && + (addr->s6_addr[8] ^ 0x02) == lladdr->addr[0]) { + return true; + } + } else if (lladdr->type == NET_LINK_BLUETOOTH) { + if (!memcmp(&addr->s6_addr[9], &lladdr->addr[1], 2) && + !memcmp(&addr->s6_addr[13], &lladdr->addr[3], 3) && + addr->s6_addr[11] == 0xff && + addr->s6_addr[12] == 0xfe +#if defined(CONFIG_NET_L2_BLUETOOTH_ZEP1656) + /* Workaround against older Linux kernel BT IPSP + * code. This will be removed eventually. + */ + && (addr->s6_addr[8] ^ 0x02) == lladdr->addr[0] +#endif + ) { + return true; + } } break; |