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 * You should have received a copy of the GNU General Public License along 19 * with this program; if not, write to the Free Software Foundation, Inc., 20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 21 */ 22 23/* Jon's code is based on 6lowpan implementation for Contiki which is: 24 * Copyright (c) 2008, Swedish Institute of Computer Science. 25 * All rights reserved. 26 * 27 * Redistribution and use in source and binary forms, with or without 28 * modification, are permitted provided that the following conditions 29 * are met: 30 * 1. Redistributions of source code must retain the above copyright 31 * notice, this list of conditions and the following disclaimer. 32 * 2. Redistributions in binary form must reproduce the above copyright 33 * notice, this list of conditions and the following disclaimer in the 34 * documentation and/or other materials provided with the distribution. 35 * 3. Neither the name of the Institute nor the names of its contributors 36 * may be used to endorse or promote products derived from this software 37 * without specific prior written permission. 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 40 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 42 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 43 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 44 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 45 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 47 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 48 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 49 * SUCH DAMAGE. 50 */ 51 52#include <linux/bitops.h> 53#include <linux/if_arp.h> 54#include <linux/module.h> 55#include <linux/netdevice.h> 56#include <net/6lowpan.h> 57#include <net/ipv6.h> 58#include <net/af_ieee802154.h> 59 60/* Uncompress address function for source and 61 * destination address(non-multicast). 62 * 63 * address_mode is sam value or dam value. 64 */ 65static int uncompress_addr(struct sk_buff *skb, 66 struct in6_addr *ipaddr, const u8 address_mode, 67 const u8 *lladdr, const u8 addr_type, 68 const u8 addr_len) 69{ 70 bool fail; 71 72 switch (address_mode) { 73 case LOWPAN_IPHC_ADDR_00: 74 /* for global link addresses */ 75 fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16); 76 break; 77 case LOWPAN_IPHC_ADDR_01: 78 /* fe:80::XXXX:XXXX:XXXX:XXXX */ 79 ipaddr->s6_addr[0] = 0xFE; 80 ipaddr->s6_addr[1] = 0x80; 81 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8); 82 break; 83 case LOWPAN_IPHC_ADDR_02: 84 /* fe:80::ff:fe00:XXXX */ 85 ipaddr->s6_addr[0] = 0xFE; 86 ipaddr->s6_addr[1] = 0x80; 87 ipaddr->s6_addr[11] = 0xFF; 88 ipaddr->s6_addr[12] = 0xFE; 89 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2); 90 break; 91 case LOWPAN_IPHC_ADDR_03: 92 fail = false; 93 switch (addr_type) { 94 case IEEE802154_ADDR_LONG: 95 /* fe:80::XXXX:XXXX:XXXX:XXXX 96 * \_________________/ 97 * hwaddr 98 */ 99 ipaddr->s6_addr[0] = 0xFE; 100 ipaddr->s6_addr[1] = 0x80; 101 memcpy(&ipaddr->s6_addr[8], lladdr, addr_len); 102 /* second bit-flip (Universe/Local) 103 * is done according RFC2464 104 */ 105 ipaddr->s6_addr[8] ^= 0x02; 106 break; 107 case IEEE802154_ADDR_SHORT: 108 /* fe:80::ff:fe00:XXXX 109 * \__/ 110 * short_addr 111 * 112 * Universe/Local bit is zero. 113 */ 114 ipaddr->s6_addr[0] = 0xFE; 115 ipaddr->s6_addr[1] = 0x80; 116 ipaddr->s6_addr[11] = 0xFF; 117 ipaddr->s6_addr[12] = 0xFE; 118 ipaddr->s6_addr16[7] = htons(*((u16 *)lladdr)); 119 break; 120 default: 121 pr_debug("Invalid addr_type set\n"); 122 return -EINVAL; 123 } 124 break; 125 default: 126 pr_debug("Invalid address mode value: 0x%x\n", address_mode); 127 return -EINVAL; 128 } 129 130 if (fail) { 131 pr_debug("Failed to fetch skb data\n"); 132 return -EIO; 133 } 134 135 raw_dump_inline(NULL, "Reconstructed ipv6 addr is", 136 ipaddr->s6_addr, 16); 137 138 return 0; 139} 140 141/* Uncompress address function for source context 142 * based address(non-multicast). 143 */ 144static int uncompress_context_based_src_addr(struct sk_buff *skb, 145 struct in6_addr *ipaddr, 146 const u8 sam) 147{ 148 switch (sam) { 149 case LOWPAN_IPHC_ADDR_00: 150 /* unspec address :: 151 * Do nothing, address is already :: 152 */ 153 break; 154 case LOWPAN_IPHC_ADDR_01: 155 /* TODO */ 156 case LOWPAN_IPHC_ADDR_02: 157 /* TODO */ 158 case LOWPAN_IPHC_ADDR_03: 159 /* TODO */ 160 netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam); 161 return -EINVAL; 162 default: 163 pr_debug("Invalid sam value: 0x%x\n", sam); 164 return -EINVAL; 165 } 166 167 raw_dump_inline(NULL, 168 "Reconstructed context based ipv6 src addr is", 169 ipaddr->s6_addr, 16); 170 171 return 0; 172} 173 174static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr, 175 struct net_device *dev, skb_delivery_cb deliver_skb) 176{ 177 struct sk_buff *new; 178 int stat; 179 180 new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb), 181 GFP_ATOMIC); 182 kfree_skb(skb); 183 184 if (!new) 185 return -ENOMEM; 186 187 skb_push(new, sizeof(struct ipv6hdr)); 188 skb_reset_network_header(new); 189 skb_copy_to_linear_data(new, hdr, sizeof(struct ipv6hdr)); 190 191 new->protocol = htons(ETH_P_IPV6); 192 new->pkt_type = PACKET_HOST; 193 new->dev = dev; 194 195 raw_dump_table(__func__, "raw skb data dump before receiving", 196 new->data, new->len); 197 198 stat = deliver_skb(new, dev); 199 200 kfree_skb(new); 201 202 return stat; 203} 204 205/* Uncompress function for multicast destination address, 206 * when M bit is set. 207 */ 208static int lowpan_uncompress_multicast_daddr(struct sk_buff *skb, 209 struct in6_addr *ipaddr, 210 const u8 dam) 211{ 212 bool fail; 213 214 switch (dam) { 215 case LOWPAN_IPHC_DAM_00: 216 /* 00: 128 bits. The full address 217 * is carried in-line. 218 */ 219 fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16); 220 break; 221 case LOWPAN_IPHC_DAM_01: 222 /* 01: 48 bits. The address takes 223 * the form ffXX::00XX:XXXX:XXXX. 224 */ 225 ipaddr->s6_addr[0] = 0xFF; 226 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1); 227 fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5); 228 break; 229 case LOWPAN_IPHC_DAM_10: 230 /* 10: 32 bits. The address takes 231 * the form ffXX::00XX:XXXX. 232 */ 233 ipaddr->s6_addr[0] = 0xFF; 234 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1); 235 fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3); 236 break; 237 case LOWPAN_IPHC_DAM_11: 238 /* 11: 8 bits. The address takes 239 * the form ff02::00XX. 240 */ 241 ipaddr->s6_addr[0] = 0xFF; 242 ipaddr->s6_addr[1] = 0x02; 243 fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1); 244 break; 245 default: 246 pr_debug("DAM value has a wrong value: 0x%x\n", dam); 247 return -EINVAL; 248 } 249 250 if (fail) { 251 pr_debug("Failed to fetch skb data\n"); 252 return -EIO; 253 } 254 255 raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is", 256 ipaddr->s6_addr, 16); 257 258 return 0; 259} 260 261static int uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh) 262{ 263 bool fail; 264 u8 tmp = 0, val = 0; 265 266 fail = lowpan_fetch_skb(skb, &tmp, sizeof(tmp)); 267 268 if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) { 269 pr_debug("UDP header uncompression\n"); 270 switch (tmp & LOWPAN_NHC_UDP_CS_P_11) { 271 case LOWPAN_NHC_UDP_CS_P_00: 272 fail |= lowpan_fetch_skb(skb, &uh->source, 273 sizeof(uh->source)); 274 fail |= lowpan_fetch_skb(skb, &uh->dest, 275 sizeof(uh->dest)); 276 break; 277 case LOWPAN_NHC_UDP_CS_P_01: 278 fail |= lowpan_fetch_skb(skb, &uh->source, 279 sizeof(uh->source)); 280 fail |= lowpan_fetch_skb(skb, &val, sizeof(val)); 281 uh->dest = htons(val + LOWPAN_NHC_UDP_8BIT_PORT); 282 break; 283 case LOWPAN_NHC_UDP_CS_P_10: 284 fail |= lowpan_fetch_skb(skb, &val, sizeof(val)); 285 uh->source = htons(val + LOWPAN_NHC_UDP_8BIT_PORT); 286 fail |= lowpan_fetch_skb(skb, &uh->dest, 287 sizeof(uh->dest)); 288 break; 289 case LOWPAN_NHC_UDP_CS_P_11: 290 fail |= lowpan_fetch_skb(skb, &val, sizeof(val)); 291 uh->source = htons(LOWPAN_NHC_UDP_4BIT_PORT + 292 (val >> 4)); 293 uh->dest = htons(LOWPAN_NHC_UDP_4BIT_PORT + 294 (val & 0x0f)); 295 break; 296 default: 297 pr_debug("ERROR: unknown UDP format\n"); 298 goto err; 299 } 300 301 pr_debug("uncompressed UDP ports: src = %d, dst = %d\n", 302 ntohs(uh->source), ntohs(uh->dest)); 303 304 /* checksum */ 305 if (tmp & LOWPAN_NHC_UDP_CS_C) { 306 pr_debug_ratelimited("checksum elided currently not supported\n"); 307 goto err; 308 } else { 309 fail |= lowpan_fetch_skb(skb, &uh->check, 310 sizeof(uh->check)); 311 } 312 313 /* UDP length needs to be infered from the lower layers 314 * here, we obtain the hint from the remaining size of the 315 * frame 316 */ 317 uh->len = htons(skb->len + sizeof(struct udphdr)); 318 pr_debug("uncompressed UDP length: src = %d", ntohs(uh->len)); 319 } else { 320 pr_debug("ERROR: unsupported NH format\n"); 321 goto err; 322 } 323 324 if (fail) 325 goto err; 326 327 return 0; 328err: 329 return -EINVAL; 330} 331 332/* TTL uncompression values */ 333static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 }; 334 335int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, 336 const u8 *saddr, const u8 saddr_type, const u8 saddr_len, 337 const u8 *daddr, const u8 daddr_type, const u8 daddr_len, 338 u8 iphc0, u8 iphc1, skb_delivery_cb deliver_skb) 339{ 340 struct ipv6hdr hdr = {}; 341 u8 tmp, num_context = 0; 342 int err; 343 344 raw_dump_table(__func__, "raw skb data dump uncompressed", 345 skb->data, skb->len); 346 347 /* another if the CID flag is set */ 348 if (iphc1 & LOWPAN_IPHC_CID) { 349 pr_debug("CID flag is set, increase header with one\n"); 350 if (lowpan_fetch_skb(skb, &num_context, sizeof(num_context))) 351 goto drop; 352 } 353 354 hdr.version = 6; 355 356 /* Traffic Class and Flow Label */ 357 switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) { 358 /* Traffic Class and FLow Label carried in-line 359 * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes) 360 */ 361 case 0: /* 00b */ 362 if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) 363 goto drop; 364 365 memcpy(&hdr.flow_lbl, &skb->data[0], 3); 366 skb_pull(skb, 3); 367 hdr.priority = ((tmp >> 2) & 0x0f); 368 hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) | 369 (hdr.flow_lbl[0] & 0x0f); 370 break; 371 /* Traffic class carried in-line 372 * ECN + DSCP (1 byte), Flow Label is elided 373 */ 374 case 2: /* 10b */ 375 if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) 376 goto drop; 377 378 hdr.priority = ((tmp >> 2) & 0x0f); 379 hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30); 380 break; 381 /* Flow Label carried in-line 382 * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided 383 */ 384 case 1: /* 01b */ 385 if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) 386 goto drop; 387 388 hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30); 389 memcpy(&hdr.flow_lbl[1], &skb->data[0], 2); 390 skb_pull(skb, 2); 391 break; 392 /* Traffic Class and Flow Label are elided */ 393 case 3: /* 11b */ 394 break; 395 default: 396 break; 397 } 398 399 /* Next Header */ 400 if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { 401 /* Next header is carried inline */ 402 if (lowpan_fetch_skb(skb, &hdr.nexthdr, sizeof(hdr.nexthdr))) 403 goto drop; 404 405 pr_debug("NH flag is set, next header carried inline: %02x\n", 406 hdr.nexthdr); 407 } 408 409 /* Hop Limit */ 410 if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I) { 411 hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03]; 412 } else { 413 if (lowpan_fetch_skb(skb, &hdr.hop_limit, 414 sizeof(hdr.hop_limit))) 415 goto drop; 416 } 417 418 /* Extract SAM to the tmp variable */ 419 tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03; 420 421 if (iphc1 & LOWPAN_IPHC_SAC) { 422 /* Source address context based uncompression */ 423 pr_debug("SAC bit is set. Handle context based source address.\n"); 424 err = uncompress_context_based_src_addr(skb, &hdr.saddr, tmp); 425 } else { 426 /* Source address uncompression */ 427 pr_debug("source address stateless compression\n"); 428 err = uncompress_addr(skb, &hdr.saddr, tmp, saddr, 429 saddr_type, saddr_len); 430 } 431 432 /* Check on error of previous branch */ 433 if (err) 434 goto drop; 435 436 /* Extract DAM to the tmp variable */ 437 tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03; 438 439 /* check for Multicast Compression */ 440 if (iphc1 & LOWPAN_IPHC_M) { 441 if (iphc1 & LOWPAN_IPHC_DAC) { 442 pr_debug("dest: context-based mcast compression\n"); 443 /* TODO: implement this */ 444 } else { 445 err = lowpan_uncompress_multicast_daddr(skb, &hdr.daddr, 446 tmp); 447 448 if (err) 449 goto drop; 450 } 451 } else { 452 err = uncompress_addr(skb, &hdr.daddr, tmp, daddr, 453 daddr_type, daddr_len); 454 pr_debug("dest: stateless compression mode %d dest %pI6c\n", 455 tmp, &hdr.daddr); 456 if (err) 457 goto drop; 458 } 459 460 /* UDP data uncompression */ 461 if (iphc0 & LOWPAN_IPHC_NH_C) { 462 struct udphdr uh; 463 struct sk_buff *new; 464 465 if (uncompress_udp_header(skb, &uh)) 466 goto drop; 467 468 /* replace the compressed UDP head by the uncompressed UDP 469 * header 470 */ 471 new = skb_copy_expand(skb, sizeof(struct udphdr), 472 skb_tailroom(skb), GFP_ATOMIC); 473 kfree_skb(skb); 474 475 if (!new) 476 return -ENOMEM; 477 478 skb = new; 479 480 skb_push(skb, sizeof(struct udphdr)); 481 skb_reset_transport_header(skb); 482 skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr)); 483 484 raw_dump_table(__func__, "raw UDP header dump", 485 (u8 *)&uh, sizeof(uh)); 486 487 hdr.nexthdr = UIP_PROTO_UDP; 488 } 489 490 hdr.payload_len = htons(skb->len); 491 492 pr_debug("skb headroom size = %d, data length = %d\n", 493 skb_headroom(skb), skb->len); 494 495 pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n\t" 496 "nexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n", 497 hdr.version, ntohs(hdr.payload_len), hdr.nexthdr, 498 hdr.hop_limit, &hdr.daddr); 499 500 raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr)); 501 502 return skb_deliver(skb, &hdr, dev, deliver_skb); 503 504drop: 505 kfree_skb(skb); 506 return -EINVAL; 507} 508EXPORT_SYMBOL_GPL(lowpan_process_data); 509 510static u8 lowpan_compress_addr_64(u8 **hc_ptr, u8 shift, 511 const struct in6_addr *ipaddr, 512 const unsigned char *lladdr) 513{ 514 u8 val = 0; 515 516 if (is_addr_mac_addr_based(ipaddr, lladdr)) { 517 val = 3; /* 0-bits */ 518 pr_debug("address compression 0 bits\n"); 519 } else if (lowpan_is_iid_16_bit_compressable(ipaddr)) { 520 /* compress IID to 16 bits xxxx::XXXX */ 521 lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[7], 2); 522 val = 2; /* 16-bits */ 523 raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)", 524 *hc_ptr - 2, 2); 525 } else { 526 /* do not compress IID => xxxx::IID */ 527 lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[4], 8); 528 val = 1; /* 64-bits */ 529 raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)", 530 *hc_ptr - 8, 8); 531 } 532 533 return rol8(val, shift); 534} 535 536static void compress_udp_header(u8 **hc_ptr, struct sk_buff *skb) 537{ 538 struct udphdr *uh = udp_hdr(skb); 539 u8 tmp; 540 541 if (((ntohs(uh->source) & LOWPAN_NHC_UDP_4BIT_MASK) == 542 LOWPAN_NHC_UDP_4BIT_PORT) && 543 ((ntohs(uh->dest) & LOWPAN_NHC_UDP_4BIT_MASK) == 544 LOWPAN_NHC_UDP_4BIT_PORT)) { 545 pr_debug("UDP header: both ports compression to 4 bits\n"); 546 /* compression value */ 547 tmp = LOWPAN_NHC_UDP_CS_P_11; 548 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); 549 /* source and destination port */ 550 tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_4BIT_PORT + 551 ((ntohs(uh->source) - LOWPAN_NHC_UDP_4BIT_PORT) << 4); 552 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); 553 } else if ((ntohs(uh->dest) & LOWPAN_NHC_UDP_8BIT_MASK) == 554 LOWPAN_NHC_UDP_8BIT_PORT) { 555 pr_debug("UDP header: remove 8 bits of dest\n"); 556 /* compression value */ 557 tmp = LOWPAN_NHC_UDP_CS_P_01; 558 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); 559 /* source port */ 560 lowpan_push_hc_data(hc_ptr, &uh->source, sizeof(uh->source)); 561 /* destination port */ 562 tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_8BIT_PORT; 563 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); 564 } else if ((ntohs(uh->source) & LOWPAN_NHC_UDP_8BIT_MASK) == 565 LOWPAN_NHC_UDP_8BIT_PORT) { 566 pr_debug("UDP header: remove 8 bits of source\n"); 567 /* compression value */ 568 tmp = LOWPAN_NHC_UDP_CS_P_10; 569 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); 570 /* source port */ 571 tmp = ntohs(uh->source) - LOWPAN_NHC_UDP_8BIT_PORT; 572 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); 573 /* destination port */ 574 lowpan_push_hc_data(hc_ptr, &uh->dest, sizeof(uh->dest)); 575 } else { 576 pr_debug("UDP header: can't compress\n"); 577 /* compression value */ 578 tmp = LOWPAN_NHC_UDP_CS_P_00; 579 lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); 580 /* source port */ 581 lowpan_push_hc_data(hc_ptr, &uh->source, sizeof(uh->source)); 582 /* destination port */ 583 lowpan_push_hc_data(hc_ptr, &uh->dest, sizeof(uh->dest)); 584 } 585 586 /* checksum is always inline */ 587 lowpan_push_hc_data(hc_ptr, &uh->check, sizeof(uh->check)); 588 589 /* skip the UDP header */ 590 skb_pull(skb, sizeof(struct udphdr)); 591} 592 593int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, 594 unsigned short type, const void *_daddr, 595 const void *_saddr, unsigned int len) 596{ 597 u8 tmp, iphc0, iphc1, *hc_ptr; 598 struct ipv6hdr *hdr; 599 u8 head[100] = {}; 600 int addr_type; 601 602 if (type != ETH_P_IPV6) 603 return -EINVAL; 604 605 hdr = ipv6_hdr(skb); 606 hc_ptr = head + 2; 607 608 pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n" 609 "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n", 610 hdr->version, ntohs(hdr->payload_len), hdr->nexthdr, 611 hdr->hop_limit, &hdr->daddr); 612 613 raw_dump_table(__func__, "raw skb network header dump", 614 skb_network_header(skb), sizeof(struct ipv6hdr)); 615 616 /* As we copy some bit-length fields, in the IPHC encoding bytes, 617 * we sometimes use |= 618 * If the field is 0, and the current bit value in memory is 1, 619 * this does not work. We therefore reset the IPHC encoding here 620 */ 621 iphc0 = LOWPAN_DISPATCH_IPHC; 622 iphc1 = 0; 623 624 /* TODO: context lookup */ 625 626 raw_dump_inline(__func__, "saddr", 627 (unsigned char *)_saddr, IEEE802154_ADDR_LEN); 628 raw_dump_inline(__func__, "daddr", 629 (unsigned char *)_daddr, IEEE802154_ADDR_LEN); 630 631 raw_dump_table(__func__, "sending raw skb network uncompressed packet", 632 skb->data, skb->len); 633 634 /* Traffic class, flow label 635 * If flow label is 0, compress it. If traffic class is 0, compress it 636 * We have to process both in the same time as the offset of traffic 637 * class depends on the presence of version and flow label 638 */ 639 640 /* hc format of TC is ECN | DSCP , original one is DSCP | ECN */ 641 tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4); 642 tmp = ((tmp & 0x03) << 6) | (tmp >> 2); 643 644 if (((hdr->flow_lbl[0] & 0x0F) == 0) && 645 (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) { 646 /* flow label can be compressed */ 647 iphc0 |= LOWPAN_IPHC_FL_C; 648 if ((hdr->priority == 0) && 649 ((hdr->flow_lbl[0] & 0xF0) == 0)) { 650 /* compress (elide) all */ 651 iphc0 |= LOWPAN_IPHC_TC_C; 652 } else { 653 /* compress only the flow label */ 654 *hc_ptr = tmp; 655 hc_ptr += 1; 656 } 657 } else { 658 /* Flow label cannot be compressed */ 659 if ((hdr->priority == 0) && 660 ((hdr->flow_lbl[0] & 0xF0) == 0)) { 661 /* compress only traffic class */ 662 iphc0 |= LOWPAN_IPHC_TC_C; 663 *hc_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F); 664 memcpy(hc_ptr + 1, &hdr->flow_lbl[1], 2); 665 hc_ptr += 3; 666 } else { 667 /* compress nothing */ 668 memcpy(hc_ptr, hdr, 4); 669 /* replace the top byte with new ECN | DSCP format */ 670 *hc_ptr = tmp; 671 hc_ptr += 4; 672 } 673 } 674 675 /* NOTE: payload length is always compressed */ 676 677 /* Next Header is compress if UDP */ 678 if (hdr->nexthdr == UIP_PROTO_UDP) 679 iphc0 |= LOWPAN_IPHC_NH_C; 680 681 if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) 682 lowpan_push_hc_data(&hc_ptr, &hdr->nexthdr, 683 sizeof(hdr->nexthdr)); 684 685 /* Hop limit 686 * if 1: compress, encoding is 01 687 * if 64: compress, encoding is 10 688 * if 255: compress, encoding is 11 689 * else do not compress 690 */ 691 switch (hdr->hop_limit) { 692 case 1: 693 iphc0 |= LOWPAN_IPHC_TTL_1; 694 break; 695 case 64: 696 iphc0 |= LOWPAN_IPHC_TTL_64; 697 break; 698 case 255: 699 iphc0 |= LOWPAN_IPHC_TTL_255; 700 break; 701 default: 702 lowpan_push_hc_data(&hc_ptr, &hdr->hop_limit, 703 sizeof(hdr->hop_limit)); 704 } 705 706 addr_type = ipv6_addr_type(&hdr->saddr); 707 /* source address compression */ 708 if (addr_type == IPV6_ADDR_ANY) { 709 pr_debug("source address is unspecified, setting SAC\n"); 710 iphc1 |= LOWPAN_IPHC_SAC; 711 } else { 712 if (addr_type & IPV6_ADDR_LINKLOCAL) { 713 iphc1 |= lowpan_compress_addr_64(&hc_ptr, 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 } 722 } 723 724 addr_type = ipv6_addr_type(&hdr->daddr); 725 /* destination address compression */ 726 if (addr_type & IPV6_ADDR_MULTICAST) { 727 pr_debug("destination address is multicast: "); 728 iphc1 |= LOWPAN_IPHC_M; 729 if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) { 730 pr_debug("compressed to 1 octet\n"); 731 iphc1 |= LOWPAN_IPHC_DAM_11; 732 /* use last byte */ 733 lowpan_push_hc_data(&hc_ptr, 734 &hdr->daddr.s6_addr[15], 1); 735 } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) { 736 pr_debug("compressed to 4 octets\n"); 737 iphc1 |= LOWPAN_IPHC_DAM_10; 738 /* second byte + the last three */ 739 lowpan_push_hc_data(&hc_ptr, 740 &hdr->daddr.s6_addr[1], 1); 741 lowpan_push_hc_data(&hc_ptr, 742 &hdr->daddr.s6_addr[13], 3); 743 } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) { 744 pr_debug("compressed to 6 octets\n"); 745 iphc1 |= LOWPAN_IPHC_DAM_01; 746 /* second byte + the last five */ 747 lowpan_push_hc_data(&hc_ptr, 748 &hdr->daddr.s6_addr[1], 1); 749 lowpan_push_hc_data(&hc_ptr, 750 &hdr->daddr.s6_addr[11], 5); 751 } else { 752 pr_debug("using full address\n"); 753 iphc1 |= LOWPAN_IPHC_DAM_00; 754 lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16); 755 } 756 } else { 757 if (addr_type & IPV6_ADDR_LINKLOCAL) { 758 /* TODO: context lookup */ 759 iphc1 |= lowpan_compress_addr_64(&hc_ptr, 760 LOWPAN_IPHC_DAM_BIT, &hdr->daddr, _daddr); 761 pr_debug("dest address unicast link-local %pI6c " 762 "iphc1 0x%02x\n", &hdr->daddr, iphc1); 763 } else { 764 pr_debug("dest address unicast %pI6c\n", &hdr->daddr); 765 lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16); 766 } 767 } 768 769 /* UDP header compression */ 770 if (hdr->nexthdr == UIP_PROTO_UDP) 771 compress_udp_header(&hc_ptr, skb); 772 773 head[0] = iphc0; 774 head[1] = iphc1; 775 776 skb_pull(skb, sizeof(struct ipv6hdr)); 777 skb_reset_transport_header(skb); 778 memcpy(skb_push(skb, hc_ptr - head), head, hc_ptr - head); 779 skb_reset_network_header(skb); 780 781 pr_debug("header len %d skb %u\n", (int)(hc_ptr - head), skb->len); 782 783 raw_dump_table(__func__, "raw skb data dump compressed", 784 skb->data, skb->len); 785 return 0; 786} 787EXPORT_SYMBOL_GPL(lowpan_header_compress); 788 789MODULE_LICENSE("GPL"); 790