6lowpan.h revision 8df8c56a5abc70af5862aa7cac2875aeeb17a42b
18df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen/* 28df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * Copyright 2011, Siemens AG 38df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com> 48df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 58df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 68df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen/* 78df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * Based on patches from Jon Smirl <jonsmirl@gmail.com> 88df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com> 98df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * 108df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * This program is free software; you can redistribute it and/or modify 118df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * it under the terms of the GNU General Public License version 2 128df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * as published by the Free Software Foundation. 138df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * 148df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * This program is distributed in the hope that it will be useful, 158df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * but WITHOUT ANY WARRANTY; without even the implied warranty of 168df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 178df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * GNU General Public License for more details. 188df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * 198df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * You should have received a copy of the GNU General Public License along 208df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * with this program; if not, write to the Free Software Foundation, Inc., 218df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 228df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 238df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 248df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen/* Jon's code is based on 6lowpan implementation for Contiki which is: 258df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * Copyright (c) 2008, Swedish Institute of Computer Science. 268df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * All rights reserved. 278df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * 288df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * Redistribution and use in source and binary forms, with or without 298df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * modification, are permitted provided that the following conditions 308df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * are met: 318df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * 1. Redistributions of source code must retain the above copyright 328df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * notice, this list of conditions and the following disclaimer. 338df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * 2. Redistributions in binary form must reproduce the above copyright 348df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * notice, this list of conditions and the following disclaimer in the 358df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * documentation and/or other materials provided with the distribution. 368df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * 3. Neither the name of the Institute nor the names of its contributors 378df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * may be used to endorse or promote products derived from this software 388df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * without specific prior written permission. 398df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * 408df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 418df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 428df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 438df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 448df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 458df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 468df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 478df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 488df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 498df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 508df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * SUCH DAMAGE. 518df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 528df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 538df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen#include <linux/bitops.h> 548df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen#include <linux/if_arp.h> 558df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen#include <linux/netdevice.h> 568df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen#include <net/ipv6.h> 578df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen#include <net/af_ieee802154.h> 588df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 598df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen#include "6lowpan.h" 608df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 618df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen/* print data in line */ 628df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanenstatic inline void raw_dump_inline(const char *caller, char *msg, 638df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen unsigned char *buf, int len) 648df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen{ 658df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (msg) 668df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("%s():%s: ", caller, msg); 678df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen print_hex_dump_debug("", DUMP_PREFIX_NONE, 688df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 16, 1, buf, len, false); 698df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen} 708df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 718df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen/* 728df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * print data in a table format: 738df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * 748df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * addr: xx xx xx xx xx xx 758df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * addr: xx xx xx xx xx xx 768df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * ... 778df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 788df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanenstatic inline void raw_dump_table(const char *caller, char *msg, 798df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen unsigned char *buf, int len) 808df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen{ 818df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (msg) 828df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("%s():%s:\n", caller, msg); 838df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen print_hex_dump_debug("\t", DUMP_PREFIX_OFFSET, 848df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 16, 1, buf, len, false); 858df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen} 868df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 878df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen/* 888df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * Uncompress address function for source and 898df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * destination address(non-multicast). 908df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * 918df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * address_mode is sam value or dam value. 928df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 938df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanenstatic int uncompress_addr(struct sk_buff *skb, 948df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen struct in6_addr *ipaddr, const u8 address_mode, 958df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen const u8 *lladdr, const u8 addr_type, 968df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen const u8 addr_len) 978df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen{ 988df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen bool fail; 998df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 1008df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen switch (address_mode) { 1018df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case LOWPAN_IPHC_ADDR_00: 1028df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* for global link addresses */ 1038df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16); 1048df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 1058df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case LOWPAN_IPHC_ADDR_01: 1068df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* fe:80::XXXX:XXXX:XXXX:XXXX */ 1078df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr[0] = 0xFE; 1088df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr[1] = 0x80; 1098df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8); 1108df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 1118df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case LOWPAN_IPHC_ADDR_02: 1128df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* fe:80::ff:fe00:XXXX */ 1138df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr[0] = 0xFE; 1148df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr[1] = 0x80; 1158df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr[11] = 0xFF; 1168df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr[12] = 0xFE; 1178df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2); 1188df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 1198df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case LOWPAN_IPHC_ADDR_03: 1208df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen fail = false; 1218df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen switch (addr_type) { 1228df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case IEEE802154_ADDR_LONG: 1238df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* fe:80::XXXX:XXXX:XXXX:XXXX 1248df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * \_________________/ 1258df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * hwaddr 1268df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 1278df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr[0] = 0xFE; 1288df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr[1] = 0x80; 1298df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(&ipaddr->s6_addr[8], lladdr, addr_len); 1308df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* second bit-flip (Universe/Local) 1318df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * is done according RFC2464 1328df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 1338df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr[8] ^= 0x02; 1348df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 1358df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case IEEE802154_ADDR_SHORT: 1368df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* fe:80::ff:fe00:XXXX 1378df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * \__/ 1388df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * short_addr 1398df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * 1408df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * Universe/Local bit is zero. 1418df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 1428df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr[0] = 0xFE; 1438df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr[1] = 0x80; 1448df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr[11] = 0xFF; 1458df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr[12] = 0xFE; 1468df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr16[7] = htons(*((u16 *)lladdr)); 1478df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 1488df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen default: 1498df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("Invalid addr_type set\n"); 1508df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen return -EINVAL; 1518df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 1528df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 1538df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen default: 1548df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("Invalid address mode value: 0x%x\n", address_mode); 1558df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen return -EINVAL; 1568df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 1578df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 1588df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (fail) { 1598df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("Failed to fetch skb data\n"); 1608df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen return -EIO; 1618df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 1628df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 1638df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen raw_dump_inline(NULL, "Reconstructed ipv6 addr is", 1648df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr, 16); 1658df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 1668df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen return 0; 1678df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen} 1688df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 1698df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen/* 1708df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * Uncompress address function for source context 1718df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * based address(non-multicast). 1728df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 1738df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanenstatic int uncompress_context_based_src_addr(struct sk_buff *skb, 1748df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen struct in6_addr *ipaddr, 1758df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen const u8 sam) 1768df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen{ 1778df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen switch (sam) { 1788df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case LOWPAN_IPHC_ADDR_00: 1798df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* unspec address :: 1808df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * Do nothing, address is already :: 1818df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 1828df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 1838df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case LOWPAN_IPHC_ADDR_01: 1848df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* TODO */ 1858df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case LOWPAN_IPHC_ADDR_02: 1868df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* TODO */ 1878df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case LOWPAN_IPHC_ADDR_03: 1888df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* TODO */ 1898df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam); 1908df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen return -EINVAL; 1918df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen default: 1928df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("Invalid sam value: 0x%x\n", sam); 1938df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen return -EINVAL; 1948df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 1958df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 1968df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen raw_dump_inline(NULL, 1978df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen "Reconstructed context based ipv6 src addr is", 1988df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr, 16); 1998df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 2008df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen return 0; 2018df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen} 2028df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 2038df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanenstatic int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr, 2048df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen struct net_device *dev, skb_delivery_cb deliver_skb) 2058df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen{ 2068df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen struct sk_buff *new; 2078df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen int stat; 2088df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 2098df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb), 2108df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen GFP_ATOMIC); 2118df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen kfree_skb(skb); 2128df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 2138df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (!new) 2148df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen return -ENOMEM; 2158df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 2168df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb_push(new, sizeof(struct ipv6hdr)); 2178df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb_reset_network_header(new); 2188df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb_copy_to_linear_data(new, hdr, sizeof(struct ipv6hdr)); 2198df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 2208df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen new->protocol = htons(ETH_P_IPV6); 2218df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen new->pkt_type = PACKET_HOST; 2228df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen new->dev = dev; 2238df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 2248df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen raw_dump_table(__func__, "raw skb data dump before receiving", 2258df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen new->data, new->len); 2268df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 2278df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen stat = deliver_skb(new, dev); 2288df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 2298df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen kfree_skb(new); 2308df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 2318df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen return stat; 2328df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen} 2338df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 2348df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen/* Uncompress function for multicast destination address, 2358df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * when M bit is set. 2368df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 2378df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanenstatic int 2388df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanenlowpan_uncompress_multicast_daddr(struct sk_buff *skb, 2398df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen struct in6_addr *ipaddr, 2408df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen const u8 dam) 2418df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen{ 2428df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen bool fail; 2438df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 2448df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen switch (dam) { 2458df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case LOWPAN_IPHC_DAM_00: 2468df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* 00: 128 bits. The full address 2478df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * is carried in-line. 2488df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 2498df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16); 2508df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 2518df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case LOWPAN_IPHC_DAM_01: 2528df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* 01: 48 bits. The address takes 2538df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * the form ffXX::00XX:XXXX:XXXX. 2548df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 2558df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr[0] = 0xFF; 2568df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1); 2578df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5); 2588df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 2598df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case LOWPAN_IPHC_DAM_10: 2608df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* 10: 32 bits. The address takes 2618df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * the form ffXX::00XX:XXXX. 2628df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 2638df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr[0] = 0xFF; 2648df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1); 2658df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3); 2668df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 2678df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case LOWPAN_IPHC_DAM_11: 2688df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* 11: 8 bits. The address takes 2698df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * the form ff02::00XX. 2708df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 2718df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr[0] = 0xFF; 2728df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr[1] = 0x02; 2738df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1); 2748df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 2758df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen default: 2768df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("DAM value has a wrong value: 0x%x\n", dam); 2778df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen return -EINVAL; 2788df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 2798df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 2808df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (fail) { 2818df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("Failed to fetch skb data\n"); 2828df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen return -EIO; 2838df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 2848df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 2858df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is", 2868df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ipaddr->s6_addr, 16); 2878df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 2888df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen return 0; 2898df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen} 2908df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 2918df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanenstatic int 2928df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanenuncompress_udp_header(struct sk_buff *skb, struct udphdr *uh) 2938df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen{ 2948df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen u8 tmp; 2958df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 2968df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (!uh) 2978df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen goto err; 2988df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 2998df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (lowpan_fetch_skb_u8(skb, &tmp)) 3008df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen goto err; 3018df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 3028df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) { 3038df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("UDP header uncompression\n"); 3048df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen switch (tmp & LOWPAN_NHC_UDP_CS_P_11) { 3058df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case LOWPAN_NHC_UDP_CS_P_00: 3068df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(&uh->source, &skb->data[0], 2); 3078df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(&uh->dest, &skb->data[2], 2); 3088df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb_pull(skb, 4); 3098df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 3108df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case LOWPAN_NHC_UDP_CS_P_01: 3118df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(&uh->source, &skb->data[0], 2); 3128df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen uh->dest = 3138df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb->data[2] + LOWPAN_NHC_UDP_8BIT_PORT; 3148df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb_pull(skb, 3); 3158df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 3168df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case LOWPAN_NHC_UDP_CS_P_10: 3178df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen uh->source = skb->data[0] + LOWPAN_NHC_UDP_8BIT_PORT; 3188df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(&uh->dest, &skb->data[1], 2); 3198df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb_pull(skb, 3); 3208df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 3218df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case LOWPAN_NHC_UDP_CS_P_11: 3228df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen uh->source = 3238df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen LOWPAN_NHC_UDP_4BIT_PORT + (skb->data[0] >> 4); 3248df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen uh->dest = 3258df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen LOWPAN_NHC_UDP_4BIT_PORT + (skb->data[0] & 0x0f); 3268df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb_pull(skb, 1); 3278df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 3288df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen default: 3298df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("ERROR: unknown UDP format\n"); 3308df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen goto err; 3318df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 3328df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 3338df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 3348df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("uncompressed UDP ports: src = %d, dst = %d\n", 3358df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen uh->source, uh->dest); 3368df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 3378df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* copy checksum */ 3388df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(&uh->check, &skb->data[0], 2); 3398df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb_pull(skb, 2); 3408df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 3418df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* 3428df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * UDP lenght needs to be infered from the lower layers 3438df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * here, we obtain the hint from the remaining size of the 3448df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * frame 3458df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 3468df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen uh->len = htons(skb->len + sizeof(struct udphdr)); 3478df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("uncompressed UDP length: src = %d", uh->len); 3488df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } else { 3498df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("ERROR: unsupported NH format\n"); 3508df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen goto err; 3518df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 3528df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 3538df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen return 0; 3548df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanenerr: 3558df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen return -EINVAL; 3568df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen} 3578df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 3588df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen/* TTL uncompression values */ 3598df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanenstatic const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 }; 3608df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 3618df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanenint lowpan_process_data(struct sk_buff *skb, struct net_device *dev, 3628df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen const u8 *saddr, const u8 saddr_type, const u8 saddr_len, 3638df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen const u8 *daddr, const u8 daddr_type, const u8 daddr_len, 3648df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen u8 iphc0, u8 iphc1, skb_delivery_cb deliver_skb) 3658df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen{ 3668df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen struct ipv6hdr hdr = {}; 3678df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen u8 tmp, num_context = 0; 3688df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen int err; 3698df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 3708df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen raw_dump_table(__func__, "raw skb data dump uncompressed", 3718df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb->data, skb->len); 3728df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 3738df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* another if the CID flag is set */ 3748df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (iphc1 & LOWPAN_IPHC_CID) { 3758df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("CID flag is set, increase header with one\n"); 3768df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (lowpan_fetch_skb_u8(skb, &num_context)) 3778df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen goto drop; 3788df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 3798df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 3808df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hdr.version = 6; 3818df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 3828df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* Traffic Class and Flow Label */ 3838df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) { 3848df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* 3858df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * Traffic Class and FLow Label carried in-line 3868df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes) 3878df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 3888df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case 0: /* 00b */ 3898df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (lowpan_fetch_skb_u8(skb, &tmp)) 3908df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen goto drop; 3918df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 3928df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(&hdr.flow_lbl, &skb->data[0], 3); 3938df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb_pull(skb, 3); 3948df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hdr.priority = ((tmp >> 2) & 0x0f); 3958df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) | 3968df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen (hdr.flow_lbl[0] & 0x0f); 3978df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 3988df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* 3998df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * Traffic class carried in-line 4008df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * ECN + DSCP (1 byte), Flow Label is elided 4018df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 4028df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case 2: /* 10b */ 4038df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (lowpan_fetch_skb_u8(skb, &tmp)) 4048df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen goto drop; 4058df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 4068df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hdr.priority = ((tmp >> 2) & 0x0f); 4078df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30); 4088df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 4098df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* 4108df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * Flow Label carried in-line 4118df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided 4128df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 4138df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case 1: /* 01b */ 4148df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (lowpan_fetch_skb_u8(skb, &tmp)) 4158df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen goto drop; 4168df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 4178df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30); 4188df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(&hdr.flow_lbl[1], &skb->data[0], 2); 4198df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb_pull(skb, 2); 4208df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 4218df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* Traffic Class and Flow Label are elided */ 4228df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case 3: /* 11b */ 4238df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 4248df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen default: 4258df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 4268df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 4278df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 4288df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* Next Header */ 4298df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { 4308df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* Next header is carried inline */ 4318df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (lowpan_fetch_skb_u8(skb, &(hdr.nexthdr))) 4328df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen goto drop; 4338df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 4348df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("NH flag is set, next header carried inline: %02x\n", 4358df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hdr.nexthdr); 4368df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 4378df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 4388df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* Hop Limit */ 4398df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I) 4408df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03]; 4418df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen else { 4428df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (lowpan_fetch_skb_u8(skb, &(hdr.hop_limit))) 4438df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen goto drop; 4448df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 4458df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 4468df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* Extract SAM to the tmp variable */ 4478df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03; 4488df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 4498df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (iphc1 & LOWPAN_IPHC_SAC) { 4508df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* Source address context based uncompression */ 4518df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("SAC bit is set. Handle context based source address.\n"); 4528df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen err = uncompress_context_based_src_addr( 4538df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb, &hdr.saddr, tmp); 4548df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } else { 4558df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* Source address uncompression */ 4568df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("source address stateless compression\n"); 4578df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen err = uncompress_addr(skb, &hdr.saddr, tmp, saddr, 4588df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen saddr_type, saddr_len); 4598df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 4608df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 4618df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* Check on error of previous branch */ 4628df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (err) 4638df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen goto drop; 4648df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 4658df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* Extract DAM to the tmp variable */ 4668df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03; 4678df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 4688df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* check for Multicast Compression */ 4698df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (iphc1 & LOWPAN_IPHC_M) { 4708df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (iphc1 & LOWPAN_IPHC_DAC) { 4718df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("dest: context-based mcast compression\n"); 4728df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* TODO: implement this */ 4738df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } else { 4748df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen err = lowpan_uncompress_multicast_daddr( 4758df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb, &hdr.daddr, tmp); 4768df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (err) 4778df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen goto drop; 4788df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 4798df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } else { 4808df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen err = uncompress_addr(skb, &hdr.daddr, tmp, daddr, 4818df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen daddr_type, daddr_len); 4828df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("dest: stateless compression mode %d dest %pI6c\n", 4838df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen tmp, &hdr.daddr); 4848df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (err) 4858df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen goto drop; 4868df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 4878df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 4888df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* UDP data uncompression */ 4898df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (iphc0 & LOWPAN_IPHC_NH_C) { 4908df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen struct udphdr uh; 4918df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen struct sk_buff *new; 4928df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (uncompress_udp_header(skb, &uh)) 4938df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen goto drop; 4948df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 4958df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* 4968df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * replace the compressed UDP head by the uncompressed UDP 4978df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * header 4988df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 4998df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen new = skb_copy_expand(skb, sizeof(struct udphdr), 5008df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb_tailroom(skb), GFP_ATOMIC); 5018df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen kfree_skb(skb); 5028df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 5038df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (!new) 5048df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen return -ENOMEM; 5058df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 5068df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb = new; 5078df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 5088df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb_push(skb, sizeof(struct udphdr)); 5098df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb_reset_transport_header(skb); 5108df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr)); 5118df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 5128df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen raw_dump_table(__func__, "raw UDP header dump", 5138df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen (u8 *)&uh, sizeof(uh)); 5148df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 5158df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hdr.nexthdr = UIP_PROTO_UDP; 5168df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 5178df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 5188df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hdr.payload_len = htons(skb->len); 5198df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 5208df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("skb headroom size = %d, data length = %d\n", 5218df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb_headroom(skb), skb->len); 5228df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 5238df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n\t" 5248df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen "nexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n", 5258df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hdr.version, ntohs(hdr.payload_len), hdr.nexthdr, 5268df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hdr.hop_limit, &hdr.daddr); 5278df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 5288df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, 5298df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen sizeof(hdr)); 5308df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 5318df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen return skb_deliver(skb, &hdr, dev, deliver_skb); 5328df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 5338df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanendrop: 5348df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen kfree_skb(skb); 5358df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen return -EINVAL; 5368df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen} 5378df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka RissanenEXPORT_SYMBOL_GPL(lowpan_process_data); 5388df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 5398df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanenstatic u8 lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift, 5408df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen const struct in6_addr *ipaddr, 5418df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen const unsigned char *lladdr) 5428df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen{ 5438df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen u8 val = 0; 5448df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 5458df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (is_addr_mac_addr_based(ipaddr, lladdr)) { 5468df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen val = 3; /* 0-bits */ 5478df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("address compression 0 bits\n"); 5488df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } else if (lowpan_is_iid_16_bit_compressable(ipaddr)) { 5498df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* compress IID to 16 bits xxxx::XXXX */ 5508df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(*hc06_ptr, &ipaddr->s6_addr16[7], 2); 5518df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen *hc06_ptr += 2; 5528df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen val = 2; /* 16-bits */ 5538df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)", 5548df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen *hc06_ptr - 2, 2); 5558df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } else { 5568df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* do not compress IID => xxxx::IID */ 5578df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(*hc06_ptr, &ipaddr->s6_addr16[4], 8); 5588df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen *hc06_ptr += 8; 5598df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen val = 1; /* 64-bits */ 5608df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)", 5618df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen *hc06_ptr - 8, 8); 5628df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 5638df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 5648df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen return rol8(val, shift); 5658df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen} 5668df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 5678df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanenstatic void compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb) 5688df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen{ 5698df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen struct udphdr *uh = udp_hdr(skb); 5708df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 5718df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (((uh->source & LOWPAN_NHC_UDP_4BIT_MASK) == 5728df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen LOWPAN_NHC_UDP_4BIT_PORT) && 5738df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ((uh->dest & LOWPAN_NHC_UDP_4BIT_MASK) == 5748df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen LOWPAN_NHC_UDP_4BIT_PORT)) { 5758df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("UDP header: both ports compression to 4 bits\n"); 5768df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen **hc06_ptr = LOWPAN_NHC_UDP_CS_P_11; 5778df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen **(hc06_ptr + 1) = /* subtraction is faster */ 5788df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen (u8)((uh->dest - LOWPAN_NHC_UDP_4BIT_PORT) + 5798df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ((uh->source & LOWPAN_NHC_UDP_4BIT_PORT) << 4)); 5808df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen *hc06_ptr += 2; 5818df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } else if ((uh->dest & LOWPAN_NHC_UDP_8BIT_MASK) == 5828df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen LOWPAN_NHC_UDP_8BIT_PORT) { 5838df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("UDP header: remove 8 bits of dest\n"); 5848df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen **hc06_ptr = LOWPAN_NHC_UDP_CS_P_01; 5858df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(*hc06_ptr + 1, &uh->source, 2); 5868df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen **(hc06_ptr + 3) = (u8)(uh->dest - LOWPAN_NHC_UDP_8BIT_PORT); 5878df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen *hc06_ptr += 4; 5888df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } else if ((uh->source & LOWPAN_NHC_UDP_8BIT_MASK) == 5898df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen LOWPAN_NHC_UDP_8BIT_PORT) { 5908df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("UDP header: remove 8 bits of source\n"); 5918df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen **hc06_ptr = LOWPAN_NHC_UDP_CS_P_10; 5928df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(*hc06_ptr + 1, &uh->dest, 2); 5938df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen **(hc06_ptr + 3) = (u8)(uh->source - LOWPAN_NHC_UDP_8BIT_PORT); 5948df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen *hc06_ptr += 4; 5958df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } else { 5968df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("UDP header: can't compress\n"); 5978df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen **hc06_ptr = LOWPAN_NHC_UDP_CS_P_00; 5988df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(*hc06_ptr + 1, &uh->source, 2); 5998df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(*hc06_ptr + 3, &uh->dest, 2); 6008df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen *hc06_ptr += 5; 6018df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 6028df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 6038df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* checksum is always inline */ 6048df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(*hc06_ptr, &uh->check, 2); 6058df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen *hc06_ptr += 2; 6068df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 6078df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* skip the UDP header */ 6088df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb_pull(skb, sizeof(struct udphdr)); 6098df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen} 6108df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 6118df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanenint lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, 6128df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen unsigned short type, const void *_daddr, 6138df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen const void *_saddr, unsigned int len) 6148df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen{ 6158df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen u8 tmp, iphc0, iphc1, *hc06_ptr; 6168df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen struct ipv6hdr *hdr; 6178df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen u8 head[100] = {}; 6188df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 6198df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (type != ETH_P_IPV6) 6208df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen return -EINVAL; 6218df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 6228df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hdr = ipv6_hdr(skb); 6238df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hc06_ptr = head + 2; 6248df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 6258df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n" 6268df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n", 6278df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hdr->version, ntohs(hdr->payload_len), hdr->nexthdr, 6288df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hdr->hop_limit, &hdr->daddr); 6298df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 6308df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen raw_dump_table(__func__, "raw skb network header dump", 6318df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb_network_header(skb), sizeof(struct ipv6hdr)); 6328df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 6338df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* 6348df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * As we copy some bit-length fields, in the IPHC encoding bytes, 6358df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * we sometimes use |= 6368df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * If the field is 0, and the current bit value in memory is 1, 6378df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * this does not work. We therefore reset the IPHC encoding here 6388df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 6398df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen iphc0 = LOWPAN_DISPATCH_IPHC; 6408df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen iphc1 = 0; 6418df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 6428df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* TODO: context lookup */ 6438df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 6448df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen raw_dump_inline(__func__, "saddr", 6458df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen (unsigned char *)_saddr, IEEE802154_ADDR_LEN); 6468df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen raw_dump_inline(__func__, "daddr", 6478df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen (unsigned char *)_daddr, IEEE802154_ADDR_LEN); 6488df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 6498df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen raw_dump_table(__func__, 6508df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen "sending raw skb network uncompressed packet", 6518df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb->data, skb->len); 6528df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 6538df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* 6548df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * Traffic class, flow label 6558df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * If flow label is 0, compress it. If traffic class is 0, compress it 6568df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * We have to process both in the same time as the offset of traffic 6578df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * class depends on the presence of version and flow label 6588df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 6598df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 6608df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* hc06 format of TC is ECN | DSCP , original one is DSCP | ECN */ 6618df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4); 6628df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen tmp = ((tmp & 0x03) << 6) | (tmp >> 2); 6638df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 6648df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (((hdr->flow_lbl[0] & 0x0F) == 0) && 6658df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) { 6668df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* flow label can be compressed */ 6678df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen iphc0 |= LOWPAN_IPHC_FL_C; 6688df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if ((hdr->priority == 0) && 6698df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ((hdr->flow_lbl[0] & 0xF0) == 0)) { 6708df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* compress (elide) all */ 6718df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen iphc0 |= LOWPAN_IPHC_TC_C; 6728df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } else { 6738df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* compress only the flow label */ 6748df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen *hc06_ptr = tmp; 6758df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hc06_ptr += 1; 6768df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 6778df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } else { 6788df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* Flow label cannot be compressed */ 6798df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if ((hdr->priority == 0) && 6808df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen ((hdr->flow_lbl[0] & 0xF0) == 0)) { 6818df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* compress only traffic class */ 6828df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen iphc0 |= LOWPAN_IPHC_TC_C; 6838df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen *hc06_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F); 6848df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(hc06_ptr + 1, &hdr->flow_lbl[1], 2); 6858df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hc06_ptr += 3; 6868df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } else { 6878df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* compress nothing */ 6888df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(hc06_ptr, &hdr, 4); 6898df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* replace the top byte with new ECN | DSCP format */ 6908df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen *hc06_ptr = tmp; 6918df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hc06_ptr += 4; 6928df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 6938df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 6948df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 6958df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* NOTE: payload length is always compressed */ 6968df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 6978df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* Next Header is compress if UDP */ 6988df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (hdr->nexthdr == UIP_PROTO_UDP) 6998df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen iphc0 |= LOWPAN_IPHC_NH_C; 7008df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 7018df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { 7028df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen *hc06_ptr = hdr->nexthdr; 7038df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hc06_ptr += 1; 7048df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 7058df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 7068df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* 7078df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * Hop limit 7088df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * if 1: compress, encoding is 01 7098df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * if 64: compress, encoding is 10 7108df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * if 255: compress, encoding is 11 7118df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen * else do not compress 7128df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen */ 7138df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen switch (hdr->hop_limit) { 7148df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case 1: 7158df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen iphc0 |= LOWPAN_IPHC_TTL_1; 7168df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 7178df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case 64: 7188df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen iphc0 |= LOWPAN_IPHC_TTL_64; 7198df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 7208df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen case 255: 7218df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen iphc0 |= LOWPAN_IPHC_TTL_255; 7228df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 7238df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen default: 7248df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen *hc06_ptr = hdr->hop_limit; 7258df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hc06_ptr += 1; 7268df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen break; 7278df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 7288df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 7298df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* source address compression */ 7308df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (is_addr_unspecified(&hdr->saddr)) { 7318df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("source address is unspecified, setting SAC\n"); 7328df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen iphc1 |= LOWPAN_IPHC_SAC; 7338df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* TODO: context lookup */ 7348df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } else if (is_addr_link_local(&hdr->saddr)) { 7358df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen iphc1 |= lowpan_compress_addr_64(&hc06_ptr, 7368df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen LOWPAN_IPHC_SAM_BIT, &hdr->saddr, _saddr); 7378df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("source address unicast link-local %pI6c " 7388df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen "iphc1 0x%02x\n", &hdr->saddr, iphc1); 7398df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } else { 7408df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("send the full source address\n"); 7418df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(hc06_ptr, &hdr->saddr.s6_addr16[0], 16); 7428df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hc06_ptr += 16; 7438df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 7448df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 7458df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* destination address compression */ 7468df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (is_addr_mcast(&hdr->daddr)) { 7478df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("destination address is multicast: "); 7488df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen iphc1 |= LOWPAN_IPHC_M; 7498df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) { 7508df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("compressed to 1 octet\n"); 7518df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen iphc1 |= LOWPAN_IPHC_DAM_11; 7528df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* use last byte */ 7538df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen *hc06_ptr = hdr->daddr.s6_addr[15]; 7548df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hc06_ptr += 1; 7558df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) { 7568df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("compressed to 4 octets\n"); 7578df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen iphc1 |= LOWPAN_IPHC_DAM_10; 7588df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* second byte + the last three */ 7598df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen *hc06_ptr = hdr->daddr.s6_addr[1]; 7608df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[13], 3); 7618df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hc06_ptr += 4; 7628df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) { 7638df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("compressed to 6 octets\n"); 7648df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen iphc1 |= LOWPAN_IPHC_DAM_01; 7658df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* second byte + the last five */ 7668df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen *hc06_ptr = hdr->daddr.s6_addr[1]; 7678df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[11], 5); 7688df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hc06_ptr += 6; 7698df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } else { 7708df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("using full address\n"); 7718df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen iphc1 |= LOWPAN_IPHC_DAM_00; 7728df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(hc06_ptr, &hdr->daddr.s6_addr[0], 16); 7738df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hc06_ptr += 16; 7748df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 7758df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } else { 7768df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* TODO: context lookup */ 7778df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (is_addr_link_local(&hdr->daddr)) { 7788df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen iphc1 |= lowpan_compress_addr_64(&hc06_ptr, 7798df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen LOWPAN_IPHC_DAM_BIT, &hdr->daddr, _daddr); 7808df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("dest address unicast link-local %pI6c " 7818df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen "iphc1 0x%02x\n", &hdr->daddr, iphc1); 7828df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } else { 7838df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("dest address unicast %pI6c\n", &hdr->daddr); 7848df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(hc06_ptr, &hdr->daddr.s6_addr16[0], 16); 7858df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen hc06_ptr += 16; 7868df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 7878df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen } 7888df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 7898df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen /* UDP header compression */ 7908df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen if (hdr->nexthdr == UIP_PROTO_UDP) 7918df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen compress_udp_header(&hc06_ptr, skb); 7928df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 7938df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen head[0] = iphc0; 7948df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen head[1] = iphc1; 7958df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 7968df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb_pull(skb, sizeof(struct ipv6hdr)); 7978df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb_reset_transport_header(skb); 7988df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen memcpy(skb_push(skb, hc06_ptr - head), head, hc06_ptr - head); 7998df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb_reset_network_header(skb); 8008df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 8018df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen pr_debug("header len %d skb %u\n", (int)(hc06_ptr - head), skb->len); 8028df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen 8038df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen raw_dump_table(__func__, "raw skb data dump compressed", 8048df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen skb->data, skb->len); 8058df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen return 0; 8068df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka Rissanen} 8078df8c56a5abc70af5862aa7cac2875aeeb17a42bJukka RissanenEXPORT_SYMBOL_GPL(lowpan_header_compress); 808