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