summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2017-03-12 04:19:37 -0400
committerMarcel Holtmann <marcel@holtmann.org>2017-04-12 16:02:36 -0400
commitfa09ae661fb5ab6f9826545d5128f2b7393bcf4a (patch)
tree3e97a905cfc5182279062b77b3be654db917876a
parent8a7a4b476719df1e06f8eae837b13bdf79908843 (diff)
6lowpan: Use netdev addr_len to determine lladdr len
This allow technologies such as Bluetooth to use its native lladdr which is eui48 instead of eui64 which was expected by functions like lowpan_header_decompress and lowpan_header_compress. Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--include/net/6lowpan.h19
-rw-r--r--net/6lowpan/iphc.c49
-rw-r--r--net/bluetooth/6lowpan.c42
3 files changed, 63 insertions, 47 deletions
diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h
index 5ab4c9901ccc..c5792cb6c3eb 100644
--- a/include/net/6lowpan.h
+++ b/include/net/6lowpan.h
@@ -198,6 +198,25 @@ static inline void lowpan_iphc_uncompress_eui64_lladdr(struct in6_addr *ipaddr,
198 ipaddr->s6_addr[8] ^= 0x02; 198 ipaddr->s6_addr[8] ^= 0x02;
199} 199}
200 200
201static inline void lowpan_iphc_uncompress_eui48_lladdr(struct in6_addr *ipaddr,
202 const void *lladdr)
203{
204 /* fe:80::XXXX:XXff:feXX:XXXX
205 * \_________________/
206 * hwaddr
207 */
208 ipaddr->s6_addr[0] = 0xFE;
209 ipaddr->s6_addr[1] = 0x80;
210 memcpy(&ipaddr->s6_addr[8], lladdr, 3);
211 ipaddr->s6_addr[11] = 0xFF;
212 ipaddr->s6_addr[12] = 0xFE;
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}
219
201#ifdef DEBUG 220#ifdef DEBUG
202/* print data in line */ 221/* print data in line */
203static inline void raw_dump_inline(const char *caller, char *msg, 222static inline void raw_dump_inline(const char *caller, char *msg,
diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
index fb5f6fa8f1df..6b1042e21656 100644
--- a/net/6lowpan/iphc.c
+++ b/net/6lowpan/iphc.c
@@ -278,6 +278,23 @@ lowpan_iphc_ctx_get_by_mcast_addr(const struct net_device *dev,
278 return ret; 278 return ret;
279} 279}
280 280
281static void lowpan_iphc_uncompress_lladdr(const struct net_device *dev,
282 struct in6_addr *ipaddr,
283 const void *lladdr)
284{
285 switch (dev->addr_len) {
286 case ETH_ALEN:
287 lowpan_iphc_uncompress_eui48_lladdr(ipaddr, lladdr);
288 break;
289 case EUI64_ADDR_LEN:
290 lowpan_iphc_uncompress_eui64_lladdr(ipaddr, lladdr);
291 break;
292 default:
293 WARN_ON_ONCE(1);
294 break;
295 }
296}
297
281/* Uncompress address function for source and 298/* Uncompress address function for source and
282 * destination address(non-multicast). 299 * destination address(non-multicast).
283 * 300 *
@@ -320,7 +337,7 @@ static int lowpan_iphc_uncompress_addr(struct sk_buff *skb,
320 lowpan_iphc_uncompress_802154_lladdr(ipaddr, lladdr); 337 lowpan_iphc_uncompress_802154_lladdr(ipaddr, lladdr);
321 break; 338 break;
322 default: 339 default:
323 lowpan_iphc_uncompress_eui64_lladdr(ipaddr, lladdr); 340 lowpan_iphc_uncompress_lladdr(dev, ipaddr, lladdr);
324 break; 341 break;
325 } 342 }
326 break; 343 break;
@@ -381,7 +398,7 @@ static int lowpan_iphc_uncompress_ctx_addr(struct sk_buff *skb,
381 lowpan_iphc_uncompress_802154_lladdr(ipaddr, lladdr); 398 lowpan_iphc_uncompress_802154_lladdr(ipaddr, lladdr);
382 break; 399 break;
383 default: 400 default:
384 lowpan_iphc_uncompress_eui64_lladdr(ipaddr, lladdr); 401 lowpan_iphc_uncompress_lladdr(dev, ipaddr, lladdr);
385 break; 402 break;
386 } 403 }
387 ipv6_addr_prefix_copy(ipaddr, &ctx->pfx, ctx->plen); 404 ipv6_addr_prefix_copy(ipaddr, &ctx->pfx, ctx->plen);
@@ -810,6 +827,21 @@ lowpan_iphc_compress_ctx_802154_lladdr(const struct in6_addr *ipaddr,
810 return lladdr_compress; 827 return lladdr_compress;
811} 828}
812 829
830static bool lowpan_iphc_addr_equal(const struct net_device *dev,
831 const struct lowpan_iphc_ctx *ctx,
832 const struct in6_addr *ipaddr,
833 const void *lladdr)
834{
835 struct in6_addr tmp = {};
836
837 lowpan_iphc_uncompress_lladdr(dev, &tmp, lladdr);
838
839 if (ctx)
840 ipv6_addr_prefix_copy(&tmp, &ctx->pfx, ctx->plen);
841
842 return ipv6_addr_equal(&tmp, ipaddr);
843}
844
813static u8 lowpan_compress_ctx_addr(u8 **hc_ptr, const struct net_device *dev, 845static u8 lowpan_compress_ctx_addr(u8 **hc_ptr, const struct net_device *dev,
814 const struct in6_addr *ipaddr, 846 const struct in6_addr *ipaddr,
815 const struct lowpan_iphc_ctx *ctx, 847 const struct lowpan_iphc_ctx *ctx,
@@ -827,13 +859,7 @@ static u8 lowpan_compress_ctx_addr(u8 **hc_ptr, const struct net_device *dev,
827 } 859 }
828 break; 860 break;
829 default: 861 default:
830 /* check for SAM/DAM = 11 */ 862 if (lowpan_iphc_addr_equal(dev, ctx, ipaddr, lladdr)) {
831 memcpy(&tmp.s6_addr[8], lladdr, EUI64_ADDR_LEN);
832 /* second bit-flip (Universe/Local) is done according RFC2464 */
833 tmp.s6_addr[8] ^= 0x02;
834 /* context information are always used */
835 ipv6_addr_prefix_copy(&tmp, &ctx->pfx, ctx->plen);
836 if (ipv6_addr_equal(&tmp, ipaddr)) {
837 dam = LOWPAN_IPHC_DAM_11; 863 dam = LOWPAN_IPHC_DAM_11;
838 goto out; 864 goto out;
839 } 865 }
@@ -929,11 +955,12 @@ static u8 lowpan_compress_addr_64(u8 **hc_ptr, const struct net_device *dev,
929 } 955 }
930 break; 956 break;
931 default: 957 default:
932 if (is_addr_mac_addr_based(ipaddr, lladdr)) { 958 if (lowpan_iphc_addr_equal(dev, NULL, ipaddr, lladdr)) {
933 dam = LOWPAN_IPHC_DAM_11; /* 0-bits */ 959 dam = LOWPAN_IPHC_DAM_11;
934 pr_debug("address compression 0 bits\n"); 960 pr_debug("address compression 0 bits\n");
935 goto out; 961 goto out;
936 } 962 }
963
937 break; 964 break;
938 } 965 }
939 966
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index bad0e9d1ea20..54bf4d765a7d 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -64,7 +64,7 @@ struct lowpan_peer {
64 struct l2cap_chan *chan; 64 struct l2cap_chan *chan;
65 65
66 /* peer addresses in various formats */ 66 /* peer addresses in various formats */
67 unsigned char eui64_addr[EUI64_ADDR_LEN]; 67 unsigned char lladdr[ETH_ALEN];
68 struct in6_addr peer_addr; 68 struct in6_addr peer_addr;
69}; 69};
70 70
@@ -80,8 +80,6 @@ struct lowpan_btle_dev {
80 struct delayed_work notify_peers; 80 struct delayed_work notify_peers;
81}; 81};
82 82
83static void set_addr(u8 *eui, u8 *addr, u8 addr_type);
84
85static inline struct lowpan_btle_dev * 83static inline struct lowpan_btle_dev *
86lowpan_btle_dev(const struct net_device *netdev) 84lowpan_btle_dev(const struct net_device *netdev)
87{ 85{
@@ -277,7 +275,6 @@ static int iphc_decompress(struct sk_buff *skb, struct net_device *netdev,
277 const u8 *saddr; 275 const u8 *saddr;
278 struct lowpan_btle_dev *dev; 276 struct lowpan_btle_dev *dev;
279 struct lowpan_peer *peer; 277 struct lowpan_peer *peer;
280 unsigned char eui64_daddr[EUI64_ADDR_LEN];
281 278
282 dev = lowpan_btle_dev(netdev); 279 dev = lowpan_btle_dev(netdev);
283 280
@@ -287,10 +284,9 @@ static int iphc_decompress(struct sk_buff *skb, struct net_device *netdev,
287 if (!peer) 284 if (!peer)
288 return -EINVAL; 285 return -EINVAL;
289 286
290 saddr = peer->eui64_addr; 287 saddr = peer->lladdr;
291 set_addr(&eui64_daddr[0], chan->src.b, chan->src_type);
292 288
293 return lowpan_header_decompress(skb, netdev, &eui64_daddr, saddr); 289 return lowpan_header_decompress(skb, netdev, netdev->dev_addr, saddr);
294} 290}
295 291
296static int recv_pkt(struct sk_buff *skb, struct net_device *dev, 292static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
@@ -477,7 +473,7 @@ static int setup_header(struct sk_buff *skb, struct net_device *netdev,
477 } 473 }
478 } 474 }
479 475
480 daddr = peer->eui64_addr; 476 daddr = peer->lladdr;
481 *peer_addr = addr; 477 *peer_addr = addr;
482 *peer_addr_type = addr_type; 478 *peer_addr_type = addr_type;
483 lowpan_cb(skb)->chan = peer->chan; 479 lowpan_cb(skb)->chan = peer->chan;
@@ -663,27 +659,6 @@ static struct device_type bt_type = {
663 .name = "bluetooth", 659 .name = "bluetooth",
664}; 660};
665 661
666static void set_addr(u8 *eui, u8 *addr, u8 addr_type)
667{
668 /* addr is the BT address in little-endian format */
669 eui[0] = addr[5];
670 eui[1] = addr[4];
671 eui[2] = addr[3];
672 eui[3] = 0xFF;
673 eui[4] = 0xFE;
674 eui[5] = addr[2];
675 eui[6] = addr[1];
676 eui[7] = addr[0];
677
678 /* Universal/local bit set, BT 6lowpan draft ch. 3.2.1 */
679 if (addr_type == BDADDR_LE_PUBLIC)
680 eui[0] &= ~0x02;
681 else
682 eui[0] |= 0x02;
683
684 BT_DBG("type %d addr %*phC", addr_type, 8, eui);
685}
686
687static void ifup(struct net_device *netdev) 662static void ifup(struct net_device *netdev)
688{ 663{
689 int err; 664 int err;
@@ -762,14 +737,9 @@ static struct l2cap_chan *add_peer_chan(struct l2cap_chan *chan,
762 peer->chan = chan; 737 peer->chan = chan;
763 memset(&peer->peer_addr, 0, sizeof(struct in6_addr)); 738 memset(&peer->peer_addr, 0, sizeof(struct in6_addr));
764 739
765 /* RFC 2464 ch. 5 */ 740 baswap((void *)peer->lladdr, &chan->dst);
766 peer->peer_addr.s6_addr[0] = 0xFE;
767 peer->peer_addr.s6_addr[1] = 0x80;
768 set_addr((u8 *)&peer->peer_addr.s6_addr + 8, chan->dst.b,
769 chan->dst_type);
770 741
771 memcpy(&peer->eui64_addr, (u8 *)&peer->peer_addr.s6_addr + 8, 742 lowpan_iphc_uncompress_eui48_lladdr(&peer->peer_addr, peer->lladdr);
772 EUI64_ADDR_LEN);
773 743
774 /* IPv6 address needs to have the U/L bit set properly so toggle 744 /* IPv6 address needs to have the U/L bit set properly so toggle
775 * it back here. 745 * it back here.