2 * Copyright (c) 2017 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 2008, Swedish Institute of Computer Science.
30 * All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. Neither the name of the Institute nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
44 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * This file is part of the Contiki operating system.
62 * Header file for the 6lowpan implementation
63 * (RFC4944 and draft-hui-6lowpan-hc-01)
64 * \author Adam Dunkels <adam@sics.se>
65 * \author Nicolas Tsiftes <nvt@sics.se>
66 * \author Niclas Finne <nfi@sics.se>
67 * \author Mathilde Durvy <mdurvy@cisco.com>
68 * \author Julien Abeille <jabeille@cisco.com>
72 #include <sys/types.h>
73 #include <sys/queue.h>
74 #include <sys/domain.h>
75 #include <net/ethernet.h>
76 #include <netinet/ip.h>
77 #include <netinet/ip6.h>
78 #include <netinet/tcp.h>
79 #include <netinet/udp.h>
80 #include <netinet/icmp6.h>
81 #include <sys/errno.h>
82 #include <libkern/libkern.h>
85 #include <net/sixxlowpan.h>
86 #include <net/frame802154.h>
89 compress_hdr_hc1(struct frame802154
*, u_int8_t
*,
90 long *, size_t *, u_int8_t
*);
92 uncompress_hdr_hc1(struct frame802154
*, u_int8_t
*,
93 uint16_t, long *, size_t *, u_int8_t
*);
98 * \addtogroup sicslowpan
103 * \name General sicslowpan defines
106 /* Min and Max compressible UDP ports - HC06 */
107 #define SICSLOWPAN_UDP_PORT_MIN 0xF0B0
108 #define SICSLOWPAN_UDP_PORT_MAX 0xF0BF /* F0B0 + 15 */
113 * \name 6lowpan compressions
116 #define SICSLOWPAN_COMPRESSION_IPV6 0
117 #define SICSLOWPAN_COMPRESSION_HC1 1
118 #define SICSLOWPAN_COMPRESSION_HC06 2
122 * \name 6lowpan dispatches
125 #define SICSLOWPAN_DISPATCH_IPV6 0x41 /* 01000001 = 65 */
126 #define SICSLOWPAN_DISPATCH_HC1 0x42 /* 01000010 = 66 */
127 #define SICSLOWPAN_DISPATCH_IPHC 0x60 /* 011xxxxx = ... */
128 #define SICSLOWPAN_DISPATCH_FRAG1 0xc0 /* 11000xxx */
129 #define SICSLOWPAN_DISPATCH_FRAGN 0xe0 /* 11100xxx */
132 /** \name HC1 encoding
135 #define SICSLOWPAN_HC1_NH_UDP 0x02
136 #define SICSLOWPAN_HC1_NH_TCP 0x06
137 #define SICSLOWPAN_HC1_NH_ICMP6 0x04
140 /** \name HC_UDP encoding (works together with HC1)
143 #define SICSLOWPAN_HC_UDP_ALL_C 0xE0
147 * \name IPHC encoding
151 * Values of fields within the IPHC encoding first byte
152 * (C stands for compressed and I for inline)
154 #define SICSLOWPAN_IPHC_FL_C 0x10
155 #define SICSLOWPAN_IPHC_TC_C 0x08
156 #define SICSLOWPAN_IPHC_NH_C 0x04
157 #define SICSLOWPAN_IPHC_TTL_1 0x01
158 #define SICSLOWPAN_IPHC_TTL_64 0x02
159 #define SICSLOWPAN_IPHC_TTL_255 0x03
160 #define SICSLOWPAN_IPHC_TTL_I 0x00
163 /* Values of fields within the IPHC encoding second byte */
164 #define SICSLOWPAN_IPHC_CID 0x80
166 #define SICSLOWPAN_IPHC_SAC 0x40
167 #define SICSLOWPAN_IPHC_SAM_00 0x00
168 #define SICSLOWPAN_IPHC_SAM_01 0x10
169 #define SICSLOWPAN_IPHC_SAM_10 0x20
170 #define SICSLOWPAN_IPHC_SAM_11 0x30
172 #define SICSLOWPAN_IPHC_SAM_BIT 4
174 #define SICSLOWPAN_IPHC_M 0x08
175 #define SICSLOWPAN_IPHC_DAC 0x04
176 #define SICSLOWPAN_IPHC_DAM_00 0x00
177 #define SICSLOWPAN_IPHC_DAM_01 0x01
178 #define SICSLOWPAN_IPHC_DAM_10 0x02
179 #define SICSLOWPAN_IPHC_DAM_11 0x03
181 #define SICSLOWPAN_IPHC_DAM_BIT 0
183 /* Link local context number */
184 #define SICSLOWPAN_IPHC_ADDR_CONTEXT_LL 0
185 /* 16-bit multicast addresses compression */
186 #define SICSLOWPAN_IPHC_MCAST_RANGE 0xA0
190 #define SICSLOWPAN_NHC_MASK 0xF0
191 #define SICSLOWPAN_NHC_EXT_HDR 0xE0
194 * \name LOWPAN_UDP encoding (works together with IPHC)
198 * \name LOWPAN_UDP encoding (works together with IPHC)
201 #define SICSLOWPAN_NHC_UDP_MASK 0xF8
202 #define SICSLOWPAN_NHC_UDP_ID 0xF0
203 #define SICSLOWPAN_NHC_UDP_CHECKSUMC 0x04
204 #define SICSLOWPAN_NHC_UDP_CHECKSUMI 0x00
205 /* values for port compression, _with checksum_ ie bit 5 set to 0 */
206 #define SICSLOWPAN_NHC_UDP_CS_P_00 0xF0 /* all inline */
207 #define SICSLOWPAN_NHC_UDP_CS_P_01 0xF1 /* source 16bit inline, dest = 0xF0 + 8 bit inline */
208 #define SICSLOWPAN_NHC_UDP_CS_P_10 0xF2 /* source = 0xF0 + 8bit inline, dest = 16 bit inline */
209 #define SICSLOWPAN_NHC_UDP_CS_P_11 0xF3 /* source & dest = 0xF0B + 4bit inline */
214 * \name The 6lowpan "headers" length
218 #define SICSLOWPAN_IPV6_HDR_LEN 1 /*one byte*/
219 #define SICSLOWPAN_HC1_HDR_LEN 3
220 #define SICSLOWPAN_HC1_HC_UDP_HDR_LEN 7
221 #define SICSLOWPAN_FRAG1_HDR_LEN 4
222 #define SICSLOWPAN_FRAGN_HDR_LEN 5
224 // Minimum size of the compressed 6LoWPAN header length
225 #define SICSLOWPAN_MIN_COMP_HDR_LEN 7
227 // Minimum size of the uncompressed IPv6 header length
228 #define SICSLOWPAN_MIN_UNCOMP_HDR_LEN 40
231 #define UIP_IPH_LEN 40
232 #define UIP_UDPH_LEN 8 /* Size of UDP header */
233 #define UIP_TCPH_LEN 20 /* Size of TCP header */
234 #define UIP_ICMPH_LEN 4 /* Size of ICMP header */
239 * \brief The header for fragments
240 * \note We do not define different structures for FRAG1
241 * and FRAGN headers, which are different. For FRAG1, the
242 * offset field is just not used
244 /* struct sicslowpan_frag_hdr { */
245 /* uint16_t dispatch_size; */
247 /* uint8_t offset; */
251 * \brief The HC1 header when HC_UDP is not used
253 * When all fields are compressed and HC_UDP is not used,
254 * we use this structure. If HC_UDP is used, the ttl is
255 * in another spot, and we use the sicslowpan_hc1_hc_udp
258 /* struct sicslowpan_hc1_hdr { */
259 /* uint8_t dispatch; */
260 /* uint8_t encoding; */
265 * \brief HC1 followed by HC_UDP
267 /* struct sicslowpan_hc1_hc_udp_hdr { */
268 /* uint8_t dispatch; */
269 /* uint8_t hc1_encoding; */
270 /* uint8_t hc_udp_encoding; */
273 /* uint16_t udpchksum; */
277 * \brief An address context for IPHC address compression
278 * each context can have upto 8 bytes
280 struct sicslowpan_addr_context
{
281 uint8_t used
; /* possibly use as prefix-length */
287 * \name Address compressibility test functions
292 * \brief check whether we can compress the IID in
293 * address 'a' to 16 bits.
294 * This is used for unicast addresses only, and is true
295 * if the address is on the format \<PREFIX\>::0000:00ff:fe00:XXXX
296 * NOTE: we currently assume 64-bits prefixes
298 #define sicslowpan_is_iid_16_bit_compressable(a) \
299 ((((a)->u16[4]) == 0) && \
300 (((a)->u8[10]) == 0)&& \
301 (((a)->u8[11]) == 0xff)&& \
302 (((a)->u8[12]) == 0xfe)&& \
303 (((a)->u8[13]) == 0))
306 * \brief check whether the 9-bit group-id of the
307 * compressed multicast address is known. It is true
308 * if the 9-bit group is the all nodes or all routers
310 * \param a is typed uint8_t *
312 #define sicslowpan_is_mcast_addr_decompressable(a) \
313 (((*a & 0x01) == 0) && \
314 ((*(a + 1) == 0x01) || (*(a + 1) == 0x02)))
317 * \brief check whether the 112-bit group-id of the
318 * multicast address is mappable to a 9-bit group-id
319 * It is true if the group is the all nodes or all
322 #define sicslowpan_is_mcast_addr_compressable(a) \
323 ((((a)->u16[1]) == 0) && \
324 (((a)->u16[2]) == 0) && \
325 (((a)->u16[3]) == 0) && \
326 (((a)->u16[4]) == 0) && \
327 (((a)->u16[5]) == 0) && \
328 (((a)->u16[6]) == 0) && \
329 (((a)->u8[14]) == 0) && \
330 ((((a)->u8[15]) == 1) || (((a)->u8[15]) == 2)))
332 /* FFXX::00XX:XXXX:XXXX */
333 #define sicslowpan_is_mcast_addr_compressable48(a) \
334 ((((a)->u16[1]) == 0) && \
335 (((a)->u16[2]) == 0) && \
336 (((a)->u16[3]) == 0) && \
337 (((a)->u16[4]) == 0) && \
338 (((a)->u8[10]) == 0))
340 /* FFXX::00XX:XXXX */
341 #define sicslowpan_is_mcast_addr_compressable32(a) \
342 ((((a)->u16[1]) == 0) && \
343 (((a)->u16[2]) == 0) && \
344 (((a)->u16[3]) == 0) && \
345 (((a)->u16[4]) == 0) && \
346 (((a)->u16[5]) == 0) && \
347 (((a)->u8[12]) == 0))
350 #define sicslowpan_is_mcast_addr_compressable8(a) \
351 ((((a)->u8[1]) == 2) && \
352 (((a)->u16[1]) == 0) && \
353 (((a)->u16[2]) == 0) && \
354 (((a)->u16[3]) == 0) && \
355 (((a)->u16[4]) == 0) && \
356 (((a)->u16[5]) == 0) && \
357 (((a)->u16[6]) == 0) && \
358 (((a)->u8[14]) == 0))
360 #define uip_is_addr_mac_addr_based(a, m) \
361 ((((a)->s6_addr[8]) == (((m)[0]) ^ 0x02)) && \
362 (((a)->s6_addr[9]) == (m)[1]) && \
363 (((a)->s6_addr[10]) == (m)[2]) && \
364 (((a)->s6_addr[11]) == (m)[3]) && \
365 (((a)->s6_addr[12]) == (m)[4]) && \
366 (((a)->s6_addr[13]) == (m)[5]) && \
367 (((a)->s6_addr[14]) == (m)[6]) && \
368 (((a)->s6_addr[15]) == (m)[7]))
371 * Construct an IPv6 address from eight 16-bit words.
373 * This function constructs an IPv6 address.
377 #define uip_ip6addr(addr, addr0, addr1, addr2, addr3, addr4, addr5, addr6, addr7) do {\
378 (addr)->s6_addr[0] = htons(addr0); \
379 (addr)->s6_addr[1] = htons(addr1); \
380 (addr)->s6_addr[2] = htons(addr2); \
381 (addr)->s6_addr[3] = htons(addr3); \
382 (addr)->s6_addr[4] = htons(addr4); \
383 (addr)->s6_addr[5] = htons(addr5); \
384 (addr)->s6_addr[6] = htons(addr6); \
385 (addr)->s6_addr[7] = htons(addr7); \
389 * Construct an IPv6 address from sixteen 8-bit words.
391 * This function constructs an IPv6 address.
395 #define uip_ip6addr_u8(addr, addr0, addr1, addr2, addr3, addr4, addr5, addr6, addr7, addr8, addr9, addr10, addr11, addr12, addr13, addr14, addr15) do {\
396 (addr)->s6_addr[0] = addr0; \
397 (addr)->s6_addr[1] = addr1; \
398 (addr)->s6_addr[2] = addr2; \
399 (addr)->s6_addr[3] = addr3; \
400 (addr)->s6_addr[4] = addr4; \
401 (addr)->s6_addr[5] = addr5; \
402 (addr)->s6_addr[6] = addr6; \
403 (addr)->s6_addr[7] = addr7; \
404 (addr)->s6_addr[8] = addr8; \
405 (addr)->s6_addr[9] = addr9; \
406 (addr)->s6_addr[10] = addr10; \
407 (addr)->s6_addr[11] = addr11; \
408 (addr)->s6_addr[12] = addr12; \
409 (addr)->s6_addr[13] = addr13; \
410 (addr)->s6_addr[14] = addr14; \
411 (addr)->s6_addr[15] = addr15; \
416 /** \brief 16 bit 802.15.4 address */
417 typedef struct uip_802154_shortaddr
{
419 } uip_802154_shortaddr
;
420 /** \brief 64 bit 802.15.4 address */
421 typedef struct uip_802154_longaddr
{
423 } uip_802154_longaddr
;
425 /** \brief 802.11 address */
426 typedef struct uip_80211_addr
{
430 /** \brief 802.3 address */
431 typedef struct uip_eth_addr
{
434 typedef uip_802154_longaddr uip_lladdr_t
;
436 #define UIP_802154_SHORTADDR_LEN 2
437 #define UIP_802154_LONGADDR_LEN 8
438 #define UIP_LLADDR_LEN UIP_802154_LONGADDR_LEN
441 #define GET16(ptr) (((uint16_t)(((u_int8_t *)ptr)[0] << 8)) | (((u_int8_t *)ptr)[1]))
442 #define SET16(ptr, value) do { \
443 ((u_int8_t *)ptr)[0] = ((value) >> 8) & 0xff; \
444 ((u_int8_t *)ptr)[1] = (value) & 0xff; \
447 /** \name Pointers in the packetbuf buffer
450 #define PACKETBUF_FRAG_DISPATCH_SIZE 0 /* 16 bit */
451 #define PACKETBUF_FRAG_TAG 2 /* 16 bit */
452 #define PACKETBUF_FRAG_OFFSET 4 /* 8 bit */
454 #define PACKETBUF_HC1_DISPATCH 0 /* 8 bit */
455 #define PACKETBUF_HC1_ENCODING 1 /* 8 bit */
456 #define PACKETBUF_HC1_TTL 2 /* 8 bit */
458 #define PACKETBUF_HC1_HC_UDP_DISPATCH 0 /* 8 bit */
459 #define PACKETBUF_HC1_HC_UDP_HC1_ENCODING 1 /* 8 bit */
460 #define PACKETBUF_HC1_HC_UDP_UDP_ENCODING 2 /* 8 bit */
461 #define PACKETBUF_HC1_HC_UDP_TTL 3 /* 8 bit */
462 #define PACKETBUF_HC1_HC_UDP_PORTS 4 /* 8 bit */
463 #define PACKETBUF_HC1_HC_UDP_CHKSUM 5 /* 16 bit */
466 #define LINKADDR_SIZE 8
468 unsigned char u8
[LINKADDR_SIZE
];
473 uip_ds6_set_addr_iid(struct in6_addr
*ipaddr
, uip_lladdr_t
*lladdr
)
475 /* We consider only links with IEEE EUI-64 identifier or
476 * IEEE 48-bit MAC addresses */
477 #if (UIP_LLADDR_LEN == 8)
478 memcpy(ipaddr
->s6_addr
+ 8, lladdr
, UIP_LLADDR_LEN
);
479 ipaddr
->s6_addr
[8] ^= 0x02;
480 #elif (UIP_LLADDR_LEN == 6)
481 memcpy(ipaddr
->s6_addr
+ 8, lladdr
, 3);
482 ipaddr
->s6_addr
[11] = 0xff;
483 ipaddr
->s6_addr
[12] = 0xfe;
484 memcpy(ipaddr
->s6_addr
+ 13, (uint8_t *)lladdr
+ 3, 3);
485 ipaddr
->s6_addr
[8] ^= 0x02;
487 #error uip-ds6.c cannot build interface address when UIP_LLADDR_LEN is not 6 or 8
492 compress_hdr_ipv6(__unused
struct frame802154
*ieee02154hdr
,
493 __unused u_int8_t
*payload
,
494 long *hdroffset
, size_t *hdrlen
, u_int8_t
*hdrbuf
)
497 * Negative offset: 6LoWPAN header needs to ve prepended to the data
499 *hdroffset
= -SICSLOWPAN_IPV6_HDR_LEN
;
500 *hdrlen
= SICSLOWPAN_IPV6_HDR_LEN
;
501 hdrbuf
[0] = SICSLOWPAN_DISPATCH_IPV6
;
508 /*--------------------------------------------------------------------*/
509 /** \name HC1 compression and uncompression functions
511 /*--------------------------------------------------------------------*/
513 * \brief Compress IP/UDP header using HC1 and HC_UDP
515 * This function is called by the 6lowpan code to create a compressed
516 * 6lowpan packet in the packetbuf buffer from a full IPv6 packet in the
520 * If we can compress everything, we use HC1 dispatch, if not we use
522 * We can compress everything if:
524 * - Flow label and traffic class are 0
525 * - Both src and dest ip addresses are link local
526 * - Both src and dest interface ID are recoverable from lower layer
528 * - Next header is either ICMP, UDP or TCP
529 * Moreover, if next header is UDP, we try to compress it using HC_UDP.
530 * This is feasible is both ports are between F0B0 and F0B0 + 15\n\n
532 * Resulting header structure:
533 * - For ICMP, TCP, non compressed UDP\n
534 * HC1 encoding = 11111010 (UDP) 11111110 (TCP) 11111100 (ICMP)\n
537 * 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
538 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
539 * | LoWPAN HC1 Dsp | HC1 encoding | IPv6 Hop limit| L4 hdr + data|
540 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
542 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
545 * - For compressed UDP
546 * HC1 encoding = 11111011, HC_UDP encoding = 11100000\n
549 * 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
550 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
551 * | LoWPAN HC1 Dsp| HC1 encoding | HC_UDP encod.| IPv6 Hop limit|
552 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
553 * | src p.| dst p.| UDP checksum | L4 data...
554 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
557 * \param link_destaddr L2 destination address, needed to compress the
558 * IP destination field
562 compress_hdr_hc1(struct frame802154
*ieee02154hdr
, u_int8_t
*payload
,
563 long *hdroffset
, size_t *hdrlen
, u_int8_t
*hdrbuf
)
565 struct ip6_hdr
*ip6
= (struct ip6_hdr
*)(payload
);
567 if (*hdrlen
< SICSLOWPAN_MIN_COMP_HDR_LEN
) {
574 * Check if all the assumptions for full compression
577 if ((ip6
->ip6_vfc
& IPV6_VERSION_MASK
) != IPV6_VERSION
||
578 !IN6_IS_ADDR_LINKLOCAL(&ip6
->ip6_src
) ||
579 !uip_is_addr_mac_addr_based(&ip6
->ip6_src
, ieee02154hdr
->src_addr
) ||
580 !IN6_IS_ADDR_LINKLOCAL(&ip6
->ip6_dst
) ||
581 !uip_is_addr_mac_addr_based(&ip6
->ip6_dst
,
582 ieee02154hdr
->dest_addr
) ||
583 (ip6
->ip6_nxt
!= IPPROTO_ICMPV6
&&
584 ip6
->ip6_nxt
!= IPPROTO_UDP
&&
585 ip6
->ip6_nxt
!= IPPROTO_TCP
)) {
588 * Something cannot be compressed, use IPV6 DISPATCH,
589 * compress nothing, copy IPv6 header in packetbuf buffer
591 return compress_hdr_ipv6(ieee02154hdr
, payload
, hdroffset
, hdrlen
, hdrbuf
);
595 * maximum compresssion:
596 * All fields in the IP header but Hop Limit are elided
597 * If next header is UDP, we compress UDP header using HC2
599 hdrbuf
[PACKETBUF_HC1_DISPATCH
] = SICSLOWPAN_DISPATCH_HC1
;
601 switch (ip6
->ip6_nxt
) {
603 /* HC1 encoding and ttl */
604 hdrbuf
[PACKETBUF_HC1_ENCODING
] = 0xFC;
605 hdrbuf
[PACKETBUF_HC1_TTL
] = ip6
->ip6_hlim
;
606 *hdrlen
= SICSLOWPAN_HC1_HDR_LEN
;
607 *hdroffset
= sizeof(struct ip6_hdr
);
611 /* HC1 encoding and ttl */
612 hdrbuf
[PACKETBUF_HC1_ENCODING
] = 0xFE;
613 hdrbuf
[PACKETBUF_HC1_TTL
] = ip6
->ip6_hlim
;
614 *hdrlen
= SICSLOWPAN_HC1_HDR_LEN
;
615 *hdroffset
= sizeof(struct ip6_hdr
);
619 struct udphdr
*udp
= (struct udphdr
*)(uintptr_t)(ip6
+ 1);
622 * try to compress UDP header (we do only full compression).
623 * This is feasible if both src and dest ports are between
624 * SICSLOWPAN_UDP_PORT_MIN and SICSLOWPAN_UDP_PORT_MIN + 15
626 printf("source/remote ports %u/%u\n", ntohs(udp
->uh_sport
), ntohs(udp
->uh_dport
));
627 if (ntohs(udp
->uh_sport
) >= SICSLOWPAN_UDP_PORT_MIN
&&
628 ntohs(udp
->uh_sport
) < SICSLOWPAN_UDP_PORT_MAX
&&
629 ntohs(udp
->uh_dport
) >= SICSLOWPAN_UDP_PORT_MIN
&&
630 ntohs(udp
->uh_dport
) < SICSLOWPAN_UDP_PORT_MAX
) {
632 hdrbuf
[PACKETBUF_HC1_HC_UDP_HC1_ENCODING
] = 0xFB;
634 /* HC_UDP encoding, ttl, src and dest ports, checksum */
635 hdrbuf
[PACKETBUF_HC1_HC_UDP_UDP_ENCODING
] = 0xE0;
636 hdrbuf
[PACKETBUF_HC1_HC_UDP_TTL
] = ip6
->ip6_hlim
;
638 hdrbuf
[PACKETBUF_HC1_HC_UDP_PORTS
] =
639 (uint8_t)((ntohs(udp
->uh_sport
) - SICSLOWPAN_UDP_PORT_MIN
) << 4) +
640 (uint8_t)((ntohs(udp
->uh_dport
) - SICSLOWPAN_UDP_PORT_MIN
));
642 memcpy(&hdrbuf
[PACKETBUF_HC1_HC_UDP_CHKSUM
], &udp
->uh_sum
, 2);
643 *hdrlen
= SICSLOWPAN_HC1_HC_UDP_HDR_LEN
;
644 *hdroffset
= sizeof(struct ip6_hdr
) + sizeof(struct udphdr
);
646 /* HC1 encoding and ttl */
647 hdrbuf
[PACKETBUF_HC1_ENCODING
] = 0xFA;
648 hdrbuf
[PACKETBUF_HC1_TTL
] = ip6
->ip6_hlim
;
649 *hdrlen
= SICSLOWPAN_HC1_HDR_LEN
;
650 *hdroffset
= sizeof(struct ip6_hdr
);
660 /*--------------------------------------------------------------------*/
662 * \brief Uncompress HC1 (and HC_UDP) headers and put them in
665 * This function is called by the input function when the dispatch is
667 * We %process the packet in the packetbuf buffer, uncompress the header
668 * fields, and copy the result in the sicslowpan buffer.
669 * At the end of the decompression, packetbuf_hdr_len and uncompressed_hdr_len
670 * are set to the appropriate values
672 * \param ip_len Equal to 0 if the packet is not a fragment (IP length
673 * is then inferred from the L2 length), non 0 if the packet is a 1st
677 uncompress_hdr_hc1(struct frame802154
*frame
, u_int8_t
*payload
,
678 uint16_t ip_len
, long *hdroffset
, size_t *hdrlen
, u_int8_t
*hdrbuf
)
680 struct ip6_hdr
*ip6
= (struct ip6_hdr
*)hdrbuf
;
682 if (payload
[PACKETBUF_HC1_DISPATCH
] == SICSLOWPAN_DISPATCH_IPV6
) {
683 *hdroffset
= -SICSLOWPAN_IPV6_HDR_LEN
;
684 *hdrlen
= SICSLOWPAN_IPV6_HDR_LEN
;
690 /* version, traffic class, flow label */
692 ip6
->ip6_vfc
= IPV6_VERSION
;
694 /* src and dest ip addresses */
695 uip_ip6addr_u8(&ip6
->ip6_src
, 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
696 uip_ds6_set_addr_iid(&ip6
->ip6_src
,
697 (uip_lladdr_t
*)frame
->src_addr
);
699 uip_ip6addr_u8(&ip6
->ip6_dst
, 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
700 uip_ds6_set_addr_iid(&ip6
->ip6_dst
,
701 (uip_lladdr_t
*)frame
->dest_addr
);
703 *hdrlen
= UIP_IPH_LEN
;
705 /* Next header field */
706 switch (payload
[PACKETBUF_HC1_ENCODING
] & 0x06) {
707 case SICSLOWPAN_HC1_NH_ICMP6
:
708 ip6
->ip6_nxt
= IPPROTO_ICMPV6
;
709 ip6
->ip6_hlim
= payload
[PACKETBUF_HC1_TTL
];
710 *hdroffset
= SICSLOWPAN_HC1_HDR_LEN
;
713 case SICSLOWPAN_HC1_NH_TCP
:
714 ip6
->ip6_nxt
= IPPROTO_TCP
;
715 ip6
->ip6_hlim
= payload
[PACKETBUF_HC1_TTL
];
716 *hdroffset
= SICSLOWPAN_HC1_HDR_LEN
;
719 case SICSLOWPAN_HC1_NH_UDP
:
720 ip6
->ip6_nxt
= IPPROTO_UDP
;
721 if (payload
[PACKETBUF_HC1_HC_UDP_HC1_ENCODING
] & 0x01) {
722 struct udphdr
*udp
= (struct udphdr
*)(uintptr_t)ip6
;
724 /* UDP header is compressed with HC_UDP */
725 if (payload
[PACKETBUF_HC1_HC_UDP_UDP_ENCODING
] !=
726 SICSLOWPAN_HC_UDP_ALL_C
) {
727 printf("sicslowpan (uncompress_hdr), packet not supported");
732 ip6
->ip6_hlim
= payload
[PACKETBUF_HC1_HC_UDP_TTL
];
733 /* UDP ports, len, checksum */
735 htons(SICSLOWPAN_UDP_PORT_MIN
+ (payload
[PACKETBUF_HC1_HC_UDP_PORTS
] >> 4));
737 htons(SICSLOWPAN_UDP_PORT_MIN
+ (payload
[PACKETBUF_HC1_HC_UDP_PORTS
] & 0x0F));
739 memcpy(&udp
->uh_sum
, &payload
[PACKETBUF_HC1_HC_UDP_CHKSUM
], 2);
740 *hdrlen
+= UIP_UDPH_LEN
;
741 *hdroffset
= SICSLOWPAN_HC1_HC_UDP_HDR_LEN
;
743 ip6
->ip6_hlim
= payload
[PACKETBUF_HC1_TTL
];
744 *hdroffset
= SICSLOWPAN_HC1_HDR_LEN
;
749 /* this shouldn't happen, drop */
753 /* IP length field. */
755 size_t len
= frame
->payload_len
- *hdroffset
+ *hdrlen
- sizeof(struct ip6_hdr
);
757 /* This is not a fragmented packet */
758 SET16(&ip6
->ip6_plen
, len
);
760 /* This is a 1st fragment */
761 SET16(&ip6
->ip6_plen
, ip_len
- UIP_IPH_LEN
);
763 /* length field in UDP header */
764 if (ip6
->ip6_nxt
== IPPROTO_UDP
) {
765 struct udphdr
*udp
= (struct udphdr
*)(uintptr_t)ip6
;
767 memcpy(&udp
->uh_ulen
, &ip6
->ip6_plen
, 2);
773 sixxlowpan_compress(struct frame802154
*ieee02154hdr
, u_int8_t
*payload
)
777 u_int8_t hdrbuf
[128];
780 bzero(hdrbuf
, sizeof(hdrbuf
));
781 hdrlen
= sizeof(hdrbuf
);
783 error
= compress_hdr_hc1(ieee02154hdr
, payload
,
784 &hdroffset
, &hdrlen
, hdrbuf
);
791 * hdroffset negative means that we have to add
792 * hdrlen of extra stuff
794 memmove(&payload
[hdrlen
],
796 ieee02154hdr
->payload_len
);
797 memcpy(&payload
[0], hdrbuf
, hdrlen
);
799 ieee02154hdr
->payload_len
+= hdrlen
;
800 } else if (hdroffset
> 0) {
802 * hdroffset is the size of the compressed header
804 * hdrlen is the size of the data that has been compressed
805 * -- i.e. when the untouched data starts
807 memmove(&payload
[hdrlen
],
809 ieee02154hdr
->payload_len
- hdroffset
);
810 memcpy(&payload
[0], hdrbuf
, hdrlen
);
812 ieee02154hdr
->payload_len
+= hdrlen
- hdroffset
;
819 sixxlowpan_uncompress(struct frame802154
*ieee02154hdr
, u_int8_t
*payload
)
823 u_int8_t hdrbuf
[128];
826 bzero(hdrbuf
, sizeof(hdrbuf
));
827 hdrlen
= sizeof(hdrbuf
);
829 error
= uncompress_hdr_hc1(ieee02154hdr
, (u_int8_t
*)payload
,
830 0, &hdroffset
, &hdrlen
, hdrbuf
);
838 * hdroffset negative means that we have to remove
839 * hdrlen of extra stuff
841 if (ieee02154hdr
->payload_len
< hdrlen
) {
846 ieee02154hdr
->payload_len
- hdrlen
);
847 ieee02154hdr
->payload_len
-= hdrlen
;
850 * hdroffset is the size of the compressed header
851 * -- i.e. when the untouched data starts
853 * hdrlen is the size of the decompressed header
854 * that takes the place of compressed header of size hdroffset
856 if (ieee02154hdr
->payload_len
< hdroffset
) {
859 memmove(payload
+ hdrlen
,
861 ieee02154hdr
->payload_len
- hdroffset
);
862 memcpy(payload
, hdrbuf
, hdrlen
);
863 ieee02154hdr
->payload_len
+= hdrlen
- hdroffset
;
870 sixxlowpan_output(struct frame802154
*ieee02154hdr
, u_int8_t
*payload
)
874 error
= sixxlowpan_compress(ieee02154hdr
, payload
);
880 * TO DO: fragmentation
888 sixxlowpan_input(struct frame802154
*ieee02154hdr
, u_int8_t
*payload
)
892 error
= sixxlowpan_uncompress(ieee02154hdr
, payload
);
898 * TO DO: fragmentation