summaryrefslogtreecommitdiffstats
path: root/net/6lowpan
diff options
context:
space:
mode:
authorAlexander Aring <alex.aring@gmail.com>2015-10-13 07:42:58 -0400
committerMarcel Holtmann <marcel@holtmann.org>2015-10-20 18:49:24 -0400
commit8911d7748ca360ef96cb207cc5165eb9c08669e5 (patch)
treeed912fd4c9021f1f937eece443d0be1173b9c5c1 /net/6lowpan
parenta6f773891a836abfa16fcbb8af14c29c3e109336 (diff)
6lowpan: cleanup lowpan_header_decompress
This patch changes the lowpan_header_decompress function by removing inklayer related information from parameters. This is currently for supporting short and extended address for iphc handling in 802154. We don't support short address handling anyway right now, but there exists already code for handling short addresses in lowpan_header_decompress. The address parameters are also changed to a void pointer, so 6LoWPAN linklayer specific code can put complex structures as these parameters and cast it again inside the generic code by evaluating linklayer type before. The order is also changed by destination address at first and then source address, which is the same like all others functions where destination is always the first, memcpy, dev_hard_header, lowpan_header_compress, etc. This patch also moves the fetching of iphc values from 6LoWPAN linklayer specific code into the generic branch. Signed-off-by: Alexander Aring <alex.aring@gmail.com> Acked-by: Jukka Rissanen <jukka.rissanen@linux.intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/6lowpan')
-rw-r--r--net/6lowpan/iphc.c113
-rw-r--r--net/6lowpan/nhc.c3
-rw-r--r--net/6lowpan/nhc.h3
3 files changed, 73 insertions, 46 deletions
diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
index 4e4af8c82296..8f967d3b494e 100644
--- a/net/6lowpan/iphc.c
+++ b/net/6lowpan/iphc.c
@@ -49,21 +49,71 @@
49#include <linux/bitops.h> 49#include <linux/bitops.h>
50#include <linux/if_arp.h> 50#include <linux/if_arp.h>
51#include <linux/netdevice.h> 51#include <linux/netdevice.h>
52
52#include <net/6lowpan.h> 53#include <net/6lowpan.h>
53#include <net/ipv6.h> 54#include <net/ipv6.h>
54#include <net/af_ieee802154.h> 55
56/* special link-layer handling */
57#include <net/mac802154.h>
55 58
56#include "nhc.h" 59#include "nhc.h"
57 60
61static inline void iphc_uncompress_eui64_lladdr(struct in6_addr *ipaddr,
62 const void *lladdr)
63{
64 /* fe:80::XXXX:XXXX:XXXX:XXXX
65 * \_________________/
66 * hwaddr
67 */
68 ipaddr->s6_addr[0] = 0xFE;
69 ipaddr->s6_addr[1] = 0x80;
70 memcpy(&ipaddr->s6_addr[8], lladdr, EUI64_ADDR_LEN);
71 /* second bit-flip (Universe/Local)
72 * is done according RFC2464
73 */
74 ipaddr->s6_addr[8] ^= 0x02;
75}
76
77static inline void iphc_uncompress_802154_lladdr(struct in6_addr *ipaddr,
78 const void *lladdr)
79{
80 const struct ieee802154_addr *addr = lladdr;
81 u8 eui64[EUI64_ADDR_LEN] = { };
82
83 switch (addr->mode) {
84 case IEEE802154_ADDR_LONG:
85 ieee802154_le64_to_be64(eui64, &addr->extended_addr);
86 iphc_uncompress_eui64_lladdr(ipaddr, eui64);
87 break;
88 case IEEE802154_ADDR_SHORT:
89 /* fe:80::ff:fe00:XXXX
90 * \__/
91 * short_addr
92 *
93 * Universe/Local bit is zero.
94 */
95 ipaddr->s6_addr[0] = 0xFE;
96 ipaddr->s6_addr[1] = 0x80;
97 ipaddr->s6_addr[11] = 0xFF;
98 ipaddr->s6_addr[12] = 0xFE;
99 ieee802154_le16_to_be16(&ipaddr->s6_addr16[7],
100 &addr->short_addr);
101 break;
102 default:
103 /* should never handled and filtered by 802154 6lowpan */
104 WARN_ON_ONCE(1);
105 break;
106 }
107}
108
58/* Uncompress address function for source and 109/* Uncompress address function for source and
59 * destination address(non-multicast). 110 * destination address(non-multicast).
60 * 111 *
61 * address_mode is sam value or dam value. 112 * address_mode is sam value or dam value.
62 */ 113 */
63static int uncompress_addr(struct sk_buff *skb, 114static int uncompress_addr(struct sk_buff *skb, const struct net_device *dev,
64 struct in6_addr *ipaddr, const u8 address_mode, 115 struct in6_addr *ipaddr, u8 address_mode,
65 const u8 *lladdr, const u8 addr_type, 116 const void *lladdr)
66 const u8 addr_len)
67{ 117{
68 bool fail; 118 bool fail;
69 119
@@ -88,36 +138,13 @@ static int uncompress_addr(struct sk_buff *skb,
88 break; 138 break;
89 case LOWPAN_IPHC_ADDR_03: 139 case LOWPAN_IPHC_ADDR_03:
90 fail = false; 140 fail = false;
91 switch (addr_type) { 141 switch (lowpan_priv(dev)->lltype) {
92 case IEEE802154_ADDR_LONG: 142 case LOWPAN_LLTYPE_IEEE802154:
93 /* fe:80::XXXX:XXXX:XXXX:XXXX 143 iphc_uncompress_802154_lladdr(ipaddr, lladdr);
94 * \_________________/
95 * hwaddr
96 */
97 ipaddr->s6_addr[0] = 0xFE;
98 ipaddr->s6_addr[1] = 0x80;
99 memcpy(&ipaddr->s6_addr[8], lladdr, addr_len);
100 /* second bit-flip (Universe/Local)
101 * is done according RFC2464
102 */
103 ipaddr->s6_addr[8] ^= 0x02;
104 break;
105 case IEEE802154_ADDR_SHORT:
106 /* fe:80::ff:fe00:XXXX
107 * \__/
108 * short_addr
109 *
110 * Universe/Local bit is zero.
111 */
112 ipaddr->s6_addr[0] = 0xFE;
113 ipaddr->s6_addr[1] = 0x80;
114 ipaddr->s6_addr[11] = 0xFF;
115 ipaddr->s6_addr[12] = 0xFE;
116 ipaddr->s6_addr16[7] = htons(*((u16 *)lladdr));
117 break; 144 break;
118 default: 145 default:
119 pr_debug("Invalid addr_type set\n"); 146 iphc_uncompress_eui64_lladdr(ipaddr, lladdr);
120 return -EINVAL; 147 break;
121 } 148 }
122 break; 149 break;
123 default: 150 default:
@@ -228,20 +255,20 @@ static int lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
228/* TTL uncompression values */ 255/* TTL uncompression values */
229static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 }; 256static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 };
230 257
231int 258int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev,
232lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, 259 const void *daddr, const void *saddr)
233 const u8 *saddr, const u8 saddr_type,
234 const u8 saddr_len, const u8 *daddr,
235 const u8 daddr_type, const u8 daddr_len,
236 u8 iphc0, u8 iphc1)
237{ 260{
238 struct ipv6hdr hdr = {}; 261 struct ipv6hdr hdr = {};
239 u8 tmp, num_context = 0; 262 u8 iphc0, iphc1, tmp, num_context = 0;
240 int err; 263 int err;
241 264
242 raw_dump_table(__func__, "raw skb data dump uncompressed", 265 raw_dump_table(__func__, "raw skb data dump uncompressed",
243 skb->data, skb->len); 266 skb->data, skb->len);
244 267
268 if (lowpan_fetch_skb_u8(skb, &iphc0) ||
269 lowpan_fetch_skb_u8(skb, &iphc1))
270 return -EINVAL;
271
245 /* another if the CID flag is set */ 272 /* another if the CID flag is set */
246 if (iphc1 & LOWPAN_IPHC_CID) { 273 if (iphc1 & LOWPAN_IPHC_CID) {
247 pr_debug("CID flag is set, increase header with one\n"); 274 pr_debug("CID flag is set, increase header with one\n");
@@ -323,8 +350,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
323 } else { 350 } else {
324 /* Source address uncompression */ 351 /* Source address uncompression */
325 pr_debug("source address stateless compression\n"); 352 pr_debug("source address stateless compression\n");
326 err = uncompress_addr(skb, &hdr.saddr, tmp, saddr, 353 err = uncompress_addr(skb, dev, &hdr.saddr, tmp, saddr);
327 saddr_type, saddr_len);
328 } 354 }
329 355
330 /* Check on error of previous branch */ 356 /* Check on error of previous branch */
@@ -347,8 +373,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
347 return -EINVAL; 373 return -EINVAL;
348 } 374 }
349 } else { 375 } else {
350 err = uncompress_addr(skb, &hdr.daddr, tmp, daddr, 376 err = uncompress_addr(skb, dev, &hdr.daddr, tmp, daddr);
351 daddr_type, daddr_len);
352 pr_debug("dest: stateless compression mode %d dest %pI6c\n", 377 pr_debug("dest: stateless compression mode %d dest %pI6c\n",
353 tmp, &hdr.daddr); 378 tmp, &hdr.daddr);
354 if (err) 379 if (err)
diff --git a/net/6lowpan/nhc.c b/net/6lowpan/nhc.c
index fd20fc51a7c4..589224e458dd 100644
--- a/net/6lowpan/nhc.c
+++ b/net/6lowpan/nhc.c
@@ -157,7 +157,8 @@ out:
157 return ret; 157 return ret;
158} 158}
159 159
160int lowpan_nhc_do_uncompression(struct sk_buff *skb, struct net_device *dev, 160int lowpan_nhc_do_uncompression(struct sk_buff *skb,
161 const struct net_device *dev,
161 struct ipv6hdr *hdr) 162 struct ipv6hdr *hdr)
162{ 163{
163 struct lowpan_nhc *nhc; 164 struct lowpan_nhc *nhc;
diff --git a/net/6lowpan/nhc.h b/net/6lowpan/nhc.h
index c249f17fa37b..e3a564421898 100644
--- a/net/6lowpan/nhc.h
+++ b/net/6lowpan/nhc.h
@@ -119,7 +119,8 @@ int lowpan_nhc_do_compression(struct sk_buff *skb, const struct ipv6hdr *hdr,
119 * @dev: netdevice for print logging information. 119 * @dev: netdevice for print logging information.
120 * @hdr: ipv6hdr for setting nexthdr value. 120 * @hdr: ipv6hdr for setting nexthdr value.
121 */ 121 */
122int lowpan_nhc_do_uncompression(struct sk_buff *skb, struct net_device *dev, 122int lowpan_nhc_do_uncompression(struct sk_buff *skb,
123 const struct net_device *dev,
123 struct ipv6hdr *hdr); 124 struct ipv6hdr *hdr);
124 125
125/** 126/**