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 #define NETIFAPI_VAR_REF(name) API_VAR_REF(name) 50 #define NETIFAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct netifapi_msg, name) 51 #define NETIFAPI_VAR_ALLOC(name) API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name, ERR_MEM) 52 #define NETIFAPI_VAR_FREE(name) API_VAR_FREE(MEMP_NETIFAPI_MSG, name) 53 54 /** 55 * Call netif_add() inside the tcpip_thread context. 56 */ 57 static err_t 58 netifapi_do_netif_add(struct tcpip_api_call_data *m) 59 { 60 /* cast through void* to silence alignment warnings. 61 * We know it works because the structs have been instantiated as struct netifapi_msg */ 62 struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; 63 64 if (!netif_add( msg->netif, 65 #if LWIP_IPV4 66 API_EXPR_REF(msg->msg.add.ipaddr), 67 API_EXPR_REF(msg->msg.add.netmask), 68 API_EXPR_REF(msg->msg.add.gw), 69 #endif /* LWIP_IPV4 */ 70 msg->msg.add.state, 71 msg->msg.add.init, 72 msg->msg.add.input)) { 73 return ERR_IF; 74 } else { 75 return ERR_OK; 76 } 77 } 78 79 #if LWIP_IPV4 80 /** 81 * Call netif_set_addr() inside the tcpip_thread context. 82 */ 83 static err_t 84 netifapi_do_netif_set_addr(struct tcpip_api_call_data *m) 85 { 86 /* cast through void* to silence alignment warnings. 87 * We know it works because the structs have been instantiated as struct netifapi_msg */ 88 struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; 89 90 netif_set_addr( msg->netif, 91 API_EXPR_REF(msg->msg.add.ipaddr), 92 API_EXPR_REF(msg->msg.add.netmask), 93 API_EXPR_REF(msg->msg.add.gw)); 94 return ERR_OK; 95 } 96 #endif /* LWIP_IPV4 */ 97 98 /** 99 * Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the 100 * tcpip_thread context. 101 */ 102 static err_t 103 netifapi_do_netif_common(struct tcpip_api_call_data *m) 104 { 105 /* cast through void* to silence alignment warnings. 106 * We know it works because the structs have been instantiated as struct netifapi_msg */ 107 struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; 108 109 if (msg->msg.common.errtfunc != NULL) { 110 return msg->msg.common.errtfunc(msg->netif); 111 } else { 112 msg->msg.common.voidfunc(msg->netif); 113 return ERR_OK; 114 } 115 } 116 117 /** 118 * @ingroup netifapi_netif 119 * Call netif_add() in a thread-safe way by running that function inside the 120 * tcpip_thread context. 121 * 122 * @note for params @see netif_add() 123 */ 124 err_t 125 netifapi_netif_add(struct netif *netif, 126 #if LWIP_IPV4 127 const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, 128 #endif /* LWIP_IPV4 */ 129 void *state, netif_init_fn init, netif_input_fn input) 130 { 131 err_t err; 132 NETIFAPI_VAR_DECLARE(msg); 133 NETIFAPI_VAR_ALLOC(msg); 134 135 #if LWIP_IPV4 136 if (ipaddr == NULL) { 137 ipaddr = IP4_ADDR_ANY4; 138 } 139 if (netmask == NULL) { 140 netmask = IP4_ADDR_ANY4; 141 } 142 if (gw == NULL) { 143 gw = IP4_ADDR_ANY4; 144 } 145 #endif /* LWIP_IPV4 */ 146 147 NETIFAPI_VAR_REF(msg).netif = netif; 148 #if LWIP_IPV4 149 NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); 150 NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask); 151 NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw); 152 #endif /* LWIP_IPV4 */ 153 NETIFAPI_VAR_REF(msg).msg.add.state = state; 154 NETIFAPI_VAR_REF(msg).msg.add.init = init; 155 NETIFAPI_VAR_REF(msg).msg.add.input = input; 156 err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call); 157 NETIFAPI_VAR_FREE(msg); 158 return err; 159 } 160 161 #if LWIP_IPV4 162 /** 163 * @ingroup netifapi_netif 164 * Call netif_set_addr() in a thread-safe way by running that function inside the 165 * tcpip_thread context. 166 * 167 * @note for params @see netif_set_addr() 168 */ 169 err_t 170 netifapi_netif_set_addr(struct netif *netif, 171 const ip4_addr_t *ipaddr, 172 const ip4_addr_t *netmask, 173 const ip4_addr_t *gw) 174 { 175 err_t err; 176 NETIFAPI_VAR_DECLARE(msg); 177 NETIFAPI_VAR_ALLOC(msg); 178 179 if (ipaddr == NULL) { 180 ipaddr = IP4_ADDR_ANY4; 181 } 182 if (netmask == NULL) { 183 netmask = IP4_ADDR_ANY4; 184 } 185 if (gw == NULL) { 186 gw = IP4_ADDR_ANY4; 187 } 188 189 NETIFAPI_VAR_REF(msg).netif = netif; 190 NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); 191 NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask); 192 NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw); 193 err = tcpip_api_call(netifapi_do_netif_set_addr, &API_VAR_REF(msg).call); 194 NETIFAPI_VAR_FREE(msg); 195 return err; 196 } 197 #endif /* LWIP_IPV4 */ 198 199 /** 200 * call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe 201 * way by running that function inside the tcpip_thread context. 202 * 203 * @note use only for functions where there is only "netif" parameter. 204 */ 205 err_t 206 netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, 207 netifapi_errt_fn errtfunc) 208 { 209 err_t err; 210 NETIFAPI_VAR_DECLARE(msg); 211 NETIFAPI_VAR_ALLOC(msg); 212 213 NETIFAPI_VAR_REF(msg).netif = netif; 214 NETIFAPI_VAR_REF(msg).msg.common.voidfunc = voidfunc; 215 NETIFAPI_VAR_REF(msg).msg.common.errtfunc = errtfunc; 216 err = tcpip_api_call(netifapi_do_netif_common, &API_VAR_REF(msg).call); 217 NETIFAPI_VAR_FREE(msg); 218 return err; 219 } 220 221 #endif /* LWIP_NETIF_API */ 222