iphc.c 17.5 KB
Newer Older
1 2 3 4 5
/*
 * Copyright 2011, Siemens AG
 * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
 */

6
/* Based on patches from Jon Smirl <jonsmirl@gmail.com>
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
 * Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

/* Jon's code is based on 6lowpan implementation for Contiki which is:
 * Copyright (c) 2008, Swedish Institute of Computer Science.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the Institute nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <linux/bitops.h>
#include <linux/if_arp.h>
51
#include <linux/module.h>
52
#include <linux/netdevice.h>
53
#include <net/6lowpan.h>
54 55 56
#include <net/ipv6.h>
#include <net/af_ieee802154.h>

57 58
#include "nhc.h"

59
/* Uncompress address function for source and
60 61 62 63 64
 * destination address(non-multicast).
 *
 * address_mode is sam value or dam value.
 */
static int uncompress_addr(struct sk_buff *skb,
65 66 67
			   struct in6_addr *ipaddr, const u8 address_mode,
			   const u8 *lladdr, const u8 addr_type,
			   const u8 addr_len)
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
{
	bool fail;

	switch (address_mode) {
	case LOWPAN_IPHC_ADDR_00:
		/* for global link addresses */
		fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
		break;
	case LOWPAN_IPHC_ADDR_01:
		/* fe:80::XXXX:XXXX:XXXX:XXXX */
		ipaddr->s6_addr[0] = 0xFE;
		ipaddr->s6_addr[1] = 0x80;
		fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8);
		break;
	case LOWPAN_IPHC_ADDR_02:
		/* fe:80::ff:fe00:XXXX */
		ipaddr->s6_addr[0] = 0xFE;
		ipaddr->s6_addr[1] = 0x80;
		ipaddr->s6_addr[11] = 0xFF;
		ipaddr->s6_addr[12] = 0xFE;
		fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2);
		break;
	case LOWPAN_IPHC_ADDR_03:
		fail = false;
		switch (addr_type) {
		case IEEE802154_ADDR_LONG:
			/* fe:80::XXXX:XXXX:XXXX:XXXX
			 *        \_________________/
			 *              hwaddr
			 */
			ipaddr->s6_addr[0] = 0xFE;
			ipaddr->s6_addr[1] = 0x80;
			memcpy(&ipaddr->s6_addr[8], lladdr, addr_len);
			/* second bit-flip (Universe/Local)
			 * is done according RFC2464
			 */
			ipaddr->s6_addr[8] ^= 0x02;
			break;
		case IEEE802154_ADDR_SHORT:
			/* fe:80::ff:fe00:XXXX
			 *		  \__/
			 *	       short_addr
			 *
			 * Universe/Local bit is zero.
			 */
			ipaddr->s6_addr[0] = 0xFE;
			ipaddr->s6_addr[1] = 0x80;
			ipaddr->s6_addr[11] = 0xFF;
			ipaddr->s6_addr[12] = 0xFE;
			ipaddr->s6_addr16[7] = htons(*((u16 *)lladdr));
			break;
		default:
			pr_debug("Invalid addr_type set\n");
			return -EINVAL;
		}
		break;
	default:
		pr_debug("Invalid address mode value: 0x%x\n", address_mode);
		return -EINVAL;
	}

	if (fail) {
		pr_debug("Failed to fetch skb data\n");
		return -EIO;
	}

	raw_dump_inline(NULL, "Reconstructed ipv6 addr is",
			ipaddr->s6_addr, 16);

	return 0;
}

140
/* Uncompress address function for source context
141 142 143
 * based address(non-multicast).
 */
static int uncompress_context_based_src_addr(struct sk_buff *skb,
144 145
					     struct in6_addr *ipaddr,
					     const u8 sam)
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
{
	switch (sam) {
	case LOWPAN_IPHC_ADDR_00:
		/* unspec address ::
		 * Do nothing, address is already ::
		 */
		break;
	case LOWPAN_IPHC_ADDR_01:
		/* TODO */
	case LOWPAN_IPHC_ADDR_02:
		/* TODO */
	case LOWPAN_IPHC_ADDR_03:
		/* TODO */
		netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam);
		return -EINVAL;
	default:
		pr_debug("Invalid sam value: 0x%x\n", sam);
		return -EINVAL;
	}

	raw_dump_inline(NULL,
			"Reconstructed context based ipv6 src addr is",
			ipaddr->s6_addr, 16);

	return 0;
}

