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
netifapi_do_netif_add(struct tcpip_api_call_data * m)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
netifapi_do_netif_set_addr(struct tcpip_api_call_data * m)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
netifapi_do_netif_common(struct tcpip_api_call_data * m)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
netifapi_netif_add(struct netif * netif,const ip4_addr_t * ipaddr,const ip4_addr_t * netmask,const ip4_addr_t * gw,void * state,netif_init_fn init,netif_input_fn input)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
netifapi_netif_set_addr(struct netif * netif,const ip4_addr_t * ipaddr,const ip4_addr_t * netmask,const ip4_addr_t * gw)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
netifapi_netif_common(struct netif * netif,netifapi_void_fn voidfunc,netifapi_errt_fn errtfunc)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