1 /* 2 * Copyright 2011, Siemens AG 3 * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com> 4 */ 5 6 /* Based on patches from Jon Smirl <jonsmirl@gmail.com> 7 * Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 11 * as published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 */ 19 20 /* Jon's code is based on 6lowpan implementation for Contiki which is: 21 * Copyright (c) 2008, Swedish Institute of Computer Science. 22 * All rights reserved. 23 * 24 * Redistribution and use in source and binary forms, with or without 25 * modification, are permitted provided that the following conditions 26 * are met: 27 * 1. Redistributions of source code must retain the above copyright 28 * notice, this list of conditions and the following disclaimer. 29 * 2. Redistributions in binary form must reproduce the above copyright 30 * notice, this list of conditions and the following disclaimer in the 31 * documentation and/or other materials provided with the distribution. 32 * 3. Neither the name of the Institute nor the names of its contributors 33 * may be used to endorse or promote products derived from this software 34 * without specific prior written permission. 35 * 36 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 37 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 39 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 40 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 41 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 42 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 44 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 45 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 46 * SUCH DAMAGE. 47 */ 48 49 #include <linux/bitops.h> 50 #include <linux/if_arp.h> 51 #include <linux/netdevice.h> 52 #include <net/6lowpan.h> 53 #include <net/ipv6.h> 54 #include <net/af_ieee802154.h> 55 56 #include "nhc.h" 57 58 /* Uncompress address function for source and 59 * destination address(non-multicast). 60 * 61 * address_mode is sam value or dam value. 62 */ 63 static int uncompress_addr(struct sk_buff *skb, 64 struct in6_addr *ipaddr, const u8 address_mode, 65 const u8 *lladdr, const u8 addr_type, 66 const u8 addr_len) 67 { 68 bool fail; 69 70 switch (address_mode) { 71 case LOWPAN_IPHC_ADDR_00: 72 /* for global link addresses */ 73 fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16); 74 break; 75 case LOWPAN_IPHC_ADDR_01: 76 /* fe:80::XXXX:XXXX:XXXX:XXXX */ 77 ipaddr->s6_addr[0] = 0xFE; 78 ipaddr->s6_addr[1] = 0x80; 79 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8); 80 break; 81 case LOWPAN_IPHC_ADDR_02: 82 /* fe:80::ff:fe00:XXXX */ 83 ipaddr->s6_addr[0] = 0xFE; 84 ipaddr->s6_addr[1] = 0x80; 85 ipaddr->s6_addr[11] = 0xFF; 86 ipaddr->s6_addr[12] = 0xFE; 87 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2); 88 break; 89 case LOWPAN_IPHC_ADDR_03: 90 fail = false; 91 switch (addr_type) { 92 case IEEE802154_ADDR_LONG: 93 /* fe:80::XXXX:XXXX:XXXX:XXXX 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; 118 default: 119 pr_debug("Invalid addr_type set\n"); 120 return -EINVAL; 121 } 122 break; 123 default: 124 pr_debug("Invalid address mode value: 0x%x\n", address_mode); 125 return -EINVAL; 126 } 127 128 if (fail) { 129 pr_debug("Failed to fetch skb data\n"); 130 return -EIO; 131 } 132 133 raw_dump_inline(NULL, "Reconstructed ipv6 addr is", 134 ipaddr->s6_addr, 16); 135 136 return 0; 137 } 138 139 /* Uncompress address function for source context 140 * based address(non-multicast). 141 */ 142 static int uncompress_context_based_src_addr(struct sk_buff *skb, 143 struct in6_addr *ipaddr, 144 const u8 sam) 145 { 146 switch (sam) { 147 case LOWPAN_IPHC_ADDR_00: 148 /* unspec address :: 149 * Do nothing, address is already :: 150 */ 151 break; 152 case LOWPAN_IPHC_ADDR_01: 153 /* TODO */ 154 case LOWPAN_IPHC_ADDR_02: 155 /* TODO */ 156 case LOWPAN_IPHC_ADDR_03: 157 /* TODO */ 158 netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam); 159 return -EINVAL; 160 default: 161 pr_debug("Invalid sam value: 0x%x\n", sam); 162 return -EINVAL; 163 } 164 165 raw_dump_inline(NULL, 166 "Reconstructed context based ipv6 src addr is", 167 ipaddr->s6_addr, 16); 168 169 return 0; 170 } 171 172 /* Uncompress function for multicast destination address, 173 * when M bit is set. 174 */ 175 static int lowpan_uncompress_multicast_daddr(struct sk_buff *skb, 176 struct in6_addr *ipaddr, 177 const u8 dam) 178 { 179 bool fail; 180 181 switch (dam) { 182 case LOWPAN_IPHC_DAM_00: 183 /* 00: 128 bits. The full address 184 * is carried in-line. 185 */ 186 fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16); 187 break; 188 case LOWPAN_IPHC_DAM_01: 189 /* 01: 48 bits. The address takes 190 * the form ffXX::00XX:XXXX:XXXX. 191 */ 192 ipaddr->s6_addr[0] = 0xFF; 193 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1); 194 fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5); 195 break; 196 case LOWPAN_IPHC_DAM_10: 197 /* 10: 32 bits. The address takes 198 * the form ffXX::00XX:XXXX. 199 */ 200 ipaddr->s6_addr[0] = 0xFF; 201 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1); 202 fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3); 203 break; 204 case LOWPAN_IPHC_DAM_11: 205 /* 11: 8 bits. The address takes 206 * the form ff02::00XX. 207 */ 208 ipaddr->s6_addr[0] = 0xFF; 209 ipaddr->s6_addr[1] = 0x02; 210 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1); 211 break; 212 default: 213 pr_debug("DAM value has a wrong value: 0x%x\n", dam); 214 return -EINVAL; 215 } 216 217 if (fail) { 218 pr_debug("Failed to fetch skb data\n"); 219 return -EIO; 220 } 221 222 raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is", 223 ipaddr->s6_addr, 16); 224 225 return 0; 226 } 227 228 /* TTL uncompression values */ 229 static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 }; 230 231 int 232 lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, 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 { 238 struct ipv6hdr hdr = {}; 239 u8 tmp, num_context = 0; 240 int err; 241 242 raw_dump_table(__func__, "raw skb data dump uncompressed", 243 skb->data, skb->len); 244 245 /* another if the CID flag is set */ 246 if (iphc1 & LOWPAN_IPHC_CID) { 247 pr_debug("CID flag is set, increase header with one\n"); 248 if (lowpan_fetch_skb(skb, &num_context, sizeof(num_context))) 249 return -EINVAL; 250 } 251 252 hdr.version = 6; 253 254 /* Traffic Class and Flow Label */ 255 switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) { 256 /* Traffic Class and FLow Label carried in-line 257 * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes) 258 */ 259 case 0: /* 00b */ 260 if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) 261 return -EINVAL; 262 263 memcpy(&hdr.flow_lbl, &skb->data[0], 3); 264 skb_pull(skb, 3); 265 hdr.priority = ((tmp >> 2) & 0x0f); 266 hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) | 267 (hdr.flow_lbl[0] & 0x0f); 268 break; 269 /* Traffic class carried in-line 270 * ECN + DSCP (1 byte), Flow Label is elided 271 */ 272 case 2: /* 10b */ 273 if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) 274 return -EINVAL; 275 276 hdr.priority = ((tmp >> 2) & 0x0f); 277 hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30); 278 break; 279 /* Flow Label carried in-line 280 * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided 281 */ 282 case 1: /* 01b */ 283 if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) 284 return -EINVAL; 285 286 hdr.flow_lbl[0] = (tmp & 0x0F) | ((tmp >> 2) & 0x30); 287 memcpy(&hdr.flow_lbl[1], &skb->data[0], 2); 288 skb_pull(skb, 2); 289 break; 290 /* Traffic Class and Flow Label are elided */ 291 case 3: /* 11b */ 292 break; 293 default: 294 break; 295 } 296 297 /* Next Header */ 298 if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { 299 /* Next header is carried inline */ 300 if (lowpan_fetch_skb(skb, &hdr.nexthdr, sizeof(hdr.nexthdr))) 301 return -EINVAL; 302 303 pr_debug("NH flag is set, next header carried inline: %02x\n", 304 hdr.nexthdr); 305 } 306 307 /* Hop Limit */ 308 if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I) { 309 hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03]; 310 } else { 311 if (lowpan_fetch_skb(skb, &hdr.hop_limit, 312 sizeof(hdr.hop_limit))) 313 return -EINVAL; 314 } 315 316 /* Extract SAM to the tmp variable */ 317 tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03; 318 319 if (iphc1 & LOWPAN_IPHC_SAC) { 320 /* Source address context based uncompression */ 321 pr_debug("SAC bit is set. Handle context based source address.\n"); 322 err = uncompress_context_based_src_addr(skb, &hdr.saddr, tmp); 323 } else { 324 /* Source address uncompression */ 325 pr_debug("source address stateless compression\n"); 326 err = uncompress_addr(skb, &hdr.saddr, tmp, saddr, 327 saddr_type, saddr_len); 328 } 329 330 /* Check on error of previous branch */ 331 if (err) 332 return -EINVAL; 333 334 /* Extract DAM to the tmp variable */ 335 tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03; 336 337 /* check for Multicast Compression */ 338 if (iphc1 & LOWPAN_IPHC_M) { 339 if (iphc1 & LOWPAN_IPHC_DAC) { 340 pr_debug("dest: context-based mcast compression\n"); 341 /* TODO: implement this */ 342 } else { 343 err = lowpan_uncompress_multicast_daddr(skb, &hdr.daddr, 344 tmp); 345 346 if (err) 347 return -EINVAL; 348 } 349 } else { 350 err = uncompress_addr(skb, &hdr.daddr, tmp, daddr, 351 daddr_type, daddr_len); 352 pr_debug("dest: stateless compression mode %d dest %pI6c\n", 353 tmp, &hdr.daddr); 354 if (err) 355 return -EINVAL; 356 } 357 358 /* Next header data uncompression */ 359 if (iphc0 & LOWPAN_IPHC_NH_C) { 360 err = lowpan_nhc_do_uncompression(skb, dev, &hdr); 361 if (err < 0) 362 return err; 363 } else { 364 err = skb_cow(skb, sizeof(hdr)); 365 if (unlikely(err)) 366 return err; 367 } 368 369 hdr.payload_len = htons(skb->len); 370 371 pr_debug("skb headroom size = %d, data length = %d\n", 372 skb_headroom(skb), skb->len); 373 374 pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n\t" 375 "nexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n", 376 hdr.version, ntohs(hdr.payload_len), hdr.nexthdr, 377 hdr.hop_limit, &hdr.daddr); 378 379 skb_push(skb, sizeof(hdr)); 380 skb_reset_network_header(skb); 381 skb_copy_to_linear_data(skb, &hdr, sizeof(hdr)); 382 383 raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr)); 384 385 return 0; 386 } 387 EXPORT_SYMBOL_GPL(lowpan_header_decompress); 388 389 static u8 lowpan_compress_addr_64(u8 **hc_ptr, u8 shift, 390 const struct in6_addr *ipaddr, 391 const unsigned char *lladdr) 392 { 393 u8 val = 0; 394 395 if (is_addr_mac_addr_based(ipaddr, lladdr)) { 396 val = 3; /* 0-bits */ 397 pr_debug("address compression 0 bits\n"); 398 } else if (lowpan_is_iid_16_bit_compressable(ipaddr)) { 399 /* compress IID to 16 bits xxxx::XXXX */ 400 lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[7], 2); 401 val = 2; /* 16-bits */ 402 raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)", 403 *hc_ptr - 2, 2); 404 } else { 405 /* do not compress IID => xxxx::IID */ 406 lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[4], 8); 407 val = 1; /* 64-bits */ 408 raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)", 409 *hc_ptr - 8, 8); 410 } 411 412 return rol8(val, shift); 413 } 414 415 int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, 416 unsigned short type, const void *_daddr, 417 const void *_saddr, unsigned int len) 418 { 419 u8 tmp, iphc0, iphc1, *hc_ptr; 420 struct ipv6hdr *hdr; 421 u8 head[100] = {}; 422 int ret, addr_type; 423 424 if (type != ETH_P_IPV6) 425 return -EINVAL; 426 427 hdr = ipv6_hdr(skb); 428 hc_ptr = head + 2; 429 430 pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n" 431 "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n", 432 hdr->version, ntohs(hdr->payload_len), hdr->nexthdr, 433 hdr->hop_limit, &hdr->daddr); 434 435 raw_dump_table(__func__, "raw skb network header dump", 436 skb_network_header(skb), sizeof(struct ipv6hdr)); 437 438 /* As we copy some bit-length fields, in the IPHC encoding bytes, 439 * we sometimes use |= 440 * If the field is 0, and the current bit value in memory is 1, 441 * this does not work. We therefore reset the IPHC encoding here 442 */ 443 iphc0 = LOWPAN_DISPATCH_IPHC; 444 iphc1 = 0; 445 446 /* TODO: context lookup */ 447 448 raw_dump_inline(__func__, "saddr", 449 (unsigned char *)_saddr, IEEE802154_ADDR_LEN); 450 raw_dump_inline(__func__, "daddr", 451 (unsigned char *)_daddr, IEEE802154_ADDR_LEN); 452 453 raw_dump_table(__func__, "sending raw skb network uncompressed packet", 454 skb->data, skb->len); 455 456 /* Traffic class, flow label 457 * If flow label is 0, compress it. If traffic class is 0, compress it 458 * We have to process both in the same time as the offset of traffic 459 * class depends on the presence of version and flow label 460 */ 461 462 /* hc format of TC is ECN | DSCP , original one is DSCP | ECN */ 463 tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4); 464 tmp = ((tmp & 0x03) << 6) | (tmp >> 2); 465 466 if (((hdr->flow_lbl[0] & 0x0F) == 0) && 467 (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) { 468 /* flow label can be compressed */ 469 iphc0 |= LOWPAN_IPHC_FL_C; 470 if ((hdr->priority == 0) && 471 ((hdr->flow_lbl[0] & 0xF0) == 0)) { 472 /* compress (elide) all */ 473 iphc0 |= LOWPAN_IPHC_TC_C; 474 } else { 475 /* compress only the flow label */ 476 *hc_ptr = tmp; 477 hc_ptr += 1; 478 } 479 } else { 480 /* Flow label cannot be compressed */ 481 if ((hdr->priority == 0) && 482 ((hdr->flow_lbl[0] & 0xF0) == 0)) { 483 /* compress only traffic class */ 484 iphc0 |= LOWPAN_IPHC_TC_C; 485 *hc_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F); 486 memcpy(hc_ptr + 1, &hdr->flow_lbl[1], 2); 487 hc_ptr += 3; 488 } else { 489 /* compress nothing */ 490 memcpy(hc_ptr, hdr, 4); 491 /* replace the top byte with new ECN | DSCP format */ 492 *hc_ptr = tmp; 493 hc_ptr += 4; 494 } 495 } 496 497 /* NOTE: payload length is always compressed */ 498 499 /* Check if we provide the nhc format for nexthdr and compression 500 * functionality. If not nexthdr is handled inline and not compressed. 501 */ 502 ret = lowpan_nhc_check_compression(skb, hdr, &hc_ptr, &iphc0); 503 if (ret < 0) 504 return ret; 505 506 /* Hop limit 507 * if 1: compress, encoding is 01 508 * if 64: compress, encoding is 10 509 * if 255: compress, encoding is 11 510 * else do not compress 511 */ 512 switch (hdr->hop_limit) { 513 case 1: 514 iphc0 |= LOWPAN_IPHC_TTL_1; 515 break; 516 case 64: 517 iphc0 |= LOWPAN_IPHC_TTL_64; 518 break; 519 case 255: 520 iphc0 |= LOWPAN_IPHC_TTL_255; 521 break; 522 default: 523 lowpan_push_hc_data(&hc_ptr, &hdr->hop_limit, 524 sizeof(hdr->hop_limit)); 525 } 526 527 addr_type = ipv6_addr_type(&hdr->saddr); 528 /* source address compression */ 529 if (addr_type == IPV6_ADDR_ANY) { 530 pr_debug("source address is unspecified, setting SAC\n"); 531 iphc1 |= LOWPAN_IPHC_SAC; 532 } else { 533 if (addr_type & IPV6_ADDR_LINKLOCAL) { 534 iphc1 |= lowpan_compress_addr_64(&hc_ptr, 535 LOWPAN_IPHC_SAM_BIT, 536 &hdr->saddr, _saddr); 537 pr_debug("source address unicast link-local %pI6c iphc1 0x%02x\n", 538 &hdr->saddr, iphc1); 539 } else { 540 pr_debug("send the full source address\n"); 541 lowpan_push_hc_data(&hc_ptr, hdr->saddr.s6_addr, 16); 542 } 543 } 544 545 addr_type = ipv6_addr_type(&hdr->daddr); 546 /* destination address compression */ 547 if (addr_type & IPV6_ADDR_MULTICAST) { 548 pr_debug("destination address is multicast: "); 549 iphc1 |= LOWPAN_IPHC_M; 550 if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) { 551 pr_debug("compressed to 1 octet\n"); 552 iphc1 |= LOWPAN_IPHC_DAM_11; 553 /* use last byte */ 554 lowpan_push_hc_data(&hc_ptr, 555 &hdr->daddr.s6_addr[15], 1); 556 } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) { 557 pr_debug("compressed to 4 octets\n"); 558 iphc1 |= LOWPAN_IPHC_DAM_10; 559 /* second byte + the last three */ 560 lowpan_push_hc_data(&hc_ptr, 561 &hdr->daddr.s6_addr[1], 1); 562 lowpan_push_hc_data(&hc_ptr, 563 &hdr->daddr.s6_addr[13], 3); 564 } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) { 565 pr_debug("compressed to 6 octets\n"); 566 iphc1 |= LOWPAN_IPHC_DAM_01; 567 /* second byte + the last five */ 568 lowpan_push_hc_data(&hc_ptr, 569 &hdr->daddr.s6_addr[1], 1); 570 lowpan_push_hc_data(&hc_ptr, 571 &hdr->daddr.s6_addr[11], 5); 572 } else { 573 pr_debug("using full address\n"); 574 iphc1 |= LOWPAN_IPHC_DAM_00; 575 lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16); 576 } 577 } else { 578 if (addr_type & IPV6_ADDR_LINKLOCAL) { 579 /* TODO: context lookup */ 580 iphc1 |= lowpan_compress_addr_64(&hc_ptr, 581 LOWPAN_IPHC_DAM_BIT, &hdr->daddr, _daddr); 582 pr_debug("dest address unicast link-local %pI6c " 583 "iphc1 0x%02x\n", &hdr->daddr, iphc1); 584 } else { 585 pr_debug("dest address unicast %pI6c\n", &hdr->daddr); 586 lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16); 587 } 588 } 589 590 /* next header compression */ 591 if (iphc0 & LOWPAN_IPHC_NH_C) { 592 ret = lowpan_nhc_do_compression(skb, hdr, &hc_ptr); 593 if (ret < 0) 594 return ret; 595 } 596 597 head[0] = iphc0; 598 head[1] = iphc1; 599 600 skb_pull(skb, sizeof(struct ipv6hdr)); 601 skb_reset_transport_header(skb); 602 memcpy(skb_push(skb, hc_ptr - head), head, hc_ptr - head); 603 skb_reset_network_header(skb); 604 605 pr_debug("header len %d skb %u\n", (int)(hc_ptr - head), skb->len); 606 607 raw_dump_table(__func__, "raw skb data dump compressed", 608 skb->data, skb->len); 609 return 0; 610 } 611 EXPORT_SYMBOL_GPL(lowpan_header_compress); 612