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.
Dependents: mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510
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 11:02:41 by
