• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
netifapi_do_netif_add(struct tcpip_api_call_data * m)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
netifapi_do_netif_set_addr(struct tcpip_api_call_data * m)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
netifapi_do_name_to_index(struct tcpip_api_call_data * m)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
netifapi_do_index_to_name(struct tcpip_api_call_data * m)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
netifapi_do_netif_common(struct tcpip_api_call_data * m)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
netifapi_arp_add(const ip4_addr_t * ipaddr,struct eth_addr * ethaddr,enum netifapi_arp_entry type)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
netifapi_arp_remove(const ip4_addr_t * ipaddr,enum netifapi_arp_entry type)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
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)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
netifapi_netif_set_addr(struct netif * netif,const ip4_addr_t * ipaddr,const ip4_addr_t * netmask,const ip4_addr_t * gw)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
netifapi_netif_common(struct netif * netif,netifapi_void_fn voidfunc,netifapi_errt_fn errtfunc)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
netifapi_netif_name_to_index(const char * name,u8_t * idx)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
netifapi_netif_index_to_name(u8_t idx,char * name)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