/* Uncompress function for multicast destination address,
 * when M bit is set.
 */
176 177 178
static int lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
					     struct in6_addr *ipaddr,
					     const u8 dam)
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
{
	bool fail;

	switch (dam) {
	case LOWPAN_IPHC_DAM_00:
		/* 00:  128 bits.  The full address
		 * is carried in-line.
		 */
		fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
		break;
	case LOWPAN_IPHC_DAM_01:
		/* 01:  48 bits.  The address takes
		 * the form ffXX::00XX:XXXX:XXXX.
		 */
		ipaddr->s6_addr[0] = 0xFF;
		fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
		fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5);
		break;
	case LOWPAN_IPHC_DAM_10:
		/* 10:  32 bits.  The address takes
		 * the form ffXX::00XX:XXXX.
		 */
		ipaddr->s6_addr[0] = 0xFF;
		fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
		fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3);
		break;
	case LOWPAN_IPHC_DAM_11:
		/* 11:  8 bits.  The address takes
		 * the form ff02::00XX.
		 */
		ipaddr->s6_addr[0] = 0xFF;
		ipaddr->s6_addr[1] = 0x02;
		fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1);
		break;
	default:
		pr_debug("DAM value has a wrong value: 0x%x\n", dam);
		return -EINVAL;
	}

	if (fail) {
		pr_debug("Failed to fetch skb data\n");
		return -EIO;
	}

	raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is",
224
			ipaddr->s6_addr, 16);
225 226 227 228 229 230 231

	return 0;
}

/* TTL uncompression values */
static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 };

232 233 234 235 236 237
int
lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
			 const u8 *saddr, const u8 saddr_type,
			 const u8 saddr_len, const u8 *daddr,
			 const u8 daddr_type, const u8 daddr_len,
			 u8 iphc0, u8 iphc1)
238 239 240 241 242 243
{
	struct ipv6hdr hdr = {};
	u8 tmp, num_context = 0;
	int err;

	raw_dump_table(__func__, "raw skb data dump uncompressed",
244
		       skb->data, skb->len);
245 246 247 248

	/* another if the CID flag is set */
	if (iphc1 & LOWPAN_IPHC_CID) {
		pr_debug("CID flag is set, increase header with one\n");
249
		if (lowpan_fetch_skb(skb, &num_context, sizeof(num_context)))
250
			return -EINVAL;
251 252 253 254 255 256
	}

	hdr.version = 6;

	/* Traffic Class and Flow Label */
	switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) {
257
	/* Traffic Class and FLow Label carried in-line
258 259 260
	 * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes)
	 */
	case 0: /* 00b */
261
		if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
262
			return -EINVAL;
263 264 265 266 267 268 269

		memcpy(&hdr.flow_lbl, &skb->data[0], 3);
		skb_pull(skb, 3);
		hdr.priority = ((tmp >> 2) & 0x0f);
		hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) |
					(hdr.flow_lbl[0] & 0x0f);
		break;
270
	/* Traffic class carried in-line
271 272 273
	 * ECN + DSCP (1 byte), Flow Label is elided
	 */
	case 2: /* 10b */
274
		if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
275
			return -EINVAL;
276 277 278 279

		hdr.priority = ((tmp >> 2) & 0x0f);
		hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30);
		break;
280
	/* Flow Label carried in-line
281 282 283
	 * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided
	 */
	case 1: /* 01b */
284
		if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
285
			return -EINVAL;
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300

		hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30);
		memcpy(&hdr.flow_lbl[1], &skb->data[0], 2);
		skb_pull(skb, 2);
		break;
	/* Traffic Class and Flow Label are elided */
	case 3: /* 11b */
		break;
	default:
		break;
	}

	/* Next Header */
	if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
		/* Next header is carried inline */
301
		if (lowpan_fetch_skb(skb, &hdr.nexthdr, sizeof(hdr.nexthdr)))
302
			return -EINVAL;
303 304 305 306 307 308

		pr_debug("NH flag is set, next header carried inline: %02x\n",
			 hdr.nexthdr);
	}

	/* Hop Limit */
