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: TYBLE16_simple_data_logger TYBLE16_MP3_Air
lwip_zepif.c
00001 /** 00002 * @file 00003 * 00004 * @defgroup zepif ZEP - ZigBee Encapsulation Protocol 00005 * @ingroup netifs 00006 * A netif implementing the ZigBee Encapsulation Protocol (ZEP). 00007 * This is used to tunnel 6LowPAN over UDP. 00008 * 00009 * Usage (there must be a default netif before!): 00010 * @code{.c} 00011 * netif_add(&zep_netif, NULL, NULL, NULL, NULL, zepif_init, tcpip_6lowpan_input); 00012 * netif_create_ip6_linklocal_address(&zep_netif, 1); 00013 * netif_set_up(&zep_netif); 00014 * netif_set_link_up(&zep_netif); 00015 * @endcode 00016 */ 00017 00018 /* 00019 * Copyright (c) 2018 Simon Goldschmidt 00020 * All rights reserved. 00021 * 00022 * Redistribution and use in source and binary forms, with or without modification, 00023 * are permitted provided that the following conditions are met: 00024 * 00025 * 1. Redistributions of source code must retain the above copyright notice, 00026 * this list of conditions and the following disclaimer. 00027 * 2. Redistributions in binary form must reproduce the above copyright notice, 00028 * this list of conditions and the following disclaimer in the documentation 00029 * and/or other materials provided with the distribution. 00030 * 3. The name of the author may not be used to endorse or promote products 00031 * derived from this software without specific prior written permission. 00032 * 00033 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00034 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00035 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00036 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00037 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00038 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00039 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00040 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00041 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00042 * OF SUCH DAMAGE. 00043 * 00044 * This file is part of the lwIP TCP/IP stack. 00045 * 00046 * Author: Simon Goldschmidt <goldsimon@gmx.de> 00047 * 00048 */ 00049 00050 #include "netif/zepif.h" 00051 00052 #if LWIP_IPV6 && LWIP_UDP 00053 00054 #include "netif/lowpan6.h" 00055 #include "lwip/udp.h" 00056 #include "lwip/timeouts.h" 00057 #include <string.h> 00058 00059 /** Define this to 1 to loop back TX packets for testing */ 00060 #ifndef ZEPIF_LOOPBACK 00061 #define ZEPIF_LOOPBACK 0 00062 #endif 00063 00064 #define ZEP_MAX_DATA_LEN 127 00065 00066 #ifdef PACK_STRUCT_USE_INCLUDES 00067 # include "arch/bpstruct.h" 00068 #endif 00069 PACK_STRUCT_BEGIN 00070 struct zep_hdr { 00071 PACK_STRUCT_FLD_8(u8_t prot_id[2]); 00072 PACK_STRUCT_FLD_8(u8_t prot_version); 00073 PACK_STRUCT_FLD_8(u8_t type); 00074 PACK_STRUCT_FLD_8(u8_t channel_id); 00075 PACK_STRUCT_FIELD(u16_t device_id); 00076 PACK_STRUCT_FLD_8(u8_t crc_mode); 00077 PACK_STRUCT_FLD_8(u8_t unknown_1); 00078 PACK_STRUCT_FIELD(u32_t timestamp[2]); 00079 PACK_STRUCT_FIELD(u32_t seq_num); 00080 PACK_STRUCT_FLD_8(u8_t unknown_2[10]); 00081 PACK_STRUCT_FLD_8(u8_t len); 00082 } PACK_STRUCT_STRUCT; 00083 PACK_STRUCT_END 00084 #ifdef PACK_STRUCT_USE_INCLUDES 00085 # include "arch/epstruct.h" 00086 #endif 00087 00088 struct zepif_state { 00089 struct zepif_init init; 00090 struct udp_pcb *pcb; 00091 u32_t seqno; 00092 }; 00093 00094 static u8_t zep_lowpan_timer_running; 00095 00096 /* Helper function that calls the 6LoWPAN timer and reschedules itself */ 00097 static void 00098 zep_lowpan_timer(void *arg) 00099 { 00100 lowpan6_tmr(); 00101 if (zep_lowpan_timer_running) { 00102 sys_timeout(LOWPAN6_TMR_INTERVAL, zep_lowpan_timer, arg); 00103 } 00104 } 00105 00106 /* Pass received pbufs into 6LowPAN netif */ 00107 static void 00108 zepif_udp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, 00109 const ip_addr_t *addr, u16_t port) 00110 { 00111 err_t err; 00112 struct netif *netif_lowpan6 = (struct netif *)arg; 00113 struct zep_hdr *zep; 00114 00115 LWIP_ASSERT("arg != NULL", arg != NULL); 00116 LWIP_ASSERT("pcb != NULL", pcb != NULL); 00117 LWIP_UNUSED_ARG(pcb); /* for LWIP_NOASSERT */ 00118 LWIP_UNUSED_ARG(addr); 00119 LWIP_UNUSED_ARG(port); 00120 if (p == NULL) { 00121 return; 00122 } 00123 00124 /* Parse and hide the ZEP header */ 00125 if (p->len < sizeof(struct zep_hdr)) { 00126 /* need the zep_hdr in one piece */ 00127 goto err_return; 00128 } 00129 zep = (struct zep_hdr *)p->payload; 00130 if (zep->prot_id[0] != 'E') { 00131 goto err_return; 00132 } 00133 if (zep->prot_id[1] != 'X') { 00134 goto err_return; 00135 } 00136 if (zep->prot_version != 2) { 00137 /* we only support this version for now */ 00138 goto err_return; 00139 } 00140 if (zep->type != 1) { 00141 goto err_return; 00142 } 00143 if (zep->crc_mode != 1) { 00144 goto err_return; 00145 } 00146 if (zep->len != p->tot_len - sizeof(struct zep_hdr)) { 00147 goto err_return; 00148 } 00149 /* everything seems to be OK, hide the ZEP header */ 00150 if (pbuf_remove_header(p, sizeof(struct zep_hdr))) { 00151 goto err_return; 00152 } 00153 /* TODO Check CRC? */ 00154 /* remove CRC trailer */ 00155 pbuf_realloc(p, p->tot_len - 2); 00156 00157 /* Call into 6LoWPAN code. */ 00158 err = netif_lowpan6->input(p, netif_lowpan6); 00159 if (err == ERR_OK) { 00160 return; 00161 } 00162 err_return: 00163 pbuf_free(p); 00164 } 00165 00166 /* Send 6LoWPAN TX packets as UDP broadcast */ 00167 static err_t 00168 zepif_linkoutput(struct netif *netif, struct pbuf *p) 00169 { 00170 err_t err; 00171 struct pbuf *q; 00172 struct zep_hdr *zep; 00173 struct zepif_state *state; 00174 00175 LWIP_ASSERT("invalid netif", netif != NULL); 00176 LWIP_ASSERT("invalid pbuf", p != NULL); 00177 00178 if (p->tot_len > ZEP_MAX_DATA_LEN) { 00179 return ERR_VAL; 00180 } 00181 LWIP_ASSERT("TODO: support chained pbufs", p->next == NULL); 00182 00183 state = (struct zepif_state *)netif->state; 00184 LWIP_ASSERT("state->pcb != NULL", state->pcb != NULL); 00185 00186 q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct zep_hdr) + p->tot_len, PBUF_RAM); 00187 if (q == NULL) { 00188 return ERR_MEM; 00189 } 00190 zep = (struct zep_hdr *)q->payload; 00191 memset(zep, 0, sizeof(struct zep_hdr)); 00192 zep->prot_id[0] = 'E'; 00193 zep->prot_id[1] = 'X'; 00194 zep->prot_version = 2; 00195 zep->type = 1; /* Data */ 00196 zep->channel_id = 0; /* whatever */ 00197 zep->device_id = lwip_htons(1); /* whatever */ 00198 zep->crc_mode = 1; 00199 zep->unknown_1 = 0xff; 00200 zep->seq_num = lwip_htonl(state->seqno); 00201 state->seqno++; 00202 zep->len = (u8_t)p->tot_len; 00203 00204 err = pbuf_take_at(q, p->payload, p->tot_len, sizeof(struct zep_hdr)); 00205 if (err == ERR_OK) { 00206 #if ZEPIF_LOOPBACK 00207 zepif_udp_recv(netif, state->pcb, pbuf_clone(PBUF_RAW, PBUF_RAM, q), NULL, 0); 00208 #endif 00209 err = udp_sendto(state->pcb, q, state->init.zep_dst_ip_addr, state->init.zep_dst_udp_port); 00210 } 00211 pbuf_free(q); 00212 00213 return err; 00214 } 00215 00216 /** 00217 * @ingroup zepif 00218 * Set up a raw 6LowPAN netif and surround it with input- and output 00219 * functions for ZEP 00220 */ 00221 err_t 00222 zepif_init(struct netif *netif) 00223 { 00224 err_t err; 00225 struct zepif_init *init_state = (struct zepif_init *)netif->state; 00226 struct zepif_state *state = (struct zepif_state *)mem_malloc(sizeof(struct zepif_state)); 00227 00228 LWIP_ASSERT("zepif needs an input callback", netif->input != NULL); 00229 00230 if (state == NULL) { 00231 return ERR_MEM; 00232 } 00233 memset(state, 0, sizeof(struct zepif_state)); 00234 if (init_state != NULL) { 00235 memcpy(&state->init, init_state, sizeof(struct zepif_init)); 00236 } 00237 if (state->init.zep_src_udp_port == 0) { 00238 state->init.zep_src_udp_port = ZEPIF_DEFAULT_UDP_PORT; 00239 } 00240 if (state->init.zep_dst_udp_port == 0) { 00241 state->init.zep_dst_udp_port = ZEPIF_DEFAULT_UDP_PORT; 00242 } 00243 #if LWIP_IPV4 00244 if (state->init.zep_dst_ip_addr == NULL) { 00245 /* With IPv4 enabled, default to broadcasting packets if no address is set */ 00246 state->init.zep_dst_ip_addr = IP_ADDR_BROADCAST; 00247 } 00248 #endif /* LWIP_IPV4 */ 00249 00250 netif->state = NULL; 00251 00252 state->pcb = udp_new_ip_type(IPADDR_TYPE_ANY); 00253 if (state->pcb == NULL) { 00254 err = ERR_MEM; 00255 goto err_ret; 00256 } 00257 err = udp_bind(state->pcb, state->init.zep_src_ip_addr, state->init.zep_src_udp_port); 00258 if (err != ERR_OK) { 00259 goto err_ret; 00260 } 00261 if (state->init.zep_netif != NULL) { 00262 udp_bind_netif(state->pcb, state->init.zep_netif); 00263 } 00264 LWIP_ASSERT("udp_bind(lowpan6_broadcast_pcb) failed", err == ERR_OK); 00265 ip_set_option(state->pcb, SOF_BROADCAST); 00266 udp_recv(state->pcb, zepif_udp_recv, netif); 00267 00268 err = lowpan6_if_init(netif); 00269 LWIP_ASSERT("lowpan6_if_init set a state", netif->state == NULL); 00270 if (err == ERR_OK) { 00271 netif->state = state; 00272 netif->hwaddr_len = 6; 00273 if (init_state != NULL) { 00274 memcpy(netif->hwaddr, init_state->addr, 6); 00275 } else { 00276 u8_t i; 00277 for (i = 0; i < 6; i++) { 00278 netif->hwaddr[i] = i; 00279 } 00280 netif->hwaddr[0] &= 0xfc; 00281 } 00282 netif->linkoutput = zepif_linkoutput; 00283 00284 if (!zep_lowpan_timer_running) { 00285 sys_timeout(LOWPAN6_TMR_INTERVAL, zep_lowpan_timer, NULL); 00286 zep_lowpan_timer_running = 1; 00287 } 00288 00289 return ERR_OK; 00290 } 00291 00292 err_ret: 00293 if (state->pcb != NULL) { 00294 udp_remove(state->pcb); 00295 } 00296 mem_free(state); 00297 return err; 00298 } 00299 00300 #endif /* LWIP_IPV6 && LWIP_UDP */
Generated on Tue Jul 12 2022 13:54:30 by
