summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJukka Rissanen <jukka.rissanen@linux.intel.com>2017-02-15 13:48:25 +0200
committerAnas Nashif <nashif@linux.intel.com>2017-02-28 11:59:56 +0000
commit2a2a05d0714b944202c713625caee259367255c5 (patch)
tree00d998ca4f90fe67634c84ead9702892b05fe74a
parent9c04bde3cb51c64d13574f5eebbdc45836da793b (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.h47
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;