iphc.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. /*
  2. * Copyright 2011, Siemens AG
  3. * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
  4. */
  5. /* Based on patches from Jon Smirl <jonsmirl@gmail.com>
  6. * Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License version 2
  10. * as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. */
  18. /* Jon's code is based on 6lowpan implementation for Contiki which is:
  19. * Copyright (c) 2008, Swedish Institute of Computer Science.
  20. * All rights reserved.
  21. *
  22. * Redistribution and use in source and binary forms, with or without
  23. * modification, are permitted provided that the following conditions
  24. * are met:
  25. * 1. Redistributions of source code must retain the above copyright
  26. * notice, this list of conditions and the following disclaimer.
  27. * 2. Redistributions in binary form must reproduce the above copyright
  28. * notice, this list of conditions and the following disclaimer in the
  29. * documentation and/or other materials provided with the distribution.
  30. * 3. Neither the name of the Institute nor the names of its contributors
  31. * may be used to endorse or promote products derived from this software
  32. * without specific prior written permission.
  33. *
  34. * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  35. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  36. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  37. * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  38. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  39. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  40. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  41. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  42. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  43. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  44. * SUCH DAMAGE.
  45. */
  46. #include <linux/bitops.h>
  47. #include <linux/if_arp.h>
  48. #include <linux/module.h>
  49. #include <linux/netdevice.h>
  50. #include <net/6lowpan.h>
  51. #include <net/ipv6.h>
  52. #include <net/af_ieee802154.h>
  53. #include "nhc.h"
  54. /* Uncompress address function for source and
  55. * destination address(non-multicast).
  56. *
  57. * address_mode is sam value or dam value.
  58. */
  59. static int uncompress_addr(struct sk_buff *skb,
  60. struct in6_addr *ipaddr, const u8 address_mode,
  61. const u8 *lladdr, const u8 addr_type,
  62. const u8 addr_len)
  63. {
  64. bool fail;
  65. switch (address_mode) {
  66. case LOWPAN_IPHC_ADDR_00:
  67. /* for global link addresses */
  68. fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
  69. break;
  70. case LOWPAN_IPHC_ADDR_01:
  71. /* fe:80::XXXX:XXXX:XXXX:XXXX */
  72. ipaddr->s6_addr[0] = 0xFE;
  73. ipaddr->s6_addr[1] = 0x80;
  74. fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8);
  75. break;
  76. case LOWPAN_IPHC_ADDR_02:
  77. /* fe:80::ff:fe00:XXXX */
  78. ipaddr->s6_addr[0] = 0xFE;
  79. ipaddr->s6_addr[1] = 0x80;
  80. ipaddr->s6_addr[11] = 0xFF;
  81. ipaddr->s6_addr[12] = 0xFE;
  82. fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2);
  83. break;
  84. case LOWPAN_IPHC_ADDR_03:
  85. fail = false;
  86. switch (addr_type) {
  87. case IEEE802154_ADDR_LONG:
  88. /* fe:80::XXXX:XXXX:XXXX:XXXX
  89. * \_________________/
  90. * hwaddr
  91. */
  92. ipaddr->s6_addr[0] = 0xFE;
  93. ipaddr->s6_addr[1] = 0x80;
  94. memcpy(&ipaddr->s6_addr[8], lladdr, addr_len);
  95. /* second bit-flip (Universe/Local)
  96. * is done according RFC2464
  97. */
  98. ipaddr->s6_addr[8] ^= 0x02;
  99. break;
  100. case IEEE802154_ADDR_SHORT:
  101. /* fe:80::ff:fe00:XXXX
  102. * \__/
  103. * short_addr
  104. *
  105. * Universe/Local bit is zero.
  106. */
  107. ipaddr->s6_addr[0] = 0xFE;
  108. ipaddr->s6_addr[1] = 0x80;
  109. ipaddr->s6_addr[11] = 0xFF;
  110. ipaddr->s6_addr[12] = 0xFE;
  111. ipaddr->s6_addr16[7] = htons(*((u16 *)lladdr));
  112. break;
  113. default:
  114. pr_debug("Invalid addr_type set\n");
  115. return -EINVAL;
  116. }
  117. break;
  118. default:
  119. pr_debug("Invalid address mode value: 0x%x\n", address_mode);
  120. return -EINVAL;
  121. }
  122. if (fail) {
  123. pr_debug("Failed to fetch skb data\n");
  124. return -EIO;
  125. }
  126. raw_dump_inline(NULL, "Reconstructed ipv6 addr is",
  127. ipaddr->s6_addr, 16);
  128. return 0;
  129. }
  130. /* Uncompress address function for source context
  131. * based address(non-multicast).
  132. */
  133. static int uncompress_context_based_src_addr(struct sk_buff *skb,
  134. struct in6_addr *ipaddr,
  135. const u8 sam)
  136. {
  137. switch (sam) {
  138. case LOWPAN_IPHC_ADDR_00:
  139. /* unspec address ::
  140. * Do nothing, address is already ::
  141. */
  142. break;
  143. case LOWPAN_IPHC_ADDR_01:
  144. /* TODO */
  145. case LOWPAN_IPHC_ADDR_02:
  146. /* TODO */
  147. case LOWPAN_IPHC_ADDR_03:
  148. /* TODO */
  149. netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam);
  150. return -EINVAL;
  151. default:
  152. pr_debug("Invalid sam value: 0x%x\n", sam);
  153. return -EINVAL;
  154. }
  155. raw_dump_inline(NULL,
  156. "Reconstructed context based ipv6 src addr is",
  157. ipaddr->s6_addr, 16);
  158. return 0;
  159. }
  160. /* Uncompress function for multicast destination address,
  161. * when M bit is set.
  162. */
  163. static int lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
  164. struct in6_addr *ipaddr,
  165. const u8 dam)
  166. {
  167. bool fail;
  168. switch (dam) {
  169. case LOWPAN_IPHC_DAM_00:
  170. /* 00: 128 bits. The full address
  171. * is carried in-line.
  172. */
  173. fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
  174. break;
  175. case LOWPAN_IPHC_DAM_01:
  176. /* 01: 48 bits. The address takes
  177. * the form ffXX::00XX:XXXX:XXXX.
  178. */
  179. ipaddr->s6_addr[0] = 0xFF;
  180. fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
  181. fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5);
  182. break;
  183. case LOWPAN_IPHC_DAM_10:
  184. /* 10: 32 bits. The address takes
  185. * the form ffXX::00XX:XXXX.
  186. */
  187. ipaddr->s6_addr[0] = 0xFF;
  188. fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
  189. fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3);
  190. break;
  191. case LOWPAN_IPHC_DAM_11:
  192. /* 11: 8 bits. The address takes
  193. * the form ff02::00XX.
  194. */
  195. ipaddr->s6_addr[0] = 0xFF;
  196. ipaddr->s6_addr[1] = 0x02;
  197. fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1);
  198. break;
  199. default:
  200. pr_debug("DAM value has a wrong value: 0x%x\n", dam);
  201. return -EINVAL;
  202. }
  203. if (fail) {
  204. pr_debug("Failed to fetch skb data\n");
  205. return -EIO;
  206. }
  207. raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is",
  208. ipaddr->s6_addr, 16);
  209. return 0;
  210. }
  211. /* TTL uncompression values */
  212. static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 };
  213. int
  214. lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
  215. const u8 *saddr, const u8 saddr_type,
  216. const u8 saddr_len, const u8 *daddr,
  217. const u8 daddr_type, const u8 daddr_len,
  218. u8 iphc0, u8 iphc1)
  219. {
  220. struct ipv6hdr hdr = {};
  221. u8 tmp, num_context = 0;
  222. int err;
  223. raw_dump_table(__func__, "raw skb data dump uncompressed",
  224. skb->data, skb->len);
  225. /* another if the CID flag is set */
  226. if (iphc1 & LOWPAN_IPHC_CID) {
  227. pr_debug("CID flag is set, increase header with one\n");
  228. if (lowpan_fetch_skb(skb, &num_context, sizeof(num_context)))
  229. return -EINVAL;
  230. }
  231. hdr.version = 6;
  232. /* Traffic Class and Flow Label */
  233. switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) {
  234. /* Traffic Class and FLow Label carried in-line
  235. * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes)
  236. */
  237. case 0: /* 00b */
  238. if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
  239. return -EINVAL;
  240. memcpy(&hdr.flow_lbl, &skb->data[0], 3);
  241. skb_pull(skb, 3);
  242. hdr.priority = ((tmp >> 2) & 0x0f);
  243. hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) |
  244. (hdr.flow_lbl[0] & 0x0f);
  245. break;
  246. /* Traffic class carried in-line
  247. * ECN + DSCP (1 byte), Flow Label is elided
  248. */
  249. case 2: /* 10b */
  250. if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
  251. return -EINVAL;
  252. hdr.priority = ((tmp >> 2) & 0x0f);
  253. hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30);
  254. break;
  255. /* Flow Label carried in-line
  256. * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided
  257. */
  258. case 1: /* 01b */
  259. if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
  260. return -EINVAL;
  261. hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30);
  262. memcpy(&hdr.flow_lbl[1], &skb->data[0], 2);
  263. skb_pull(skb, 2);
  264. break;
  265. /* Traffic Class and Flow Label are elided */
  266. case 3: /* 11b */
  267. break;
  268. default:
  269. break;
  270. }
  271. /* Next Header */
  272. if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
  273. /* Next header is carried inline */
  274. if (lowpan_fetch_skb(skb, &hdr.nexthdr, sizeof(hdr.nexthdr)))
  275. return -EINVAL;
  276. pr_debug("NH flag is set, next header carried inline: %02x\n",
  277. hdr.nexthdr);
  278. }
  279. /* Hop Limit */
  280. if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I) {
  281. hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03];
  282. } else {
  283. if (lowpan_fetch_skb(skb, &hdr.hop_limit,
  284. sizeof(hdr.hop_limit)))
  285. return -EINVAL;
  286. }
  287. /* Extract SAM to the tmp variable */
  288. tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03;
  289. if (iphc1 & LOWPAN_IPHC_SAC) {
  290. /* Source address context based uncompression */
  291. pr_debug("SAC bit is set. Handle context based source address.\n");
  292. err = uncompress_context_based_src_addr(skb, &hdr.saddr, tmp);
  293. } else {
  294. /* Source address uncompression */
  295. pr_debug("source address stateless compression\n");
  296. err = uncompress_addr(skb, &hdr.saddr, tmp, saddr,
  297. saddr_type, saddr_len);
  298. }
  299. /* Check on error of previous branch */
  300. if (err)
  301. return -EINVAL;
  302. /* Extract DAM to the tmp variable */
  303. tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03;
  304. /* check for Multicast Compression */
  305. if (iphc1 & LOWPAN_IPHC_M) {
  306. if (iphc1 & LOWPAN_IPHC_DAC) {
  307. pr_debug("dest: context-based mcast compression\n");
  308. /* TODO: implement this */
  309. } else {
  310. err = lowpan_uncompress_multicast_daddr(skb, &hdr.daddr,
  311. tmp);
  312. if (err)
  313. return -EINVAL;
  314. }
  315. } else {
  316. err = uncompress_addr(skb, &hdr.daddr, tmp, daddr,
  317. daddr_type, daddr_len);
  318. pr_debug("dest: stateless compression mode %d dest %pI6c\n",
  319. tmp, &hdr.daddr);
  320. if (err)
  321. return -EINVAL;
  322. }
  323. /* Next header data uncompression */
  324. if (iphc0 & LOWPAN_IPHC_NH_C) {
  325. err = lowpan_nhc_do_uncompression(skb, dev, &hdr);
  326. if (err < 0)
  327. return err;
  328. } else {
  329. err = skb_cow(skb, sizeof(hdr));
  330. if (unlikely(err))
  331. return err;
  332. }
  333. hdr.payload_len = htons(skb->len);
  334. pr_debug("skb headroom size = %d, data length = %d\n",
  335. skb_headroom(skb), skb->len);
  336. pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n\t"
  337. "nexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n",
  338. hdr.version, ntohs(hdr.payload_len), hdr.nexthdr,
  339. hdr.hop_limit, &hdr.daddr);
  340. skb_push(skb, sizeof(hdr));
  341. skb_reset_network_header(skb);
  342. skb_copy_to_linear_data(skb, &hdr, sizeof(hdr));
  343. raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr));
  344. return 0;
  345. }
  346. EXPORT_SYMBOL_GPL(lowpan_header_decompress);
  347. static u8 lowpan_compress_addr_64(u8 **hc_ptr, u8 shift,
  348. const struct in6_addr *ipaddr,
  349. const unsigned char *lladdr)
  350. {
  351. u8 val = 0;
  352. if (is_addr_mac_addr_based(ipaddr, lladdr)) {
  353. val = 3; /* 0-bits */
  354. pr_debug("address compression 0 bits\n");
  355. } else if (lowpan_is_iid_16_bit_compressable(ipaddr)) {
  356. /* compress IID to 16 bits xxxx::XXXX */
  357. lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[7], 2);
  358. val = 2; /* 16-bits */
  359. raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)",
  360. *hc_ptr - 2, 2);
  361. } else {
  362. /* do not compress IID => xxxx::IID */
  363. lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[4], 8);
  364. val = 1; /* 64-bits */
  365. raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)",
  366. *hc_ptr - 8, 8);
  367. }
  368. return rol8(val, shift);
  369. }
  370. int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
  371. unsigned short type, const void *_daddr,
  372. const void *_saddr, unsigned int len)
  373. {
  374. u8 tmp, iphc0, iphc1, *hc_ptr;
  375. struct ipv6hdr *hdr;
  376. u8 head[100] = {};
  377. int ret, addr_type;
  378. if (type != ETH_P_IPV6)
  379. return -EINVAL;
  380. hdr = ipv6_hdr(skb);
  381. hc_ptr = head + 2;
  382. pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n"
  383. "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n",
  384. hdr->version, ntohs(hdr->payload_len), hdr->nexthdr,
  385. hdr->hop_limit, &hdr->daddr);
  386. raw_dump_table(__func__, "raw skb network header dump",
  387. skb_network_header(skb), sizeof(struct ipv6hdr));
  388. /* As we copy some bit-length fields, in the IPHC encoding bytes,
  389. * we sometimes use |=
  390. * If the field is 0, and the current bit value in memory is 1,
  391. * this does not work. We therefore reset the IPHC encoding here
  392. */
  393. iphc0 = LOWPAN_DISPATCH_IPHC;
  394. iphc1 = 0;
  395. /* TODO: context lookup */
  396. raw_dump_inline(__func__, "saddr",
  397. (unsigned char *)_saddr, IEEE802154_ADDR_LEN);
  398. raw_dump_inline(__func__, "daddr",
  399. (unsigned char *)_daddr, IEEE802154_ADDR_LEN);
  400. raw_dump_table(__func__, "sending raw skb network uncompressed packet",
  401. skb->data, skb->len);
  402. /* Traffic class, flow label
  403. * If flow label is 0, compress it. If traffic class is 0, compress it
  404. * We have to process both in the same time as the offset of traffic
  405. * class depends on the presence of version and flow label
  406. */
  407. /* hc format of TC is ECN | DSCP , original one is DSCP | ECN */
  408. tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4);
  409. tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
  410. if (((hdr->flow_lbl[0] & 0x0F) == 0) &&
  411. (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) {
  412. /* flow label can be compressed */
  413. iphc0 |= LOWPAN_IPHC_FL_C;
  414. if ((hdr->priority == 0) &&
  415. ((hdr->flow_lbl[0] & 0xF0) == 0)) {
  416. /* compress (elide) all */
  417. iphc0 |= LOWPAN_IPHC_TC_C;
  418. } else {
  419. /* compress only the flow label */
  420. *hc_ptr = tmp;
  421. hc_ptr += 1;
  422. }
  423. } else {
  424. /* Flow label cannot be compressed */
  425. if ((hdr->priority == 0) &&
  426. ((hdr->flow_lbl[0] & 0xF0) == 0)) {
  427. /* compress only traffic class */
  428. iphc0 |= LOWPAN_IPHC_TC_C;
  429. *hc_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F);
  430. memcpy(hc_ptr + 1, &hdr->flow_lbl[1], 2);
  431. hc_ptr += 3;
  432. } else {
  433. /* compress nothing */
  434. memcpy(hc_ptr, hdr, 4);
  435. /* replace the top byte with new ECN | DSCP format */
  436. *hc_ptr = tmp;
  437. hc_ptr += 4;
  438. }
  439. }
  440. /* NOTE: payload length is always compressed */
  441. /* Check if we provide the nhc format for nexthdr and compression
  442. * functionality. If not nexthdr is handled inline and not compressed.
  443. */
  444. ret = lowpan_nhc_check_compression(skb, hdr, &hc_ptr, &iphc0);
  445. if (ret < 0)
  446. return ret;
  447. /* Hop limit
  448. * if 1: compress, encoding is 01
  449. * if 64: compress, encoding is 10
  450. * if 255: compress, encoding is 11
  451. * else do not compress
  452. */
  453. switch (hdr->hop_limit) {
  454. case 1:
  455. iphc0 |= LOWPAN_IPHC_TTL_1;
  456. break;
  457. case 64:
  458. iphc0 |= LOWPAN_IPHC_TTL_64;
  459. break;
  460. case 255:
  461. iphc0 |= LOWPAN_IPHC_TTL_255;
  462. break;
  463. default:
  464. lowpan_push_hc_data(&hc_ptr, &hdr->hop_limit,
  465. sizeof(hdr->hop_limit));
  466. }
  467. addr_type = ipv6_addr_type(&hdr->saddr);
  468. /* source address compression */
  469. if (addr_type == IPV6_ADDR_ANY) {
  470. pr_debug("source address is unspecified, setting SAC\n");
  471. iphc1 |= LOWPAN_IPHC_SAC;
  472. } else {
  473. if (addr_type & IPV6_ADDR_LINKLOCAL) {
  474. iphc1 |= lowpan_compress_addr_64(&hc_ptr,
  475. LOWPAN_IPHC_SAM_BIT,
  476. &hdr->saddr, _saddr);
  477. pr_debug("source address unicast link-local %pI6c iphc1 0x%02x\n",
  478. &hdr->saddr, iphc1);
  479. } else {
  480. pr_debug("send the full source address\n");
  481. lowpan_push_hc_data(&hc_ptr, hdr->saddr.s6_addr, 16);
  482. }
  483. }
  484. addr_type = ipv6_addr_type(&hdr->daddr);
  485. /* destination address compression */
  486. if (addr_type & IPV6_ADDR_MULTICAST) {
  487. pr_debug("destination address is multicast: ");
  488. iphc1 |= LOWPAN_IPHC_M;
  489. if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) {
  490. pr_debug("compressed to 1 octet\n");
  491. iphc1 |= LOWPAN_IPHC_DAM_11;
  492. /* use last byte */
  493. lowpan_push_hc_data(&hc_ptr,
  494. &hdr->daddr.s6_addr[15], 1);
  495. } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) {
  496. pr_debug("compressed to 4 octets\n");
  497. iphc1 |= LOWPAN_IPHC_DAM_10;
  498. /* second byte + the last three */
  499. lowpan_push_hc_data(&hc_ptr,
  500. &hdr->daddr.s6_addr[1], 1);
  501. lowpan_push_hc_data(&hc_ptr,
  502. &hdr->daddr.s6_addr[13], 3);
  503. } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) {
  504. pr_debug("compressed to 6 octets\n");
  505. iphc1 |= LOWPAN_IPHC_DAM_01;
  506. /* second byte + the last five */
  507. lowpan_push_hc_data(&hc_ptr,
  508. &hdr->daddr.s6_addr[1], 1);
  509. lowpan_push_hc_data(&hc_ptr,
  510. &hdr->daddr.s6_addr[11], 5);
  511. } else {
  512. pr_debug("using full address\n");
  513. iphc1 |= LOWPAN_IPHC_DAM_00;
  514. lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16);
  515. }
  516. } else {
  517. if (addr_type & IPV6_ADDR_LINKLOCAL) {
  518. /* TODO: context lookup */
  519. iphc1 |= lowpan_compress_addr_64(&hc_ptr,
  520. LOWPAN_IPHC_DAM_BIT, &hdr->daddr, _daddr);
  521. pr_debug("dest address unicast link-local %pI6c "
  522. "iphc1 0x%02x\n", &hdr->daddr, iphc1);
  523. } else {
  524. pr_debug("dest address unicast %pI6c\n", &hdr->daddr);
  525. lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16);
  526. }
  527. }
  528. /* next header compression */
  529. if (iphc0 & LOWPAN_IPHC_NH_C) {
  530. ret = lowpan_nhc_do_compression(skb, hdr, &hc_ptr);
  531. if (ret < 0)
  532. return ret;
  533. }
  534. head[0] = iphc0;
  535. head[1] = iphc1;
  536. skb_pull(skb, sizeof(struct ipv6hdr));
  537. skb_reset_transport_header(skb);
  538. memcpy(skb_push(skb, hc_ptr - head), head, hc_ptr - head);
  539. skb_reset_network_header(skb);
  540. pr_debug("header len %d skb %u\n", (int)(hc_ptr - head), skb->len);
  541. raw_dump_table(__func__, "raw skb data dump compressed",
  542. skb->data, skb->len);
  543. return 0;
  544. }
  545. EXPORT_SYMBOL_GPL(lowpan_header_compress);
  546. static int __init lowpan_module_init(void)
  547. {
  548. request_module_nowait("nhc_dest");
  549. request_module_nowait("nhc_fragment");
  550. request_module_nowait("nhc_hop");
  551. request_module_nowait("nhc_ipv6");
  552. request_module_nowait("nhc_mobility");
  553. request_module_nowait("nhc_routing");
  554. request_module_nowait("nhc_udp");
  555. return 0;
  556. }
  557. module_init(lowpan_module_init);
  558. MODULE_LICENSE("GPL");