• 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 /**********************************************************************************
42  * Notice of Export Control Law
43  * ===============================================
44  * LiteOS may be subject to applicable export control laws and regulations, which
45  * might include those applicable to LiteOS of U.S. and the country in which you
46  * are located.
47  * Import, export and usage of LiteOS in any manner by you shall be in compliance
48  * with such applicable export control laws and regulations.
49  **********************************************************************************/
50 
51 #include "lwip/opt.h"
52 
53 #if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */
54 
55 #include "lwip/etharp.h"
56 #include "lwip/netifapi.h"
57 #include "lwip/memp.h"
58 #include "lwip/priv/tcpip_priv.h"
59 #include "lwip/mld6.h"
60 #include "lwip/dhcp.h"
61 #include "lwip/dhcp6.h"
62 #include "lwip/if_api.h"
63 #include "lwip/nd6.h"
64 
65 #include <string.h> /* strncpy */
66 
67 #define NETIFAPI_VAR_REF(name)      API_VAR_REF(name)
68 #define NETIFAPI_VAR_DECLARE(name)  API_VAR_DECLARE(struct netifapi_msg, name)
69 #define NETIFAPI_VAR_ALLOC(name)    API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name, ERR_MEM)
70 #define NETIFAPI_VAR_FREE(name)     API_VAR_FREE(MEMP_NETIFAPI_MSG, name)
71 
72 #if LWIP_MPU_COMPATIBLE
netifapi_msg_alloc(struct netifapi_msg ** name)73 static inline err_t netifapi_msg_alloc(struct netifapi_msg **name)
74 {
75   API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, (*name), ERR_MEM);
76   LWIP_UNUSED_ARG(name);
77   return ERR_OK;
78 }
79 #else
netifapi_msg_alloc(struct netifapi_msg * name)80 static inline err_t netifapi_msg_alloc(struct netifapi_msg *name)
81 {
82   LWIP_UNUSED_ARG(name);
83   return ERR_OK;
84 }
85 #endif
86 
87 #if LWIP_DHCP_VENDOR_CLASS_IDENTIFIER
88 static err_t do_netifapi_set_vci(struct tcpip_api_call_data *m);
89 err_t netifapi_set_vci(char *vci, u8_t vci_len);
90 static err_t do_netifapi_get_vci(struct tcpip_api_call_data *m);
91 err_t netifapi_get_vci(char *vci, u8_t *vci_len);
92 #endif /* LWIP_DHCP_VENDOR_CLASS_IDENTIFIER */
93 
94 /**
95  * Call netif_add() inside the tcpip_thread context.
96  */
97 static err_t
netifapi_do_netif_add(struct tcpip_api_call_data * m)98 netifapi_do_netif_add(struct tcpip_api_call_data *m)
99 {
100   /* cast through void* to silence alignment warnings.
101    * We know it works because the structs have been instantiated as struct netifapi_msg */
102   struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m;
103 
104   if (!netif_add(msg->netif
105 #if LWIP_IPV4
106                  , API_EXPR_REF(msg->msg.add.ipaddr),
107                  API_EXPR_REF(msg->msg.add.netmask),
108                  API_EXPR_REF(msg->msg.add.gw)
109 #endif /* LWIP_IPV4 */
110                 )) {
111     return ERR_IF;
112   } else {
113     return ERR_OK;
114   }
115 }
116 
117 #if LWIP_IPV4
118 /**
119  * Call netif_set_addr() inside the tcpip_thread context.
120  */
121 static err_t
netifapi_do_netif_set_addr(struct tcpip_api_call_data * m)122 netifapi_do_netif_set_addr(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   return netif_set_addr(msg->netif,
129                         API_EXPR_REF(msg->msg.add.ipaddr),
130                         API_EXPR_REF(msg->msg.add.netmask),
131                         API_EXPR_REF(msg->msg.add.gw));
132 }
133 
134 /**
135  * Call netif_get_addr() inside the tcpip_thread context.
136  */
137 static err_t
netifapi_do_netif_get_addr(struct tcpip_api_call_data * m)138 netifapi_do_netif_get_addr(struct tcpip_api_call_data *m)
139 {
140   /* cast through void* to silence alignment warnings.
141    * We know it works because the structs have been instantiated as struct netifapi_msg */
142   struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
143 
144   return netif_get_addr(msg->netif,
145                         msg->msg.add_get.ipaddr,
146                         msg->msg.add_get.netmask,
147                         msg->msg.add_get.gw);
148 }
149 
150 #endif /* LWIP_IPV4 */
151 
152 #if DRIVER_STATUS_CHECK
153 err_t
netifapi_wake_queue(struct netif * netif)154 netifapi_wake_queue(struct netif *netif)
155 {
156   return netifapi_netif_common(netif, NULL, netif_wake_queue);
157 }
158 
159 err_t
netifapi_stop_queue(struct netif * netif)160 netifapi_stop_queue(struct netif *netif)
161 {
162   return netifapi_netif_common(netif, NULL, netif_stop_queue);
163 }
164 #endif /* DRIVER_STATUS_CHECK */
165 
166 /**
167 * Call netif_name_to_index() inside the tcpip_thread context.
168 */
169 static err_t
netifapi_do_name_to_index(struct tcpip_api_call_data * m)170 netifapi_do_name_to_index(struct tcpip_api_call_data *m)
171 {
172   /* cast through void* to silence alignment warnings.
173    * We know it works because the structs have been instantiated as struct netifapi_msg */
174   u8_t index;
175   struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
176 
177   index = netif_name_to_index(msg->msg.ifs.name);
178   msg->msg.ifs.index = index;
179 
180   if (index == NETIF_NO_INDEX) {
181     return ERR_VAL;
182   } else {
183     return ERR_OK;
184   }
185 }
186 
187 /**
188 * Call netif_index_to_name() inside the tcpip_thread context.
189 */
190 static err_t
netifapi_do_index_to_name(struct tcpip_api_call_data * m)191 netifapi_do_index_to_name(struct tcpip_api_call_data *m)
192 {
193   /* cast through void* to silence alignment warnings.
194    * We know it works because the structs have been instantiated as struct netifapi_msg */
195   struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m;
196 
197   if (!netif_index_to_name(msg->msg.ifs.index, msg->msg.ifs.name)) {
198     /* return failure via empty name */
199     msg->msg.ifs.name[0] = '\0';
200   }
201   return ERR_OK;
202 }
203 
204 /**
205  * Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the
206  * tcpip_thread context.
207  */
208 static err_t
netifapi_do_netif_common(struct tcpip_api_call_data * m)209 netifapi_do_netif_common(struct tcpip_api_call_data *m)
210 {
211   /* cast through void* to silence alignment warnings.
212    * We know it works because the structs have been instantiated as struct netifapi_msg */
213   struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m;
214 
215   if (msg->msg.common.errtfunc != NULL) {
216     return msg->msg.common.errtfunc(msg->netif);
217   } else {
218     msg->msg.common.voidfunc(msg->netif);
219     return ERR_OK;
220   }
221 }
222 
223 #if LWIP_ARP && LWIP_IPV4
224 /**
225  * @ingroup netifapi_arp
226  * Add or update an entry in the ARP cache.
227  * For an update, ipaddr is used to find the cache entry.
228  *
229  * @param ipaddr IPv4 address of cache entry
230  * @param ethaddr hardware address mapped to ipaddr
231  * @param type type of ARP cache entry
232  * @return ERR_OK: entry added/updated, else error from err_t
233  */
234 err_t
netifapi_arp_add(const ip4_addr_t * ipaddr,struct eth_addr * ethaddr,enum netifapi_arp_entry type)235 netifapi_arp_add(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, enum netifapi_arp_entry type)
236 {
237   err_t err;
238 
239   /* We only support permanent entries currently */
240   LWIP_UNUSED_ARG(type);
241 
242 #if ETHARP_SUPPORT_STATIC_ENTRIES && LWIP_TCPIP_CORE_LOCKING
243   LOCK_TCPIP_CORE();
244   err = etharp_add_static_entry(ipaddr, ethaddr);
245   UNLOCK_TCPIP_CORE();
246 #else
247   /* @todo add new vars to struct netifapi_msg and create a 'do' func */
248   LWIP_UNUSED_ARG(ipaddr);
249   LWIP_UNUSED_ARG(ethaddr);
250   err = ERR_VAL;
251 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES && LWIP_TCPIP_CORE_LOCKING */
252 
253   return err;
254 }
255 
256 /**
257  * @ingroup netifapi_arp
258  * Remove an entry in the ARP cache identified by ipaddr
259  *
260  * @param ipaddr IPv4 address of cache entry
261  * @param type type of ARP cache entry
262  * @return ERR_OK: entry removed, else error from err_t
263  */
264 err_t
netifapi_arp_remove(const ip4_addr_t * ipaddr,enum netifapi_arp_entry type)265 netifapi_arp_remove(const ip4_addr_t *ipaddr, enum netifapi_arp_entry type)
266 {
267   err_t err;
268 
269   /* We only support permanent entries currently */
270   LWIP_UNUSED_ARG(type);
271 
272 #if ETHARP_SUPPORT_STATIC_ENTRIES && LWIP_TCPIP_CORE_LOCKING
273   LOCK_TCPIP_CORE();
274   err = etharp_remove_static_entry(ipaddr);
275   UNLOCK_TCPIP_CORE();
276 #else
277   /* @todo add new vars to struct netifapi_msg and create a 'do' func */
278   LWIP_UNUSED_ARG(ipaddr);
279   err = ERR_VAL;
280 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES && LWIP_TCPIP_CORE_LOCKING */
281 
282   return err;
283 }
284 
285 static err_t
netifapi_do_ip_to_mac(struct tcpip_api_call_data * m)286 netifapi_do_ip_to_mac(struct tcpip_api_call_data *m)
287 {
288   struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m;
289   return etharp_ip_to_mac((const ip4_addr_t *)(msg->msg.arp.ip), msg->msg.arp.mac, msg->msg.arp.maclen);
290 }
291 
292 err_t
netifapi_ip_to_mac(const ip4_addr_t * ip,u8_t * mac,u8_t * maclen)293 netifapi_ip_to_mac(const ip4_addr_t *ip, u8_t *mac, u8_t *maclen)
294 {
295   err_t err;
296   NETIFAPI_VAR_DECLARE(msg);
297 
298   LWIP_ERROR("netifapi_ip_to_mac : invalid arguments \n", ((ip != NULL)), return ERR_ARG);
299   LWIP_ERROR("netifapi_ip_to_mac : invalid arguments \n", ((mac != NULL)), return ERR_ARG);
300   LWIP_ERROR("netifapi_ip_to_mac : invalid arguments \n", ((maclen != NULL)), return ERR_ARG);
301 
302   NETIFAPI_VAR_ALLOC(msg);
303   NETIFAPI_VAR_REF(msg).msg.arp.ip = (ip4_addr_t *)ip;
304   NETIFAPI_VAR_REF(msg).msg.arp.mac = mac;
305   NETIFAPI_VAR_REF(msg).msg.arp.maclen = maclen;
306   err = tcpip_api_call(netifapi_do_ip_to_mac, &API_VAR_REF(msg).call);
307   NETIFAPI_VAR_FREE(msg);
308   return err;
309 }
310 
311 #endif /* LWIP_ARP && LWIP_IPV4 */
312 
313 /**
314  * @ingroup netifapi_netif
315  * Call netif_add() in a thread-safe way by running that function inside the
316  * tcpip_thread context.
317  *
318  * @note for params @see netif_add()
319  */
320 err_t
netifapi_netif_add(struct netif * netif,const ip4_addr_t * ipaddr,const ip4_addr_t * netmask,const ip4_addr_t * gw)321 netifapi_netif_add(struct netif *netif
322 #if LWIP_IPV4
323                    ,const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw
324 #endif /* LWIP_IPV4 */
325                    )
326 {
327   err_t err;
328   NETIFAPI_VAR_DECLARE(msg);
329   NETIFAPI_VAR_ALLOC(msg);
330 
331 #if LWIP_IPV4
332   if (ipaddr == NULL) {
333     ipaddr = IP4_ADDR_ANY4;
334   }
335   if (netmask == NULL) {
336     netmask = IP4_ADDR_ANY4;
337   }
338   if (gw == NULL) {
339     gw = IP4_ADDR_ANY4;
340   }
341 #endif /* LWIP_IPV4 */
342 
343   NETIFAPI_VAR_REF(msg).netif = netif;
344 #if LWIP_IPV4
345   NETIFAPI_VAR_REF(msg).msg.add.ipaddr  = NETIFAPI_VAR_REF(ipaddr);
346   NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask);
347   NETIFAPI_VAR_REF(msg).msg.add.gw      = NETIFAPI_VAR_REF(gw);
348 #endif /* LWIP_IPV4 */
349   err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call);
350   NETIFAPI_VAR_FREE(msg);
351   return err;
352 }
353 
354 #ifdef LWIP_TESTBED
355 err_t
netifapi_netif_reset(struct netif * netif)356 netifapi_netif_reset(struct netif *netif)
357 {
358   return netifapi_netif_common(netif, NULL, netif_reset);
359 }
360 #endif
361 
362 /**
363  * Call netif_find() inside the tcpip_thread context.
364  */
365 static err_t
do_netifapi_netif_find_by_name(struct tcpip_api_call_data * m)366 do_netifapi_netif_find_by_name(struct tcpip_api_call_data *m)
367 {
368   struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
369 
370   msg->netif = netif_find(msg->msg.find_by_name.name);
371   return ERR_OK;
372 }
373 
374 struct netif*
netifapi_netif_find_by_name(const char * name)375 netifapi_netif_find_by_name(const char *name)
376 {
377   struct netif *netif = NULL;
378   NETIFAPI_VAR_DECLARE(msg);
379   if (netifapi_msg_alloc(&msg) != ERR_OK) {
380     return NULL;
381   }
382 
383   NETIFAPI_VAR_REF(msg).netif = NULL;
384   NETIFAPI_VAR_REF(msg).msg.find_by_name.name = name;
385   (void)tcpip_api_call(do_netifapi_netif_find_by_name, &API_VAR_REF(msg).call);
386   netif = NETIFAPI_VAR_REF(msg).netif;
387   NETIFAPI_VAR_FREE(msg);
388   return netif;
389 }
390 
391 /**
392  * Call netif_find_by_ifindex() inside the tcpip_thread context.
393  */
394 static err_t
do_netifapi_netif_find_by_ifindex(struct tcpip_api_call_data * m)395 do_netifapi_netif_find_by_ifindex(struct tcpip_api_call_data *m)
396 {
397   struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
398 
399   msg->netif = netif_find_by_ifindex(msg->msg.find_by_ifindex.ifindex);
400   return ERR_OK;
401 }
402 
403 struct netif*
netifapi_netif_find_by_ifindex(unsigned ifindex)404 netifapi_netif_find_by_ifindex(unsigned ifindex)
405 {
406   struct netif *netif = NULL;
407   NETIFAPI_VAR_DECLARE(msg);
408   if (netifapi_msg_alloc(&msg) != ERR_OK) {
409     return NULL;
410   }
411 
412   NETIFAPI_VAR_REF(msg).netif = NULL;
413   NETIFAPI_VAR_REF(msg).msg.find_by_ifindex.ifindex = (u8_t)ifindex;
414   (void)tcpip_api_call(do_netifapi_netif_find_by_ifindex, &API_VAR_REF(msg).call);
415   netif = NETIFAPI_VAR_REF(msg).netif;
416   NETIFAPI_VAR_FREE(msg);
417   return netif;
418 }
419 
420 /**
421  * Call netif_find_by_ipaddr() inside the tcpip_thread context.
422  */
423 static err_t
do_netifapi_netif_find_by_ipaddr(struct tcpip_api_call_data * m)424 do_netifapi_netif_find_by_ipaddr(struct tcpip_api_call_data *m)
425 {
426   struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
427   msg->netif = netif_find_by_ipaddr(msg->msg.find_by_ipaddr.ipaddr);
428   return ERR_OK;
429 }
430 
431 struct netif *
netifapi_netif_find_by_ipaddr(const ip_addr_t * ipaddr)432 netifapi_netif_find_by_ipaddr(const ip_addr_t *ipaddr)
433 {
434   struct netif *netif = NULL;
435   NETIFAPI_VAR_DECLARE(msg);
436   if (netifapi_msg_alloc(&msg) != ERR_OK) {
437     return NULL;
438   }
439 
440   NETIFAPI_VAR_REF(msg).netif = NULL;
441   NETIFAPI_VAR_REF(msg).msg.find_by_ipaddr.ipaddr = ipaddr;
442   (void)tcpip_api_call(do_netifapi_netif_find_by_ipaddr, &API_VAR_REF(msg).call);
443   netif = NETIFAPI_VAR_REF(msg).netif;
444   NETIFAPI_VAR_FREE(msg);
445   return netif;
446 }
447 
448 #if LWIP_IPV4
449 /**
450  * @ingroup netifapi_netif
451  * Call netif_set_addr() in a thread-safe way by running that function inside the
452  * tcpip_thread context.
453  *
454  * @note for params @see netif_set_addr()
455  */
456 err_t
netifapi_netif_set_addr(struct netif * netif,const ip4_addr_t * ipaddr,const ip4_addr_t * netmask,const ip4_addr_t * gw)457 netifapi_netif_set_addr(struct netif *netif,
458                         const ip4_addr_t *ipaddr,
459                         const ip4_addr_t *netmask,
460                         const ip4_addr_t *gw)
461 {
462   err_t err;
463   NETIFAPI_VAR_DECLARE(msg);
464   NETIFAPI_VAR_ALLOC(msg);
465 
466   if (ipaddr == NULL) {
467     ipaddr = IP4_ADDR_ANY4;
468   }
469   if (netmask == NULL) {
470     netmask = IP4_ADDR_ANY4;
471   }
472   if (gw == NULL) {
473     gw = IP4_ADDR_ANY4;
474   }
475 
476   NETIFAPI_VAR_REF(msg).netif = netif;
477   NETIFAPI_VAR_REF(msg).msg.add.ipaddr  = NETIFAPI_VAR_REF(ipaddr);
478   NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask);
479   NETIFAPI_VAR_REF(msg).msg.add.gw      = NETIFAPI_VAR_REF(gw);
480   err = tcpip_api_call(netifapi_do_netif_set_addr, &API_VAR_REF(msg).call);
481   NETIFAPI_VAR_FREE(msg);
482   return err;
483 }
484 
485 err_t
netifapi_netif_get_addr(struct netif * netif,ip4_addr_t * ipaddr,ip4_addr_t * netmask,ip4_addr_t * gw)486 netifapi_netif_get_addr(struct netif *netif,
487                         ip4_addr_t *ipaddr,
488                         ip4_addr_t *netmask,
489                         ip4_addr_t *gw)
490 {
491   err_t err;
492   NETIFAPI_VAR_DECLARE(msg);
493   NETIFAPI_VAR_ALLOC(msg);
494 
495   NETIFAPI_VAR_REF(msg).netif = netif;
496   NETIFAPI_VAR_REF(msg).msg.add_get.ipaddr  = ipaddr;
497   NETIFAPI_VAR_REF(msg).msg.add_get.netmask = netmask;
498   NETIFAPI_VAR_REF(msg).msg.add_get.gw      = gw;
499   err = tcpip_api_call(netifapi_do_netif_get_addr, &API_VAR_REF(msg).call);
500   NETIFAPI_VAR_FREE(msg);
501   return err;
502 }
503 
504 #endif /* LWIP_IPV4 */
505 
506 /**
507  * call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe
508  * way by running that function inside the tcpip_thread context.
509  *
510  * @note use only for functions where there is only "netif" parameter.
511  */
512 err_t
netifapi_netif_common(struct netif * netif,netifapi_void_fn voidfunc,netifapi_errt_fn errtfunc)513 netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc,
514                       netifapi_errt_fn errtfunc)
515 {
516   err_t err;
517   NETIFAPI_VAR_DECLARE(msg);
518 
519   LWIP_ERROR("netifapi_netif_common : invalid arguments", voidfunc != NULL || errtfunc != NULL, return ERR_VAL);
520 
521   NETIFAPI_VAR_ALLOC(msg);
522   NETIFAPI_VAR_REF(msg).netif = netif;
523   NETIFAPI_VAR_REF(msg).msg.common.voidfunc = voidfunc;
524   NETIFAPI_VAR_REF(msg).msg.common.errtfunc = errtfunc;
525   err = tcpip_api_call(netifapi_do_netif_common, &API_VAR_REF(msg).call);
526   NETIFAPI_VAR_FREE(msg);
527   return err;
528 }
529 
530 /*
531  * Remove a network interface from the list of lwIP netifs.
532  *
533  * @param netif the network interface to remove
534  *
535  * @return
536  *  - ERR_OK: On success
537  *  - ERR_MEM: On failure due to memory
538  *  - ERR_VAL: On failure due to Illegal value
539  *  - ERR_NODEV: On failure due to No such netif
540  */
541 err_t
netifapi_netif_remove(struct netif * netif)542 netifapi_netif_remove(struct netif *netif)
543 {
544   return netifapi_netif_common(netif, NULL, netif_remove);
545 }
546 
547 /*
548  * Bring an interface up, available for processing
549  * traffic.
550  *
551  * @note: Enabling DHCP on a down interface will make it come
552  * up once configured.
553  *
554  * @param netif the network interface
555  *
556  * @return
557  *  - ERR_OK: On success
558  *  - ERR_MEM: On failure due to memory
559  *  - ERR_VAL: On failure due to Illegal value
560  */
561 err_t
netifapi_netif_set_up(struct netif * netif)562 netifapi_netif_set_up(struct netif *netif)
563 {
564   return netifapi_netif_common(netif, NULL, netif_set_up);
565 }
566 
567 /*
568  * Bring an interface down, disabling any traffic processing.
569  *
570  * @note: Enabling DHCP on a down interface will make it come
571  * up once configured.
572  *
573  * @param netif the network interface
574  *
575  * @return
576  *  - ERR_OK: On success
577  *  - ERR_MEM: On failure due to memory
578  *  - ERR_VAL: On failure due to Illegal value
579  */
580 err_t
netifapi_netif_set_down(struct netif * netif)581 netifapi_netif_set_down(struct netif *netif)
582 {
583   return netifapi_netif_common(netif, NULL, netif_set_down);
584 }
585 
586 /*
587  * Called by a driver when its link goes up
588  *
589  * @param netif The network interface
590  *
591  * @return
592  *  - ERR_OK: On success
593  *  - ERR_MEM: On failure due to memory
594  *  - ERR_VAL: On failure due to Illegal value
595  */
596 err_t
netifapi_netif_set_link_up(struct netif * netif)597 netifapi_netif_set_link_up(struct netif *netif)
598 {
599   return netifapi_netif_common(netif, NULL, netif_set_link_up);
600 }
601 
602 /*
603  * Called by a driver when its link goes down
604  *
605  * @param netif The network interface
606  *
607  * @return
608  *  - ERR_OK: On success
609  *  - ERR_MEM: On failure due to memory
610  *  - ERR_VAL: On failure due to Illegal value
611  */
612 err_t
netifapi_netif_set_link_down(struct netif * netif)613 netifapi_netif_set_link_down(struct netif *netif)
614 {
615   return netifapi_netif_common(netif, NULL, netif_set_link_down);
616 }
617 
618 #if LWIP_DHCP
619 /*
620  * Start DHCP negotiation for a network interface.
621  *
622  * If no DHCP client instance was attached to this interface,
623  * a new client is created first. If a DHCP client instance
624  * was already present, it restarts negotiation.
625  *
626  * @param netif The lwIP network interface
627  *
628  * @return lwIP error code
629  * - ERR_OK - No error
630  * - ERR_MEM - Out of memory
631  */
632 err_t
netifapi_dhcp_start(struct netif * netif)633 netifapi_dhcp_start(struct netif *netif)
634 {
635   return netifapi_netif_common(netif, NULL, dhcp_start);
636 }
637 
638 /*
639  * Remove the DHCP client from the interface.
640  *
641  * @param netif The network interface to stop DHCP on
642  *
643  * @return
644  *  - ERR_OK: On success
645  *  - ERR_MEM: On failure due to memory
646  *  - ERR_VAL: On failure due to Illegal value
647  */
648 err_t
netifapi_dhcp_stop(struct netif * netif)649 netifapi_dhcp_stop(struct netif *netif)
650 {
651   return netifapi_netif_common(netif, dhcp_stop, NULL);
652 }
653 
654 /*
655  * Inform a DHCP server of our manual configuration.
656  *
657  * This informs DHCP servers of our fixed IP_add configuration
658  * by sending an INFORM message. It does not involve DHCP address
659  * configuration, it is just here to be nice to the network.
660  *
661  * @param netif The lwIP network interface
662  *
663  * @return
664  *  - ERR_OK: On success
665  *  - ERR_MEM: On failure due to memory
666  *  - ERR_VAL: On failure due to Illegal value
667  */
668 err_t
netifapi_dhcp_inform(struct netif * netif)669 netifapi_dhcp_inform(struct netif *netif)
670 {
671   return netifapi_netif_common(netif, dhcp_inform, NULL);
672 }
673 
674 /*
675  * Renew an existing DHCP lease at the involved DHCP server.
676  *
677  * @param netif The lwIP network interface
678  *
679  * @return
680  *  - ERR_OK: On success
681  *  - ERR_MEM: On failure due to memory
682  *  - ERR_VAL: On failure due to Illegal value
683  */
684 err_t
netifapi_dhcp_renew(struct netif * netif)685 netifapi_dhcp_renew(struct netif *netif)
686 {
687   return netifapi_netif_common(netif, NULL, dhcp_renew);
688 }
689 
690 /*
691  * Release a DHCP lease (usually called before @ref dhcp_stop).
692  *
693  * @param netif The lwIP network interface
694  *
695  * @return
696  *  - ERR_OK: On success
697  *  - ERR_MEM: On failure due to memory
698  *  - ERR_VAL: On failure due to Illegal value
699  */
700 err_t
netifapi_dhcp_release(struct netif * netif)701 netifapi_dhcp_release(struct netif *netif)
702 {
703   return netifapi_netif_common(netif, NULL, dhcp_release);
704 }
705 
706 /*
707  * @ingroup netifapi_dhcp4
708  * @see dhcp_release_and_stop()
709  */
netifapi_dhcp_release_and_stop(struct netif * netif)710 err_t netifapi_dhcp_release_and_stop(struct netif *netif)
711 {
712   return netifapi_netif_common(netif, dhcp_release_and_stop, NULL);
713 }
714 
715 /*
716  * Check DHCP negotiation is done for a network interface.
717  *
718  * @param netif The lwIP network interface
719  *
720  * @return
721  * - ERR_OK - if DHCP is bound
722  * - ERR_MEM - if DHCP bound is still progressing
723  */
724 err_t
netifapi_dhcp_is_bound(struct netif * netif)725 netifapi_dhcp_is_bound(struct netif *netif)
726 {
727   return netifapi_netif_common(netif, NULL, dhcp_is_bound);
728 }
729 
730 /*
731  * Removes a struct dhcp from a netif.
732  *
733  * ATTENTION: Only use this when not using dhcp_set_struct() to allocate the
734  * struct dhcp since the memory is passed back to the heap.
735  *
736  * @param netif the netif from which to remove the struct dhcp
737  *
738  * @return
739  *  - ERR_OK: On success
740  *  - ERR_MEM: On failure due to memory
741  *  - ERR_VAL: On failure due to Illegal value
742  */
743 err_t
netifapi_dhcp_cleanup(struct netif * netif)744 netifapi_dhcp_cleanup(struct netif *netif)
745 {
746   return netifapi_netif_common(netif, dhcp_cleanup, NULL);
747 }
748 
749 /**
750  * To call dhcp_set_struct() inside the tcpip_thread context.
751  */
752 static err_t
netifapi_do_dhcp_set_struct(struct tcpip_api_call_data * m)753 netifapi_do_dhcp_set_struct(struct tcpip_api_call_data *m)
754 {
755   struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
756 
757   dhcp_set_struct(msg->netif, msg->msg.dhcp_struct.dhcp);
758   return ERR_OK;
759 }
760 
761 /*
762  * Set a statically allocated struct dhcp to work with.
763  * Using this prevents dhcp_start to allocate it using mem_malloc.
764  *
765  * @param netif the netif for which to set the struct dhcp
766  * @param dhcp (uninitialised) dhcp struct allocated by the application
767  *
768  * @return
769  *  - ERR_OK: On success
770  *  - ERR_MEM: On failure due to memory
771  *  - ERR_VAL: On failure due to Illegal value
772  */
773 err_t
netifapi_dhcp_set_struct(struct netif * netif,struct dhcp * dhcp)774 netifapi_dhcp_set_struct(struct netif *netif, struct dhcp *dhcp)
775 {
776   err_t err;
777   NETIFAPI_VAR_DECLARE(msg);
778 
779   NETIFAPI_VAR_ALLOC(msg);
780   NETIFAPI_VAR_REF(msg).netif = netif;
781   NETIFAPI_VAR_REF(msg).msg.dhcp_struct.dhcp = dhcp;
782   err = tcpip_api_call(netifapi_do_dhcp_set_struct, &API_VAR_REF(msg).call);
783   NETIFAPI_VAR_FREE(msg);
784   return err;
785 }
786 
787 /*
788  * To remove the statically assigned dhcp structure
789  *
790  * @param netif the network interface
791  *
792  * @return
793  *  - ERR_OK: On success
794  *  - ERR_MEM: On failure due to memory
795  *  - ERR_VAL: On failure due to Illegal value
796  */
797 err_t
netifapi_dhcp_remove_struct(struct netif * netif)798 netifapi_dhcp_remove_struct(struct netif *netif)
799 {
800   return netifapi_netif_common(netif, dhcp_remove_struct, NULL);
801 }
802 
803 #if LWIP_DHCP_SUBSTITUTE
804 err_t
netifapi_dhcp_clients_info_get(struct netif * netif,struct dhcp_clients_info ** clis_info)805 netifapi_dhcp_clients_info_get(struct netif *netif, struct dhcp_clients_info **clis_info)
806 {
807   return netifapi_netif_call_argcb(netif, dhcp_clients_info_get, (void *)clis_info);
808 }
809 
810 err_t
netifapi_dhcp_clients_info_free(struct netif * netif,struct dhcp_clients_info ** clis_info)811 netifapi_dhcp_clients_info_free(struct netif *netif, struct dhcp_clients_info **clis_info)
812 {
813   return netifapi_netif_call_argcb(netif, dhcp_clients_info_free, (void *)clis_info);
814 }
815 
816 err_t
netifapi_dhcp_client_info_find(struct netif * netif,struct dhcp_client_info * cli_info)817 netifapi_dhcp_client_info_find(struct netif *netif, struct dhcp_client_info *cli_info)
818 {
819   return netifapi_netif_call_argcb(netif, dhcp_client_info_find, (void *)cli_info);
820 }
821 
822 #if LWIP_DHCP_LIMIT_CONCURRENT_REQUESTS
823 static err_t
do_dhcp_set_max_concurrent_num(struct netif * netif,void * arg)824 do_dhcp_set_max_concurrent_num(struct netif *netif, void *arg)
825 {
826   return dhcp_set_max_concurrent_num(netif, *((u16_t *)arg));
827 }
828 
829 err_t
netifapi_dhcp_set_max_concurrent_num(struct netif * netif,u16_t dhcp_max_concurrent_num)830 netifapi_dhcp_set_max_concurrent_num(struct netif *netif, u16_t dhcp_max_concurrent_num)
831 {
832   return netifapi_netif_call_argcb(netif, do_dhcp_set_max_concurrent_num, (void *)(&dhcp_max_concurrent_num));
833 }
834 #endif /* LWIP_DHCP_LIMIT_CONCURRENT_REQUESTS */
835 #endif /* LWIP_DHCP_SUBSTITUTE */
836 #endif /* LWIP_DHCP */
837 
838 /*
839  * Call the "argfunc" inside the tcpip_thread context.
840  */
841 static err_t
netifapi_do_netif_argcb(struct tcpip_api_call_data * m)842 netifapi_do_netif_argcb(struct tcpip_api_call_data *m)
843 {
844   /* cast through void* to silence alignment warnings.
845    * We know it works because the structs have been instantiated as struct netifapi_msg */
846   struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
847   return msg->msg.arg_cb.argfunc(msg->netif, msg->msg.arg_cb.arg);
848 }
849 
850 /*
851  * call the "argfunc" with argument arg in a thread-safe
852  * way by running that function inside the tcpip_thread context.
853  *
854  * @note use only for functions where there is only "netif" parameter.
855  */
856 err_t
netifapi_netif_call_argcb(struct netif * netif,netifapi_arg_fn argfunc,void * arg)857 netifapi_netif_call_argcb(struct netif *netif, netifapi_arg_fn argfunc, void *arg)
858 {
859   err_t err;
860   NETIFAPI_VAR_DECLARE(msg);
861 
862   LWIP_ERROR("netifapi_netif_call_argcb : invalid arguments", ((netif != NULL)), return ERR_VAL);
863   LWIP_ERROR("netifapi_netif_call_argcb : invalid arguments", ((argfunc != NULL)), return ERR_VAL);
864 
865   NETIFAPI_VAR_ALLOC(msg);
866   NETIFAPI_VAR_REF(msg).netif = netif;
867   NETIFAPI_VAR_REF(msg).msg.arg_cb.argfunc = argfunc;
868   NETIFAPI_VAR_REF(msg).msg.arg_cb.arg = arg;
869   err = tcpip_api_call(netifapi_do_netif_argcb, &API_VAR_REF(msg).call);
870   NETIFAPI_VAR_FREE(msg);
871   return err;
872 }
873 
874 /*
875  * call the "argfunc" with argument arg in a thread-safe
876  * way by running that function inside the tcpip_thread context.
877  */
878 err_t
netifapi_call_argcb(netifapi_arg_fn argfunc,void * arg)879 netifapi_call_argcb(netifapi_arg_fn argfunc, void *arg)
880 {
881   err_t err;
882   NETIFAPI_VAR_DECLARE(msg);
883 
884   LWIP_ERROR("netifapi_netif_call_argcb : invalid arguments", ((argfunc != NULL)), return ERR_VAL);
885 
886   NETIFAPI_VAR_ALLOC(msg);
887   NETIFAPI_VAR_REF(msg).netif = NULL;
888   NETIFAPI_VAR_REF(msg).msg.arg_cb.argfunc = argfunc;
889   NETIFAPI_VAR_REF(msg).msg.arg_cb.arg = arg;
890   err = tcpip_api_call(netifapi_do_netif_argcb, &API_VAR_REF(msg).call);
891   NETIFAPI_VAR_FREE(msg);
892   return err;
893 }
894 
895 /*
896  * Set a network interface as the default network interface
897  * (used to output all packets for which no specific route is found)
898  *
899  * @param netif the default network interface
900  *
901  * @return
902  *  - ERR_OK: On success
903  *  - ERR_MEM: On failure due to memory
904  *  - ERR_VAL: On failure due to Illegal value
905  */
906 err_t
netifapi_netif_set_default(struct netif * netif)907 netifapi_netif_set_default(struct netif *netif)
908 {
909   return netifapi_netif_common(netif, NULL, netif_set_default);
910 }
911 
912 static err_t
do_netifapi_netif_get_default(struct tcpip_api_call_data * m)913 do_netifapi_netif_get_default(struct tcpip_api_call_data *m)
914 {
915   struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
916 
917   if ((netif_default != NULL) && netif_is_up(netif_default)) {
918     msg->netif = netif_default;
919   } else {
920     msg->netif = NULL;
921   }
922 
923   return ERR_OK;
924 }
925 
926 /*
927  * Get the default network interface
928  *
929  * @return
930  *  - NULL if either the default netif was NOT exist or the default netif was down,
931  *  - else return the default netif pointer
932  */
netifapi_netif_get_default(void)933 struct netif *netifapi_netif_get_default(void)
934 {
935   struct netif *netif_def = NULL;
936   NETIFAPI_VAR_DECLARE(msg);
937 
938   if (netifapi_msg_alloc(&msg) != ERR_OK) {
939     return NULL;
940   }
941 
942   NETIFAPI_VAR_REF(msg).netif = NULL;
943   (void)tcpip_api_call(do_netifapi_netif_get_default, &API_VAR_REF(msg).call);
944   netif_def = NETIFAPI_VAR_REF(msg).netif;
945   NETIFAPI_VAR_FREE(msg);
946   return netif_def;
947 }
948 
949 #if LWIP_IPV6
950 
netif_create_ip6_linklocal_address_wrapper(struct netif * netif,void * arg)951 err_t netif_create_ip6_linklocal_address_wrapper(struct netif *netif, void *arg)
952 {
953   u32_t *tmp = (u32_t*)arg;
954   u32_t from_mac_48bit = *tmp;
955   return netif_create_ip6_linklocal_address(netif, (u8_t)from_mac_48bit);
956 }
957 
958 /*
959  * @ingroup netif_ip6
960  * This function allows for the easy addition of a new IPv6 address to an interface.
961  * It takes care of finding an empty slot and then sets the address tentative
962  * (to make sure that all the subsequent processing happens).
963  *
964  * @param netif netif to add the address on
965  * @param ip6addr address to add
966  * @param chosen_idx if != NULL, the chosen IPv6 address index will be stored here
967  */
968 err_t
netifapi_netif_add_ip6_linklocal_address(struct netif * netif,u8_t from_mac_48bit)969 netifapi_netif_add_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit)
970 {
971   err_t err;
972   u32_t is_from_mac_48bit = from_mac_48bit;
973   NETIFAPI_VAR_DECLARE(msg);
974 
975   LWIP_ERROR("netifapi_netif_add_ip6_linklocal_address : invalid arguments", ((netif != NULL)), return ERR_VAL);
976   NETIFAPI_VAR_ALLOC(msg);
977 
978   NETIFAPI_VAR_REF(msg).netif = netif;
979   NETIFAPI_VAR_REF(msg).msg.arg_cb.argfunc = netif_create_ip6_linklocal_address_wrapper;
980   NETIFAPI_VAR_REF(msg).msg.arg_cb.arg = &is_from_mac_48bit;
981   err = tcpip_api_call(netifapi_do_netif_argcb, &API_VAR_REF(msg).call);
982   NETIFAPI_VAR_FREE(msg);
983   return err;
984 }
985 
986 /*
987  * @ingroup netif_ip6
988  * This function allows for the easy addition of a new IPv6 address to an interface.
989  * It takes care of finding an empty slot and then sets the address tentative
990  * (to make sure that all the subsequent processing happens).
991  *
992  * @param netif netif to add the address on
993  * @param ip6addr address to add
994  * @param chosen_idx if != NULL, the chosen IPv6 address index will be stored here
995  */
996 err_t
netifapi_netif_add_ip6_address(struct netif * netif,ip_addr_t * ipaddr)997 netifapi_netif_add_ip6_address(struct netif *netif, ip_addr_t *ipaddr)
998 {
999   err_t err;
1000   NETIFAPI_VAR_DECLARE(msg);
1001 
1002   LWIP_ERROR("netifapi_netif_add_ip6_address : invalid arguments", ((ipaddr != NULL)), return ERR_VAL);
1003   LWIP_ERROR("netifapi_netif_add_ip6_address : invalid arguments", ((netif != NULL)), return ERR_VAL);
1004 
1005   /* Do no allow multicast or any ip address or loopback address to be set as interface address */
1006   if (!IP_IS_V6(ipaddr) ||
1007       ip_addr_ismulticast(ipaddr) ||
1008       ip_addr_isany(ipaddr) ||
1009       ip_addr_isloopback(ipaddr)) {
1010     return ERR_VAL;
1011   }
1012 
1013   NETIFAPI_VAR_ALLOC(msg);
1014 
1015   NETIFAPI_VAR_REF(msg).netif = netif;
1016   NETIFAPI_VAR_REF(msg).msg.arg_cb.argfunc = netif_do_add_ipv6_addr;
1017   NETIFAPI_VAR_REF(msg).msg.arg_cb.arg = (void*)ipaddr;
1018   err = tcpip_api_call(netifapi_do_netif_argcb, &API_VAR_REF(msg).call);
1019   NETIFAPI_VAR_FREE(msg);
1020   return err;
1021 }
1022 
1023 #if LWIP_IPV6_AUTOCONFIG
1024 err_t
netifapi_set_ip6_autoconfig_enabled(struct netif * netif)1025 netifapi_set_ip6_autoconfig_enabled(struct netif *netif)
1026 {
1027   return netifapi_netif_common(netif, netif_set_ip6_autoconfig_enabled, NULL);
1028 }
1029 
1030 err_t
netifapi_set_ip6_autoconfig_disabled(struct netif * netif)1031 netifapi_set_ip6_autoconfig_disabled(struct netif *netif)
1032 {
1033   return netifapi_netif_common(netif, netif_set_ip6_autoconfig_disabled, NULL);
1034 }
1035 #endif /* LWIP_IPV6_AUTOCONFIG */
1036 
1037 #endif /* LWIP_IPV6 */
1038 
1039 #if LWIP_IPV6 && LWIP_IPV6_MLD
netif_do_join_ip6_multicastgroup(struct netif * netif,void * arguments)1040 err_t netif_do_join_ip6_multicastgroup(struct netif *netif, void *arguments)
1041 {
1042   ip6_addr_t *ipaddr = (ip6_addr_t *)arguments;
1043   err_t err;
1044 
1045   err = mld6_join_staticgroup_netif(netif, ipaddr);
1046   return err;
1047 }
1048 
1049 err_t
netifapi_netif_join_ip6_multicastgroup(struct netif * netif,ip6_addr_t * ip6addr)1050 netifapi_netif_join_ip6_multicastgroup(struct netif *netif, ip6_addr_t *ip6addr)
1051 {
1052   err_t err;
1053   NETIFAPI_VAR_DECLARE(msg);
1054 
1055   LWIP_ERROR("netifapi_netif_add_ip6_address : invalid arguments", ((ip6addr != NULL)), return ERR_VAL);
1056   LWIP_ERROR("netifapi_netif_add_ip6_address : invalid arguments", ((netif != NULL)), return ERR_VAL);
1057 
1058   NETIFAPI_VAR_ALLOC(msg);
1059 
1060   NETIFAPI_VAR_REF(msg).netif = netif;
1061   NETIFAPI_VAR_REF(msg).msg.arg_cb.argfunc = netif_do_join_ip6_multicastgroup;
1062   NETIFAPI_VAR_REF(msg).msg.arg_cb.arg = (void*)ip6addr;
1063   err = tcpip_api_call(netifapi_do_netif_argcb, &API_VAR_REF(msg).call);
1064   NETIFAPI_VAR_FREE(msg);
1065   return err;
1066 }
1067 
1068 #endif
1069 
1070 #if LWIP_IPV6
1071 /*
1072  * @ingroup netif_ip6
1073  * This function allows for the easy removal of a existing IPv6 address to an interface.
1074  *
1075  * @param netif netif to add the address on
1076  * @param ip6addr address to add
1077  * @param chosen_idx if != NULL, the chosen IPv6 address index will be removed from here
1078  */
1079 void
netifapi_netif_rmv_ip6_address(struct netif * netif,ip_addr_t * ipaddr)1080 netifapi_netif_rmv_ip6_address(struct netif *netif, ip_addr_t *ipaddr)
1081 {
1082   NETIFAPI_VAR_DECLARE(msg);
1083 
1084   LWIP_ERROR("netifapi_netif_add_ip6_address : invalid arguments", ((ipaddr != NULL)), return);
1085   LWIP_ERROR("netifapi_netif_add_ip6_address : invalid arguments", ((netif != NULL)), return);
1086 
1087   if (netifapi_msg_alloc(&msg) != ERR_OK) {
1088     return;
1089   }
1090 
1091   NETIFAPI_VAR_REF(msg).netif = netif;
1092   NETIFAPI_VAR_REF(msg).msg.arg_cb.argfunc = netif_do_rmv_ipv6_addr;
1093   NETIFAPI_VAR_REF(msg).msg.arg_cb.arg = (void*)ipaddr;
1094   (void)tcpip_api_call(netifapi_do_netif_argcb, &API_VAR_REF(msg).call);
1095   NETIFAPI_VAR_FREE(msg);
1096   return;
1097 }
1098 #endif
1099 
1100 #if LWIP_NETIF_LINK_CALLBACK
1101 static err_t
netifapi_do_netif_set_link_callback(struct tcpip_api_call_data * m)1102 netifapi_do_netif_set_link_callback(struct tcpip_api_call_data *m)
1103 {
1104   /* cast through void* to silence alignment warnings.
1105    * We know it works because the structs have been instantiated as struct netifapi_msg */
1106   struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
1107   err_t err;
1108 
1109   err = netif_set_link_callback(msg->netif, msg->msg.netif_link_cb.link_callback);
1110   return err;
1111 }
1112 
1113 err_t
netifapi_netif_set_link_callback(struct netif * netif,netif_status_callback_fn link_callback)1114 netifapi_netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback)
1115 {
1116   err_t err;
1117   NETIFAPI_VAR_DECLARE(msg);
1118 
1119   LWIP_ERROR("netifapi_netif_set_link_callback : invalid arguments", (netif != NULL), return ERR_VAL);
1120   NETIFAPI_VAR_ALLOC(msg);
1121 
1122   NETIFAPI_VAR_REF(msg).netif = netif;
1123   NETIFAPI_VAR_REF(msg).msg.netif_link_cb.link_callback = link_callback;
1124   err = tcpip_api_call(netifapi_do_netif_set_link_callback, &API_VAR_REF(msg).call);
1125   NETIFAPI_VAR_FREE(msg);
1126   return err;
1127 }
1128 #endif
1129 
1130 #if LWIP_NETIF_EXT_STATUS_CALLBACK
1131 static err_t
netifapi_do_netif_add_ext_callback(struct tcpip_api_call_data * m)1132 netifapi_do_netif_add_ext_callback(struct tcpip_api_call_data *m)
1133 {
1134   /* cast through void* to silence alignment warnings.
1135    * We know it works because the structs have been instantiated as struct netifapi_msg */
1136   struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m;
1137   /* avoid adding duplicate cb, otherwise the linklist may form a circle */
1138   netif_remove_ext_callback(msg->msg.netif_ext_cb.cb);
1139   netif_add_ext_callback(msg->msg.netif_ext_cb.cb, msg->msg.netif_ext_cb.fn);
1140   return ERR_OK;
1141 }
1142 
1143 err_t
netifapi_netif_add_ext_callback(netif_ext_callback_t * callback,netif_ext_callback_fn fn)1144 netifapi_netif_add_ext_callback(netif_ext_callback_t *callback, netif_ext_callback_fn fn)
1145 {
1146   err_t err;
1147   NETIFAPI_VAR_DECLARE(msg);
1148   LWIP_ERROR("netifapi_netif_add_ext_callback : invalid arguments", (callback != NULL), return ERR_VAL);
1149   LWIP_ERROR("netifapi_netif_add_ext_callback : invalid arguments", (fn != NULL), return ERR_VAL);
1150   NETIFAPI_VAR_ALLOC(msg);
1151   NETIFAPI_VAR_REF(msg).msg.netif_ext_cb.cb = callback;
1152   NETIFAPI_VAR_REF(msg).msg.netif_ext_cb.fn = fn;
1153   err = tcpip_api_call(netifapi_do_netif_add_ext_callback, &API_VAR_REF(msg).call);
1154   NETIFAPI_VAR_FREE(msg);
1155   return err;
1156 }
1157 
1158 static err_t
netifapi_do_netif_remove_ext_callback(struct tcpip_api_call_data * m)1159 netifapi_do_netif_remove_ext_callback(struct tcpip_api_call_data *m)
1160 {
1161   /* cast through void* to silence alignment warnings.
1162    * We know it works because the structs have been instantiated as struct netifapi_msg */
1163   struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m;
1164   netif_remove_ext_callback(msg->msg.netif_ext_cb.cb);
1165   return ERR_OK;
1166 }
1167 
1168 err_t
netifapi_netif_remove_ext_callback(netif_ext_callback_t * callback)1169 netifapi_netif_remove_ext_callback(netif_ext_callback_t *callback)
1170 {
1171   err_t err;
1172   NETIFAPI_VAR_DECLARE(msg);
1173   LWIP_ERROR("netifapi_netif_remove_ext_callback : invalid arguments", (callback != NULL), return ERR_VAL);
1174   NETIFAPI_VAR_ALLOC(msg);
1175   NETIFAPI_VAR_REF(msg).msg.netif_ext_cb.cb = callback;
1176   err = tcpip_api_call(netifapi_do_netif_remove_ext_callback, &API_VAR_REF(msg).call);
1177   NETIFAPI_VAR_FREE(msg);
1178   return err;
1179 }
1180 #endif /* LWIP_NETIF_EXT_STATUS_CALLBACK */
1181 
1182 static err_t
netifapi_do_netif_set_mtu(struct tcpip_api_call_data * m)1183 netifapi_do_netif_set_mtu(struct tcpip_api_call_data *m)
1184 {
1185   /* cast through void* to silence alignment warnings.
1186    * We know it works because the structs have been instantiated as struct netifapi_msg */
1187   err_t ret;
1188   struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
1189   ret = netif_set_mtu(msg->netif, msg->msg.netif_mtu.mtu);
1190   return ret;
1191 }
1192 
1193 err_t
netifapi_netif_set_mtu(struct netif * netif,u16_t mtu)1194 netifapi_netif_set_mtu(struct netif *netif, u16_t mtu)
1195 {
1196   err_t err;
1197   NETIFAPI_VAR_DECLARE(msg);
1198 
1199   LWIP_ERROR("netifapi_netif_set_mtu : invalid arguments", (netif != NULL), return ERR_VAL);
1200   NETIFAPI_VAR_ALLOC(msg);
1201 
1202   NETIFAPI_VAR_REF(msg).netif = netif;
1203   NETIFAPI_VAR_REF(msg).msg.netif_mtu.mtu = mtu;
1204   err = tcpip_api_call(netifapi_do_netif_set_mtu, &API_VAR_REF(msg).call);
1205   NETIFAPI_VAR_FREE(msg);
1206   return err;
1207 }
1208 
1209 #if LWIP_DHCPS
1210 static err_t
netifapi_do_dhcps_start(struct tcpip_api_call_data * m)1211 netifapi_do_dhcps_start(struct tcpip_api_call_data *m)
1212 {
1213   /* cast through void* to silence alignment warnings.
1214    * We know it works because the structs have been instantiated as struct netifapi_msg */
1215   err_t ret;
1216   struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
1217   ret = dhcps_start(msg->netif, msg->msg.dhcp_start_params.start_ip, msg->msg.dhcp_start_params.ip_num);
1218   return ret;
1219 }
1220 
1221 err_t
netifapi_dhcps_start(struct netif * netif,char * start_ip,u16_t ip_num)1222 netifapi_dhcps_start(struct netif *netif, char *start_ip, u16_t ip_num)
1223 {
1224   err_t err;
1225   NETIFAPI_VAR_DECLARE(msg);
1226 
1227   LWIP_ERROR("netifapi_dhcps_start : invalid arguments", (netif != NULL), return ERR_VAL);
1228   NETIFAPI_VAR_ALLOC(msg);
1229 
1230   NETIFAPI_VAR_REF(msg).netif = netif;
1231   NETIFAPI_VAR_REF(msg).msg.dhcp_start_params.start_ip = start_ip;
1232   NETIFAPI_VAR_REF(msg).msg.dhcp_start_params.ip_num = ip_num;
1233 
1234   err = tcpip_api_call(netifapi_do_dhcps_start, &API_VAR_REF(msg).call);
1235 
1236   NETIFAPI_VAR_FREE(msg);
1237   return err;
1238 }
1239 
1240 err_t
netifapi_dhcps_stop(struct netif * netif)1241 netifapi_dhcps_stop(struct netif *netif)
1242 {
1243   LWIP_ERROR("netifapi_dhcps_stop : invalid arguments", (netif != NULL), return ERR_VAL);
1244 
1245   return netifapi_netif_common(netif, dhcps_stop, NULL);
1246 }
1247 
1248 static err_t
netifapi_do_dhcps_get_client_ip(struct tcpip_api_call_data * m)1249 netifapi_do_dhcps_get_client_ip(struct tcpip_api_call_data *m)
1250 {
1251   /*
1252    * cast through void* to silence alignment warnings.
1253    * We know it works because the structs have been instantiated as struct netifapi_msg
1254    */
1255   err_t ret;
1256   struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m;
1257   ret = dhcps_find_client_lease(msg->netif, msg->msg.dhcp_get_ip_params.mac,
1258                                 msg->msg.dhcp_get_ip_params.maclen, msg->msg.dhcp_get_ip_params.ip);
1259   return ret;
1260 }
1261 
1262 err_t
netifapi_dhcps_get_client_ip(struct netif * netif,u8_t * mac,u8_t maclen,ip_addr_t * ip)1263 netifapi_dhcps_get_client_ip(struct netif *netif, u8_t *mac, u8_t maclen, ip_addr_t *ip)
1264 {
1265   err_t err;
1266   NETIFAPI_VAR_DECLARE(msg);
1267 
1268   LWIP_ERROR("netifapi_dhcps_get_client_ip : invalid arguments", (netif != NULL), return ERR_VAL);
1269   NETIFAPI_VAR_ALLOC(msg);
1270 
1271   NETIFAPI_VAR_REF(msg).netif = netif;
1272   NETIFAPI_VAR_REF(msg).msg.dhcp_get_ip_params.mac = mac;
1273   NETIFAPI_VAR_REF(msg).msg.dhcp_get_ip_params.maclen = maclen;
1274   NETIFAPI_VAR_REF(msg).msg.dhcp_get_ip_params.ip = ip;
1275 
1276   err = tcpip_api_call(netifapi_do_dhcps_get_client_ip, &API_VAR_REF(msg).call);
1277 
1278   NETIFAPI_VAR_FREE(msg);
1279   return err;
1280 }
1281 #endif /* LWIP_DHCPS */
1282 
1283 #if LWIP_AUTOIP
1284 /*
1285  * Call autoip_start() in a thread-safe way by running that function inside the
1286  * tcpip_thread context.
1287  *
1288  * @note use only for functions where there is only "netif" parameter.
1289  */
1290 err_t
netifapi_autoip_start(struct netif * netif)1291 netifapi_autoip_start(struct netif *netif)
1292 {
1293   return netifapi_netif_common(netif, NULL, autoip_start);
1294 }
1295 
1296 /*
1297  * Call autoip_stop() in a thread-safe way by running that function inside the
1298  * tcpip_thread context.
1299  *
1300  * @note use only for functions where there is only "netif" parameter.
1301  */
1302 err_t
netifapi_autoip_stop(struct netif * netif)1303 netifapi_autoip_stop(struct netif *netif)
1304 {
1305   return netifapi_netif_common(netif, NULL, autoip_stop);
1306 }
1307 #endif /* LWIP_AUTOIP */
1308 
1309 #if LWIP_IPV6_DHCP6
1310 err_t
netifapi_dhcp6_enable_stateful(struct netif * netif)1311 netifapi_dhcp6_enable_stateful(struct netif *netif)
1312 {
1313   LWIP_ERROR("netifapi_dhcp6_enable_stateful : netif == NULL", ((netif != NULL)), return ERR_VAL);
1314   return netifapi_netif_common(netif, NULL, dhcp6_enable_stateful);
1315 }
1316 
1317 err_t
netifapi_dhcp6_enable_stateless(struct netif * netif)1318 netifapi_dhcp6_enable_stateless(struct netif *netif)
1319 {
1320   LWIP_ERROR("netifapi_dhcp6_enable_stateless : netif == NULL", ((netif != NULL)), return ERR_VAL);
1321   return netifapi_netif_common(netif, NULL, dhcp6_enable_stateless);
1322 }
1323 
1324 err_t
netifapi_dhcp6_disable(struct netif * netif)1325 netifapi_dhcp6_disable(struct netif *netif)
1326 {
1327   LWIP_ERROR("netifapi_dhcp6_disable : netif == NULL", ((netif != NULL)), return ERR_VAL);
1328   return netifapi_netif_common(netif, dhcp6_disable, NULL);
1329 }
1330 
1331 err_t
netifapi_dhcp6_release_stateful(struct netif * netif)1332 netifapi_dhcp6_release_stateful(struct netif *netif)
1333 {
1334   LWIP_ERROR("netifapi_dhcp6_release_stateful : netif == NULL", ((netif != NULL)), return ERR_VAL);
1335   return netifapi_netif_common(netif, NULL, dhcp6_release_stateful);
1336 }
1337 
1338 err_t
netifapi_dhcp6_cleanup(struct netif * netif)1339 netifapi_dhcp6_cleanup(struct netif *netif)
1340 {
1341   LWIP_ERROR("netifapi_dhcp6_cleanup : netif == NULL", ((netif != NULL)), return ERR_VAL);
1342   return netifapi_netif_common(netif, dhcp6_cleanup, NULL);
1343 }
1344 #endif /* LWIP_IPV6_DHCP6 */
1345 
1346 /**
1347 * @ingroup netifapi_netif
1348 * Call netif_name_to_index() in a thread-safe way by running that function inside the
1349 * tcpip_thread context.
1350 *
1351 * @param name the interface name of the netif
1352 * @param idx output index of the found netif
1353 */
1354 err_t
netifapi_netif_name_to_index(const char * name,u8_t * idx)1355 netifapi_netif_name_to_index(const char *name, u8_t *idx)
1356 {
1357 #if LWIP_MPU_COMPATIBLE
1358   size_t namelen;
1359 #endif
1360   err_t err;
1361   NETIFAPI_VAR_DECLARE(msg);
1362   NETIFAPI_VAR_ALLOC(msg);
1363   if ((name == NULL) || (idx == NULL)) {
1364     return ERR_ARG;
1365   }
1366   *idx = 0;
1367 
1368 #if LWIP_MPU_COMPATIBLE
1369   namelen = strlen(name);
1370   if (namelen <= (NETIF_NAMESIZE - 1)) {
1371     (void)strncpy_s(NETIFAPI_VAR_REF(msg).msg.ifs.name, NETIF_NAMESIZE, name, namelen);
1372     NETIFAPI_VAR_REF(msg).msg.ifs.name[namelen] = '\0';
1373   } else {
1374     return ERR_ARG;
1375   }
1376 #else
1377   NETIFAPI_VAR_REF(msg).msg.ifs.name = LWIP_CONST_CAST(char *, name);
1378 #endif /* LWIP_MPU_COMPATIBLE */
1379   err = tcpip_api_call(netifapi_do_name_to_index, &API_VAR_REF(msg).call);
1380   if (!err) {
1381     *idx = NETIFAPI_VAR_REF(msg).msg.ifs.index;
1382   }
1383   NETIFAPI_VAR_FREE(msg);
1384   return err;
1385 }
1386 
1387 /**
1388 * @ingroup netifapi_netif
1389 * Call netif_index_to_name() in a thread-safe way by running that function inside the
1390 * tcpip_thread context.
1391 *
1392 * @param idx the interface index of the netif
1393 * @param name output name of the found netif, empty '\0' string if netif not found.
1394 *             name should be of at least NETIF_NAMESIZE bytes
1395 */
1396 err_t
netifapi_netif_index_to_name(u8_t idx,char * name)1397 netifapi_netif_index_to_name(u8_t idx, char *name)
1398 {
1399   err_t err;
1400   NETIFAPI_VAR_DECLARE(msg);
1401   NETIFAPI_VAR_ALLOC(msg);
1402 
1403   if (name == NULL) {
1404     return ERR_ARG;
1405   }
1406   NETIFAPI_VAR_REF(msg).msg.ifs.index = idx;
1407 #if !LWIP_MPU_COMPATIBLE
1408   NETIFAPI_VAR_REF(msg).msg.ifs.name = name;
1409 #endif /* LWIP_MPU_COMPATIBLE */
1410   err = tcpip_api_call(netifapi_do_index_to_name, &API_VAR_REF(msg).call);
1411 #if LWIP_MPU_COMPATIBLE
1412   if (!err) {
1413     /* here stack is assuming that the input buffer is of minimum size NETIF_NAMESIZE.
1414         This is a limitation of the API */
1415     (void)strncpy_s(name, NETIF_NAMESIZE,
1416                     NETIFAPI_VAR_REF(msg).msg.ifs.name, strlen(NETIFAPI_VAR_REF(msg).msg.ifs.name));
1417     name[strlen(NETIFAPI_VAR_REF(msg).msg.ifs.name)] = '\0';
1418   }
1419 #endif /* LWIP_MPU_COMPATIBLE */
1420   NETIFAPI_VAR_FREE(msg);
1421   return err;
1422 }
1423 
1424 /*
1425 * Call netif_get_nameindex_all() inside the tcpip_thread context.
1426 */
1427 static err_t
netifapi_netif_get_nameindex_all(struct tcpip_api_call_data * m)1428 netifapi_netif_get_nameindex_all(struct tcpip_api_call_data *m)
1429 {
1430   err_t err;
1431   struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
1432   err = netif_get_nameindex_all((void *)(&msg->msg.if_list));
1433   return err;
1434 }
1435 
1436 /*
1437 * @ingroup netifapi_netif
1438 * Call netifapi_netif_get_nameindex_all() in a thread-safe way by running that function inside the
1439 * tcpip_thread context.
1440 *
1441 * @param ppIfLst , the pointer to all the interface list in name index format,if_nameindex structure.
1442 *
1443 */
netifapi_netif_nameindex_all(void * arg)1444 err_t netifapi_netif_nameindex_all(void *arg)
1445 {
1446   err_t err;
1447   struct if_nameindex **tmp_iflist = (struct if_nameindex **)arg;
1448   NETIFAPI_VAR_DECLARE(msg);
1449   NETIFAPI_VAR_ALLOC(msg);
1450 
1451   if (tmp_iflist == NULL) {
1452     return ERR_ARG;
1453   }
1454 
1455   err = tcpip_api_call(netifapi_netif_get_nameindex_all, &API_VAR_REF(msg).call);
1456   *tmp_iflist = NETIFAPI_VAR_REF(msg).msg.if_list;
1457 
1458   NETIFAPI_VAR_FREE(msg);
1459   return err;
1460 }
1461 
1462 #if LWIP_NETIF_HOSTNAME
1463 static err_t
do_netifapi_set_hostname(struct tcpip_api_call_data * m)1464 do_netifapi_set_hostname(struct tcpip_api_call_data *m)
1465 {
1466   /* cast through void* to silence alignment warnings.
1467    * We know it works because the structs have been instantiated as struct netifapi_msg */
1468   struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
1469 
1470   if (strncpy_s(msg->netif->hostname, NETIF_HOSTNAME_MAX_LEN,
1471                 msg->msg.hostname.name, NETIF_HOSTNAME_MAX_LEN - 1) == EOK) {
1472     if (msg->msg.hostname.namelen < (NETIF_HOSTNAME_MAX_LEN - 1)) {
1473       msg->netif->hostname[msg->msg.hostname.namelen] = '\0';
1474     } else {
1475       msg->netif->hostname[NETIF_HOSTNAME_MAX_LEN - 1] = '\0';
1476     }
1477     return ERR_OK;
1478   }
1479   return ERR_VAL;
1480 }
1481 
1482 err_t
netifapi_set_hostname(struct netif * netif,char * hostname,u8_t namelen)1483 netifapi_set_hostname(struct netif *netif, char *hostname, u8_t namelen)
1484 {
1485   err_t err;
1486   NETIFAPI_VAR_DECLARE(msg);
1487 
1488   LWIP_ERROR("netifapi_set_hostname:netif is NULL", (netif != NULL), return ERR_ARG);
1489   LWIP_ERROR("netifapi_set_hostname:hostname is NULL", (hostname != NULL), return ERR_ARG);
1490 
1491   NETIFAPI_VAR_ALLOC(msg);
1492 
1493   NETIFAPI_VAR_REF(msg).netif = netif;
1494   NETIFAPI_VAR_REF(msg).msg.hostname.name  = hostname;
1495   NETIFAPI_VAR_REF(msg).msg.hostname.namelen = namelen;
1496 
1497   err = tcpip_api_call(do_netifapi_set_hostname, &API_VAR_REF(msg).call);
1498   NETIFAPI_VAR_FREE(msg);
1499   return err;
1500 }
1501 
1502 static err_t
do_netifapi_get_hostname(struct tcpip_api_call_data * m)1503 do_netifapi_get_hostname(struct tcpip_api_call_data *m)
1504 {
1505   /* cast through void* to silence alignment warnings.
1506    * We know it works because the structs have been instantiated as struct netifapi_msg */
1507   struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
1508 
1509   if (strncpy_s(msg->msg.hostname.name, msg->msg.hostname.namelen,
1510                 msg->netif->hostname, (size_t)(msg->msg.hostname.namelen - 1)) == 0) {
1511     msg->msg.hostname.name[msg->msg.hostname.namelen - 1] = '\0';
1512     return ERR_OK;
1513   }
1514   return ERR_VAL;
1515 }
1516 
1517 err_t
netifapi_get_hostname(struct netif * netif,char * hostname,u8_t namelen)1518 netifapi_get_hostname(struct netif *netif, char *hostname, u8_t namelen)
1519 {
1520   err_t err;
1521   NETIFAPI_VAR_DECLARE(msg);
1522 
1523   LWIP_ERROR("netifapi_get_hostname:netif is NULL", (netif != NULL), return ERR_ARG);
1524   LWIP_ERROR("netifapi_get_hostname:hostname is NULL", (hostname != NULL), return ERR_ARG);
1525 
1526   NETIFAPI_VAR_ALLOC(msg);
1527 
1528   NETIFAPI_VAR_REF(msg).netif = netif;
1529   NETIFAPI_VAR_REF(msg).msg.hostname.name  = hostname;
1530   NETIFAPI_VAR_REF(msg).msg.hostname.namelen = namelen;
1531 
1532   err = tcpip_api_call(do_netifapi_get_hostname, &API_VAR_REF(msg).call);
1533   NETIFAPI_VAR_FREE(msg);
1534   return err;
1535 }
1536 
1537 #endif /* LWIP_NETIF_HOSTNAME */
1538 
1539 #if LWIP_DHCP_VENDOR_CLASS_IDENTIFIER
1540 static err_t
do_netifapi_set_vci(struct tcpip_api_call_data * m)1541 do_netifapi_set_vci(struct tcpip_api_call_data *m)
1542 {
1543   err_t ret;
1544   struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
1545   ret = dhcp_set_vci(msg->msg.vci.vci, *(msg->msg.vci.vci_len));
1546   return ret;
1547 }
1548 
1549 err_t
netifapi_set_vci(char * vci,u8_t vci_len)1550 netifapi_set_vci(char *vci, u8_t vci_len)
1551 {
1552   err_t err;
1553   NETIFAPI_VAR_DECLARE(msg);
1554 
1555   LWIP_ERROR("netifapi_set_vci:vci is NULL", (vci != NULL), return ERR_ARG);
1556   LWIP_ERROR("netifapi_set_vci:vci_len > DHCP_VCI_MAX_LEN", (vci_len <= DHCP_VCI_MAX_LEN), return ERR_ARG);
1557 
1558   NETIFAPI_VAR_ALLOC(msg);
1559 
1560   NETIFAPI_VAR_REF(msg).netif = NULL;
1561   NETIFAPI_VAR_REF(msg).msg.vci.vci = vci;
1562   NETIFAPI_VAR_REF(msg).msg.vci.vci_len = &vci_len;
1563 
1564   err = tcpip_api_call(do_netifapi_set_vci, &API_VAR_REF(msg).call);
1565 
1566   NETIFAPI_VAR_FREE(msg);
1567   return err;
1568 }
1569 
1570 static err_t
do_netifapi_get_vci(struct tcpip_api_call_data * m)1571 do_netifapi_get_vci(struct tcpip_api_call_data *m)
1572 {
1573   err_t ret;
1574   struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
1575   ret = dhcp_get_vci(msg->msg.vci.vci, msg->msg.vci.vci_len);
1576   return ret;
1577 }
1578 
1579 err_t
netifapi_get_vci(char * vci,u8_t * vci_len)1580 netifapi_get_vci(char *vci, u8_t *vci_len)
1581 {
1582   err_t err;
1583   NETIFAPI_VAR_DECLARE(msg);
1584 
1585   LWIP_ERROR("netifapi_get_vci:vci is NULL", (vci != NULL), return ERR_ARG);
1586   LWIP_ERROR("netifapi_get_vci:vci_len is NULL", (vci_len != NULL), return ERR_ARG);
1587   LWIP_ERROR("netifapi_get_vci:*vci_len < DHCP_VCI_MAX_LEN", (*vci_len >= DHCP_VCI_MAX_LEN), return ERR_ARG);
1588 
1589   NETIFAPI_VAR_ALLOC(msg);
1590 
1591   NETIFAPI_VAR_REF(msg).netif = NULL;
1592   NETIFAPI_VAR_REF(msg).msg.vci.vci = vci;
1593   NETIFAPI_VAR_REF(msg).msg.vci.vci_len = vci_len;
1594 
1595   err = tcpip_api_call(do_netifapi_get_vci, &API_VAR_REF(msg).call);
1596 
1597   NETIFAPI_VAR_FREE(msg);
1598   return err;
1599 }
1600 #endif /* LWIP_DHCP_VENDOR_CLASS_IDENTIFIER */
1601 
1602 #if LWIP_IP_FILTER || LWIP_IPV6_FILTER
1603 static err_t
do_netifapi_set_ip_filter(struct tcpip_api_call_data * m)1604 do_netifapi_set_ip_filter(struct tcpip_api_call_data *m)
1605 {
1606   err_t ret = ERR_VAL;
1607   struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m;
1608 #if LWIP_IP_FILTER
1609   if (msg->msg.ip_filter.type == IPADDR_TYPE_V4) {
1610     ret = set_ip4_filter(msg->msg.ip_filter.filter_fn);
1611   }
1612 #endif /* LWIP_IP_FILTER */
1613 #if LWIP_IPV6_FILTER
1614   if (msg->msg.ip_filter.type == IPADDR_TYPE_V6) {
1615     ret = set_ip6_filter(msg->msg.ip_filter.filter_fn);
1616   }
1617 #endif /* LWIP_IPV6_FILTER */
1618   return ret;
1619 }
1620 
1621 /*
1622  * Set ip filter_fn, the filter_fn will be called when pass a packet to ip_input.
1623  *
1624  * @param filter_fn The filter implement function, NULL indicate disable the filter.
1625  * @return
1626  *  - ERR_OK: On success
1627  *  - ERR_VAL: On failure due to Illegal value
1628  */
1629 err_t
netifapi_set_ip_filter(ip_filter_fn filter_fn,int type)1630 netifapi_set_ip_filter(ip_filter_fn filter_fn, int type)
1631 {
1632   err_t err;
1633   NETIFAPI_VAR_DECLARE(msg);
1634 
1635   NETIFAPI_VAR_ALLOC(msg);
1636   (void)memset_s(&msg, sizeof(struct netifapi_msg), 0, sizeof(struct netifapi_msg));
1637 
1638   NETIFAPI_VAR_REF(msg).msg.ip_filter.filter_fn = filter_fn;
1639   NETIFAPI_VAR_REF(msg).msg.ip_filter.type      = type;
1640 
1641   err = tcpip_api_call(do_netifapi_set_ip_filter, &API_VAR_REF(msg).call);
1642   NETIFAPI_VAR_FREE(msg);
1643   return err;
1644 }
1645 #endif /* LWIP_IP_FILTER || LWIP_IPV6_FILTER */
1646 
1647 #if LWIP_IPV6
1648 #if LWIP_ND6_ROUTER
1649 static err_t
netifapi_do_set_ra_enable(struct tcpip_api_call_data * m)1650 netifapi_do_set_ra_enable(struct tcpip_api_call_data *m)
1651 {
1652   struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m;
1653   struct netif *nif = msg->netif;
1654   u8_t ra_enable = msg->msg.ip6_state.state;
1655 
1656   nif->ra_enable = (ra_enable > 0) ? lwIP_TRUE : lwIP_FALSE;
1657   return ERR_OK;
1658 }
1659 
1660 err_t
netifapi_set_ra_enable(struct netif * netif,u8_t ra_enable)1661 netifapi_set_ra_enable(struct netif *netif, u8_t ra_enable)
1662 {
1663   err_t err;
1664   NETIFAPI_VAR_DECLARE(msg);
1665 
1666   LWIP_ERROR("netifapi_set_ipv6_forwarding : invalid arguments \n", (netif != NULL), return ERR_ARG);
1667 
1668   NETIFAPI_VAR_ALLOC(msg);
1669 
1670   NETIFAPI_VAR_REF(msg).netif = netif;
1671   NETIFAPI_VAR_REF(msg).msg.ip6_state.state = ra_enable;
1672 
1673   err = tcpip_api_call(netifapi_do_set_ra_enable, &API_VAR_REF(msg).call);
1674   NETIFAPI_VAR_FREE(msg);
1675   return err;
1676 }
1677 
1678 static err_t
netifapi_do_set_ipv6_forwarding(struct tcpip_api_call_data * m)1679 netifapi_do_set_ipv6_forwarding(struct tcpip_api_call_data *m)
1680 {
1681   struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m;
1682   struct netif *nif = msg->netif;
1683   u8_t forwarding = msg->msg.ip6_state.state;
1684 
1685   nif->forwarding = forwarding;
1686   return ERR_OK;
1687 }
1688 
1689 err_t
netifapi_set_ipv6_forwarding(struct netif * netif,u8_t forwarding)1690 netifapi_set_ipv6_forwarding(struct netif *netif, u8_t forwarding)
1691 {
1692   err_t err;
1693   NETIFAPI_VAR_DECLARE(msg);
1694 
1695   LWIP_ERROR("netifapi_set_ipv6_forwarding : invalid arguments \n", (netif != NULL), return ERR_ARG);
1696 
1697   NETIFAPI_VAR_ALLOC(msg);
1698 
1699   NETIFAPI_VAR_REF(msg).netif = netif;
1700   NETIFAPI_VAR_REF(msg).msg.ip6_state.state = forwarding;
1701 
1702   err = tcpip_api_call(netifapi_do_set_ipv6_forwarding, &API_VAR_REF(msg).call);
1703   NETIFAPI_VAR_FREE(msg);
1704   return err;
1705 }
1706 
1707 static err_t
netifapi_do_set_accept_ra(struct tcpip_api_call_data * m)1708 netifapi_do_set_accept_ra(struct tcpip_api_call_data *m)
1709 {
1710   struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m;
1711   struct netif *nif = msg->netif;
1712   u8_t accept_ra = msg->msg.ip6_state.state;
1713 
1714   nif->accept_ra = accept_ra;
1715   return ERR_OK;
1716 }
1717 
1718 err_t
netifapi_set_accept_ra(struct netif * netif,u8_t accept_ra)1719 netifapi_set_accept_ra(struct netif *netif, u8_t accept_ra)
1720 {
1721   err_t err;
1722   NETIFAPI_VAR_DECLARE(msg);
1723 
1724   LWIP_ERROR("netifapi_set_ipv6_forwarding : invalid arguments \n", (netif != NULL), return ERR_ARG);
1725 
1726   NETIFAPI_VAR_ALLOC(msg);
1727 
1728   NETIFAPI_VAR_REF(msg).netif = netif;
1729   NETIFAPI_VAR_REF(msg).msg.ip6_state.state = accept_ra;
1730 
1731   err = tcpip_api_call(netifapi_do_set_accept_ra, &API_VAR_REF(msg).call);
1732   NETIFAPI_VAR_FREE(msg);
1733   return err;
1734 }
1735 #endif /* LWIP_ND6_ROUTER */
1736 
1737 /*
1738  * These APIs will be responsible for adding , deleting and querying the
1739  * neighbor cache when IPv6 is enabled
1740  */
1741 #if LWIP_NETIF_NBR_CACHE_API
1742 static err_t
netifapi_do_add_ipv6_neighbor(struct tcpip_api_call_data * m)1743 netifapi_do_add_ipv6_neighbor(struct tcpip_api_call_data *m)
1744 {
1745   err_t err;
1746   struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m;
1747   struct ipv6_neighbor *nb = msg->msg.ipv6_tables_access_params.nbrinfo;
1748   struct nd6_neighbor_info nd6nbr;
1749 
1750   nd6nbr.curstate = nb->curstate;
1751   nd6nbr.hwlen = nb->hwlen;
1752   nd6nbr.reachabletime = nb->reachabletime;
1753 
1754   if (memcpy_s(nd6nbr.hwaddr, NETIF_MAX_HWADDR_LEN, nb->hwaddr, nb->hwlen) != EOK) {
1755     return ERR_MEM;
1756   }
1757   ip6_addr_set(&(nd6nbr.nbripaddr), &(nb->nbripaddr));
1758 
1759   err = nd6_add_neighbor_cache_entry_manually(msg->netif, &nd6nbr);
1760   return err;
1761 }
1762 
1763 static err_t
netifapi_do_del_ipv6_neighbor(struct tcpip_api_call_data * m)1764 netifapi_do_del_ipv6_neighbor(struct tcpip_api_call_data *m)
1765 {
1766   err_t err;
1767   struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m;
1768   struct ip6_addr *nbrip = msg->msg.ipv6_tables_access_params.nodeip;
1769 
1770   err = nd6_del_neighbor_cache_entry_manually(msg->netif, nbrip);
1771   return err;
1772 }
1773 
1774 static err_t
netifapi_do_query_ipv6_neighbor(struct tcpip_api_call_data * m)1775 netifapi_do_query_ipv6_neighbor(struct tcpip_api_call_data *m)
1776 {
1777   err_t err;
1778   struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m;
1779   struct ipv6_neighbor *nb = msg->msg.ipv6_tables_access_params.nbrinfo;
1780   struct ip6_addr *nbrip = msg->msg.ipv6_tables_access_params.nodeip;
1781 
1782   struct nd6_neighbor_info nd6nbr;
1783 
1784   err = nd6_get_neighbor_cache_info(msg->netif, nbrip, &nd6nbr);
1785   if (err == ERR_OK) {
1786     /* Copy the info */
1787     nb->curstate = nd6nbr.curstate;
1788     nb->hwlen = nd6nbr.hwlen;
1789     nb->reachabletime = nd6nbr.reachabletime;
1790 
1791     if (memcpy_s(nb->hwaddr, NETIF_MAX_HWADDR_LEN, nd6nbr.hwaddr, nd6nbr.hwlen) != EOK) {
1792       return ERR_MEM;
1793     }
1794     nb->hwlen = nd6nbr.hwlen;
1795 
1796     ip6_addr_set(&(nb->nbripaddr), &(nd6nbr.nbripaddr));
1797   }
1798 
1799   return err;
1800 }
1801 
1802 err_t
netifapi_add_ipv6_neighbor(struct netif * netif,struct ipv6_neighbor * nbr)1803 netifapi_add_ipv6_neighbor(struct netif *netif, struct ipv6_neighbor *nbr)
1804 {
1805   err_t err;
1806   NETIFAPI_VAR_DECLARE(msg);
1807 
1808   LWIP_ERROR("netifapi_add_ipv6_neighbor : invalid arguments \n", \
1809              ((netif != NULL) && (nbr != NULL)), return ERR_ARG);
1810 
1811   LWIP_ERROR("netifapi_add_ipv6_neighbor : MAC len is invalid \n", \
1812              ((nbr->hwlen <= NETIF_MAX_HWADDR_LEN)), return ERR_VAL);
1813 
1814   NETIFAPI_VAR_ALLOC(msg);
1815 
1816   if ((nbr->curstate != ND6_STATE_REACHABLE)
1817 #if LWIP_ND6_STATIC_NBR
1818       && (nbr->curstate != ND6_STATE_PERMANENT)
1819 #endif
1820      ) {
1821     LWIP_ERROR("netifapi_add_ipv6_neighbor : invalid sate \n", 0, return ERR_VAL);
1822   }
1823 
1824 #if LWIP_ND6_STATIC_NBR
1825   if ((nbr->curstate == ND6_STATE_PERMANENT) && (nbr->reachabletime != 0)) {
1826     LWIP_ERROR("netifapi_add_ipv6_neighbor : For static neighbors rechable time " \
1827                "must be set to 0 \n", 0, return ERR_VAL);
1828   }
1829 #endif
1830 
1831   if ((nbr->curstate == ND6_STATE_REACHABLE) &&
1832       (nbr->reachabletime > LWIP_ND6_REACHABLE_TIME)) {
1833     LWIP_DEBUGF(NETIF_DEBUG, ("netifapi: Trying to set the reachable time[%u] " \
1834                               "greater than configured[%d] after first expiry it will use the " \
1835                               "configured one\n", nbr->reachabletime, LWIP_ND6_REACHABLE_TIME));
1836   }
1837 
1838   (void)memset_s(&msg, sizeof(struct netifapi_msg), 0, sizeof(struct netifapi_msg));
1839   NETIFAPI_VAR_REF(msg).netif = netif;
1840   NETIFAPI_VAR_REF(msg).msg.ipv6_tables_access_params.nbrinfo = nbr;
1841 
1842   err = tcpip_api_call(netifapi_do_add_ipv6_neighbor, &API_VAR_REF(msg).call);
1843   NETIFAPI_VAR_FREE(msg);
1844   return err;
1845 
1846   /* Validate the input parameter */
1847 }
1848 
1849 err_t
netifapi_del_ipv6_neighbor(struct netif * netif,struct ip6_addr * ipaddr)1850 netifapi_del_ipv6_neighbor(struct netif *netif, struct ip6_addr *ipaddr)
1851 {
1852   err_t err;
1853   NETIFAPI_VAR_DECLARE(msg);
1854 
1855   LWIP_ERROR("netifapi_del_ipv6_neighbor : invalid arguments \n", \
1856              ((netif != NULL) && (ipaddr != NULL)), return ERR_ARG);
1857 
1858   NETIFAPI_VAR_ALLOC(msg);
1859 
1860   (void)memset_s(&msg, sizeof(struct netifapi_msg), 0, sizeof(struct netifapi_msg));
1861   NETIFAPI_VAR_REF(msg).netif = netif;
1862   NETIFAPI_VAR_REF(msg).msg.ipv6_tables_access_params.nodeip = ipaddr;
1863 
1864   err = tcpip_api_call(netifapi_do_del_ipv6_neighbor, &API_VAR_REF(msg).call);
1865   NETIFAPI_VAR_FREE(msg);
1866   return err;
1867 }
1868 
1869 err_t
netifapi_query_ipv6_neighbor(struct netif * netif,struct ip6_addr * ipaddr,struct ipv6_neighbor * nbrinfo)1870 netifapi_query_ipv6_neighbor(struct netif *netif, struct ip6_addr *ipaddr,
1871                              struct ipv6_neighbor *nbrinfo)
1872 {
1873   err_t err;
1874   NETIFAPI_VAR_DECLARE(msg);
1875 
1876   LWIP_ERROR("netifapi_del_ipv6_neighbor : invalid arguments \n", \
1877              ((netif != NULL) && (ipaddr != NULL) && (nbrinfo != NULL)), return ERR_ARG);
1878 
1879   NETIFAPI_VAR_ALLOC(msg);
1880 
1881   (void)memset_s(&msg, sizeof(struct netifapi_msg), 0, sizeof(struct netifapi_msg));
1882   NETIFAPI_VAR_REF(msg).netif = netif;
1883   NETIFAPI_VAR_REF(msg).msg.ipv6_tables_access_params.nodeip = ipaddr;
1884   NETIFAPI_VAR_REF(msg).msg.ipv6_tables_access_params.nbrinfo = nbrinfo;
1885 
1886   err = tcpip_api_call(netifapi_do_query_ipv6_neighbor, &API_VAR_REF(msg).call);
1887   NETIFAPI_VAR_FREE(msg);
1888   return err;
1889 }
1890 #endif /* LWIP_NETIF_NBR_CACHE_API */
1891 #endif /* LWIP_IPV6 */
1892 
1893 #if LWIP_LOWPOWER
1894 static err_t
netifapi_do_set_lowpower_mod(struct tcpip_api_call_data * m)1895 netifapi_do_set_lowpower_mod(struct tcpip_api_call_data *m)
1896 {
1897   struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m;
1898   enum lowpower_mod mod = msg->msg.lp.mod;
1899   set_lowpower_mod(mod);
1900   return ERR_OK;
1901 }
1902 
1903 err_t
netifapi_enable_lowpower(void)1904 netifapi_enable_lowpower(void)
1905 {
1906   err_t err;
1907   NETIFAPI_VAR_DECLARE(msg);
1908 
1909   NETIFAPI_VAR_ALLOC(msg);
1910 
1911   NETIFAPI_VAR_REF(msg).msg.lp.mod = LOW_TMR_LOWPOWER_MOD;
1912 
1913   err = tcpip_api_call(netifapi_do_set_lowpower_mod, &API_VAR_REF(msg).call);
1914   NETIFAPI_VAR_FREE(msg);
1915   return err;
1916 }
1917 
1918 err_t
netifapi_disable_lowpower(void)1919 netifapi_disable_lowpower(void)
1920 {
1921   err_t err;
1922   NETIFAPI_VAR_DECLARE(msg);
1923 
1924   NETIFAPI_VAR_ALLOC(msg);
1925 
1926   NETIFAPI_VAR_REF(msg).msg.lp.mod = LOW_TMR_NORMAL_MOD;
1927 
1928   err = tcpip_api_call(netifapi_do_set_lowpower_mod, &API_VAR_REF(msg).call);
1929   NETIFAPI_VAR_FREE(msg);
1930   return err;
1931 }
1932 #endif /* LWIP_LOWPOWER */
1933 
1934 #endif /* LWIP_NETIF_API */
1935