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 */ 60 static err_t 61 netifapi_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 67 if (!netif_add( msg->netif, 68 #if LWIP_IPV4 69 API_EXPR_REF(msg->msg.add.ipaddr), 70 API_EXPR_REF(msg->msg.add.netmask), 71 API_EXPR_REF(msg->msg.add.gw), 72 #endif /* LWIP_IPV4 */ 73 msg->msg.add.state, 74 msg->msg.add.init, 75 msg->msg.add.input)) { 76 return ERR_IF; 77 } else { 78 return ERR_OK; 79 } 80 } 81 82 #if LWIP_IPV4 83 /** 84 * Call netif_set_addr() inside the tcpip_thread context. 85 */ 86 static err_t 87 netifapi_do_netif_set_addr(struct tcpip_api_call_data *m) 88 { 89 /* cast through void* to silence alignment warnings. 90 * We know it works because the structs have been instantiated as struct netifapi_msg */ 91 struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m; 92 93 netif_set_addr( msg->netif, 94 API_EXPR_REF(msg->msg.add.ipaddr), 95 API_EXPR_REF(msg->msg.add.netmask), 96 API_EXPR_REF(msg->msg.add.gw)); 97 return ERR_OK; 98 } 99 #endif /* LWIP_IPV4 */ 100 101 /** 102 * Call netif_name_to_index() inside the tcpip_thread context. 103 */ 104 static err_t 105 netifapi_do_name_to_index(struct tcpip_api_call_data *m) 106 { 107 /* cast through void* to silence alignment warnings. 108 * We know it works because the structs have been instantiated as struct netifapi_msg */ 109 struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m; 110 111 msg->msg.ifs.index = netif_name_to_index(msg->msg.ifs.name); 112 return ERR_OK; 113 } 114 115 /** 116 * Call netif_index_to_name() inside the tcpip_thread context. 117 */ 118 static err_t 119 netifapi_do_index_to_name(struct tcpip_api_call_data *m) 120 { 121 /* cast through void* to silence alignment warnings. 122 * We know it works because the structs have been instantiated as struct netifapi_msg */ 123 struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m; 124 125 if (!netif_index_to_name(msg->msg.ifs.index, msg->msg.ifs.name)) { 126 /* return failure via empty name */ 127 msg->msg.ifs.name[0] = '\0'; 128 } 129 return ERR_OK; 130 } 131 132 /** 133 * Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the 134 * tcpip_thread context. 135 */ 136 static err_t 137 netifapi_do_netif_common(struct tcpip_api_call_data *m) 138 { 139 /* cast through void* to silence alignment warnings. 140 * We know it works because the structs have been instantiated as struct netifapi_msg */ 141 struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m; 142 143 if (msg->msg.common.errtfunc != NULL) { 144 return msg->msg.common.errtfunc(msg->netif); 145 } else { 146 msg->msg.common.voidfunc(msg->netif); 147 return ERR_OK; 148 } 149 } 150 151 #if LWIP_ARP && LWIP_IPV4 152 /** 153 * @ingroup netifapi_arp 154 * Add or update an entry in the ARP cache. 155 * For an update, ipaddr is used to find the cache entry. 156 * 157 * @param ipaddr IPv4 address of cache entry 158 * @param ethaddr hardware address mapped to ipaddr 159 * @param type type of ARP cache entry 160 * @return ERR_OK: entry added/updated, else error from err_t 161 */ 162 err_t 163 netifapi_arp_add(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, enum netifapi_arp_entry type) 164 { 165 err_t err; 166 167 /* We only support permanent entries currently */ 168 LWIP_UNUSED_ARG(type); 169 170 #if ETHARP_SUPPORT_STATIC_ENTRIES && LWIP_TCPIP_CORE_LOCKING 171 LOCK_TCPIP_CORE(); 172 err = etharp_add_static_entry(ipaddr, ethaddr); 173 UNLOCK_TCPIP_CORE(); 174 #else 175 /* @todo add new vars to struct netifapi_msg and create a 'do' func */ 176 LWIP_UNUSED_ARG(ipaddr); 177 LWIP_UNUSED_ARG(ethaddr); 178 err = ERR_VAL; 179 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES && LWIP_TCPIP_CORE_LOCKING */ 180 181 return err; 182 } 183 184 /** 185 * @ingroup netifapi_arp 186 * Remove an entry in the ARP cache identified by ipaddr 187 * 188 * @param ipaddr IPv4 address of cache entry 189 * @param type type of ARP cache entry 190 * @return ERR_OK: entry removed, else error from err_t 191 */ 192 err_t 193 netifapi_arp_remove(const ip4_addr_t *ipaddr, enum netifapi_arp_entry type) 194 { 195 err_t err; 196 197 /* We only support permanent entries currently */ 198 LWIP_UNUSED_ARG(type); 199 200 #if ETHARP_SUPPORT_STATIC_ENTRIES && LWIP_TCPIP_CORE_LOCKING 201 LOCK_TCPIP_CORE(); 202 err = etharp_remove_static_entry(ipaddr); 203 UNLOCK_TCPIP_CORE(); 204 #else 205 /* @todo add new vars to struct netifapi_msg and create a 'do' func */ 206 LWIP_UNUSED_ARG(ipaddr); 207 err = ERR_VAL; 208 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES && LWIP_TCPIP_CORE_LOCKING */ 209 210 return err; 211 } 212 #endif /* LWIP_ARP && LWIP_IPV4 */ 213 214 /** 215 * @ingroup netifapi_netif 216 * Call netif_add() in a thread-safe way by running that function inside the 217 * tcpip_thread context. 218 * 219 * @note for params @see netif_add() 220 */ 221 err_t 222 netifapi_netif_add(struct netif *netif, 223 #if LWIP_IPV4 224 const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, 225 #endif /* LWIP_IPV4 */ 226 void *state, netif_init_fn init, netif_input_fn input) 227 { 228 err_t err; 229 NETIFAPI_VAR_DECLARE(msg); 230 NETIFAPI_VAR_ALLOC(msg); 231 232 #if LWIP_IPV4 233 if (ipaddr == NULL) { 234 ipaddr = IP4_ADDR_ANY4; 235 } 236 if (netmask == NULL) { 237 netmask = IP4_ADDR_ANY4; 238 } 239 if (gw == NULL) { 240 gw = IP4_ADDR_ANY4; 241 } 242 #endif /* LWIP_IPV4 */ 243 244 NETIFAPI_VAR_REF(msg).netif = netif; 245 #if LWIP_IPV4 246 NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); 247 NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask); 248 NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw); 249 #endif /* LWIP_IPV4 */ 250 NETIFAPI_VAR_REF(msg).msg.add.state = state; 251 NETIFAPI_VAR_REF(msg).msg.add.init = init; 252 NETIFAPI_VAR_REF(msg).msg.add.input = input; 253 err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call); 254 NETIFAPI_VAR_FREE(msg); 255 return err; 256 } 257 258 #if LWIP_IPV4 259 /** 260 * @ingroup netifapi_netif 261 * Call netif_set_addr() in a thread-safe way by running that function inside the 262 * tcpip_thread context. 263 * 264 * @note for params @see netif_set_addr() 265 */ 266 err_t 267 netifapi_netif_set_addr(struct netif *netif, 268 const ip4_addr_t *ipaddr, 269 const ip4_addr_t *netmask, 270 const ip4_addr_t *gw) 271 { 272 err_t err; 273 NETIFAPI_VAR_DECLARE(msg); 274 NETIFAPI_VAR_ALLOC(msg); 275 276 if (ipaddr == NULL) { 277 ipaddr = IP4_ADDR_ANY4; 278 } 279 if (netmask == NULL) { 280 netmask = IP4_ADDR_ANY4; 281 } 282 if (gw == NULL) { 283 gw = IP4_ADDR_ANY4; 284 } 285 286 NETIFAPI_VAR_REF(msg).netif = netif; 287 NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); 288 NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask); 289 NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw); 290 err = tcpip_api_call(netifapi_do_netif_set_addr, &API_VAR_REF(msg).call); 291 NETIFAPI_VAR_FREE(msg); 292 return err; 293 } 294 #endif /* LWIP_IPV4 */ 295 296 /** 297 * call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe 298 * way by running that function inside the tcpip_thread context. 299 * 300 * @note use only for functions where there is only "netif" parameter. 301 */ 302 err_t 303 netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, 304 netifapi_errt_fn errtfunc) 305 { 306 err_t err; 307 NETIFAPI_VAR_DECLARE(msg); 308 NETIFAPI_VAR_ALLOC(msg); 309 310 NETIFAPI_VAR_REF(msg).netif = netif; 311 NETIFAPI_VAR_REF(msg).msg.common.voidfunc = voidfunc; 312 NETIFAPI_VAR_REF(msg).msg.common.errtfunc = errtfunc; 313 err = tcpip_api_call(netifapi_do_netif_common, &API_VAR_REF(msg).call); 314 NETIFAPI_VAR_FREE(msg); 315 return err; 316 } 317 318 /** 319 * @ingroup netifapi_netif 320 * Call netif_name_to_index() in a thread-safe way by running that function inside the 321 * tcpip_thread context. 322 * 323 * @param name the interface name of the netif 324 * @param idx output index of the found netif 325 */ 326 err_t 327 netifapi_netif_name_to_index(const char *name, u8_t *idx) 328 { 329 err_t err; 330 NETIFAPI_VAR_DECLARE(msg); 331 NETIFAPI_VAR_ALLOC(msg); 332 333 *idx = 0; 334 335 #if LWIP_MPU_COMPATIBLE 336 strncpy(NETIFAPI_VAR_REF(msg).msg.ifs.name, name, NETIF_NAMESIZE - 1); 337 NETIFAPI_VAR_REF(msg).msg.ifs.name[NETIF_NAMESIZE - 1] = '\0'; 338 #else 339 NETIFAPI_VAR_REF(msg).msg.ifs.name = LWIP_CONST_CAST(char *, name); 340 #endif /* LWIP_MPU_COMPATIBLE */ 341 err = tcpip_api_call(netifapi_do_name_to_index, &API_VAR_REF(msg).call); 342 if (!err) { 343 *idx = NETIFAPI_VAR_REF(msg).msg.ifs.index; 344 } 345 NETIFAPI_VAR_FREE(msg); 346 return err; 347 } 348 349 /** 350 * @ingroup netifapi_netif 351 * Call netif_index_to_name() in a thread-safe way by running that function inside the 352 * tcpip_thread context. 353 * 354 * @param idx the interface index of the netif 355 * @param name output name of the found netif, empty '\0' string if netif not found. 356 * name should be of at least NETIF_NAMESIZE bytes 357 */ 358 err_t 359 netifapi_netif_index_to_name(u8_t idx, char *name) 360 { 361 err_t err; 362 NETIFAPI_VAR_DECLARE(msg); 363 NETIFAPI_VAR_ALLOC(msg); 364 365 NETIFAPI_VAR_REF(msg).msg.ifs.index = idx; 366 #if !LWIP_MPU_COMPATIBLE 367 NETIFAPI_VAR_REF(msg).msg.ifs.name = name; 368 #endif /* LWIP_MPU_COMPATIBLE */ 369 err = tcpip_api_call(netifapi_do_index_to_name, &API_VAR_REF(msg).call); 370 #if LWIP_MPU_COMPATIBLE 371 if (!err) { 372 strncpy(name, NETIFAPI_VAR_REF(msg).msg.ifs.name, NETIF_NAMESIZE - 1); 373 name[NETIF_NAMESIZE - 1] = '\0'; 374 } 375 #endif /* LWIP_MPU_COMPATIBLE */ 376 NETIFAPI_VAR_FREE(msg); 377 return err; 378 } 379 380 #endif /* LWIP_NETIF_API */ 381