309
	if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I) {
310
		hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03];
311
	} else {
312 313
		if (lowpan_fetch_skb(skb, &hdr.hop_limit,
				     sizeof(hdr.hop_limit)))
314
			return -EINVAL;
315 316 317 318 319 320 321 322
	}

	/* Extract SAM to the tmp variable */
	tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03;

	if (iphc1 & LOWPAN_IPHC_SAC) {
		/* Source address context based uncompression */
		pr_debug("SAC bit is set. Handle context based source address.\n");
323
		err = uncompress_context_based_src_addr(skb, &hdr.saddr, tmp);
324 325 326 327
	} else {
		/* Source address uncompression */
		pr_debug("source address stateless compression\n");
		err = uncompress_addr(skb, &hdr.saddr, tmp, saddr,
328
				      saddr_type, saddr_len);
329 330 331 332
	}

	/* Check on error of previous branch */
	if (err)
333
		return -EINVAL;
334 335 336 337 338 339 340 341 342 343

	/* Extract DAM to the tmp variable */
	tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03;

	/* check for Multicast Compression */
	if (iphc1 & LOWPAN_IPHC_M) {
		if (iphc1 & LOWPAN_IPHC_DAC) {
			pr_debug("dest: context-based mcast compression\n");
			/* TODO: implement this */
		} else {
344 345 346
			err = lowpan_uncompress_multicast_daddr(skb, &hdr.daddr,
								tmp);

347
			if (err)
348
				return -EINVAL;
349 350 351
		}
	} else {
		err = uncompress_addr(skb, &hdr.daddr, tmp, daddr,
352
				      daddr_type, daddr_len);
353
		pr_debug("dest: stateless compression mode %d dest %pI6c\n",
354
			 tmp, &hdr.daddr);
355
		if (err)
356
			return -EINVAL;
357 358
	}

359
	/* Next header data uncompression */
360
	if (iphc0 & LOWPAN_IPHC_NH_C) {
361 362
		err = lowpan_nhc_do_uncompression(skb, dev, &hdr);
		if (err < 0)
363 364 365
			return err;
	} else {
		err = skb_cow(skb, sizeof(hdr));
366
		if (unlikely(err))
367
			return err;
368 369 370 371 372 373 374 375 376 377 378 379
	}

	hdr.payload_len = htons(skb->len);

	pr_debug("skb headroom size = %d, data length = %d\n",
		 skb_headroom(skb), skb->len);

	pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength  = %d\n\t"
		 "nexthdr = 0x%02x\n\thop_lim = %d\n\tdest    = %pI6c\n",
		hdr.version, ntohs(hdr.payload_len), hdr.nexthdr,
		hdr.hop_limit, &hdr.daddr);

380 381 382
	skb_push(skb, sizeof(hdr));
	skb_reset_network_header(skb);
	skb_copy_to_linear_data(skb, &hdr, sizeof(hdr));
383

384
	raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr));
385

386
	return 0;
387
}
388
EXPORT_SYMBOL_GPL(lowpan_header_decompress);
389

390
static u8 lowpan_compress_addr_64(u8 **hc_ptr, u8 shift,
391 392
				  const struct in6_addr *ipaddr,
				  const unsigned char *lladdr)
393 394 395 396 397 398 399 400
{
	u8 val = 0;

	if (is_addr_mac_addr_based(ipaddr, lladdr)) {
		val = 3; /* 0-bits */
		pr_debug("address compression 0 bits\n");
	} else if (lowpan_is_iid_16_bit_compressable(ipaddr)) {
		/* compress IID to 16 bits xxxx::XXXX */
401
		lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[7], 2);
402 403
		val = 2; /* 16-bits */
		raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)",
404
				*hc_ptr - 2, 2);
405 406
	} else {
		/* do not compress IID => xxxx::IID */
407
		lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[4], 8);
408 409
		val = 1; /* 64-bits */
		raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)",
410
				*hc_ptr - 8, 8);
411 412 413 414 415 416
	}

	return rol8(val, shift);
}

int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
417 418
			   unsigned short type, const void *_daddr,
			   const void *_saddr, unsigned int len)
