ReactOS 0.4.16-dev-533-gc7d1aa3
lowpan6.c
Go to the documentation of this file.
1
10/*
11 * Copyright (c) 2015 Inico Technologies Ltd.
12 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without modification,
15 * are permitted provided that the following conditions are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright notice,
18 * this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright notice,
20 * this list of conditions and the following disclaimer in the documentation
21 * and/or other materials provided with the distribution.
22 * 3. The name of the author may not be used to endorse or promote products
23 * derived from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
28 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
30 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 * OF SUCH DAMAGE.
35 *
36 * This file is part of the lwIP TCP/IP stack.
37 *
38 * Author: Ivan Delamer <delamer@inicotech.com>
39 *
40 *
41 * Please coordinate changes and requests with Ivan Delamer
42 * <delamer@inicotech.com>
43 */
44
51#include "netif/lowpan6.h"
52
53#if LWIP_IPV6
54
55#include "lwip/ip.h"
56#include "lwip/pbuf.h"
57#include "lwip/ip_addr.h"
58#include "lwip/netif.h"
59#include "lwip/nd6.h"
60#include "lwip/mem.h"
61#include "lwip/udp.h"
62#include "lwip/tcpip.h"
63#include "lwip/snmp.h"
64#include "netif/ieee802154.h"
65
66#include <string.h>
67
68#if LWIP_6LOWPAN_802154_HW_CRC
69#define LWIP_6LOWPAN_DO_CALC_CRC(buf, len) 0
70#else
71#define LWIP_6LOWPAN_DO_CALC_CRC(buf, len) LWIP_6LOWPAN_CALC_CRC(buf, len)
72#endif
73
77struct lowpan6_reass_helper {
78 struct lowpan6_reass_helper *next_packet;
79 struct pbuf *reass;
80 struct pbuf *frags;
81 u8_t timer;
82 struct lowpan6_link_addr sender_addr;
83 u16_t datagram_size;
84 u16_t datagram_tag;
85};
86
88struct lowpan6_ieee802154_data {
90 struct lowpan6_reass_helper *reass_list;
91#if LWIP_6LOWPAN_NUM_CONTEXTS > 0
93 ip6_addr_t lowpan6_context[LWIP_6LOWPAN_NUM_CONTEXTS];
94#endif
96 u16_t tx_datagram_tag;
98 u16_t ieee_802154_pan_id;
100 u8_t tx_frame_seq_num;
101};
102
103/* Maximum frame size is 127 bytes minus CRC size */
104#define LOWPAN6_MAX_PAYLOAD (127 - 2)
105
107static struct lowpan6_ieee802154_data lowpan6_data;
108
109#if LWIP_6LOWPAN_NUM_CONTEXTS > 0
110#define LWIP_6LOWPAN_CONTEXTS(netif) lowpan6_data.lowpan6_context
111#else
112#define LWIP_6LOWPAN_CONTEXTS(netif) NULL
113#endif
114
115static const struct lowpan6_link_addr ieee_802154_broadcast = {2, {0xff, 0xff}};
116
117#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS
118static struct lowpan6_link_addr short_mac_addr = {2, {0, 0}};
119#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */
120
121/* IEEE 802.15.4 specific functions: */
122
129static u8_t
130lowpan6_write_iee802154_header(struct ieee_802154_hdr *hdr, const struct lowpan6_link_addr *src,
131 const struct lowpan6_link_addr *dst)
132{
133 u8_t ieee_header_len;
134 u8_t *buffer;
135 u8_t i;
136 u16_t fc;
137
138 fc = IEEE_802154_FC_FT_DATA; /* send data packet (2003 frame version) */
139 fc |= IEEE_802154_FC_PANID_COMPR; /* set PAN ID compression, for now src and dst PANs are equal */
140 if (dst != &ieee_802154_broadcast) {
141 fc |= IEEE_802154_FC_ACK_REQ; /* data packet, no broadcast: ack required. */
142 }
143 if (dst->addr_len == 2) {
145 } else {
146 LWIP_ASSERT("invalid dst address length", dst->addr_len == 8);
148 }
149 if (src->addr_len == 2) {
151 } else {
152 LWIP_ASSERT("invalid src address length", src->addr_len == 8);
154 }
155 hdr->frame_control = fc;
156 hdr->sequence_number = lowpan6_data.tx_frame_seq_num++;
157 hdr->destination_pan_id = lowpan6_data.ieee_802154_pan_id; /* pan id */
158
159 buffer = (u8_t *)hdr;
160 ieee_header_len = 5;
161 i = dst->addr_len;
162 /* reverse memcpy of dst addr */
163 while (i-- > 0) {
164 buffer[ieee_header_len++] = dst->addr[i];
165 }
166 /* Source PAN ID skipped due to PAN ID Compression */
167 i = src->addr_len;
168 /* reverse memcpy of src addr */
169 while (i-- > 0) {
170 buffer[ieee_header_len++] = src->addr[i];
171 }
172 return ieee_header_len;
173}
174
185static err_t
186lowpan6_parse_iee802154_header(struct pbuf *p, struct lowpan6_link_addr *src,
187 struct lowpan6_link_addr *dest)
188{
189 u8_t *puc;
190 s8_t i;
191 u16_t frame_control, addr_mode;
192 u16_t datagram_offset;
193
194 /* Parse IEEE 802.15.4 header */
195 puc = (u8_t *)p->payload;
196 frame_control = puc[0] | (puc[1] << 8);
197 datagram_offset = 2;
198 if (frame_control & IEEE_802154_FC_SEQNO_SUPPR) {
199 if (IEEE_802154_FC_FRAME_VERSION_GET(frame_control) <= 1) {
200 /* sequence number suppressed, this is not valid for versions 0/1 */
201 return ERR_VAL;
202 }
203 } else {
204 datagram_offset++;
205 }
206 datagram_offset += 2; /* Skip destination PAN ID */
207 addr_mode = frame_control & IEEE_802154_FC_DST_ADDR_MODE_MASK;
208 if (addr_mode == IEEE_802154_FC_DST_ADDR_MODE_EXT) {
209 /* extended address (64 bit) */
210 dest->addr_len = 8;
211 /* reverse memcpy: */
212 for (i = 0; i < 8; i++) {
213 dest->addr[i] = puc[datagram_offset + 7 - i];
214 }
215 datagram_offset += 8;
216 } else if (addr_mode == IEEE_802154_FC_DST_ADDR_MODE_SHORT) {
217 /* short address (16 bit) */
218 dest->addr_len = 2;
219 /* reverse memcpy: */
220 dest->addr[0] = puc[datagram_offset + 1];
221 dest->addr[1] = puc[datagram_offset];
222 datagram_offset += 2;
223 } else {
224 /* unsupported address mode (do we need "no address"?) */
225 return ERR_VAL;
226 }
227
228 if (!(frame_control & IEEE_802154_FC_PANID_COMPR)) {
229 /* No PAN ID compression, skip source PAN ID */
230 datagram_offset += 2;
231 }
232
233 addr_mode = frame_control & IEEE_802154_FC_SRC_ADDR_MODE_MASK;
234 if (addr_mode == IEEE_802154_FC_SRC_ADDR_MODE_EXT) {
235 /* extended address (64 bit) */
236 src->addr_len = 8;
237 /* reverse memcpy: */
238 for (i = 0; i < 8; i++) {
239 src->addr[i] = puc[datagram_offset + 7 - i];
240 }
241 datagram_offset += 8;
242 } else if (addr_mode == IEEE_802154_FC_DST_ADDR_MODE_SHORT) {
243 /* short address (16 bit) */
244 src->addr_len = 2;
245 src->addr[0] = puc[datagram_offset + 1];
246 src->addr[1] = puc[datagram_offset];
247 datagram_offset += 2;
248 } else {
249 /* unsupported address mode (do we need "no address"?) */
250 return ERR_VAL;
251 }
252
253 /* hide IEEE802.15.4 header. */
254 if (pbuf_remove_header(p, datagram_offset)) {
255 return ERR_VAL;
256 }
257 return ERR_OK;
258}
259
261u16_t
262lowpan6_calc_crc(const void* buf, u16_t len)
263{
264#define CCITT_POLY_16 0x8408U
265 u16_t i;
266 u8_t b;
267 u16_t crc = 0;
268 const u8_t* p = (const u8_t*)buf;
269
270 for (i = 0; i < len; i++) {
271 u8_t data = *p;
272 for (b = 0U; b < 8U; b++) {
273 if (((data ^ crc) & 1) != 0) {
274 crc = (u16_t)((crc >> 1) ^ CCITT_POLY_16);
275 } else {
276 crc = (u16_t)(crc >> 1);
277 }
278 data = (u8_t)(data >> 1);
279 }
280 p++;
281 }
282 return crc;
283}
284
285/* Fragmentation specific functions: */
286
287static void
288free_reass_datagram(struct lowpan6_reass_helper *lrh)
289{
290 if (lrh->reass) {
291 pbuf_free(lrh->reass);
292 }
293 if (lrh->frags) {
294 pbuf_free(lrh->frags);
295 }
296 mem_free(lrh);
297}
298
302static void
303dequeue_datagram(struct lowpan6_reass_helper *lrh, struct lowpan6_reass_helper *prev)
304{
305 if (lowpan6_data.reass_list == lrh) {
306 lowpan6_data.reass_list = lowpan6_data.reass_list->next_packet;
307 } else {
308 /* it wasn't the first, so it must have a valid 'prev' */
309 LWIP_ASSERT("sanity check linked list", prev != NULL);
310 prev->next_packet = lrh->next_packet;
311 }
312}
313
319void
320lowpan6_tmr(void)
321{
322 struct lowpan6_reass_helper *lrh, *lrh_next, *lrh_prev = NULL;
323
324 lrh = lowpan6_data.reass_list;
325 while (lrh != NULL) {
326 lrh_next = lrh->next_packet;
327 if ((--lrh->timer) == 0) {
328 dequeue_datagram(lrh, lrh_prev);
329 free_reass_datagram(lrh);
330 } else {
331 lrh_prev = lrh;
332 }
333 lrh = lrh_next;
334 }
335}
336
337/*
338 * Encapsulates data into IEEE 802.15.4 frames.
339 * Fragments an IPv6 datagram into 6LowPAN units, which fit into IEEE 802.15.4 frames.
340 * If configured, will compress IPv6 and or UDP headers.
341 * */
342static err_t
343lowpan6_frag(struct netif *netif, struct pbuf *p, const struct lowpan6_link_addr *src, const struct lowpan6_link_addr *dst)
344{
345 struct pbuf *p_frag;
346 u16_t frag_len, remaining_len, max_data_len;
347 u8_t *buffer;
348 u8_t ieee_header_len;
349 u8_t lowpan6_header_len;
350 u8_t hidden_header_len;
351 u16_t crc;
352 u16_t datagram_offset;
353 err_t err = ERR_IF;
354
355 LWIP_ASSERT("lowpan6_frag: netif->linkoutput not set", netif->linkoutput != NULL);
356
357 /* We'll use a dedicated pbuf for building 6LowPAN fragments. */
358 p_frag = pbuf_alloc(PBUF_RAW, 127, PBUF_RAM);
359 if (p_frag == NULL) {
360 MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
361 return ERR_MEM;
362 }
363 LWIP_ASSERT("this needs a pbuf in one piece", p_frag->len == p_frag->tot_len);
364
365 /* Write IEEE 802.15.4 header. */
366 buffer = (u8_t *)p_frag->payload;
367 ieee_header_len = lowpan6_write_iee802154_header((struct ieee_802154_hdr *)buffer, src, dst);
368 LWIP_ASSERT("ieee_header_len < p_frag->len", ieee_header_len < p_frag->len);
369
370#if LWIP_6LOWPAN_IPHC
371 /* Perform 6LowPAN IPv6 header compression according to RFC 6282 */
372 /* do the header compression (this does NOT copy any non-compressed data) */
373 err = lowpan6_compress_headers(netif, (u8_t *)p->payload, p->len,
374 &buffer[ieee_header_len], p_frag->len - ieee_header_len, &lowpan6_header_len,
375 &hidden_header_len, LWIP_6LOWPAN_CONTEXTS(netif), src, dst);
376 if (err != ERR_OK) {
377 MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
378 pbuf_free(p_frag);
379 return err;
380 }
381 pbuf_remove_header(p, hidden_header_len);
382
383#else /* LWIP_6LOWPAN_IPHC */
384 /* Send uncompressed IPv6 header with appropriate dispatch byte. */
385 lowpan6_header_len = 1;
386 hidden_header_len = 0;
387 buffer[ieee_header_len] = 0x41; /* IPv6 dispatch */
388#endif /* LWIP_6LOWPAN_IPHC */
389
390 /* Calculate remaining packet length */
391 remaining_len = p->tot_len;
392
393 if (remaining_len > 0x7FF) {
394 MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
395 /* datagram_size must fit into 11 bit */
396 pbuf_free(p_frag);
397 return ERR_VAL;
398 }
399
400 /* Fragment, or 1 packet? */
401 max_data_len = LOWPAN6_MAX_PAYLOAD - ieee_header_len - lowpan6_header_len;
402 if (remaining_len > max_data_len) {
403 u16_t data_len;
404 /* We must move the 6LowPAN header to make room for the FRAG header. */
405 memmove(&buffer[ieee_header_len + 4], &buffer[ieee_header_len], lowpan6_header_len);
406
407 /* Now we need to fragment the packet. FRAG1 header first */
408 buffer[ieee_header_len] = 0xc0 | (((p->tot_len + hidden_header_len) >> 8) & 0x7);
409 buffer[ieee_header_len + 1] = (p->tot_len + hidden_header_len) & 0xff;
410
411 lowpan6_data.tx_datagram_tag++;
412 buffer[ieee_header_len + 2] = (lowpan6_data.tx_datagram_tag >> 8) & 0xff;
413 buffer[ieee_header_len + 3] = lowpan6_data.tx_datagram_tag & 0xff;
414
415 /* Fragment follows. */
416 data_len = (max_data_len - 4) & 0xf8;
417 frag_len = data_len + lowpan6_header_len;
418
419 pbuf_copy_partial(p, buffer + ieee_header_len + lowpan6_header_len + 4, frag_len - lowpan6_header_len, 0);
420 remaining_len -= frag_len - lowpan6_header_len;
421 /* datagram offset holds the offset before compression */
422 datagram_offset = frag_len - lowpan6_header_len + hidden_header_len;
423 LWIP_ASSERT("datagram offset must be a multiple of 8", (datagram_offset & 7) == 0);
424
425 /* Calculate frame length */
426 p_frag->len = p_frag->tot_len = ieee_header_len + 4 + frag_len + 2; /* add 2 bytes for crc*/
427
428 /* 2 bytes CRC */
429 crc = LWIP_6LOWPAN_DO_CALC_CRC(p_frag->payload, p_frag->len - 2);
430 pbuf_take_at(p_frag, &crc, 2, p_frag->len - 2);
431
432 /* send the packet */
433 MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len);
434 LWIP_DEBUGF(LWIP_LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p));
435 err = netif->linkoutput(netif, p_frag);
436
437 while ((remaining_len > 0) && (err == ERR_OK)) {
438 struct ieee_802154_hdr *hdr = (struct ieee_802154_hdr *)buffer;
439 /* new frame, new seq num for ACK */
440 hdr->sequence_number = lowpan6_data.tx_frame_seq_num++;
441
442 buffer[ieee_header_len] |= 0x20; /* Change FRAG1 to FRAGN */
443
444 LWIP_ASSERT("datagram offset must be a multiple of 8", (datagram_offset & 7) == 0);
445 buffer[ieee_header_len + 4] = (u8_t)(datagram_offset >> 3); /* datagram offset in FRAGN header (datagram_offset is max. 11 bit) */
446
447 frag_len = (127 - ieee_header_len - 5 - 2) & 0xf8;
448 if (frag_len > remaining_len) {
449 frag_len = remaining_len;
450 }
451
452 pbuf_copy_partial(p, buffer + ieee_header_len + 5, frag_len, p->tot_len - remaining_len);
453 remaining_len -= frag_len;
454 datagram_offset += frag_len;
455
456 /* Calculate frame length */
457 p_frag->len = p_frag->tot_len = frag_len + 5 + ieee_header_len + 2;
458
459 /* 2 bytes CRC */
460 crc = LWIP_6LOWPAN_DO_CALC_CRC(p_frag->payload, p_frag->len - 2);
461 pbuf_take_at(p_frag, &crc, 2, p_frag->len - 2);
462
463 /* send the packet */
464 MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len);
465 LWIP_DEBUGF(LWIP_LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p));
466 err = netif->linkoutput(netif, p_frag);
467 }
468 } else {
469 /* It fits in one frame. */
470 frag_len = remaining_len;
471
472 /* Copy IPv6 packet */
473 pbuf_copy_partial(p, buffer + ieee_header_len + lowpan6_header_len, frag_len, 0);
474 remaining_len = 0;
475
476 /* Calculate frame length */
477 p_frag->len = p_frag->tot_len = frag_len + lowpan6_header_len + ieee_header_len + 2;
478 LWIP_ASSERT("", p_frag->len <= 127);
479
480 /* 2 bytes CRC */
481 crc = LWIP_6LOWPAN_DO_CALC_CRC(p_frag->payload, p_frag->len - 2);
482 pbuf_take_at(p_frag, &crc, 2, p_frag->len - 2);
483
484 /* send the packet */
485 MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len);
486 LWIP_DEBUGF(LWIP_LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p));
487 err = netif->linkoutput(netif, p_frag);
488 }
489
490 pbuf_free(p_frag);
491
492 return err;
493}
494
499err_t
500lowpan6_set_context(u8_t idx, const ip6_addr_t *context)
501{
502#if LWIP_6LOWPAN_NUM_CONTEXTS > 0
504 return ERR_ARG;
505 }
506
507 IP6_ADDR_ZONECHECK(context);
508
509 ip6_addr_set(&lowpan6_data.lowpan6_context[idx], context);
510
511 return ERR_OK;
512#else
515 return ERR_ARG;
516#endif
517}
518
519#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS
524err_t
525lowpan6_set_short_addr(u8_t addr_high, u8_t addr_low)
526{
527 short_mac_addr.addr[0] = addr_high;
528 short_mac_addr.addr[1] = addr_low;
529
530 return ERR_OK;
531}
532#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */
533
534/* Create IEEE 802.15.4 address from netif address */
535static err_t
536lowpan6_hwaddr_to_addr(struct netif *netif, struct lowpan6_link_addr *addr)
537{
538 addr->addr_len = 8;
539 if (netif->hwaddr_len == 8) {
540 LWIP_ERROR("NETIF_MAX_HWADDR_LEN >= 8 required", sizeof(netif->hwaddr) >= 8, return ERR_VAL;);
541 SMEMCPY(addr->addr, netif->hwaddr, 8);
542 } else if (netif->hwaddr_len == 6) {
543 /* Copy from MAC-48 */
544 SMEMCPY(addr->addr, netif->hwaddr, 3);
545 addr->addr[3] = addr->addr[4] = 0xff;
546 SMEMCPY(&addr->addr[5], &netif->hwaddr[3], 3);
547 } else {
548 /* Invalid address length, don't know how to convert this */
549 return ERR_VAL;
550 }
551 return ERR_OK;
552}
553
566err_t
567lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr)
568{
570 const u8_t *hwaddr;
571 struct lowpan6_link_addr src, dest;
572#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS
573 ip6_addr_t ip6_src;
574 struct ip6_hdr *ip6_hdr;
575#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */
576
577#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS
578 /* Check if we can compress source address (use aligned copy) */
579 ip6_hdr = (struct ip6_hdr *)q->payload;
580 ip6_addr_copy_from_packed(ip6_src, ip6_hdr->src);
581 ip6_addr_assign_zone(&ip6_src, IP6_UNICAST, netif);
582 if (lowpan6_get_address_mode(&ip6_src, &short_mac_addr) == 3) {
583 src.addr_len = 2;
584 src.addr[0] = short_mac_addr.addr[0];
585 src.addr[1] = short_mac_addr.addr[1];
586 } else
587#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */
588 {
589 result = lowpan6_hwaddr_to_addr(netif, &src);
590 if (result != ERR_OK) {
591 MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
592 return result;
593 }
594 }
595
596 /* multicast destination IP address? */
597 if (ip6_addr_ismulticast(ip6addr)) {
598 MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
599 /* We need to send to the broadcast address.*/
600 return lowpan6_frag(netif, q, &src, &ieee_802154_broadcast);
601 }
602
603 /* We have a unicast destination IP address */
604 /* @todo anycast? */
605
606#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS
607 if (src.addr_len == 2) {
608 /* If source address was compressible to short_mac_addr, and dest has same subnet and
609 * is also compressible to 2-bytes, assume we can infer dest as a short address too. */
610 dest.addr_len = 2;
611 dest.addr[0] = ((u8_t *)q->payload)[38];
612 dest.addr[1] = ((u8_t *)q->payload)[39];
613 if ((src.addr_len == 2) && (ip6_addr_net_zoneless_eq(&ip6_hdr->src, &ip6_hdr->dest)) &&
614 (lowpan6_get_address_mode(ip6addr, &dest) == 3)) {
615 MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
616 return lowpan6_frag(netif, q, &src, &dest);
617 }
618 }
619#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */
620
621 /* Ask ND6 what to do with the packet. */
622 result = nd6_get_next_hop_addr_or_queue(netif, q, ip6addr, &hwaddr);
623 if (result != ERR_OK) {
624 MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
625 return result;
626 }
627
628 /* If no hardware address is returned, nd6 has queued the packet for later. */
629 if (hwaddr == NULL) {
630 return ERR_OK;
631 }
632
633 /* Send out the packet using the returned hardware address. */
634 dest.addr_len = netif->hwaddr_len;
635 /* XXX: Inferring the length of the source address from the destination address
636 * is not correct for IEEE 802.15.4, but currently we don't get this information
637 * from the neighbor cache */
639 MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
640 return lowpan6_frag(netif, q, &src, &dest);
641}
646err_t
647lowpan6_input(struct pbuf *p, struct netif *netif)
648{
649 u8_t *puc, b;
650 s8_t i;
651 struct lowpan6_link_addr src, dest;
652 u16_t datagram_size = 0;
653 u16_t datagram_offset, datagram_tag;
654 struct lowpan6_reass_helper *lrh, *lrh_next, *lrh_prev = NULL;
655
656 if (p == NULL) {
657 return ERR_OK;
658 }
659
660 MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
661
662 if (p->len != p->tot_len) {
663 /* for now, this needs a pbuf in one piece */
664 goto lowpan6_input_discard;
665 }
666
667 if (lowpan6_parse_iee802154_header(p, &src, &dest) != ERR_OK) {
668 goto lowpan6_input_discard;
669 }
670
671 /* Check dispatch. */
672 puc = (u8_t *)p->payload;
673
674 b = *puc;
675 if ((b & 0xf8) == 0xc0) {
676 /* FRAG1 dispatch. add this packet to reassembly list. */
677 datagram_size = ((u16_t)(puc[0] & 0x07) << 8) | (u16_t)puc[1];
678 datagram_tag = ((u16_t)puc[2] << 8) | (u16_t)puc[3];
679
680 /* check for duplicate */
681 lrh = lowpan6_data.reass_list;
682 while (lrh != NULL) {
683 u8_t discard = 0;
684 lrh_next = lrh->next_packet;
685 if ((lrh->sender_addr.addr_len == src.addr_len) &&
686 (memcmp(lrh->sender_addr.addr, src.addr, src.addr_len) == 0)) {
687 /* address match with packet in reassembly. */
688 if ((datagram_tag == lrh->datagram_tag) && (datagram_size == lrh->datagram_size)) {
689 /* duplicate fragment. */
690 goto lowpan6_input_discard;
691 } else {
692 /* We are receiving the start of a new datagram. Discard old one (incomplete). */
693 discard = 1;
694 }
695 }
696 if (discard) {
697 dequeue_datagram(lrh, lrh_prev);
698 free_reass_datagram(lrh);
699 } else {
700 lrh_prev = lrh;
701 }
702 /* Check next datagram in queue. */
703 lrh = lrh_next;
704 }
705
706 pbuf_remove_header(p, 4); /* hide frag1 dispatch */
707
708 lrh = (struct lowpan6_reass_helper *) mem_malloc(sizeof(struct lowpan6_reass_helper));
709 if (lrh == NULL) {
710 goto lowpan6_input_discard;
711 }
712
713 lrh->sender_addr.addr_len = src.addr_len;
714 for (i = 0; i < src.addr_len; i++) {
715 lrh->sender_addr.addr[i] = src.addr[i];
716 }
717 lrh->datagram_size = datagram_size;
718 lrh->datagram_tag = datagram_tag;
719 lrh->frags = NULL;
720 if (*(u8_t *)p->payload == 0x41) {
721 /* This is a complete IPv6 packet, just skip dispatch byte. */
722 pbuf_remove_header(p, 1); /* hide dispatch byte. */
723 lrh->reass = p;
724 } else if ((*(u8_t *)p->payload & 0xe0 ) == 0x60) {
725 lrh->reass = lowpan6_decompress(p, datagram_size, LWIP_6LOWPAN_CONTEXTS(netif), &src, &dest);
726 if (lrh->reass == NULL) {
727 /* decompression failed */
728 mem_free(lrh);
729 goto lowpan6_input_discard;
730 }
731 }
732 /* TODO: handle the case where we already have FRAGN received */
733 lrh->next_packet = lowpan6_data.reass_list;
734 lrh->timer = 2;
735 lowpan6_data.reass_list = lrh;
736
737 return ERR_OK;
738 } else if ((b & 0xf8) == 0xe0) {
739 /* FRAGN dispatch, find packet being reassembled. */
740 datagram_size = ((u16_t)(puc[0] & 0x07) << 8) | (u16_t)puc[1];
741 datagram_tag = ((u16_t)puc[2] << 8) | (u16_t)puc[3];
742 datagram_offset = (u16_t)puc[4] << 3;
743 pbuf_remove_header(p, 4); /* hide frag1 dispatch but keep datagram offset for reassembly */
744
745 for (lrh = lowpan6_data.reass_list; lrh != NULL; lrh_prev = lrh, lrh = lrh->next_packet) {
746 if ((lrh->sender_addr.addr_len == src.addr_len) &&
747 (memcmp(lrh->sender_addr.addr, src.addr, src.addr_len) == 0) &&
748 (datagram_tag == lrh->datagram_tag) &&
749 (datagram_size == lrh->datagram_size)) {
750 break;
751 }
752 }
753 if (lrh == NULL) {
754 /* rogue fragment */
755 goto lowpan6_input_discard;
756 }
757 /* Insert new pbuf into list of fragments. Each fragment is a pbuf,
758 this only works for unchained pbufs. */
759 LWIP_ASSERT("p->next == NULL", p->next == NULL);
760 if (lrh->reass != NULL) {
761 /* FRAG1 already received, check this offset against first len */
762 if (datagram_offset < lrh->reass->len) {
763 /* fragment overlap, discard old fragments */
764 dequeue_datagram(lrh, lrh_prev);
765 free_reass_datagram(lrh);
766 goto lowpan6_input_discard;
767 }
768 }
769 if (lrh->frags == NULL) {
770 /* first FRAGN */
771 lrh->frags = p;
772 } else {
773 /* find the correct place to insert */
774 struct pbuf *q, *last;
775 u16_t new_frag_len = p->len - 1; /* p->len includes datagram_offset byte */
776 for (q = lrh->frags, last = NULL; q != NULL; last = q, q = q->next) {
777 u16_t q_datagram_offset = ((u8_t *)q->payload)[0] << 3;
778 u16_t q_frag_len = q->len - 1;
779 if (datagram_offset < q_datagram_offset) {
780 if (datagram_offset + new_frag_len > q_datagram_offset) {
781 /* overlap, discard old fragments */
782 dequeue_datagram(lrh, lrh_prev);
783 free_reass_datagram(lrh);
784 goto lowpan6_input_discard;
785 }
786 /* insert here */
787 break;
788 } else if (datagram_offset == q_datagram_offset) {
789 if (q_frag_len != new_frag_len) {
790 /* fragment mismatch, discard old fragments */
791 dequeue_datagram(lrh, lrh_prev);
792 free_reass_datagram(lrh);
793 goto lowpan6_input_discard;
794 }
795 /* duplicate, ignore */
796 pbuf_free(p);
797 return ERR_OK;
798 }
799 }
800 /* insert fragment */
801 if (last == NULL) {
802 lrh->frags = p;
803 } else {
804 last->next = p;
805 p->next = q;
806 }
807 }
808 /* check if all fragments were received */
809 if (lrh->reass) {
810 u16_t offset = lrh->reass->len;
811 struct pbuf *q;
812 for (q = lrh->frags; q != NULL; q = q->next) {
813 u16_t q_datagram_offset = ((u8_t *)q->payload)[0] << 3;
814 if (q_datagram_offset != offset) {
815 /* not complete, wait for more fragments */
816 return ERR_OK;
817 }
818 offset += q->len - 1;
819 }
820 if (offset == datagram_size) {
821 /* all fragments received, combine pbufs */
822 u16_t datagram_left = datagram_size - lrh->reass->len;
823 for (q = lrh->frags; q != NULL; q = q->next) {
824 /* hide datagram_offset byte now */
826 q->tot_len = datagram_left;
827 datagram_left -= q->len;
828 }
829 LWIP_ASSERT("datagram_left == 0", datagram_left == 0);
830 q = lrh->reass;
831 q->tot_len = datagram_size;
832 q->next = lrh->frags;
833 lrh->frags = NULL;
834 lrh->reass = NULL;
835 dequeue_datagram(lrh, lrh_prev);
836 mem_free(lrh);
837
838 /* @todo: distinguish unicast/multicast */
839 MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
840 return ip6_input(q, netif);
841 }
842 }
843 /* pbuf enqueued, waiting for more fragments */
844 return ERR_OK;
845 } else {
846 if (b == 0x41) {
847 /* This is a complete IPv6 packet, just skip dispatch byte. */
848 pbuf_remove_header(p, 1); /* hide dispatch byte. */
849 } else if ((b & 0xe0 ) == 0x60) {
850 /* IPv6 headers are compressed using IPHC. */
851 p = lowpan6_decompress(p, datagram_size, LWIP_6LOWPAN_CONTEXTS(netif), &src, &dest);
852 if (p == NULL) {
853 MIB2_STATS_NETIF_INC(netif, ifindiscards);
854 return ERR_OK;
855 }
856 } else {
857 goto lowpan6_input_discard;
858 }
859
860 /* @todo: distinguish unicast/multicast */
861 MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
862
863 return ip6_input(p, netif);
864 }
865lowpan6_input_discard:
866 MIB2_STATS_NETIF_INC(netif, ifindiscards);
867 pbuf_free(p);
868 /* always return ERR_OK here to prevent the caller freeing the pbuf */
869 return ERR_OK;
870}
871
875err_t
876lowpan6_if_init(struct netif *netif)
877{
878 netif->name[0] = 'L';
879 netif->name[1] = '6';
880 netif->output_ip6 = lowpan6_output;
881
882 MIB2_INIT_NETIF(netif, snmp_ifType_other, 0);
883
884 /* maximum transfer unit */
886
887 /* broadcast capability */
888 netif->flags = NETIF_FLAG_BROADCAST /* | NETIF_FLAG_LOWPAN6 */;
889
890 return ERR_OK;
891}
892
897err_t
898lowpan6_set_pan_id(u16_t pan_id)
899{
900 lowpan6_data.ieee_802154_pan_id = pan_id;
901
902 return ERR_OK;
903}
904
905#if !NO_SYS
914err_t
915tcpip_6lowpan_input(struct pbuf *p, struct netif *inp)
916{
917 return tcpip_inpkt(p, inp, lowpan6_input);
918}
919#endif /* !NO_SYS */
920
921#endif /* LWIP_IPV6 */
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define U(x)
Definition: wordpad.c:45
PFOR_CONTEXT fc
Definition: for.c:57
#define mem_free(ptr, bsize)
Definition: types.h:124
#define NULL
Definition: types.h:112
unsigned int idx
Definition: utils.c:41
void * mem_malloc(mem_size_t size_in)
Definition: mem.c:831
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:158
#define LWIP_ERROR(message, expression, handler)
Definition: debug.h:130
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:116
#define MIB2_STATS_NETIF_ADD(n, x, val)
Definition: snmp.h:140
#define MIB2_STATS_NETIF_INC(n, x)
Definition: snmp.h:139
#define MIB2_INIT_NETIF(netif, type, speed)
Definition: snmp.h:138
#define ERR_MEM
Definition: fontsub.h:52
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
GLintptr offset
Definition: glext.h:5920
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLenum dst
Definition: glext.h:6340
GLenum const GLvoid * addr
Definition: glext.h:9621
GLuint64EXT * result
Definition: glext.h:11304
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
uint8_t u8_t
Definition: arch.h:125
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:373
uint16_t u16_t
Definition: arch.h:127
int8_t s8_t
Definition: arch.h:126
#define LWIP_DBG_TRACE
Definition: debug.h:83
s8_t err_t
Definition: err.h:96
@ ERR_IF
Definition: err.h:79
@ ERR_OK
Definition: err.h:55
@ ERR_VAL
Definition: err.h:67
@ ERR_ARG
Definition: err.h:88
#define SMEMCPY(dst, src, len)
Definition: opt.h:145
#define NETIF_FLAG_BROADCAST
Definition: netif.h:87
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:224
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:727
u16_t pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:1058
err_t pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:1271
@ PBUF_RAM
Definition: pbuf.h:152
@ PBUF_RAW
Definition: pbuf.h:111
#define IEEE_802154_FC_SRC_ADDR_MODE_SHORT
Definition: ieee802154.h:105
#define IEEE_802154_FC_FRAME_VERSION_GET(x)
Definition: ieee802154.h:103
#define IEEE_802154_FC_SRC_ADDR_MODE_MASK
Definition: ieee802154.h:104
#define IEEE_802154_FC_FT_DATA
Definition: ieee802154.h:84
#define IEEE_802154_FC_SRC_ADDR_MODE_EXT
Definition: ieee802154.h:106
#define IEEE_802154_FC_DST_ADDR_MODE_EXT
Definition: ieee802154.h:101
#define IEEE_802154_FC_ACK_REQ
Definition: ieee802154.h:93
#define IEEE_802154_FC_DST_ADDR_MODE_SHORT
Definition: ieee802154.h:100
#define IEEE_802154_FC_PANID_COMPR
Definition: ieee802154.h:94
#define IEEE_802154_FC_SEQNO_SUPPR
Definition: ieee802154.h:96
#define IEEE_802154_FC_DST_ADDR_MODE_MASK
Definition: ieee802154.h:98
char hwaddr[6]
Definition: iptest.cpp:31
char hdr[14]
Definition: iptest.cpp:33
#define b
Definition: ke_i.h:79
if(dx< 0)
Definition: linetemp.h:194
#define LWIP_6LOWPAN_NUM_CONTEXTS
Definition: lowpan6_opts.h:50
#define LWIP_LOWPAN6_DEBUG
Definition: lowpan6_opts.h:85
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
static UINT UINT last
Definition: font.c:45
static char * dest
Definition: rtl.c:135
#define ip6_hdr
Definition: netiodef.h:183
#define ip6_src
Definition: netiodef.h:189
u8_t pbuf_remove_header(struct pbuf *p, size_t header_size_decrement)
Definition: pbuf.c:585
#define IP6_MIN_MTU_LENGTH
Definition: ip6.h:47
#define err(...)
Definition: http.c:7252
struct define * next
Definition: compiler.c:65
Definition: ip6.h:82
Definition: netif.h:269
u8_t flags
Definition: netif.h:354
char name[2]
Definition: netif.h:356
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]
Definition: netif.h:350
u16_t mtu
Definition: netif.h:344
netif_linkoutput_fn linkoutput
Definition: netif.h:308
u8_t hwaddr_len
Definition: netif.h:352
Definition: pbuf.h:186
u16_t tot_len
Definition: pbuf.h:200
u16_t len
Definition: pbuf.h:203
void * payload
Definition: pbuf.h:191
err_t tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn)
Definition: tcpip.c:245