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 switch (lowpan_priv(dev)->lltype) { 370 case LOWPAN_LLTYPE_IEEE802154: 371 if (lowpan_802154_cb(skb)->d_size) 372 hdr.payload_len = htons(lowpan_802154_cb(skb)->d_size - 373 sizeof(struct ipv6hdr)); 374 else 375 hdr.payload_len = htons(skb->len); 376 break; 377 default: 378 hdr.payload_len = htons(skb->len); 379 break; 380 } 381 382 pr_debug("skb headroom size = %d, data length = %d\n", 383 skb_headroom(skb), skb->len); 384 385 pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n\t" 386 "nexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n", 387 hdr.version, ntohs(hdr.payload_len), hdr.nexthdr, 388 hdr.hop_limit, &hdr.daddr); 389 390 skb_push(skb, sizeof(hdr)); 391 skb_reset_network_header(skb); 392 skb_copy_to_linear_data(skb, &hdr, sizeof(hdr)); 393 394 raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr)); 395 396 return 0; 397 } 398 EXPORT_SYMBOL_GPL(lowpan_header_decompress); 399 400 static u8 lowpan_compress_addr_64(u8 **hc_ptr, u8 shift, 401 const struct in6_addr *ipaddr, 402 const unsigned char *lladdr) 403 { 404 u8 val = 0; 405 406 if (is_addr_mac_addr_based(ipaddr, lladdr)) { 407 val = 3; /* 0-bits */ 408 pr_debug("address compression 0 bits\n"); 409 } else if (lowpan_is_iid_16_bit_compressable(ipaddr)) { 410 /* compress IID to 16 bits xxxx::XXXX */ 411 lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[7], 2); 412 val = 2; /* 16-bits */ 413 raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)", 414 *hc_ptr - 2, 2); 415 } else { 416 /* do not compress IID => xxxx::IID */ 417 lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[4], 8); 418 val = 1; /* 64-bits */ 419 raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)", 420 *hc_ptr - 8, 8); 421 } 422 423 return rol8(val, shift); 424 } 425 426 int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, 427 unsigned short type, const void *_daddr, 428 const void *_saddr, unsigned int len) 429 { 430 u8 tmp, iphc0, iphc1, *hc_ptr; 431 struct ipv6hdr *hdr; 432 u8 head[100] = {}; 433 int ret, addr_type; 434 435 if (type != ETH_P_IPV6) 436 return -EINVAL; 437 438 hdr = ipv6_hdr(skb); 439 hc_ptr = head + 2; 440 441 pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n" 442 "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n", 443 hdr->version, ntohs(hdr->payload_len), hdr->nexthdr, 444 hdr->hop_limit, &hdr->daddr); 445 446 raw_dump_table(__func__, "raw skb network header dump", 447 skb_network_header(skb), sizeof(struct ipv6hdr)); 448 449 /* As we copy some bit-length fields, in the IPHC encoding bytes, 450 * we sometimes use |= 451 * If the field is 0, and the current bit value in memory is 1, 452 * this does not work. We therefore reset the IPHC encoding here 453 */ 454 iphc0 = LOWPAN_DISPATCH_IPHC; 455 iphc1 = 0; 456 457 /* TODO: context lookup */ 458 459 raw_dump_inline(__func__, "saddr", 460 (unsigned char *)_saddr, IEEE802154_ADDR_LEN); 461 raw_dump_inline(__func__, "daddr", 462 (unsigned char *)_daddr, IEEE802154_ADDR_LEN); 463 464 raw_dump_table(__func__, "sending raw skb network uncompressed packet", 465 skb->data, skb->len); 466 467 /* Traffic class, flow label 468 * If flow label is 0, compress it. If traffic class is 0, compress it 469 * We have to process both in the same time as the offset of traffic 470 * class depends on the presence of version and flow label 471 */ 472 473 /* hc format of TC is ECN | DSCP , original one is DSCP | ECN */ 474 tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4); 475 tmp = ((tmp & 0x03) << 6) | (tmp >> 2); 476 477 if (((hdr->flow_lbl[0] & 0x0F) == 0) && 478 (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) { 479 /* flow label can be compressed */ 480 iphc0 |= LOWPAN_IPHC_FL_C; 481 if ((hdr->priority == 0) && 482 ((hdr->flow_lbl[0] & 0xF0) == 0)) { 483 /* compress (elide) all */ 484 iphc0 |= LOWPAN_IPHC_TC_C; 485 } else { 486 /* compress only the flow label */ 487 *hc_ptr = tmp; 488 hc_ptr += 1; 489 } 490 } else { 491 /* Flow label cannot be compressed */ 492 if ((hdr->priority == 0) && 493 ((hdr->flow_lbl[0] & 0xF0) == 0)) { 494 /* compress only traffic class */ 495 iphc0 |= LOWPAN_IPHC_TC_C; 496 *hc_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F); 497 memcpy(hc_ptr + 1, &hdr->flow_lbl[1], 2); 498 hc_ptr += 3; 499 } else { 500 /* compress nothing */ 501 memcpy(hc_ptr, hdr, 4); 502 /* replace the top byte with new ECN | DSCP format */ 503 *hc_ptr = tmp; 504 hc_ptr += 4; 505 } 506 } 507 508 /* NOTE: payload length is always compressed */ 509 510 /* Check if we provide the nhc format for nexthdr and compression 511 * functionality. If not nexthdr is handled inline and not compressed. 512 */ 513 ret = lowpan_nhc_check_compression(skb, hdr, &hc_ptr, &iphc0); 514 if (ret < 0) 515 return ret; 516 517 /* Hop limit 518 * if 1: compress, encoding is 01 519 * if 64: compress, encoding is 10 520 * if 255: compress, encoding is 11 521 * else do not compress 522 */ 523 switch (hdr->hop_limit) { 524 case 1: 525 iphc0 |= LOWPAN_IPHC_TTL_1; 526 break; 527 case 64: 528 iphc0 |= LOWPAN_IPHC_TTL_64; 529 break; 530 case 255: 531 iphc0 |= LOWPAN_IPHC_TTL_255; 532 break; 533 default: 534 lowpan_push_hc_data(&hc_ptr, &hdr->hop_limit, 535 sizeof(hdr->hop_limit)); 536 } 537 538 addr_type = ipv6_addr_type(&hdr->saddr); 539 /* source address compression */ 540 if (addr_type == IPV6_ADDR_ANY) { 541 pr_debug("source address is unspecified, setting SAC\n"); 542 iphc1 |= LOWPAN_IPHC_SAC; 543 } else { 544 if (addr_type & IPV6_ADDR_LINKLOCAL) { 545 iphc1 |= lowpan_compress_addr_64(&hc_ptr, 546 LOWPAN_IPHC_SAM_BIT, 547 &hdr->saddr, _saddr); 548 pr_debug("source address unicast link-local %pI6c iphc1 0x%02x\n", 549 &hdr->saddr, iphc1); 550 } else { 551 pr_debug("send the full source address\n"); 552 lowpan_push_hc_data(&hc_ptr, hdr->saddr.s6_addr, 16); 553 } 554 } 555 556 addr_type = ipv6_addr_type(&hdr->daddr); 557 /* destination address compression */ 558 if (addr_type & IPV6_ADDR_MULTICAST) { 559 pr_debug("destination address is multicast: "); 560 iphc1 |= LOWPAN_IPHC_M; 561 if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) { 562 pr_debug("compressed to 1 octet\n"); 563 iphc1 |= LOWPAN_IPHC_DAM_11; 564 /* use last byte */ 565 lowpan_push_hc_data(&hc_ptr, 566 &hdr->daddr.s6_addr[15], 1); 567 } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) { 568 pr_debug("compressed to 4 octets\n"); 569 iphc1 |= LOWPAN_IPHC_DAM_10; 570 /* second byte + the last three */ 571 lowpan_push_hc_data(&hc_ptr, 572 &hdr->daddr.s6_addr[1], 1); 573 lowpan_push_hc_data(&hc_ptr, 574 &hdr->daddr.s6_addr[13], 3); 575 } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) { 576 pr_debug("compressed to 6 octets\n"); 577 iphc1 |= LOWPAN_IPHC_DAM_01; 578 /* second byte + the last five */ 579 lowpan_push_hc_data(&hc_ptr, 580 &hdr->daddr.s6_addr[1], 1); 581 lowpan_push_hc_data(&hc_ptr, 582 &hdr->daddr.s6_addr[11], 5); 583 } else { 584 pr_debug("using full address\n"); 585 iphc1 |= LOWPAN_IPHC_DAM_00; 586 lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16); 587 } 588 } else { 589 if (addr_type & IPV6_ADDR_LINKLOCAL) { 590 /* TODO: context lookup */ 591 iphc1 |= lowpan_compress_addr_64(&hc_ptr, 592 LOWPAN_IPHC_DAM_BIT, &hdr->daddr, _daddr); 593 pr_debug("dest address unicast link-local %pI6c " 594 "iphc1 0x%02x\n", &hdr->daddr, iphc1); 595 } else { 596 pr_debug("dest address unicast %pI6c\n", &hdr->daddr); 597 lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16); 598 } 599 } 600 601 /* next header compression */ 602 if (iphc0 & LOWPAN_IPHC_NH_C) { 603 ret = lowpan_nhc_do_compression(skb, hdr, &hc_ptr); 604 if (ret < 0) 605 return ret; 606 } 607 608 head[0] = iphc0; 609 head[1] = iphc1; 610 611 skb_pull(skb, sizeof(struct ipv6hdr)); 612 skb_reset_transport_header(skb); 613 memcpy(skb_push(skb, hc_ptr - head), head, hc_ptr - head); 614 skb_reset_network_header(skb); 615 616 pr_debug("header len %d skb %u\n", (int)(hc_ptr - head), skb->len); 617 618 raw_dump_table(__func__, "raw skb data dump compressed", 619 skb->data, skb->len); 620 return 0; 621 } 622 EXPORT_SYMBOL_GPL(lowpan_header_compress); 623