The Pedigree Project  0.1
lowpan6.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
26 /*
27  * Copyright (c) 2015 Inico Technologies Ltd.
28  * All rights reserved.
29  *
30  * Redistribution and use in source and binary forms, with or without modification,
31  * are permitted provided that the following conditions are met:
32  *
33  * 1. Redistributions of source code must retain the above copyright notice,
34  * this list of conditions and the following disclaimer.
35  * 2. Redistributions in binary form must reproduce the above copyright notice,
36  * this list of conditions and the following disclaimer in the documentation
37  * and/or other materials provided with the distribution.
38  * 3. The name of the author may not be used to endorse or promote products
39  * derived from this software without specific prior written permission.
40  *
41  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
42  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
43  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
44  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
46  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
47  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
48  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
49  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
50  * OF SUCH DAMAGE.
51  *
52  * This file is part of the lwIP TCP/IP stack.
53  *
54  * Author: Ivan Delamer <delamer@inicotech.com>
55  *
56  *
57  * Please coordinate changes and requests with Ivan Delamer
58  * <delamer@inicotech.com>
59  */
60 
67 #include "netif/lowpan6.h"
68 
69 #if LWIP_IPV6 && LWIP_6LOWPAN
70 
71 #include "lwip/ip.h"
72 #include "lwip/pbuf.h"
73 #include "lwip/ip_addr.h"
74 #include "lwip/netif.h"
75 #include "lwip/nd6.h"
76 #include "lwip/mem.h"
77 #include "lwip/udp.h"
78 #include "lwip/tcpip.h"
79 #include "lwip/snmp.h"
80 
81 #include <string.h>
82 
83 struct ieee_802154_addr {
84  u8_t addr_len;
85  u8_t addr[8];
86 };
87 
90 struct lowpan6_reass_helper {
91  struct pbuf *pbuf;
92  struct lowpan6_reass_helper *next_packet;
93  u8_t timer;
94  struct ieee_802154_addr sender_addr;
95  u16_t datagram_size;
96  u16_t datagram_tag;
97 };
98 
99 static struct lowpan6_reass_helper * reass_list;
100 
101 #if LWIP_6LOWPAN_NUM_CONTEXTS > 0
102 static ip6_addr_t lowpan6_context[LWIP_6LOWPAN_NUM_CONTEXTS];
103 #endif
104 
105 static u16_t ieee_802154_pan_id;
106 
107 static const struct ieee_802154_addr ieee_802154_broadcast = {2, {0xff, 0xff}};
108 
109 #if LWIP_6LOWPAN_INFER_SHORT_ADDRESS
110 static struct ieee_802154_addr short_mac_addr = {2, {0,0}};
111 #endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */
112 
113 static err_t dequeue_datagram(struct lowpan6_reass_helper *lrh);
114 
120 void
121 lowpan6_tmr(void)
122 {
123  struct lowpan6_reass_helper *lrh, *lrh_temp;
124 
125  lrh = reass_list;
126  while (lrh != NULL) {
127  lrh_temp = lrh->next_packet;
128  if ((--lrh->timer) == 0) {
129  dequeue_datagram(lrh);
130  pbuf_free(lrh->pbuf);
131  mem_free(lrh);
132  }
133  lrh = lrh_temp;
134  }
135 }
136 
140 static err_t
141 dequeue_datagram(struct lowpan6_reass_helper *lrh)
142 {
143  struct lowpan6_reass_helper *lrh_temp;
144 
145  if (reass_list == lrh) {
146  reass_list = reass_list->next_packet;
147  } else {
148  lrh_temp = reass_list;
149  while (lrh_temp != NULL) {
150  if (lrh_temp->next_packet == lrh) {
151  lrh_temp->next_packet = lrh->next_packet;
152  break;
153  }
154  lrh_temp = lrh_temp->next_packet;
155  }
156  }
157 
158  return ERR_OK;
159 }
160 
161 static s8_t
162 lowpan6_context_lookup(const ip6_addr_t *ip6addr)
163 {
164  s8_t i;
165 
166  for (i = 0; i < LWIP_6LOWPAN_NUM_CONTEXTS; i++) {
167  if (ip6_addr_netcmp(&lowpan6_context[i], ip6addr)) {
168  return i;
169  }
170  }
171 
172  return -1;
173 }
174 
175 /* Determine compression mode for unicast address. */
176 static s8_t
177 lowpan6_get_address_mode(const ip6_addr_t *ip6addr, const struct ieee_802154_addr *mac_addr)
178 {
179  if (mac_addr->addr_len == 2) {
180  if ((ip6addr->addr[2] == (u32_t)PP_HTONL(0x000000ff)) &&
181  ((ip6addr->addr[3] & PP_HTONL(0xffff0000)) == PP_NTOHL(0xfe000000))) {
182  if ((ip6addr->addr[3] & PP_HTONL(0x0000ffff)) == lwip_ntohl((mac_addr->addr[0] << 8) | mac_addr->addr[1])) {
183  return 3;
184  }
185  }
186  } else if (mac_addr->addr_len == 8) {
187  if ((ip6addr->addr[2] == lwip_ntohl(((mac_addr->addr[0] ^ 2) << 24) | (mac_addr->addr[1] << 16) | mac_addr->addr[2] << 8 | mac_addr->addr[3])) &&
188  (ip6addr->addr[3] == lwip_ntohl((mac_addr->addr[4] << 24) | (mac_addr->addr[5] << 16) | mac_addr->addr[6] << 8 | mac_addr->addr[7]))) {
189  return 3;
190  }
191  }
192 
193  if ((ip6addr->addr[2] == PP_HTONL(0x000000ffUL)) &&
194  ((ip6addr->addr[3] & PP_HTONL(0xffff0000)) == PP_NTOHL(0xfe000000UL))) {
195  return 2;
196  }
197 
198  return 1;
199 }
200 
201 /* Determine compression mode for multicast address. */
202 static s8_t
203 lowpan6_get_address_mode_mc(const ip6_addr_t *ip6addr)
204 {
205  if ((ip6addr->addr[0] == PP_HTONL(0xff020000)) &&
206  (ip6addr->addr[1] == 0) &&
207  (ip6addr->addr[2] == 0) &&
208  ((ip6addr->addr[3] & PP_HTONL(0xffffff00)) == 0)) {
209  return 3;
210  } else if (((ip6addr->addr[0] & PP_HTONL(0xff00ffff)) == PP_HTONL(0xff000000)) &&
211  (ip6addr->addr[1] == 0)) {
212  if ((ip6addr->addr[2] == 0) &&
213  ((ip6addr->addr[3] & PP_HTONL(0xff000000)) == 0)) {
214  return 2;
215  } else if ((ip6addr->addr[2] & PP_HTONL(0xffffff00)) == 0) {
216  return 1;
217  }
218  }
219 
220  return 0;
221 }
222 
223 /*
224  * Encapsulates data into IEEE 802.15.4 frames.
225  * Fragments an IPv6 datagram into 6LowPAN units, which fit into IEEE 802.15.4 frames.
226  * If configured, will compress IPv6 and or UDP headers.
227  * */
228 static err_t
229 lowpan6_frag(struct netif *netif, struct pbuf *p, const struct ieee_802154_addr *src, const struct ieee_802154_addr *dst)
230 {
231  struct pbuf * p_frag;
232  u16_t frag_len, remaining_len;
233  u8_t * buffer;
234  u8_t ieee_header_len;
235  u8_t lowpan6_header_len;
236  s8_t i;
237  static u8_t frame_seq_num;
238  static u16_t datagram_tag;
239  u16_t datagram_offset;
240  err_t err = ERR_IF;
241 
242  /* We'll use a dedicated pbuf for building 6LowPAN fragments. */
243  p_frag = pbuf_alloc(PBUF_RAW, 127, PBUF_RAM);
244  if (p_frag == NULL) {
245  MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
246  return ERR_MEM;
247  }
248 
249  /* Write IEEE 802.15.4 header. */
250  buffer = (u8_t*)p_frag->payload;
251  ieee_header_len = 0;
252  if (dst == &ieee_802154_broadcast) {
253  buffer[ieee_header_len++] = 0x01; /* data packet, no ack required. */
254  } else {
255  buffer[ieee_header_len++] = 0x21; /* data packet, ack required. */
256  }
257  buffer[ieee_header_len] = (0x00 << 4); /* 2003 frame version */
258  buffer[ieee_header_len] |= (dst->addr_len == 2) ? (0x02 << 2) : (0x03 << 2); /* destination addressing mode */
259  buffer[ieee_header_len] |= (src->addr_len == 2) ? (0x02 << 6) : (0x03 << 6); /* source addressing mode */
260  ieee_header_len++;
261  buffer[ieee_header_len++] = frame_seq_num++;
262 
263  buffer[ieee_header_len++] = ieee_802154_pan_id & 0xff; /* pan id */
264  buffer[ieee_header_len++] = (ieee_802154_pan_id >> 8) & 0xff; /* pan id */
265  i = dst->addr_len;
266  while (i-- > 0) {
267  buffer[ieee_header_len++] = dst->addr[i];
268  }
269 
270  buffer[ieee_header_len++] = ieee_802154_pan_id & 0xff; /* pan id */
271  buffer[ieee_header_len++] = (ieee_802154_pan_id >> 8) & 0xff; /* pan id */
272  i = src->addr_len;
273  while (i-- > 0) {
274  buffer[ieee_header_len++] = src->addr[i];
275  }
276 
277 #if LWIP_6LOWPAN_IPHC
278  /* Perform 6LowPAN IPv6 header compression according to RFC 6282 */
279  {
280  struct ip6_hdr *ip6hdr;
281 
282  /* Point to ip6 header and align copies of src/dest addresses. */
283  ip6hdr = (struct ip6_hdr *)p->payload;
284  ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest);
285  ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src);
286 
287  /* Basic length of 6LowPAN header, set dispatch and clear fields. */
288  lowpan6_header_len = 2;
289  buffer[ieee_header_len] = 0x60;
290  buffer[ieee_header_len + 1] = 0;
291 
292  /* Determine whether there will be a Context Identifier Extension byte or not.
293  * If so, set it already. */
294 #if LWIP_6LOWPAN_NUM_CONTEXTS > 0
295  buffer[ieee_header_len + 2] = 0;
296 
297  i = lowpan6_context_lookup(ip_2_ip6(&ip_data.current_iphdr_src));
298  if (i >= 0) {
299  /* Stateful source address compression. */
300  buffer[ieee_header_len + 1] |= 0x40;
301  buffer[ieee_header_len + 2] |= (i & 0x0f) << 4;
302  }
303 
304  i = lowpan6_context_lookup(ip_2_ip6(&ip_data.current_iphdr_dest));
305  if (i >= 0) {
306  /* Stateful destination address compression. */
307  buffer[ieee_header_len + 1] |= 0x04;
308  buffer[ieee_header_len + 2] |= i & 0x0f;
309  }
310 
311  if (buffer[ieee_header_len + 2] != 0x00) {
312  /* Context identifier extension byte is appended. */
313  buffer[ieee_header_len + 1] |= 0x80;
314  lowpan6_header_len++;
315  }
316 #endif /* LWIP_6LOWPAN_NUM_CONTEXTS > 0 */
317 
318  /* Determine TF field: Traffic Class, Flow Label */
319  if (IP6H_FL(ip6hdr) == 0) {
320  /* Flow label is elided. */
321  buffer[ieee_header_len] |= 0x10;
322  if (IP6H_TC(ip6hdr) == 0) {
323  /* Traffic class (ECN+DSCP) elided too. */
324  buffer[ieee_header_len] |= 0x08;
325  } else {
326  /* Traffic class (ECN+DSCP) appended. */
327  buffer[ieee_header_len + lowpan6_header_len++] = IP6H_TC(ip6hdr);
328  }
329  } else {
330  if (((IP6H_TC(ip6hdr) & 0x3f) == 0)) {
331  /* DSCP portion of Traffic Class is elided, ECN and FL are appended (3 bytes) */
332  buffer[ieee_header_len] |= 0x08;
333 
334  buffer[ieee_header_len + lowpan6_header_len] = IP6H_TC(ip6hdr) & 0xc0;
335  buffer[ieee_header_len + lowpan6_header_len++] |= (IP6H_FL(ip6hdr) >> 16) & 0x0f;
336  buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 8) & 0xff;
337  buffer[ieee_header_len + lowpan6_header_len++] = IP6H_FL(ip6hdr) & 0xff;
338  } else {
339  /* Traffic class and flow label are appended (4 bytes) */
340  buffer[ieee_header_len + lowpan6_header_len++] = IP6H_TC(ip6hdr);
341  buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 16) & 0x0f;
342  buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 8) & 0xff;
343  buffer[ieee_header_len + lowpan6_header_len++] = IP6H_FL(ip6hdr) & 0xff;
344  }
345  }
346 
347  /* Compress NH?
348  * Only if UDP for now. @todo support other NH compression. */
349  if (IP6H_NEXTH(ip6hdr) == IP6_NEXTH_UDP) {
350  buffer[ieee_header_len] |= 0x04;
351  } else {
352  /* append nexth. */
353  buffer[ieee_header_len + lowpan6_header_len++] = IP6H_NEXTH(ip6hdr);
354  }
355 
356  /* Compress hop limit? */
357  if (IP6H_HOPLIM(ip6hdr) == 255) {
358  buffer[ieee_header_len] |= 0x03;
359  } else if (IP6H_HOPLIM(ip6hdr) == 64) {
360  buffer[ieee_header_len] |= 0x02;
361  } else if (IP6H_HOPLIM(ip6hdr) == 1) {
362  buffer[ieee_header_len] |= 0x01;
363  } else {
364  /* append hop limit */
365  buffer[ieee_header_len + lowpan6_header_len++] = IP6H_HOPLIM(ip6hdr);
366  }
367 
368  /* Compress source address */
369  if (((buffer[ieee_header_len + 1] & 0x40) != 0) ||
370  (ip6_addr_islinklocal(ip_2_ip6(&ip_data.current_iphdr_src)))) {
371  /* Context-based or link-local source address compression. */
372  i = lowpan6_get_address_mode(ip_2_ip6(&ip_data.current_iphdr_src), src);
373  buffer[ieee_header_len + 1] |= (i & 0x03) << 4;
374  if (i == 1) {
375  MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 16, 8);
376  lowpan6_header_len += 8;
377  } else if (i == 2) {
378  MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 22, 2);
379  lowpan6_header_len += 2;
380  }
381  } else if (ip6_addr_isany(ip_2_ip6(&ip_data.current_iphdr_src))) {
382  /* Special case: mark SAC and leave SAM=0 */
383  buffer[ieee_header_len + 1] |= 0x40;
384  } else {
385  /* Append full address. */
386  MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 8, 16);
387  lowpan6_header_len += 16;
388  }
389 
390  /* Compress destination address */
391  if (ip6_addr_ismulticast(ip_2_ip6(&ip_data.current_iphdr_dest))) {
392  /* @todo support stateful multicast address compression */
393 
394  buffer[ieee_header_len + 1] |= 0x08;
395 
396  i = lowpan6_get_address_mode_mc(ip_2_ip6(&ip_data.current_iphdr_dest));
397  buffer[ieee_header_len + 1] |= i & 0x03;
398  if (i == 0) {
399  MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 24, 16);
400  lowpan6_header_len += 16;
401  } else if (i == 1) {
402  buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[25];
403  MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 35, 5);
404  lowpan6_header_len += 5;
405  } else if (i == 2) {
406  buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[25];
407  MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 37, 3);
408  lowpan6_header_len += 3;
409  } else if (i == 3) {
410  buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[39];
411  }
412  } else if (((buffer[ieee_header_len + 1] & 0x04) != 0) ||
413  (ip6_addr_islinklocal(ip_2_ip6(&ip_data.current_iphdr_dest)))) {
414  /* Context-based or link-local destination address compression. */
415  i = lowpan6_get_address_mode(ip_2_ip6(&ip_data.current_iphdr_dest), dst);
416  buffer[ieee_header_len + 1] |= i & 0x03;
417  if (i == 1) {
418  MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 32, 8);
419  lowpan6_header_len += 8;
420  } else if (i == 2) {
421  MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 38, 2);
422  lowpan6_header_len += 2;
423  }
424  } else {
425  /* Append full address. */
426  MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 24, 16);
427  lowpan6_header_len += 16;
428  }
429 
430  /* Move to payload. */
431  pbuf_header(p, -IP6_HLEN);
432 
433  /* Compress UDP header? */
434  if (IP6H_NEXTH(ip6hdr) == IP6_NEXTH_UDP) {
435  /* @todo support optional checksum compression */
436 
437  buffer[ieee_header_len + lowpan6_header_len] = 0xf0;
438 
439  /* determine port compression mode. */
440  if ((((u8_t *)p->payload)[0] == 0xf0) && ((((u8_t *)p->payload)[1] & 0xf0) == 0xb0) &&
441  (((u8_t *)p->payload)[2] == 0xf0) && ((((u8_t *)p->payload)[3] & 0xf0) == 0xb0)) {
442  /* Compress source and dest ports. */
443  buffer[ieee_header_len + lowpan6_header_len++] |= 0x03;
444  buffer[ieee_header_len + lowpan6_header_len++] = ((((u8_t *)p->payload)[1] & 0x0f) << 4) | (((u8_t *)p->payload)[3] & 0x0f);
445  } else if (((u8_t *)p->payload)[0] == 0xf0) {
446  /* Compress source port. */
447  buffer[ieee_header_len + lowpan6_header_len++] |= 0x02;
448  buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1];
449  buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[2];
450  buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3];
451  } else if (((u8_t *)p->payload)[2] == 0xf0) {
452  /* Compress dest port. */
453  buffer[ieee_header_len + lowpan6_header_len++] |= 0x01;
454  buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[0];
455  buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1];
456  buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3];
457  } else {
458  /* append full ports. */
459  lowpan6_header_len++;
460  buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[0];
461  buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1];
462  buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[2];
463  buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3];
464  }
465 
466  /* elide length and copy checksum */
467  buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[6];
468  buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[7];
469 
470  pbuf_header(p, -UDP_HLEN);
471  }
472  }
473 
474 #else /* LWIP_6LOWPAN_HC */
475  /* Send uncompressed IPv6 header with appropriate dispatch byte. */
476  lowpan6_header_len = 1;
477  buffer[ieee_header_len] = 0x41; /* IPv6 dispatch */
478 #endif /* LWIP_6LOWPAN_HC */
479 
480  /* Calculate remaining packet length */
481  remaining_len = p->tot_len;
482 
483  if (remaining_len > 0x7FF) {
484  MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
485  /* datagram_size must fit into 11 bit */
486  pbuf_free(p_frag);
487  return ERR_VAL;
488  }
489 
490  /* Fragment, or 1 packet? */
491  if (remaining_len > (127 - ieee_header_len - lowpan6_header_len - 3)) { /* 127 - header - 1 byte dispatch - 2 bytes CRC */
492  /* We must move the 6LowPAN header to make room for the FRAG header. */
493  i = lowpan6_header_len;
494  while (i-- != 0) {
495  buffer[ieee_header_len + i + 4] = buffer[ieee_header_len + i];
496  }
497 
498  /* Now we need to fragment the packet. FRAG1 header first */
499  buffer[ieee_header_len] = 0xc0 | (((p->tot_len + lowpan6_header_len) >> 8) & 0x7);
500  buffer[ieee_header_len + 1] = (p->tot_len + lowpan6_header_len) & 0xff;
501 
502  datagram_tag++;
503  buffer[ieee_header_len + 2] = datagram_tag & 0xff;
504  buffer[ieee_header_len + 3] = (datagram_tag >> 8) & 0xff;
505 
506  /* Fragment follows. */
507  frag_len = (127 - ieee_header_len - 4 - 2) & 0xf8;
508 
509  pbuf_copy_partial(p, buffer + ieee_header_len + lowpan6_header_len + 4, frag_len - lowpan6_header_len, 0);
510  remaining_len -= frag_len - lowpan6_header_len;
511  datagram_offset = frag_len;
512 
513  /* 2 bytes CRC */
514 #if LWIP_6LOWPAN_HW_CRC
515  /* Leave blank, will be filled by HW. */
516 #else /* LWIP_6LOWPAN_HW_CRC */
517  /* @todo calculate CRC */
518 #endif /* LWIP_6LOWPAN_HW_CRC */
519 
520  /* Calculate frame length */
521  p_frag->len = p_frag->tot_len = ieee_header_len + 4 + frag_len + 2; /* add 2 dummy bytes for crc*/
522 
523  /* send the packet */
524  MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len);
525  LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p));
526  err = netif->linkoutput(netif, p_frag);
527 
528  while ((remaining_len > 0) && (err == ERR_OK)) {
529  /* new frame, new seq num for ACK */
530  buffer[2] = frame_seq_num++;
531 
532  buffer[ieee_header_len] |= 0x20; /* Change FRAG1 to FRAGN */
533 
534  buffer[ieee_header_len + 4] = (u8_t)(datagram_offset >> 3); /* datagram offset in FRAGN header (datagram_offset is max. 11 bit) */
535 
536  frag_len = (127 - ieee_header_len - 5 - 2) & 0xf8;
537  if (frag_len > remaining_len) {
538  frag_len = remaining_len;
539  }
540 
541  pbuf_copy_partial(p, buffer + ieee_header_len + 5, frag_len, p->tot_len - remaining_len);
542  remaining_len -= frag_len;
543  datagram_offset += frag_len;
544 
545  /* 2 bytes CRC */
546 #if LWIP_6LOWPAN_HW_CRC
547  /* Leave blank, will be filled by HW. */
548 #else /* LWIP_6LOWPAN_HW_CRC */
549  /* @todo calculate CRC */
550 #endif /* LWIP_6LOWPAN_HW_CRC */
551 
552  /* Calculate frame length */
553  p_frag->len = p_frag->tot_len = frag_len + 5 + ieee_header_len + 2;
554 
555  /* send the packet */
556  MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len);
557  LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p));
558  err = netif->linkoutput(netif, p_frag);
559  }
560  } else {
561  /* It fits in one frame. */
562  frag_len = remaining_len;
563 
564  /* Copy IPv6 packet */
565  pbuf_copy_partial(p, buffer + ieee_header_len + lowpan6_header_len, frag_len, 0);
566  remaining_len = 0;
567 
568  /* 2 bytes CRC */
569 #if LWIP_6LOWPAN_HW_CRC
570  /* Leave blank, will be filled by HW. */
571 #else /* LWIP_6LOWPAN_HW_CRC */
572  /* @todo calculate CRC */
573 #endif /* LWIP_6LOWPAN_HW_CRC */
574 
575  /* Calculate frame length */
576  p_frag->len = p_frag->tot_len = frag_len + lowpan6_header_len + ieee_header_len + 2;
577 
578  /* send the packet */
579  MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len);
580  LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p));
581  err = netif->linkoutput(netif, p_frag);
582  }
583 
584  pbuf_free(p_frag);
585 
586  return err;
587 }
588 
589 err_t
590 lowpan6_set_context(u8_t idx, const ip6_addr_t * context)
591 {
592  if (idx >= LWIP_6LOWPAN_NUM_CONTEXTS) {
593  return ERR_ARG;
594  }
595 
596  ip6_addr_set(&lowpan6_context[idx], context);
597 
598  return ERR_OK;
599 }
600 
601 #if LWIP_6LOWPAN_INFER_SHORT_ADDRESS
602 err_t
603 lowpan6_set_short_addr(u8_t addr_high, u8_t addr_low)
604 {
605  short_mac_addr.addr[0] = addr_high;
606  short_mac_addr.addr[1] = addr_low;
607 
608  return ERR_OK;
609 }
610 #endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */
611 
612 #if LWIP_IPV4
613 err_t
614 lowpan4_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
615 {
616  (void)netif;
617  (void)q;
618  (void)ipaddr;
619 
620  return ERR_IF;
621 }
622 #endif /* LWIP_IPV4 */
623 
635 err_t
636 lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
637 {
638  err_t result;
639  const u8_t *hwaddr;
640  struct ieee_802154_addr src, dest;
641 #if LWIP_6LOWPAN_INFER_SHORT_ADDRESS
642  ip6_addr_t ip6_src;
643  struct ip6_hdr * ip6_hdr;
644 #endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */
645 
646 #if LWIP_6LOWPAN_INFER_SHORT_ADDRESS
647  /* Check if we can compress source address (use aligned copy) */
648  ip6_hdr = (struct ip6_hdr *)q->payload;
649  ip6_addr_set(&ip6_src, &ip6_hdr->src);
650  if (lowpan6_get_address_mode(&ip6_src, &short_mac_addr) == 3) {
651  src.addr_len = 2;
652  src.addr[0] = short_mac_addr.addr[0];
653  src.addr[1] = short_mac_addr.addr[1];
654  } else
655 #endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */
656  {
657  src.addr_len = netif->hwaddr_len;
658  SMEMCPY(src.addr, netif->hwaddr, netif->hwaddr_len);
659  }
660 
661  /* multicast destination IP address? */
662  if (ip6_addr_ismulticast(ip6addr)) {
663  MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
664  /* We need to send to the broadcast address.*/
665  return lowpan6_frag(netif, q, &src, &ieee_802154_broadcast);
666  }
667 
668  /* We have a unicast destination IP address */
669  /* @todo anycast? */
670 
671 #if LWIP_6LOWPAN_INFER_SHORT_ADDRESS
672  if (src.addr_len == 2) {
673  /* If source address was compressable to short_mac_addr, and dest has same subnet and
674  * is also compressable to 2-bytes, assume we can infer dest as a short address too. */
675  dest.addr_len = 2;
676  dest.addr[0] = ((u8_t *)q->payload)[38];
677  dest.addr[1] = ((u8_t *)q->payload)[39];
678  if ((src.addr_len == 2) && (ip6_addr_netcmp(&ip6_hdr->src, &ip6_hdr->dest)) &&
679  (lowpan6_get_address_mode(ip6addr, &dest) == 3)) {
680  MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
681  return lowpan6_frag(netif, q, &src, &dest);
682  }
683  }
684 #endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */
685 
686  /* Ask ND6 what to do with the packet. */
687  result = nd6_get_next_hop_addr_or_queue(netif, q, ip6addr, &hwaddr);
688  if (result != ERR_OK) {
689  MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
690  return result;
691  }
692 
693  /* If no hardware address is returned, nd6 has queued the packet for later. */
694  if (hwaddr == NULL) {
695  return ERR_OK;
696  }
697 
698  /* Send out the packet using the returned hardware address. */
699  dest.addr_len = netif->hwaddr_len;
700  SMEMCPY(dest.addr, hwaddr, netif->hwaddr_len);
701  MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
702  return lowpan6_frag(netif, q, &src, &dest);
703 }
704 
705 static struct pbuf *
706 lowpan6_decompress(struct pbuf * p, struct ieee_802154_addr * src, struct ieee_802154_addr * dest)
707 {
708  struct pbuf * q;
709  u8_t * lowpan6_buffer;
710  s8_t lowpan6_offset;
711  struct ip6_hdr *ip6hdr;
712  s8_t i;
713  s8_t ip6_offset = IP6_HLEN;
714 
715 
716  q = pbuf_alloc(PBUF_IP, p->len + IP6_HLEN + UDP_HLEN, PBUF_POOL);
717  if (q == NULL) {
718  pbuf_free(p);
719  return NULL;
720  }
721 
722  lowpan6_buffer = (u8_t *)p->payload;
723  ip6hdr = (struct ip6_hdr *)q->payload;
724 
725  lowpan6_offset = 2;
726  if (lowpan6_buffer[1] & 0x80) {
727  lowpan6_offset++;
728  }
729 
730  /* Set IPv6 version, traffic class and flow label. */
731  if ((lowpan6_buffer[0] & 0x18) == 0x00) {
732  IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset], ((lowpan6_buffer[lowpan6_offset+1] & 0x0f) << 16) | (lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset+3]);
733  lowpan6_offset += 4;
734  } else if ((lowpan6_buffer[0] & 0x18) == 0x08) {
735  IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset] & 0xc0, ((lowpan6_buffer[lowpan6_offset] & 0x0f) << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset+2]);
736  lowpan6_offset += 3;
737  } else if ((lowpan6_buffer[0] & 0x18) == 0x10) {
738  IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset],0);
739  lowpan6_offset += 1;
740  } else if ((lowpan6_buffer[0] & 0x18) == 0x18) {
741  IP6H_VTCFL_SET(ip6hdr, 6, 0, 0);
742  }
743 
744  /* Set Next Header */
745  if ((lowpan6_buffer[0] & 0x04) == 0x00) {
746  IP6H_NEXTH_SET(ip6hdr, lowpan6_buffer[lowpan6_offset++]);
747  } else {
748  /* We should fill this later with NHC decoding */
749  IP6H_NEXTH_SET(ip6hdr, 0);
750  }
751 
752  /* Set Hop Limit */
753  if ((lowpan6_buffer[0] & 0x03) == 0x00) {
754  IP6H_HOPLIM_SET(ip6hdr, lowpan6_buffer[lowpan6_offset++]);
755  } else if ((lowpan6_buffer[0] & 0x03) == 0x01) {
756  IP6H_HOPLIM_SET(ip6hdr, 1);
757  } else if ((lowpan6_buffer[0] & 0x03) == 0x02) {
758  IP6H_HOPLIM_SET(ip6hdr, 64);
759  } else if ((lowpan6_buffer[0] & 0x03) == 0x03) {
760  IP6H_HOPLIM_SET(ip6hdr, 255);
761  }
762 
763  /* Source address decoding. */
764  if ((lowpan6_buffer[1] & 0x40) == 0x00) {
765  /* Stateless compression */
766  if ((lowpan6_buffer[1] & 0x30) == 0x00) {
767  /* copy full address */
768  MEMCPY(&ip6hdr->src.addr[0], lowpan6_buffer + lowpan6_offset, 16);
769  lowpan6_offset += 16;
770  } else if ((lowpan6_buffer[1] & 0x30) == 0x10) {
771  ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL);
772  ip6hdr->src.addr[1] = 0;
773  MEMCPY(&ip6hdr->src.addr[2], lowpan6_buffer + lowpan6_offset, 8);
774  lowpan6_offset += 8;
775  } else if ((lowpan6_buffer[1] & 0x30) == 0x20) {
776  ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL);
777  ip6hdr->src.addr[1] = 0;
778  ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL);
779  ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) |
780  lowpan6_buffer[lowpan6_offset+1]);
781  lowpan6_offset += 2;
782  } else if ((lowpan6_buffer[1] & 0x30) == 0x30) {
783  ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL);
784  ip6hdr->src.addr[1] = 0;
785  if (src->addr_len == 2) {
786  ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL);
787  ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (src->addr[0] << 8) | src->addr[1]);
788  } else {
789  ip6hdr->src.addr[2] = lwip_htonl(((src->addr[0] ^ 2) << 24) | (src->addr[1] << 16) |
790  (src->addr[2] << 8) | src->addr[3]);
791  ip6hdr->src.addr[3] = lwip_htonl((src->addr[4] << 24) | (src->addr[5] << 16) |
792  (src->addr[6] << 8) | src->addr[7]);
793  }
794  }
795  } else {
796  /* Stateful compression */
797  if ((lowpan6_buffer[1] & 0x30) == 0x00) {
798  /* ANY address */
799  ip6hdr->src.addr[0] = 0;
800  ip6hdr->src.addr[1] = 0;
801  ip6hdr->src.addr[2] = 0;
802  ip6hdr->src.addr[3] = 0;
803  } else {
804  /* Set prefix from context info */
805  if (lowpan6_buffer[1] & 0x80) {
806  i = (lowpan6_buffer[2] >> 4) & 0x0f;
807  } else {
808  i = 0;
809  }
810  if (i >= LWIP_6LOWPAN_NUM_CONTEXTS) {
811  /* Error */
812  pbuf_free(p);
813  pbuf_free(q);
814  return NULL;
815  }
816 
817  ip6hdr->src.addr[0] = lowpan6_context[i].addr[0];
818  ip6hdr->src.addr[1] = lowpan6_context[i].addr[1];
819  }
820 
821  if ((lowpan6_buffer[1] & 0x30) == 0x10) {
822  MEMCPY(&ip6hdr->src.addr[2], lowpan6_buffer + lowpan6_offset, 8);
823  lowpan6_offset += 8;
824  } else if ((lowpan6_buffer[1] & 0x30) == 0x20) {
825  ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL);
826  ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset+1]);
827  lowpan6_offset += 2;
828  } else if ((lowpan6_buffer[1] & 0x30) == 0x30) {
829  if (src->addr_len == 2) {
830  ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL);
831  ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (src->addr[0] << 8) | src->addr[1]);
832  } else {
833  ip6hdr->src.addr[2] = lwip_htonl(((src->addr[0] ^ 2) << 24) | (src->addr[1] << 16) | (src->addr[2] << 8) | src->addr[3]);
834  ip6hdr->src.addr[3] = lwip_htonl((src->addr[4] << 24) | (src->addr[5] << 16) | (src->addr[6] << 8) | src->addr[7]);
835  }
836  }
837  }
838 
839  /* Destination address decoding. */
840  if (lowpan6_buffer[1] & 0x08) {
841  /* Multicast destination */
842  if (lowpan6_buffer[1] & 0x04) {
843  /* @todo support stateful multicast addressing */
844  pbuf_free(p);
845  pbuf_free(q);
846  return NULL;
847  }
848 
849  if ((lowpan6_buffer[1] & 0x03) == 0x00) {
850  /* copy full address */
851  MEMCPY(&ip6hdr->dest.addr[0], lowpan6_buffer + lowpan6_offset, 16);
852  lowpan6_offset += 16;
853  } else if ((lowpan6_buffer[1] & 0x03) == 0x01) {
854  ip6hdr->dest.addr[0] = lwip_htonl(0xff000000UL | (lowpan6_buffer[lowpan6_offset++] << 16));
855  ip6hdr->dest.addr[1] = 0;
856  ip6hdr->dest.addr[2] = lwip_htonl(lowpan6_buffer[lowpan6_offset++]);
857  ip6hdr->dest.addr[3] = lwip_htonl((lowpan6_buffer[lowpan6_offset] << 24) | (lowpan6_buffer[lowpan6_offset + 1] << 16) | (lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset + 3]);
858  lowpan6_offset += 4;
859  } else if ((lowpan6_buffer[1] & 0x03) == 0x02) {
860  ip6hdr->dest.addr[0] = lwip_htonl(0xff000000UL | lowpan6_buffer[lowpan6_offset++]);
861  ip6hdr->dest.addr[1] = 0;
862  ip6hdr->dest.addr[2] = 0;
863  ip6hdr->dest.addr[3] = lwip_htonl((lowpan6_buffer[lowpan6_offset] << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset + 2]);
864  lowpan6_offset += 3;
865  } else if ((lowpan6_buffer[1] & 0x03) == 0x03) {
866  ip6hdr->dest.addr[0] = PP_HTONL(0xff020000UL);
867  ip6hdr->dest.addr[1] = 0;
868  ip6hdr->dest.addr[2] = 0;
869  ip6hdr->dest.addr[3] = lwip_htonl(lowpan6_buffer[lowpan6_offset++]);
870  }
871 
872  } else {
873  if (lowpan6_buffer[1] & 0x04) {
874  /* Stateful destination compression */
875  /* Set prefix from context info */
876  if (lowpan6_buffer[1] & 0x80) {
877  i = lowpan6_buffer[2] & 0x0f;
878  } else {
879  i = 0;
880  }
881  if (i >= LWIP_6LOWPAN_NUM_CONTEXTS) {
882  /* Error */
883  pbuf_free(p);
884  pbuf_free(q);
885  return NULL;
886  }
887 
888  ip6hdr->dest.addr[0] = lowpan6_context[i].addr[0];
889  ip6hdr->dest.addr[1] = lowpan6_context[i].addr[1];
890  } else {
891  /* Link local address compression */
892  ip6hdr->dest.addr[0] = PP_HTONL(0xfe800000UL);
893  ip6hdr->dest.addr[1] = 0;
894  }
895 
896  if ((lowpan6_buffer[1] & 0x03) == 0x00) {
897  /* copy full address */
898  MEMCPY(&ip6hdr->dest.addr[0], lowpan6_buffer + lowpan6_offset, 16);
899  lowpan6_offset += 16;
900  } else if ((lowpan6_buffer[1] & 0x03) == 0x01) {
901  MEMCPY(&ip6hdr->dest.addr[2], lowpan6_buffer + lowpan6_offset, 8);
902  lowpan6_offset += 8;
903  } else if ((lowpan6_buffer[1] & 0x03) == 0x02) {
904  ip6hdr->dest.addr[2] = PP_HTONL(0x000000ffUL);
905  ip6hdr->dest.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset + 1]);
906  lowpan6_offset += 2;
907  } else if ((lowpan6_buffer[1] & 0x03) == 0x03) {
908  if (dest->addr_len == 2) {
909  ip6hdr->dest.addr[2] = PP_HTONL(0x000000ffUL);
910  ip6hdr->dest.addr[3] = lwip_htonl(0xfe000000UL | (dest->addr[0] << 8) | dest->addr[1]);
911  } else {
912  ip6hdr->dest.addr[2] = lwip_htonl(((dest->addr[0] ^ 2) << 24) | (dest->addr[1] << 16) | dest->addr[2] << 8 | dest->addr[3]);
913  ip6hdr->dest.addr[3] = lwip_htonl((dest->addr[4] << 24) | (dest->addr[5] << 16) | dest->addr[6] << 8 | dest->addr[7]);
914  }
915  }
916  }
917 
918 
919  /* Next Header Compression (NHC) decoding? */
920  if (lowpan6_buffer[0] & 0x04) {
921  if ((lowpan6_buffer[lowpan6_offset] & 0xf8) == 0xf0) {
922  struct udp_hdr *udphdr;
923 
924  /* UDP compression */
925  IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_UDP);
926  udphdr = (struct udp_hdr *)((u8_t *)q->payload + ip6_offset);
927 
928  if (lowpan6_buffer[lowpan6_offset] & 0x04) {
929  /* @todo support checksum decompress */
930  pbuf_free(p);
931  pbuf_free(q);
932  return NULL;
933  }
934 
935  /* Decompress ports */
936  i = lowpan6_buffer[lowpan6_offset++] & 0x03;
937  if (i == 0) {
938  udphdr->src = lwip_htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]);
939  udphdr->dest = lwip_htons(lowpan6_buffer[lowpan6_offset + 2] << 8 | lowpan6_buffer[lowpan6_offset + 3]);
940  lowpan6_offset += 4;
941  } else if (i == 0x01) {
942  udphdr->src = lwip_htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]);
943  udphdr->dest = lwip_htons(0xf000 | lowpan6_buffer[lowpan6_offset + 2]);
944  lowpan6_offset += 3;
945  } else if (i == 0x02) {
946  udphdr->src = lwip_htons(0xf000 | lowpan6_buffer[lowpan6_offset]);
947  udphdr->dest = lwip_htons(lowpan6_buffer[lowpan6_offset + 1] << 8 | lowpan6_buffer[lowpan6_offset + 2]);
948  lowpan6_offset += 3;
949  } else if (i == 0x03) {
950  udphdr->src = lwip_htons(0xf0b0 | ((lowpan6_buffer[lowpan6_offset] >> 4) & 0x0f));
951  udphdr->dest = lwip_htons(0xf0b0 | (lowpan6_buffer[lowpan6_offset] & 0x0f));
952  lowpan6_offset += 1;
953  }
954 
955  udphdr->chksum = lwip_htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]);
956  lowpan6_offset += 2;
957  udphdr->len = lwip_htons(p->tot_len - lowpan6_offset + UDP_HLEN);
958 
959  ip6_offset += UDP_HLEN;
960  } else {
961  /* @todo support NHC other than UDP */
962  pbuf_free(p);
963  pbuf_free(q);
964  return NULL;
965  }
966  }
967 
968  /* Now we copy leftover contents from p to q, so we have all L2 and L3 headers (and L4?) in a single PBUF.
969  * Replace p with q, and free p */
970  pbuf_header(p, -lowpan6_offset);
971  MEMCPY((u8_t*)q->payload + ip6_offset, p->payload, p->len);
972  q->len = q->tot_len = ip6_offset + p->len;
973  if (p->next != NULL) {
974  pbuf_cat(q, p->next);
975  }
976  p->next = NULL;
977  pbuf_free(p);
978 
979  /* Infer IPv6 payload length for header */
980  IP6H_PLEN_SET(ip6hdr, q->tot_len - IP6_HLEN);
981 
982  /* all done */
983  return q;
984 }
985 
986 err_t
987 lowpan6_input(struct pbuf * p, struct netif *netif)
988 {
989  u8_t * puc;
990  s8_t i;
991  struct ieee_802154_addr src, dest;
992  u16_t datagram_size, datagram_offset, datagram_tag;
993  struct lowpan6_reass_helper *lrh, *lrh_temp;
994 
995  MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
996 
997  /* Analyze header. @todo validate. */
998  puc = (u8_t*)p->payload;
999  datagram_offset = 5;
1000  if ((puc[1] & 0x0c) == 0x0c) {
1001  dest.addr_len = 8;
1002  for (i = 0; i < 8; i++) {
1003  dest.addr[i] = puc[datagram_offset + 7 - i];
1004  }
1005  datagram_offset += 8;
1006  } else {
1007  dest.addr_len = 2;
1008  dest.addr[0] = puc[datagram_offset + 1];
1009  dest.addr[1] = puc[datagram_offset];
1010  datagram_offset += 2;
1011  }
1012 
1013  datagram_offset += 2; /* skip PAN ID. */
1014 
1015  if ((puc[1] & 0xc0) == 0xc0) {
1016  src.addr_len = 8;
1017  for (i = 0; i < 8; i++) {
1018  src.addr[i] = puc[datagram_offset + 7 - i];
1019  }
1020  datagram_offset += 8;
1021  } else {
1022  src.addr_len = 2;
1023  src.addr[0] = puc[datagram_offset + 1];
1024  src.addr[1] = puc[datagram_offset];
1025  datagram_offset += 2;
1026  }
1027 
1028  pbuf_header(p, -datagram_offset); /* hide IEEE802.15.4 header. */
1029 
1030  /* Check dispatch. */
1031  puc = (u8_t*)p->payload;
1032 
1033  if ((*puc & 0xf8) == 0xc0) {
1034  /* FRAG1 dispatch. add this packet to reassembly list. */
1035  datagram_size = ((u16_t)(puc[0] & 0x07) << 8) | (u16_t)puc[1];
1036  datagram_tag = ((u16_t)puc[2] << 8) | (u16_t)puc[3];
1037 
1038  /* check for duplicate */
1039  lrh = reass_list;
1040  while (lrh != NULL) {
1041  if ((lrh->sender_addr.addr_len == src.addr_len) &&
1042  (memcmp(lrh->sender_addr.addr, src.addr, src.addr_len) == 0)) {
1043  /* address match with packet in reassembly. */
1044  if ((datagram_tag == lrh->datagram_tag) && (datagram_size == lrh->datagram_size)) {
1045  MIB2_STATS_NETIF_INC(netif, ifindiscards);
1046  /* duplicate fragment. */
1047  pbuf_free(p);
1048  return ERR_OK;
1049  } else {
1050  /* We are receiving the start of a new datagram. Discard old one (incomplete). */
1051  lrh_temp = lrh->next_packet;
1052  dequeue_datagram(lrh);
1053  pbuf_free(lrh->pbuf);
1054  mem_free(lrh);
1055 
1056  /* Check next datagram in queue. */
1057  lrh = lrh_temp;
1058  }
1059  } else {
1060  /* Check next datagram in queue. */
1061  lrh = lrh->next_packet;
1062  }
1063  }
1064 
1065  pbuf_header(p, -4); /* hide frag1 dispatch */
1066 
1067  lrh = (struct lowpan6_reass_helper *) mem_malloc(sizeof(struct lowpan6_reass_helper));
1068  if (lrh == NULL) {
1069  MIB2_STATS_NETIF_INC(netif, ifindiscards);
1070  pbuf_free(p);
1071  return ERR_MEM;
1072  }
1073 
1074  lrh->sender_addr.addr_len = src.addr_len;
1075  for (i = 0; i < src.addr_len; i++) {
1076  lrh->sender_addr.addr[i] = src.addr[i];
1077  }
1078  lrh->datagram_size = datagram_size;
1079  lrh->datagram_tag = datagram_tag;
1080  lrh->pbuf = p;
1081  lrh->next_packet = reass_list;
1082  lrh->timer = 2;
1083  reass_list = lrh;
1084 
1085  return ERR_OK;
1086  } else if ((*puc & 0xf8) == 0xe0) {
1087  /* FRAGN dispatch, find packet being reassembled. */
1088  datagram_size = ((u16_t)(puc[0] & 0x07) << 8) | (u16_t)puc[1];
1089  datagram_tag = ((u16_t)puc[2] << 8) | (u16_t)puc[3];
1090  datagram_offset = (u16_t)puc[4] << 3;
1091  pbuf_header(p, -5); /* hide frag1 dispatch */
1092 
1093  for (lrh = reass_list; lrh != NULL; lrh = lrh->next_packet) {
1094  if ((lrh->sender_addr.addr_len == src.addr_len) &&
1095  (memcmp(lrh->sender_addr.addr, src.addr, src.addr_len) == 0) &&
1096  (datagram_tag == lrh->datagram_tag) &&
1097  (datagram_size == lrh->datagram_size)) {
1098  break;
1099  }
1100  }
1101  if (lrh == NULL) {
1102  /* rogue fragment */
1103  MIB2_STATS_NETIF_INC(netif, ifindiscards);
1104  pbuf_free(p);
1105  return ERR_OK;
1106  }
1107 
1108  if (lrh->pbuf->tot_len < datagram_offset) {
1109  /* duplicate, ignore. */
1110  pbuf_free(p);
1111  return ERR_OK;
1112  } else if (lrh->pbuf->tot_len > datagram_offset) {
1113  MIB2_STATS_NETIF_INC(netif, ifindiscards);
1114  /* We have missed a fragment. Delete whole reassembly. */
1115  dequeue_datagram(lrh);
1116  pbuf_free(lrh->pbuf);
1117  mem_free(lrh);
1118  pbuf_free(p);
1119  return ERR_OK;
1120  }
1121  pbuf_cat(lrh->pbuf, p);
1122  p = NULL;
1123 
1124  /* is packet now complete?*/
1125  if (lrh->pbuf->tot_len >= lrh->datagram_size) {
1126  /* dequeue from reass list. */
1127  dequeue_datagram(lrh);
1128 
1129  /* get pbuf */
1130  p = lrh->pbuf;
1131 
1132  /* release helper */
1133  mem_free(lrh);
1134  } else {
1135  return ERR_OK;
1136  }
1137  }
1138 
1139  if (p == NULL) {
1140  return ERR_OK;
1141  }
1142 
1143  /* We have a complete packet, check dispatch for headers. */
1144  puc = (u8_t*)p->payload;
1145 
1146  if (*puc == 0x41) {
1147  /* This is a complete IPv6 packet, just skip dispatch byte. */
1148  pbuf_header(p, -1); /* hide dispatch byte. */
1149  } else if ((*puc & 0xe0 )== 0x60) {
1150  /* IPv6 headers are compressed using IPHC. */
1151  p = lowpan6_decompress(p, &src, &dest);
1152  if (p == NULL) {
1153  MIB2_STATS_NETIF_INC(netif, ifindiscards);
1154  return ERR_OK;
1155  }
1156  } else {
1157  MIB2_STATS_NETIF_INC(netif, ifindiscards);
1158  pbuf_free(p);
1159  return ERR_OK;
1160  }
1161 
1162  /* @todo: distinguish unicast/multicast */
1163  MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
1164 
1165  return ip6_input(p, netif);
1166 }
1167 
1168 err_t
1169 lowpan6_if_init(struct netif *netif)
1170 {
1171  netif->name[0] = 'L';
1172  netif->name[1] = '6';
1173 #if LWIP_IPV4
1174  netif->output = lowpan4_output;
1175 #endif /* LWIP_IPV4 */
1176  netif->output_ip6 = lowpan6_output;
1177 
1178  MIB2_INIT_NETIF(netif, snmp_ifType_other, 0);
1179 
1180  /* maximum transfer unit */
1181  netif->mtu = 1280;
1182 
1183  /* broadcast capability */
1184  netif->flags = NETIF_FLAG_BROADCAST /* | NETIF_FLAG_LOWPAN6 */;
1185 
1186  return ERR_OK;
1187 }
1188 
1189 err_t
1190 lowpan6_set_pan_id(u16_t pan_id)
1191 {
1192  ieee_802154_pan_id = pan_id;
1193 
1194  return ERR_OK;
1195 }
1196 
1197 #if !NO_SYS
1198 
1205 err_t
1206 tcpip_6lowpan_input(struct pbuf *p, struct netif *inp)
1207 {
1208  return tcpip_inpkt(p, inp, lowpan6_input);
1209 }
1210 #endif /* !NO_SYS */
1211 
1212 #endif /* LWIP_IPV6 && LWIP_6LOWPAN */
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]
Definition: netif.h:322
u16_t tot_len
Definition: pbuf.h:175
Definition: pbuf.h:113
struct pbuf * next
Definition: pbuf.h:163
u16_t len
Definition: pbuf.h:178
void mem_free(void *rmem)
Definition: mem.c:438
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
Definition: pbuf.c:684
err_t tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn)
Definition: tcpip.c:188
#define NETIF_FLAG_BROADCAST
Definition: netif.h:100
u8_t hwaddr_len
Definition: netif.h:320
Definition: err.h:84
ip_addr_t current_iphdr_dest
Definition: ip.h:143
Definition: err.h:115
Definition: pbuf.h:161
u8_t flags
Definition: netif.h:324
Definition: netif.h:244
void pbuf_cat(struct pbuf *h, struct pbuf *t)
Definition: pbuf.c:859
Definition: err.h:106
s8_t err_t
Definition: err.h:76
u16_t mtu
Definition: netif.h:318
#define LWIP_DEBUGF(debug, message)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:267
u16_t pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:1034
Definition: pbuf.h:127
Definition: err.h:94
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:734
Definition: err.h:82
void * payload
Definition: pbuf.h:166
Definition: pbuf.h:99
char name[2]
Definition: netif.h:326
void * mem_malloc(mem_size_t size)
Definition: mem.c:622
ip_addr_t current_iphdr_src
Definition: ip.h:141
netif_linkoutput_fn linkoutput
Definition: netif.h:274