aboutsummaryrefslogtreecommitdiffstats
path: root/net/6lowpan
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-08-05 16:18:20 -0400
committerDavid S. Miller <davem@davemloft.net>2014-08-05 16:18:20 -0400
commitaef4f5b6db654e512ebcccab2a6e50424c05d2f9 (patch)
tree4daaee5ac85d1128233a45908dac5212f38ec7aa /net/6lowpan
parent61ab9efddf51cbc0d57356a4d650785cf5721fbe (diff)
parentdc6be9f54a4ecb0a09765d1f515ed947d86b7528 (diff)
Merge tag 'master-2014-07-31' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
Conflicts: net/6lowpan/iphc.c Minor conflicts in iphc.c were changes overlapping with some style cleanups. John W. Linville says: ==================== Please pull this last(?) batch of wireless change intended for the 3.17 stream... For the NFC bits, Samuel says: "This is a rather quiet one, we have: - A new driver from ST Microelectronics for their NCI ST21NFCB, including device tree support. - p2p support for the ST21NFCA driver - A few fixes an enhancements for the NFC digital laye" For the Atheros bits, Kalle says: "Michal and Janusz did some important RX aggregation fixes, basically we were missing RX reordering altogether. The 10.1 firmware doesn't support Ad-Hoc mode and Michal fixed ath10k so that it doesn't advertise Ad-Hoc support with that firmware. Also he implemented a workaround for a KVM issue." For the Bluetooth bits, Gustavo and Johan say: "To quote Gustavo from his previous request: 'Some last minute fixes for -next. We have a fix for a use after free in RFCOMM, another fix to an issue with ADV_DIRECT_IND and one for ADV_IND with auto-connection handling. Last, we added support for reading the codec and MWS setting for controllers that support these features.' Additionally there are fixes to LE scanning, an update to conform to the 4.1 core specification as well as fixes for tracking the page scan state. All of these fixes are important for 3.17." And, "We've got: - 6lowpan fixes/cleanups - A couple crash fixes, one for the Marvell HCI driver and another in LE SMP. - Fix for an incorrect connected state check - Fix for the bondable requirement during pairing (an issue which had crept in because of using "pairable" when in fact the actual meaning was "bondable" (these have different meanings in Bluetooth)" Along with those are some late-breaking hardware support patches in brcmfmac and b43 as well as a stray ath9k patch. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/6lowpan')
-rw-r--r--net/6lowpan/iphc.c212
1 files changed, 105 insertions, 107 deletions
diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
index a1b7117a9600..142eef55c9e2 100644
--- a/net/6lowpan/iphc.c
+++ b/net/6lowpan/iphc.c
@@ -177,8 +177,8 @@ static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr,
177 struct sk_buff *new; 177 struct sk_buff *new;
178 int stat; 178 int stat;
179 179
180 new = skb_copy_expand(skb, sizeof(struct ipv6hdr), 180 new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb),
181 skb_tailroom(skb), GFP_ATOMIC); 181 GFP_ATOMIC);
182 kfree_skb(skb); 182 kfree_skb(skb);
183 183
184 if (!new) 184 if (!new)
@@ -205,10 +205,9 @@ static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr,
205/* Uncompress function for multicast destination address, 205/* Uncompress function for multicast destination address,
206 * when M bit is set. 206 * when M bit is set.
207 */ 207 */
208static int 208static int lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
209lowpan_uncompress_multicast_daddr(struct sk_buff *skb, 209 struct in6_addr *ipaddr,
210 struct in6_addr *ipaddr, 210 const u8 dam)
211 const u8 dam)
212{ 211{
213 bool fail; 212 bool fail;
214 213
@@ -254,41 +253,41 @@ lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
254 } 253 }
255 254
256 raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is", 255 raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is",
257 ipaddr->s6_addr, 16); 256 ipaddr->s6_addr, 16);
258 257
259 return 0; 258 return 0;
260} 259}
261 260
262static int 261static int uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
263uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
264{ 262{
265 bool fail; 263 bool fail;
266 u8 tmp = 0, val = 0; 264 u8 tmp = 0, val = 0;
267 265
268 if (!uh) 266 fail = lowpan_fetch_skb(skb, &tmp, sizeof(tmp));
269 goto err;
270
271 fail = lowpan_fetch_skb(skb, &tmp, 1);
272 267
273 if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) { 268 if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) {
274 pr_debug("UDP header uncompression\n"); 269 pr_debug("UDP header uncompression\n");
275 switch (tmp & LOWPAN_NHC_UDP_CS_P_11) { 270 switch (tmp & LOWPAN_NHC_UDP_CS_P_11) {
276 case LOWPAN_NHC_UDP_CS_P_00: 271 case LOWPAN_NHC_UDP_CS_P_00:
277 fail |= lowpan_fetch_skb(skb, &uh->source, 2); 272 fail |= lowpan_fetch_skb(skb, &uh->source,
278 fail |= lowpan_fetch_skb(skb, &uh->dest, 2); 273 sizeof(uh->source));
274 fail |= lowpan_fetch_skb(skb, &uh->dest,
275 sizeof(uh->dest));
279 break; 276 break;
280 case LOWPAN_NHC_UDP_CS_P_01: 277 case LOWPAN_NHC_UDP_CS_P_01:
281 fail |= lowpan_fetch_skb(skb, &uh->source, 2); 278 fail |= lowpan_fetch_skb(skb, &uh->source,
282 fail |= lowpan_fetch_skb(skb, &val, 1); 279 sizeof(uh->source));
280 fail |= lowpan_fetch_skb(skb, &val, sizeof(val));
283 uh->dest = htons(val + LOWPAN_NHC_UDP_8BIT_PORT); 281 uh->dest = htons(val + LOWPAN_NHC_UDP_8BIT_PORT);
284 break; 282 break;
285 case LOWPAN_NHC_UDP_CS_P_10: 283 case LOWPAN_NHC_UDP_CS_P_10:
286 fail |= lowpan_fetch_skb(skb, &val, 1); 284 fail |= lowpan_fetch_skb(skb, &val, sizeof(val));
287 uh->source = htons(val + LOWPAN_NHC_UDP_8BIT_PORT); 285 uh->source = htons(val + LOWPAN_NHC_UDP_8BIT_PORT);
288 fail |= lowpan_fetch_skb(skb, &uh->dest, 2); 286 fail |= lowpan_fetch_skb(skb, &uh->dest,
287 sizeof(uh->dest));
289 break; 288 break;
290 case LOWPAN_NHC_UDP_CS_P_11: 289 case LOWPAN_NHC_UDP_CS_P_11:
291 fail |= lowpan_fetch_skb(skb, &val, 1); 290 fail |= lowpan_fetch_skb(skb, &val, sizeof(val));
292 uh->source = htons(LOWPAN_NHC_UDP_4BIT_PORT + 291 uh->source = htons(LOWPAN_NHC_UDP_4BIT_PORT +
293 (val >> 4)); 292 (val >> 4));
294 uh->dest = htons(LOWPAN_NHC_UDP_4BIT_PORT + 293 uh->dest = htons(LOWPAN_NHC_UDP_4BIT_PORT +
@@ -307,10 +306,11 @@ uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
307 pr_debug_ratelimited("checksum elided currently not supported\n"); 306 pr_debug_ratelimited("checksum elided currently not supported\n");
308 goto err; 307 goto err;
309 } else { 308 } else {
310 fail |= lowpan_fetch_skb(skb, &uh->check, 2); 309 fail |= lowpan_fetch_skb(skb, &uh->check,
310 sizeof(uh->check));
311 } 311 }
312 312
313 /* UDP lenght needs to be infered from the lower layers 313 /* UDP length needs to be infered from the lower layers
314 * here, we obtain the hint from the remaining size of the 314 * here, we obtain the hint from the remaining size of the
315 * frame 315 * frame
316 */ 316 */
@@ -333,9 +333,8 @@ err:
333static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 }; 333static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 };
334 334
335int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, 335int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
336 const u8 *saddr, const u8 saddr_type, 336 const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
337 const u8 saddr_len, const u8 *daddr, 337 const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
338 const u8 daddr_type, const u8 daddr_len,
339 u8 iphc0, u8 iphc1, skb_delivery_cb deliver_skb) 338 u8 iphc0, u8 iphc1, skb_delivery_cb deliver_skb)
340{ 339{
341 struct ipv6hdr hdr = {}; 340 struct ipv6hdr hdr = {};
@@ -348,7 +347,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
348 /* another if the CID flag is set */ 347 /* another if the CID flag is set */
349 if (iphc1 & LOWPAN_IPHC_CID) { 348 if (iphc1 & LOWPAN_IPHC_CID) {
350 pr_debug("CID flag is set, increase header with one\n"); 349 pr_debug("CID flag is set, increase header with one\n");
351 if (lowpan_fetch_skb_u8(skb, &num_context)) 350 if (lowpan_fetch_skb(skb, &num_context, sizeof(num_context)))
352 goto drop; 351 goto drop;
353 } 352 }
354 353
@@ -360,7 +359,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
360 * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes) 359 * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes)
361 */ 360 */
362 case 0: /* 00b */ 361 case 0: /* 00b */
363 if (lowpan_fetch_skb_u8(skb, &tmp)) 362 if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
364 goto drop; 363 goto drop;
365 364
366 memcpy(&hdr.flow_lbl, &skb->data[0], 3); 365 memcpy(&hdr.flow_lbl, &skb->data[0], 3);
@@ -373,7 +372,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
373 * ECN + DSCP (1 byte), Flow Label is elided 372 * ECN + DSCP (1 byte), Flow Label is elided
374 */ 373 */
375 case 2: /* 10b */ 374 case 2: /* 10b */
376 if (lowpan_fetch_skb_u8(skb, &tmp)) 375 if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
377 goto drop; 376 goto drop;
378 377
379 hdr.priority = ((tmp >> 2) & 0x0f); 378 hdr.priority = ((tmp >> 2) & 0x0f);
@@ -383,7 +382,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
383 * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided 382 * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided
384 */ 383 */
385 case 1: /* 01b */ 384 case 1: /* 01b */
386 if (lowpan_fetch_skb_u8(skb, &tmp)) 385 if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
387 goto drop; 386 goto drop;
388 387
389 hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30); 388 hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30);
@@ -400,7 +399,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
400 /* Next Header */ 399 /* Next Header */
401 if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { 400 if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
402 /* Next header is carried inline */ 401 /* Next header is carried inline */
403 if (lowpan_fetch_skb_u8(skb, &(hdr.nexthdr))) 402 if (lowpan_fetch_skb(skb, &hdr.nexthdr, sizeof(hdr.nexthdr)))
404 goto drop; 403 goto drop;
405 404
406 pr_debug("NH flag is set, next header carried inline: %02x\n", 405 pr_debug("NH flag is set, next header carried inline: %02x\n",
@@ -411,7 +410,8 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
411 if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I) { 410 if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I) {
412 hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03]; 411 hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03];
413 } else { 412 } else {
414 if (lowpan_fetch_skb_u8(skb, &(hdr.hop_limit))) 413 if (lowpan_fetch_skb(skb, &hdr.hop_limit,
414 sizeof(hdr.hop_limit)))
415 goto drop; 415 goto drop;
416 } 416 }
417 417
@@ -421,8 +421,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
421 if (iphc1 & LOWPAN_IPHC_SAC) { 421 if (iphc1 & LOWPAN_IPHC_SAC) {
422 /* Source address context based uncompression */ 422 /* Source address context based uncompression */
423 pr_debug("SAC bit is set. Handle context based source address.\n"); 423 pr_debug("SAC bit is set. Handle context based source address.\n");
424 err = uncompress_context_based_src_addr( 424 err = uncompress_context_based_src_addr(skb, &hdr.saddr, tmp);
425 skb, &hdr.saddr, tmp);
426 } else { 425 } else {
427 /* Source address uncompression */ 426 /* Source address uncompression */
428 pr_debug("source address stateless compression\n"); 427 pr_debug("source address stateless compression\n");
@@ -443,8 +442,9 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
443 pr_debug("dest: context-based mcast compression\n"); 442 pr_debug("dest: context-based mcast compression\n");
444 /* TODO: implement this */ 443 /* TODO: implement this */
445 } else { 444 } else {
446 err = lowpan_uncompress_multicast_daddr( 445 err = lowpan_uncompress_multicast_daddr(skb, &hdr.daddr,
447 skb, &hdr.daddr, tmp); 446 tmp);
447
448 if (err) 448 if (err)
449 goto drop; 449 goto drop;
450 } 450 }
@@ -497,8 +497,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
497 hdr.version, ntohs(hdr.payload_len), hdr.nexthdr, 497 hdr.version, ntohs(hdr.payload_len), hdr.nexthdr,
498 hdr.hop_limit, &hdr.daddr); 498 hdr.hop_limit, &hdr.daddr);
499 499
500 raw_dump_table(__func__, "raw header dump", 500 raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr));
501 (u8 *)&hdr, sizeof(hdr));
502 501
503 return skb_deliver(skb, &hdr, dev, deliver_skb); 502 return skb_deliver(skb, &hdr, dev, deliver_skb);
504 503
@@ -508,7 +507,7 @@ drop:
508} 507}
509EXPORT_SYMBOL_GPL(lowpan_process_data); 508EXPORT_SYMBOL_GPL(lowpan_process_data);
510 509
511static u8 lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift, 510static u8 lowpan_compress_addr_64(u8 **hc_ptr, u8 shift,
512 const struct in6_addr *ipaddr, 511 const struct in6_addr *ipaddr,
513 const unsigned char *lladdr) 512 const unsigned char *lladdr)
514{ 513{
@@ -519,24 +518,22 @@ static u8 lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift,
519 pr_debug("address compression 0 bits\n"); 518 pr_debug("address compression 0 bits\n");
520 } else if (lowpan_is_iid_16_bit_compressable(ipaddr)) { 519 } else if (lowpan_is_iid_16_bit_compressable(ipaddr)) {
521 /* compress IID to 16 bits xxxx::XXXX */ 520 /* compress IID to 16 bits xxxx::XXXX */
522 memcpy(*hc06_ptr, &ipaddr->s6_addr16[7], 2); 521 lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[7], 2);
523 *hc06_ptr += 2;
524 val = 2; /* 16-bits */ 522 val = 2; /* 16-bits */
525 raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)", 523 raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)",
526 *hc06_ptr - 2, 2); 524 *hc_ptr - 2, 2);
527 } else { 525 } else {
528 /* do not compress IID => xxxx::IID */ 526 /* do not compress IID => xxxx::IID */
529 memcpy(*hc06_ptr, &ipaddr->s6_addr16[4], 8); 527 lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[4], 8);
530 *hc06_ptr += 8;
531 val = 1; /* 64-bits */ 528 val = 1; /* 64-bits */
532 raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)", 529 raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)",
533 *hc06_ptr - 8, 8); 530 *hc_ptr - 8, 8);
534 } 531 }
535 532
536 return rol8(val, shift); 533 return rol8(val, shift);
537} 534}
538 535
539static void compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb) 536static void compress_udp_header(u8 **hc_ptr, struct sk_buff *skb)
540{ 537{
541 struct udphdr *uh = udp_hdr(skb); 538 struct udphdr *uh = udp_hdr(skb);
542 u8 tmp; 539 u8 tmp;
@@ -548,46 +545,46 @@ static void compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb)
548 pr_debug("UDP header: both ports compression to 4 bits\n"); 545 pr_debug("UDP header: both ports compression to 4 bits\n");
549 /* compression value */ 546 /* compression value */
550 tmp = LOWPAN_NHC_UDP_CS_P_11; 547 tmp = LOWPAN_NHC_UDP_CS_P_11;
551 lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); 548 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
552 /* source and destination port */ 549 /* source and destination port */
553 tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_4BIT_PORT + 550 tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_4BIT_PORT +
554 ((ntohs(uh->source) - LOWPAN_NHC_UDP_4BIT_PORT) << 4); 551 ((ntohs(uh->source) - LOWPAN_NHC_UDP_4BIT_PORT) << 4);
555 lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); 552 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
556 } else if ((ntohs(uh->dest) & LOWPAN_NHC_UDP_8BIT_MASK) == 553 } else if ((ntohs(uh->dest) & LOWPAN_NHC_UDP_8BIT_MASK) ==
557 LOWPAN_NHC_UDP_8BIT_PORT) { 554 LOWPAN_NHC_UDP_8BIT_PORT) {
558 pr_debug("UDP header: remove 8 bits of dest\n"); 555 pr_debug("UDP header: remove 8 bits of dest\n");
559 /* compression value */ 556 /* compression value */
560 tmp = LOWPAN_NHC_UDP_CS_P_01; 557 tmp = LOWPAN_NHC_UDP_CS_P_01;
561 lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); 558 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
562 /* source port */ 559 /* source port */
563 lowpan_push_hc_data(hc06_ptr, &uh->source, sizeof(uh->source)); 560 lowpan_push_hc_data(hc_ptr, &uh->source, sizeof(uh->source));
564 /* destination port */ 561 /* destination port */
565 tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_8BIT_PORT; 562 tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_8BIT_PORT;
566 lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); 563 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
567 } else if ((ntohs(uh->source) & LOWPAN_NHC_UDP_8BIT_MASK) == 564 } else if ((ntohs(uh->source) & LOWPAN_NHC_UDP_8BIT_MASK) ==
568 LOWPAN_NHC_UDP_8BIT_PORT) { 565 LOWPAN_NHC_UDP_8BIT_PORT) {
569 pr_debug("UDP header: remove 8 bits of source\n"); 566 pr_debug("UDP header: remove 8 bits of source\n");
570 /* compression value */ 567 /* compression value */
571 tmp = LOWPAN_NHC_UDP_CS_P_10; 568 tmp = LOWPAN_NHC_UDP_CS_P_10;
572 lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); 569 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
573 /* source port */ 570 /* source port */
574 tmp = ntohs(uh->source) - LOWPAN_NHC_UDP_8BIT_PORT; 571 tmp = ntohs(uh->source) - LOWPAN_NHC_UDP_8BIT_PORT;
575 lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); 572 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
576 /* destination port */ 573 /* destination port */
577 lowpan_push_hc_data(hc06_ptr, &uh->dest, sizeof(uh->dest)); 574 lowpan_push_hc_data(hc_ptr, &uh->dest, sizeof(uh->dest));
578 } else { 575 } else {
579 pr_debug("UDP header: can't compress\n"); 576 pr_debug("UDP header: can't compress\n");
580 /* compression value */ 577 /* compression value */
581 tmp = LOWPAN_NHC_UDP_CS_P_00; 578 tmp = LOWPAN_NHC_UDP_CS_P_00;
582 lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); 579 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
583 /* source port */ 580 /* source port */
584 lowpan_push_hc_data(hc06_ptr, &uh->source, sizeof(uh->source)); 581 lowpan_push_hc_data(hc_ptr, &uh->source, sizeof(uh->source));
585 /* destination port */ 582 /* destination port */
586 lowpan_push_hc_data(hc06_ptr, &uh->dest, sizeof(uh->dest)); 583 lowpan_push_hc_data(hc_ptr, &uh->dest, sizeof(uh->dest));
587 } 584 }
588 585
589 /* checksum is always inline */ 586 /* checksum is always inline */
590 lowpan_push_hc_data(hc06_ptr, &uh->check, sizeof(uh->check)); 587 lowpan_push_hc_data(hc_ptr, &uh->check, sizeof(uh->check));
591 588
592 /* skip the UDP header */ 589 /* skip the UDP header */
593 skb_pull(skb, sizeof(struct udphdr)); 590 skb_pull(skb, sizeof(struct udphdr));
@@ -597,15 +594,16 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
597 unsigned short type, const void *_daddr, 594 unsigned short type, const void *_daddr,
598 const void *_saddr, unsigned int len) 595 const void *_saddr, unsigned int len)
599{ 596{
600 u8 tmp, iphc0, iphc1, *hc06_ptr; 597 u8 tmp, iphc0, iphc1, *hc_ptr;
601 struct ipv6hdr *hdr; 598 struct ipv6hdr *hdr;
602 u8 head[100] = {}; 599 u8 head[100] = {};
600 int addr_type;
603 601
604 if (type != ETH_P_IPV6) 602 if (type != ETH_P_IPV6)
605 return -EINVAL; 603 return -EINVAL;
606 604
607 hdr = ipv6_hdr(skb); 605 hdr = ipv6_hdr(skb);
608 hc06_ptr = head + 2; 606 hc_ptr = head + 2;
609 607
610 pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n" 608 pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n"
611 "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n", 609 "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n",
@@ -630,8 +628,7 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
630 raw_dump_inline(__func__, "daddr", 628 raw_dump_inline(__func__, "daddr",
631 (unsigned char *)_daddr, IEEE802154_ADDR_LEN); 629 (unsigned char *)_daddr, IEEE802154_ADDR_LEN);
632 630
633 raw_dump_table(__func__, 631 raw_dump_table(__func__, "sending raw skb network uncompressed packet",
634 "sending raw skb network uncompressed packet",
635 skb->data, skb->len); 632 skb->data, skb->len);
636 633
637 /* Traffic class, flow label 634 /* Traffic class, flow label
@@ -640,7 +637,7 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
640 * class depends on the presence of version and flow label 637 * class depends on the presence of version and flow label
641 */ 638 */
642 639
643 /* hc06 format of TC is ECN | DSCP , original one is DSCP | ECN */ 640 /* hc format of TC is ECN | DSCP , original one is DSCP | ECN */
644 tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4); 641 tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4);
645 tmp = ((tmp & 0x03) << 6) | (tmp >> 2); 642 tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
646 643
@@ -654,8 +651,8 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
654 iphc0 |= LOWPAN_IPHC_TC_C; 651 iphc0 |= LOWPAN_IPHC_TC_C;
655 } else { 652 } else {
656 /* compress only the flow label */ 653 /* compress only the flow label */
657 *hc06_ptr = tmp; 654 *hc_ptr = tmp;
658 hc06_ptr += 1; 655 hc_ptr += 1;
659 } 656 }
660 } else { 657 } else {
661 /* Flow label cannot be compressed */ 658 /* Flow label cannot be compressed */
@@ -663,15 +660,15 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
663 ((hdr->flow_lbl[0] & 0xF0) == 0)) { 660 ((hdr->flow_lbl[0] & 0xF0) == 0)) {
664 /* compress only traffic class */ 661 /* compress only traffic class */
665 iphc0 |= LOWPAN_IPHC_TC_C; 662 iphc0 |= LOWPAN_IPHC_TC_C;
666 *hc06_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F); 663 *hc_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F);
667 memcpy(hc06_ptr + 1, &hdr->flow_lbl[1], 2); 664 memcpy(hc_ptr + 1, &hdr->flow_lbl[1], 2);
668 hc06_ptr += 3; 665 hc_ptr += 3;
669 } else { 666 } else {
670 /* compress nothing */ 667 /* compress nothing */
671 memcpy(hc06_ptr, hdr, 4); 668 memcpy(hc_ptr, hdr, 4);
672 /* replace the top byte with new ECN | DSCP format */ 669 /* replace the top byte with new ECN | DSCP format */
673 *hc06_ptr = tmp; 670 *hc_ptr = tmp;
674 hc06_ptr += 4; 671 hc_ptr += 4;
675 } 672 }
676 } 673 }
677 674
@@ -681,10 +678,9 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
681 if (hdr->nexthdr == UIP_PROTO_UDP) 678 if (hdr->nexthdr == UIP_PROTO_UDP)
682 iphc0 |= LOWPAN_IPHC_NH_C; 679 iphc0 |= LOWPAN_IPHC_NH_C;
683 680
684 if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { 681 if ((iphc0 & LOWPAN_IPHC_NH_C) == 0)
685 *hc06_ptr = hdr->nexthdr; 682 lowpan_push_hc_data(&hc_ptr, &hdr->nexthdr,
686 hc06_ptr += 1; 683 sizeof(hdr->nexthdr));
687 }
688 684
689 /* Hop limit 685 /* Hop limit
690 * if 1: compress, encoding is 01 686 * if 1: compress, encoding is 01
@@ -703,84 +699,86 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
703 iphc0 |= LOWPAN_IPHC_TTL_255; 699 iphc0 |= LOWPAN_IPHC_TTL_255;
704 break; 700 break;
705 default: 701 default:
706 *hc06_ptr = hdr->hop_limit; 702 lowpan_push_hc_data(&hc_ptr, &hdr->hop_limit,
707 hc06_ptr += 1; 703 sizeof(hdr->hop_limit));
708 break;
709 } 704 }
710 705
706 addr_type = ipv6_addr_type(&hdr->saddr);
711 /* source address compression */ 707 /* source address compression */
712 if (is_addr_unspecified(&hdr->saddr)) { 708 if (addr_type == IPV6_ADDR_ANY) {
713 pr_debug("source address is unspecified, setting SAC\n"); 709 pr_debug("source address is unspecified, setting SAC\n");
714 iphc1 |= LOWPAN_IPHC_SAC; 710 iphc1 |= LOWPAN_IPHC_SAC;
715 /* TODO: context lookup */
716 } else if (is_addr_link_local(&hdr->saddr)) {
717 iphc1 |= lowpan_compress_addr_64(&hc06_ptr,
718 LOWPAN_IPHC_SAM_BIT, &hdr->saddr, _saddr);
719 pr_debug("source address unicast link-local %pI6c "
720 "iphc1 0x%02x\n", &hdr->saddr, iphc1);
721 } else { 711 } else {
722 pr_debug("send the full source address\n"); 712 if (addr_type & IPV6_ADDR_LINKLOCAL) {
723 memcpy(hc06_ptr, &hdr->saddr.s6_addr16[0], 16); 713 iphc1 |= lowpan_compress_addr_64(&hc_ptr,
724 hc06_ptr += 16; 714 LOWPAN_IPHC_SAM_BIT,
715 &hdr->saddr, _saddr);
716 pr_debug("source address unicast link-local %pI6c iphc1 0x%02x\n",
717 &hdr->saddr, iphc1);
718 } else {
719 pr_debug("send the full source address\n");
720 lowpan_push_hc_data(&hc_ptr, hdr->saddr.s6_addr, 16);
721 }
725 } 722 }
726 723
724 addr_type = ipv6_addr_type(&hdr->daddr);
727 /* destination address compression */ 725 /* destination address compression */
728 if (is_addr_mcast(&hdr->daddr)) { 726 if (addr_type & IPV6_ADDR_MULTICAST) {
729 pr_debug("destination address is multicast: "); 727 pr_debug("destination address is multicast: ");
730 iphc1 |= LOWPAN_IPHC_M; 728 iphc1 |= LOWPAN_IPHC_M;
731 if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) { 729 if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) {
732 pr_debug("compressed to 1 octet\n"); 730 pr_debug("compressed to 1 octet\n");
733 iphc1 |= LOWPAN_IPHC_DAM_11; 731 iphc1 |= LOWPAN_IPHC_DAM_11;
734 /* use last byte */ 732 /* use last byte */
735 *hc06_ptr = hdr->daddr.s6_addr[15]; 733 lowpan_push_hc_data(&hc_ptr,
736 hc06_ptr += 1; 734 &hdr->daddr.s6_addr[15], 1);
737 } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) { 735 } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) {
738 pr_debug("compressed to 4 octets\n"); 736 pr_debug("compressed to 4 octets\n");
739 iphc1 |= LOWPAN_IPHC_DAM_10; 737 iphc1 |= LOWPAN_IPHC_DAM_10;
740 /* second byte + the last three */ 738 /* second byte + the last three */
741 *hc06_ptr = hdr->daddr.s6_addr[1]; 739 lowpan_push_hc_data(&hc_ptr,
742 memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[13], 3); 740 &hdr->daddr.s6_addr[1], 1);
743 hc06_ptr += 4; 741 lowpan_push_hc_data(&hc_ptr,
742 &hdr->daddr.s6_addr[13], 3);
744 } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) { 743 } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) {
745 pr_debug("compressed to 6 octets\n"); 744 pr_debug("compressed to 6 octets\n");
746 iphc1 |= LOWPAN_IPHC_DAM_01; 745 iphc1 |= LOWPAN_IPHC_DAM_01;
747 /* second byte + the last five */ 746 /* second byte + the last five */
748 *hc06_ptr = hdr->daddr.s6_addr[1]; 747 lowpan_push_hc_data(&hc_ptr,
749 memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[11], 5); 748 &hdr->daddr.s6_addr[1], 1);
750 hc06_ptr += 6; 749 lowpan_push_hc_data(&hc_ptr,
750 &hdr->daddr.s6_addr[11], 5);
751 } else { 751 } else {
752 pr_debug("using full address\n"); 752 pr_debug("using full address\n");
753 iphc1 |= LOWPAN_IPHC_DAM_00; 753 iphc1 |= LOWPAN_IPHC_DAM_00;
754 memcpy(hc06_ptr, &hdr->daddr.s6_addr[0], 16); 754 lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16);
755 hc06_ptr += 16;
756 } 755 }
757 } else { 756 } else {
758 /* TODO: context lookup */ 757 if (addr_type & IPV6_ADDR_LINKLOCAL) {
759 if (is_addr_link_local(&hdr->daddr)) { 758 /* TODO: context lookup */
760 iphc1 |= lowpan_compress_addr_64(&hc06_ptr, 759 iphc1 |= lowpan_compress_addr_64(&hc_ptr,
761 LOWPAN_IPHC_DAM_BIT, &hdr->daddr, _daddr); 760 LOWPAN_IPHC_DAM_BIT, &hdr->daddr, _daddr);
762 pr_debug("dest address unicast link-local %pI6c " 761 pr_debug("dest address unicast link-local %pI6c "
763 "iphc1 0x%02x\n", &hdr->daddr, iphc1); 762 "iphc1 0x%02x\n", &hdr->daddr, iphc1);
764 } else { 763 } else {
765 pr_debug("dest address unicast %pI6c\n", &hdr->daddr); 764 pr_debug("dest address unicast %pI6c\n", &hdr->daddr);
766 memcpy(hc06_ptr, &hdr->daddr.s6_addr16[0], 16); 765 lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16);
767 hc06_ptr += 16;
768 } 766 }
769 } 767 }
770 768
771 /* UDP header compression */ 769 /* UDP header compression */
772 if (hdr->nexthdr == UIP_PROTO_UDP) 770 if (hdr->nexthdr == UIP_PROTO_UDP)
773 compress_udp_header(&hc06_ptr, skb); 771 compress_udp_header(&hc_ptr, skb);
774 772
775 head[0] = iphc0; 773 head[0] = iphc0;
776 head[1] = iphc1; 774 head[1] = iphc1;
777 775
778 skb_pull(skb, sizeof(struct ipv6hdr)); 776 skb_pull(skb, sizeof(struct ipv6hdr));
779 skb_reset_transport_header(skb); 777 skb_reset_transport_header(skb);
780 memcpy(skb_push(skb, hc06_ptr - head), head, hc06_ptr - head); 778 memcpy(skb_push(skb, hc_ptr - head), head, hc_ptr - head);
781 skb_reset_network_header(skb); 779 skb_reset_network_header(skb);
782 780
783 pr_debug("header len %d skb %u\n", (int)(hc06_ptr - head), skb->len); 781 pr_debug("header len %d skb %u\n", (int)(hc_ptr - head), skb->len);
784 782
785 raw_dump_table(__func__, "raw skb data dump compressed", 783 raw_dump_table(__func__, "raw skb data dump compressed",
786 skb->data, skb->len); 784 skb->data, skb->len);