linux/net/6lowpan/iphc.c
<<
>>
Prefs
   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
  53#include <net/6lowpan.h>
  54#include <net/ipv6.h>
  55
  56#include "6lowpan_i.h"
  57#include "nhc.h"
  58
  59/* Values of fields within the IPHC encoding first byte */
  60#define LOWPAN_IPHC_TF_MASK     0x18
  61#define LOWPAN_IPHC_TF_00       0x00
  62#define LOWPAN_IPHC_TF_01       0x08
  63#define LOWPAN_IPHC_TF_10       0x10
  64#define LOWPAN_IPHC_TF_11       0x18
  65
  66#define LOWPAN_IPHC_NH          0x04
  67
  68#define LOWPAN_IPHC_HLIM_MASK   0x03
  69#define LOWPAN_IPHC_HLIM_00     0x00
  70#define LOWPAN_IPHC_HLIM_01     0x01
  71#define LOWPAN_IPHC_HLIM_10     0x02
  72#define LOWPAN_IPHC_HLIM_11     0x03
  73
  74/* Values of fields within the IPHC encoding second byte */
  75#define LOWPAN_IPHC_CID         0x80
  76
  77#define LOWPAN_IPHC_SAC         0x40
  78
  79#define LOWPAN_IPHC_SAM_MASK    0x30
  80#define LOWPAN_IPHC_SAM_00      0x00
  81#define LOWPAN_IPHC_SAM_01      0x10
  82#define LOWPAN_IPHC_SAM_10      0x20
  83#define LOWPAN_IPHC_SAM_11      0x30
  84
  85#define LOWPAN_IPHC_M           0x08
  86
  87#define LOWPAN_IPHC_DAC         0x04
  88
  89#define LOWPAN_IPHC_DAM_MASK    0x03
  90#define LOWPAN_IPHC_DAM_00      0x00
  91#define LOWPAN_IPHC_DAM_01      0x01
  92#define LOWPAN_IPHC_DAM_10      0x02
  93#define LOWPAN_IPHC_DAM_11      0x03
  94
  95/* ipv6 address based on mac
  96 * second bit-flip (Universe/Local) is done according RFC2464
  97 */
  98#define is_addr_mac_addr_based(a, m) \
  99        ((((a)->s6_addr[8])  == (((m)[0]) ^ 0x02)) &&   \
 100         (((a)->s6_addr[9])  == (m)[1]) &&              \
 101         (((a)->s6_addr[10]) == (m)[2]) &&              \
 102         (((a)->s6_addr[11]) == (m)[3]) &&              \
 103         (((a)->s6_addr[12]) == (m)[4]) &&              \
 104         (((a)->s6_addr[13]) == (m)[5]) &&              \
 105         (((a)->s6_addr[14]) == (m)[6]) &&              \
 106         (((a)->s6_addr[15]) == (m)[7]))
 107
 108/* check whether we can compress the IID to 16 bits,
 109 * it's possible for unicast addresses with first 49 bits are zero only.
 110 */
 111#define lowpan_is_iid_16_bit_compressable(a)    \
 112        ((((a)->s6_addr16[4]) == 0) &&          \
 113         (((a)->s6_addr[10]) == 0) &&           \
 114         (((a)->s6_addr[11]) == 0xff) &&        \
 115         (((a)->s6_addr[12]) == 0xfe) &&        \
 116         (((a)->s6_addr[13]) == 0))
 117
 118/* check whether the 112-bit gid of the multicast address is mappable to: */
 119
 120/* 48 bits, FFXX::00XX:XXXX:XXXX */
 121#define lowpan_is_mcast_addr_compressable48(a)  \
 122        ((((a)->s6_addr16[1]) == 0) &&          \
 123         (((a)->s6_addr16[2]) == 0) &&          \
 124         (((a)->s6_addr16[3]) == 0) &&          \
 125         (((a)->s6_addr16[4]) == 0) &&          \
 126         (((a)->s6_addr[10]) == 0))
 127
 128/* 32 bits, FFXX::00XX:XXXX */
 129#define lowpan_is_mcast_addr_compressable32(a)  \
 130        ((((a)->s6_addr16[1]) == 0) &&          \
 131         (((a)->s6_addr16[2]) == 0) &&          \
 132         (((a)->s6_addr16[3]) == 0) &&          \
 133         (((a)->s6_addr16[4]) == 0) &&          \
 134         (((a)->s6_addr16[5]) == 0) &&          \
 135         (((a)->s6_addr[12]) == 0))
 136
 137/* 8 bits, FF02::00XX */
 138#define lowpan_is_mcast_addr_compressable8(a)   \
 139        ((((a)->s6_addr[1])  == 2) &&           \
 140         (((a)->s6_addr16[1]) == 0) &&          \
 141         (((a)->s6_addr16[2]) == 0) &&          \
 142         (((a)->s6_addr16[3]) == 0) &&          \
 143         (((a)->s6_addr16[4]) == 0) &&          \
 144         (((a)->s6_addr16[5]) == 0) &&          \
 145         (((a)->s6_addr16[6]) == 0) &&          \
 146         (((a)->s6_addr[14]) == 0))
 147
 148#define lowpan_is_linklocal_zero_padded(a)      \
 149        (!(hdr->saddr.s6_addr[1] & 0x3f) &&     \
 150         !hdr->saddr.s6_addr16[1] &&            \
 151         !hdr->saddr.s6_addr32[1])
 152
 153#define LOWPAN_IPHC_CID_DCI(cid)        (cid & 0x0f)
 154#define LOWPAN_IPHC_CID_SCI(cid)        ((cid & 0xf0) >> 4)
 155
 156static inline void
 157lowpan_iphc_uncompress_802154_lladdr(struct in6_addr *ipaddr,
 158                                     const void *lladdr)
 159{
 160        const struct ieee802154_addr *addr = lladdr;
 161        u8 eui64[EUI64_ADDR_LEN];
 162
 163        switch (addr->mode) {
 164        case IEEE802154_ADDR_LONG:
 165                ieee802154_le64_to_be64(eui64, &addr->extended_addr);
 166                lowpan_iphc_uncompress_eui64_lladdr(ipaddr, eui64);
 167                break;
 168        case IEEE802154_ADDR_SHORT:
 169                /* fe:80::ff:fe00:XXXX
 170                 *                \__/
 171                 *             short_addr
 172                 *
 173                 * Universe/Local bit is zero.
 174                 */
 175                ipaddr->s6_addr[0] = 0xFE;
 176                ipaddr->s6_addr[1] = 0x80;
 177                ipaddr->s6_addr[11] = 0xFF;
 178                ipaddr->s6_addr[12] = 0xFE;
 179                ieee802154_le16_to_be16(&ipaddr->s6_addr16[7],
 180                                        &addr->short_addr);
 181                break;
 182        default:
 183                /* should never handled and filtered by 802154 6lowpan */
 184                WARN_ON_ONCE(1);
 185                break;
 186        }
 187}
 188
 189static struct lowpan_iphc_ctx *
 190lowpan_iphc_ctx_get_by_id(const struct net_device *dev, u8 id)
 191{
 192        struct lowpan_iphc_ctx *ret = &lowpan_dev(dev)->ctx.table[id];
 193
 194        if (!lowpan_iphc_ctx_is_active(ret))
 195                return NULL;
 196
 197        return ret;
 198}
 199
 200static struct lowpan_iphc_ctx *
 201lowpan_iphc_ctx_get_by_addr(const struct net_device *dev,
 202                            const struct in6_addr *addr)
 203{
 204        struct lowpan_iphc_ctx *table = lowpan_dev(dev)->ctx.table;
 205        struct lowpan_iphc_ctx *ret = NULL;
 206        struct in6_addr addr_pfx;
 207        u8 addr_plen;
 208        int i;
 209
 210        for (i = 0; i < LOWPAN_IPHC_CTX_TABLE_SIZE; i++) {
 211                /* Check if context is valid. A context that is not valid
 212                 * MUST NOT be used for compression.
 213                 */
 214                if (!lowpan_iphc_ctx_is_active(&table[i]) ||
 215                    !lowpan_iphc_ctx_is_compression(&table[i]))
 216                        continue;
 217
 218                ipv6_addr_prefix(&addr_pfx, addr, table[i].plen);
 219
 220                /* if prefix len < 64, the remaining bits until 64th bit is
 221                 * zero. Otherwise we use table[i]->plen.
 222                 */
 223                if (table[i].plen < 64)
 224                        addr_plen = 64;
 225                else
 226                        addr_plen = table[i].plen;
 227
 228                if (ipv6_prefix_equal(&addr_pfx, &table[i].pfx, addr_plen)) {
 229                        /* remember first match */
 230                        if (!ret) {
 231                                ret = &table[i];
 232                                continue;
 233                        }
 234
 235                        /* get the context with longest prefix len */
 236                        if (table[i].plen > ret->plen)
 237                                ret = &table[i];
 238                }
 239        }
 240
 241        return ret;
 242}
 243
 244static struct lowpan_iphc_ctx *
 245lowpan_iphc_ctx_get_by_mcast_addr(const struct net_device *dev,
 246                                  const struct in6_addr *addr)
 247{
 248        struct lowpan_iphc_ctx *table = lowpan_dev(dev)->ctx.table;
 249        struct lowpan_iphc_ctx *ret = NULL;
 250        struct in6_addr addr_mcast, network_pfx = {};
 251        int i;
 252
 253        /* init mcast address with  */
 254        memcpy(&addr_mcast, addr, sizeof(*addr));
 255
 256        for (i = 0; i < LOWPAN_IPHC_CTX_TABLE_SIZE; i++) {
 257                /* Check if context is valid. A context that is not valid
 258                 * MUST NOT be used for compression.
 259                 */
 260                if (!lowpan_iphc_ctx_is_active(&table[i]) ||
 261                    !lowpan_iphc_ctx_is_compression(&table[i]))
 262                        continue;
 263
 264                /* setting plen */
 265                addr_mcast.s6_addr[3] = table[i].plen;
 266                /* get network prefix to copy into multicast address */
 267                ipv6_addr_prefix(&network_pfx, &table[i].pfx,
 268                                 table[i].plen);
 269                /* setting network prefix */
 270                memcpy(&addr_mcast.s6_addr[4], &network_pfx, 8);
 271
 272                if (ipv6_addr_equal(addr, &addr_mcast)) {
 273                        ret = &table[i];
 274                        break;
 275                }
 276        }
 277
 278        return ret;
 279}
 280
 281static void lowpan_iphc_uncompress_lladdr(const struct net_device *dev,
 282                                          struct in6_addr *ipaddr,
 283                                          const void *lladdr)
 284{
 285        switch (dev->addr_len) {
 286        case ETH_ALEN:
 287                lowpan_iphc_uncompress_eui48_lladdr(ipaddr, lladdr);
 288                break;
 289        case EUI64_ADDR_LEN:
 290                lowpan_iphc_uncompress_eui64_lladdr(ipaddr, lladdr);
 291                break;
 292        default:
 293                WARN_ON_ONCE(1);
 294                break;
 295        }
 296}
 297
 298/* Uncompress address function for source and
 299 * destination address(non-multicast).
 300 *
 301 * address_mode is the masked value for sam or dam value
 302 */
 303static int lowpan_iphc_uncompress_addr(struct sk_buff *skb,
 304                                       const struct net_device *dev,
 305                                       struct in6_addr *ipaddr,
 306                                       u8 address_mode, const void *lladdr)
 307{
 308        bool fail;
 309
 310        switch (address_mode) {
 311        /* SAM and DAM are the same here */
 312        case LOWPAN_IPHC_DAM_00:
 313                /* for global link addresses */
 314                fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
 315                break;
 316        case LOWPAN_IPHC_SAM_01:
 317        case LOWPAN_IPHC_DAM_01:
 318                /* fe:80::XXXX:XXXX:XXXX:XXXX */
 319                ipaddr->s6_addr[0] = 0xFE;
 320                ipaddr->s6_addr[1] = 0x80;
 321                fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8);
 322                break;
 323        case LOWPAN_IPHC_SAM_10:
 324        case LOWPAN_IPHC_DAM_10:
 325                /* fe:80::ff:fe00:XXXX */
 326                ipaddr->s6_addr[0] = 0xFE;
 327                ipaddr->s6_addr[1] = 0x80;
 328                ipaddr->s6_addr[11] = 0xFF;
 329                ipaddr->s6_addr[12] = 0xFE;
 330                fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2);
 331                break;
 332        case LOWPAN_IPHC_SAM_11:
 333        case LOWPAN_IPHC_DAM_11:
 334                fail = false;
 335                switch (lowpan_dev(dev)->lltype) {
 336                case LOWPAN_LLTYPE_IEEE802154:
 337                        lowpan_iphc_uncompress_802154_lladdr(ipaddr, lladdr);
 338                        break;
 339                default:
 340                        lowpan_iphc_uncompress_lladdr(dev, ipaddr, lladdr);
 341                        break;
 342                }
 343                break;
 344        default:
 345                pr_debug("Invalid address mode value: 0x%x\n", address_mode);
 346                return -EINVAL;
 347        }
 348
 349        if (fail) {
 350                pr_debug("Failed to fetch skb data\n");
 351                return -EIO;
 352        }
 353
 354        raw_dump_inline(NULL, "Reconstructed ipv6 addr is",
 355                        ipaddr->s6_addr, 16);
 356
 357        return 0;
 358}
 359
 360/* Uncompress address function for source context
 361 * based address(non-multicast).
 362 */
 363static int lowpan_iphc_uncompress_ctx_addr(struct sk_buff *skb,
 364                                           const struct net_device *dev,
 365                                           const struct lowpan_iphc_ctx *ctx,
 366                                           struct in6_addr *ipaddr,
 367                                           u8 address_mode, const void *lladdr)
 368{
 369        bool fail;
 370
 371        switch (address_mode) {
 372        /* SAM and DAM are the same here */
 373        case LOWPAN_IPHC_DAM_00:
 374                fail = false;
 375                /* SAM_00 -> unspec address ::
 376                 * Do nothing, address is already ::
 377                 *
 378                 * DAM 00 -> reserved should never occur.
 379                 */
 380                break;
 381        case LOWPAN_IPHC_SAM_01:
 382        case LOWPAN_IPHC_DAM_01:
 383                fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8);
 384                ipv6_addr_prefix_copy(ipaddr, &ctx->pfx, ctx->plen);
 385                break;
 386        case LOWPAN_IPHC_SAM_10:
 387        case LOWPAN_IPHC_DAM_10:
 388                ipaddr->s6_addr[11] = 0xFF;
 389                ipaddr->s6_addr[12] = 0xFE;
 390                fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2);
 391                ipv6_addr_prefix_copy(ipaddr, &ctx->pfx, ctx->plen);
 392                break;
 393        case LOWPAN_IPHC_SAM_11:
 394        case LOWPAN_IPHC_DAM_11:
 395                fail = false;
 396                switch (lowpan_dev(dev)->lltype) {
 397                case LOWPAN_LLTYPE_IEEE802154:
 398                        lowpan_iphc_uncompress_802154_lladdr(ipaddr, lladdr);
 399                        break;
 400                default:
 401                        lowpan_iphc_uncompress_lladdr(dev, ipaddr, lladdr);
 402                        break;
 403                }
 404                ipv6_addr_prefix_copy(ipaddr, &ctx->pfx, ctx->plen);
 405                break;
 406        default:
 407                pr_debug("Invalid sam value: 0x%x\n", address_mode);
 408                return -EINVAL;
 409        }
 410
 411        if (fail) {
 412                pr_debug("Failed to fetch skb data\n");
 413                return -EIO;
 414        }
 415
 416        raw_dump_inline(NULL,
 417                        "Reconstructed context based ipv6 src addr is",
 418                        ipaddr->s6_addr, 16);
 419
 420        return 0;
 421}
 422
 423/* Uncompress function for multicast destination address,
 424 * when M bit is set.
 425 */
 426static int lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
 427                                             struct in6_addr *ipaddr,
 428                                             u8 address_mode)
 429{
 430        bool fail;
 431
 432        switch (address_mode) {
 433        case LOWPAN_IPHC_DAM_00:
 434                /* 00:  128 bits.  The full address
 435                 * is carried in-line.
 436                 */
 437                fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
 438                break;
 439        case LOWPAN_IPHC_DAM_01:
 440                /* 01:  48 bits.  The address takes
 441                 * the form ffXX::00XX:XXXX:XXXX.
 442                 */
 443                ipaddr->s6_addr[0] = 0xFF;
 444                fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
 445                fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5);
 446                break;
 447        case LOWPAN_IPHC_DAM_10:
 448                /* 10:  32 bits.  The address takes
 449                 * the form ffXX::00XX:XXXX.
 450                 */
 451                ipaddr->s6_addr[0] = 0xFF;
 452                fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
 453                fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3);
 454                break;
 455        case LOWPAN_IPHC_DAM_11:
 456                /* 11:  8 bits.  The address takes
 457                 * the form ff02::00XX.
 458                 */
 459                ipaddr->s6_addr[0] = 0xFF;
 460                ipaddr->s6_addr[1] = 0x02;
 461                fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1);
 462                break;
 463        default:
 464                pr_debug("DAM value has a wrong value: 0x%x\n", address_mode);
 465                return -EINVAL;
 466        }
 467
 468        if (fail) {
 469                pr_debug("Failed to fetch skb data\n");
 470                return -EIO;
 471        }
 472
 473        raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is",
 474                        ipaddr->s6_addr, 16);
 475
 476        return 0;
 477}
 478
 479static int lowpan_uncompress_multicast_ctx_daddr(struct sk_buff *skb,
 480                                                 struct lowpan_iphc_ctx *ctx,
 481                                                 struct in6_addr *ipaddr,
 482                                                 u8 address_mode)
 483{
 484        struct in6_addr network_pfx = {};
 485        bool fail;
 486
 487        ipaddr->s6_addr[0] = 0xFF;
 488        fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 2);
 489        fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[12], 4);
 490        if (fail)
 491                return -EIO;
 492
 493        /* take prefix_len and network prefix from the context */
 494        ipaddr->s6_addr[3] = ctx->plen;
 495        /* get network prefix to copy into multicast address */
 496        ipv6_addr_prefix(&network_pfx, &ctx->pfx, ctx->plen);
 497        /* setting network prefix */
 498        memcpy(&ipaddr->s6_addr[4], &network_pfx, 8);
 499
 500        return 0;
 501}
 502
 503/* get the ecn values from iphc tf format and set it to ipv6hdr */
 504static inline void lowpan_iphc_tf_set_ecn(struct ipv6hdr *hdr, const u8 *tf)
 505{
 506        /* get the two higher bits which is ecn */
 507        u8 ecn = tf[0] & 0xc0;
 508
 509        /* ECN takes 0x30 in hdr->flow_lbl[0] */
 510        hdr->flow_lbl[0] |= (ecn >> 2);
 511}
 512
 513/* get the dscp values from iphc tf format and set it to ipv6hdr */
 514static inline void lowpan_iphc_tf_set_dscp(struct ipv6hdr *hdr, const u8 *tf)
 515{
 516        /* DSCP is at place after ECN */
 517        u8 dscp = tf[0] & 0x3f;
 518
 519        /* The four highest bits need to be set at hdr->priority */
 520        hdr->priority |= ((dscp & 0x3c) >> 2);
 521        /* The two lower bits is part of hdr->flow_lbl[0] */
 522        hdr->flow_lbl[0] |= ((dscp & 0x03) << 6);
 523}
 524
 525/* get the flow label values from iphc tf format and set it to ipv6hdr */
 526static inline void lowpan_iphc_tf_set_lbl(struct ipv6hdr *hdr, const u8 *lbl)
 527{
 528        /* flow label is always some array started with lower nibble of
 529         * flow_lbl[0] and followed with two bytes afterwards. Inside inline
 530         * data the flow_lbl position can be different, which will be handled
 531         * by lbl pointer. E.g. case "01" vs "00" the traffic class is 8 bit
 532         * shifted, the different lbl pointer will handle that.
 533         *
 534         * The flow label will started at lower nibble of flow_lbl[0], the
 535         * higher nibbles are part of DSCP + ECN.
 536         */
 537        hdr->flow_lbl[0] |= lbl[0] & 0x0f;
 538        memcpy(&hdr->flow_lbl[1], &lbl[1], 2);
 539}
 540
 541/* lowpan_iphc_tf_decompress - decompress the traffic class.
 542 *      This function will return zero on success, a value lower than zero if
 543 *      failed.
 544 */
 545static int lowpan_iphc_tf_decompress(struct sk_buff *skb, struct ipv6hdr *hdr,
 546                                     u8 val)
 547{
 548        u8 tf[4];
 549
 550        /* Traffic Class and Flow Label */
 551        switch (val) {
 552        case LOWPAN_IPHC_TF_00:
 553                /* ECN + DSCP + 4-bit Pad + Flow Label (4 bytes) */
 554                if (lowpan_fetch_skb(skb, tf, 4))
 555                        return -EINVAL;
 556
 557                /*                      1                   2                   3
 558                 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 559                 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 560                 * |ECN|   DSCP    |  rsv  |             Flow Label                |
 561                 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 562                 */
 563                lowpan_iphc_tf_set_ecn(hdr, tf);
 564                lowpan_iphc_tf_set_dscp(hdr, tf);
 565                lowpan_iphc_tf_set_lbl(hdr, &tf[1]);
 566                break;
 567        case LOWPAN_IPHC_TF_01:
 568                /* ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided. */
 569                if (lowpan_fetch_skb(skb, tf, 3))
 570                        return -EINVAL;
 571
 572                /*                     1                   2
 573                 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
 574                 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 575                 * |ECN|rsv|             Flow Label                |
 576                 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 577                 */
 578                lowpan_iphc_tf_set_ecn(hdr, tf);
 579                lowpan_iphc_tf_set_lbl(hdr, &tf[0]);
 580                break;
 581        case LOWPAN_IPHC_TF_10:
 582                /* ECN + DSCP (1 byte), Flow Label is elided. */
 583                if (lowpan_fetch_skb(skb, tf, 1))
 584                        return -EINVAL;
 585
 586                /*  0 1 2 3 4 5 6 7
 587                 * +-+-+-+-+-+-+-+-+
 588                 * |ECN|   DSCP    |
 589                 * +-+-+-+-+-+-+-+-+
 590                 */
 591                lowpan_iphc_tf_set_ecn(hdr, tf);
 592                lowpan_iphc_tf_set_dscp(hdr, tf);
 593                break;
 594        case LOWPAN_IPHC_TF_11:
 595                /* Traffic Class and Flow Label are elided */
 596                break;
 597        default:
 598                WARN_ON_ONCE(1);
 599                return -EINVAL;
 600        }
 601
 602        return 0;
 603}
 604
 605/* TTL uncompression values */
 606static const u8 lowpan_ttl_values[] = {
 607        [LOWPAN_IPHC_HLIM_01] = 1,
 608        [LOWPAN_IPHC_HLIM_10] = 64,
 609        [LOWPAN_IPHC_HLIM_11] = 255,
 610};
 611
 612int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev,
 613                             const void *daddr, const void *saddr)
 614{
 615        struct ipv6hdr hdr = {};
 616        struct lowpan_iphc_ctx *ci;
 617        u8 iphc0, iphc1, cid = 0;
 618        int err;
 619
 620        raw_dump_table(__func__, "raw skb data dump uncompressed",
 621                       skb->data, skb->len);
 622
 623        if (lowpan_fetch_skb(skb, &iphc0, sizeof(iphc0)) ||
 624            lowpan_fetch_skb(skb, &iphc1, sizeof(iphc1)))
 625                return -EINVAL;
 626
 627        hdr.version = 6;
 628
 629        /* default CID = 0, another if the CID flag is set */
 630        if (iphc1 & LOWPAN_IPHC_CID) {
 631                if (lowpan_fetch_skb(skb, &cid, sizeof(cid)))
 632                        return -EINVAL;
 633        }
 634
 635        err = lowpan_iphc_tf_decompress(skb, &hdr,
 636                                        iphc0 & LOWPAN_IPHC_TF_MASK);
 637        if (err < 0)
 638                return err;
 639
 640        /* Next Header */
 641        if (!(iphc0 & LOWPAN_IPHC_NH)) {
 642                /* Next header is carried inline */
 643                if (lowpan_fetch_skb(skb, &hdr.nexthdr, sizeof(hdr.nexthdr)))
 644                        return -EINVAL;
 645
 646                pr_debug("NH flag is set, next header carried inline: %02x\n",
 647                         hdr.nexthdr);
 648        }
 649
 650        /* Hop Limit */
 651        if ((iphc0 & LOWPAN_IPHC_HLIM_MASK) != LOWPAN_IPHC_HLIM_00) {
 652                hdr.hop_limit = lowpan_ttl_values[iphc0 & LOWPAN_IPHC_HLIM_MASK];
 653        } else {
 654                if (lowpan_fetch_skb(skb, &hdr.hop_limit,
 655                                     sizeof(hdr.hop_limit)))
 656                        return -EINVAL;
 657        }
 658
 659        if (iphc1 & LOWPAN_IPHC_SAC) {
 660                spin_lock_bh(&lowpan_dev(dev)->ctx.lock);
 661                ci = lowpan_iphc_ctx_get_by_id(dev, LOWPAN_IPHC_CID_SCI(cid));
 662                if (!ci) {
 663                        spin_unlock_bh(&lowpan_dev(dev)->ctx.lock);
 664                        return -EINVAL;
 665                }
 666
 667                pr_debug("SAC bit is set. Handle context based source address.\n");
 668                err = lowpan_iphc_uncompress_ctx_addr(skb, dev, ci, &hdr.saddr,
 669                                                      iphc1 & LOWPAN_IPHC_SAM_MASK,
 670                                                      saddr);
 671                spin_unlock_bh(&lowpan_dev(dev)->ctx.lock);
 672        } else {
 673                /* Source address uncompression */
 674                pr_debug("source address stateless compression\n");
 675                err = lowpan_iphc_uncompress_addr(skb, dev, &hdr.saddr,
 676                                                  iphc1 & LOWPAN_IPHC_SAM_MASK,
 677                                                  saddr);
 678        }
 679
 680        /* Check on error of previous branch */
 681        if (err)
 682                return -EINVAL;
 683
 684        switch (iphc1 & (LOWPAN_IPHC_M | LOWPAN_IPHC_DAC)) {
 685        case LOWPAN_IPHC_M | LOWPAN_IPHC_DAC:
 686                skb->pkt_type = PACKET_BROADCAST;
 687
 688                spin_lock_bh(&lowpan_dev(dev)->ctx.lock);
 689                ci = lowpan_iphc_ctx_get_by_id(dev, LOWPAN_IPHC_CID_DCI(cid));
 690                if (!ci) {
 691                        spin_unlock_bh(&lowpan_dev(dev)->ctx.lock);
 692                        return -EINVAL;
 693                }
 694
 695                /* multicast with context */
 696                pr_debug("dest: context-based mcast compression\n");
 697                err = lowpan_uncompress_multicast_ctx_daddr(skb, ci,
 698                                                            &hdr.daddr,
 699                                                            iphc1 & LOWPAN_IPHC_DAM_MASK);
 700                spin_unlock_bh(&lowpan_dev(dev)->ctx.lock);
 701                break;
 702        case LOWPAN_IPHC_M:
 703                skb->pkt_type = PACKET_BROADCAST;
 704
 705                /* multicast */
 706                err = lowpan_uncompress_multicast_daddr(skb, &hdr.daddr,
 707                                                        iphc1 & LOWPAN_IPHC_DAM_MASK);
 708                break;
 709        case LOWPAN_IPHC_DAC:
 710                skb->pkt_type = PACKET_HOST;
 711
 712                spin_lock_bh(&lowpan_dev(dev)->ctx.lock);
 713                ci = lowpan_iphc_ctx_get_by_id(dev, LOWPAN_IPHC_CID_DCI(cid));
 714                if (!ci) {
 715                        spin_unlock_bh(&lowpan_dev(dev)->ctx.lock);
 716                        return -EINVAL;
 717                }
 718
 719                /* Destination address context based uncompression */
 720                pr_debug("DAC bit is set. Handle context based destination address.\n");
 721                err = lowpan_iphc_uncompress_ctx_addr(skb, dev, ci, &hdr.daddr,
 722                                                      iphc1 & LOWPAN_IPHC_DAM_MASK,
 723                                                      daddr);
 724                spin_unlock_bh(&lowpan_dev(dev)->ctx.lock);
 725                break;
 726        default:
 727                skb->pkt_type = PACKET_HOST;
 728
 729                err = lowpan_iphc_uncompress_addr(skb, dev, &hdr.daddr,
 730                                                  iphc1 & LOWPAN_IPHC_DAM_MASK,
 731                                                  daddr);
 732                pr_debug("dest: stateless compression mode %d dest %pI6c\n",
 733                         iphc1 & LOWPAN_IPHC_DAM_MASK, &hdr.daddr);
 734                break;
 735        }
 736
 737        if (err)
 738                return -EINVAL;
 739
 740        /* Next header data uncompression */
 741        if (iphc0 & LOWPAN_IPHC_NH) {
 742                err = lowpan_nhc_do_uncompression(skb, dev, &hdr);
 743                if (err < 0)
 744                        return err;
 745        } else {
 746                err = skb_cow(skb, sizeof(hdr));
 747                if (unlikely(err))
 748                        return err;
 749        }
 750
 751        switch (lowpan_dev(dev)->lltype) {
 752        case LOWPAN_LLTYPE_IEEE802154:
 753                if (lowpan_802154_cb(skb)->d_size)
 754                        hdr.payload_len = htons(lowpan_802154_cb(skb)->d_size -
 755                                                sizeof(struct ipv6hdr));
 756                else
 757                        hdr.payload_len = htons(skb->len);
 758                break;
 759        default:
 760                hdr.payload_len = htons(skb->len);
 761                break;
 762        }
 763
 764        pr_debug("skb headroom size = %d, data length = %d\n",
 765                 skb_headroom(skb), skb->len);
 766
 767        pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength  = %d\n\t"
 768                 "nexthdr = 0x%02x\n\thop_lim = %d\n\tdest    = %pI6c\n",
 769                hdr.version, ntohs(hdr.payload_len), hdr.nexthdr,
 770                hdr.hop_limit, &hdr.daddr);
 771
 772        skb_push(skb, sizeof(hdr));
 773        skb_reset_network_header(skb);
 774        skb_copy_to_linear_data(skb, &hdr, sizeof(hdr));
 775
 776        raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr));
 777
 778        return 0;
 779}
 780EXPORT_SYMBOL_GPL(lowpan_header_decompress);
 781
 782static const u8 lowpan_iphc_dam_to_sam_value[] = {
 783        [LOWPAN_IPHC_DAM_00] = LOWPAN_IPHC_SAM_00,
 784        [LOWPAN_IPHC_DAM_01] = LOWPAN_IPHC_SAM_01,
 785        [LOWPAN_IPHC_DAM_10] = LOWPAN_IPHC_SAM_10,
 786        [LOWPAN_IPHC_DAM_11] = LOWPAN_IPHC_SAM_11,
 787};
 788
 789static inline bool
 790lowpan_iphc_compress_ctx_802154_lladdr(const struct in6_addr *ipaddr,
 791                                       const struct lowpan_iphc_ctx *ctx,
 792                                       const void *lladdr)
 793{
 794        const struct ieee802154_addr *addr = lladdr;
 795        unsigned char extended_addr[EUI64_ADDR_LEN];
 796        bool lladdr_compress = false;
 797        struct in6_addr tmp = {};
 798
 799        switch (addr->mode) {
 800        case IEEE802154_ADDR_LONG:
 801                ieee802154_le64_to_be64(&extended_addr, &addr->extended_addr);
 802                /* check for SAM/DAM = 11 */
 803                memcpy(&tmp.s6_addr[8], &extended_addr, EUI64_ADDR_LEN);
 804                /* second bit-flip (Universe/Local) is done according RFC2464 */
 805                tmp.s6_addr[8] ^= 0x02;
 806                /* context information are always used */
 807                ipv6_addr_prefix_copy(&tmp, &ctx->pfx, ctx->plen);
 808                if (ipv6_addr_equal(&tmp, ipaddr))
 809                        lladdr_compress = true;
 810                break;
 811        case IEEE802154_ADDR_SHORT:
 812                tmp.s6_addr[11] = 0xFF;
 813                tmp.s6_addr[12] = 0xFE;
 814                ieee802154_le16_to_be16(&tmp.s6_addr16[7],
 815                                        &addr->short_addr);
 816                /* context information are always used */
 817                ipv6_addr_prefix_copy(&tmp, &ctx->pfx, ctx->plen);
 818                if (ipv6_addr_equal(&tmp, ipaddr))
 819                        lladdr_compress = true;
 820                break;
 821        default:
 822                /* should never handled and filtered by 802154 6lowpan */
 823                WARN_ON_ONCE(1);
 824                break;
 825        }
 826
 827        return lladdr_compress;
 828}
 829
 830static bool lowpan_iphc_addr_equal(const struct net_device *dev,
 831                                   const struct lowpan_iphc_ctx *ctx,
 832                                   const struct in6_addr *ipaddr,
 833                                   const void *lladdr)
 834{
 835        struct in6_addr tmp = {};
 836
 837        lowpan_iphc_uncompress_lladdr(dev, &tmp, lladdr);
 838
 839        if (ctx)
 840                ipv6_addr_prefix_copy(&tmp, &ctx->pfx, ctx->plen);
 841
 842        return ipv6_addr_equal(&tmp, ipaddr);
 843}
 844
 845static u8 lowpan_compress_ctx_addr(u8 **hc_ptr, const struct net_device *dev,
 846                                   const struct in6_addr *ipaddr,
 847                                   const struct lowpan_iphc_ctx *ctx,
 848                                   const unsigned char *lladdr, bool sam)
 849{
 850        struct in6_addr tmp = {};
 851        u8 dam;
 852
 853        switch (lowpan_dev(dev)->lltype) {
 854        case LOWPAN_LLTYPE_IEEE802154:
 855                if (lowpan_iphc_compress_ctx_802154_lladdr(ipaddr, ctx,
 856                                                           lladdr)) {
 857                        dam = LOWPAN_IPHC_DAM_11;
 858                        goto out;
 859                }
 860                break;
 861        default:
 862                if (lowpan_iphc_addr_equal(dev, ctx, ipaddr, lladdr)) {
 863                        dam = LOWPAN_IPHC_DAM_11;
 864                        goto out;
 865                }
 866                break;
 867        }
 868
 869        memset(&tmp, 0, sizeof(tmp));
 870        /* check for SAM/DAM = 10 */
 871        tmp.s6_addr[11] = 0xFF;
 872        tmp.s6_addr[12] = 0xFE;
 873        memcpy(&tmp.s6_addr[14], &ipaddr->s6_addr[14], 2);
 874        /* context information are always used */
 875        ipv6_addr_prefix_copy(&tmp, &ctx->pfx, ctx->plen);
 876        if (ipv6_addr_equal(&tmp, ipaddr)) {
 877                lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr[14], 2);
 878                dam = LOWPAN_IPHC_DAM_10;
 879                goto out;
 880        }
 881
 882        memset(&tmp, 0, sizeof(tmp));
 883        /* check for SAM/DAM = 01, should always match */
 884        memcpy(&tmp.s6_addr[8], &ipaddr->s6_addr[8], 8);
 885        /* context information are always used */
 886        ipv6_addr_prefix_copy(&tmp, &ctx->pfx, ctx->plen);
 887        if (ipv6_addr_equal(&tmp, ipaddr)) {
 888                lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr[8], 8);
 889                dam = LOWPAN_IPHC_DAM_01;
 890                goto out;
 891        }
 892
 893        WARN_ONCE(1, "context found but no address mode matched\n");
 894        return LOWPAN_IPHC_DAM_00;
 895out:
 896
 897        if (sam)
 898                return lowpan_iphc_dam_to_sam_value[dam];
 899        else
 900                return dam;
 901}
 902
 903static inline bool
 904lowpan_iphc_compress_802154_lladdr(const struct in6_addr *ipaddr,
 905                                   const void *lladdr)
 906{
 907        const struct ieee802154_addr *addr = lladdr;
 908        unsigned char extended_addr[EUI64_ADDR_LEN];
 909        bool lladdr_compress = false;
 910        struct in6_addr tmp = {};
 911
 912        switch (addr->mode) {
 913        case IEEE802154_ADDR_LONG:
 914                ieee802154_le64_to_be64(&extended_addr, &addr->extended_addr);
 915                if (is_addr_mac_addr_based(ipaddr, extended_addr))
 916                        lladdr_compress = true;
 917                break;
 918        case IEEE802154_ADDR_SHORT:
 919                /* fe:80::ff:fe00:XXXX
 920                 *                \__/
 921                 *             short_addr
 922                 *
 923                 * Universe/Local bit is zero.
 924                 */
 925                tmp.s6_addr[0] = 0xFE;
 926                tmp.s6_addr[1] = 0x80;
 927                tmp.s6_addr[11] = 0xFF;
 928                tmp.s6_addr[12] = 0xFE;
 929                ieee802154_le16_to_be16(&tmp.s6_addr16[7],
 930                                        &addr->short_addr);
 931                if (ipv6_addr_equal(&tmp, ipaddr))
 932                        lladdr_compress = true;
 933                break;
 934        default:
 935                /* should never handled and filtered by 802154 6lowpan */
 936                WARN_ON_ONCE(1);
 937                break;
 938        }
 939
 940        return lladdr_compress;
 941}
 942
 943static u8 lowpan_compress_addr_64(u8 **hc_ptr, const struct net_device *dev,
 944                                  const struct in6_addr *ipaddr,
 945                                  const unsigned char *lladdr, bool sam)
 946{
 947        u8 dam = LOWPAN_IPHC_DAM_01;
 948
 949        switch (lowpan_dev(dev)->lltype) {
 950        case LOWPAN_LLTYPE_IEEE802154:
 951                if (lowpan_iphc_compress_802154_lladdr(ipaddr, lladdr)) {
 952                        dam = LOWPAN_IPHC_DAM_11; /* 0-bits */
 953                        pr_debug("address compression 0 bits\n");
 954                        goto out;
 955                }
 956                break;
 957        default:
 958                if (lowpan_iphc_addr_equal(dev, NULL, ipaddr, lladdr)) {
 959                        dam = LOWPAN_IPHC_DAM_11;
 960                        pr_debug("address compression 0 bits\n");
 961                        goto out;
 962                }
 963
 964                break;
 965        }
 966
 967        if (lowpan_is_iid_16_bit_compressable(ipaddr)) {
 968                /* compress IID to 16 bits xxxx::XXXX */
 969                lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[7], 2);
 970                dam = LOWPAN_IPHC_DAM_10; /* 16-bits */
 971                raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)",
 972                                *hc_ptr - 2, 2);
 973                goto out;
 974        }
 975
 976        /* do not compress IID => xxxx::IID */
 977        lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[4], 8);
 978        raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)",
 979                        *hc_ptr - 8, 8);
 980
 981out:
 982
 983        if (sam)
 984                return lowpan_iphc_dam_to_sam_value[dam];
 985        else
 986                return dam;
 987}
 988
 989/* lowpan_iphc_get_tc - get the ECN + DCSP fields in hc format */
 990static inline u8 lowpan_iphc_get_tc(const struct ipv6hdr *hdr)
 991{
 992        u8 dscp, ecn;
 993
 994        /* hdr->priority contains the higher bits of dscp, lower are part of
 995         * flow_lbl[0]. Note ECN, DCSP is swapped in ipv6 hdr.
 996         */
 997        dscp = (hdr->priority << 2) | ((hdr->flow_lbl[0] & 0xc0) >> 6);
 998        /* ECN is at the two lower bits from first nibble of flow_lbl[0] */
 999        ecn = (hdr->flow_lbl[0] & 0x30);
1000        /* for pretty debug output, also shift ecn to get the ecn value */
1001        pr_debug("ecn 0x%02x dscp 0x%02x\n", ecn >> 4, dscp);
1002        /* ECN is at 0x30 now, shift it to have ECN + DCSP */
1003        return (ecn << 2) | dscp;
1004}
1005
1006/* lowpan_iphc_is_flow_lbl_zero - check if flow label is zero */
1007static inline bool lowpan_iphc_is_flow_lbl_zero(const struct ipv6hdr *hdr)
1008{
1009        return ((!(hdr->flow_lbl[0] & 0x0f)) &&
1010                !hdr->flow_lbl[1] && !hdr->flow_lbl[2]);
1011}
1012
1013/* lowpan_iphc_tf_compress - compress the traffic class which is set by
1014 *      ipv6hdr. Return the corresponding format identifier which is used.
1015 */
1016static u8 lowpan_iphc_tf_compress(u8 **hc_ptr, const struct ipv6hdr *hdr)
1017{
1018        /* get ecn dscp data in a byteformat as: ECN(hi) + DSCP(lo) */
1019        u8 tc = lowpan_iphc_get_tc(hdr), tf[4], val;
1020
1021        /* printout the traffic class in hc format */
1022        pr_debug("tc 0x%02x\n", tc);
1023
1024        if (lowpan_iphc_is_flow_lbl_zero(hdr)) {
1025                if (!tc) {
1026                        /* 11:  Traffic Class and Flow Label are elided. */
1027                        val = LOWPAN_IPHC_TF_11;
1028                } else {
1029                        /* 10:  ECN + DSCP (1 byte), Flow Label is elided.
1030                         *
1031                         *  0 1 2 3 4 5 6 7
1032                         * +-+-+-+-+-+-+-+-+
1033                         * |ECN|   DSCP    |
1034                         * +-+-+-+-+-+-+-+-+
1035                         */
1036                        lowpan_push_hc_data(hc_ptr, &tc, sizeof(tc));
1037                        val = LOWPAN_IPHC_TF_10;
1038                }
1039        } else {
1040                /* check if dscp is zero, it's after the first two bit */
1041                if (!(tc & 0x3f)) {
1042                        /* 01:  ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided
1043                         *
1044                         *                     1                   2
1045                         * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
1046                         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1047                         * |ECN|rsv|             Flow Label                |
1048                         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1049                         */
1050                        memcpy(&tf[0], &hdr->flow_lbl[0], 3);
1051                        /* zero the highest 4-bits, contains DCSP + ECN */
1052                        tf[0] &= ~0xf0;
1053                        /* set ECN */
1054                        tf[0] |= (tc & 0xc0);
1055
1056                        lowpan_push_hc_data(hc_ptr, tf, 3);
1057                        val = LOWPAN_IPHC_TF_01;
1058                } else {
1059                        /* 00:  ECN + DSCP + 4-bit Pad + Flow Label (4 bytes)
1060                         *
1061                         *                      1                   2                   3
1062                         *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1063                         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1064                         * |ECN|   DSCP    |  rsv  |             Flow Label                |
1065                         * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1066                         */
1067                        memcpy(&tf[0], &tc, sizeof(tc));
1068                        /* highest nibble of flow_lbl[0] is part of DSCP + ECN
1069                         * which will be the 4-bit pad and will be filled with
1070                         * zeros afterwards.
1071                         */
1072                        memcpy(&tf[1], &hdr->flow_lbl[0], 3);
1073                        /* zero the 4-bit pad, which is reserved */
1074                        tf[1] &= ~0xf0;
1075
1076                        lowpan_push_hc_data(hc_ptr, tf, 4);
1077                        val = LOWPAN_IPHC_TF_00;
1078                }
1079        }
1080
1081        return val;
1082}
1083
1084static u8 lowpan_iphc_mcast_ctx_addr_compress(u8 **hc_ptr,
1085                                              const struct lowpan_iphc_ctx *ctx,
1086                                              const struct in6_addr *ipaddr)
1087{
1088        u8 data[6];
1089
1090        /* flags/scope, reserved (RIID) */
1091        memcpy(data, &ipaddr->s6_addr[1], 2);
1092        /* group ID */
1093        memcpy(&data[1], &ipaddr->s6_addr[11], 4);
1094        lowpan_push_hc_data(hc_ptr, data, 6);
1095
1096        return LOWPAN_IPHC_DAM_00;
1097}
1098
1099static u8 lowpan_iphc_mcast_addr_compress(u8 **hc_ptr,
1100                                          const struct in6_addr *ipaddr)
1101{
1102        u8 val;
1103
1104        if (lowpan_is_mcast_addr_compressable8(ipaddr)) {
1105                pr_debug("compressed to 1 octet\n");
1106                /* use last byte */
1107                lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr[15], 1);
1108                val = LOWPAN_IPHC_DAM_11;
1109        } else if (lowpan_is_mcast_addr_compressable32(ipaddr)) {
1110                pr_debug("compressed to 4 octets\n");
1111                /* second byte + the last three */
1112                lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr[1], 1);
1113                lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr[13], 3);
1114                val = LOWPAN_IPHC_DAM_10;
1115        } else if (lowpan_is_mcast_addr_compressable48(ipaddr)) {
1116                pr_debug("compressed to 6 octets\n");
1117                /* second byte + the last five */
1118                lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr[1], 1);
1119                lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr[11], 5);
1120                val = LOWPAN_IPHC_DAM_01;
1121        } else {
1122                pr_debug("using full address\n");
1123                lowpan_push_hc_data(hc_ptr, ipaddr->s6_addr, 16);
1124                val = LOWPAN_IPHC_DAM_00;
1125        }
1126
1127        return val;
1128}
1129
1130int lowpan_header_compress(struct sk_buff *skb, const struct net_device *dev,
1131                           const void *daddr, const void *saddr)
1132{
1133        u8 iphc0, iphc1, *hc_ptr, cid = 0;
1134        struct ipv6hdr *hdr;
1135        u8 head[LOWPAN_IPHC_MAX_HC_BUF_LEN] = {};
1136        struct lowpan_iphc_ctx *dci, *sci, dci_entry, sci_entry;
1137        int ret, ipv6_daddr_type, ipv6_saddr_type;
1138
1139        if (skb->protocol != htons(ETH_P_IPV6))
1140                return -EINVAL;
1141
1142        hdr = ipv6_hdr(skb);
1143        hc_ptr = head + 2;
1144
1145        pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength  = %d\n"
1146                 "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest    = %pI6c\n",
1147                 hdr->version, ntohs(hdr->payload_len), hdr->nexthdr,
1148                 hdr->hop_limit, &hdr->daddr);
1149
1150        raw_dump_table(__func__, "raw skb network header dump",
1151                       skb_network_header(skb), sizeof(struct ipv6hdr));
1152
1153        /* As we copy some bit-length fields, in the IPHC encoding bytes,
1154         * we sometimes use |=
1155         * If the field is 0, and the current bit value in memory is 1,
1156         * this does not work. We therefore reset the IPHC encoding here
1157         */
1158        iphc0 = LOWPAN_DISPATCH_IPHC;
1159        iphc1 = 0;
1160
1161        raw_dump_table(__func__, "sending raw skb network uncompressed packet",
1162                       skb->data, skb->len);
1163
1164        ipv6_daddr_type = ipv6_addr_type(&hdr->daddr);
1165        spin_lock_bh(&lowpan_dev(dev)->ctx.lock);
1166        if (ipv6_daddr_type & IPV6_ADDR_MULTICAST)
1167                dci = lowpan_iphc_ctx_get_by_mcast_addr(dev, &hdr->daddr);
1168        else
1169                dci = lowpan_iphc_ctx_get_by_addr(dev, &hdr->daddr);
1170        if (dci) {
1171                memcpy(&dci_entry, dci, sizeof(*dci));
1172                cid |= dci->id;
1173        }
1174        spin_unlock_bh(&lowpan_dev(dev)->ctx.lock);
1175
1176        spin_lock_bh(&lowpan_dev(dev)->ctx.lock);
1177        sci = lowpan_iphc_ctx_get_by_addr(dev, &hdr->saddr);
1178        if (sci) {
1179                memcpy(&sci_entry, sci, sizeof(*sci));
1180                cid |= (sci->id << 4);
1181        }
1182        spin_unlock_bh(&lowpan_dev(dev)->ctx.lock);
1183
1184        /* if cid is zero it will be compressed */
1185        if (cid) {
1186                iphc1 |= LOWPAN_IPHC_CID;
1187                lowpan_push_hc_data(&hc_ptr, &cid, sizeof(cid));
1188        }
1189
1190        /* Traffic Class, Flow Label compression */
1191        iphc0 |= lowpan_iphc_tf_compress(&hc_ptr, hdr);
1192
1193        /* NOTE: payload length is always compressed */
1194
1195        /* Check if we provide the nhc format for nexthdr and compression
1196         * functionality. If not nexthdr is handled inline and not compressed.
1197         */
1198        ret = lowpan_nhc_check_compression(skb, hdr, &hc_ptr);
1199        if (ret == -ENOENT)
1200                lowpan_push_hc_data(&hc_ptr, &hdr->nexthdr,
1201                                    sizeof(hdr->nexthdr));
1202        else
1203                iphc0 |= LOWPAN_IPHC_NH;
1204
1205        /* Hop limit
1206         * if 1:   compress, encoding is 01
1207         * if 64:  compress, encoding is 10
1208         * if 255: compress, encoding is 11
1209         * else do not compress
1210         */
1211        switch (hdr->hop_limit) {
1212        case 1:
1213                iphc0 |= LOWPAN_IPHC_HLIM_01;
1214                break;
1215        case 64:
1216                iphc0 |= LOWPAN_IPHC_HLIM_10;
1217                break;
1218        case 255:
1219                iphc0 |= LOWPAN_IPHC_HLIM_11;
1220                break;
1221        default:
1222                lowpan_push_hc_data(&hc_ptr, &hdr->hop_limit,
1223                                    sizeof(hdr->hop_limit));
1224        }
1225
1226        ipv6_saddr_type = ipv6_addr_type(&hdr->saddr);
1227        /* source address compression */
1228        if (ipv6_saddr_type == IPV6_ADDR_ANY) {
1229                pr_debug("source address is unspecified, setting SAC\n");
1230                iphc1 |= LOWPAN_IPHC_SAC;
1231        } else {
1232                if (sci) {
1233                        iphc1 |= lowpan_compress_ctx_addr(&hc_ptr, dev,
1234                                                          &hdr->saddr,
1235                                                          &sci_entry, saddr,
1236                                                          true);
1237                        iphc1 |= LOWPAN_IPHC_SAC;
1238                } else {
1239                        if (ipv6_saddr_type & IPV6_ADDR_LINKLOCAL &&
1240                            lowpan_is_linklocal_zero_padded(hdr->saddr)) {
1241                                iphc1 |= lowpan_compress_addr_64(&hc_ptr, dev,
1242                                                                 &hdr->saddr,
1243                                                                 saddr, true);
1244                                pr_debug("source address unicast link-local %pI6c iphc1 0x%02x\n",
1245                                         &hdr->saddr, iphc1);
1246                        } else {
1247                                pr_debug("send the full source address\n");
1248                                lowpan_push_hc_data(&hc_ptr,
1249                                                    hdr->saddr.s6_addr, 16);
1250                        }
1251                }
1252        }
1253
1254        /* destination address compression */
1255        if (ipv6_daddr_type & IPV6_ADDR_MULTICAST) {
1256                pr_debug("destination address is multicast: ");
1257                iphc1 |= LOWPAN_IPHC_M;
1258                if (dci) {
1259                        iphc1 |= lowpan_iphc_mcast_ctx_addr_compress(&hc_ptr,
1260                                                                     &dci_entry,
1261                                                                     &hdr->daddr);
1262                        iphc1 |= LOWPAN_IPHC_DAC;
1263                } else {
1264                        iphc1 |= lowpan_iphc_mcast_addr_compress(&hc_ptr,
1265                                                                 &hdr->daddr);
1266                }
1267        } else {
1268                if (dci) {
1269                        iphc1 |= lowpan_compress_ctx_addr(&hc_ptr, dev,
1270                                                          &hdr->daddr,
1271                                                          &dci_entry, daddr,
1272                                                          false);
1273                        iphc1 |= LOWPAN_IPHC_DAC;
1274                } else {
1275                        if (ipv6_daddr_type & IPV6_ADDR_LINKLOCAL &&
1276                            lowpan_is_linklocal_zero_padded(hdr->daddr)) {
1277                                iphc1 |= lowpan_compress_addr_64(&hc_ptr, dev,
1278                                                                 &hdr->daddr,
1279                                                                 daddr, false);
1280                                pr_debug("dest address unicast link-local %pI6c iphc1 0x%02x\n",
1281                                         &hdr->daddr, iphc1);
1282                        } else {
1283                                pr_debug("dest address unicast %pI6c\n",
1284                                         &hdr->daddr);
1285                                lowpan_push_hc_data(&hc_ptr,
1286                                                    hdr->daddr.s6_addr, 16);
1287                        }
1288                }
1289        }
1290
1291        /* next header compression */
1292        if (iphc0 & LOWPAN_IPHC_NH) {
1293                ret = lowpan_nhc_do_compression(skb, hdr, &hc_ptr);
1294                if (ret < 0)
1295                        return ret;
1296        }
1297
1298        head[0] = iphc0;
1299        head[1] = iphc1;
1300
1301        skb_pull(skb, sizeof(struct ipv6hdr));
1302        skb_reset_transport_header(skb);
1303        memcpy(skb_push(skb, hc_ptr - head), head, hc_ptr - head);
1304        skb_reset_network_header(skb);
1305
1306        pr_debug("header len %d skb %u\n", (int)(hc_ptr - head), skb->len);
1307
1308        raw_dump_table(__func__, "raw skb data dump compressed",
1309                       skb->data, skb->len);
1310        return 0;
1311}
1312EXPORT_SYMBOL_GPL(lowpan_header_compress);
1313