xref: /third_party/lwip/src/api/netifapi.c (revision 195972f6)
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 */
60static err_t
61netifapi_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 */
89static err_t
90netifapi_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*/
107static err_t
108netifapi_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*/
121static err_t
122netifapi_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 */
143static err_t
144netifapi_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 */
169err_t
170netifapi_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 */
199err_t
200netifapi_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 */
228err_t
229netifapi_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 */
273err_t
274netifapi_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 */
309err_t
310netifapi_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*/
333err_t
334netifapi_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*/
365err_t
366netifapi_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
388static err_t
389netifapi_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
397err_t
398netifapi_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
412err_t
413netifapi_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