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/netifapi.h" 46 #include "lwip/memp.h" 47 #include "lwip/priv/tcpip_priv.h" 48 49 #include <string.h> /* strncpy */ 50 51 #define NETIFAPI_VAR_REF(name) API_VAR_REF(name) 52 #define NETIFAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct netifapi_msg, name) 53 #define NETIFAPI_VAR_ALLOC(name) API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name, ERR_MEM) 54 #define NETIFAPI_VAR_FREE(name) API_VAR_FREE(MEMP_NETIFAPI_MSG, name) 55 56 /** 57 * Call netif_add() inside the tcpip_thread context. 58 */ 59 static err_t 60 netifapi_do_netif_add(struct tcpip_api_call_data *m) 61 { 62 /* cast through void* to silence alignment warnings. 63 * We know it works because the structs have been instantiated as struct netifapi_msg */ 64 struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; 65 66 if (!netif_add( msg->netif, 67 #if LWIP_IPV4 68 API_EXPR_REF(msg->msg.add.ipaddr), 69 API_EXPR_REF(msg->msg.add.netmask), 70 API_EXPR_REF(msg->msg.add.gw), 71 #endif /* LWIP_IPV4 */ 72 msg->msg.add.state, 73 msg->msg.add.init, 74 msg->msg.add.input)) { 75 return ERR_IF; 76 } else { 77 return ERR_OK; 78 } 79 } 80 81 #if LWIP_IPV4 82 /** 83 * Call netif_set_addr() inside the tcpip_thread context. 84 */ 85 static err_t 86 netifapi_do_netif_set_addr(struct tcpip_api_call_data *m) 87 { 88 /* cast through void* to silence alignment warnings. 89 * We know it works because the structs have been instantiated as struct netifapi_msg */ 90 struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; 91 92 netif_set_addr( msg->netif, 93 API_EXPR_REF(msg->msg.add.ipaddr), 94 API_EXPR_REF(msg->msg.add.netmask), 95 API_EXPR_REF(msg->msg.add.gw)); 96 return ERR_OK; 97 } 98 #endif /* LWIP_IPV4 */ 99 100 /** 101 * Call netif_name_to_index() inside the tcpip_thread context. 102 */ 103 static err_t 104 netifapi_do_name_to_index(struct tcpip_api_call_data *m) 105 { 106 /* cast through void* to silence alignment warnings. 107 * We know it works because the structs have been instantiated as struct netifapi_msg */ 108 struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; 109 110 msg->msg.ifs.index = netif_name_to_index(msg->msg.ifs.name); 111 return ERR_OK; 112 } 113 114 /** 115 * Call netif_index_to_name() inside the tcpip_thread context. 116 */ 117 static err_t 118 netifapi_do_index_to_name(struct tcpip_api_call_data *m) 119 { 120 /* cast through void* to silence alignment warnings. 121 * We know it works because the structs have been instantiated as struct netifapi_msg */ 122 struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; 123 124 if (!netif_index_to_name(msg->msg.ifs.index, msg->msg.ifs.name)) { 125 /* return failure via empty name */ 126 msg->msg.ifs.name[0] = '\0'; 127 } 128 return ERR_OK; 129 } 130 131 /** 132 * Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the 133 * tcpip_thread context. 134 */ 135 static err_t 136 netifapi_do_netif_common(struct tcpip_api_call_data *m) 137 { 138 /* cast through void* to silence alignment warnings. 139 * We know it works because the structs have been instantiated as struct netifapi_msg */ 140 struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; 141 142 if (msg->msg.common.errtfunc != NULL) { 143 return msg->msg.common.errtfunc(msg->netif); 144 } else { 145 msg->msg.common.voidfunc(msg->netif); 146 return ERR_OK; 147 } 148 } 149 150 /** 151 * @ingroup netifapi_netif 152 * Call netif_add() in a thread-safe way by running that function inside the 153 * tcpip_thread context. 154 * 155 * @note for params @see netif_add() 156 */ 157 err_t 158 netifapi_netif_add(struct netif *netif, 159 #if LWIP_IPV4 160 const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, 161 #endif /* LWIP_IPV4 */ 162 void *state, netif_init_fn init, netif_input_fn input) 163 { 164 err_t err; 165 NETIFAPI_VAR_DECLARE(msg); 166 NETIFAPI_VAR_ALLOC(msg); 167 168 #if LWIP_IPV4 169 if (ipaddr == NULL) { 170 ipaddr = IP4_ADDR_ANY4; 171 } 172 if (netmask == NULL) { 173 netmask = IP4_ADDR_ANY4; 174 } 175 if (gw == NULL) { 176 gw = IP4_ADDR_ANY4; 177 } 178 #endif /* LWIP_IPV4 */ 179 180 NETIFAPI_VAR_REF(msg).netif = netif; 181 #if LWIP_IPV4 182 NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); 183 NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask); 184 NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw); 185 #endif /* LWIP_IPV4 */ 186 NETIFAPI_VAR_REF(msg).msg.add.state = state; 187 NETIFAPI_VAR_REF(msg).msg.add.init = init; 188 NETIFAPI_VAR_REF(msg).msg.add.input = input; 189 err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call); 190 NETIFAPI_VAR_FREE(msg); 191 return err; 192 } 193 194 #if LWIP_IPV4 195 /** 196 * @ingroup netifapi_netif 197 * Call netif_set_addr() in a thread-safe way by running that function inside the 198 * tcpip_thread context. 199 * 200 * @note for params @see netif_set_addr() 201 */ 202 err_t 203 netifapi_netif_set_addr(struct netif *netif, 204 const ip4_addr_t *ipaddr, 205 const ip4_addr_t *netmask, 206 const ip4_addr_t *gw) 207 { 208 err_t err; 209 NETIFAPI_VAR_DECLARE(msg); 210 NETIFAPI_VAR_ALLOC(msg); 211 212 if (ipaddr == NULL) { 213 ipaddr = IP4_ADDR_ANY4; 214 } 215 if (netmask == NULL) { 216 netmask = IP4_ADDR_ANY4; 217 } 218 if (gw == NULL) { 219 gw = IP4_ADDR_ANY4; 220 } 221 222 NETIFAPI_VAR_REF(msg).netif = netif; 223 NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); 224 NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask); 225 NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw); 226 err = tcpip_api_call(netifapi_do_netif_set_addr, &API_VAR_REF(msg).call); 227 NETIFAPI_VAR_FREE(msg); 228 return err; 229 } 230 #endif /* LWIP_IPV4 */ 231 232 /** 233 * call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe 234 * way by running that function inside the tcpip_thread context. 235 * 236 * @note use only for functions where there is only "netif" parameter. 237 */ 238 err_t 239 netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, 240 netifapi_errt_fn errtfunc) 241 { 242 err_t err; 243 NETIFAPI_VAR_DECLARE(msg); 244 NETIFAPI_VAR_ALLOC(msg); 245 246 NETIFAPI_VAR_REF(msg).netif = netif; 247 NETIFAPI_VAR_REF(msg).msg.common.voidfunc = voidfunc; 248 NETIFAPI_VAR_REF(msg).msg.common.errtfunc = errtfunc; 249 err = tcpip_api_call(netifapi_do_netif_common, &API_VAR_REF(msg).call); 250 NETIFAPI_VAR_FREE(msg); 251 return err; 252 } 253 254 /** 255 * @ingroup netifapi_netif 256 * Call netif_name_to_index() in a thread-safe way by running that function inside the 257 * tcpip_thread context. 258 * 259 * @param name the interface name of the netif 260 * @param idx output index of the found netif 261 */ 262 err_t 263 netifapi_netif_name_to_index(const char *name, u8_t *idx) 264 { 265 err_t err; 266 NETIFAPI_VAR_DECLARE(msg); 267 NETIFAPI_VAR_ALLOC(msg); 268 269 *idx = 0; 270 271 #if LWIP_MPU_COMPATIBLE 272 strncpy(NETIFAPI_VAR_REF(msg).msg.ifs.name, name, NETIF_NAMESIZE - 1); 273 NETIFAPI_VAR_REF(msg).msg.ifs.name[NETIF_NAMESIZE - 1] = '\0'; 274 #else 275 NETIFAPI_VAR_REF(msg).msg.ifs.name = LWIP_CONST_CAST(char*, name); 276 #endif /* LWIP_MPU_COMPATIBLE */ 277 err = tcpip_api_call(netifapi_do_name_to_index, &API_VAR_REF(msg).call); 278 if (!err) { 279 *idx = NETIFAPI_VAR_REF(msg).msg.ifs.index; 280 } 281 NETIFAPI_VAR_FREE(msg); 282 return err; 283 } 284 285 /** 286 * @ingroup netifapi_netif 287 * Call netif_index_to_name() in a thread-safe way by running that function inside the 288 * tcpip_thread context. 289 * 290 * @param idx the interface index of the netif 291 * @param name output name of the found netif, empty '\0' string if netif not found. 292 * name should be of at least NETIF_NAMESIZE bytes 293 */ 294 err_t 295 netifapi_netif_index_to_name(u8_t idx, char *name) 296 { 297 err_t err; 298 NETIFAPI_VAR_DECLARE(msg); 299 NETIFAPI_VAR_ALLOC(msg); 300 301 NETIFAPI_VAR_REF(msg).msg.ifs.index = idx; 302 #if !LWIP_MPU_COMPATIBLE 303 NETIFAPI_VAR_REF(msg).msg.ifs.name = name; 304 #endif /* LWIP_MPU_COMPATIBLE */ 305 err = tcpip_api_call(netifapi_do_index_to_name, &API_VAR_REF(msg).call); 306 #if LWIP_MPU_COMPATIBLE 307 if (!err) { 308 strncpy(name, NETIFAPI_VAR_REF(msg).msg.ifs.name, NETIF_NAMESIZE - 1); 309 name[NETIF_NAMESIZE - 1] = '\0'; 310 } 311 #endif /* LWIP_MPU_COMPATIBLE */ 312 NETIFAPI_VAR_FREE(msg); 313 return err; 314 } 315 316 #endif /* LWIP_NETIF_API */ 317