lowpan6.c 41 KB

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