1/** 2 * @file 3 * Network Interface Sequential API module 4 * 5 * @defgroup netifapi NETIF API 6 * @ingroup sequential_api 7 * Thread-safe functions to be called from non-TCPIP threads 8 * 9 * @defgroup netifapi_netif NETIF related 10 * @ingroup netifapi 11 * To be called from non-TCPIP threads 12 */ 13 14/* 15 * Redistribution and use in source and binary forms, with or without modification, 16 * are permitted provided that the following conditions are met: 17 * 18 * 1. Redistributions of source code must retain the above copyright notice, 19 * this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above copyright notice, 21 * this list of conditions and the following disclaimer in the documentation 22 * and/or other materials provided with the distribution. 23 * 3. The name of the author may not be used to endorse or promote products 24 * derived from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 28 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 29 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 30 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 31 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 34 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 35 * OF SUCH DAMAGE. 36 * 37 * This file is part of the lwIP TCP/IP stack. 38 * 39 */ 40 41#include "lwip/opt.h" 42 43#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ 44 45#include "lwip/etharp.h" 46#include "lwip/netifapi.h" 47#include "lwip/memp.h" 48#include "lwip/priv/tcpip_priv.h" 49 50#include <string.h> /* strncpy */ 51 52#define NETIFAPI_VAR_REF(name) API_VAR_REF(name) 53#define NETIFAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct netifapi_msg, name) 54#define NETIFAPI_VAR_ALLOC(name) API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name, ERR_MEM) 55#define NETIFAPI_VAR_FREE(name) API_VAR_FREE(MEMP_NETIFAPI_MSG, name) 56 57/** 58 * Call netif_add() inside the tcpip_thread context. 59 */ 60static err_t 61netifapi_do_netif_add(struct tcpip_api_call_data *m) 62{ 63 /* cast through void* to silence alignment warnings. 64 * We know it works because the structs have been instantiated as struct netifapi_msg */ 65 struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m; 66#ifdef LOSCFG_NET_CONTAINER 67 if (!netif_add( msg->netif, get_curr_process_net_group(), 68#else 69 if (!netif_add( msg->netif, 70#endif 71#if LWIP_IPV4 72 API_EXPR_REF(msg->msg.add.ipaddr), 73 API_EXPR_REF(msg->msg.add.netmask), 74 API_EXPR_REF(msg->msg.add.gw), 75#endif /* LWIP_IPV4 */ 76 msg->msg.add.state, 77 msg->msg.add.init, 78 msg->msg.add.input)) { 79 return ERR_IF; 80 } else { 81 return ERR_OK; 82 } 83} 84 85#if LWIP_IPV4 86/** 87 * Call netif_set_addr() inside the tcpip_thread context. 88 */ 89static err_t 90netifapi_do_netif_set_addr(struct tcpip_api_call_data *m) 91{ 92 /* cast through void* to silence alignment warnings. 93 * We know it works because the structs have been instantiated as struct netifapi_msg */ 94 struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m; 95 96 netif_set_addr( msg->netif, 97 API_EXPR_REF(msg->msg.add.ipaddr), 98 API_EXPR_REF(msg->msg.add.netmask), 99 API_EXPR_REF(msg->msg.add.gw)); 100 return ERR_OK; 101} 102#endif /* LWIP_IPV4 */ 103 104/** 105* Call netif_name_to_index() inside the tcpip_thread context. 106*/ 107static err_t 108netifapi_do_name_to_index(struct tcpip_api_call_data *m) 109{ 110 /* cast through void* to silence alignment warnings. 111 * We know it works because the structs have been instantiated as struct netifapi_msg */ 112 struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m; 113 114 msg->msg.ifs.index = netif_name_to_index(msg->msg.ifs.name); 115 return ERR_OK; 116} 117 118/** 119* Call netif_index_to_name() inside the tcpip_thread context. 120*/ 121static err_t 122netifapi_do_index_to_name(struct tcpip_api_call_data *m) 123{ 124 /* cast through void* to silence alignment warnings. 125 * We know it works because the structs have been instantiated as struct netifapi_msg */ 126 struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m; 127 128#ifdef LOSCFG_NET_CONTAINER 129 if (!netif_index_to_name(msg->msg.ifs.index, msg->msg.ifs.name, get_curr_process_net_group())) { 130#else 131 if (!netif_index_to_name(msg->msg.ifs.index, msg->msg.ifs.name)) { 132#endif 133 /* return failure via empty name */ 134 msg->msg.ifs.name[0] = '\0'; 135 } 136 return ERR_OK; 137} 138 139/** 140 * Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the 141 * tcpip_thread context. 142 */ 143static err_t 144netifapi_do_netif_common(struct tcpip_api_call_data *m) 145{ 146 /* cast through void* to silence alignment warnings. 147 * We know it works because the structs have been instantiated as struct netifapi_msg */ 148 struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m; 149 150 if (msg->msg.common.errtfunc != NULL) { 151 return msg->msg.common.errtfunc(msg->netif); 152 } else { 153 msg->msg.common.voidfunc(msg->netif); 154 return ERR_OK; 155 } 156} 157 158#if LWIP_ARP && LWIP_IPV4 159/** 160 * @ingroup netifapi_arp 161 * Add or update an entry in the ARP cache. 162 * For an update, ipaddr is used to find the cache entry. 163 * 164 * @param ipaddr IPv4 address of cache entry 165 * @param ethaddr hardware address mapped to ipaddr 166 * @param type type of ARP cache entry 167 * @return ERR_OK: entry added/updated, else error from err_t 168 */ 169err_t 170netifapi_arp_add(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, enum netifapi_arp_entry type) 171{ 172 err_t err; 173 174 /* We only support permanent entries currently */ 175 LWIP_UNUSED_ARG(type); 176 177#if ETHARP_SUPPORT_STATIC_ENTRIES && LWIP_TCPIP_CORE_LOCKING 178 LOCK_TCPIP_CORE(); 179 err = etharp_add_static_entry(ipaddr, ethaddr); 180 UNLOCK_TCPIP_CORE(); 181#else 182 /* @todo add new vars to struct netifapi_msg and create a 'do' func */ 183 LWIP_UNUSED_ARG(ipaddr); 184 LWIP_UNUSED_ARG(ethaddr); 185 err = ERR_VAL; 186#endif /* ETHARP_SUPPORT_STATIC_ENTRIES && LWIP_TCPIP_CORE_LOCKING */ 187 188 return err; 189} 190 191/** 192 * @ingroup netifapi_arp 193 * Remove an entry in the ARP cache identified by ipaddr 194 * 195 * @param ipaddr IPv4 address of cache entry 196 * @param type type of ARP cache entry 197 * @return ERR_OK: entry removed, else error from err_t 198 */ 199err_t 200netifapi_arp_remove(const ip4_addr_t *ipaddr, enum netifapi_arp_entry type) 201{ 202 err_t err; 203 204 /* We only support permanent entries currently */ 205 LWIP_UNUSED_ARG(type); 206 207#if ETHARP_SUPPORT_STATIC_ENTRIES && LWIP_TCPIP_CORE_LOCKING 208 LOCK_TCPIP_CORE(); 209 err = etharp_remove_static_entry(ipaddr); 210 UNLOCK_TCPIP_CORE(); 211#else 212 /* @todo add new vars to struct netifapi_msg and create a 'do' func */ 213 LWIP_UNUSED_ARG(ipaddr); 214 err = ERR_VAL; 215#endif /* ETHARP_SUPPORT_STATIC_ENTRIES && LWIP_TCPIP_CORE_LOCKING */ 216 217 return err; 218} 219#endif /* LWIP_ARP && LWIP_IPV4 */ 220 221/** 222 * @ingroup netifapi_netif 223 * Call netif_add() in a thread-safe way by running that function inside the 224 * tcpip_thread context. 225 * 226 * @note for params @see netif_add() 227 */ 228err_t 229netifapi_netif_add(struct netif *netif, 230#if LWIP_IPV4 231 const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, 232#endif /* LWIP_IPV4 */ 233 void *state, netif_init_fn init, netif_input_fn input) 234{ 235 err_t err; 236 NETIFAPI_VAR_DECLARE(msg); 237 NETIFAPI_VAR_ALLOC(msg); 238 239#if LWIP_IPV4 240 if (ipaddr == NULL) { 241 ipaddr = IP4_ADDR_ANY4; 242 } 243 if (netmask == NULL) { 244 netmask = IP4_ADDR_ANY4; 245 } 246 if (gw == NULL) { 247 gw = IP4_ADDR_ANY4; 248 } 249#endif /* LWIP_IPV4 */ 250 251 NETIFAPI_VAR_REF(msg).netif = netif; 252#if LWIP_IPV4 253 NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); 254 NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask); 255 NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw); 256#endif /* LWIP_IPV4 */ 257 NETIFAPI_VAR_REF(msg).msg.add.state = state; 258 NETIFAPI_VAR_REF(msg).msg.add.init = init; 259 NETIFAPI_VAR_REF(msg).msg.add.input = input; 260 err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call); 261 NETIFAPI_VAR_FREE(msg); 262 return err; 263} 264 265#if LWIP_IPV4 266/** 267 * @ingroup netifapi_netif 268 * Call netif_set_addr() in a thread-safe way by running that function inside the 269 * tcpip_thread context. 270 * 271 * @note for params @see netif_set_addr() 272 */ 273err_t 274netifapi_netif_set_addr(struct netif *netif, 275 const ip4_addr_t *ipaddr, 276 const ip4_addr_t *netmask, 277 const ip4_addr_t *gw) 278{ 279 err_t err; 280 NETIFAPI_VAR_DECLARE(msg); 281 NETIFAPI_VAR_ALLOC(msg); 282 283 if (ipaddr == NULL) { 284 ipaddr = IP4_ADDR_ANY4; 285 } 286 if (netmask == NULL) { 287 netmask = IP4_ADDR_ANY4; 288 } 289 if (gw == NULL) { 290 gw = IP4_ADDR_ANY4; 291 } 292 293 NETIFAPI_VAR_REF(msg).netif = netif; 294 NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); 295 NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask); 296 NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw); 297 err = tcpip_api_call(netifapi_do_netif_set_addr, &API_VAR_REF(msg).call); 298 NETIFAPI_VAR_FREE(msg); 299 return err; 300} 301#endif /* LWIP_IPV4 */ 302 303/** 304 * call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe 305 * way by running that function inside the tcpip_thread context. 306 * 307 * @note use only for functions where there is only "netif" parameter. 308 */ 309err_t 310netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, 311 netifapi_errt_fn errtfunc) 312{ 313 err_t err; 314 NETIFAPI_VAR_DECLARE(msg); 315 NETIFAPI_VAR_ALLOC(msg); 316 317 NETIFAPI_VAR_REF(msg).netif = netif; 318 NETIFAPI_VAR_REF(msg).msg.common.voidfunc = voidfunc; 319 NETIFAPI_VAR_REF(msg).msg.common.errtfunc = errtfunc; 320 err = tcpip_api_call(netifapi_do_netif_common, &API_VAR_REF(msg).call); 321 NETIFAPI_VAR_FREE(msg); 322 return err; 323} 324 325/** 326* @ingroup netifapi_netif 327* Call netif_name_to_index() in a thread-safe way by running that function inside the 328* tcpip_thread context. 329* 330* @param name the interface name of the netif 331* @param idx output index of the found netif 332*/ 333err_t 334netifapi_netif_name_to_index(const char *name, u8_t *idx) 335{ 336 err_t err; 337 NETIFAPI_VAR_DECLARE(msg); 338 NETIFAPI_VAR_ALLOC(msg); 339 340 *idx = 0; 341 342#if LWIP_MPU_COMPATIBLE 343 strncpy(NETIFAPI_VAR_REF(msg).msg.ifs.name, name, NETIF_NAMESIZE - 1); 344 NETIFAPI_VAR_REF(msg).msg.ifs.name[NETIF_NAMESIZE - 1] = '\0'; 345#else 346 NETIFAPI_VAR_REF(msg).msg.ifs.name = LWIP_CONST_CAST(char *, name); 347#endif /* LWIP_MPU_COMPATIBLE */ 348 err = tcpip_api_call(netifapi_do_name_to_index, &API_VAR_REF(msg).call); 349 if (!err) { 350 *idx = NETIFAPI_VAR_REF(msg).msg.ifs.index; 351 } 352 NETIFAPI_VAR_FREE(msg); 353 return err; 354} 355 356/** 357* @ingroup netifapi_netif 358* Call netif_index_to_name() in a thread-safe way by running that function inside the 359* tcpip_thread context. 360* 361* @param idx the interface index of the netif 362* @param name output name of the found netif, empty '\0' string if netif not found. 363* name should be of at least NETIF_NAMESIZE bytes 364*/ 365err_t 366netifapi_netif_index_to_name(u8_t idx, char *name) 367{ 368 err_t err; 369 NETIFAPI_VAR_DECLARE(msg); 370 NETIFAPI_VAR_ALLOC(msg); 371 372 NETIFAPI_VAR_REF(msg).msg.ifs.index = idx; 373#if !LWIP_MPU_COMPATIBLE 374 NETIFAPI_VAR_REF(msg).msg.ifs.name = name; 375#endif /* LWIP_MPU_COMPATIBLE */ 376 err = tcpip_api_call(netifapi_do_index_to_name, &API_VAR_REF(msg).call); 377#if LWIP_MPU_COMPATIBLE 378 if (!err) { 379 strncpy(name, NETIFAPI_VAR_REF(msg).msg.ifs.name, NETIF_NAMESIZE - 1); 380 name[NETIF_NAMESIZE - 1] = '\0'; 381 } 382#endif /* LWIP_MPU_COMPATIBLE */ 383 NETIFAPI_VAR_FREE(msg); 384 return err; 385} 386 387#if LWIP_LOWPOWER 388static err_t 389netifapi_do_set_lowpower_mod(struct tcpip_api_call_data *m) 390{ 391 struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m; 392 enum lowpower_mod mod = msg->msg.lp.mod; 393 set_lowpower_mod(mod); 394 return ERR_OK; 395} 396 397err_t 398netifapi_enable_lowpower(void) 399{ 400 err_t err; 401 NETIFAPI_VAR_DECLARE(msg); 402 403 NETIFAPI_VAR_ALLOC(msg); 404 405 NETIFAPI_VAR_REF(msg).msg.lp.mod = LOW_TMR_LOWPOWER_MOD; 406 407 err = tcpip_api_call(netifapi_do_set_lowpower_mod, &API_VAR_REF(msg).call); 408 NETIFAPI_VAR_FREE(msg); 409 return err; 410} 411 412err_t 413netifapi_disable_lowpower(void) 414{ 415 err_t err; 416 NETIFAPI_VAR_DECLARE(msg); 417 418 NETIFAPI_VAR_ALLOC(msg); 419 420 NETIFAPI_VAR_REF(msg).msg.lp.mod = LOW_TMR_NORMAL_MOD; 421 422 err = tcpip_api_call(netifapi_do_set_lowpower_mod, &API_VAR_REF(msg).call); 423 NETIFAPI_VAR_FREE(msg); 424 return err; 425} 426#endif /* LWIP_LOWPOWER */ 427 428#endif /* LWIP_NETIF_API */ 429