Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

6lowpan: Fix IID format for Bluetooth

According to RFC 7668 U/L bit shall not be used:

https://wiki.tools.ietf.org/html/rfc7668#section-3.2.2 [Page 10]:

In the figure, letter 'b' represents a bit from the
Bluetooth device address, copied as is without any changes on any
bit. This means that no bit in the IID indicates whether the
underlying Bluetooth device address is public or random.

|0 1|1 3|3 4|4 6|
|0 5|6 1|2 7|8 3|
+----------------+----------------+----------------+----------------+
|bbbbbbbbbbbbbbbb|bbbbbbbb11111111|11111110bbbbbbbb|bbbbbbbbbbbbbbbb|
+----------------+----------------+----------------+----------------+

Because of this the code cannot figure out the address type from the IP
address anymore thus it makes no sense to use peer_lookup_ba as it needs
the peer address type.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>
Acked-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>

authored by

Luiz Augusto von Dentz and committed by
Marcel Holtmann
9dae2e03 fa09ae66

+17 -72
-4
include/net/6lowpan.h
··· 211 211 ipaddr->s6_addr[11] = 0xFF; 212 212 ipaddr->s6_addr[12] = 0xFE; 213 213 memcpy(&ipaddr->s6_addr[13], lladdr + 3, 3); 214 - /* second bit-flip (Universe/Local) 215 - * is done according RFC2464 216 - */ 217 - ipaddr->s6_addr[8] ^= 0x02; 218 214 } 219 215 220 216 #ifdef DEBUG
+12 -67
net/bluetooth/6lowpan.c
··· 398 398 return err; 399 399 } 400 400 401 - static u8 get_addr_type_from_eui64(u8 byte) 402 - { 403 - /* Is universal(0) or local(1) bit */ 404 - return ((byte & 0x02) ? BDADDR_LE_RANDOM : BDADDR_LE_PUBLIC); 405 - } 406 - 407 - static void copy_to_bdaddr(struct in6_addr *ip6_daddr, bdaddr_t *addr) 408 - { 409 - u8 *eui64 = ip6_daddr->s6_addr + 8; 410 - 411 - addr->b[0] = eui64[7]; 412 - addr->b[1] = eui64[6]; 413 - addr->b[2] = eui64[5]; 414 - addr->b[3] = eui64[2]; 415 - addr->b[4] = eui64[1]; 416 - addr->b[5] = eui64[0]; 417 - } 418 - 419 - static void convert_dest_bdaddr(struct in6_addr *ip6_daddr, 420 - bdaddr_t *addr, u8 *addr_type) 421 - { 422 - copy_to_bdaddr(ip6_daddr, addr); 423 - 424 - /* We need to toggle the U/L bit that we got from IPv6 address 425 - * so that we get the proper address and type of the BD address. 426 - */ 427 - addr->b[5] ^= 0x02; 428 - 429 - *addr_type = get_addr_type_from_eui64(addr->b[5]); 430 - } 431 - 432 401 static int setup_header(struct sk_buff *skb, struct net_device *netdev, 433 402 bdaddr_t *peer_addr, u8 *peer_addr_type) 434 403 { ··· 405 436 struct ipv6hdr *hdr; 406 437 struct lowpan_btle_dev *dev; 407 438 struct lowpan_peer *peer; 408 - bdaddr_t addr, *any = BDADDR_ANY; 409 - u8 *daddr = any->b; 439 + u8 *daddr; 410 440 int err, status = 0; 411 441 412 442 hdr = ipv6_hdr(skb); ··· 416 448 417 449 if (ipv6_addr_is_multicast(&ipv6_daddr)) { 418 450 lowpan_cb(skb)->chan = NULL; 451 + daddr = NULL; 419 452 } else { 420 - u8 addr_type; 453 + BT_DBG("dest IP %pI6c", &ipv6_daddr); 421 454 422 - /* Get destination BT device from skb. 423 - * If there is no such peer then discard the packet. 455 + /* The packet might be sent to 6lowpan interface 456 + * because of routing (either via default route 457 + * or user set route) so get peer according to 458 + * the destination address. 424 459 */ 425 - convert_dest_bdaddr(&ipv6_daddr, &addr, &addr_type); 426 - 427 - BT_DBG("dest addr %pMR type %d IP %pI6c", &addr, 428 - addr_type, &ipv6_daddr); 429 - 430 - peer = peer_lookup_ba(dev, &addr, addr_type); 460 + peer = peer_lookup_dst(dev, &ipv6_daddr, skb); 431 461 if (!peer) { 432 - /* The packet might be sent to 6lowpan interface 433 - * because of routing (either via default route 434 - * or user set route) so get peer according to 435 - * the destination address. 436 - */ 437 - peer = peer_lookup_dst(dev, &ipv6_daddr, skb); 438 - if (!peer) { 439 - BT_DBG("no such peer %pMR found", &addr); 440 - return -ENOENT; 441 - } 462 + BT_DBG("no such peer"); 463 + return -ENOENT; 442 464 } 443 465 444 466 daddr = peer->lladdr; 445 - *peer_addr = addr; 446 - *peer_addr_type = addr_type; 467 + peer_addr = &peer->chan->dst; 468 + *peer_addr_type = peer->chan->dst_type; 447 469 lowpan_cb(skb)->chan = peer->chan; 448 470 449 471 status = 1; ··· 675 717 return chan; 676 718 } 677 719 678 - static void set_ip_addr_bits(u8 addr_type, u8 *addr) 679 - { 680 - if (addr_type == BDADDR_LE_PUBLIC) 681 - *addr |= 0x02; 682 - else 683 - *addr &= ~0x02; 684 - } 685 - 686 720 static struct l2cap_chan *add_peer_chan(struct l2cap_chan *chan, 687 721 struct lowpan_btle_dev *dev) 688 722 { ··· 690 740 baswap((void *)peer->lladdr, &chan->dst); 691 741 692 742 lowpan_iphc_uncompress_eui48_lladdr(&peer->peer_addr, peer->lladdr); 693 - 694 - /* IPv6 address needs to have the U/L bit set properly so toggle 695 - * it back here. 696 - */ 697 - set_ip_addr_bits(chan->dst_type, (u8 *)&peer->peer_addr.s6_addr + 8); 698 743 699 744 spin_lock(&devices_lock); 700 745 INIT_LIST_HEAD(&peer->list);
+5 -1
net/ipv6/addrconf.c
··· 2077 2077 { 2078 2078 switch (dev->addr_len) { 2079 2079 case ETH_ALEN: 2080 - return addrconf_ifid_eui48(eui, dev); 2080 + memcpy(eui, dev->dev_addr, 3); 2081 + eui[3] = 0xFF; 2082 + eui[4] = 0xFE; 2083 + memcpy(eui + 5, dev->dev_addr + 3, 3); 2084 + break; 2081 2085 case EUI64_ADDR_LEN: 2082 2086 memcpy(eui, dev->dev_addr, EUI64_ADDR_LEN); 2083 2087 eui[0] ^= 2;