Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-os by
lwip_lowpan6.c
00001 /** 00002 * @file 00003 * 00004 * 6LowPAN output for IPv6. Uses ND tables for link-layer addressing. Fragments packets to 6LowPAN units. 00005 */ 00006 00007 /* 00008 * Copyright (c) 2015 Inico Technologies Ltd. 00009 * All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without modification, 00012 * are permitted provided that the following conditions are met: 00013 * 00014 * 1. Redistributions of source code must retain the above copyright notice, 00015 * this list of conditions and the following disclaimer. 00016 * 2. Redistributions in binary form must reproduce the above copyright notice, 00017 * this list of conditions and the following disclaimer in the documentation 00018 * and/or other materials provided with the distribution. 00019 * 3. The name of the author may not be used to endorse or promote products 00020 * derived from this software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00023 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00024 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00025 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00026 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00027 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00028 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00029 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00030 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00031 * OF SUCH DAMAGE. 00032 * 00033 * This file is part of the lwIP TCP/IP stack. 00034 * 00035 * Author: Ivan Delamer <delamer@inicotech.com> 00036 * 00037 * 00038 * Please coordinate changes and requests with Ivan Delamer 00039 * <delamer@inicotech.com> 00040 */ 00041 00042 /** 00043 * @defgroup sixlowpan 6LowPAN netif 00044 * @ingroup addons 00045 * 6LowPAN netif implementation 00046 */ 00047 00048 #include "netif/lowpan6.h" 00049 00050 #if LWIP_IPV6 && LWIP_6LOWPAN 00051 00052 #include "lwip/ip.h" 00053 #include "lwip/pbuf.h" 00054 #include "lwip/ip_addr.h" 00055 #include "lwip/netif.h" 00056 #include "lwip/nd6.h" 00057 #include "lwip/mem.h" 00058 #include "lwip/udp.h" 00059 #include "lwip/tcpip.h" 00060 #include "lwip/snmp.h" 00061 00062 #include <string.h> 00063 00064 struct ieee_802154_addr { 00065 u8_t addr_len; 00066 u8_t addr[8]; 00067 }; 00068 00069 /** This is a helper struct. 00070 */ 00071 struct lowpan6_reass_helper { 00072 struct pbuf *pbuf; 00073 struct lowpan6_reass_helper *next_packet; 00074 u8_t timer; 00075 struct ieee_802154_addr sender_addr; 00076 u16_t datagram_size; 00077 u16_t datagram_tag; 00078 }; 00079 00080 static struct lowpan6_reass_helper * reass_list; 00081 00082 #if LWIP_6LOWPAN_NUM_CONTEXTS > 0 00083 static ip6_addr_t lowpan6_context[LWIP_6LOWPAN_NUM_CONTEXTS]; 00084 #endif 00085 00086 static u16_t ieee_802154_pan_id; 00087 00088 static const struct ieee_802154_addr ieee_802154_broadcast = {2, {0xff, 0xff}}; 00089 00090 #if LWIP_6LOWPAN_INFER_SHORT_ADDRESS 00091 static struct ieee_802154_addr short_mac_addr = {2, {0,0}}; 00092 #endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ 00093 00094 static err_t dequeue_datagram(struct lowpan6_reass_helper *lrh); 00095 00096 /** 00097 * Periodic timer for 6LowPAN functions: 00098 * 00099 * - Remove incomplete/old packets 00100 */ 00101 void 00102 lowpan6_tmr(void) 00103 { 00104 struct lowpan6_reass_helper *lrh, *lrh_temp; 00105 00106 lrh = reass_list; 00107 while (lrh != NULL) { 00108 lrh_temp = lrh->next_packet; 00109 if ((--lrh->timer) == 0) { 00110 dequeue_datagram(lrh); 00111 pbuf_free(lrh->pbuf); 00112 mem_free(lrh); 00113 } 00114 lrh = lrh_temp; 00115 } 00116 } 00117 00118 /** 00119 * Removes a datagram from the reassembly queue. 00120 **/ 00121 static err_t 00122 dequeue_datagram(struct lowpan6_reass_helper *lrh) 00123 { 00124 struct lowpan6_reass_helper *lrh_temp; 00125 00126 if (reass_list == lrh) { 00127 reass_list = reass_list->next_packet; 00128 } else { 00129 lrh_temp = reass_list; 00130 while (lrh_temp != NULL) { 00131 if (lrh_temp->next_packet == lrh) { 00132 lrh_temp->next_packet = lrh->next_packet; 00133 break; 00134 } 00135 lrh_temp = lrh_temp->next_packet; 00136 } 00137 } 00138 00139 return ERR_OK; 00140 } 00141 00142 static s8_t 00143 lowpan6_context_lookup(const ip6_addr_t *ip6addr) 00144 { 00145 s8_t i; 00146 00147 for (i = 0; i < LWIP_6LOWPAN_NUM_CONTEXTS; i++) { 00148 if (ip6_addr_netcmp(&lowpan6_context[i], ip6addr)) { 00149 return i; 00150 } 00151 } 00152 00153 return -1; 00154 } 00155 00156 /* Determine compression mode for unicast address. */ 00157 static s8_t 00158 lowpan6_get_address_mode(const ip6_addr_t *ip6addr, const struct ieee_802154_addr *mac_addr) 00159 { 00160 if (mac_addr->addr_len == 2) { 00161 if ((ip6addr->addr[2] == (u32_t)PP_HTONL(0x000000ff)) && 00162 ((ip6addr->addr[3] & PP_HTONL(0xffff0000)) == PP_NTOHL(0xfe000000))) { 00163 if ((ip6addr->addr[3] & PP_HTONL(0x0000ffff)) == ntohl((mac_addr->addr[0] << 8) | mac_addr->addr[1])) { 00164 return 3; 00165 } 00166 } 00167 } else if (mac_addr->addr_len == 8) { 00168 if ((ip6addr->addr[2] == ntohl(((mac_addr->addr[0] ^ 2) << 24) | (mac_addr->addr[1] << 16) | mac_addr->addr[2] << 8 | mac_addr->addr[3])) && 00169 (ip6addr->addr[3] == ntohl((mac_addr->addr[4] << 24) | (mac_addr->addr[5] << 16) | mac_addr->addr[6] << 8 | mac_addr->addr[7]))) { 00170 return 3; 00171 } 00172 } 00173 00174 if ((ip6addr->addr[2] == PP_HTONL(0x000000ffUL)) && 00175 ((ip6addr->addr[3] & PP_HTONL(0xffff0000)) == PP_NTOHL(0xfe000000UL))) { 00176 return 2; 00177 } 00178 00179 return 1; 00180 } 00181 00182 /* Determine compression mode for multicast address. */ 00183 static s8_t 00184 lowpan6_get_address_mode_mc(const ip6_addr_t *ip6addr) 00185 { 00186 if ((ip6addr->addr[0] == PP_HTONL(0xff020000)) && 00187 (ip6addr->addr[1] == 0) && 00188 (ip6addr->addr[2] == 0) && 00189 ((ip6addr->addr[3] & PP_HTONL(0xffffff00)) == 0)) { 00190 return 3; 00191 } else if (((ip6addr->addr[0] & PP_HTONL(0xff00ffff)) == PP_HTONL(0xff000000)) && 00192 (ip6addr->addr[1] == 0)) { 00193 if ((ip6addr->addr[2] == 0) && 00194 ((ip6addr->addr[3] & PP_HTONL(0xff000000)) == 0)) { 00195 return 2; 00196 } else if ((ip6addr->addr[2] & PP_HTONL(0xffffff00)) == 0) { 00197 return 1; 00198 } 00199 } 00200 00201 return 0; 00202 } 00203 00204 /* 00205 * Encapsulates data into IEEE 802.15.4 frames. 00206 * Fragments an IPv6 datagram into 6LowPAN units, which fit into IEEE 802.15.4 frames. 00207 * If configured, will compress IPv6 and or UDP headers. 00208 * */ 00209 static err_t 00210 lowpan6_frag(struct netif *netif, struct pbuf *p, const struct ieee_802154_addr *src, const struct ieee_802154_addr *dst) 00211 { 00212 struct pbuf * p_frag; 00213 u16_t frag_len, remaining_len; 00214 u8_t * buffer; 00215 u8_t ieee_header_len; 00216 u8_t lowpan6_header_len; 00217 s8_t i; 00218 static u8_t frame_seq_num; 00219 static u16_t datagram_tag; 00220 u16_t datagram_offset; 00221 err_t err = ERR_IF; 00222 00223 /* We'll use a dedicated pbuf for building 6LowPAN fragments. */ 00224 p_frag = pbuf_alloc(PBUF_RAW, 127, PBUF_RAM); 00225 if (p_frag == NULL) { 00226 MIB2_STATS_NETIF_INC(netif, ifoutdiscards); 00227 return ERR_MEM; 00228 } 00229 00230 /* Write IEEE 802.15.4 header. */ 00231 buffer = (u8_t*)p_frag->payload; 00232 ieee_header_len = 0; 00233 if (dst == &ieee_802154_broadcast) { 00234 buffer[ieee_header_len++] = 0x01; /* data packet, no ack required. */ 00235 } else { 00236 buffer[ieee_header_len++] = 0x21; /* data packet, ack required. */ 00237 } 00238 buffer[ieee_header_len] = (0x00 << 4); /* 2003 frame version */ 00239 buffer[ieee_header_len] |= (dst->addr_len == 2) ? (0x02 << 2) : (0x03 << 2); /* destination addressing mode */ 00240 buffer[ieee_header_len] |= (src->addr_len == 2) ? (0x02 << 6) : (0x03 << 6); /* source addressing mode */ 00241 ieee_header_len++; 00242 buffer[ieee_header_len++] = frame_seq_num++; 00243 00244 buffer[ieee_header_len++] = ieee_802154_pan_id & 0xff; /* pan id */ 00245 buffer[ieee_header_len++] = (ieee_802154_pan_id >> 8) & 0xff; /* pan id */ 00246 i = dst->addr_len; 00247 while (i-- > 0) { 00248 buffer[ieee_header_len++] = dst->addr[i]; 00249 } 00250 00251 buffer[ieee_header_len++] = ieee_802154_pan_id & 0xff; /* pan id */ 00252 buffer[ieee_header_len++] = (ieee_802154_pan_id >> 8) & 0xff; /* pan id */ 00253 i = src->addr_len; 00254 while (i-- > 0) { 00255 buffer[ieee_header_len++] = src->addr[i]; 00256 } 00257 00258 #if LWIP_6LOWPAN_IPHC 00259 /* Perform 6LowPAN IPv6 header compression according to RFC 6282 */ 00260 { 00261 struct ip6_hdr *ip6hdr; 00262 00263 /* Point to ip6 header and align copies of src/dest addresses. */ 00264 ip6hdr = (struct ip6_hdr *)p->payload; 00265 ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest); 00266 ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src); 00267 00268 /* Basic length of 6LowPAN header, set dispatch and clear fields. */ 00269 lowpan6_header_len = 2; 00270 buffer[ieee_header_len] = 0x60; 00271 buffer[ieee_header_len + 1] = 0; 00272 00273 /* Determine whether there will be a Context Identifier Extension byte or not. 00274 * If so, set it already. */ 00275 #if LWIP_6LOWPAN_NUM_CONTEXTS > 0 00276 buffer[ieee_header_len + 2] = 0; 00277 00278 i = lowpan6_context_lookup(ip_2_ip6(&ip_data.current_iphdr_src)); 00279 if (i >= 0) { 00280 /* Stateful source address compression. */ 00281 buffer[ieee_header_len + 1] |= 0x40; 00282 buffer[ieee_header_len + 2] |= (i & 0x0f) << 4; 00283 } 00284 00285 i = lowpan6_context_lookup(ip_2_ip6(&ip_data.current_iphdr_dest)); 00286 if (i >= 0) { 00287 /* Stateful destination address compression. */ 00288 buffer[ieee_header_len + 1] |= 0x04; 00289 buffer[ieee_header_len + 2] |= i & 0x0f; 00290 } 00291 00292 if (buffer[ieee_header_len + 2] != 0x00) { 00293 /* Context identifier extension byte is appended. */ 00294 buffer[ieee_header_len + 1] |= 0x80; 00295 lowpan6_header_len++; 00296 } 00297 #endif /* LWIP_6LOWPAN_NUM_CONTEXTS > 0 */ 00298 00299 /* Determine TF field: Traffic Class, Flow Label */ 00300 if (IP6H_FL(ip6hdr) == 0) { 00301 /* Flow label is elided. */ 00302 buffer[ieee_header_len] |= 0x10; 00303 if (IP6H_TC(ip6hdr) == 0) { 00304 /* Traffic class (ECN+DSCP) elided too. */ 00305 buffer[ieee_header_len] |= 0x08; 00306 } else { 00307 /* Traffic class (ECN+DSCP) appended. */ 00308 buffer[ieee_header_len + lowpan6_header_len++] = IP6H_TC(ip6hdr); 00309 } 00310 } else { 00311 if (((IP6H_TC(ip6hdr) & 0x3f) == 0)) { 00312 /* DSCP portion of Traffic Class is elided, ECN and FL are appended (3 bytes) */ 00313 buffer[ieee_header_len] |= 0x08; 00314 00315 buffer[ieee_header_len + lowpan6_header_len] = IP6H_TC(ip6hdr) & 0xc0; 00316 buffer[ieee_header_len + lowpan6_header_len++] |= (IP6H_FL(ip6hdr) >> 16) & 0x0f; 00317 buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 8) & 0xff; 00318 buffer[ieee_header_len + lowpan6_header_len++] = IP6H_FL(ip6hdr) & 0xff; 00319 } else { 00320 /* Traffic class and flow label are appended (4 bytes) */ 00321 buffer[ieee_header_len + lowpan6_header_len++] = IP6H_TC(ip6hdr); 00322 buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 16) & 0x0f; 00323 buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 8) & 0xff; 00324 buffer[ieee_header_len + lowpan6_header_len++] = IP6H_FL(ip6hdr) & 0xff; 00325 } 00326 } 00327 00328 /* Compress NH? 00329 * Only if UDP for now. @todo support other NH compression. */ 00330 if (IP6H_NEXTH(ip6hdr) == IP6_NEXTH_UDP) { 00331 buffer[ieee_header_len] |= 0x04; 00332 } else { 00333 /* append nexth. */ 00334 buffer[ieee_header_len + lowpan6_header_len++] = IP6H_NEXTH(ip6hdr); 00335 } 00336 00337 /* Compress hop limit? */ 00338 if (IP6H_HOPLIM(ip6hdr) == 255) { 00339 buffer[ieee_header_len] |= 0x03; 00340 } else if (IP6H_HOPLIM(ip6hdr) == 64) { 00341 buffer[ieee_header_len] |= 0x02; 00342 } else if (IP6H_HOPLIM(ip6hdr) == 1) { 00343 buffer[ieee_header_len] |= 0x01; 00344 } else { 00345 /* append hop limit */ 00346 buffer[ieee_header_len + lowpan6_header_len++] = IP6H_HOPLIM(ip6hdr); 00347 } 00348 00349 /* Compress source address */ 00350 if (((buffer[ieee_header_len + 1] & 0x40) != 0) || 00351 (ip6_addr_islinklocal(ip_2_ip6(&ip_data.current_iphdr_src)))) { 00352 /* Context-based or link-local source address compression. */ 00353 i = lowpan6_get_address_mode(ip_2_ip6(&ip_data.current_iphdr_src), src); 00354 buffer[ieee_header_len + 1] |= (i & 0x03) << 4; 00355 if (i == 1) { 00356 MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 16, 8); 00357 lowpan6_header_len += 8; 00358 } else if (i == 2) { 00359 MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 22, 2); 00360 lowpan6_header_len += 2; 00361 } 00362 } else if (ip6_addr_isany(ip_2_ip6(&ip_data.current_iphdr_src))) { 00363 /* Special case: mark SAC and leave SAM=0 */ 00364 buffer[ieee_header_len + 1] |= 0x40; 00365 } else { 00366 /* Append full address. */ 00367 MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 8, 16); 00368 lowpan6_header_len += 16; 00369 } 00370 00371 /* Compress destination address */ 00372 if (ip6_addr_ismulticast(ip_2_ip6(&ip_data.current_iphdr_dest))) { 00373 /* @todo support stateful multicast address compression */ 00374 00375 buffer[ieee_header_len + 1] |= 0x08; 00376 00377 i = lowpan6_get_address_mode_mc(ip_2_ip6(&ip_data.current_iphdr_dest)); 00378 buffer[ieee_header_len + 1] |= i & 0x03; 00379 if (i == 0) { 00380 MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 24, 16); 00381 lowpan6_header_len += 16; 00382 } else if (i == 1) { 00383 buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[25]; 00384 MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 35, 5); 00385 lowpan6_header_len += 5; 00386 } else if (i == 2) { 00387 buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[25]; 00388 MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 37, 3); 00389 lowpan6_header_len += 3; 00390 } else if (i == 3) { 00391 buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[39]; 00392 } 00393 } else if (((buffer[ieee_header_len + 1] & 0x04) != 0) || 00394 (ip6_addr_islinklocal(ip_2_ip6(&ip_data.current_iphdr_dest)))) { 00395 /* Context-based or link-local destination address compression. */ 00396 i = lowpan6_get_address_mode(ip_2_ip6(&ip_data.current_iphdr_dest), dst); 00397 buffer[ieee_header_len + 1] |= i & 0x03; 00398 if (i == 1) { 00399 MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 32, 8); 00400 lowpan6_header_len += 8; 00401 } else if (i == 2) { 00402 MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 38, 2); 00403 lowpan6_header_len += 2; 00404 } 00405 } else { 00406 /* Append full address. */ 00407 MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 24, 16); 00408 lowpan6_header_len += 16; 00409 } 00410 00411 /* Move to payload. */ 00412 pbuf_header(p, -IP6_HLEN); 00413 00414 /* Compress UDP header? */ 00415 if (IP6H_NEXTH(ip6hdr) == IP6_NEXTH_UDP) { 00416 /* @todo support optional checksum compression */ 00417 00418 buffer[ieee_header_len + lowpan6_header_len] = 0xf0; 00419 00420 /* determine port compression mode. */ 00421 if ((((u8_t *)p->payload)[0] == 0xf0) && ((((u8_t *)p->payload)[1] & 0xf0) == 0xb0) && 00422 (((u8_t *)p->payload)[2] == 0xf0) && ((((u8_t *)p->payload)[3] & 0xf0) == 0xb0)) { 00423 /* Compress source and dest ports. */ 00424 buffer[ieee_header_len + lowpan6_header_len++] |= 0x03; 00425 buffer[ieee_header_len + lowpan6_header_len++] = ((((u8_t *)p->payload)[1] & 0x0f) << 4) | (((u8_t *)p->payload)[3] & 0x0f); 00426 } else if (((u8_t *)p->payload)[0] == 0xf0) { 00427 /* Compress source port. */ 00428 buffer[ieee_header_len + lowpan6_header_len++] |= 0x02; 00429 buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1]; 00430 buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[2]; 00431 buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3]; 00432 } else if (((u8_t *)p->payload)[2] == 0xf0) { 00433 /* Compress dest port. */ 00434 buffer[ieee_header_len + lowpan6_header_len++] |= 0x01; 00435 buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[0]; 00436 buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1]; 00437 buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3]; 00438 } else { 00439 /* append full ports. */ 00440 lowpan6_header_len++; 00441 buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[0]; 00442 buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1]; 00443 buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[2]; 00444 buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3]; 00445 } 00446 00447 /* elide length and copy checksum */ 00448 buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[6]; 00449 buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[7]; 00450 00451 pbuf_header(p, -UDP_HLEN); 00452 } 00453 } 00454 00455 #else /* LWIP_6LOWPAN_HC */ 00456 /* Send uncompressed IPv6 header with appropriate dispatch byte. */ 00457 lowpan6_header_len = 1; 00458 buffer[ieee_header_len] = 0x41; /* IPv6 dispatch */ 00459 #endif /* LWIP_6LOWPAN_HC */ 00460 00461 /* Calculate remaining packet length */ 00462 remaining_len = p->tot_len; 00463 00464 if (remaining_len > 0x7FF) { 00465 MIB2_STATS_NETIF_INC(netif, ifoutdiscards); 00466 /* datagram_size must fit into 11 bit */ 00467 pbuf_free(p_frag); 00468 return ERR_VAL; 00469 } 00470 00471 /* Fragment, or 1 packet? */ 00472 if (remaining_len > (127 - ieee_header_len - lowpan6_header_len - 3)) { /* 127 - header - 1 byte dispatch - 2 bytes CRC */ 00473 /* We must move the 6LowPAN header to make room for the FRAG header. */ 00474 i = lowpan6_header_len; 00475 while (i-- != 0) { 00476 buffer[ieee_header_len + i + 4] = buffer[ieee_header_len + i]; 00477 } 00478 00479 /* Now we need to fragment the packet. FRAG1 header first */ 00480 buffer[ieee_header_len] = 0xc0 | (((p->tot_len + lowpan6_header_len) >> 8) & 0x7); 00481 buffer[ieee_header_len + 1] = (p->tot_len + lowpan6_header_len) & 0xff; 00482 00483 datagram_tag++; 00484 buffer[ieee_header_len + 2] = datagram_tag & 0xff; 00485 buffer[ieee_header_len + 3] = (datagram_tag >> 8) & 0xff; 00486 00487 /* Fragment follows. */ 00488 frag_len = (127 - ieee_header_len - 4 - 2) & 0xf8; 00489 00490 pbuf_copy_partial(p, buffer + ieee_header_len + lowpan6_header_len + 4, frag_len - lowpan6_header_len, 0); 00491 remaining_len -= frag_len - lowpan6_header_len; 00492 datagram_offset = frag_len; 00493 00494 /* 2 bytes CRC */ 00495 #if LWIP_6LOWPAN_HW_CRC 00496 /* Leave blank, will be filled by HW. */ 00497 #else /* LWIP_6LOWPAN_HW_CRC */ 00498 /* @todo calculate CRC */ 00499 #endif /* LWIP_6LOWPAN_HW_CRC */ 00500 00501 /* Calculate frame length */ 00502 p_frag->len = p_frag->tot_len = ieee_header_len + 4 + frag_len + 2; /* add 2 dummy bytes for crc*/ 00503 00504 /* send the packet */ 00505 MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len); 00506 LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p)); 00507 err = netif->linkoutput(netif, p_frag); 00508 00509 while ((remaining_len > 0) && (err == ERR_OK)) { 00510 /* new frame, new seq num for ACK */ 00511 buffer[2] = frame_seq_num++; 00512 00513 buffer[ieee_header_len] |= 0x20; /* Change FRAG1 to FRAGN */ 00514 00515 buffer[ieee_header_len + 4] = (u8_t)(datagram_offset >> 3); /* datagram offset in FRAGN header (datagram_offset is max. 11 bit) */ 00516 00517 frag_len = (127 - ieee_header_len - 5 - 2) & 0xf8; 00518 if (frag_len > remaining_len) { 00519 frag_len = remaining_len; 00520 } 00521 00522 pbuf_copy_partial(p, buffer + ieee_header_len + 5, frag_len, p->tot_len - remaining_len); 00523 remaining_len -= frag_len; 00524 datagram_offset += frag_len; 00525 00526 /* 2 bytes CRC */ 00527 #if LWIP_6LOWPAN_HW_CRC 00528 /* Leave blank, will be filled by HW. */ 00529 #else /* LWIP_6LOWPAN_HW_CRC */ 00530 /* @todo calculate CRC */ 00531 #endif /* LWIP_6LOWPAN_HW_CRC */ 00532 00533 /* Calculate frame length */ 00534 p_frag->len = p_frag->tot_len = frag_len + 5 + ieee_header_len + 2; 00535 00536 /* send the packet */ 00537 MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len); 00538 LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p)); 00539 err = netif->linkoutput(netif, p_frag); 00540 } 00541 } else { 00542 /* It fits in one frame. */ 00543 frag_len = remaining_len; 00544 00545 /* Copy IPv6 packet */ 00546 pbuf_copy_partial(p, buffer + ieee_header_len + lowpan6_header_len, frag_len, 0); 00547 remaining_len = 0; 00548 00549 /* 2 bytes CRC */ 00550 #if LWIP_6LOWPAN_HW_CRC 00551 /* Leave blank, will be filled by HW. */ 00552 #else /* LWIP_6LOWPAN_HW_CRC */ 00553 /* @todo calculate CRC */ 00554 #endif /* LWIP_6LOWPAN_HW_CRC */ 00555 00556 /* Calculate frame length */ 00557 p_frag->len = p_frag->tot_len = frag_len + lowpan6_header_len + ieee_header_len + 2; 00558 00559 /* send the packet */ 00560 MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len); 00561 LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p)); 00562 err = netif->linkoutput(netif, p_frag); 00563 } 00564 00565 pbuf_free(p_frag); 00566 00567 return err; 00568 } 00569 00570 err_t 00571 lowpan6_set_context(u8_t idx, const ip6_addr_t * context) 00572 { 00573 if (idx >= LWIP_6LOWPAN_NUM_CONTEXTS) { 00574 return ERR_ARG; 00575 } 00576 00577 ip6_addr_set(&lowpan6_context[idx], context); 00578 00579 return ERR_OK; 00580 } 00581 00582 #if LWIP_6LOWPAN_INFER_SHORT_ADDRESS 00583 err_t 00584 lowpan6_set_short_addr(u8_t addr_high, u8_t addr_low) 00585 { 00586 short_mac_addr.addr[0] = addr_high; 00587 short_mac_addr.addr[1] = addr_low; 00588 00589 return ERR_OK; 00590 } 00591 #endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ 00592 00593 #if LWIP_IPV4 00594 err_t 00595 lowpan4_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) 00596 { 00597 (void)netif; 00598 (void)q; 00599 (void)ipaddr; 00600 00601 return ERR_IF; 00602 } 00603 #endif /* LWIP_IPV4 */ 00604 00605 /** 00606 * Resolve and fill-in IEEE 802.15.4 address header for outgoing IPv6 packet. 00607 * 00608 * Perform Header Compression and fragment if necessary. 00609 * 00610 * @param netif The lwIP network interface which the IP packet will be sent on. 00611 * @param q The pbuf(s) containing the IP packet to be sent. 00612 * @param ip6addr The IP address of the packet destination. 00613 * 00614 * @return 00615 */ 00616 err_t 00617 lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) 00618 { 00619 s8_t i; 00620 struct ieee_802154_addr src, dest; 00621 #if LWIP_6LOWPAN_INFER_SHORT_ADDRESS 00622 ip6_addr_t ip6_src; 00623 struct ip6_hdr * ip6_hdr; 00624 #endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ 00625 00626 #if LWIP_6LOWPAN_INFER_SHORT_ADDRESS 00627 /* Check if we can compress source address (use aligned copy) */ 00628 ip6_hdr = (struct ip6_hdr *)q->payload; 00629 ip6_addr_set(&ip6_src, &ip6_hdr->src); 00630 if (lowpan6_get_address_mode(&ip6_src, &short_mac_addr) == 3) { 00631 src.addr_len = 2; 00632 src.addr[0] = short_mac_addr.addr[0]; 00633 src.addr[1] = short_mac_addr.addr[1]; 00634 } else 00635 #endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ 00636 { 00637 src.addr_len = netif->hwaddr_len; 00638 SMEMCPY(src.addr, netif->hwaddr, netif->hwaddr_len); 00639 } 00640 00641 /* multicast destination IP address? */ 00642 if (ip6_addr_ismulticast(ip6addr)) { 00643 MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts); 00644 /* We need to send to the broadcast address.*/ 00645 return lowpan6_frag(netif, q, &src, &ieee_802154_broadcast); 00646 } 00647 00648 /* We have a unicast destination IP address */ 00649 /* @todo anycast? */ 00650 00651 #if LWIP_6LOWPAN_INFER_SHORT_ADDRESS 00652 if (src.addr_len == 2) { 00653 /* If source address was compressable to short_mac_addr, and dest has same subnet and 00654 * is also compressable to 2-bytes, assume we can infer dest as a short address too. */ 00655 dest.addr_len = 2; 00656 dest.addr[0] = ((u8_t *)q->payload)[38]; 00657 dest.addr[1] = ((u8_t *)q->payload)[39]; 00658 if ((src.addr_len == 2) && (ip6_addr_netcmp(&ip6_hdr->src, &ip6_hdr->dest)) && 00659 (lowpan6_get_address_mode(ip6addr, &dest) == 3)) { 00660 MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); 00661 return lowpan6_frag(netif, q, &src, &dest); 00662 } 00663 } 00664 #endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ 00665 00666 00667 /* Get next hop record. */ 00668 i = nd6_get_next_hop_entry(ip6addr, netif); 00669 if (i < 0) { 00670 MIB2_STATS_NETIF_INC(netif, ifoutdiscards); 00671 /* failed to get a next hop neighbor record. */ 00672 return ERR_MEM; 00673 } 00674 00675 /* Now that we have a destination record, send or queue the packet. */ 00676 if (neighbor_cache[i].state == ND6_STALE) { 00677 /* Switch to delay state. */ 00678 neighbor_cache[i].state = ND6_DELAY; 00679 neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; 00680 } 00681 /* @todo should we send or queue if PROBE? send for now, to let unicast NS pass. */ 00682 if ((neighbor_cache[i].state == ND6_REACHABLE) || 00683 (neighbor_cache[i].state == ND6_DELAY) || 00684 (neighbor_cache[i].state == ND6_PROBE)) { 00685 00686 /* Send out. */ 00687 dest.addr_len = netif->hwaddr_len; 00688 SMEMCPY(dest.addr, neighbor_cache[i].lladdr, netif->hwaddr_len); 00689 MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); 00690 return lowpan6_frag(netif, q, &src, &dest); 00691 } 00692 00693 /* We should queue packet on this interface. */ 00694 return nd6_queue_packet(i, q); 00695 } 00696 00697 static struct pbuf * 00698 lowpan6_decompress(struct pbuf * p, struct ieee_802154_addr * src, struct ieee_802154_addr * dest) 00699 { 00700 struct pbuf * q; 00701 u8_t * lowpan6_buffer; 00702 s8_t lowpan6_offset; 00703 struct ip6_hdr *ip6hdr; 00704 s8_t i; 00705 s8_t ip6_offset = IP6_HLEN; 00706 00707 00708 q = pbuf_alloc(PBUF_IP, p->len + IP6_HLEN + UDP_HLEN, PBUF_POOL); 00709 if (q == NULL) { 00710 pbuf_free(p); 00711 return NULL; 00712 } 00713 00714 lowpan6_buffer = (u8_t *)p->payload; 00715 ip6hdr = (struct ip6_hdr *)q->payload; 00716 00717 lowpan6_offset = 2; 00718 if (lowpan6_buffer[1] & 0x80) { 00719 lowpan6_offset++; 00720 } 00721 00722 /* Set IPv6 version, traffic class and flow label. */ 00723 if ((lowpan6_buffer[0] & 0x18) == 0x00) { 00724 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]); 00725 lowpan6_offset += 4; 00726 } else if ((lowpan6_buffer[0] & 0x18) == 0x08) { 00727 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]); 00728 lowpan6_offset += 3; 00729 } else if ((lowpan6_buffer[0] & 0x18) == 0x10) { 00730 IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset],0); 00731 lowpan6_offset += 1; 00732 } else if ((lowpan6_buffer[0] & 0x18) == 0x18) { 00733 IP6H_VTCFL_SET(ip6hdr, 6, 0, 0); 00734 } 00735 00736 /* Set Next Header */ 00737 if ((lowpan6_buffer[0] & 0x04) == 0x00) { 00738 IP6H_NEXTH_SET(ip6hdr, lowpan6_buffer[lowpan6_offset++]); 00739 } else { 00740 /* We should fill this later with NHC decoding */ 00741 IP6H_NEXTH_SET(ip6hdr, 0); 00742 } 00743 00744 /* Set Hop Limit */ 00745 if ((lowpan6_buffer[0] & 0x03) == 0x00) { 00746 IP6H_HOPLIM_SET(ip6hdr, lowpan6_buffer[lowpan6_offset++]); 00747 } else if ((lowpan6_buffer[0] & 0x03) == 0x01) { 00748 IP6H_HOPLIM_SET(ip6hdr, 1); 00749 } else if ((lowpan6_buffer[0] & 0x03) == 0x02) { 00750 IP6H_HOPLIM_SET(ip6hdr, 64); 00751 } else if ((lowpan6_buffer[0] & 0x03) == 0x03) { 00752 IP6H_HOPLIM_SET(ip6hdr, 255); 00753 } 00754 00755 /* Source address decoding. */ 00756 if ((lowpan6_buffer[1] & 0x40) == 0x00) { 00757 /* Stateless compression */ 00758 if ((lowpan6_buffer[1] & 0x30) == 0x00) { 00759 /* copy full address */ 00760 MEMCPY(&ip6hdr->src.addr[0], lowpan6_buffer + lowpan6_offset, 16); 00761 lowpan6_offset += 16; 00762 } else if ((lowpan6_buffer[1] & 0x30) == 0x10) { 00763 ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL); 00764 ip6hdr->src.addr[1] = 0; 00765 MEMCPY(&ip6hdr->src.addr[2], lowpan6_buffer + lowpan6_offset, 8); 00766 lowpan6_offset += 8; 00767 } else if ((lowpan6_buffer[1] & 0x30) == 0x20) { 00768 ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL); 00769 ip6hdr->src.addr[1] = 0; 00770 ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); 00771 ip6hdr->src.addr[3] = htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | 00772 lowpan6_buffer[lowpan6_offset+1]); 00773 lowpan6_offset += 2; 00774 } else if ((lowpan6_buffer[1] & 0x30) == 0x30) { 00775 ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL); 00776 ip6hdr->src.addr[1] = 0; 00777 if (src->addr_len == 2) { 00778 ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); 00779 ip6hdr->src.addr[3] = htonl(0xfe000000UL | (src->addr[0] << 8) | src->addr[1]); 00780 } else { 00781 ip6hdr->src.addr[2] = htonl(((src->addr[0] ^ 2) << 24) | (src->addr[1] << 16) | 00782 (src->addr[2] << 8) | src->addr[3]); 00783 ip6hdr->src.addr[3] = htonl((src->addr[4] << 24) | (src->addr[5] << 16) | 00784 (src->addr[6] << 8) | src->addr[7]); 00785 } 00786 } 00787 } else { 00788 /* Stateful compression */ 00789 if ((lowpan6_buffer[1] & 0x30) == 0x00) { 00790 /* ANY address */ 00791 ip6hdr->src.addr[0] = 0; 00792 ip6hdr->src.addr[1] = 0; 00793 ip6hdr->src.addr[2] = 0; 00794 ip6hdr->src.addr[3] = 0; 00795 } else { 00796 /* Set prefix from context info */ 00797 if (lowpan6_buffer[1] & 0x80) { 00798 i = (lowpan6_buffer[2] >> 4) & 0x0f; 00799 } else { 00800 i = 0; 00801 } 00802 if (i >= LWIP_6LOWPAN_NUM_CONTEXTS) { 00803 /* Error */ 00804 pbuf_free(p); 00805 pbuf_free(q); 00806 return NULL; 00807 } 00808 00809 ip6hdr->src.addr[0] = lowpan6_context[i].addr[0]; 00810 ip6hdr->src.addr[1] = lowpan6_context[i].addr[1]; 00811 } 00812 00813 if ((lowpan6_buffer[1] & 0x30) == 0x10) { 00814 MEMCPY(&ip6hdr->src.addr[2], lowpan6_buffer + lowpan6_offset, 8); 00815 lowpan6_offset += 8; 00816 } else if ((lowpan6_buffer[1] & 0x30) == 0x20) { 00817 ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); 00818 ip6hdr->src.addr[3] = htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset+1]); 00819 lowpan6_offset += 2; 00820 } else if ((lowpan6_buffer[1] & 0x30) == 0x30) { 00821 if (src->addr_len == 2) { 00822 ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); 00823 ip6hdr->src.addr[3] = htonl(0xfe000000UL | (src->addr[0] << 8) | src->addr[1]); 00824 } else { 00825 ip6hdr->src.addr[2] = htonl(((src->addr[0] ^ 2) << 24) | (src->addr[1] << 16) | (src->addr[2] << 8) | src->addr[3]); 00826 ip6hdr->src.addr[3] = htonl((src->addr[4] << 24) | (src->addr[5] << 16) | (src->addr[6] << 8) | src->addr[7]); 00827 } 00828 } 00829 } 00830 00831 /* Destination address decoding. */ 00832 if (lowpan6_buffer[1] & 0x08) { 00833 /* Multicast destination */ 00834 if (lowpan6_buffer[1] & 0x04) { 00835 /* @todo support stateful multicast addressing */ 00836 pbuf_free(p); 00837 pbuf_free(q); 00838 return NULL; 00839 } 00840 00841 if ((lowpan6_buffer[1] & 0x03) == 0x00) { 00842 /* copy full address */ 00843 MEMCPY(&ip6hdr->dest.addr[0], lowpan6_buffer + lowpan6_offset, 16); 00844 lowpan6_offset += 16; 00845 } else if ((lowpan6_buffer[1] & 0x03) == 0x01) { 00846 ip6hdr->dest.addr[0] = htonl(0xff000000UL | (lowpan6_buffer[lowpan6_offset++] << 16)); 00847 ip6hdr->dest.addr[1] = 0; 00848 ip6hdr->dest.addr[2] = htonl(lowpan6_buffer[lowpan6_offset++]); 00849 ip6hdr->dest.addr[3] = htonl((lowpan6_buffer[lowpan6_offset] << 24) | (lowpan6_buffer[lowpan6_offset + 1] << 16) | (lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset + 3]); 00850 lowpan6_offset += 4; 00851 } else if ((lowpan6_buffer[1] & 0x03) == 0x02) { 00852 ip6hdr->dest.addr[0] = htonl(0xff000000UL | lowpan6_buffer[lowpan6_offset++]); 00853 ip6hdr->dest.addr[1] = 0; 00854 ip6hdr->dest.addr[2] = 0; 00855 ip6hdr->dest.addr[3] = htonl((lowpan6_buffer[lowpan6_offset] << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset + 2]); 00856 lowpan6_offset += 3; 00857 } else if ((lowpan6_buffer[1] & 0x03) == 0x03) { 00858 ip6hdr->dest.addr[0] = PP_HTONL(0xff020000UL); 00859 ip6hdr->dest.addr[1] = 0; 00860 ip6hdr->dest.addr[2] = 0; 00861 ip6hdr->dest.addr[3] = htonl(lowpan6_buffer[lowpan6_offset++]); 00862 } 00863 00864 } else { 00865 if (lowpan6_buffer[1] & 0x04) { 00866 /* Stateful destination compression */ 00867 /* Set prefix from context info */ 00868 if (lowpan6_buffer[1] & 0x80) { 00869 i = lowpan6_buffer[2] & 0x0f; 00870 } else { 00871 i = 0; 00872 } 00873 if (i >= LWIP_6LOWPAN_NUM_CONTEXTS) { 00874 /* Error */ 00875 pbuf_free(p); 00876 pbuf_free(q); 00877 return NULL; 00878 } 00879 00880 ip6hdr->dest.addr[0] = lowpan6_context[i].addr[0]; 00881 ip6hdr->dest.addr[1] = lowpan6_context[i].addr[1]; 00882 } else { 00883 /* Link local address compression */ 00884 ip6hdr->dest.addr[0] = PP_HTONL(0xfe800000UL); 00885 ip6hdr->dest.addr[1] = 0; 00886 } 00887 00888 if ((lowpan6_buffer[1] & 0x03) == 0x00) { 00889 /* copy full address */ 00890 MEMCPY(&ip6hdr->dest.addr[0], lowpan6_buffer + lowpan6_offset, 16); 00891 lowpan6_offset += 16; 00892 } else if ((lowpan6_buffer[1] & 0x03) == 0x01) { 00893 MEMCPY(&ip6hdr->dest.addr[2], lowpan6_buffer + lowpan6_offset, 8); 00894 lowpan6_offset += 8; 00895 } else if ((lowpan6_buffer[1] & 0x03) == 0x02) { 00896 ip6hdr->dest.addr[2] = PP_HTONL(0x000000ffUL); 00897 ip6hdr->dest.addr[3] = htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset + 1]); 00898 lowpan6_offset += 2; 00899 } else if ((lowpan6_buffer[1] & 0x03) == 0x03) { 00900 if (dest->addr_len == 2) { 00901 ip6hdr->dest.addr[2] = PP_HTONL(0x000000ffUL); 00902 ip6hdr->dest.addr[3] = htonl(0xfe000000UL | (dest->addr[0] << 8) | dest->addr[1]); 00903 } else { 00904 ip6hdr->dest.addr[2] = htonl(((dest->addr[0] ^ 2) << 24) | (dest->addr[1] << 16) | dest->addr[2] << 8 | dest->addr[3]); 00905 ip6hdr->dest.addr[3] = htonl((dest->addr[4] << 24) | (dest->addr[5] << 16) | dest->addr[6] << 8 | dest->addr[7]); 00906 } 00907 } 00908 } 00909 00910 00911 /* Next Header Compression (NHC) decoding? */ 00912 if (lowpan6_buffer[0] & 0x04) { 00913 if ((lowpan6_buffer[lowpan6_offset] & 0xf8) == 0xf0) { 00914 struct udp_hdr *udphdr; 00915 00916 /* UDP compression */ 00917 IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_UDP); 00918 udphdr = (struct udp_hdr *)((u8_t *)q->payload + ip6_offset); 00919 00920 if (lowpan6_buffer[lowpan6_offset] & 0x04) { 00921 /* @todo support checksum decompress */ 00922 pbuf_free(p); 00923 pbuf_free(q); 00924 return NULL; 00925 } 00926 00927 /* Decompress ports */ 00928 i = lowpan6_buffer[lowpan6_offset++] & 0x03; 00929 if (i == 0) { 00930 udphdr->src = htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); 00931 udphdr->dest = htons(lowpan6_buffer[lowpan6_offset + 2] << 8 | lowpan6_buffer[lowpan6_offset + 3]); 00932 lowpan6_offset += 4; 00933 } else if (i == 0x01) { 00934 udphdr->src = htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); 00935 udphdr->dest = htons(0xf000 | lowpan6_buffer[lowpan6_offset + 2]); 00936 lowpan6_offset += 3; 00937 } else if (i == 0x02) { 00938 udphdr->src = htons(0xf000 | lowpan6_buffer[lowpan6_offset]); 00939 udphdr->dest = htons(lowpan6_buffer[lowpan6_offset + 1] << 8 | lowpan6_buffer[lowpan6_offset + 2]); 00940 lowpan6_offset += 3; 00941 } else if (i == 0x03) { 00942 udphdr->src = htons(0xf0b0 | ((lowpan6_buffer[lowpan6_offset] >> 4) & 0x0f)); 00943 udphdr->dest = htons(0xf0b0 | (lowpan6_buffer[lowpan6_offset] & 0x0f)); 00944 lowpan6_offset += 1; 00945 } 00946 00947 udphdr->chksum = htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); 00948 lowpan6_offset += 2; 00949 udphdr->len = htons(p->tot_len - lowpan6_offset + UDP_HLEN); 00950 00951 ip6_offset += UDP_HLEN; 00952 } else { 00953 /* @todo support NHC other than UDP */ 00954 pbuf_free(p); 00955 pbuf_free(q); 00956 return NULL; 00957 } 00958 } 00959 00960 /* Now we copy leftover contents from p to q, so we have all L2 and L3 headers (and L4?) in a single PBUF. 00961 * Replace p with q, and free p */ 00962 pbuf_header(p, -lowpan6_offset); 00963 MEMCPY((u8_t*)q->payload + ip6_offset, p->payload, p->len); 00964 q->len = q->tot_len = ip6_offset + p->len; 00965 if (p->next != NULL) { 00966 pbuf_cat(q, p->next); 00967 } 00968 p->next = NULL; 00969 pbuf_free(p); 00970 00971 /* Infer IPv6 payload length for header */ 00972 IP6H_PLEN_SET(ip6hdr, q->tot_len - IP6_HLEN); 00973 00974 /* all done */ 00975 return q; 00976 } 00977 00978 err_t 00979 lowpan6_input(struct pbuf * p, struct netif *netif) 00980 { 00981 u8_t * puc; 00982 s8_t i; 00983 struct ieee_802154_addr src, dest; 00984 u16_t datagram_size, datagram_offset, datagram_tag; 00985 struct lowpan6_reass_helper *lrh, *lrh_temp; 00986 00987 MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len); 00988 00989 /* Analyze header. @todo validate. */ 00990 puc = (u8_t*)p->payload; 00991 datagram_offset = 5; 00992 if ((puc[1] & 0x0c) == 0x0c) { 00993 dest.addr_len = 8; 00994 for (i = 0; i < 8; i++) { 00995 dest.addr[i] = puc[datagram_offset + 7 - i]; 00996 } 00997 datagram_offset += 8; 00998 } else { 00999 dest.addr_len = 2; 01000 dest.addr[0] = puc[datagram_offset + 1]; 01001 dest.addr[1] = puc[datagram_offset]; 01002 datagram_offset += 2; 01003 } 01004 01005 datagram_offset += 2; /* skip PAN ID. */ 01006 01007 if ((puc[1] & 0xc0) == 0xc0) { 01008 src.addr_len = 8; 01009 for (i = 0; i < 8; i++) { 01010 src.addr[i] = puc[datagram_offset + 7 - i]; 01011 } 01012 datagram_offset += 8; 01013 } else { 01014 src.addr_len = 2; 01015 src.addr[0] = puc[datagram_offset + 1]; 01016 src.addr[1] = puc[datagram_offset]; 01017 datagram_offset += 2; 01018 } 01019 01020 pbuf_header(p, -datagram_offset); /* hide IEEE802.15.4 header. */ 01021 01022 /* Check dispatch. */ 01023 puc = (u8_t*)p->payload; 01024 01025 if ((*puc & 0xf8) == 0xc0) { 01026 /* FRAG1 dispatch. add this packet to reassembly list. */ 01027 datagram_size = ((u16_t)(puc[0] & 0x07) << 8) | (u16_t)puc[1]; 01028 datagram_tag = ((u16_t)puc[2] << 8) | (u16_t)puc[3]; 01029 01030 /* check for duplicate */ 01031 lrh = reass_list; 01032 while (lrh != NULL) { 01033 if ((lrh->sender_addr.addr_len == src.addr_len) && 01034 (memcmp(lrh->sender_addr.addr, src.addr, src.addr_len) == 0)) { 01035 /* address match with packet in reassembly. */ 01036 if ((datagram_tag == lrh->datagram_tag) && (datagram_size == lrh->datagram_size)) { 01037 MIB2_STATS_NETIF_INC(netif, ifindiscards); 01038 /* duplicate fragment. */ 01039 pbuf_free(p); 01040 return ERR_OK; 01041 } else { 01042 /* We are receiving the start of a new datagram. Discard old one (incomplete). */ 01043 lrh_temp = lrh->next_packet; 01044 dequeue_datagram(lrh); 01045 pbuf_free(lrh->pbuf); 01046 mem_free(lrh); 01047 01048 /* Check next datagram in queue. */ 01049 lrh = lrh_temp; 01050 } 01051 } else { 01052 /* Check next datagram in queue. */ 01053 lrh = lrh->next_packet; 01054 } 01055 } 01056 01057 pbuf_header(p, -4); /* hide frag1 dispatch */ 01058 01059 lrh = (struct lowpan6_reass_helper *) mem_malloc(sizeof(struct lowpan6_reass_helper)); 01060 if (lrh == NULL) { 01061 MIB2_STATS_NETIF_INC(netif, ifindiscards); 01062 pbuf_free(p); 01063 return ERR_MEM; 01064 } 01065 01066 lrh->sender_addr.addr_len = src.addr_len; 01067 for (i = 0; i < src.addr_len; i++) { 01068 lrh->sender_addr.addr[i] = src.addr[i]; 01069 } 01070 lrh->datagram_size = datagram_size; 01071 lrh->datagram_tag = datagram_tag; 01072 lrh->pbuf = p; 01073 lrh->next_packet = reass_list; 01074 lrh->timer = 2; 01075 reass_list = lrh; 01076 01077 return ERR_OK; 01078 } else if ((*puc & 0xf8) == 0xe0) { 01079 /* FRAGN dispatch, find packet being reassembled. */ 01080 datagram_size = ((u16_t)(puc[0] & 0x07) << 8) | (u16_t)puc[1]; 01081 datagram_tag = ((u16_t)puc[2] << 8) | (u16_t)puc[3]; 01082 datagram_offset = (u16_t)puc[4] << 3; 01083 pbuf_header(p, -5); /* hide frag1 dispatch */ 01084 01085 for (lrh = reass_list; lrh != NULL; lrh = lrh->next_packet) { 01086 if ((lrh->sender_addr.addr_len == src.addr_len) && 01087 (memcmp(lrh->sender_addr.addr, src.addr, src.addr_len) == 0) && 01088 (datagram_tag == lrh->datagram_tag) && 01089 (datagram_size == lrh->datagram_size)) { 01090 break; 01091 } 01092 } 01093 if (lrh == NULL) { 01094 /* rogue fragment */ 01095 MIB2_STATS_NETIF_INC(netif, ifindiscards); 01096 pbuf_free(p); 01097 return ERR_OK; 01098 } 01099 01100 if (lrh->pbuf->tot_len < datagram_offset) { 01101 /* duplicate, ignore. */ 01102 pbuf_free(p); 01103 return ERR_OK; 01104 } else if (lrh->pbuf->tot_len > datagram_offset) { 01105 MIB2_STATS_NETIF_INC(netif, ifindiscards); 01106 /* We have missed a fragment. Delete whole reassembly. */ 01107 dequeue_datagram(lrh); 01108 pbuf_free(lrh->pbuf); 01109 mem_free(lrh); 01110 pbuf_free(p); 01111 return ERR_OK; 01112 } 01113 pbuf_cat(lrh->pbuf, p); 01114 p = NULL; 01115 01116 /* is packet now complete?*/ 01117 if (lrh->pbuf->tot_len >= lrh->datagram_size) { 01118 /* dequeue from reass list. */ 01119 dequeue_datagram(lrh); 01120 01121 /* get pbuf */ 01122 p = lrh->pbuf; 01123 01124 /* release helper */ 01125 mem_free(lrh); 01126 } else { 01127 return ERR_OK; 01128 } 01129 } 01130 01131 if (p == NULL) { 01132 return ERR_OK; 01133 } 01134 01135 /* We have a complete packet, check dispatch for headers. */ 01136 puc = (u8_t*)p->payload; 01137 01138 if (*puc == 0x41) { 01139 /* This is a complete IPv6 packet, just skip dispatch byte. */ 01140 pbuf_header(p, -1); /* hide dispatch byte. */ 01141 } else if ((*puc & 0xe0 )== 0x60) { 01142 /* IPv6 headers are compressed using IPHC. */ 01143 p = lowpan6_decompress(p, &src, &dest); 01144 if (p == NULL) { 01145 MIB2_STATS_NETIF_INC(netif, ifindiscards); 01146 return ERR_OK; 01147 } 01148 } else { 01149 MIB2_STATS_NETIF_INC(netif, ifindiscards); 01150 pbuf_free(p); 01151 return ERR_OK; 01152 } 01153 01154 /* @todo: distinguish unicast/multicast */ 01155 MIB2_STATS_NETIF_INC(netif, ifinucastpkts); 01156 01157 return ip6_input(p, netif); 01158 } 01159 01160 err_t 01161 lowpan6_if_init(struct netif *netif) 01162 { 01163 netif->name[0] = 'L'; 01164 netif->name[1] = '6'; 01165 #if LWIP_IPV4 01166 netif->output = lowpan4_output; 01167 #endif /* LWIP_IPV4 */ 01168 netif->output_ip6 = lowpan6_output; 01169 01170 MIB2_INIT_NETIF(netif, snmp_ifType_other, 0); 01171 01172 /* maximum transfer unit */ 01173 netif->mtu = 1280; 01174 01175 /* broadcast capability */ 01176 netif->flags = NETIF_FLAG_BROADCAST /* | NETIF_FLAG_LOWPAN6 */; 01177 01178 return ERR_OK; 01179 } 01180 01181 err_t 01182 lowpan6_set_pan_id(u16_t pan_id) 01183 { 01184 ieee_802154_pan_id = pan_id; 01185 01186 return ERR_OK; 01187 } 01188 01189 #if !NO_SYS 01190 /** 01191 * Pass a received packet to tcpip_thread for input processing 01192 * 01193 * @param p the received packet, p->payload pointing to the 01194 * IEEE 802.15.4 header. 01195 * @param inp the network interface on which the packet was received 01196 */ 01197 err_t 01198 tcpip_6lowpan_input(struct pbuf *p, struct netif *inp) 01199 { 01200 return tcpip_inpkt(p, inp, lowpan6_input); 01201 } 01202 #endif /* !NO_SYS */ 01203 01204 #endif /* LWIP_IPV6 && LWIP_6LOWPAN */
Generated on Tue Jul 12 2022 13:15:53 by
