Contiki-NG
sicslowpan.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35  * 6lowpan implementation (RFC4944 and draft-ietf-6lowpan-hc-06)
36  *
37  * \author Adam Dunkels <adam@sics.se>
38  * \author Nicolas Tsiftes <nvt@sics.se>
39  * \author Niclas Finne <nfi@sics.se>
40  * \author Mathilde Durvy <mdurvy@cisco.com>
41  * \author Julien Abeille <jabeille@cisco.com>
42  * \author Joakim Eriksson <joakime@sics.se>
43  * \author Joel Hoglund <joel@sics.se>
44  */
45 
46 /**
47  * \addtogroup sicslowpan
48  * \ingroup uip
49  * @{
50  */
51 
52 /**
53  * FOR HC-06 COMPLIANCE TODO:
54  * -Add compression options to UDP, currently only supports
55  * both ports compressed or both ports elided
56  *
57  * -Verify TC/FL compression works
58  *
59  * -Add stateless multicast option
60  */
61 
62 #include <string.h>
63 
64 #include "contiki.h"
65 #include "dev/watchdog.h"
66 #include "net/link-stats.h"
67 #include "net/ipv6/uipopt.h"
68 #include "net/ipv6/tcpip.h"
69 #include "net/ipv6/uip.h"
70 #include "net/ipv6/uip-ds6.h"
71 #include "net/ipv6/uipbuf.h"
72 #include "net/ipv6/sicslowpan.h"
73 #include "net/netstack.h"
74 #include "net/packetbuf.h"
75 #include "net/queuebuf.h"
76 
77 #include "net/routing/routing.h"
78 
79 /* Log configuration */
80 #include "sys/log.h"
81 #define LOG_MODULE "6LoWPAN"
82 #define LOG_LEVEL LOG_LEVEL_6LOWPAN
83 
84 #define GET16(ptr,index) (((uint16_t)((ptr)[index] << 8)) | ((ptr)[(index) + 1]))
85 #define SET16(ptr,index,value) do { \
86  (ptr)[index] = ((value) >> 8) & 0xff; \
87  (ptr)[index + 1] = (value) & 0xff; \
88 } while(0)
89 
90 /** \name Pointers in the packetbuf buffer
91  * @{
92  */
93 #define PACKETBUF_FRAG_PTR (packetbuf_ptr)
94 #define PACKETBUF_FRAG_DISPATCH_SIZE 0 /* 16 bit */
95 #define PACKETBUF_FRAG_TAG 2 /* 16 bit */
96 #define PACKETBUF_FRAG_OFFSET 4 /* 8 bit */
97 
98 /* define the buffer as a byte array */
99 #define PACKETBUF_IPHC_BUF ((uint8_t *)(packetbuf_ptr + packetbuf_hdr_len))
100 #define PACKETBUF_PAYLOAD_END ((uint8_t *)(packetbuf_ptr + mac_max_payload))
101 
102 #define PACKETBUF_6LO_PTR (packetbuf_ptr + packetbuf_hdr_len)
103 #define PACKETBUF_6LO_DISPATCH 0 /* 8 bit */
104 #define PACKETBUF_6LO_ENCODING 1 /* 8 bit */
105 #define PACKETBUF_6LO_TTL 2 /* 8 bit */
106 
107 #define PACKETBUF_6LO_HC_UDP_PTR (packetbuf_ptr + packetbuf_hdr_len)
108 #define PACKETBUF_6LO_HC_UDP_DISPATCH 0 /* 8 bit */
109 #define PACKETBUF_6LO_HC_UDP_HC1_ENCODING 1 /* 8 bit */
110 #define PACKETBUF_6LO_HC_UDP_UDP_ENCODING 2 /* 8 bit */
111 #define PACKETBUF_6LO_HC_UDP_TTL 3 /* 8 bit */
112 #define PACKETBUF_6LO_HC_UDP_PORTS 4 /* 8 bit */
113 #define PACKETBUF_6LO_HC_UDP_CHKSUM 5 /* 16 bit */
114 
115 /** \name Pointers in the sicslowpan and uip buffer
116  * @{
117  */
118 
119 /* NOTE: In the multiple-reassembly context there is only room for the header / first fragment */
120 #define SICSLOWPAN_IP_BUF(buf) ((struct uip_ip_hdr *)buf)
121 #define SICSLOWPAN_UDP_BUF(buf) ((struct uip_udp_hdr *)&buf[UIP_IPH_LEN])
122 #define SICSLOWPAN_IPPAYLOAD_BUF(buf) (&buf[UIP_IPH_LEN])
123 
124 #define UIP_IPPAYLOAD_BUF_POS(pos) (&uip_buf[UIP_IPH_LEN + (pos)])
125 #define UIP_UDP_BUF_POS(pos) ((struct uip_udp_hdr *)UIP_IPPAYLOAD_BUF_POS(pos))
126 #define UIP_EXT_HDR_LEN 2
127 
128 /** @} */
129 
130 /* set this to zero if not compressing EXT_HDR - for backwards compatibility */
131 #ifdef SICSLOWPAN_CONF_COMPRESS_EXT_HDR
132 #define COMPRESS_EXT_HDR SICSLOWPAN_CONF_COMPRESS_EXT_HDR
133 #else
134 /* Compressing on by default - turn off to be compatible with older versions */
135 #define COMPRESS_EXT_HDR 1
136 #endif
137 
138 #if COMPRESS_EXT_HDR
139 #define IS_COMPRESSABLE_PROTO(x) (x == UIP_PROTO_UDP \
140  || x == UIP_PROTO_HBHO \
141  || x == UIP_PROTO_DESTO \
142  || x == UIP_PROTO_ROUTING \
143  || x == UIP_PROTO_FRAG)
144 #else
145 #define IS_COMPRESSABLE_PROTO(x) (x == UIP_PROTO_UDP)
146 #endif /* COMPRESS_EXT_HDR */
147 
148 /** \name General variables
149  * @{
150  */
151 
152 /**
153  * A pointer to the packetbuf buffer.
154  * We initialize it to the beginning of the packetbuf buffer, then
155  * access different fields by updating the offset packetbuf_hdr_len.
156  */
157 static uint8_t *packetbuf_ptr;
158 
159 /**
160  * packetbuf_hdr_len is the total length of (the processed) 6lowpan headers
161  * (fragment headers, IPV6 or HC1, HC2, and HC1 and HC2 non compressed
162  * fields).
163  */
164 static uint8_t packetbuf_hdr_len;
165 
166 /**
167  * The length of the payload in the Packetbuf buffer.
168  * The payload is what comes after the compressed or uncompressed
169  * headers (can be the IP payload if the IP header only is compressed
170  * or the UDP payload if the UDP header is also compressed)
171  */
173 
174 /**
175  * uncomp_hdr_len is the length of the headers before compression (if HC2
176  * is used this includes the UDP header in addition to the IP header).
177  */
178 static uint8_t uncomp_hdr_len;
179 
180 /**
181  * mac_max_payload is the maimum payload space on the MAC frame.
182  */
183 static int mac_max_payload;
184 
185 /**
186  * The current page (RFC 4944)
187  */
188 static uint8_t curr_page;
189 
190 /**
191  * the result of the last transmitted fragment
192  */
193 static int last_tx_status;
194 /** @} */
195 
196 static int last_rssi;
197 
198 /* ----------------------------------------------------------------- */
199 /* Support for reassembling multiple packets */
200 /* ----------------------------------------------------------------- */
201 
202 #if SICSLOWPAN_CONF_FRAG
203 static uint16_t my_tag;
204 
205 /** The total length of the IPv6 packet in the sicslowpan_buf. */
206 
207 /* This needs to be defined in NBR / Nodes depending on available RAM */
208 /* and expected reassembly requirements */
209 #ifdef SICSLOWPAN_CONF_FRAGMENT_BUFFERS
210 #define SICSLOWPAN_FRAGMENT_BUFFERS SICSLOWPAN_CONF_FRAGMENT_BUFFERS
211 #else
212 #define SICSLOWPAN_FRAGMENT_BUFFERS 12
213 #endif
214 
215 /* REASS_CONTEXTS corresponds to the number of simultaneous
216  * reassemblies that can be made. NOTE: the first buffer for each
217  * reassembly is stored in the context since it can be larger than the
218  * rest of the fragments due to header compression.
219  **/
220 #ifdef SICSLOWPAN_CONF_REASS_CONTEXTS
221 #define SICSLOWPAN_REASS_CONTEXTS SICSLOWPAN_CONF_REASS_CONTEXTS
222 #else
223 #define SICSLOWPAN_REASS_CONTEXTS 2
224 #endif
225 
226 /* The size of each fragment (IP payload) for the 6lowpan fragmentation */
227 #ifdef SICSLOWPAN_CONF_FRAGMENT_SIZE
228 #define SICSLOWPAN_FRAGMENT_SIZE SICSLOWPAN_CONF_FRAGMENT_SIZE
229 #else
230 /* The default fragment size (110 bytes for 127-2 bytes frames) */
231 #define SICSLOWPAN_FRAGMENT_SIZE (127 - 2 - 15)
232 #endif
233 
234 /* Check the selected fragment size, since we use 8-bit integers to handle it. */
235 #if SICSLOWPAN_FRAGMENT_SIZE > 255
236 #error Too large SICSLOWPAN_FRAGMENT_SIZE set.
237 #endif
238 
239 /* Assuming that the worst growth for uncompression is 38 bytes */
240 #define SICSLOWPAN_FIRST_FRAGMENT_SIZE (SICSLOWPAN_FRAGMENT_SIZE + 38)
241 
242 /* all information needed for reassembly */
243 struct sicslowpan_frag_info {
244  /** When reassembling, the source address of the fragments being merged */
245  linkaddr_t sender;
246  /** The destination address of the fragments being merged */
247  linkaddr_t receiver;
248  /** When reassembling, the tag in the fragments being merged. */
249  uint16_t tag;
250  /** Total length of the fragmented packet */
251  uint16_t len;
252  /** Current length of reassembled fragments */
253  uint16_t reassembled_len;
254  /** Reassembly %process %timer. */
255  struct timer reass_timer;
256 
257  /** Fragment size of first fragment */
258  uint16_t first_frag_len;
259  /** First fragment - needs a larger buffer since the size is uncompressed size
260  and we need to know total size to know when we have received last fragment. */
261  uint8_t first_frag[SICSLOWPAN_FIRST_FRAGMENT_SIZE];
262 };
263 
264 static struct sicslowpan_frag_info frag_info[SICSLOWPAN_REASS_CONTEXTS];
265 
266 struct sicslowpan_frag_buf {
267  /* the index of the frag_info */
268  uint8_t index;
269  /* Fragment offset */
270  uint8_t offset;
271  /* Length of this fragment (if zero this buffer is not allocated) */
272  uint8_t len;
273  uint8_t data[SICSLOWPAN_FRAGMENT_SIZE];
274 };
275 
276 static struct sicslowpan_frag_buf frag_buf[SICSLOWPAN_FRAGMENT_BUFFERS];
277 
278 /*---------------------------------------------------------------------------*/
279 static int
280 clear_fragments(uint8_t frag_info_index)
281 {
282  int i, clear_count;
283  clear_count = 0;
284  frag_info[frag_info_index].len = 0;
285  for(i = 0; i < SICSLOWPAN_FRAGMENT_BUFFERS; i++) {
286  if(frag_buf[i].len > 0 && frag_buf[i].index == frag_info_index) {
287  /* deallocate the buffer */
288  frag_buf[i].len = 0;
289  clear_count++;
290  }
291  }
292  return clear_count;
293 }
294 /*---------------------------------------------------------------------------*/
295 static int
296 timeout_fragments(int not_context)
297 {
298  int i;
299  int count = 0;
300  for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) {
301  if(frag_info[i].len > 0 && i != not_context &&
302  timer_expired(&frag_info[i].reass_timer)) {
303  /* This context can be freed */
304  count += clear_fragments(i);
305  }
306  }
307  return count;
308 }
309 /*---------------------------------------------------------------------------*/
310 static int
311 store_fragment(uint8_t index, uint8_t offset)
312 {
313  int i;
314  int len;
315 
317 
318  if(len <= 0 || len > SICSLOWPAN_FRAGMENT_SIZE) {
319  /* Unacceptable fragment size. */
320  return -1;
321  }
322 
323  for(i = 0; i < SICSLOWPAN_FRAGMENT_BUFFERS; i++) {
324  if(frag_buf[i].len == 0) {
325  /* copy over the data from packetbuf into the fragment buffer,
326  and store offset and len */
327  frag_buf[i].offset = offset; /* frag offset */
328  frag_buf[i].len = len;
329  frag_buf[i].index = index;
330  memcpy(frag_buf[i].data, packetbuf_ptr + packetbuf_hdr_len, len);
331  /* return the length of the stored fragment */
332  return len;
333  }
334  }
335  /* failed */
336  return -1;
337 }
338 /*---------------------------------------------------------------------------*/
339 /* add a new fragment to the buffer */
340 static int8_t
341 add_fragment(uint16_t tag, uint16_t frag_size, uint8_t offset)
342 {
343  int i;
344  int len;
345  int8_t found = -1;
346 
347  if(offset == 0) {
348  /* This is a first fragment - check if we can add this */
349  for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) {
350  /* clear all fragment info with expired timer to free all fragment buffers */
351  if(frag_info[i].len > 0 && timer_expired(&frag_info[i].reass_timer)) {
352  clear_fragments(i);
353  }
354 
355  /* We use len as indication on used or not used */
356  if(found < 0 && frag_info[i].len == 0) {
357  /* We remember the first free fragment info but must continue
358  the loop to free any other expired fragment buffers. */
359  found = i;
360  }
361  }
362 
363  if(found < 0) {
364  LOG_WARN("reassembly: failed to store new fragment session - tag: %d\n", tag);
365  return -1;
366  }
367 
368  /* Found a free fragment info to store data in */
369  frag_info[found].len = frag_size;
370  frag_info[found].tag = tag;
371  linkaddr_copy(&frag_info[found].sender,
372  packetbuf_addr(PACKETBUF_ADDR_SENDER));
373  timer_set(&frag_info[found].reass_timer, SICSLOWPAN_REASS_MAXAGE * CLOCK_SECOND / 16);
374  /* first fragment can not be stored immediately but is moved into
375  the buffer while uncompressing */
376  return found;
377  }
378 
379  /* This is a N-fragment - should find the info */
380  for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) {
381  if(frag_info[i].tag == tag && frag_info[i].len > 0 &&
382  linkaddr_cmp(&frag_info[i].sender, packetbuf_addr(PACKETBUF_ADDR_SENDER))) {
383  /* Tag and Sender match - this must be the correct info to store in */
384  found = i;
385  break;
386  }
387  }
388 
389  if(found < 0) {
390  /* no entry found for storing the new fragment */
391  LOG_WARN("reassembly: failed to store N-fragment - could not find session - tag: %d offset: %d\n", tag, offset);
392  return -1;
393  }
394 
395  /* i is the index of the reassembly context */
396  len = store_fragment(i, offset);
397  if(len < 0 && timeout_fragments(i) > 0) {
398  len = store_fragment(i, offset);
399  }
400  if(len > 0) {
401  frag_info[i].reassembled_len += len;
402  return i;
403  } else {
404  /* should we also clear all fragments since we failed to store
405  this fragment? */
406  LOG_WARN("reassembly: failed to store fragment - packet reassembly will fail tag:%d l\n", frag_info[i].tag);
407  return -1;
408  }
409 }
410 /*---------------------------------------------------------------------------*/
411 /* Copy all the fragments that are associated with a specific context
412  into uip */
413 static bool
414 copy_frags2uip(int context)
415 {
416  int i;
417 
418  /* Check length fields before proceeding. */
419  if(frag_info[context].len < frag_info[context].first_frag_len ||
420  frag_info[context].len > sizeof(uip_buf)) {
421  LOG_WARN("input: invalid total size of fragments\n");
422  clear_fragments(context);
423  return false;
424  }
425 
426  /* Copy from the fragment context info buffer first */
427  memcpy((uint8_t *)UIP_IP_BUF, (uint8_t *)frag_info[context].first_frag,
428  frag_info[context].first_frag_len);
429 
430  /* Ensure that no previous data is used for reassembly in case of missing fragments. */
431  memset((uint8_t *)UIP_IP_BUF + frag_info[context].first_frag_len, 0,
432  frag_info[context].len - frag_info[context].first_frag_len);
433 
434  for(i = 0; i < SICSLOWPAN_FRAGMENT_BUFFERS; i++) {
435  /* And also copy all matching fragments */
436  if(frag_buf[i].len > 0 && frag_buf[i].index == context) {
437  if((frag_buf[i].offset << 3) + frag_buf[i].len > sizeof(uip_buf)) {
438  LOG_WARN("input: invalid fragment offset\n");
439  clear_fragments(context);
440  return false;
441  }
442  memcpy((uint8_t *)UIP_IP_BUF + (uint16_t)(frag_buf[i].offset << 3),
443  (uint8_t *)frag_buf[i].data, frag_buf[i].len);
444  }
445  }
446  /* deallocate all the fragments for this context */
447  clear_fragments(context);
448 
449  return true;
450 }
451 #endif /* SICSLOWPAN_CONF_FRAG */
452 
453 /* -------------------------------------------------------------------------- */
454 
455 /*-------------------------------------------------------------------------*/
456 /* Basic netstack sniffer */
457 /*-------------------------------------------------------------------------*/
458 static struct netstack_sniffer *callback = NULL;
459 
460 void
461 netstack_sniffer_add(struct netstack_sniffer *s)
462 {
463  callback = s;
464 }
465 
466 void
467 netstack_sniffer_remove(struct netstack_sniffer *s)
468 {
469  callback = NULL;
470 }
471 
472 static void
473 set_packet_attrs(void)
474 {
475  int c = 0;
476  /* set protocol in NETWORK_ID */
477  packetbuf_set_attr(PACKETBUF_ATTR_NETWORK_ID, UIP_IP_BUF->proto);
478 
479  /* assign values to the channel attribute (port or type + code) */
480  if(UIP_IP_BUF->proto == UIP_PROTO_UDP) {
481  c = UIP_UDP_BUF_POS(0)->srcport;
482  if(UIP_UDP_BUF_POS(0)->destport < c) {
483  c = UIP_UDP_BUF_POS(0)->destport;
484  }
485  } else if(UIP_IP_BUF->proto == UIP_PROTO_TCP) {
486  c = UIP_TCP_BUF->srcport;
487  if(UIP_TCP_BUF->destport < c) {
488  c = UIP_TCP_BUF->destport;
489  }
490  } else if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6) {
491  c = UIP_ICMP_BUF->type << 8 | UIP_ICMP_BUF->icode;
492  }
493 
494  packetbuf_set_attr(PACKETBUF_ATTR_CHANNEL, c);
495 
496 /* if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) { */
497 /* own = 1; */
498 /* } */
499 
500 }
501 
502 
503 
504 #if SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC
505 /** \name variables specific to HC06 and more recent versions
506  * @{
507  */
508 
509 /** Addresses contexts for IPHC. */
510 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
511 static struct sicslowpan_addr_context
512 addr_contexts[SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS];
513 #endif
514 
515 /** pointer to an address context. */
517 
518 /** pointer to the byte where to write next inline field. */
519 static uint8_t *hc06_ptr;
520 
521 /* Uncompression of linklocal */
522 /* 0 -> 16 bytes from packet */
523 /* 1 -> 2 bytes from prefix - bunch of zeroes and 8 from packet */
524 /* 2 -> 2 bytes from prefix - 0000::00ff:fe00:XXXX from packet */
525 /* 3 -> 2 bytes from prefix - infer 8 bytes from lladdr */
526 /* NOTE: => the uncompress function does change 0xf to 0x10 */
527 /* NOTE: 0x00 => no-autoconfig => unspecified */
528 const uint8_t unc_llconf[] = {0x0f,0x28,0x22,0x20};
529 
530 /* Uncompression of ctx-based */
531 /* 0 -> 0 bits from packet [unspecified / reserved] */
532 /* 1 -> 8 bytes from prefix - bunch of zeroes and 8 from packet */
533 /* 2 -> 8 bytes from prefix - 0000::00ff:fe00:XXXX + 2 from packet */
534 /* 3 -> 8 bytes from prefix - infer 8 bytes from lladdr */
535 const uint8_t unc_ctxconf[] = {0x00,0x88,0x82,0x80};
536 
537 /* Uncompression of ctx-based */
538 /* 0 -> 0 bits from packet */
539 /* 1 -> 2 bytes from prefix - bunch of zeroes 5 from packet */
540 /* 2 -> 2 bytes from prefix - zeroes + 3 from packet */
541 /* 3 -> 2 bytes from prefix - infer 1 bytes from lladdr */
542 const uint8_t unc_mxconf[] = {0x0f, 0x25, 0x23, 0x21};
543 
544 /* Link local prefix */
545 const uint8_t llprefix[] = {0xfe, 0x80};
546 
547 /* TTL uncompression values */
548 static const uint8_t ttl_values[] = {0, 1, 64, 255};
549 
550 /*--------------------------------------------------------------------*/
551 /** \name IPHC related functions
552  * @{ */
553 /*--------------------------------------------------------------------*/
554 /** \brief find the context corresponding to prefix ipaddr */
555 static struct sicslowpan_addr_context*
557 {
558 /* Remove code to avoid warnings and save flash if no context is used */
559 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
560  int i;
561  for(i = 0; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) {
562  if((addr_contexts[i].used == 1) &&
563  uip_ipaddr_prefixcmp(&addr_contexts[i].prefix, ipaddr, 64)) {
564  return &addr_contexts[i];
565  }
566  }
567 #endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */
568  return NULL;
569 }
570 /*--------------------------------------------------------------------*/
571 /** \brief find the context with the given number */
572 static struct sicslowpan_addr_context*
574 {
575 /* Remove code to avoid warnings and save flash if no context is used */
576 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
577  int i;
578  for(i = 0; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) {
579  if((addr_contexts[i].used == 1) &&
580  addr_contexts[i].number == number) {
581  return &addr_contexts[i];
582  }
583  }
584 #endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */
585  return NULL;
586 }
587 /*--------------------------------------------------------------------*/
588 static uint8_t
589 compress_addr_64(uint8_t bitpos, uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
590 {
591  if(uip_is_addr_mac_addr_based(ipaddr, lladdr)) {
592  return 3 << bitpos; /* 0-bits */
594  /* compress IID to 16 bits xxxx::0000:00ff:fe00:XXXX */
595  memcpy(hc06_ptr, &ipaddr->u16[7], 2);
596  hc06_ptr += 2;
597  return 2 << bitpos; /* 16-bits */
598  } else {
599  /* do not compress IID => xxxx::IID */
600  memcpy(hc06_ptr, &ipaddr->u16[4], 8);
601  hc06_ptr += 8;
602  return 1 << bitpos; /* 64-bits */
603  }
604 }
605 
606 /*-------------------------------------------------------------------- */
607 /* Uncompress addresses based on a prefix and a postfix with zeroes in
608  * between. If the postfix is zero in length it will use the link address
609  * to configure the IP address (autoconf style).
610  * pref_post_count takes a byte where the first nibble specify prefix count
611  * and the second postfix count (NOTE: 15/0xf => 16 bytes copy).
612  */
613 static void
614 uncompress_addr(uip_ipaddr_t *ipaddr, uint8_t const prefix[],
615  uint8_t pref_post_count, uip_lladdr_t *lladdr)
616 {
617  uint8_t prefcount = pref_post_count >> 4;
618  uint8_t postcount = pref_post_count & 0x0f;
619  /* full nibble 15 => 16 */
620  prefcount = prefcount == 15 ? 16 : prefcount;
621  postcount = postcount == 15 ? 16 : postcount;
622 
623  LOG_DBG("uncompression: address %d %d ", prefcount, postcount);
624 
625  if(prefcount > 0) {
626  memcpy(ipaddr, prefix, prefcount);
627  }
628  if(prefcount + postcount < 16) {
629  memset(&ipaddr->u8[prefcount], 0, 16 - (prefcount + postcount));
630  }
631  if(postcount > 0) {
632  memcpy(&ipaddr->u8[16 - postcount], hc06_ptr, postcount);
633  if(postcount == 2 && prefcount < 11) {
634  /* 16 bits uncompression => 0000:00ff:fe00:XXXX */
635  ipaddr->u8[11] = 0xff;
636  ipaddr->u8[12] = 0xfe;
637  }
638  hc06_ptr += postcount;
639  } else if (prefcount > 0) {
640  /* no IID based configuration if no prefix and no data => unspec */
641  uip_ds6_set_addr_iid(ipaddr, lladdr);
642  }
643 
644  LOG_DBG_6ADDR(ipaddr);
645  LOG_DBG_("\n");
646 }
647 
648 /*--------------------------------------------------------------------*/
649 /**
650  * \brief Compress IP/UDP header
651  *
652  * This function is called by the 6lowpan code to create a compressed
653  * 6lowpan packet in the packetbuf buffer from a full IPv6 packet in the
654  * uip_buf buffer.
655  *
656  *
657  * IPHC (RFC 6282)\n
658  * http://tools.ietf.org/html/
659  *
660  * \note We do not support ISA100_UDP header compression
661  *
662  * For LOWPAN_UDP compression, we either compress both ports or none.
663  * General format with LOWPAN_UDP compression is
664  * \verbatim
665  * 1 2 3
666  * 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
667  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
668  * |0|1|1|TF |N|HLI|C|S|SAM|M|D|DAM| SCI | DCI | comp. IPv6 hdr|
669  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
670  * | compressed IPv6 fields ..... |
671  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
672  * | LOWPAN_UDP | non compressed UDP fields ... |
673  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
674  * | L4 data ... |
675  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
676  * \endverbatim
677  * \note The context number 00 is reserved for the link local prefix.
678  * For unicast addresses, if we cannot compress the prefix, we neither
679  * compress the IID.
680  * \param link_destaddr L2 destination address, needed to compress IP
681  * dest
682  * \return 1 if success, else 0
683  */
684 static int
685 compress_hdr_iphc(linkaddr_t *link_destaddr)
686 {
687  uint8_t tmp, iphc0, iphc1, *next_hdr, *next_nhc;
688  int ext_hdr_len;
689  struct uip_udp_hdr *udp_buf;
690 
691  if(LOG_DBG_ENABLED) {
692  uint16_t ndx;
693  LOG_DBG("compression: before (%d): ", UIP_IP_BUF->len[1]);
694  for(ndx = 0; ndx < UIP_IP_BUF->len[1] + 40; ndx++) {
695  uint8_t data = ((uint8_t *) (UIP_IP_BUF))[ndx];
696  LOG_DBG_("%02x", data);
697  }
698  LOG_DBG_("\n");
699  }
700 
701 /* Macro used only internally, during header compression. Checks if there
702  * is sufficient space in packetbuf before writing any further. */
703 #define CHECK_BUFFER_SPACE(writelen) do { \
704  if(hc06_ptr + (writelen) >= PACKETBUF_PAYLOAD_END) { \
705  LOG_WARN("Not enough packetbuf space to compress header (%u bytes, %u left). Aborting.\n", \
706  (unsigned)(writelen), (unsigned)(PACKETBUF_PAYLOAD_END - hc06_ptr)); \
707  return 0; \
708  } \
709 } while(0);
710 
711  hc06_ptr = PACKETBUF_IPHC_BUF + 2;
712 
713  /* Check if there is enough space for the compressed IPv6 header, in the
714  * worst case (least compressed case). Extension headers and transport
715  * layer will be checked when they are compressed. */
716  CHECK_BUFFER_SPACE(38);
717 
718  /*
719  * As we copy some bit-length fields, in the IPHC encoding bytes,
720  * we sometimes use |=
721  * If the field is 0, and the current bit value in memory is 1,
722  * this does not work. We therefore reset the IPHC encoding here
723  */
724 
725  iphc0 = SICSLOWPAN_DISPATCH_IPHC;
726  iphc1 = 0;
727  PACKETBUF_IPHC_BUF[2] = 0; /* might not be used - but needs to be cleared */
728 
729  /*
730  * Address handling needs to be made first since it might
731  * cause an extra byte with [ SCI | DCI ]
732  *
733  */
734 
735 
736  /* check if dest context exists (for allocating third byte) */
737  /* TODO: fix this so that it remembers the looked up values for
738  avoiding two lookups - or set the lookup values immediately */
739  if(addr_context_lookup_by_prefix(&UIP_IP_BUF->destipaddr) != NULL ||
740  addr_context_lookup_by_prefix(&UIP_IP_BUF->srcipaddr) != NULL) {
741  /* set context flag and increase hc06_ptr */
742  LOG_DBG("compression: dest or src ipaddr - setting CID\n");
743  iphc1 |= SICSLOWPAN_IPHC_CID;
744  hc06_ptr++;
745  }
746 
747  /*
748  * Traffic class, flow label
749  * If flow label is 0, compress it. If traffic class is 0, compress it
750  * We have to process both in the same time as the offset of traffic class
751  * depends on the presence of version and flow label
752  */
753 
754  /* IPHC format of tc is ECN | DSCP , original is DSCP | ECN */
755 
756  tmp = (UIP_IP_BUF->vtc << 4) | (UIP_IP_BUF->tcflow >> 4);
757  tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
758 
759  if(((UIP_IP_BUF->tcflow & 0x0F) == 0) &&
760  (UIP_IP_BUF->flow == 0)) {
761  /* flow label can be compressed */
762  iphc0 |= SICSLOWPAN_IPHC_FL_C;
763  if(((UIP_IP_BUF->vtc & 0x0F) == 0) &&
764  ((UIP_IP_BUF->tcflow & 0xF0) == 0)) {
765  /* compress (elide) all */
766  iphc0 |= SICSLOWPAN_IPHC_TC_C;
767  } else {
768  /* compress only the flow label */
769  *hc06_ptr = tmp;
770  hc06_ptr += 1;
771  }
772  } else {
773  /* Flow label cannot be compressed */
774  if(((UIP_IP_BUF->vtc & 0x0F) == 0) &&
775  ((UIP_IP_BUF->tcflow & 0xF0) == 0)) {
776  /* compress only traffic class */
777  iphc0 |= SICSLOWPAN_IPHC_TC_C;
778  *hc06_ptr = (tmp & 0xc0) |
779  (UIP_IP_BUF->tcflow & 0x0F);
780  memcpy(hc06_ptr + 1, &UIP_IP_BUF->flow, 2);
781  hc06_ptr += 3;
782  } else {
783  /* compress nothing */
784  memcpy(hc06_ptr, &UIP_IP_BUF->vtc, 4);
785  /* but replace the top byte with the new ECN | DSCP format*/
786  *hc06_ptr = tmp;
787  hc06_ptr += 4;
788  }
789  }
790 
791  /* Note that the payload length is always compressed */
792 
793  /* Next header. We compress it is compressable. */
794  if(IS_COMPRESSABLE_PROTO(UIP_IP_BUF->proto)) {
795  iphc0 |= SICSLOWPAN_IPHC_NH_C;
796  }
797 
798  /* Add proto header unless it is compressed */
799  if((iphc0 & SICSLOWPAN_IPHC_NH_C) == 0) {
800  *hc06_ptr = UIP_IP_BUF->proto;
801  hc06_ptr += 1;
802  }
803 
804  /*
805  * Hop limit
806  * if 1: compress, encoding is 01
807  * if 64: compress, encoding is 10
808  * if 255: compress, encoding is 11
809  * else do not compress
810  */
811  switch(UIP_IP_BUF->ttl) {
812  case 1:
813  iphc0 |= SICSLOWPAN_IPHC_TTL_1;
814  break;
815  case 64:
816  iphc0 |= SICSLOWPAN_IPHC_TTL_64;
817  break;
818  case 255:
819  iphc0 |= SICSLOWPAN_IPHC_TTL_255;
820  break;
821  default:
822  *hc06_ptr = UIP_IP_BUF->ttl;
823  hc06_ptr += 1;
824  break;
825  }
826 
827  /* source address - cannot be multicast */
828  if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
829  LOG_DBG("compression: addr unspecified - setting SAC\n");
830  iphc1 |= SICSLOWPAN_IPHC_SAC;
831  iphc1 |= SICSLOWPAN_IPHC_SAM_00;
832  } else if((context = addr_context_lookup_by_prefix(&UIP_IP_BUF->srcipaddr))
833  != NULL) {
834  /* elide the prefix - indicate by CID and set context + SAC */
835  LOG_DBG("compression: src with context - setting CID & SAC ctx: %d\n",
836  context->number);
837  iphc1 |= SICSLOWPAN_IPHC_CID | SICSLOWPAN_IPHC_SAC;
838  PACKETBUF_IPHC_BUF[2] |= context->number << 4;
839  /* compession compare with this nodes address (source) */
840 
841  iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_SAM_BIT,
842  &UIP_IP_BUF->srcipaddr, &uip_lladdr);
843  /* No context found for this address */
844  } else if(uip_is_addr_linklocal(&UIP_IP_BUF->srcipaddr) &&
845  UIP_IP_BUF->destipaddr.u16[1] == 0 &&
846  UIP_IP_BUF->destipaddr.u16[2] == 0 &&
847  UIP_IP_BUF->destipaddr.u16[3] == 0) {
848  iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_SAM_BIT,
849  &UIP_IP_BUF->srcipaddr, &uip_lladdr);
850  } else {
851  /* send the full address => SAC = 0, SAM = 00 */
852  iphc1 |= SICSLOWPAN_IPHC_SAM_00; /* 128-bits */
853  memcpy(hc06_ptr, &UIP_IP_BUF->srcipaddr.u16[0], 16);
854  hc06_ptr += 16;
855  }
856 
857  /* dest address*/
858  if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
859  /* Address is multicast, try to compress */
860  iphc1 |= SICSLOWPAN_IPHC_M;
861  if(sicslowpan_is_mcast_addr_compressable8(&UIP_IP_BUF->destipaddr)) {
862  iphc1 |= SICSLOWPAN_IPHC_DAM_11;
863  /* use last byte */
864  *hc06_ptr = UIP_IP_BUF->destipaddr.u8[15];
865  hc06_ptr += 1;
866  } else if(sicslowpan_is_mcast_addr_compressable32(&UIP_IP_BUF->destipaddr)) {
867  iphc1 |= SICSLOWPAN_IPHC_DAM_10;
868  /* second byte + the last three */
869  *hc06_ptr = UIP_IP_BUF->destipaddr.u8[1];
870  memcpy(hc06_ptr + 1, &UIP_IP_BUF->destipaddr.u8[13], 3);
871  hc06_ptr += 4;
872  } else if(sicslowpan_is_mcast_addr_compressable48(&UIP_IP_BUF->destipaddr)) {
873  iphc1 |= SICSLOWPAN_IPHC_DAM_01;
874  /* second byte + the last five */
875  *hc06_ptr = UIP_IP_BUF->destipaddr.u8[1];
876  memcpy(hc06_ptr + 1, &UIP_IP_BUF->destipaddr.u8[11], 5);
877  hc06_ptr += 6;
878  } else {
879  iphc1 |= SICSLOWPAN_IPHC_DAM_00;
880  /* full address */
881  memcpy(hc06_ptr, &UIP_IP_BUF->destipaddr.u8[0], 16);
882  hc06_ptr += 16;
883  }
884  } else {
885  /* Address is unicast, try to compress */
886  if((context = addr_context_lookup_by_prefix(&UIP_IP_BUF->destipaddr)) != NULL) {
887  /* elide the prefix */
888  iphc1 |= SICSLOWPAN_IPHC_DAC;
889  PACKETBUF_IPHC_BUF[2] |= context->number;
890  /* compession compare with link adress (destination) */
891 
892  iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_DAM_BIT,
893  &UIP_IP_BUF->destipaddr,
894  (uip_lladdr_t *)link_destaddr);
895  /* No context found for this address */
896  } else if(uip_is_addr_linklocal(&UIP_IP_BUF->destipaddr) &&
897  UIP_IP_BUF->destipaddr.u16[1] == 0 &&
898  UIP_IP_BUF->destipaddr.u16[2] == 0 &&
899  UIP_IP_BUF->destipaddr.u16[3] == 0) {
900  iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_DAM_BIT,
901  &UIP_IP_BUF->destipaddr, (uip_lladdr_t *)link_destaddr);
902  } else {
903  /* send the full address */
904  iphc1 |= SICSLOWPAN_IPHC_DAM_00; /* 128-bits */
905  memcpy(hc06_ptr, &UIP_IP_BUF->destipaddr.u16[0], 16);
906  hc06_ptr += 16;
907  }
908  }
909 
910  uncomp_hdr_len = UIP_IPH_LEN;
911 
912  /* Start of ext hdr compression or UDP compression */
913  /* pick out the next-header position */
914  next_hdr = &UIP_IP_BUF->proto;
915  next_nhc = hc06_ptr; /* here we set the next header is compressed. */
916  ext_hdr_len = 0;
917  /* reserve the write place of this next header position */
918  LOG_DBG("compression: first header: %d\n", *next_hdr);
919  while(next_hdr != NULL && IS_COMPRESSABLE_PROTO(*next_hdr)) {
920  LOG_DBG("compression: next header: %d\n", *next_hdr);
921  int proto = -1; /* used for the specific ext hdr */
922  /* UDP and EXT header compression */
923  switch(*next_hdr) {
924  case UIP_PROTO_HBHO:
925  proto = SICSLOWPAN_NHC_ETX_HDR_HBHO;
926  case UIP_PROTO_ROUTING:
927  proto = proto == -1 ? SICSLOWPAN_NHC_ETX_HDR_ROUTING : proto;
928  case UIP_PROTO_FRAG:
929  proto = proto == -1 ? SICSLOWPAN_NHC_ETX_HDR_FRAG : proto;
930  case UIP_PROTO_DESTO:
931  /* Handle the header here! */
932  {
933  struct uip_ext_hdr *ext_hdr =
934  (struct uip_ext_hdr *) UIP_IPPAYLOAD_BUF_POS(ext_hdr_len);
935  int len;
936  proto = proto == -1 ? SICSLOWPAN_NHC_ETX_HDR_DESTO : proto;
937  /* Len is defined to be in octets from the length byte */
938  len = (ext_hdr->len << 3) + 8;
939  LOG_DBG("compression: next header %d (len:%d)\n", *next_hdr, len);
940  /* pick up the next header */
941  next_hdr = &ext_hdr->next;
942  /* If the next header is not compressable we need to reserve the
943  NHC byte extra - before the next header here. This is due to
944  next not being elided in that case. */
945  if(!IS_COMPRESSABLE_PROTO(*next_hdr)) {
946  CHECK_BUFFER_SPACE(1);
947  hc06_ptr++;
948  LOG_DBG("compression: keeping the next header in this ext hdr: %d\n",
949  ext_hdr->next);
950  }
951  /* copy the ext-hdr into the hc06 buffer */
952  CHECK_BUFFER_SPACE(len);
953  memcpy(hc06_ptr, ext_hdr, len);
954  /* modify the len to octets */
955  ext_hdr = (struct uip_ext_hdr *) hc06_ptr;
956  ext_hdr->len = len - 2; /* Len should be in bytes from len byte*/
957  ext_hdr_len += len;
958  hc06_ptr += len;
959  uncomp_hdr_len += len;
960 
961  /* Write this next header - with its NHC header - including flag
962  to tell if next header is elided in this one also- */
963  *next_nhc = SICSLOWPAN_NHC_EXT_HDR |
964  (IS_COMPRESSABLE_PROTO(*next_hdr) ? SICSLOWPAN_NHC_BIT : 0) |
965  (proto << 1);
966  /* update the position of the next header */
967  next_nhc = hc06_ptr;
968  }
969  break;
970  case UIP_PROTO_UDP:
971  /* allocate a byte for the next header posision as UDP has no next */
972  hc06_ptr++;
973  udp_buf = UIP_UDP_BUF_POS(ext_hdr_len);
974  LOG_DBG("compression: inlined UDP ports on send side: %x, %x\n",
975  UIP_HTONS(udp_buf->srcport), UIP_HTONS(udp_buf->destport));
976  /* Mask out the last 4 bits can be used as a mask */
977  if(((UIP_HTONS(udp_buf->srcport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN) &&
978  ((UIP_HTONS(udp_buf->destport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN)) {
979  /* we can compress 12 bits of both source and dest */
980  *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_11;
981  LOG_DBG("IPHC: remove 12 b of both source & dest with prefix 0xFOB\n");
982  CHECK_BUFFER_SPACE(1);
983  *hc06_ptr =
984  (uint8_t)((UIP_HTONS(udp_buf->srcport) -
985  SICSLOWPAN_UDP_4_BIT_PORT_MIN) << 4) +
986  (uint8_t)((UIP_HTONS(udp_buf->destport) -
987  SICSLOWPAN_UDP_4_BIT_PORT_MIN));
988  hc06_ptr += 1;
989  } else if((UIP_HTONS(udp_buf->destport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
990  /* we can compress 8 bits of dest, leave source. */
991  *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_01;
992  LOG_DBG("IPHC: leave source, remove 8 bits of dest with prefix 0xF0\n");
993  CHECK_BUFFER_SPACE(3);
994  memcpy(hc06_ptr, &udp_buf->srcport, 2);
995  *(hc06_ptr + 2) =
996  (uint8_t)((UIP_HTONS(udp_buf->destport) -
997  SICSLOWPAN_UDP_8_BIT_PORT_MIN));
998  hc06_ptr += 3;
999  } else if((UIP_HTONS(udp_buf->srcport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
1000  /* we can compress 8 bits of src, leave dest. Copy compressed port */
1001  *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_10;
1002  LOG_DBG("IPHC: remove 8 bits of source with prefix 0xF0, leave dest. hch: %i\n", *next_nhc);
1003  CHECK_BUFFER_SPACE(3);
1004  *hc06_ptr =
1005  (uint8_t)((UIP_HTONS(udp_buf->srcport) -
1006  SICSLOWPAN_UDP_8_BIT_PORT_MIN));
1007  memcpy(hc06_ptr + 1, &udp_buf->destport, 2);
1008  hc06_ptr += 3;
1009  } else {
1010  /* we cannot compress. Copy uncompressed ports, full checksum */
1011  *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_00;
1012  LOG_DBG("IPHC: cannot compress UDP headers\n");
1013  CHECK_BUFFER_SPACE(4);
1014  memcpy(hc06_ptr, &udp_buf->srcport, 4);
1015  hc06_ptr += 4;
1016  }
1017  /* always inline the checksum */
1018  CHECK_BUFFER_SPACE(2);
1019  memcpy(hc06_ptr, &udp_buf->udpchksum, 2);
1020  hc06_ptr += 2;
1021  uncomp_hdr_len += UIP_UDPH_LEN;
1022  /* this is the final header. */
1023  next_hdr = NULL;
1024  break;
1025  default:
1026  LOG_ERR("compression: could not handle compression of header");
1027  }
1028  }
1029  if(next_hdr != NULL) {
1030  /* Last header could not be compressed - we assume that this is then OK!*/
1031  /* as the last EXT_HDR should be "uncompressed" and have the next there */
1032  LOG_DBG("compression: last header could is not compressed: %d\n", *next_hdr);
1033  }
1034  /* before the packetbuf_hdr_len operation */
1035  PACKETBUF_IPHC_BUF[0] = iphc0;
1036  PACKETBUF_IPHC_BUF[1] = iphc1;
1037 
1038  if(LOG_DBG_ENABLED) {
1039  uint16_t ndx;
1040  LOG_DBG("compression: after (%d): ", (int)(hc06_ptr - packetbuf_ptr));
1041  for(ndx = 0; ndx < hc06_ptr - packetbuf_ptr; ndx++) {
1042  uint8_t data = ((uint8_t *) packetbuf_ptr)[ndx];
1043  LOG_DBG_("%02x", data);
1044  }
1045  LOG_DBG_("\n");
1046  }
1047 
1049 
1050  return 1;
1051 }
1052 
1053 /*--------------------------------------------------------------------*/
1054 /**
1055  * \brief Uncompress IPHC (i.e., IPHC and LOWPAN_UDP) headers and put
1056  * them in sicslowpan_buf
1057  *
1058  * This function is called by the input function when the dispatch is
1059  * IPHC.
1060  * We %process the packet in the packetbuf buffer, uncompress the header
1061  * fields, and copy the result in the sicslowpan buffer.
1062  * At the end of the decompression, packetbuf_hdr_len and uncompressed_hdr_len
1063  * are set to the appropriate values
1064  *
1065  * \param buf Pointer to the buffer to uncompress the packet into.
1066  * \param buf_size The size of the buffer to uncompress the packet into.
1067  * \param ip_len Equal to 0 if the packet is not a fragment (IP length
1068  * is then inferred from the L2 length), non 0 if the packet is a 1st
1069  * fragment.
1070  * \return A boolean value indicating whether the uncompression succeeded.
1071  */
1072 static bool
1073 uncompress_hdr_iphc(uint8_t *buf, uint16_t buf_size, uint16_t ip_len)
1074 {
1075  uint8_t tmp, iphc0, iphc1, nhc;
1076  struct uip_ext_hdr *exthdr;
1077  uint8_t* last_nextheader;
1078  uint8_t* ip_payload;
1079  uint8_t ext_hdr_len = 0;
1080  uint16_t cmpr_len;
1081 
1082 /* Macro used only internally, during header uncompression. Checks if there
1083  * is sufficient space in packetbuf before reading any further. */
1084 #define CHECK_READ_SPACE(readlen) \
1085  if((hc06_ptr - packetbuf_ptr) + (readlen) > cmpr_len) { \
1086  LOG_WARN("Not enough packetbuf space to decompress header (%u bytes, %u left). Aborting.\n", \
1087  (unsigned)(readlen), (unsigned)(cmpr_len - (hc06_ptr - packetbuf_ptr))); \
1088  return false; \
1089  }
1090 
1091  /* at least two byte will be used for the encoding */
1092  cmpr_len = packetbuf_datalen();
1093  if(cmpr_len < packetbuf_hdr_len + 2) {
1094  return false;
1095  }
1097 
1098  iphc0 = PACKETBUF_IPHC_BUF[0];
1099  iphc1 = PACKETBUF_IPHC_BUF[1];
1100 
1101  /* another if the CID flag is set */
1102  if(iphc1 & SICSLOWPAN_IPHC_CID) {
1103  LOG_DBG("uncompression: CID flag set - increase header with one\n");
1104  hc06_ptr++;
1105  }
1106 
1107  /* Traffic class and flow label */
1108  if((iphc0 & SICSLOWPAN_IPHC_FL_C) == 0) {
1109  /* Flow label are carried inline */
1110  if((iphc0 & SICSLOWPAN_IPHC_TC_C) == 0) {
1111  /* Traffic class is carried inline */
1112  CHECK_READ_SPACE(4);
1113  memcpy(&SICSLOWPAN_IP_BUF(buf)->tcflow, hc06_ptr + 1, 3);
1114  tmp = *hc06_ptr;
1115  hc06_ptr += 4;
1116  /* IPHC format of tc is ECN | DSCP , original is DSCP | ECN */
1117  /* set version, pick highest DSCP bits and set in vtc */
1118  SICSLOWPAN_IP_BUF(buf)->vtc = 0x60 | ((tmp >> 2) & 0x0f);
1119  /* ECN rolled down two steps + lowest DSCP bits at top two bits */
1120  SICSLOWPAN_IP_BUF(buf)->tcflow = ((tmp >> 2) & 0x30) | (tmp << 6) |
1121  (SICSLOWPAN_IP_BUF(buf)->tcflow & 0x0f);
1122  } else {
1123  /* Traffic class is compressed (set version and no TC)*/
1124  SICSLOWPAN_IP_BUF(buf)->vtc = 0x60;
1125  /* highest flow label bits + ECN bits */
1126  CHECK_READ_SPACE(3);
1127  SICSLOWPAN_IP_BUF(buf)->tcflow = (*hc06_ptr & 0x0F) |
1128  ((*hc06_ptr >> 2) & 0x30);
1129  memcpy(&SICSLOWPAN_IP_BUF(buf)->flow, hc06_ptr + 1, 2);
1130  hc06_ptr += 3;
1131  }
1132  } else {
1133  /* Version is always 6! */
1134  /* Version and flow label are compressed */
1135  if((iphc0 & SICSLOWPAN_IPHC_TC_C) == 0) {
1136  /* Traffic class is inline */
1137  CHECK_READ_SPACE(1);
1138  SICSLOWPAN_IP_BUF(buf)->vtc = 0x60 | ((*hc06_ptr >> 2) & 0x0f);
1139  SICSLOWPAN_IP_BUF(buf)->tcflow = ((*hc06_ptr << 6) & 0xC0) | ((*hc06_ptr >> 2) & 0x30);
1140  SICSLOWPAN_IP_BUF(buf)->flow = 0;
1141  hc06_ptr += 1;
1142  } else {
1143  /* Traffic class is compressed */
1144  SICSLOWPAN_IP_BUF(buf)->vtc = 0x60;
1145  SICSLOWPAN_IP_BUF(buf)->tcflow = 0;
1146  SICSLOWPAN_IP_BUF(buf)->flow = 0;
1147  }
1148  }
1149 
1150  /* Next Header */
1151  if((iphc0 & SICSLOWPAN_IPHC_NH_C) == 0) {
1152  /* Next header is carried inline */
1153  CHECK_READ_SPACE(1);
1154  SICSLOWPAN_IP_BUF(buf)->proto = *hc06_ptr;
1155  LOG_DBG("uncompression: next header inline: %d\n", SICSLOWPAN_IP_BUF(buf)->proto);
1156  hc06_ptr += 1;
1157  }
1158 
1159  /* Hop limit */
1160  if((iphc0 & 0x03) != SICSLOWPAN_IPHC_TTL_I) {
1161  SICSLOWPAN_IP_BUF(buf)->ttl = ttl_values[iphc0 & 0x03];
1162  } else {
1163  CHECK_READ_SPACE(1);
1164  SICSLOWPAN_IP_BUF(buf)->ttl = *hc06_ptr;
1165  hc06_ptr += 1;
1166  }
1167 
1168  /* put the source address compression mode SAM in the tmp var */
1169  tmp = ((iphc1 & SICSLOWPAN_IPHC_SAM_11) >> SICSLOWPAN_IPHC_SAM_BIT) & 0x03;
1170 
1171  /* context based compression */
1172  if(iphc1 & SICSLOWPAN_IPHC_SAC) {
1173  uint8_t sci = (iphc1 & SICSLOWPAN_IPHC_CID) ?
1174  PACKETBUF_IPHC_BUF[2] >> 4 : 0;
1175 
1176  /* Source address - check context != NULL only if SAM bits are != 0*/
1177  if (tmp != 0) {
1178  context = addr_context_lookup_by_number(sci);
1179  if(context == NULL) {
1180  LOG_ERR("uncompression: error context not found\n");
1181  return false;
1182  }
1183  }
1184  /* if tmp == 0 we do not have a context and therefore no prefix */
1185  uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->srcipaddr,
1186  tmp != 0 ? context->prefix : NULL, unc_ctxconf[tmp],
1187  (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
1188  } else {
1189  /* no compression and link local */
1190  uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->srcipaddr, llprefix, unc_llconf[tmp],
1191  (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
1192  }
1193 
1194  /* Destination address */
1195  /* put the destination address compression mode into tmp */
1196  tmp = ((iphc1 & SICSLOWPAN_IPHC_DAM_11) >> SICSLOWPAN_IPHC_DAM_BIT) & 0x03;
1197 
1198  /* multicast compression */
1199  if(iphc1 & SICSLOWPAN_IPHC_M) {
1200  /* context based multicast compression */
1201  if(iphc1 & SICSLOWPAN_IPHC_DAC) {
1202  /* TODO: implement this */
1203  } else {
1204  /* non-context based multicast compression - */
1205  /* DAM_00: 128 bits */
1206  /* DAM_01: 48 bits FFXX::00XX:XXXX:XXXX */
1207  /* DAM_10: 32 bits FFXX::00XX:XXXX */
1208  /* DAM_11: 8 bits FF02::00XX */
1209  uint8_t prefix[] = {0xff, 0x02};
1210  if(tmp > 0 && tmp < 3) {
1211  CHECK_READ_SPACE(1);
1212  prefix[1] = *hc06_ptr;
1213  hc06_ptr++;
1214  }
1215 
1216  uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr, prefix,
1217  unc_mxconf[tmp], NULL);
1218  }
1219  } else {
1220  /* no multicast */
1221  /* Context based */
1222  if(iphc1 & SICSLOWPAN_IPHC_DAC) {
1223  uint8_t dci = (iphc1 & SICSLOWPAN_IPHC_CID) ? PACKETBUF_IPHC_BUF[2] & 0x0f : 0;
1224  context = addr_context_lookup_by_number(dci);
1225 
1226  /* all valid cases below need the context! */
1227  if(context == NULL) {
1228  LOG_ERR("uncompression: error context not found\n");
1229  return false;
1230  }
1231  uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr, context->prefix,
1232  unc_ctxconf[tmp],
1233  (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
1234  } else {
1235  /* not context based => link local M = 0, DAC = 0 - same as SAC */
1236  uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr, llprefix,
1237  unc_llconf[tmp],
1238  (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
1239  }
1240  }
1241  uncomp_hdr_len += UIP_IPH_LEN;
1242 
1243  /* Next header processing - continued */
1244  nhc = iphc0 & SICSLOWPAN_IPHC_NH_C;
1245  /* The next header is compressed, NHC is following */
1246  last_nextheader = &SICSLOWPAN_IP_BUF(buf)->proto;
1247  ip_payload = SICSLOWPAN_IPPAYLOAD_BUF(buf);
1248 
1249  CHECK_READ_SPACE(1);
1250  while(nhc && (*hc06_ptr & SICSLOWPAN_NHC_MASK) == SICSLOWPAN_NHC_EXT_HDR) {
1251  uint8_t eid = (*hc06_ptr & 0x0e) >> 1;
1252  /* next header compression flag */
1253  uint8_t nh = (*hc06_ptr & 0x01);
1254  uint8_t next = 0;
1255  uint8_t len;
1256  uint8_t proto;
1257 
1258  nhc = nh;
1259 
1260  hc06_ptr++;
1261  CHECK_READ_SPACE(1);
1262  if(!nh) {
1263  next = *hc06_ptr;
1264  hc06_ptr++;
1265  LOG_DBG("uncompression: next header is inlined. Next: %d\n", next);
1266  }
1267  CHECK_READ_SPACE(1);
1268  len = *hc06_ptr;
1269  hc06_ptr++;
1270 
1271  LOG_DBG("uncompression: found ext header id: %d next: %d len: %d\n", eid, next, len);
1272  switch(eid) {
1273  case SICSLOWPAN_NHC_ETX_HDR_HBHO:
1274  proto = UIP_PROTO_HBHO;
1275  break;
1276  case SICSLOWPAN_NHC_ETX_HDR_ROUTING:
1277  proto = UIP_PROTO_ROUTING;
1278  break;
1279  case SICSLOWPAN_NHC_ETX_HDR_FRAG:
1280  proto = UIP_PROTO_FRAG;
1281  break;
1282  case SICSLOWPAN_NHC_ETX_HDR_DESTO:
1283  proto = UIP_PROTO_DESTO;
1284  break;
1285  default:
1286  LOG_DBG("uncompression: error unsupported ext header\n");
1287  return false;
1288  }
1289  *last_nextheader = proto;
1290 
1291  /* Check that there is enough room to write the extension header. */
1292  if((ip_payload - buf) + UIP_EXT_HDR_LEN + len > buf_size) {
1293  LOG_WARN("uncompression: cannot write ext header beyond target buffer\n");
1294  return false;
1295  }
1296 
1297  /* uncompress the extension header */
1298  exthdr = (struct uip_ext_hdr *)ip_payload;
1299  exthdr->len = (UIP_EXT_HDR_LEN + len) / 8;
1300  if(exthdr->len == 0) {
1301  LOG_WARN("Extension header length is below 8\n");
1302  return false;
1303  }
1304  exthdr->len--;
1305  exthdr->next = next;
1306  last_nextheader = &exthdr->next;
1307 
1308  /* The loop condition needs to read one byte after the next len bytes in the buffer. */
1309  CHECK_READ_SPACE(len + 1);
1310  memcpy((uint8_t *)exthdr + UIP_EXT_HDR_LEN, hc06_ptr, len);
1311  hc06_ptr += len;
1312 
1313  uncomp_hdr_len += (exthdr->len + 1) * 8;
1314  ip_payload += (exthdr->len + 1) * 8;
1315  ext_hdr_len += (exthdr->len + 1) * 8;
1316 
1317  LOG_DBG("uncompression: %d len: %d exthdr len: %d (calc: %d)\n",
1318  proto, len, exthdr->len, (exthdr->len + 1) * 8);
1319  }
1320 
1321  /* The next header is compressed, NHC is following */
1322  CHECK_READ_SPACE(1);
1323  if(nhc && (*hc06_ptr & SICSLOWPAN_NHC_UDP_MASK) == SICSLOWPAN_NHC_UDP_ID) {
1324  struct uip_udp_hdr *udp_buf = (struct uip_udp_hdr *)ip_payload;
1325  uint16_t udp_len;
1326  uint8_t checksum_compressed;
1327  *last_nextheader = UIP_PROTO_UDP;
1328  checksum_compressed = *hc06_ptr & SICSLOWPAN_NHC_UDP_CHECKSUMC;
1329  LOG_DBG("uncompression: incoming header value: %i\n", *hc06_ptr);
1330  switch(*hc06_ptr & SICSLOWPAN_NHC_UDP_CS_P_11) {
1331  case SICSLOWPAN_NHC_UDP_CS_P_00:
1332  /* 1 byte for NHC, 4 byte for ports, 2 bytes chksum */
1333  CHECK_READ_SPACE(5);
1334  memcpy(&udp_buf->srcport, hc06_ptr + 1, 2);
1335  memcpy(&udp_buf->destport, hc06_ptr + 3, 2);
1336  LOG_DBG("uncompression: UDP ports (ptr+5): %x, %x\n",
1337  UIP_HTONS(udp_buf->srcport),
1338  UIP_HTONS(udp_buf->destport));
1339  hc06_ptr += 5;
1340  break;
1341 
1342  case SICSLOWPAN_NHC_UDP_CS_P_01:
1343  /* 1 byte for NHC + source 16bit inline, dest = 0xF0 + 8 bit inline */
1344  LOG_DBG("uncompression: destination address\n");
1345  CHECK_READ_SPACE(4);
1346  memcpy(&udp_buf->srcport, hc06_ptr + 1, 2);
1347  udp_buf->destport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN + (*(hc06_ptr + 3)));
1348  LOG_DBG("uncompression: UDP ports (ptr+4): %x, %x\n",
1349  UIP_HTONS(udp_buf->srcport), UIP_HTONS(udp_buf->destport));
1350  hc06_ptr += 4;
1351  break;
1352 
1353  case SICSLOWPAN_NHC_UDP_CS_P_10:
1354  /* 1 byte for NHC + source = 0xF0 + 8bit inline, dest = 16 bit inline*/
1355  LOG_DBG("uncompression: source address\n");
1356  CHECK_READ_SPACE(4);
1357  udp_buf->srcport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN +
1358  (*(hc06_ptr + 1)));
1359  memcpy(&udp_buf->destport, hc06_ptr + 2, 2);
1360  LOG_DBG("uncompression: UDP ports (ptr+4): %x, %x\n",
1361  UIP_HTONS(udp_buf->srcport), UIP_HTONS(udp_buf->destport));
1362  hc06_ptr += 4;
1363  break;
1364 
1365  case SICSLOWPAN_NHC_UDP_CS_P_11:
1366  /* 1 byte for NHC, 1 byte for ports */
1367  CHECK_READ_SPACE(2);
1368  udp_buf->srcport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
1369  (*(hc06_ptr + 1) >> 4));
1370  udp_buf->destport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
1371  ((*(hc06_ptr + 1)) & 0x0F));
1372  LOG_DBG("uncompression: UDP ports (ptr+2): %x, %x\n",
1373  UIP_HTONS(udp_buf->srcport), UIP_HTONS(udp_buf->destport));
1374 
1375  hc06_ptr += 2;
1376  break;
1377  default:
1378  LOG_DBG("uncompression: error unsupported UDP compression\n");
1379  return false;
1380  }
1381  if(!checksum_compressed) { /* has_checksum, default */
1382  CHECK_READ_SPACE(2);
1383  memcpy(&udp_buf->udpchksum, hc06_ptr, 2);
1384  hc06_ptr += 2;
1385  LOG_DBG("uncompression: checksum included\n");
1386  } else {
1387  LOG_DBG("uncompression: checksum *NOT* included\n");
1388  }
1389 
1390  /* length field in UDP header (8 byte header + payload) */
1391  udp_len = 8 + packetbuf_datalen() - (hc06_ptr - packetbuf_ptr);
1392  udp_buf->udplen = UIP_HTONS(ip_len == 0 ? udp_len :
1393  ip_len - UIP_IPH_LEN - ext_hdr_len);
1394  LOG_DBG("uncompression: UDP length: %u (ext: %u) ip_len: %d udp_len: %d\n",
1395  UIP_HTONS(udp_buf->udplen), ext_hdr_len, ip_len, udp_len);
1396 
1397  uncomp_hdr_len += UIP_UDPH_LEN;
1398  }
1399 
1400  packetbuf_hdr_len = hc06_ptr - packetbuf_ptr;
1401 
1402  /* IP length field. */
1403  if(ip_len == 0) {
1404  int len = packetbuf_datalen() - packetbuf_hdr_len + uncomp_hdr_len - UIP_IPH_LEN;
1405  LOG_DBG("uncompression: IP payload length: %d. %u - %u + %u - %u\n", len,
1406  packetbuf_datalen(), packetbuf_hdr_len, uncomp_hdr_len, UIP_IPH_LEN);
1407 
1408  /* This is not a fragmented packet */
1409  SICSLOWPAN_IP_BUF(buf)->len[0] = len >> 8;
1410  SICSLOWPAN_IP_BUF(buf)->len[1] = len & 0x00FF;
1411  } else {
1412  /* This is a 1st fragment */
1413  SICSLOWPAN_IP_BUF(buf)->len[0] = (ip_len - UIP_IPH_LEN) >> 8;
1414  SICSLOWPAN_IP_BUF(buf)->len[1] = (ip_len - UIP_IPH_LEN) & 0x00FF;
1415  }
1416 
1417  return true;
1418 }
1419 /** @} */
1420 #endif /* SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC */
1421 
1422 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_6LORH
1423 /*--------------------------------------------------------------------*/
1424 /**
1425  * \brief Adds Paging dispatch byte
1426  */
1427 static void
1428 add_paging_dispatch(uint8_t page)
1429 {
1430  /* Add paging dispatch to Page 1 */
1431  PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] = SICSLOWPAN_DISPATCH_PAGING | (page & 0x0f);
1433 }
1434 /*--------------------------------------------------------------------*/
1435 /**
1436  * \brief Adds 6lorh headers before IPHC
1437  */
1438 static void
1440 {
1441  /* 6LoRH is not implemented yet */
1442 }
1443 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_6LORH */
1444 
1445 /*--------------------------------------------------------------------*/
1446 /**
1447  * \brief Digest 6lorh headers before IPHC
1448  */
1449 static void
1451 {
1452  /* Is this a paging dispatch? */
1453  if((PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] & SICSLOWPAN_DISPATCH_PAGING_MASK) == SICSLOWPAN_DISPATCH_PAGING) {
1454  /* Parse page number */
1455  curr_page = PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] & 0x0f;
1457  }
1458 }
1459 /*--------------------------------------------------------------------*/
1460 /**
1461  * \brief Digest 6lorh headers before IPHC
1462  */
1463 static void
1465 {
1466  /* 6LoRH is not implemented yet */
1467 }
1468 /*--------------------------------------------------------------------*/
1469 /** \name IPv6 dispatch "compression" function
1470  * @{ */
1471 /*--------------------------------------------------------------------*/
1472 /* \brief Packets "Compression" when only IPv6 dispatch is used
1473  *
1474  * There is no compression in this case, all fields are sent
1475  * inline. We just add the IPv6 dispatch byte before the packet.
1476  * \verbatim
1477  * 0 1 2 3
1478  * 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
1479  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1480  * | IPv6 Dsp | IPv6 header and payload ...
1481  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1482  * \endverbatim
1483  */
1484 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6
1485 static void
1486 compress_hdr_ipv6(linkaddr_t *link_destaddr)
1487 {
1488  *packetbuf_ptr = SICSLOWPAN_DISPATCH_IPV6;
1489  packetbuf_hdr_len += SICSLOWPAN_IPV6_HDR_LEN;
1490  memcpy(packetbuf_ptr + packetbuf_hdr_len, UIP_IP_BUF, UIP_IPH_LEN);
1491  packetbuf_hdr_len += UIP_IPH_LEN;
1492  uncomp_hdr_len += UIP_IPH_LEN;
1493  return;
1494 }
1495 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6 */
1496 /** @} */
1497 
1498 /*--------------------------------------------------------------------*/
1499 /** \name Input/output functions common to all compression schemes
1500  * @{ */
1501 /*--------------------------------------------------------------------*/
1502 /**
1503  * Callback function for the MAC packet sent callback
1504  */
1505 static void
1506 packet_sent(void *ptr, int status, int transmissions)
1507 {
1508  const linkaddr_t *dest;
1509 
1510  if(callback != NULL) {
1511  callback->output_callback(status);
1512  }
1513  last_tx_status = status;
1514 
1515  /* What follows only applies to unicast */
1516  dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
1517  if(linkaddr_cmp(dest, &linkaddr_null)) {
1518  return;
1519  }
1520 
1521  /* Update neighbor link statistics */
1522  link_stats_packet_sent(dest, status, transmissions);
1523 
1524  /* Call routing protocol link callback */
1525  NETSTACK_ROUTING.link_callback(dest, status, transmissions);
1526 
1527  /* DS6 callback, used for UIP_DS6_LL_NUD */
1528  uip_ds6_link_callback(status, transmissions);
1529 }
1530 /*--------------------------------------------------------------------*/
1531 /**
1532  * \brief This function is called by the 6lowpan code to send out a
1533  * packet.
1534  * \param dest the link layer destination address of the packet
1535  */
1536 static void
1537 send_packet(linkaddr_t *dest)
1538 {
1539  /* Set the link layer destination address for the packet as a
1540  * packetbuf attribute. The MAC layer can access the destination
1541  * address with the function packetbuf_addr(PACKETBUF_ADDR_RECEIVER).
1542  */
1543  packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, dest);
1544 
1545 #if NETSTACK_CONF_BRIDGE_MODE
1546  /* This needs to be explicitly set here for bridge mode to work */
1547  packetbuf_set_addr(PACKETBUF_ADDR_SENDER,(void*)&uip_lladdr);
1548 #endif
1549 
1550  /* Provide a callback function to receive the result of
1551  a packet transmission. */
1552  NETSTACK_MAC.send(&packet_sent, NULL);
1553 
1554  /* If we are sending multiple packets in a row, we need to let the
1555  watchdog know that we are still alive. */
1557 }
1558 #if SICSLOWPAN_CONF_FRAG
1559 /*--------------------------------------------------------------------*/
1560 /**
1561  * \brief This function is called by the 6lowpan code to copy a fragment's
1562  * payload from uIP and send it down the stack.
1563  * \param uip_offset the offset in the uIP buffer where to copy the payload from
1564  * \param dest the link layer destination address of the packet
1565  * \return 1 if success, 0 otherwise
1566  */
1567 static int
1568 fragment_copy_payload_and_send(uint16_t uip_offset, linkaddr_t *dest) {
1569  struct queuebuf *q;
1570 
1571  /* Now copy fragment payload from uip_buf */
1573  (uint8_t *)UIP_IP_BUF + uip_offset, packetbuf_payload_len);
1575 
1576  /* Backup packetbuf to queuebuf. Enables preserving attributes for all framgnets */
1577  q = queuebuf_new_from_packetbuf();
1578  if(q == NULL) {
1579  LOG_WARN("output: could not allocate queuebuf, dropping fragment\n");
1580  return 0;
1581  }
1582 
1583  /* Send fragment */
1584  send_packet(dest);
1585 
1586  /* Restore packetbuf from queuebuf */
1587  queuebuf_to_packetbuf(q);
1588  queuebuf_free(q);
1589 
1590  /* Check tx result. */
1591  if((last_tx_status == MAC_TX_COLLISION) ||
1592  (last_tx_status >= MAC_TX_ERR)) {
1593  LOG_ERR("output: error in fragment tx, dropping subsequent fragments.\n");
1594  return 0;
1595  }
1596  return 1;
1597 }
1598 #endif /* SICSLOWPAN_CONF_FRAG */
1599 /*--------------------------------------------------------------------*/
1600 /** \brief Take an IP packet and format it to be sent on an 802.15.4
1601  * network using 6lowpan.
1602  * \param localdest The MAC address of the destination
1603  *
1604  * The IP packet is initially in uip_buf. Its header is compressed
1605  * and if necessary it is fragmented. The resulting
1606  * packet/fragments are put in packetbuf and delivered to the 802.15.4
1607  * MAC.
1608  */
1609 static uint8_t
1610 output(const linkaddr_t *localdest)
1611 {
1612  int frag_needed;
1613 
1614  /* The MAC address of the destination of the packet */
1615  linkaddr_t dest;
1616 
1617  /* init */
1618  uncomp_hdr_len = 0;
1619  packetbuf_hdr_len = 0;
1620 
1621  /* reset packetbuf buffer */
1622  packetbuf_clear();
1624 
1625  if(callback) {
1626  /* call the attribution when the callback comes, but set attributes
1627  here ! */
1628  set_packet_attrs();
1629  }
1630 
1631  /*
1632  * The destination address will be tagged to each outbound
1633  * packet. If the argument localdest is NULL, we are sending a
1634  * broadcast packet.
1635  */
1636  if(localdest == NULL) {
1637  linkaddr_copy(&dest, &linkaddr_null);
1638  } else {
1639  linkaddr_copy(&dest, localdest);
1640  }
1641 
1642  LOG_INFO("output: sending IPv6 packet with len %d\n", uip_len);
1643 
1644  /* copy over the retransmission count from uipbuf attributes */
1645  packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS,
1646  uipbuf_get_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS));
1647 
1648 /* Calculate NETSTACK_FRAMER's header length, that will be added in the NETSTACK_MAC */
1649  packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest);
1650 #if LLSEC802154_USES_AUX_HEADER
1651  /* copy LLSEC level */
1652  packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL,
1653  uipbuf_get_attr(UIPBUF_ATTR_LLSEC_LEVEL));
1654 #if LLSEC802154_USES_EXPLICIT_KEYS
1655  packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX,
1656  uipbuf_get_attr(UIPBUF_ATTR_LLSEC_KEY_ID));
1657 #endif /* LLSEC802154_USES_EXPLICIT_KEYS */
1658 #endif /* LLSEC802154_USES_AUX_HEADER */
1659 
1660  mac_max_payload = NETSTACK_MAC.max_payload();
1661 
1662  if(mac_max_payload <= 0) {
1663  /* Framing failed, drop packet */
1664  LOG_WARN("output: failed to calculate payload size - dropping packet\n");
1665  return 0;
1666  }
1667 
1668  /* Try to compress the headers */
1669 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6
1670  compress_hdr_ipv6(&dest);
1671 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6 */
1672 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_6LORH
1673  /* Add 6LoRH headers before IPHC. Only needed on routed traffic
1674  (non link-local). */
1675  if(!uip_is_addr_linklocal(&UIP_IP_BUF->destipaddr)) {
1677  add_6lorh_hdr();
1678  }
1679 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_6LORH */
1680 #if SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC
1681  if(compress_hdr_iphc(&dest) == 0) {
1682  /* Warning should already be issued by function above */
1683  return 0;
1684  }
1685 #endif /* SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC */
1686 
1687  /* Use the mac_max_payload to understand what is the max payload in a MAC
1688  * packet. We calculate it here only to make a better decision of whether
1689  * the outgoing packet needs to be fragmented or not. */
1690 
1691  packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest);
1692 
1693  frag_needed = (int)uip_len - (int)uncomp_hdr_len + (int)packetbuf_hdr_len > mac_max_payload;
1694  LOG_INFO("output: header len %d -> %d, total len %d -> %d, MAC max payload %d, frag_needed %d\n",
1697  mac_max_payload, frag_needed);
1698 
1699  if(frag_needed) {
1700 #if SICSLOWPAN_CONF_FRAG
1701  /* Number of bytes processed. */
1702  uint16_t processed_ip_out_len;
1703  uint16_t frag_tag;
1704  int curr_frag = 0;
1705 
1706  /*
1707  * The outbound IPv6 packet is too large to fit into a single 15.4
1708  * packet, so we fragment it into multiple packets and send them.
1709  * The first fragment contains frag1 dispatch, then IPv6/IPHC/HC_UDP
1710  * dispatchs/headers and IPv6 payload (with len multiple of 8 bytes).
1711  * The subsequent fragments contain the FRAGN dispatch and more of the
1712  * IPv6 payload (still multiple of 8 bytes, except for the last fragment)
1713  */
1714  /* Total IPv6 payload */
1715  int total_payload = (uip_len - uncomp_hdr_len);
1716  /* IPv6 payload that goes to first fragment */
1717  int frag1_payload = (mac_max_payload - packetbuf_hdr_len - SICSLOWPAN_FRAG1_HDR_LEN) & 0xfffffff8;
1718  /* max IPv6 payload in each FRAGN. Must be multiple of 8 bytes */
1719  int fragn_max_payload = (mac_max_payload - SICSLOWPAN_FRAGN_HDR_LEN) & 0xfffffff8;
1720  /* max IPv6 payload in the last fragment. Needs not be multiple of 8 bytes */
1721  int last_fragn_max_payload = mac_max_payload - SICSLOWPAN_FRAGN_HDR_LEN;
1722  /* sum of all IPv6 payload that goes to non-first and non-last fragments */
1723  int middle_fragn_total_payload = MAX(total_payload - frag1_payload - last_fragn_max_payload, 0);
1724  /* Ceiling of: 2 + middle_fragn_total_payload / fragn_max_payload */
1725  int fragment_count = 2;
1726  if(middle_fragn_total_payload > 0) {
1727  fragment_count += 1 + (middle_fragn_total_payload - 1) / fragn_max_payload;
1728  }
1729 
1730  int freebuf = queuebuf_numfree() - 1;
1731  LOG_INFO("output: fragmentation needed, fragments: %u, free queuebufs: %u\n",
1732  fragment_count, freebuf);
1733 
1734  if(freebuf < fragment_count) {
1735  LOG_WARN("output: dropping packet, not enough free bufs (needed: %u, free: %u)\n",
1736  fragment_count, freebuf);
1737  return 0;
1738  }
1739 
1740  if(frag1_payload < 0) {
1741  /* The current implementation requires that all headers fit in the first
1742  * fragment. Here is a corner case where the header did fit packetbuf
1743  * but do no longer fit after truncating for a length multiple of 8. */
1744  LOG_WARN("output: compressed header does not fit first fragment\n");
1745  return 0;
1746  }
1747 
1748  /* Reset last tx status -- MAC layers most often call packet_sent asynchrously */
1750  /* Update fragment tag */
1751  frag_tag = my_tag++;
1752 
1753  /* Move IPHC/IPv6 header to make room for FRAG1 header */
1754  memmove(packetbuf_ptr + SICSLOWPAN_FRAG1_HDR_LEN, packetbuf_ptr, packetbuf_hdr_len);
1755  packetbuf_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN;
1756 
1757  /* Set FRAG1 header */
1758  SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE,
1759  ((SICSLOWPAN_DISPATCH_FRAG1 << 8) | uip_len));
1760  SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG, frag_tag);
1761 
1762  /* Set frag1 payload len. Was already caulcated earlier as frag1_payload */
1763  packetbuf_payload_len = frag1_payload;
1764 
1765  /* Copy payload from uIP and send fragment */
1766  /* Send fragment */
1767  LOG_INFO("output: fragment %d/%d (tag %d, payload %d)\n",
1768  curr_frag + 1, fragment_count,
1769  frag_tag, packetbuf_payload_len);
1770  if(fragment_copy_payload_and_send(uncomp_hdr_len, &dest) == 0) {
1771  return 0;
1772  }
1773 
1774  /* Now prepare for subsequent fragments. */
1775 
1776  /* FRAGN header: tag was already set at FRAG1. Now set dispatch for all FRAGN */
1777  packetbuf_hdr_len = SICSLOWPAN_FRAGN_HDR_LEN;
1778  SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE,
1779  ((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len));
1780 
1781  /* Keep track of the total length of data sent */
1782  processed_ip_out_len = uncomp_hdr_len + packetbuf_payload_len;
1783 
1784  /* Create and send subsequent fragments. */
1785  while(processed_ip_out_len < uip_len) {
1786  curr_frag++;
1787  /* FRAGN header: set offset for this fragment */
1788  PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET] = processed_ip_out_len >> 3;
1789 
1790  /* Calculate fragment len */
1791  if(uip_len - processed_ip_out_len > last_fragn_max_payload) {
1792  /* Not last fragment, send max FRAGN payload */
1793  packetbuf_payload_len = fragn_max_payload;
1794  } else {
1795  /* last fragment */
1796  packetbuf_payload_len = uip_len - processed_ip_out_len;
1797  }
1798 
1799  /* Copy payload from uIP and send fragment */
1800  /* Send fragment */
1801  LOG_INFO("output: fragment %d/%d (tag %d, payload %d, offset %d)\n",
1802  curr_frag + 1, fragment_count,
1803  frag_tag, packetbuf_payload_len, processed_ip_out_len);
1804  if(fragment_copy_payload_and_send(processed_ip_out_len, &dest) == 0) {
1805  return 0;
1806  }
1807 
1808  processed_ip_out_len += packetbuf_payload_len;
1809  }
1810 #else /* SICSLOWPAN_CONF_FRAG */
1811  LOG_ERR("output: Packet too large to be sent without fragmentation support; dropping packet\n");
1812  return 0;
1813 #endif /* SICSLOWPAN_CONF_FRAG */
1814  } else {
1815  /*
1816  * The packet does not need to be fragmented
1817  * copy "payload" and send
1818  */
1819 
1820  if(uip_len < uncomp_hdr_len) {
1821  LOG_ERR("output: uip_len is smaller than uncomp_hdr_len (%d < %d)",
1822  (int)uip_len, (int)uncomp_hdr_len);
1823  return 0;
1824  }
1825 
1829  send_packet(&dest);
1830  }
1831  return 1;
1832 }
1833 
1834 /*--------------------------------------------------------------------*/
1835 /** \brief Process a received 6lowpan packet.
1836  *
1837  * The 6lowpan packet is put in packetbuf by the MAC. If its a frag1 or
1838  * a non-fragmented packet we first uncompress the IP header. The
1839  * 6lowpan payload and possibly the uncompressed IP header are then
1840  * copied in siclowpan_buf. If the IP packet is complete it is copied
1841  * to uip_buf and the IP layer is called.
1842  *
1843  * \note We do not check for overlapping sicslowpan fragments
1844  * (it is a SHALL in the RFC 4944 and should never happen)
1845  */
1846 static void
1847 input(void)
1848 {
1849  /* size of the IP packet (read from fragment) */
1850  uint16_t frag_size = 0;
1851  /* offset of the fragment in the IP packet */
1852  uint8_t frag_offset = 0;
1853  uint8_t *buffer;
1854  uint16_t buffer_size;
1855 
1856 #if SICSLOWPAN_CONF_FRAG
1857  uint8_t is_fragment = 0;
1858  int8_t frag_context = 0;
1859 
1860  /* tag of the fragment */
1861  uint16_t frag_tag = 0;
1862  uint8_t first_fragment = 0, last_fragment = 0;
1863 #endif /*SICSLOWPAN_CONF_FRAG*/
1864 
1865  /* Update link statistics */
1866  link_stats_input_callback(packetbuf_addr(PACKETBUF_ADDR_SENDER));
1867 
1868  /* init */
1869  uncomp_hdr_len = 0;
1870  packetbuf_hdr_len = 0;
1871 
1872  /* The MAC puts the 15.4 payload inside the packetbuf data buffer */
1874 
1875  if(packetbuf_datalen() == 0) {
1876  LOG_WARN("input: empty packet\n");
1877  return;
1878  }
1879 
1880  /* Clear uipbuf and set default attributes */
1881  uipbuf_clear();
1882 
1883  /* This is default uip_buf since we assume that this is not fragmented */
1884  buffer = (uint8_t *)UIP_IP_BUF;
1885  buffer_size = UIP_BUFSIZE;
1886 
1887  /* Save the RSSI and LQI of the incoming packet in case the upper layer will
1888  want to query us for it later. */
1889  last_rssi = (signed short)packetbuf_attr(PACKETBUF_ATTR_RSSI);
1890  uipbuf_set_attr(UIPBUF_ATTR_RSSI, packetbuf_attr(PACKETBUF_ATTR_RSSI));
1891  uipbuf_set_attr(UIPBUF_ATTR_LINK_QUALITY, packetbuf_attr(PACKETBUF_ATTR_LINK_QUALITY));
1892 
1893 
1894 #if SICSLOWPAN_CONF_FRAG
1895 
1896  /*
1897  * Since we don't support the mesh and broadcast header, the first header
1898  * we look for is the fragmentation header
1899  */
1900  switch((GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) >> 8) & SICSLOWPAN_DISPATCH_FRAG_MASK) {
1901  case SICSLOWPAN_DISPATCH_FRAG1:
1902  frag_offset = 0;
1903  frag_size = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) & 0x07ff;
1904  frag_tag = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG);
1905  packetbuf_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN;
1906  first_fragment = 1;
1907  is_fragment = 1;
1908 
1909  LOG_INFO("input: received first element of a fragmented packet (tag %d, len %d)\n",
1910  frag_tag, frag_size);
1911 
1912  /* Add the fragment to the fragmentation context */
1913  frag_context = add_fragment(frag_tag, frag_size, frag_offset);
1914 
1915  if(frag_context == -1) {
1916  LOG_ERR("input: failed to allocate new reassembly context\n");
1917  return;
1918  }
1919 
1920  buffer = frag_info[frag_context].first_frag;
1921  buffer_size = SICSLOWPAN_FIRST_FRAGMENT_SIZE;
1922  break;
1923  case SICSLOWPAN_DISPATCH_FRAGN:
1924  /*
1925  * set offset, tag, size
1926  * Offset is in units of 8 bytes
1927  */
1928  frag_offset = PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET];
1929  frag_tag = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG);
1930  frag_size = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) & 0x07ff;
1931  packetbuf_hdr_len += SICSLOWPAN_FRAGN_HDR_LEN;
1932 
1933  /* Add the fragment to the fragmentation context (this will also
1934  copy the payload) */
1935  frag_context = add_fragment(frag_tag, frag_size, frag_offset);
1936 
1937  if(frag_context == -1) {
1938  LOG_ERR("input: reassembly context not found (tag %d)\n", frag_tag);
1939  return;
1940  }
1941 
1942  /* Ok - add_fragment will store the fragment automatically - so
1943  we should not store more */
1944  buffer = NULL;
1945 
1946  if(frag_info[frag_context].reassembled_len >= frag_size) {
1947  last_fragment = 1;
1948  }
1949  is_fragment = 1;
1950  break;
1951  default:
1952  break;
1953  }
1954 
1955  if(is_fragment && !first_fragment) {
1956  /* this is a FRAGN, skip the header compression dispatch section */
1957  goto copypayload;
1958  }
1959 #endif /* SICSLOWPAN_CONF_FRAG */
1960 
1961  /* First, process 6LoRH headers */
1962  curr_page = 0;
1964  if(curr_page == 1) {
1965  LOG_INFO("input: page 1, 6LoRH\n");
1966  digest_6lorh_hdr();
1967  } else if (curr_page > 1) {
1968  LOG_ERR("input: page %u not supported\n", curr_page);
1969  return;
1970  }
1971 
1972  /* Process next dispatch and headers */
1973  if(SICSLOWPAN_COMPRESSION > SICSLOWPAN_COMPRESSION_IPV6 &&
1974  (PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] & SICSLOWPAN_DISPATCH_IPHC_MASK) == SICSLOWPAN_DISPATCH_IPHC) {
1975  LOG_DBG("uncompression: IPHC dispatch\n");
1976  if(uncompress_hdr_iphc(buffer, buffer_size, frag_size) == false) {
1977  LOG_ERR("input: failed to decompress IPHC packet\n");
1978  return;
1979  }
1980  } else if(PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] == SICSLOWPAN_DISPATCH_IPV6) {
1981  LOG_DBG("uncompression: IPV6 dispatch\n");
1982  packetbuf_hdr_len += SICSLOWPAN_IPV6_HDR_LEN;
1983 
1984  /* Put uncompressed IP header in sicslowpan_buf. */
1985  memcpy(buffer, packetbuf_ptr + packetbuf_hdr_len, UIP_IPH_LEN);
1986 
1987  /* Update uncomp_hdr_len and packetbuf_hdr_len. */
1988  packetbuf_hdr_len += UIP_IPH_LEN;
1989  uncomp_hdr_len += UIP_IPH_LEN;
1990  } else {
1991  LOG_ERR("uncompression: unknown dispatch: 0x%02x, or IPHC disabled\n",
1992  PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] & SICSLOWPAN_DISPATCH_IPHC_MASK);
1993  return;
1994  }
1995 
1996 #if SICSLOWPAN_CONF_FRAG
1997  copypayload:
1998 #endif /*SICSLOWPAN_CONF_FRAG*/
1999  /*
2000  * copy "payload" from the packetbuf buffer to the sicslowpan_buf
2001  * if this is a first fragment or not fragmented packet,
2002  * we have already copied the compressed headers, uncomp_hdr_len
2003  * and packetbuf_hdr_len are non 0, frag_offset is.
2004  * If this is a subsequent fragment, this is the contrary.
2005  */
2007  LOG_ERR("input: packet dropped due to header > total packet\n");
2008  return;
2009  }
2011 
2012 #if SICSLOWPAN_CONF_FRAG
2013  if(is_fragment) {
2014  LOG_INFO("input: fragment (tag %d, payload %d, offset %d) -- %u %u\n",
2015  frag_tag, packetbuf_payload_len, frag_offset << 3, packetbuf_datalen(), packetbuf_hdr_len);
2016  }
2017 #endif /*SICSLOWPAN_CONF_FRAG*/
2018 
2019  /* Sanity-check size of incoming packet to avoid buffer overflow */
2020  {
2021  int req_size = uncomp_hdr_len + (uint16_t)(frag_offset << 3)
2023  if(req_size > sizeof(uip_buf)) {
2024 #if SICSLOWPAN_CONF_FRAG
2025  LOG_ERR(
2026  "input: packet and fragment context %u dropped, minimum required IP_BUF size: %d+%d+%d=%d (current size: %u)\n",
2027  frag_context,
2028  uncomp_hdr_len, (uint16_t)(frag_offset << 3),
2029  packetbuf_payload_len, req_size, (unsigned)sizeof(uip_buf));
2030  /* Discard all fragments for this contex, as reassembling this particular fragment would
2031  * cause an overflow in uipbuf */
2032  clear_fragments(frag_context);
2033 #endif /* SICSLOWPAN_CONF_FRAG */
2034  return;
2035  }
2036  }
2037 
2038  /* copy the payload if buffer is non-null - which is only the case with first fragment
2039  or packets that are non fragmented */
2040  if(buffer != NULL) {
2041  memcpy((uint8_t *)buffer + uncomp_hdr_len, packetbuf_ptr + packetbuf_hdr_len, packetbuf_payload_len);
2042  }
2043 
2044  /* update processed_ip_in_len if fragment, sicslowpan_len otherwise */
2045 
2046 #if SICSLOWPAN_CONF_FRAG
2047  if(frag_size > 0) {
2048  /* Add the size of the header only for the first fragment. */
2049  if(first_fragment != 0) {
2050  frag_info[frag_context].reassembled_len = uncomp_hdr_len + packetbuf_payload_len;
2051  frag_info[frag_context].first_frag_len = uncomp_hdr_len + packetbuf_payload_len;
2052  }
2053  /* For the last fragment, we are OK if there is extrenous bytes at
2054  the end of the packet. */
2055  if(last_fragment != 0) {
2056  frag_info[frag_context].reassembled_len = frag_size;
2057  /* copy to uip */
2058  if(!copy_frags2uip(frag_context)) {
2059  return;
2060  }
2061  }
2062  }
2063 
2064  /*
2065  * If we have a full IP packet in sicslowpan_buf, deliver it to
2066  * the IP stack
2067  */
2068  if(!is_fragment || last_fragment) {
2069  /* packet is in uip already - just set length */
2070  if(is_fragment != 0 && last_fragment != 0) {
2071  uip_len = frag_size;
2072  } else {
2074  }
2075 #else
2077 #endif /* SICSLOWPAN_CONF_FRAG */
2078  LOG_INFO("input: received IPv6 packet with len %d\n",
2079  uip_len);
2080 
2081  if(LOG_DBG_ENABLED) {
2082  uint16_t ndx;
2083  LOG_DBG("uncompression: after (%u):", UIP_IP_BUF->len[1]);
2084  for (ndx = 0; ndx < UIP_IP_BUF->len[1] + 40; ndx++) {
2085  uint8_t data = ((uint8_t *) (UIP_IP_BUF))[ndx];
2086  LOG_DBG_("%02x", data);
2087  }
2088  LOG_DBG_("\n");
2089  }
2090 
2091  /* if callback is set then set attributes and call */
2092  if(callback) {
2093  set_packet_attrs();
2094  callback->input_callback();
2095  }
2096 
2097 #if LLSEC802154_USES_AUX_HEADER
2098  /*
2099  * Assuming that the last packet in packetbuf is containing
2100  * the LLSEC state so that it can be copied to uipbuf.
2101  */
2102  uipbuf_set_attr(UIPBUF_ATTR_LLSEC_LEVEL,
2103  packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL));
2104 #if LLSEC802154_USES_EXPLICIT_KEYS
2105  uipbuf_set_attr(UIPBUF_ATTR_LLSEC_KEY_ID,
2106  packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX));
2107 #endif /* LLSEC802154_USES_EXPLICIT_KEYS */
2108 #endif /* LLSEC802154_USES_AUX_HEADER */
2109 
2110  tcpip_input();
2111 #if SICSLOWPAN_CONF_FRAG
2112  }
2113 #endif /* SICSLOWPAN_CONF_FRAG */
2114 }
2115 /** @} */
2116 
2117 /*--------------------------------------------------------------------*/
2118 /* \brief 6lowpan init function (called by the MAC layer) */
2119 /*--------------------------------------------------------------------*/
2120 void
2121 sicslowpan_init(void)
2122 {
2123 
2124 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPHC
2125 /* Preinitialize any address contexts for better header compression
2126  * (Saves up to 13 bytes per 6lowpan packet)
2127  * The platform contiki-conf.h file can override this using e.g.
2128  * #define SICSLOWPAN_CONF_ADDR_CONTEXT_0 {addr_contexts[0].prefix[0]=0xbb;addr_contexts[0].prefix[1]=0xbb;}
2129  */
2130 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
2131  addr_contexts[0].used = 1;
2132  addr_contexts[0].number = 0;
2133 #ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_0
2134  SICSLOWPAN_CONF_ADDR_CONTEXT_0;
2135 #else
2136  addr_contexts[0].prefix[0] = UIP_DS6_DEFAULT_PREFIX_0;
2137  addr_contexts[0].prefix[1] = UIP_DS6_DEFAULT_PREFIX_1;
2138 #endif
2139 #endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */
2140 
2141 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 1
2142  {
2143  int i;
2144  for(i = 1; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) {
2145 #ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_1
2146  if (i==1) {
2147  addr_contexts[1].used = 1;
2148  addr_contexts[1].number = 1;
2149  SICSLOWPAN_CONF_ADDR_CONTEXT_1;
2150 #ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_2
2151  } else if (i==2) {
2152  addr_contexts[2].used = 1;
2153  addr_contexts[2].number = 2;
2154  SICSLOWPAN_CONF_ADDR_CONTEXT_2;
2155 #endif
2156  } else {
2157  addr_contexts[i].used = 0;
2158  }
2159 #else
2160  addr_contexts[i].used = 0;
2161 #endif /* SICSLOWPAN_CONF_ADDR_CONTEXT_1 */
2162  }
2163  }
2164 #endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 1 */
2165 
2166 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPHC */
2167 }
2168 /*--------------------------------------------------------------------*/
2169 int
2170 sicslowpan_get_last_rssi(void)
2171 {
2172  return last_rssi;
2173 }
2174 /*--------------------------------------------------------------------*/
2175 const struct network_driver sicslowpan_driver = {
2176  "sicslowpan",
2177  sicslowpan_init,
2178  input,
2179  output
2180 };
2181 /*--------------------------------------------------------------------*/
2182 /** @} */
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:116
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
Definition: packetbuf.c:143
The MAC layer transmission could not be performed because of a fatal error.
Definition: mac.h:101
#define UIP_IP_BUF
Direct access to IPv6 header.
Definition: uip.h:71
static uint8_t packetbuf_hdr_len
packetbuf_hdr_len is the total length of (the processed) 6lowpan headers (fragment headers...
Definition: sicslowpan.c:164
uip_lladdr_t uip_lladdr
Host L2 address.
Definition: uip6.c:107
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
Definition: timer.c:64
Header for the Contiki/uIP interface.
static void digest_paging_dispatch(void)
Digest 6lorh headers before IPHC.
Definition: sicslowpan.c:1450
static volatile uint64_t count
Num.
Definition: clock.c:50
void packetbuf_clear(void)
Clear and reset the packetbuf.
Definition: packetbuf.c:75
uint16_t uip_len
The length of the packet in the uip_buf buffer.
Definition: uip6.c:159
static int packetbuf_payload_len
The length of the payload in the Packetbuf buffer.
Definition: sicslowpan.c:172
#define UIP_ICMP_BUF
Direct access to ICMP, UDP, and TCP headers and payload, with implicit ext header offset (global uip_...
Definition: uip.h:77
void(* link_callback)(const linkaddr_t *addr, int status, int numtx)
Called by lower layers after every packet transmission.
Definition: routing.h:170
static void send_packet(linkaddr_t *dest)
This function is called by the 6lowpan code to send out a packet.
Definition: sicslowpan.c:1537
#define UIP_PROTO_HBHO
extension headers types
Definition: uip.h:1764
#define UIP_BUFSIZE
The size of the uIP packet buffer.
Definition: uipopt.h:134
static void digest_6lorh_hdr(void)
Digest 6lorh headers before IPHC.
Definition: sicslowpan.c:1464
static void packet_sent(void *ptr, int status, int transmissions)
Callback function for the MAC packet sent callback.
Definition: sicslowpan.c:1506
void uip_ds6_link_callback(int status, int numtx)
The callback function to update link-layer stats in a neighbor cache.
Definition: uip-ds6-nbr.c:534
void uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
set the last 64 bits of an IP address based on the MAC address
Definition: uip-ds6.c:576
A timer.
Definition: timer.h:82
const linkaddr_t linkaddr_null
The null link-layer address.
static uint8_t output(const linkaddr_t *localdest)
Take an IP packet and format it to be sent on an 802.15.4 network using 6lowpan.
Definition: sicslowpan.c:1610
Header file for IPv6-related data structures.
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
Definition: packetbuf.c:155
Configuration options for uIP.
#define sicslowpan_is_iid_16_bit_compressable(a)
check whether we can compress the IID in address &#39;a&#39; to 16 bits.
Definition: sicslowpan.h:257
static int mac_max_payload
mac_max_payload is the maimum payload space on the MAC frame.
Definition: sicslowpan.c:183
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
#define uip_is_addr_mac_addr_based(a, m)
was addr (a) forged based on the mac address m a type is uip_ipaddr_t m type is uiplladdr_t ...
Definition: uip.h:1934
static void add_paging_dispatch(uint8_t page)
Adds Paging dispatch byte.
Definition: sicslowpan.c:1428
Header file for the Packet queue buffer management
#define SICSLOWPAN_COMPRESSION
Do we compress the IP header or not.
Definition: uipopt.h:543
static uint8_t uncomp_hdr_len
uncomp_hdr_len is the length of the headers before compression (if HC2 is used this includes the UDP ...
Definition: sicslowpan.c:178
static int last_tx_status
the result of the last transmitted fragment
Definition: sicslowpan.c:193
The structure of a network driver in Contiki.
Definition: netstack.h:117
static uint8_t curr_page
The current page (RFC 4944)
Definition: sicslowpan.c:188
#define SICSLOWPAN_REASS_MAXAGE
Timeout for packet reassembly at the 6lowpan layer (should be < 60s)
Definition: uipopt.h:536
static uint8_t * hc06_ptr
pointer to the byte where to write next inline field.
Definition: sicslowpan.c:519
#define uip_is_addr_unspecified(a)
Is IPv6 address a the unspecified address a is of type uip_ipaddr_t.
Definition: uip.h:1836
Routing driver header file
#define uip_buf
Macro to access uip_aligned_buf as an array of bytes.
Definition: uip.h:510
int timer_expired(struct timer *t)
Check if a timer has expired.
Definition: timer.c:123
The header for fragments.
Definition: sicslowpan.h:239
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a link-layer address.
Definition: linkaddr.c:63
#define uip_is_addr_mcast(a)
is address a multicast address, see RFC 4291 a is of type uip_ipaddr_t*
Definition: uip.h:1961
#define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS
If we use IPHC compression, how many address contexts do we support.
Definition: uipopt.h:552
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
Definition: linkaddr.c:69
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
Definition: uip.h:1223
void(* send)(mac_callback_t sent_callback, void *ptr)
Send a packet from the packetbuf.
Definition: mac.h:69
Header file for the uIP TCP/IP stack.
static int compress_hdr_iphc(linkaddr_t *link_destaddr)
Compress IP/UDP header.
Definition: sicslowpan.c:685
static void add_6lorh_hdr(void)
Adds 6lorh headers before IPHC.
Definition: sicslowpan.c:1439
Header file for the Packet buffer (packetbuf) management
Include file for the Contiki low-layer network stack (NETSTACK)
int(* max_payload)(void)
Read out estimated max payload size based on payload in packetbuf.
Definition: mac.h:81
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition: watchdog.c:85
Header file for the 6lowpan implementation (RFC4944 and draft-hui-6lowpan-hc-01) ...
#define uip_is_addr_linklocal(a)
is addr (a) a link local unicast address, see RFC 4291 i.e.
Definition: uip.h:1877
The MAC layer transmission was OK.
Definition: mac.h:87
Header file for the logging system
static void input(void)
Process a received 6lowpan packet.
Definition: sicslowpan.c:1847
static struct sicslowpan_addr_context * addr_context_lookup_by_number(uint8_t number)
find the context with the given number
Definition: sicslowpan.c:573
static struct sicslowpan_addr_context * addr_context_lookup_by_prefix(uip_ipaddr_t *ipaddr)
find the context corresponding to prefix ipaddr
Definition: sicslowpan.c:556
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
Definition: packetbuf.c:136
void tcpip_input(void)
Deliver an incoming packet to the TCP/IP stack.
Definition: tcpip.c:445
static uint8_t * packetbuf_ptr
A pointer to the packetbuf buffer.
Definition: sicslowpan.c:157
static struct sicslowpan_addr_context * context
Addresses contexts for IPHC.
Definition: sicslowpan.c:516
The MAC layer did not get an acknowledgement for the packet.
Definition: mac.h:91
static bool uncompress_hdr_iphc(uint8_t *buf, uint16_t buf_size, uint16_t ip_len)
Uncompress IPHC (i.e., IPHC and LOWPAN_UDP) headers and put them in sicslowpan_buf.
Definition: sicslowpan.c:1073