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