419
{
420
	u8 tmp, iphc0, iphc1, *hc_ptr;
421 422
	struct ipv6hdr *hdr;
	u8 head[100] = {};
423
	int ret, addr_type;
424 425 426 427 428

	if (type != ETH_P_IPV6)
		return -EINVAL;

	hdr = ipv6_hdr(skb);
429
	hc_ptr = head + 2;
430 431 432

	pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength  = %d\n"
		 "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest    = %pI6c\n",
433 434
		 hdr->version, ntohs(hdr->payload_len), hdr->nexthdr,
		 hdr->hop_limit, &hdr->daddr);
435 436

	raw_dump_table(__func__, "raw skb network header dump",
437
		       skb_network_header(skb), sizeof(struct ipv6hdr));
438

439
	/* As we copy some bit-length fields, in the IPHC encoding bytes,
440 441 442 443 444 445 446 447 448 449 450 451 452 453
	 * we sometimes use |=
	 * If the field is 0, and the current bit value in memory is 1,
	 * this does not work. We therefore reset the IPHC encoding here
	 */
	iphc0 = LOWPAN_DISPATCH_IPHC;
	iphc1 = 0;

	/* TODO: context lookup */

	raw_dump_inline(__func__, "saddr",
			(unsigned char *)_saddr, IEEE802154_ADDR_LEN);
	raw_dump_inline(__func__, "daddr",
			(unsigned char *)_daddr, IEEE802154_ADDR_LEN);

454
	raw_dump_table(__func__, "sending raw skb network uncompressed packet",
455
		       skb->data, skb->len);
456

457
	/* Traffic class, flow label
458 459 460 461 462
	 * If flow label is 0, compress it. If traffic class is 0, compress it
	 * We have to process both in the same time as the offset of traffic
	 * class depends on the presence of version and flow label
	 */

463
	/* hc format of TC is ECN | DSCP , original one is DSCP | ECN */
464 465 466 467
	tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4);
	tmp = ((tmp & 0x03) << 6) | (tmp >> 2);

	if (((hdr->flow_lbl[0] & 0x0F) == 0) &&
468
	    (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) {
469 470 471
		/* flow label can be compressed */
		iphc0 |= LOWPAN_IPHC_FL_C;
		if ((hdr->priority == 0) &&
472
		    ((hdr->flow_lbl[0] & 0xF0) == 0)) {
473 474 475 476
			/* compress (elide) all */
			iphc0 |= LOWPAN_IPHC_TC_C;
		} else {
			/* compress only the flow label */
477 478
			*hc_ptr = tmp;
			hc_ptr += 1;
479 480 481 482
		}
	} else {
		/* Flow label cannot be compressed */
		if ((hdr->priority == 0) &&
483
		    ((hdr->flow_lbl[0] & 0xF0) == 0)) {
484 485
			/* compress only traffic class */
			iphc0 |= LOWPAN_IPHC_TC_C;
486 487 488
			*hc_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F);
			memcpy(hc_ptr + 1, &hdr->flow_lbl[1], 2);
			hc_ptr += 3;
489 490
		} else {
			/* compress nothing */
491
			memcpy(hc_ptr, hdr, 4);
492
			/* replace the top byte with new ECN | DSCP format */
493 494
			*hc_ptr = tmp;
			hc_ptr += 4;
495 496 497 498 499
		}
	}

	/* NOTE: payload length is always compressed */

500 501 502 503 504 505
	/* Check if we provide the nhc format for nexthdr and compression
	 * functionality. If not nexthdr is handled inline and not compressed.
	 */
	ret = lowpan_nhc_check_compression(skb, hdr, &hc_ptr, &iphc0);
	if (ret < 0)
		return ret;
506

507
	/* Hop limit
508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
	 * if 1:   compress, encoding is 01
	 * if 64:  compress, encoding is 10
	 * if 255: compress, encoding is 11
	 * else do not compress
	 */
	switch (hdr->hop_limit) {
	case 1:
		iphc0 |= LOWPAN_IPHC_TTL_1;
		break;
	case 64:
		iphc0 |= LOWPAN_IPHC_TTL_64;
		break;
	case 255:
		iphc0 |= LOWPAN_IPHC_TTL_255;
		break;
	default:
524 525
		lowpan_push_hc_data(&hc_ptr, &hdr->hop_limit,
				    sizeof(hdr->hop_limit));
526 527
	}

