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 */
57static err_t
58netifapi_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 */
83static err_t
84netifapi_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 */
102static err_t
103netifapi_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 */
124err_t
125netifapi_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 */
169err_t
170netifapi_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 */
205err_t
206netifapi_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