528
	addr_type = ipv6_addr_type(&hdr->saddr);
529
	/* source address compression */
530
	if (addr_type == IPV6_ADDR_ANY) {
531 532 533
		pr_debug("source address is unspecified, setting SAC\n");
		iphc1 |= LOWPAN_IPHC_SAC;
	} else {
534 535 536 537 538 539 540 541 542 543
		if (addr_type & IPV6_ADDR_LINKLOCAL) {
			iphc1 |= lowpan_compress_addr_64(&hc_ptr,
							 LOWPAN_IPHC_SAM_BIT,
							 &hdr->saddr, _saddr);
			pr_debug("source address unicast link-local %pI6c iphc1 0x%02x\n",
				 &hdr->saddr, iphc1);
		} else {
			pr_debug("send the full source address\n");
			lowpan_push_hc_data(&hc_ptr, hdr->saddr.s6_addr, 16);
		}
544 545
	}

546
	addr_type = ipv6_addr_type(&hdr->daddr);
547
	/* destination address compression */
548
	if (addr_type & IPV6_ADDR_MULTICAST) {
549 550 551 552 553 554
		pr_debug("destination address is multicast: ");
		iphc1 |= LOWPAN_IPHC_M;
		if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) {
			pr_debug("compressed to 1 octet\n");
			iphc1 |= LOWPAN_IPHC_DAM_11;
			/* use last byte */
555 556
			lowpan_push_hc_data(&hc_ptr,
					    &hdr->daddr.s6_addr[15], 1);
557 558 559 560
		} else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) {
			pr_debug("compressed to 4 octets\n");
			iphc1 |= LOWPAN_IPHC_DAM_10;
			/* second byte + the last three */
561 562 563 564
			lowpan_push_hc_data(&hc_ptr,
					    &hdr->daddr.s6_addr[1], 1);
			lowpan_push_hc_data(&hc_ptr,
					    &hdr->daddr.s6_addr[13], 3);
565 566 567 568
		} else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) {
			pr_debug("compressed to 6 octets\n");
			iphc1 |= LOWPAN_IPHC_DAM_01;
			/* second byte + the last five */
569 570 571 572
			lowpan_push_hc_data(&hc_ptr,
					    &hdr->daddr.s6_addr[1], 1);
			lowpan_push_hc_data(&hc_ptr,
					    &hdr->daddr.s6_addr[11], 5);
573 574 575
		} else {
			pr_debug("using full address\n");
			iphc1 |= LOWPAN_IPHC_DAM_00;
576
			lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16);
577 578
		}
	} else {
579 580
		if (addr_type & IPV6_ADDR_LINKLOCAL) {
			/* TODO: context lookup */
581
			iphc1 |= lowpan_compress_addr_64(&hc_ptr,
582 583
				LOWPAN_IPHC_DAM_BIT, &hdr->daddr, _daddr);
			pr_debug("dest address unicast link-local %pI6c "
584
				 "iphc1 0x%02x\n", &hdr->daddr, iphc1);
585 586
		} else {
			pr_debug("dest address unicast %pI6c\n", &hdr->daddr);
587
			lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16);
588 589 590
		}
	}

591 592 593 594 595 596
	/* next header compression */
	if (iphc0 & LOWPAN_IPHC_NH_C) {
		ret = lowpan_nhc_do_compression(skb, hdr, &hc_ptr);
		if (ret < 0)
			return ret;
	}
597 598 599 600 601 602

	head[0] = iphc0;
	head[1] = iphc1;

	skb_pull(skb, sizeof(struct ipv6hdr));
	skb_reset_transport_header(skb);
603
	memcpy(skb_push(skb, hc_ptr - head), head, hc_ptr - head);
604 605
	skb_reset_network_header(skb);

606
	pr_debug("header len %d skb %u\n", (int)(hc_ptr - head), skb->len);
607 608

	raw_dump_table(__func__, "raw skb data dump compressed",
609
		       skb->data, skb->len);
610 611 612
	return 0;
}
EXPORT_SYMBOL_GPL(lowpan_header_compress);
613

614 615 616 617 618 619 620 621
static int __init lowpan_module_init(void)
{
	request_module_nowait("nhc_udp");

	return 0;
}
module_init(lowpan_module_init);

622
MODULE_LICENSE("GPL");