• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * @file
3  * lwIP network interface abstraction
4  *
5  * @defgroup netif Network interface (NETIF)
6  * @ingroup callbackstyle_api
7  *
8  * @defgroup netif_ip4 IPv4 address handling
9  * @ingroup netif
10  *
11  * @defgroup netif_ip6 IPv6 address handling
12  * @ingroup netif
13  *
14  * @defgroup netif_cd Client data handling
15  * Store data (void*) on a netif for application usage.
16  * @see @ref LWIP_NUM_NETIF_CLIENT_DATA
17  * @ingroup netif
18  */
19 
20 /*
21  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
22  * All rights reserved.
23  *
24  * Redistribution and use in source and binary forms, with or without modification,
25  * are permitted provided that the following conditions are met:
26  *
27  * 1. Redistributions of source code must retain the above copyright notice,
28  *    this list of conditions and the following disclaimer.
29  * 2. Redistributions in binary form must reproduce the above copyright notice,
30  *    this list of conditions and the following disclaimer in the documentation
31  *    and/or other materials provided with the distribution.
32  * 3. The name of the author may not be used to endorse or promote products
33  *    derived from this software without specific prior written permission.
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
37  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
38  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
39  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
40  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
41  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
42  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
43  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
44  * OF SUCH DAMAGE.
45  *
46  * This file is part of the lwIP TCP/IP stack.
47  *
48  * Author: Adam Dunkels <adam@sics.se>
49  */
50 
51 #include "lwip/opt.h"
52 
53 #include <string.h> /* memset */
54 #include <stdlib.h> /* atoi */
55 
56 #include "lwip/def.h"
57 #include "lwip/ip_addr.h"
58 #include "lwip/ip6_addr.h"
59 #include "lwip/netif.h"
60 #include "lwip/priv/tcp_priv.h"
61 #include "lwip/udp.h"
62 #include "lwip/priv/raw_priv.h"
63 #include "lwip/priv/tcp_priv.h"
64 #include "lwip/snmp.h"
65 #include "lwip/igmp.h"
66 #include "lwip/etharp.h"
67 #include "lwip/stats.h"
68 #include "lwip/sys.h"
69 #include "lwip/ip.h"
70 #include "lwip/if_api.h"
71 #if ENABLE_LOOPBACK
72 #if LWIP_NETIF_LOOPBACK_MULTITHREADING
73 #include "lwip/tcpip.h"
74 #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
75 #endif /* ENABLE_LOOPBACK */
76 
77 #include "netif/ethernet.h"
78 
79 #if LWIP_NETIF_PROMISC
80 #include "netif/ifaddrs.h"
81 #include "lwip/raw.h"
82 #endif
83 
84 #if LWIP_AUTOIP
85 #include "lwip/autoip.h"
86 #endif /* LWIP_AUTOIP */
87 #if LWIP_DHCP
88 #include "lwip/dhcp.h"
89 #endif /* LWIP_DHCP */
90 #if LWIP_IPV6_DHCP6
91 #include "lwip/dhcp6.h"
92 #endif /* LWIP_IPV6_DHCP6 */
93 #if LWIP_IPV6_MLD
94 #include "lwip/mld6.h"
95 #endif /* LWIP_IPV6_MLD */
96 #if LWIP_IPV6
97 #include "lwip/nd6.h"
98 #include "lwip/ethip6.h"
99 #endif
100 #include "netif/driverif.h"
101 
102 #if LWIP_NAT64
103 #include "lwip/nat64.h"
104 #endif
105 
106 #if LWIP_IP6IN4
107 #include "lwip/ip6in4.h"
108 #endif
109 
110 #if LWIP_MDNS_RESPONDER
111 #include "lwip/mdns.h"
112 #endif
113 
114 #include "lwip/tcpip.h"
115 
116 #if LWIP_TCP
117 #include "lwip/priv/tcpip_priv.h"
118 #endif
119 #include "lwip/lwip_rpl.h"
120 #include "lwip/priv/api_msg.h"
121 
122 /* Interface indexes always start at 1 per RFC 3493, section 4, num starts at 0 .. 8 for padding */
123 #define IF_NAMEINDEX_ELE_SIZE    (sizeof(struct if_nameindex) + NETIF_NAMESIZE + 4)
124 
125 #if LWIP_NETIF_STATUS_CALLBACK
126 #define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0)
127 #else
128 #define NETIF_STATUS_CALLBACK(n)
129 #endif /* LWIP_NETIF_STATUS_CALLBACK */
130 #if LWIP_L2_NETDEV_STATUS_CALLBACK
131 #define L2_NETDEV_STATUS_CALLBACK(n) \
132   do { if (n->l2_netdev_status_callback) { (n->l2_netdev_status_callback)(n); }} while (0)
133 #else
134 #define L2_NETDEV_STATUS_CALLBACK(n)
135 #endif /* LWIP_NETIF_STATUS_CALLBACK */
136 
137 #if LWIP_NETIF_LINK_CALLBACK
138 #define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0)
139 #else
140 #define NETIF_LINK_CALLBACK(n)
141 #endif /* LWIP_NETIF_LINK_CALLBACK */
142 
143 #if LWIP_NETIF_EXT_STATUS_CALLBACK
144 static netif_ext_callback_t *ext_callback;
145 #endif
146 
147 #if !LWIP_SINGLE_NETIF
148 struct netif *netif_list;
149 #endif /* !LWIP_SINGLE_NETIF */
150 struct netif *netif_default;
151 
152 #if PF_PKT_SUPPORT
153 extern struct raw_pcb *pkt_raw_pcbs;
154 #endif
155 
156 #if LWIP_NUM_NETIF_CLIENT_DATA > 0
157 static u8_t netif_client_id;
158 #endif
159 
160 #define NETIF_REPORT_TYPE_IPV4  0x01
161 #define NETIF_REPORT_TYPE_IPV6  0x02
162 static void netif_issue_reports(struct netif *netif, u8_t report_type, s8_t addr_idx);
163 
164 #if LWIP_HAVE_LOOPIF
165 #if LWIP_IPV4
166 static err_t netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr);
167 #endif
168 #if LWIP_IPV6
169 static err_t netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr);
170 #endif
171 
172 
173 static struct netif loop_netif;
174 
175 /**
176  * open or close netdev by netif without block as not using mutex
177  * the api only called by AT command ifconfig up/down
178  * @param netif the lwip network interface structure
179  * @return ERR_OK callback is ok
180  *         ERR_VAL netif is NULL
181  */
182 #if LWIP_L2_NETDEV_STATUS_CALLBACK
183 u8_t
netif_l2_netdev_status_callback(struct netif * nif)184 netif_l2_netdev_status_callback(struct netif *nif)
185 {
186   if (nif == NULL) {
187     return ERR_VAL;
188   }
189   L2_NETDEV_STATUS_CALLBACK(nif);
190   return ERR_OK;
191 }
192 #endif
193 
194 /**
195  * Initialize a lwip network interface structure for a loopback interface
196  *
197  * @param netif the lwip network interface structure for this loopif
198  * @return ERR_OK if the loopif is initialized
199  *         ERR_MEM if private data couldn't be allocated
200  */
201 static err_t
netif_loopif_init(struct netif * netif)202 netif_loopif_init(struct netif *netif)
203 {
204   LWIP_ASSERT("netif_loopif_init: invalid netif", netif != NULL);
205 
206   /* initialize the snmp variables and counters inside the struct netif
207    * ifSpeed: no assumption can be made!
208    */
209   MIB2_INIT_NETIF(netif, snmp_ifType_softwareLoopback, 0);
210 
211   netif->name[0] = 'l';
212   netif->name[1] = 'o';
213   netif->name[2] = '\0';
214   netif->link_layer_type = LOOPBACK_IF;
215   netif->mtu = NETIF_LOOPBACK_MTU;
216 #if LWIP_IPV4
217   netif->output = netif_loop_output_ipv4;
218 #endif
219 #if LWIP_IPV6
220   netif->output_ip6 = netif_loop_output_ipv6;
221 #endif
222 #if LWIP_LOOPIF_MULTICAST
223   netif_set_flags(netif, NETIF_FLAG_IGMP);
224 #endif
225   NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_DISABLE_ALL);
226   return ERR_OK;
227 }
228 #endif /* LWIP_HAVE_LOOPIF */
229 
230 #if LWIP_DHCP
231 /*
232  * Close DHCP and set static network.
233  *
234  * @param netif a pre-allocated netif structure
235  *
236  * @return ERR_OK, or ERR_VAL if failed.
237  */
238 err_t
netif_dhcp_off(struct netif * netif)239 netif_dhcp_off(struct netif *netif)
240 {
241   ip_addr_t old_ipaddr;
242   ip_addr_t old_netmask;
243   ip_addr_t old_gateway;
244 
245   if (netif == NULL) {
246     return ERR_VAL;
247   }
248   old_ipaddr = netif->ip_addr;
249   old_netmask = netif->netmask;
250   old_gateway = netif->gw;
251 
252   if (netif_dhcp_data(netif)) {
253     (void)dhcp_release(netif);
254     dhcp_stop(netif);
255 #if !LWIP_DHCP_SUBSTITUTE
256     dhcp_cleanup(netif);
257 #endif
258     LWIP_DEBUGF(NETIF_DEBUG, ("DHCP is close;set static IP\n"));
259   }
260 
261   ip_addr_set_val(netif->ip_addr, old_ipaddr);
262   ip_addr_set_val(netif->netmask, old_netmask);
263   ip_addr_set_val(netif->gw, old_gateway);
264   (void)netif_set_up(netif);
265 
266   return ERR_OK;
267 }
268 #endif /* LWIP_DHCP */
269 
270 #if LWIP_IPV6_DHCP6
netif_ip6_addr_isdhcp6(struct netif * netif,s8_t i)271 u8_t netif_ip6_addr_isdhcp6(struct netif *netif, s8_t i)
272 {
273   struct dhcp6 *dhcp6 = NULL;
274   if (netif == NULL) {
275     return 0;
276   }
277   dhcp6 = netif_dhcp6_data(netif);
278   if (dhcp6 == NULL) {
279     return 0;
280   }
281   if ((dhcp6_stateful_enabled(dhcp6))
282 #if LWIP_IPV6_DHCP6_STATEFUL
283        && (dhcp6->addr_idx == i)
284 #endif /* LWIP_IPV6_DHCP6_STATEFUL */
285     ) {
286     return 1;
287   }
288 #if !LWIP_IPV6_DHCP6_STATEFUL
289   LWIP_UNUSED_ARG(i);
290 #endif
291   return 0;
292 }
293 #endif /* LWIP_IPV6_DHCP6 */
294 
netif_ipaddr_isbrdcast(const ip_addr_t * ipaddr)295 u8_t netif_ipaddr_isbrdcast(const ip_addr_t *ipaddr)
296 {
297   struct netif *netif = NULL;
298 
299   for (netif = netif_list; netif != NULL; netif = netif->next) {
300     if (netif_is_up(netif) && ip_addr_isbroadcast(ipaddr, netif)) {
301       return 1;
302     }
303   }
304 
305   return 0;
306 }
307 
308 void
netif_init(void)309 netif_init(void)
310 {
311 #if LWIP_HAVE_LOOPIF
312 #if LWIP_IPV4
313 #define LOOPIF_ADDRINIT , &loop_ipaddr, &loop_netmask, &loop_gw
314   ip4_addr_t loop_ipaddr, loop_netmask, loop_gw;
315   IP4_ADDR(&loop_gw, 127, 0, 0, 1);
316   IP4_ADDR(&loop_ipaddr, 127, 0, 0, 1);
317   IP4_ADDR(&loop_netmask, 255, 0, 0, 0);
318 #else /* LWIP_IPV4 */
319 #define LOOPIF_ADDRINIT
320 #endif /* LWIP_IPV4 */
321 
322   (void)netif_add(&loop_netif LOOPIF_ADDRINIT);
323 
324 #if LWIP_IPV6
325   IP_ADDR6_HOST(loop_netif.ip6_addr, 0, 0, 0, 0x00000001UL);
326   loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID;
327 #endif /* LWIP_IPV6 */
328 
329   (void)netif_set_link_up(&loop_netif);
330   (void)netif_set_up(&loop_netif);
331 #if DRIVER_STATUS_CHECK
332   loop_netif.flags |= NETIF_FLAG_DRIVER_RDY;
333 #endif
334 
335   loop_netif.flags |= NETIF_FLAG_LOOPBACK;
336 #endif /* LWIP_HAVE_LOOPIF */
337 }
338 
339 /**
340  * @ingroup lwip_nosys
341  * Forwards a received packet for input processing with
342  * ethernet_input() or ip_input() depending on netif flags.
343  * Don't call directly, pass to netif_add() and call
344  * netif->input().
345  * Only works if the netif driver correctly sets
346  * NETIF_FLAG_ETHARP and/or NETIF_FLAG_ETHERNET flag!
347  */
348 err_t
netif_input(struct pbuf * p,struct netif * inp)349 netif_input(struct pbuf *p, struct netif *inp)
350 {
351   LWIP_ASSERT_CORE_LOCKED();
352 
353   LWIP_ERROR("netif_input : invalid arguments", (inp != NULL), return ERR_ARG);
354   LWIP_ERROR("netif_input : invalid arguments", (p != NULL), return ERR_ARG);
355 
356 #if LWIP_ETHERNET
357   if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
358     return ethernet_input(p, inp);
359   } else
360 #endif /* LWIP_ETHERNET */
361     return ip_input(p, inp);
362 }
363 
364 /**
365  * @ingroup netif
366  * Add a network interface to the list of lwIP netifs.
367  *
368  * Same as @ref netif_add but without IPv4 addresses
369  */
370 struct netif *
netif_add_noaddr(struct netif * netif)371 netif_add_noaddr(struct netif *netif)
372 {
373   return netif_add(netif
374 #if LWIP_IPV4
375                    , NULL, NULL, NULL
376 #endif /* LWIP_IPV4*/
377                   );
378 }
379 
netif_check_num_isusing(const char * ifname,const u8_t num)380 u8_t netif_check_num_isusing(const char *ifname, const u8_t num)
381 {
382   struct netif *netif = NULL;
383   LWIP_ERROR("netif_check_num_isusing : invalid arguments", (ifname != NULL), return 0);
384 
385   for (netif = netif_list; netif != NULL; netif = netif->next) {
386     if ((num == netif->num) && (strncmp(netif->name, ifname, NETIF_NAMESIZE) == 0)) {
387       return 1;
388     }
389   }
390 
391   return 0;
392 }
393 
netif_alloc_num(const char * name)394 static u8_t netif_alloc_num(const char *name)
395 {
396   u8_t num;
397 
398   for (num = 0; num < LWIP_NETIF_NUM_MAX; num++) {
399     if (netif_check_num_isusing(name, num) == 0) {
400       break;
401     }
402   }
403 
404   return num;
405 }
406 
407 struct netif *
netif_find_by_ifindex(u8_t ifindex)408 netif_find_by_ifindex(u8_t ifindex)
409 {
410   struct netif *netif = NULL;
411 
412   if (ifindex < LWIP_NETIF_IFINDEX_START) {
413     LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: Invalid ifindex(%u) \n", ifindex));
414     return netif;
415   }
416 
417   for (netif = netif_list; netif != NULL; netif = netif->next) {
418     if (netif->ifindex == ifindex) {
419       LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: found\n"));
420       return netif;
421     }
422   }
423 
424   LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: didn't find\n"));
425   return NULL;
426 }
427 
428 /* Need to support the get index for all families
429 removed PF_PKT_SUPPORT flag , as this flags restricts the usage to only PF_FAMILY Begin */
430 static u8_t
netif_alloc_ifindex(void)431 netif_alloc_ifindex(void)
432 {
433   u8_t tmp_index;
434 
435   for (tmp_index = LWIP_NETIF_IFINDEX_START; tmp_index <= LWIP_NETIF_IFINDEX_MAX; tmp_index++) {
436     if (netif_get_by_index(tmp_index) == NULL) {
437       break;
438     }
439   }
440 
441   return tmp_index;
442 }
443 
444 /**
445  * @ingroup netif
446  * Add a network interface to the list of lwIP netifs.
447  *
448  * @param netif a pre-allocated netif structure
449  * @param ipaddr IP address for the new netif
450  * @param netmask network mask for the new netif
451  * @param gw default gateway IP address for the new netif
452  * @param state opaque data passed to the new netif
453  * @param init callback function that initializes the interface
454  * @param input callback function that is called to pass
455  * ingress packets up in the protocol layer stack.\n
456  * It is recommended to use a function that passes the input directly
457  * to the stack (netif_input(), NO_SYS=1 mode) or via sending a
458  * message to TCPIP thread (tcpip_input(), NO_SYS=0 mode).\n
459  * These functions use netif flags NETIF_FLAG_ETHARP and NETIF_FLAG_ETHERNET
460  * to decide whether to forward to ethernet_input() or ip_input().
461  * In other words, the functions only work when the netif
462  * driver is implemented correctly!\n
463  * Most members of struct netif should be be initialized by the
464  * netif init function = netif driver (init parameter of this function).\n
465  * IPv6: Don't forget to call netif_create_ip6_linklocal_address() after
466  * setting the MAC address in struct netif.hwaddr
467  * (IPv6 requires a link-local address).
468  *
469  * @return netif, or NULL if failed.
470  */
471 struct netif *
netif_add(struct netif * netif,const ip4_addr_t * ipaddr,const ip4_addr_t * netmask,const ip4_addr_t * gw)472 netif_add(struct netif *netif
473 #if LWIP_IPV4
474   , const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw
475 #endif
476 )
477 {
478 #if LWIP_IPV6
479   s8_t i;
480 #endif
481 
482   LWIP_ASSERT_CORE_LOCKED();
483 
484 #if LWIP_SINGLE_NETIF
485   if (netif_default != NULL) {
486     LWIP_ASSERT("single netif already set", 0);
487     return NULL;
488   }
489 #endif
490 
491   LWIP_ERROR("netif_add: invalid netif", netif != NULL, return NULL);
492 
493 #if LWIP_IPV4
494   if (ipaddr == NULL) {
495     ipaddr = ip_2_ip4(IP4_ADDR_ANY);
496   }
497   if (netmask == NULL) {
498     netmask = ip_2_ip4(IP4_ADDR_ANY);
499   }
500   if (gw == NULL) {
501     gw = ip_2_ip4(IP4_ADDR_ANY);
502   }
503 
504   /* reset new interface configuration state */
505   ip_addr_set_zero_ip4(&netif->ip_addr);
506   ip_addr_set_zero_ip4(&netif->netmask);
507   ip_addr_set_zero_ip4(&netif->gw);
508 #endif /* LWIP_IPV4 */
509 
510 #if LWIP_NETIF_PROMISC
511   (void)atomic_set((&netif->flags_ext), 0);
512   netif->flags_ext1 = 0;
513 #endif /* LWIP_NETIF_PROMISC */
514 
515 #if LWIP_IPV6
516   for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
517     ip_addr_set_zero_ip6(&netif->ip6_addr[i]);
518     netif->ip6_addr_state[i] = IP6_ADDR_INVALID;
519 #if LWIP_IPV6_ADDRESS_LIFETIMES
520     netif->ip6_addr_valid_life[i] = IP6_ADDR_LIFE_STATIC;
521     netif->ip6_addr_pref_life[i] = IP6_ADDR_LIFE_STATIC;
522 #endif /* LWIP_IPV6_ADDRESS_LIFETIMES */
523   }
524   netif->output_ip6 = ethip6_output;
525 #if LWIP_ND6_ROUTER
526   netif->forwarding = lwIP_FALSE;
527   netif->accept_ra = lwIP_FALSE;
528   netif->ra_enable = lwIP_FALSE;
529   netif->ra_init_cnt = ND6_RA_INIT_COUNT;
530   netif->ra_timer = ND6_RA_INIT_INTERVAL;
531 #endif
532   netif->ipv6_addr_event_cb = NULL;
533 
534   /**
535   @page RFC-4862 RFC-4862
536   @par Compliant Sections
537   Section 5.5.4.  Address Lifetime Expiry
538   @par Behavior Description
539   Test: System management MUST have the ability to disable preferred_lifetime management facility,
540   and the facility MUST be disabled by default. User can enable/disable at runtime using ioctl for
541   a particular interface.
542   */
543   /* Default value for enable_deprecated is DISABLE. */
544 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS
545   /* Default value for DAD. */
546   netif->ipv6_flags = netif->ipv6_flags | LWIP_IPV6_ND6_FLAG_DAD;
547 #endif
548 #endif /* LWIP_IPV6 */
549   NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL);
550   netif->mtu = 0;
551   netif->flags = 0;
552 #ifdef netif_get_client_data
553   memset(netif->client_data, 0, sizeof(netif->client_data));
554 #endif /* LWIP_NUM_NETIF_CLIENT_DATA */
555 #if LWIP_DHCPS
556   netif->dhcps = NULL;
557 #endif /* LWIP_DHCPS */
558 #if LWIP_IPV6
559 #if LWIP_IPV6_AUTOCONFIG
560   /* IPv6 address autoconfiguration not enabled by default */
561   netif->ip6_autoconfig_enabled = 0;
562 #endif /* LWIP_IPV6_AUTOCONFIG */
563 #if LWIP_IPV6_SEND_ROUTER_SOLICIT
564   nd6_restart_netif(netif);
565 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
566 #if LWIP_L2_NETDEV_STATUS_CALLBACK
567   netif->l2_netdev_status_callback = NULL;
568 #endif
569 #endif /* LWIP_IPV6 */
570 #if LWIP_NETIF_STATUS_CALLBACK
571   netif->status_callback = NULL;
572 #endif /* LWIP_NETIF_STATUS_CALLBACK */
573 #if LWIP_NETIF_LINK_CALLBACK
574   netif->link_callback = NULL;
575 #endif /* LWIP_NETIF_LINK_CALLBACK */
576 #if LWIP_NETIF_REMOVE_CALLBACK
577   netif->remove_callback = NULL;
578 #endif /* LWIP_NETIF_REMOVE_CALLBACK */
579 #if LWIP_API_MESH
580   netif->linklayer_event = netif_linklayer_event_callback;
581 #if  LWIP_RIPPLE
582   netif->remove_peer = NULL;
583   netif->set_beacon_prio = NULL;
584   netif->set_unique_id = NULL;
585   netif->get_peer_count = NULL;
586   netif->set_rank = NULL;
587   netif->get_link_metric = NULL;
588 #endif /* LWIP_RIPPLE */
589 #endif /* LWIP_API_MESH */
590 #if LWIP_IGMP && LWIP_LINK_MCAST_FILTER
591   netif->igmp_mac_filter = NULL;
592 #endif /* LWIP_IGMP && LWIP_LINK_MCAST_FILTER */
593 #if LWIP_IPV6 && LWIP_IPV6_MLD && LWIP_LINK_MCAST_FILTER
594   netif->mld_mac_filter = NULL;
595 #endif /* LWIP_IPV6 && LWIP_IPV6_MLD && LWIP_LINK_MCAST_FILTER */
596 #if LWIP_ARP && LWIP_ARP_GRATUITOUS_REXMIT
597   netif->arp_gratuitous_doing = lwIP_FALSE;
598   netif->arp_gratuitous_cnt = 0;
599 #endif
600 
601 #if LWIP_HAVE_LOOPIF
602   if (netif == &loop_netif) {
603     (void)netif_loopif_init(netif);
604     netif->num = 0;
605   } else
606 #endif
607   {
608   /* call user specified initialization function for netif */
609     if (driverif_init(netif) != ERR_OK) {
610       return NULL;
611     }
612 
613     netif->num = netif_alloc_num(netif->name);
614     if (netif->num == LWIP_NETIF_NUM_MAX) {
615       LWIP_DEBUGF(NETIF_DEBUG, ("netif: interface num alloc fail"));
616       return NULL;
617     }
618   }
619 
620   netif->input = tcpip_input;
621 
622   NETIF_RESET_HINTS(netif);
623 #if ENABLE_LOOPBACK
624   netif->loop_first = NULL;
625   netif->loop_last = NULL;
626 #if LWIP_LOOPBACK_MAX_PBUFS
627   netif->loop_cnt_current = 0;
628 #endif /* LWIP_LOOPBACK_MAX_PBUFS */
629 #if LWIP_NETIF_LOOPBACK_MULTITHREADING
630   netif->reschedule_poll = 0;
631 #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
632 #endif /* ENABLE_LOOPBACK */
633 
634 #if LWIP_IPV4
635   (void)netif_set_addr(netif, ipaddr, netmask, gw);
636 #endif /* LWIP_IPV4 */
637 
638 #if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES
639   /* Initialize the MTU for IPv6 to the one set by the netif driver.
640      This can be updated later by RA. */
641   netif->mtu6 = netif->mtu;
642 #endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */
643 
644   /*
645    * Need to support the get index for all families
646    * removed PF_PKT_SUPPORT flag , as this flags restricts the usage to only PF_FAMILY
647    */
648   netif->ifindex = netif_alloc_ifindex();
649   LWIP_DEBUGF(NETIF_DEBUG, ("netif: netif->ifindex=%d", netif->ifindex));
650   if ((netif->ifindex < LWIP_NETIF_IFINDEX_START) || (netif->ifindex > LWIP_NETIF_IFINDEX_MAX)) {
651     LWIP_DEBUGF(NETIF_DEBUG, ("netif: interface index alloc fail"));
652     return NULL;
653   }
654 
655 #if !LWIP_SINGLE_NETIF
656   /* add this netif to the list */
657   netif->next = netif_list;
658   netif_list = netif;
659 #endif /* "LWIP_SINGLE_NETIF */
660   mib2_netif_added(netif);
661 
662 #if LWIP_IGMP
663   /* start IGMP processing */
664   if (netif->flags & NETIF_FLAG_IGMP) {
665     igmp_start(netif);
666   }
667 #endif /* LWIP_IGMP */
668 
669   LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %s IP",
670                             netif->name));
671 #if LWIP_IPV4
672   LWIP_DEBUGF(NETIF_DEBUG, (" addr "));
673   ip4_addr_debug_print(NETIF_DEBUG, ipaddr);
674   LWIP_DEBUGF(NETIF_DEBUG, (" netmask "));
675   ip4_addr_debug_print(NETIF_DEBUG, netmask);
676   LWIP_DEBUGF(NETIF_DEBUG, (" gw "));
677   ip4_addr_debug_print(NETIF_DEBUG, gw);
678 #endif /* LWIP_IPV4 */
679   LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
680 
681   netif_invoke_ext_callback(netif, LWIP_NSC_NETIF_ADDED, NULL);
682 
683   return netif;
684 }
685 
686 static void
netif_do_ip_addr_changed(const ip_addr_t * old_addr,const ip_addr_t * new_addr)687 netif_do_ip_addr_changed(const ip_addr_t *old_addr, const ip_addr_t *new_addr)
688 {
689 #if LWIP_TCP
690   tcp_netif_ip_addr_changed(old_addr, new_addr);
691 #endif /* LWIP_TCP */
692 #if LWIP_UDP
693   udp_netif_ip_addr_changed(old_addr, new_addr);
694 #endif /* LWIP_UDP */
695 #if LWIP_RAW
696   raw_netif_ip_addr_changed(old_addr, new_addr);
697 #endif /* LWIP_RAW */
698 }
699 
700 #if LWIP_IPV4
701 static int
netif_do_set_ipaddr(struct netif * netif,const ip4_addr_t * ipaddr,ip_addr_t * old_addr)702 netif_do_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr, ip_addr_t *old_addr)
703 {
704   LWIP_ASSERT("invalid pointer", ipaddr != NULL);
705   LWIP_ASSERT("invalid pointer", old_addr != NULL);
706 
707   /* address is actually being changed? */
708   if (ip4_addr_cmp(ipaddr, netif_ip4_addr(netif)) == 0) {
709     ip_addr_t new_addr;
710     *ip_2_ip4(&new_addr) = *ipaddr;
711     IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_V4);
712 
713     ip_addr_copy(*old_addr, *netif_ip_addr4(netif));
714 
715     LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n"));
716     netif_do_ip_addr_changed(old_addr, &new_addr);
717 
718     mib2_remove_ip4(netif);
719     mib2_remove_route_ip4(0, netif);
720     /* set new IP address to netif */
721     ip4_addr_set(ip_2_ip4(&netif->ip_addr), ipaddr);
722     IP_SET_TYPE_VAL(netif->ip_addr, IPADDR_TYPE_V4);
723     mib2_add_ip4(netif);
724     mib2_add_route_ip4(0, netif);
725 
726     netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4, (s8_t)LWIP_INVALID_IPV6_IDX);
727 
728     NETIF_STATUS_CALLBACK(netif);
729     return 1; /* address changed */
730   }
731   return 0; /* address unchanged */
732 }
733 
734 /**
735  * @ingroup netif_ip4
736  * Change the IP address of a network interface
737  *
738  * @param netif the network interface to change
739  * @param ipaddr the new IP address
740  *
741  * @note call netif_set_addr() if you also want to change netmask and
742  * default gateway
743  */
744 void
netif_set_ipaddr(struct netif * netif,const ip4_addr_t * ipaddr)745 netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr)
746 {
747   ip_addr_t old_addr;
748 
749   LWIP_ERROR("netif_set_ipaddr: invalid netif", netif != NULL, return);
750 
751   /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */
752   if (ipaddr == NULL) {
753     ipaddr = IP4_ADDR_ANY4;
754   }
755 
756   LWIP_ASSERT_CORE_LOCKED();
757 
758   if (netif_do_set_ipaddr(netif, ipaddr, &old_addr)) {
759 #if LWIP_NETIF_EXT_STATUS_CALLBACK
760     netif_ext_callback_args_t args;
761     args.ipv4_changed.old_address = &old_addr;
762     netif_invoke_ext_callback(netif, LWIP_NSC_IPV4_ADDRESS_CHANGED, &args);
763 #endif
764   }
765 }
766 
767 static int
netif_do_set_netmask(struct netif * netif,const ip4_addr_t * netmask,ip_addr_t * old_nm)768 netif_do_set_netmask(struct netif *netif, const ip4_addr_t *netmask, ip_addr_t *old_nm)
769 {
770   /* address is actually being changed? */
771   if (ip4_addr_cmp(netmask, netif_ip4_netmask(netif)) == 0) {
772 #if LWIP_NETIF_EXT_STATUS_CALLBACK
773     LWIP_ASSERT("invalid pointer", old_nm != NULL);
774     ip_addr_copy(*old_nm, *netif_ip_netmask4(netif));
775 #else
776     LWIP_UNUSED_ARG(old_nm);
777 #endif
778     mib2_remove_route_ip4(0, netif);
779     /* set new netmask to netif */
780     ip4_addr_set(ip_2_ip4(&netif->netmask), netmask);
781     IP_SET_TYPE_VAL(netif->netmask, IPADDR_TYPE_V4);
782     mib2_add_route_ip4(0, netif);
783     LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
784                 ("netif: netmask of interface %s set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
785                 netif->name,
786                 ip4_addr1_16(netif_ip4_netmask(netif)),
787                 ip4_addr2_16(netif_ip4_netmask(netif)),
788                 ip4_addr3_16(netif_ip4_netmask(netif)),
789                 ip4_addr4_16(netif_ip4_netmask(netif))));
790     return 1; /* netmask changed */
791   }
792   return 0; /* netmask unchanged */
793 }
794 
795 /**
796  * @ingroup netif_ip4
797  * Change the netmask of a network interface
798  *
799  * @param netif the network interface to change
800  * @param netmask the new netmask
801  *
802  * @note call netif_set_addr() if you also want to change ip address and
803  * default gateway
804  */
805 void
netif_set_netmask(struct netif * netif,const ip4_addr_t * netmask)806 netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask)
807 {
808 #if LWIP_NETIF_EXT_STATUS_CALLBACK
809   ip_addr_t old_nm_val;
810   ip_addr_t *old_nm = &old_nm_val;
811 #else
812   ip_addr_t *old_nm = NULL;
813 #endif
814   LWIP_ASSERT_CORE_LOCKED();
815 
816   LWIP_ERROR("netif_set_netmask: invalid netif", netif != NULL, return);
817 
818   /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */
819   if (netmask == NULL) {
820     netmask = IP4_ADDR_ANY4;
821   }
822 
823   if (netif_do_set_netmask(netif, netmask, old_nm)) {
824 #if LWIP_NETIF_EXT_STATUS_CALLBACK
825     netif_ext_callback_args_t args;
826     args.ipv4_changed.old_netmask = old_nm;
827     netif_invoke_ext_callback(netif, LWIP_NSC_IPV4_NETMASK_CHANGED, &args);
828 #endif
829   }
830 }
831 
832 static int
netif_do_set_gw(struct netif * netif,const ip4_addr_t * gw,ip_addr_t * old_gw)833 netif_do_set_gw(struct netif *netif, const ip4_addr_t *gw, ip_addr_t *old_gw)
834 {
835   /* address is actually being changed? */
836   if (ip4_addr_cmp(gw, netif_ip4_gw(netif)) == 0) {
837 #if LWIP_NETIF_EXT_STATUS_CALLBACK
838     LWIP_ASSERT("invalid pointer", old_gw != NULL);
839     ip_addr_copy(*old_gw, *netif_ip_gw4(netif));
840 #else
841     LWIP_UNUSED_ARG(old_gw);
842 #endif
843 
844     ip4_addr_set(ip_2_ip4(&netif->gw), gw);
845     IP_SET_TYPE_VAL(netif->gw, IPADDR_TYPE_V4);
846     LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
847                 ("netif: GW address of interface %s set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
848                 netif->name,
849                 ip4_addr1_16(netif_ip4_gw(netif)),
850                 ip4_addr2_16(netif_ip4_gw(netif)),
851                 ip4_addr3_16(netif_ip4_gw(netif)),
852                 ip4_addr4_16(netif_ip4_gw(netif))));
853     return 1; /* gateway changed */
854   }
855   return 0; /* gateway unchanged */
856 }
857 
858 /**
859  * @ingroup netif_ip4
860  * Change the default gateway for a network interface
861  *
862  * @param netif the network interface to change
863  * @param gw the new default gateway
864  *
865  * @note call netif_set_addr() if you also want to change ip address and netmask
866  */
867 void
netif_set_gw(struct netif * netif,const ip4_addr_t * gw)868 netif_set_gw(struct netif *netif, const ip4_addr_t *gw)
869 {
870 #if LWIP_NETIF_EXT_STATUS_CALLBACK
871   ip_addr_t old_gw_val;
872   ip_addr_t *old_gw = &old_gw_val;
873 #else
874   ip_addr_t *old_gw = NULL;
875 #endif
876   LWIP_ASSERT_CORE_LOCKED();
877 
878   LWIP_ERROR("netif_set_gw: invalid netif", netif != NULL, return);
879 
880   /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */
881   if (gw == NULL) {
882     gw = IP4_ADDR_ANY4;
883   }
884 
885   if (netif_do_set_gw(netif, gw, old_gw)) {
886 #if LWIP_NETIF_EXT_STATUS_CALLBACK
887     netif_ext_callback_args_t args;
888     args.ipv4_changed.old_gw = old_gw;
889     netif_invoke_ext_callback(netif, LWIP_NSC_IPV4_GATEWAY_CHANGED, &args);
890 #endif
891   }
892 }
893 
894 /**
895  * @ingroup netif_ip4
896  * Change IP address configuration for a network interface (including netmask
897  * and default gateway).
898  *
899  * @param netif the network interface to change
900  * @param ipaddr the new IP address
901  * @param netmask the new netmask
902  * @param gw the new default gateway
903  */
904 err_t
netif_set_addr(struct netif * netif,const ip4_addr_t * ipaddr,const ip4_addr_t * netmask,const ip4_addr_t * gw)905 netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask,
906                const ip4_addr_t *gw)
907 {
908   LWIP_ERROR("netif_set_addr: invalid arguments", (netif != NULL), return ERR_VAL);
909 #if LWIP_NETIF_EXT_STATUS_CALLBACK
910   netif_nsc_reason_t change_reason = LWIP_NSC_NONE;
911   netif_ext_callback_args_t cb_args;
912   ip_addr_t old_nm_val;
913   ip_addr_t old_gw_val;
914   ip_addr_t *old_nm = &old_nm_val;
915   ip_addr_t *old_gw = &old_gw_val;
916 #else
917   ip_addr_t *old_nm = NULL;
918   ip_addr_t *old_gw = NULL;
919 #endif
920   ip_addr_t old_addr;
921   int remove;
922 
923   LWIP_ASSERT_CORE_LOCKED();
924 
925   /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */
926   if (ipaddr == NULL) {
927     ipaddr = IP4_ADDR_ANY4;
928   }
929   if (netmask == NULL) {
930     netmask = IP4_ADDR_ANY4;
931   }
932   if (gw == NULL) {
933     gw = IP4_ADDR_ANY4;
934   }
935 
936   remove = ip4_addr_isany(ipaddr);
937   if (remove) {
938     /* when removing an address, we have to remove it *before* changing netmask/gw
939        to ensure that tcp RST segment can be sent correctly */
940     if (netif_do_set_ipaddr(netif, ipaddr, &old_addr)) {
941 #if LWIP_NETIF_EXT_STATUS_CALLBACK
942       change_reason |= LWIP_NSC_IPV4_ADDRESS_CHANGED;
943       cb_args.ipv4_changed.old_address = &old_addr;
944 #endif
945     }
946   }
947   if (netif_do_set_netmask(netif, netmask, old_nm)) {
948 #if LWIP_NETIF_EXT_STATUS_CALLBACK
949     change_reason |= LWIP_NSC_IPV4_NETMASK_CHANGED;
950     cb_args.ipv4_changed.old_netmask = old_nm;
951 #endif
952   }
953   if (netif_do_set_gw(netif, gw, old_gw)) {
954 #if LWIP_NETIF_EXT_STATUS_CALLBACK
955     change_reason |= LWIP_NSC_IPV4_GATEWAY_CHANGED;
956     cb_args.ipv4_changed.old_gw = old_gw;
957 #endif
958   }
959   if (!remove) {
960     /* set ipaddr last to ensure netmask/gw have been set when status callback is called */
961     if (netif_do_set_ipaddr(netif, ipaddr, &old_addr)) {
962 #if LWIP_NETIF_EXT_STATUS_CALLBACK
963       change_reason |= LWIP_NSC_IPV4_ADDRESS_CHANGED;
964       cb_args.ipv4_changed.old_address = &old_addr;
965 #endif
966     }
967   }
968 
969 #if LWIP_NETIF_EXT_STATUS_CALLBACK
970   if (change_reason != LWIP_NSC_NONE) {
971     change_reason |= LWIP_NSC_IPV4_SETTINGS_CHANGED;
972   }
973   if (!remove) {
974     /* Isssue a callback even if the address hasn't changed, eg. DHCP reboot */
975     change_reason |= LWIP_NSC_IPV4_ADDR_VALID;
976   }
977   if (change_reason != LWIP_NSC_NONE) {
978     netif_invoke_ext_callback(netif, change_reason, &cb_args);
979   }
980 #endif
981 
982   return ERR_OK;
983 }
984 
985 /**
986  * @ingroup netif_ip4
987  * Get IP_add configuration for a network interface (including netmask
988  * and default gateway).
989  *
990  * @param netif get the network interface
991  * @param ipaddr the network interface IP_add
992  * @param netmask the network interface netmask
993  * @param gw the network interface default gateway
994  *
995  * @note
996  *  - netmask and/or gw can be passed NULL, if these details about the netif are not needed
997  */
998 err_t
netif_get_addr(const struct netif * netif,ip4_addr_t * ipaddr,ip4_addr_t * netmask,ip4_addr_t * gw)999 netif_get_addr(const struct netif *netif, ip4_addr_t *ipaddr, ip4_addr_t *netmask, ip4_addr_t *gw)
1000 {
1001   LWIP_ERROR("netif_get_addr: invalid arguments", (netif != NULL), return ERR_VAL);
1002   LWIP_ERROR("netif_get_addr: invalid IP pointer", (ipaddr != NULL), return ERR_VAL);
1003 
1004   ip4_addr_set(ipaddr, ip_2_ip4(&(netif->ip_addr)));
1005   if (netmask != NULL) {
1006     ip4_addr_set(netmask, ip_2_ip4(&(netif->netmask)));
1007   }
1008 
1009   if (gw != NULL) {
1010     ip4_addr_set(gw, ip_2_ip4(&(netif->gw)));
1011   }
1012 
1013   return ERR_OK;
1014 }
1015 #endif /* LWIP_IPV4*/
1016 
1017 #ifdef LWIP_TESTBED
1018 #if LWIP_IPV6
1019 #include "lwip/priv/nd6_priv.h"
1020 extern struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS];
1021 extern struct nd6_destination_cache_entry destination_cache[LWIP_ND6_NUM_DESTINATIONS];
1022 extern struct nd6_router_list_entry default_router_list[LWIP_ND6_NUM_ROUTERS];
1023 #endif
1024 
1025 /**
1026  * @ingroup netif
1027  * reset a network interface from the list of lwIP netifs to a initalize state.
1028  *
1029  * @param netif the network interface to remove
1030  */
1031 err_t
netif_reset(struct netif * netif)1032 netif_reset(struct netif *netif)
1033 {
1034 #if LWIP_IPV6
1035   int i;
1036 #endif
1037 
1038   LWIP_ERROR("netif_remove : invalid value.", (netif != NULL), return ERR_VAL);
1039 
1040 #if LWIP_IPV4
1041   if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) {
1042 #if LWIP_TCP
1043     tcp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL);
1044 #endif /* LWIP_TCP */
1045 #if LWIP_UDP
1046     udp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL);
1047 #endif /* LWIP_UDP */
1048 #if LWIP_RAW
1049     raw_netif_ip_addr_changed(netif_ip_addr4(netif), NULL);
1050 #endif /* LWIP_RAW */
1051   }
1052 
1053 #if LWIP_IGMP
1054   /* stop IGMP processing */
1055   if (netif->flags & NETIF_FLAG_IGMP) {
1056     igmp_stop(netif);
1057     igmp_start(netif);
1058   }
1059 #endif /* LWIP_IGMP */
1060 #endif /* LWIP_IPV4 */
1061 
1062 #if LWIP_IPV6
1063   for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1064     if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) {
1065 #if LWIP_TCP
1066       tcp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
1067 #endif /* LWIP_TCP */
1068 #if LWIP_UDP
1069       udp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
1070 #endif /* LWIP_UDP */
1071 #if LWIP_RAW
1072       raw_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
1073 #endif /* LWIP_RAW */
1074     }
1075     netif_ip6_addr_set_state(netif, i, IP6_ADDR_INVALID);
1076   }
1077 #if LWIP_IPV6_MLD
1078   /* stop MLD processing */
1079   mld6_stop(netif);
1080 #endif /* LWIP_IPV6_MLD */
1081 #endif /* LWIP_IPV6 */
1082 #if LWIP_NETIF_PROMISC
1083   /* disable promiscuous mode if enabled */
1084   if (atomic_read(&netif->flags_ext) == NETIF_FLAG_PROMISC) {
1085     netif_update_promiscuous_mode_status(netif, 0);
1086   }
1087 #endif
1088 
1089 #if LWIP_IPV6
1090   nd6_remove_netif_neighbor_cache_entries(netif);
1091   (void)memset_s(neighbor_cache, sizeof(neighbor_cache), 0, sizeof(neighbor_cache));
1092   (void)memset_s(destination_cache, sizeof(destination_cache), 0, sizeof(destination_cache));
1093   (void)memset_s(default_router_list, sizeof(default_router_list), 0, sizeof(default_router_list));
1094 #endif
1095 
1096   LWIP_DEBUGF(NETIF_DEBUG, ("netif_reset: reset netif\n"));
1097   return ERR_OK;
1098 }
1099 #endif
1100 
1101 #if LWIP_AUTO_CLEANUP_WHILE_NETIF_REMOVE
netif_cleanup_attached_resource(struct netif * netif)1102 static void netif_cleanup_attached_resource(struct netif *netif)
1103 {
1104 #if LWIP_NAT64
1105   (void)nat64_deinit_netif(netif);
1106 #endif
1107 
1108 #if LWIP_IP6IN4
1109   (void)ip6in4_deinit_netif(netif);
1110 #endif
1111 
1112 #if LWIP_RIPPLE
1113   if (netif->flags & NETIF_IS_RPL_UP) {
1114     (void)lwip_stop_rpl(netif);
1115   }
1116   (void)rpl_context_netif_free(netif);
1117 #endif /* LWIP_RIPPLE */
1118 
1119 #if LWIP_MDNS_RESPONDER
1120   (void)mdns_resp_remove_netif(netif);
1121 #endif
1122 
1123 #if LWIP_DHCP
1124   dhcp_cleanup(netif);
1125 #endif /* LWIP_DHCP */
1126 
1127 #if LWIP_DHCPS
1128   dhcps_stop(netif);
1129 #endif /* LWIP_DHCPS */
1130 
1131 #if LWIP_IPV6_DHCP6
1132   dhcp6_disable(netif);
1133   dhcp6_cleanup(netif);
1134 #endif /* LWIP_IPV6_DHCP6 */
1135 }
1136 #endif /* LWIP_AUTO_CLEANUP_WHILE_NETIF_REMOVE */
1137 
1138 /**
1139  * @ingroup netif
1140  * Remove a network interface from the list of lwIP netifs.
1141  *
1142  * @param netif the network interface to remove
1143  */
1144 err_t
netif_remove(struct netif * netif)1145 netif_remove(struct netif *netif)
1146 {
1147 #if LWIP_IPV6
1148   int i;
1149 #endif
1150 
1151   LWIP_ASSERT_CORE_LOCKED();
1152   LWIP_ERROR("netif_remove : invalid value.", (netif != NULL), return ERR_VAL);
1153 
1154   netif_invoke_ext_callback(netif, LWIP_NSC_NETIF_REMOVED, NULL);
1155 
1156 #if LWIP_IPV4
1157   if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) {
1158     netif_do_ip_addr_changed(netif_ip_addr4(netif), NULL);
1159   }
1160 
1161 #if LWIP_IGMP
1162   /* stop IGMP processing */
1163   if (netif->flags & NETIF_FLAG_IGMP) {
1164     igmp_stop(netif);
1165   }
1166 #endif /* LWIP_IGMP */
1167 #endif /* LWIP_IPV4*/
1168 
1169 #if LWIP_IPV6
1170   for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1171     if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) {
1172       netif_do_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
1173     }
1174   }
1175 #if LWIP_IPV6_MLD_QUERIER
1176   mld6_querier_stop(netif);
1177 #endif /* LWIP_IPV6_MLD_QUERIER */
1178 #if LWIP_IPV6_MLD
1179   /* stop MLD processing */
1180   mld6_stop(netif);
1181 #endif /* LWIP_IPV6_MLD */
1182 #endif /* LWIP_IPV6 */
1183 
1184 #if LWIP_NETIF_PROMISC
1185   /* disable promiscuous mode if enabled */
1186   if (atomic_read(&netif->flags_ext) == NETIF_FLAG_PROMISC) {
1187     netif_update_promiscuous_mode_status(netif, 0);
1188   }
1189 #endif
1190 
1191 #if LWIP_AUTO_CLEANUP_WHILE_NETIF_REMOVE
1192   netif_cleanup_attached_resource(netif);
1193 #endif
1194 
1195   if (netif_is_up(netif)) {
1196     /* set netif down before removing (call callback function) */
1197     (void)netif_set_down(netif);
1198   }
1199 
1200   mib2_remove_ip4(netif);
1201 
1202   /* this netif is default? */
1203   if (netif_default == netif) {
1204     /* reset default netif */
1205     (void)netif_set_default(NULL);
1206   }
1207 #if !LWIP_SINGLE_NETIF
1208   /*  is it the first netif? */
1209   if (netif_list == netif) {
1210     netif_list = netif->next;
1211   } else {
1212     /*  look for netif further down the list */
1213     struct netif *tmp_netif;
1214     NETIF_FOREACH(tmp_netif) {
1215       if (tmp_netif->next == netif) {
1216         tmp_netif->next = netif->next;
1217         break;
1218       }
1219     }
1220     if (tmp_netif == NULL) {
1221       return ERR_OK; /* netif is not on the list */
1222     }
1223   }
1224 #endif /* !LWIP_SINGLE_NETIF */
1225   mib2_netif_removed(netif);
1226 #if LWIP_NETIF_REMOVE_CALLBACK
1227   if (netif->remove_callback) {
1228     netif->remove_callback(netif);
1229   }
1230 #endif /* LWIP_NETIF_REMOVE_CALLBACK */
1231   LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") );
1232   return ERR_OK;
1233 }
1234 
1235 #if LWIP_IPV4
1236 
1237 /*
1238  * Find a network interface by searching for its ipaddress
1239  *
1240  * @param ipaddr IP_add of the netif
1241  * @return netif if the its found
1242  *         NULL if there is no netif with ipaddr
1243  */
1244 struct netif *
netif_find_by_ip4addr(const ip_addr_t * ipaddr)1245 netif_find_by_ip4addr(const ip_addr_t *ipaddr)
1246 {
1247   struct netif *netif = NULL;
1248 
1249   LWIP_ASSERT("Expecting ipaddr to be not NULL ", ipaddr != NULL);
1250 
1251   for (netif = netif_list; netif != NULL; netif = netif->next) {
1252     if (ip_addr_cmp(&(netif->ip_addr), ipaddr)) {
1253       LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ipaddr: found\n"));
1254       return netif;
1255     }
1256   }
1257   LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ip4addr: didn't find\n"));
1258   return NULL;
1259 }
1260 
netif_find_dst_ipaddr(const ip_addr_t * ipaddr,ip_addr_t ** dst_addr)1261 s8_t netif_find_dst_ipaddr(const ip_addr_t *ipaddr, ip_addr_t **dst_addr)
1262 {
1263   struct netif *netif = NULL;
1264   ip_addr_t *pdst_addr = NULL;
1265 
1266   pdst_addr = *dst_addr;
1267   netif = netif_find_by_ipaddr(ipaddr);
1268   if (netif == NULL) {
1269     return -1;
1270   }
1271   if ((pdst_addr != NULL) && (!ip_addr_netcmp(pdst_addr, &(netif->ip_addr), ip_2_ip4(&netif->netmask))) &&
1272     !ip_addr_islinklocal(pdst_addr)) {
1273     if (!ip_addr_isany(&netif->gw)) {
1274       *dst_addr  = &(netif->gw);
1275     }
1276   }
1277 
1278   return 0;
1279 }
1280 #endif /* LWIP_IPV4 */
1281 
1282 /**
1283  * @ingroup netif
1284  * Set a network interface as the default network interface
1285  * (used to output all packets for which no specific route is found)
1286  * In case of invoking lwip_connect() without prior lwip_bind(), the driver adaptor must call this macro
1287  * since there should be atleast one default network interface to ensure the functionality while sending out
1288  * packet to peer with Link Local Address.
1289  * @param netif the default network interface
1290  */
1291 err_t
netif_set_default(struct netif * netif)1292 netif_set_default(struct netif *netif)
1293 {
1294   LWIP_ASSERT_CORE_LOCKED();
1295 
1296   if (netif == NULL) {
1297     /* remove default route */
1298     mib2_remove_route_ip4(1, netif);
1299   } else {
1300     /* install default route */
1301     mib2_add_route_ip4(1, netif);
1302   }
1303   netif_default = netif;
1304   LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %s\n",
1305                             netif ? netif->name : "\'\'"));
1306   return ERR_OK;
1307 }
1308 
1309 /**
1310  * @ingroup netif
1311  * Bring an interface up, available for processing
1312  * traffic.
1313  */
1314 err_t
netif_set_up(struct netif * netif)1315 netif_set_up(struct netif *netif)
1316 {
1317   LWIP_ASSERT_CORE_LOCKED();
1318 
1319   LWIP_ERROR("netif_set_up: invalid netif", netif != NULL, return ERR_VAL);
1320 
1321   if (!(netif->flags & NETIF_FLAG_UP)) {
1322     netif_set_flags(netif, NETIF_FLAG_UP);
1323 
1324     MIB2_COPY_SYSUPTIME_TO(&netif->ts);
1325 
1326     NETIF_STATUS_CALLBACK(netif);
1327 
1328 #if LWIP_NETIF_EXT_STATUS_CALLBACK
1329     {
1330       netif_ext_callback_args_t args;
1331       args.status_changed.state = 1;
1332       netif_invoke_ext_callback(netif, LWIP_NSC_STATUS_CHANGED, &args);
1333     }
1334 #endif
1335 
1336     netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4 | NETIF_REPORT_TYPE_IPV6, (s8_t)LWIP_INVALID_IPV6_IDX);
1337 #if LWIP_IPV6
1338     nd6_restart_netif(netif);
1339 #endif /* LWIP_IPV6 */
1340   }
1341   return ERR_OK;
1342 }
1343 
1344 /** Send ARP/IGMP/MLD/RS events, e.g. on link-up/netif-up or addr-change
1345  */
1346 static void
netif_issue_reports(struct netif * netif,u8_t report_type,s8_t addr_idx)1347 netif_issue_reports(struct netif *netif, u8_t report_type, s8_t addr_idx)
1348 {
1349   LWIP_ERROR("netif_issue_reports : invalid arguments", (netif != NULL), return);
1350 
1351   /* Only send reports when both link and admin states are up */
1352   if (!(netif->flags & NETIF_FLAG_LINK_UP) ||
1353       !(netif->flags & NETIF_FLAG_UP)) {
1354     return;
1355   }
1356 
1357 #if LWIP_IPV4
1358   if ((report_type & NETIF_REPORT_TYPE_IPV4) &&
1359       !ip4_addr_isany_val(*netif_ip4_addr(netif))) {
1360 #if LWIP_ARP
1361     /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
1362     if (netif->flags & (NETIF_FLAG_ETHARP)) {
1363       etharp_gratuitous(netif);
1364     }
1365 #endif /* LWIP_ARP */
1366 
1367 #if LWIP_IGMP
1368     /* resend IGMP memberships */
1369     if (netif->flags & NETIF_FLAG_IGMP) {
1370       igmp_report_groups(netif);
1371     }
1372 #endif /* LWIP_IGMP */
1373 #if LWIP_DHCP && LWIP_DHCP_SUBSTITUTE && LWIP_ARP
1374     dhcp_events_trigger(netif);
1375 #endif /* LWIP_DHCP && LWIP_DHCP_SUBSTITUTE && LWIP_ARP */
1376   }
1377 #endif /* LWIP_IPV4 */
1378 
1379 #if LWIP_IPV6
1380   if (report_type & NETIF_REPORT_TYPE_IPV6) {
1381 #if LWIP_IPV6_MLD
1382     /* send mld memberships */
1383     mld6_report_groups(netif);
1384 #endif /* LWIP_IPV6_MLD */
1385     /* Send nd6 report messages */
1386     nd6_report_groups(netif, addr_idx);
1387   }
1388 #else
1389   LWIP_UNUSED_ARG(addr_idx);
1390 #endif /* LWIP_IPV6 */
1391 }
1392 
1393 /**
1394  * @ingroup netif
1395  * Bring an interface down, disabling any traffic processing.
1396  */
1397 err_t
netif_set_down(struct netif * netif)1398 netif_set_down(struct netif *netif)
1399 {
1400   LWIP_ASSERT_CORE_LOCKED();
1401 
1402   LWIP_ERROR("netif_set_down: invalid netif", netif != NULL, return ERR_VAL);
1403 
1404   if (netif->flags & NETIF_FLAG_UP) {
1405 #if LWIP_NETIF_EXT_STATUS_CALLBACK
1406     {
1407       netif_ext_callback_args_t args;
1408       args.status_changed.state = 0;
1409       netif_invoke_ext_callback(netif, LWIP_NSC_STATUS_CHANGED, &args);
1410     }
1411 #endif
1412 
1413     netif_clear_flags(netif, NETIF_FLAG_UP);
1414     MIB2_COPY_SYSUPTIME_TO(&netif->ts);
1415 
1416 #if LWIP_IPV4 && LWIP_ARP
1417     if (netif->flags & NETIF_FLAG_ETHARP) {
1418       etharp_cleanup_netif(netif);
1419     }
1420 #endif /* LWIP_IPV4 && LWIP_ARP */
1421 
1422 #if LWIP_IPV6
1423     nd6_cleanup_netif(netif);
1424 #endif /* LWIP_IPV6 */
1425 
1426     NETIF_STATUS_CALLBACK(netif);
1427   }
1428 
1429   return ERR_OK;
1430 }
1431 
1432 void
netif_get_hwaddr(const struct netif * netif,unsigned char * hw_addr,int hw_len)1433 netif_get_hwaddr(const struct netif *netif, unsigned char *hw_addr, int hw_len)
1434 {
1435   int i;
1436   LWIP_ERROR("netif_get_hwaddr : invalid arguments", (netif != NULL), return);
1437 
1438   LWIP_ERROR("netif_get_hwaddr : invalid arguments", (hw_addr != NULL), return);
1439 
1440   LWIP_ERROR("netif_get_hwaddr: invalid arguments",
1441              ((unsigned int)hw_len == NETIF_MAX_HWADDR_LEN), return);
1442 
1443   for (i = 0; i < hw_len; i++) {
1444     hw_addr[i] = netif->hwaddr[i];
1445   }
1446 }
1447 
1448 /*
1449  * Change the hardware address for a network interface
1450  *
1451  * NOTE:Application should call set_link_down before calling
1452  * the netif_set_hwaddr and then set_link_up, in order
1453  * to ensure that all IPs are announced after changing
1454  * hw address
1455  *
1456  * @param netif the network interface to change
1457  * @param hw_addr the new hardware address
1458  * @param hw_len the length of new hardware address,
1459  *
1460  */
1461 err_t
netif_set_hwaddr(struct netif * netif,const unsigned char * hw_addr,int hw_len)1462 netif_set_hwaddr(struct netif *netif, const unsigned char *hw_addr, int hw_len)
1463 {
1464   LWIP_ERROR("netif_set_hwaddr : invalid arguments", (netif != NULL), return ERR_VAL);
1465 
1466   LWIP_ERROR("netif_set_hwaddr : invalid arguments", (hw_addr != NULL), return ERR_VAL);
1467 
1468   LWIP_ERROR("netif_set_hwaddr: invalid arguments",
1469              ((unsigned int)hw_len == NETIF_MAX_HWADDR_LEN), return ERR_VAL);
1470 
1471   if (netif->drv_set_hwaddr == NULL) {
1472     return ERR_OPNOTSUPP;
1473   }
1474 
1475   if (netif->drv_set_hwaddr(netif, (u8_t *)hw_addr, hw_len) != ERR_OK) {
1476     return ERR_VAL;
1477   }
1478 
1479   if (memcpy_s(netif->hwaddr, NETIF_MAX_HWADDR_LEN, hw_addr, (u32_t)hw_len) != EOK) {
1480     LWIP_DEBUGF(NETIF_DEBUG, ("netif_set_hwaddr: memcpy_s error\n"));
1481     return ERR_VAL;
1482   }
1483 
1484 #if LWIP_DHCP && LWIP_DHCP_SUBSTITUTE && LWIP_ARP
1485   dhcp_events_record(netif, DHCP_EVENT_HW);
1486 #endif /* LWIP_DHCP && LWIP_DHCP_SUBSTITUTE && LWIP_ARP */
1487 
1488   LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
1489               ("netif: HW address of interface %s%"U16_F" set to %02X:%02X:%02X:%02X:%02X:%02X\n",
1490               netif->name, netif->num,
1491               netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2],
1492               netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5]));
1493 
1494   return ERR_OK;
1495 }
1496 
1497 #if LWIP_NETIF_STATUS_CALLBACK
1498 /**
1499  * @ingroup netif
1500  * Set callback to be called when interface is brought up/down or address is changed while up
1501  */
1502 void
netif_set_status_callback(struct netif * netif,netif_status_callback_fn status_callback)1503 netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback)
1504 {
1505   LWIP_ASSERT_CORE_LOCKED();
1506 
1507   if (netif) {
1508     netif->status_callback = status_callback;
1509   }
1510 }
1511 #endif /* LWIP_NETIF_STATUS_CALLBACK */
1512 
1513 #if LWIP_NETIF_REMOVE_CALLBACK
1514 /**
1515  * @ingroup netif
1516  * Set callback to be called when the interface has been removed
1517  */
1518 void
netif_set_remove_callback(struct netif * netif,netif_status_callback_fn remove_callback)1519 netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback)
1520 {
1521   LWIP_ASSERT_CORE_LOCKED();
1522 
1523   if (netif) {
1524     netif->remove_callback = remove_callback;
1525   }
1526 }
1527 #endif /* LWIP_NETIF_REMOVE_CALLBACK */
1528 
1529 /**
1530  * @ingroup netif
1531  * Called by a driver when its link goes up
1532  */
1533 err_t
netif_set_link_up(struct netif * netif)1534 netif_set_link_up(struct netif *netif)
1535 {
1536   LWIP_ASSERT_CORE_LOCKED();
1537 
1538   LWIP_ERROR("netif_set_link_up: invalid netif", netif != NULL, return ERR_VAL);
1539 
1540   if (!(netif->flags & NETIF_FLAG_LINK_UP)) {
1541     netif_set_flags(netif, NETIF_FLAG_LINK_UP);
1542 
1543 #if LWIP_DHCP
1544     dhcp_network_changed(netif);
1545 #endif /* LWIP_DHCP */
1546 
1547 #if LWIP_AUTOIP
1548     autoip_network_changed(netif);
1549 #endif /* LWIP_AUTOIP */
1550 
1551     netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4 | NETIF_REPORT_TYPE_IPV6, (s8_t)LWIP_INVALID_IPV6_IDX);
1552 #if LWIP_IPV6
1553     nd6_restart_netif(netif);
1554 #endif /* LWIP_IPV6 */
1555 
1556     NETIF_LINK_CALLBACK(netif);
1557 #if LWIP_NETIF_EXT_STATUS_CALLBACK
1558     {
1559       netif_ext_callback_args_t args;
1560       args.link_changed.state = 1;
1561       netif_invoke_ext_callback(netif, LWIP_NSC_LINK_CHANGED, &args);
1562     }
1563 #endif
1564   }
1565   return ERR_OK;
1566 }
1567 
1568 /**
1569  * @ingroup netif
1570  * Called by a driver when its link goes down
1571  */
1572 err_t
netif_set_link_down(struct netif * netif)1573 netif_set_link_down(struct netif *netif)
1574 {
1575   LWIP_ASSERT_CORE_LOCKED();
1576 
1577   LWIP_ERROR("netif_set_link_down: invalid netif", netif != NULL, return ERR_VAL);
1578 
1579   if (netif->flags & NETIF_FLAG_LINK_UP) {
1580     netif_clear_flags(netif, NETIF_FLAG_LINK_UP);
1581 #if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES
1582     netif->mtu6 = netif->mtu;
1583 #endif
1584 
1585     NETIF_LINK_CALLBACK(netif);
1586 #if LWIP_NETIF_EXT_STATUS_CALLBACK
1587     {
1588       netif_ext_callback_args_t args;
1589       args.link_changed.state = 0;
1590       netif_invoke_ext_callback(netif, LWIP_NSC_LINK_CHANGED, &args);
1591     }
1592 #endif
1593 #if LWIP_NEIGHBOR_CLEANUP_WHILE_NETIF_LINK_DOWN
1594 #if LWIP_IPV4 && LWIP_ARP
1595     if (netif->flags & NETIF_FLAG_ETHARP) {
1596       etharp_cleanup_netif(netif);
1597     }
1598 #endif /* LWIP_IPV4 && LWIP_ARP */
1599 #if LWIP_IPV6
1600     nd6_cleanup_netif(netif);
1601 #endif /* LWIP_IPV6 */
1602 #endif /* LWIP_NEIGHBOR_CLEANUP_WHILE_NETIF_LINK_DOWN */
1603   }
1604   return ERR_OK;
1605 }
1606 
1607 /* This is called via tcpip_callback_with_block in wifi driver
1608  * when wal reports that STA has associated with AP.
1609  */
netif_set_link_up_interface(void * arg)1610 void netif_set_link_up_interface(void *arg)
1611 {
1612   struct netif *netif = (struct netif *)arg;
1613   if (netif == NULL) {
1614     return;
1615   }
1616   (void)netif_set_link_up(netif);
1617 #if LWIP_IPV6_AUTOCONFIG
1618   netif_set_ip6_autoconfig_enabled(netif);
1619 #endif
1620 #if LWIP_IPV6
1621 #if LWIP_ND6_ROUTER
1622   netif->forwarding = lwIP_FALSE;
1623   netif->ra_enable = lwIP_FALSE;
1624   netif->accept_ra = lwIP_TRUE;
1625 #endif
1626   (void)netif_create_ip6_linklocal_address(netif, lwIP_TRUE);
1627 #endif
1628 }
1629 
1630 /* This is called via tcpip_callback_with_block in wifi driver
1631  * when wal reports that STA has disassociated with AP.
1632  */
netif_set_link_down_interface(void * arg)1633 void netif_set_link_down_interface(void *arg)
1634 {
1635   struct netif *netif = (struct netif *)arg;
1636   if (netif == NULL) {
1637     return;
1638   }
1639   (void)netif_set_link_down(netif);
1640 #if LWIP_IPV4
1641   (void)netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4);
1642 #endif
1643 #if LWIP_IPV6
1644   int index;
1645   for (index = 0; index < LWIP_IPV6_NUM_ADDRESSES; index++) {
1646    (void)netif_do_rmv_ipv6_addr(netif, (void *)(&netif->ip6_addr[index]));
1647   }
1648 #endif
1649 }
1650 
1651 #if LWIP_NETIF_LINK_CALLBACK
1652 /**
1653  * @ingroup netif
1654  * Set callback to be called when link is brought up/down
1655  */
1656 err_t
netif_set_link_callback(struct netif * netif,netif_status_callback_fn link_callback)1657 netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback)
1658 {
1659   LWIP_ASSERT_CORE_LOCKED();
1660   LWIP_ERROR("netif_set_link_callback: invalid value.", (!((netif == NULL) || (link_callback == NULL))),
1661                return ERR_VAL);
1662 
1663   netif->link_callback = link_callback;
1664   return ERR_OK;
1665 }
1666 #endif /* LWIP_NETIF_LINK_CALLBACK */
1667 
1668 #if ENABLE_LOOPBACK
1669 /**
1670  * @ingroup netif
1671  * Send an IP packet to be received on the same netif (loopif-like).
1672  * The pbuf is copied and added to an internal queue which is fed to
1673  * netif->input by netif_poll().
1674  * In multithreaded mode, the call to netif_poll() is queued to be done on the
1675  * TCP/IP thread.
1676  * In callback mode, the user has the responsibility to call netif_poll() in
1677  * the main loop of their application.
1678  *
1679  * @param netif the lwip network interface structure
1680  * @param p the (IP) packet to 'send'
1681  * @return ERR_OK if the packet has been sent
1682  *         ERR_MEM if the pbuf used to copy the packet couldn't be allocated
1683  */
1684 err_t
netif_loop_output(struct netif * netif,struct pbuf * p)1685 netif_loop_output(struct netif *netif, struct pbuf *p)
1686 {
1687   struct pbuf *r;
1688   err_t err;
1689   struct pbuf *last;
1690 #if LWIP_LOOPBACK_MAX_PBUFS
1691   u16_t clen = 0;
1692 #endif /* LWIP_LOOPBACK_MAX_PBUFS */
1693   /* If we have a loopif, SNMP counters are adjusted for it,
1694    * if not they are adjusted for 'netif'. */
1695 #if MIB2_STATS
1696 #if LWIP_HAVE_LOOPIF
1697   struct netif *stats_if = &loop_netif;
1698 #else /* LWIP_HAVE_LOOPIF */
1699   struct netif *stats_if = netif;
1700 #endif /* LWIP_HAVE_LOOPIF */
1701 #endif /* MIB2_STATS */
1702 #if LWIP_NETIF_LOOPBACK_MULTITHREADING
1703   u8_t schedule_poll = 0;
1704 #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
1705   SYS_ARCH_DECL_PROTECT(lev);
1706 
1707   LWIP_ASSERT("netif_loop_output: invalid netif", netif != NULL);
1708   LWIP_ASSERT("netif_loop_output: invalid pbuf", p != NULL);
1709 
1710   /* Allocate a new pbuf */
1711   r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
1712   if (r == NULL) {
1713     LINK_STATS_INC(link.memerr);
1714     LINK_STATS_INC(link.drop);
1715     MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards);
1716     return ERR_MEM;
1717   }
1718 #if LWIP_LOOPBACK_MAX_PBUFS
1719   clen = pbuf_clen(r);
1720   /* check for overflow or too many pbuf on queue */
1721   if (((netif->loop_cnt_current + clen) < netif->loop_cnt_current) ||
1722       ((netif->loop_cnt_current + clen) > LWIP_MIN(LWIP_LOOPBACK_MAX_PBUFS, 0xFFFF))) {
1723     pbuf_free(r);
1724     LINK_STATS_INC(link.memerr);
1725     LINK_STATS_INC(link.drop);
1726     MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards);
1727     return ERR_MEM;
1728   }
1729   netif->loop_cnt_current = (u16_t)(netif->loop_cnt_current + clen);
1730 #endif /* LWIP_LOOPBACK_MAX_PBUFS */
1731 
1732   /* Copy the whole pbuf queue p into the single pbuf r */
1733   if ((err = pbuf_copy(r, p)) != ERR_OK) {
1734     pbuf_free(r);
1735     LINK_STATS_INC(link.memerr);
1736     LINK_STATS_INC(link.drop);
1737     MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards);
1738     return err;
1739   }
1740   r->flags = p->flags;
1741   /* Put the packet on a linked list which gets emptied through calling
1742      netif_poll(). */
1743 
1744   /* let last point to the last pbuf in chain r */
1745   for (last = r; last->next != NULL; last = last->next) {
1746     /* nothing to do here, just get to the last pbuf */
1747   }
1748 
1749   SYS_ARCH_PROTECT(lev);
1750   if (netif->loop_first != NULL) {
1751     LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL);
1752     netif->loop_last->next = r;
1753     netif->loop_last = last;
1754 #if LWIP_NETIF_LOOPBACK_MULTITHREADING
1755     if (netif->reschedule_poll) {
1756       schedule_poll = 1;
1757       netif->reschedule_poll = 0;
1758     }
1759 #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
1760   } else {
1761     netif->loop_first = r;
1762     netif->loop_last = last;
1763 #if LWIP_NETIF_LOOPBACK_MULTITHREADING
1764     /* No existing packets queued, schedule poll */
1765     schedule_poll = 1;
1766 #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
1767   }
1768   SYS_ARCH_UNPROTECT(lev);
1769 
1770   LINK_STATS_INC(link.xmit);
1771   MIB2_STATS_NETIF_ADD(stats_if, ifoutoctets, p->tot_len);
1772   MIB2_STATS_NETIF_INC(stats_if, ifoutucastpkts);
1773 
1774 #if LWIP_NETIF_LOOPBACK_MULTITHREADING
1775   /* For multithreading environment, schedule a call to netif_poll */
1776   if (schedule_poll) {
1777     if (tcpip_try_callback((tcpip_callback_fn)netif_poll, netif) != ERR_OK) {
1778       SYS_ARCH_PROTECT(lev);
1779       netif->reschedule_poll = 1;
1780       SYS_ARCH_UNPROTECT(lev);
1781     }
1782   }
1783 #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
1784 
1785   return ERR_OK;
1786 }
1787 
1788 #if LWIP_HAVE_LOOPIF
1789 #if LWIP_IPV4
1790 static err_t
netif_loop_output_ipv4(struct netif * netif,struct pbuf * p,const ip4_addr_t * addr)1791 netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr)
1792 {
1793   LWIP_UNUSED_ARG(addr);
1794   return netif_loop_output(netif, p);
1795 }
1796 #endif /* LWIP_IPV4 */
1797 
1798 #if LWIP_IPV6
1799 static err_t
netif_loop_output_ipv6(struct netif * netif,struct pbuf * p,const ip6_addr_t * addr)1800 netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr)
1801 {
1802   LWIP_UNUSED_ARG(addr);
1803   return netif_loop_output(netif, p);
1804 }
1805 #endif /* LWIP_IPV6 */
1806 #endif /* LWIP_HAVE_LOOPIF */
1807 
1808 
1809 /**
1810  * Call netif_poll() in the main loop of your application. This is to prevent
1811  * reentering non-reentrant functions like tcp_input(). Packets passed to
1812  * netif_loop_output() are put on a list that is passed to netif->input() by
1813  * netif_poll().
1814  */
1815 void
netif_poll(struct netif * netif)1816 netif_poll(struct netif *netif)
1817 {
1818   /* If we have a loopif, SNMP counters are adjusted for it,
1819    * if not they are adjusted for 'netif'. */
1820 #if MIB2_STATS
1821 #if LWIP_HAVE_LOOPIF
1822   struct netif *stats_if = &loop_netif;
1823 #else /* LWIP_HAVE_LOOPIF */
1824   struct netif *stats_if = netif;
1825 #endif /* LWIP_HAVE_LOOPIF */
1826 #endif /* MIB2_STATS */
1827 #if PF_PKT_SUPPORT
1828   struct raw_pcb *pcb;
1829   int match = 0;
1830 #endif
1831 
1832   SYS_ARCH_DECL_PROTECT(lev);
1833 
1834   LWIP_ASSERT("netif_poll: invalid netif", netif != NULL);
1835 
1836   /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
1837   SYS_ARCH_PROTECT(lev);
1838   while (netif->loop_first != NULL) {
1839     struct pbuf *in, *in_end;
1840 #if LWIP_LOOPBACK_MAX_PBUFS
1841     u8_t clen = 1;
1842 #endif /* LWIP_LOOPBACK_MAX_PBUFS */
1843 
1844     in = in_end = netif->loop_first;
1845     while (in_end->len != in_end->tot_len) {
1846       LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
1847       in_end = in_end->next;
1848 #if LWIP_LOOPBACK_MAX_PBUFS
1849       clen++;
1850 #endif /* LWIP_LOOPBACK_MAX_PBUFS */
1851     }
1852 #if LWIP_LOOPBACK_MAX_PBUFS
1853     /* adjust the number of pbufs on queue */
1854     LWIP_ASSERT("netif->loop_cnt_current underflow",
1855                 ((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
1856     netif->loop_cnt_current = (u16_t)(netif->loop_cnt_current - clen);
1857 #endif /* LWIP_LOOPBACK_MAX_PBUFS */
1858 
1859     /* 'in_end' now points to the last pbuf from 'in' */
1860     if (in_end == netif->loop_last) {
1861       /* this was the last pbuf in the list */
1862       netif->loop_first = netif->loop_last = NULL;
1863     } else {
1864       /* pop the pbuf off the list */
1865       netif->loop_first = in_end->next;
1866       LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
1867     }
1868     /* De-queue the pbuf from its successors on the 'loop_' list. */
1869     in_end->next = NULL;
1870     SYS_ARCH_UNPROTECT(lev);
1871 
1872     in->if_idx = netif_get_index(netif);
1873 
1874     LINK_STATS_INC(link.recv);
1875     MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len);
1876     MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts);
1877 
1878 #if PF_PKT_SUPPORT
1879       for (pcb = pkt_raw_pcbs; pcb != NULL; pcb = pcb->next) {
1880         if (((pcb->proto.eth_proto == htons(ETHTYPE_ALL)) || (pcb->proto.eth_proto == htons(ETHTYPE_IP))) &&
1881             ((!pcb->netifindex) || (pcb->netifindex == netif->ifindex))) {
1882           match = 1;
1883           break;
1884         }
1885       }
1886 
1887       /* always succeed because the alloc layer of loopback pbuf was PBUF_LINK */
1888       if (match && pbuf_header(in, PBUF_LINK_HLEN) == 0) {
1889         struct eth_hdr *ethhdr;
1890         /* add ethernet header */
1891         ethhdr = (struct eth_hdr *)(in->payload);
1892         /* smac and dmac set to all zeros for loopback IP packet */
1893         (void)memset_s(ethhdr, sizeof(struct eth_hdr), 0, sizeof(struct eth_hdr));
1894         ethhdr->type = htons(ETHTYPE_IP); /* eth protocol, should be ETH_P_IP(0x800) */
1895         in->flags = (u16_t)(in->flags & ~(PBUF_FLAG_LLMCAST | PBUF_FLAG_LLBCAST | PBUF_FLAG_OUTGOING));
1896         in->flags |= PBUF_FLAG_HOST;
1897         raw_pkt_input(in, netif, NULL);
1898         (void)pbuf_header(in, -PBUF_LINK_HLEN);
1899       }
1900 #endif /* PF_PKT_SUPPORT */
1901 
1902     /* loopback packets are always IP packets! */
1903     if (ip_input(in, netif) != ERR_OK) {
1904       pbuf_free(in);
1905     }
1906     SYS_ARCH_PROTECT(lev);
1907   }
1908   SYS_ARCH_UNPROTECT(lev);
1909 }
1910 
1911 #if !LWIP_NETIF_LOOPBACK_MULTITHREADING
1912 /**
1913  * Calls netif_poll() for every netif on the netif_list.
1914  */
1915 void
netif_poll_all(void)1916 netif_poll_all(void)
1917 {
1918   struct netif *netif;
1919   /* loop through netifs */
1920   NETIF_FOREACH(netif) {
1921     netif_poll(netif);
1922   }
1923 }
1924 #endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
1925 #endif /* ENABLE_LOOPBACK */
1926 
1927 #if LWIP_NUM_NETIF_CLIENT_DATA > 0
1928 /**
1929  * @ingroup netif_cd
1930  * Allocate an index to store data in client_data member of struct netif.
1931  * Returned value is an index in mentioned array.
1932  * @see LWIP_NUM_NETIF_CLIENT_DATA
1933  */
1934 u8_t
netif_alloc_client_data_id(void)1935 netif_alloc_client_data_id(void)
1936 {
1937   u8_t result = netif_client_id;
1938   netif_client_id++;
1939 
1940   LWIP_ASSERT_CORE_LOCKED();
1941 
1942 #if LWIP_NUM_NETIF_CLIENT_DATA + LWIP_NETIF_CLIENT_DATA_INDEX_MAX > 255
1943 #error LWIP_NUM_NETIF_CLIENT_DATA + LWIP_NETIF_CLIENT_DATA_INDEX_MAX must be <= 255
1944 #endif
1945   LWIP_ASSERT("Increase LWIP_NUM_NETIF_CLIENT_DATA in lwipopts.h", result < LWIP_NUM_NETIF_CLIENT_DATA);
1946   return (u8_t)(result + LWIP_NETIF_CLIENT_DATA_INDEX_MAX);
1947 }
1948 #endif
1949 
1950 #if LWIP_IPV6
1951 /**
1952  * @ingroup netif_ip6
1953  * Change an IPv6 address of a network interface
1954  *
1955  * @param netif the network interface to change
1956  * @param addr_idx index of the IPv6 address
1957  * @param addr6 the new IPv6 address
1958  *
1959  * @note call netif_ip6_addr_set_state() to set the address valid/temptative
1960  */
1961 void
netif_ip6_addr_set(struct netif * netif,s8_t addr_idx,const ip6_addr_t * addr6)1962 netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6)
1963 {
1964   LWIP_ASSERT_CORE_LOCKED();
1965 
1966   LWIP_ASSERT("netif_ip6_addr_set: invalid netif", netif != NULL);
1967   LWIP_ASSERT("netif_ip6_addr_set: invalid addr6", addr6 != NULL);
1968 
1969   netif_ip6_addr_set_parts(netif, addr_idx, addr6->addr[0], addr6->addr[1],
1970                            addr6->addr[2], addr6->addr[3]);
1971 }
1972 
netif_do_add_ipv6_addr(struct netif * netif,void * arguments)1973 err_t netif_do_add_ipv6_addr(struct netif *netif, void *arguments)
1974 {
1975   s8_t idx = -1;
1976   ip_addr_t *ipaddr = (ip_addr_t *)arguments;
1977   err_t err;
1978   if (IP_IS_V6(ipaddr)) {
1979     err = netif_add_ip6_address(netif, ip_2_ip6(ipaddr), &idx);
1980     if ((err != ERR_OK) || (idx == -1)) {
1981       return ERR_BUF;
1982     }
1983     netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6, idx);
1984   }
1985   return ERR_OK;
1986 }
1987 
netif_do_rmv_ipv6_addr(struct netif * netif,void * arguments)1988 err_t netif_do_rmv_ipv6_addr(struct netif *netif, void *arguments)
1989 {
1990   ip_addr_t *ipaddr = (ip_addr_t *)arguments;
1991 
1992   if (IP_IS_V6(ipaddr)) {
1993 #if LWIP_TCP
1994     tcp_unlock_accept(ip_2_ip6(ipaddr));
1995 #endif
1996     netif_ip6_addr_setinvalid(netif, ip_2_ip6(ipaddr));
1997   }
1998   return ERR_OK;
1999 }
2000 
2001 /*
2002  * Change an IPv6 address of a network interface (internal version taking 4 * u32_t)
2003  *
2004  * @param netif the network interface to change
2005  * @param addr_idx index of the IPv6 address
2006  * @param i0 word0 of the new IPv6 address
2007  * @param i1 word1 of the new IPv6 address
2008  * @param i2 word2 of the new IPv6 address
2009  * @param i3 word3 of the new IPv6 address
2010  */
2011 void
netif_ip6_addr_set_parts(struct netif * netif,s8_t addr_idx,u32_t i0,u32_t i1,u32_t i2,u32_t i3)2012 netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3)
2013 {
2014   ip_addr_t old_addr;
2015   ip_addr_t new_ipaddr;
2016   LWIP_ASSERT_CORE_LOCKED();
2017   LWIP_ASSERT("netif != NULL", netif != NULL);
2018   LWIP_ASSERT("invalid index", addr_idx != LWIP_IPV6_NUM_ADDRESSES);
2019 
2020   ip6_addr_copy(*ip_2_ip6(&old_addr), *netif_ip6_addr(netif, addr_idx));
2021   IP_SET_TYPE_VAL(old_addr, IPADDR_TYPE_V6);
2022 
2023   /* address is actually being changed? */
2024   if ((ip_2_ip6(&old_addr)->addr[0] != i0) || (ip_2_ip6(&old_addr)->addr[1] != i1) ||
2025       (ip_2_ip6(&old_addr)->addr[2] != i2) || (ip_2_ip6(&old_addr)->addr[3] != i3)) {
2026     LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set: netif address being changed\n"));
2027 
2028     IP_ADDR6(&new_ipaddr, i0, i1, i2, i3);
2029     ip6_addr_assign_zone(ip_2_ip6(&new_ipaddr), IP6_UNICAST, netif);
2030 
2031     if (ip6_addr_isvalid(netif_ip6_addr_state(netif, addr_idx))) {
2032       netif_do_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
2033     }
2034     /* @todo: remove/readd mib2 ip6 entries? */
2035 
2036     ip_addr_copy(netif->ip6_addr[addr_idx], new_ipaddr);
2037 
2038     if (ip6_addr_isvalid(netif_ip6_addr_state(netif, addr_idx))) {
2039       netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6, addr_idx);
2040       NETIF_STATUS_CALLBACK(netif);
2041     }
2042 
2043 #if LWIP_NETIF_EXT_STATUS_CALLBACK
2044     {
2045       netif_ext_callback_args_t args;
2046       args.ipv6_set.addr_index  = addr_idx;
2047       args.ipv6_set.old_address = &old_addr;
2048       netif_invoke_ext_callback(netif, LWIP_NSC_IPV6_SET, &args);
2049     }
2050 #endif
2051   }
2052 #ifdef LWIP_DEBUG
2053   char buf[IP6ADDR_STRLEN_MAX];
2054   (void)ip6addr_ntoa_r(netif_ip6_addr(netif, addr_idx), buf, IP6ADDR_STRLEN_MAX);
2055 #endif
2056   LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
2057               ("netif: IPv6 address %d of interface %s set to %s/0x%"X8_F"\n",
2058               addr_idx, netif->name, buf,
2059               netif_ip6_addr_state(netif, addr_idx)));
2060 }
2061 
2062 /**
2063  * @ingroup netif_ip6
2064  * Change the state of an IPv6 address of a network interface
2065  * (INVALID, TEMPTATIVE, PREFERRED, DEPRECATED, where TEMPTATIVE
2066  * includes the number of checks done, see ip6_addr.h)
2067  *
2068  * @param netif the network interface to change
2069  * @param addr_idx index of the IPv6 address
2070  * @param state the new IPv6 address state
2071  */
2072 void
netif_ip6_addr_set_state(struct netif * netif,s8_t addr_idx,u8_t state)2073 netif_ip6_addr_set_state(struct netif *netif, s8_t addr_idx, u8_t state)
2074 {
2075   u8_t old_state;
2076   LWIP_ASSERT_CORE_LOCKED();
2077   LWIP_ERROR("netif != NULL", netif != NULL, return);
2078   LWIP_ERROR("invalid index", (addr_idx != LWIP_IPV6_NUM_ADDRESSES), return);
2079 
2080   old_state = netif_ip6_addr_state(netif, addr_idx);
2081   /* state is actually being changed? */
2082   if (old_state != state) {
2083     u8_t old_valid = old_state & IP6_ADDR_VALID;
2084     u8_t new_valid = state & IP6_ADDR_VALID;
2085     LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n"));
2086 
2087 #if LWIP_IPV6_MLD
2088     /* Reevaluate solicited-node multicast group membership. */
2089     if (netif->flags & NETIF_FLAG_MLD6) {
2090       nd6_adjust_mld_membership(netif, addr_idx, state);
2091     }
2092 #endif /* LWIP_IPV6_MLD */
2093 
2094     if (old_valid && !new_valid) {
2095       /* address about to be removed by setting invalid */
2096       netif_do_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
2097       /* @todo: remove mib2 ip6 entries? */
2098     }
2099     netif->ip6_addr_state[addr_idx] = state;
2100 
2101     if (!old_valid && new_valid) {
2102       /* address added by setting valid */
2103       /* This is a good moment to check that the address is properly zoned. */
2104       IP6_ADDR_ZONECHECK_NETIF(netif_ip6_addr(netif, addr_idx), netif);
2105       /* @todo: add mib2 ip6 entries? */
2106       netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6, addr_idx);
2107     }
2108     if ((old_state & ~IP6_ADDR_TENTATIVE_COUNT_MASK) !=
2109         (state     & ~IP6_ADDR_TENTATIVE_COUNT_MASK)) {
2110       /* address state has changed -> call the callback function */
2111       NETIF_STATUS_CALLBACK(netif);
2112     }
2113 
2114 #if LWIP_NETIF_EXT_STATUS_CALLBACK
2115     {
2116       netif_ext_callback_args_t args;
2117       args.ipv6_addr_state_changed.addr_index = addr_idx;
2118       args.ipv6_addr_state_changed.old_state  = old_state;
2119       args.ipv6_addr_state_changed.address    = netif_ip_addr6(netif, addr_idx);
2120       netif_invoke_ext_callback(netif, LWIP_NSC_IPV6_ADDR_STATE_CHANGED, &args);
2121     }
2122 #endif
2123   }
2124 #ifdef LWIP_DEBUG
2125   char buf[IP6ADDR_STRLEN_MAX];
2126   (void)ip6addr_ntoa_r(netif_ip6_addr(netif, addr_idx), buf, IP6ADDR_STRLEN_MAX);
2127 #endif
2128   LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
2129               ("netif: IPv6 address %d of interface %s set to %s/0x%"X8_F"\n",
2130               addr_idx, netif->name, buf,
2131               netif_ip6_addr_state(netif, addr_idx)));
2132 }
2133 
2134 /**
2135  * Checks if a specific local address is present on the netif and returns its
2136  * index. Depending on its state, it may or may not be assigned to the
2137  * interface (as per RFC terminology).
2138  *
2139  * The given address may or may not be zoned (i.e., have a zone index other
2140  * than IP6_NO_ZONE). If the address is zoned, it must have the correct zone
2141  * for the given netif, or no match will be found.
2142  *
2143  * @param netif the netif to check
2144  * @param ip6addr the IPv6 address to find
2145  * @return >= 0: address found, this is its index
2146  *         -1: address not found on this netif
2147  */
2148 s8_t
netif_get_ip6_addr_match(struct netif * netif,const ip6_addr_t * ip6addr)2149 netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr)
2150 {
2151   s8_t i;
2152 
2153   LWIP_ASSERT_CORE_LOCKED();
2154 
2155   LWIP_ERROR("netif_get_ip6_addr_match : invalid arguments", (netif != NULL), return -1);
2156   LWIP_ERROR("netif_get_ip6_addr_match: invalid ip6addr", (ip6addr != NULL), return -1);
2157 
2158 #if LWIP_IPV6_SCOPES
2159   if (ip6_addr_has_zone(ip6addr) && !ip6_addr_test_zone(ip6addr, netif)) {
2160     return -1; /* wrong zone, no match */
2161   }
2162 #endif /* LWIP_IPV6_SCOPES */
2163 
2164   for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
2165     if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) &&
2166         ip6_addr_cmp_zoneless(netif_ip6_addr(netif, i), ip6addr)) {
2167       return i;
2168     }
2169   }
2170   return -1;
2171 }
2172 
2173 /*
2174  * Checks if a specific address is assigned to the netif and returns its
2175  * index.
2176  *
2177  * @param netif the netif to check
2178  * @param ip6addr the IPv6 address to find
2179  * @return >= 0: address found, this is its index
2180  *         -1: address not found on this netif
2181  */
2182 static s8_t
netif_get_ip6_preferred_addr_match(const struct netif * netif,const ip6_addr_t * ip6addr)2183 netif_get_ip6_preferred_addr_match(const struct netif *netif, const ip6_addr_t *ip6addr)
2184 {
2185   s8_t i;
2186   LWIP_ERROR("netif_get_ip6_preferred_addr_match : invalid arguments", (netif != NULL), return -1);
2187 
2188   for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
2189     if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
2190         ip6_addr_cmp(netif_ip6_addr(netif, i), ip6addr)) {
2191       return i;
2192     }
2193   }
2194   return -1;
2195 }
2196 
2197 err_t
netif_get_ip6_linklocal_address(const struct netif * netif,ip6_addr_t * addr)2198 netif_get_ip6_linklocal_address(const struct netif *netif, ip6_addr_t *addr)
2199 {
2200   LWIP_ERROR("netif_get_ip6_linklocal_address : invalid arguments netif", (netif != NULL), return ERR_VAL);
2201   LWIP_ERROR("netif_get_ip6_linklocal_address : invalid arguments addr", (addr != NULL), return ERR_VAL);
2202 
2203   if (ip6_addr_isany(netif_ip6_addr(netif, 0))) {
2204     /* link local address not yet configured */
2205     return ERR_VAL;
2206   }
2207 
2208   ip6_addr_copy_ptr(addr, netif_ip6_addr(netif, 0));
2209   return ERR_OK;
2210 }
2211 
2212 #if LWIP_RIPPLE
2213 err_t
netif_create_ip6_linklocal_address_from_mac(const linklayer_addr_t * mac,ip6_addr_t * ip6addr)2214 netif_create_ip6_linklocal_address_from_mac(const linklayer_addr_t *mac, ip6_addr_t *ip6addr)
2215 {
2216   if ((mac == NULL) || (ip6addr == NULL) || (mac->addrlen != NETIF_MAX_HWADDR_LEN)) {
2217     return ERR_ARG;
2218   }
2219 
2220   ip6addr->addr[0] = PP_HTONL(0xfe800000ul);
2221   ip6addr->addr[1] = 0;
2222   ip6addr->addr[2] = lwip_htonl((((u32_t)(mac->addr[0] ^ 0x02)) << 24) |
2223                                 ((u32_t)(mac->addr[1]) << 16) |
2224                                 ((u32_t)(mac->addr[2]) << 8) | (0xff));
2225   ip6addr->addr[3] = lwip_htonl((u32_t)(0xfeul << 24) |
2226                                 ((u32_t)(mac->addr[3]) << 16) |
2227                                 ((u32_t)(mac->addr[4]) << 8) |
2228                                 ((u32_t)(mac->addr[5])));
2229   return ERR_OK;
2230 }
2231 #endif /* LWIP_RIPPLE */
2232 
2233 /**
2234  * @ingroup netif_ip6
2235  * Create a link-local IPv6 address on a netif (stored in slot 0)
2236  *
2237  * @param netif the netif to create the address on
2238  * @param from_mac_48bit if != 0, assume hwadr is a 48-bit MAC address (std conversion)
2239  *                       if == 0, use hwaddr directly as interface ID
2240  */
2241 err_t
netif_create_ip6_linklocal_address(struct netif * netif,u8_t from_mac_48bit)2242 netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit)
2243 {
2244   u8_t i, addr_index;
2245 
2246   LWIP_ASSERT_CORE_LOCKED();
2247 
2248   LWIP_ERROR("netif_create_ip6_linklocal_address : invalid arguments", (netif != NULL), return ERR_VAL);
2249 
2250   /* Link-local prefix. */
2251   ip_2_ip6(&netif->ip6_addr[0])->addr[0] = PP_HTONL(0xfe800000ul);
2252   ip_2_ip6(&netif->ip6_addr[0])->addr[1] = 0;
2253 
2254   /* Generate interface ID. */
2255   if (from_mac_48bit) {
2256     /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */
2257     ip_2_ip6(&netif->ip6_addr[0])->addr[2] = lwip_htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) |
2258         ((u32_t)(netif->hwaddr[1]) << 16) |
2259         ((u32_t)(netif->hwaddr[2]) << 8) |
2260         (0xff));
2261     ip_2_ip6(&netif->ip6_addr[0])->addr[3] = lwip_htonl((u32_t)(0xfeul << 24) |
2262         ((u32_t)(netif->hwaddr[3]) << 16) |
2263         ((u32_t)(netif->hwaddr[4]) << 8) |
2264         (netif->hwaddr[5]));
2265   } else {
2266     /* Use hwaddr directly as interface ID. */
2267     ip_2_ip6(&netif->ip6_addr[0])->addr[2] = 0;
2268     ip_2_ip6(&netif->ip6_addr[0])->addr[3] = 0;
2269 
2270     addr_index = 3;
2271     for (i = 0; (i < 8) && (i < netif->hwaddr_len); i++) {
2272       if (i == 4) {
2273         addr_index--;
2274       }
2275       ip_2_ip6(&netif->ip6_addr[0])->addr[addr_index] |= lwip_htonl(((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03)));
2276     }
2277   }
2278 
2279   /* Set a link-local zone. Even though the zone is implied by the owning
2280    * netif, setting the zone anyway has two important conceptual advantages:
2281    * 1) it avoids the need for a ton of exceptions in internal code, allowing
2282    *    e.g. ip6_addr_cmp() to be used on local addresses;
2283    * 2) the properly zoned address is visible externally, e.g. when any outside
2284    *    code enumerates available addresses or uses one to bind a socket.
2285    * Any external code unaware of address scoping is likely to just ignore the
2286    * zone field, so this should not create any compatibility problems. */
2287   ip6_addr_assign_zone(ip_2_ip6(&netif->ip6_addr[0]), IP6_UNICAST, netif);
2288 
2289   /* Set address state. */
2290 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS
2291   /* Will perform duplicate address detection (DAD). */
2292   if (LWIP_IS_DAD_ENABLED(netif)) {
2293     netif_ip6_addr_set_state(netif, 0, IP6_ADDR_TENTATIVE);
2294   } else {
2295     netif_ip6_addr_set_state(netif, 0, IP6_ADDR_PREFERRED);
2296   }
2297 #else
2298   /* Consider address valid. */
2299   netif_ip6_addr_set_state(netif, 0, IP6_ADDR_PREFERRED);
2300 #endif /* LWIP_IPV6_AUTOCONFIG */
2301 
2302   return ERR_OK;
2303 }
2304 
2305 #if defined(LWIP_RA_PREFIX_DYNAMIC) && LWIP_RA_PREFIX_DYNAMIC
2306 void
netif_create_ip6_address_80bit_prefix(struct netif * netif,const ip6_addr_t * prefix,ip6_addr_t * ip6addr)2307 netif_create_ip6_address_80bit_prefix(struct netif *netif, const ip6_addr_t *prefix, ip6_addr_t *ip6addr)
2308 {
2309   if ((netif == NULL) || (prefix == NULL) || (ip6addr == NULL)) {
2310     return;
2311   }
2312 
2313   ip6addr->addr[0] = prefix->addr[0];
2314   ip6addr->addr[1] = prefix->addr[1];
2315   ip6addr->addr[2] = lwip_htonl((lwip_ntohl(prefix->addr[2]) & 0xffff0000ul) |
2316                                 ((u32_t)(netif->hwaddr[0]) << 8) |
2317                                 ((u32_t)(netif->hwaddr[1])));
2318   ip6addr->addr[3] = lwip_htonl(((u32_t)(netif->hwaddr[2]) << 24) |
2319                                 ((u32_t)(netif->hwaddr[3]) << 16) |
2320                                 ((u32_t)(netif->hwaddr[4]) << 8) |
2321                                 ((u32_t)(netif->hwaddr[5])));
2322   ip6_addr_clear_zone(ip6addr);
2323 }
2324 #endif
2325 
2326 /**
2327  * @ingroup netif_ip6
2328  * This function allows for the easy addition of a new IPv6 address to an interface.
2329  * It takes care of finding an empty slot and then sets the address tentative
2330  * (to make sure that all the subsequent processing happens).
2331  *
2332  * @param netif netif to add the address on
2333  * @param ip6addr address to add
2334  * @param chosen_idx if != NULL, the chosen IPv6 address index will be stored here
2335  */
2336 err_t
netif_add_ip6_address(struct netif * netif,const ip6_addr_t * ip6addr,s8_t * chosen_idx)2337 netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx)
2338 {
2339   s8_t i;
2340 
2341   LWIP_ASSERT_CORE_LOCKED();
2342 
2343   LWIP_ERROR("netif_add_ip6_address : invalid arguments", (netif != NULL), return ERR_ARG);
2344   LWIP_ERROR("netif_add_ip6_address : Expecting ip6addr to be not NULL ", (ip6addr != NULL), return ERR_ARG);
2345 
2346   i = netif_get_ip6_addr_match(netif, ip6addr);
2347   if (i >= 0) {
2348     /* Address already added */
2349     if (chosen_idx != NULL) {
2350       *chosen_idx = i;
2351     }
2352     return ERR_OK;
2353   }
2354 
2355   if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, 0))) {
2356     (void)netif_create_ip6_linklocal_address(netif, 1);
2357   }
2358 
2359   /* Find a free slot. The first one is reserved for link-local addresses. */
2360   for (i = ip6_addr_islinklocal(ip6addr) ? 0 : 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
2361     if ((ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) ||
2362         ip6_addr_isduplicated(netif_ip6_addr_state(netif, i))) && !netif_ip6_addr_isdhcp6(netif, i)) {
2363       ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr);
2364       ip6_addr_assign_zone(ip_2_ip6(&netif->ip6_addr[i]), IP6_UNICAST, netif);
2365       if (LWIP_IS_DAD_ENABLED(netif)) {
2366         netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE);
2367       } else {
2368         netif_ip6_addr_set_state(netif, i, IP6_ADDR_PREFERRED);
2369       }
2370       if (chosen_idx != NULL) {
2371         *chosen_idx = i;
2372       }
2373       return ERR_OK;
2374     }
2375   }
2376 
2377   if (chosen_idx != NULL) {
2378     *chosen_idx = -1;
2379   }
2380   return ERR_VAL;
2381 }
2382 
2383 void
netif_ip6_addr_setinvalid(struct netif * netif,const ip6_addr_t * addr6)2384 netif_ip6_addr_setinvalid(struct netif *netif, const ip6_addr_t *addr6)
2385 {
2386   s8_t idx;
2387   LWIP_ERROR("netif_ip6_addr_set : invalid arguments", (netif != NULL), return);
2388   LWIP_ERROR("netif_ip6_addr_set : invalid arguments", (addr6 != NULL), return);
2389 
2390   idx = netif_get_ip6_addr_match(netif, addr6);
2391   if (idx < 0) {
2392     return;
2393   }
2394 
2395   netif_ip6_addr_set_state(netif, idx, IP6_ADDR_INVALID);
2396   return;
2397 }
2398 
2399 struct netif *
netif_find_by_ip6addr(const ip6_addr_t * ip6addr)2400 netif_find_by_ip6addr(const ip6_addr_t *ip6addr)
2401 {
2402   struct netif *ni = NULL;
2403   int i;
2404 
2405   LWIP_ERROR("netif_find_by_ip6addr :  Expecting ip6addr to be not NULL ", (ip6addr != NULL), return NULL);
2406 
2407   for (ni = netif_list; ni != NULL; ni = ni->next) {
2408     i = netif_get_ip6_preferred_addr_match(ni, ip6addr);
2409     if (i >= 0) {
2410       return ni;
2411     }
2412   }
2413 
2414   return NULL;
2415 }
2416 
2417 #if LWIP_IPV6_AUTOCONFIG
2418 void
netif_set_ip6_autoconfig_enabled(struct netif * netif)2419 netif_set_ip6_autoconfig_enabled(struct netif *netif)
2420 {
2421   LWIP_ERROR("netif_set_ip6_autoconfig_enabled : invalid arguments", (netif != NULL), return);
2422   netif->ip6_autoconfig_enabled = 1;
2423 #if LWIP_IPV6_SEND_ROUTER_SOLICIT
2424     /* Send RS packet to obtain RA quickly */
2425     (void)nd6_send_rs(netif);
2426 #endif
2427   return;
2428 }
2429 
2430 void
netif_set_ip6_autoconfig_disabled(struct netif * netif)2431 netif_set_ip6_autoconfig_disabled(struct netif *netif)
2432 {
2433   LWIP_ERROR("netif_set_ip6_autoconfig_disabled : invalid arguments", (netif != NULL), return);
2434   netif->ip6_autoconfig_enabled = 0;
2435 
2436   /* invalid autoconfig generated addresses */
2437   nd6_clear_netif_autoconf_address(netif);
2438   return;
2439 }
2440 #endif /* LWIP_IPV6_AUTOCONFIG */
2441 
2442 #endif /* LWIP_IPV6 */
2443 
2444 /*
2445  * Change mtu setting for a network interface
2446  *
2447  * @param netif the network interface to change
2448  * @param netif_mtu the new MTU for the interface
2449  */
2450 #ifndef PPP_SUPPORT
2451 err_t
netif_set_mtu(struct netif * netif,u16_t netif_mtu)2452 netif_set_mtu(struct netif *netif, u16_t netif_mtu)
2453 {
2454   /* As per RFC 791, "Every internet module must be able to forward a datagram of 68
2455    * octets without further fragmentation.  This is because an internet header
2456    * may be up to 60 octets, and the minimum fragment is 8 octets." */
2457   LWIP_ERROR("netif_set_mtu: invalid arguments", (netif != NULL), return ERR_VAL);
2458 
2459 #if LWIP_IPV6
2460   LWIP_ERROR("netif_set_mtu: invalid arguments", (netif_mtu >= NETIF_MTU_MIN) && (netif_mtu <= IP_FRAG_MAX_MTU),
2461              return ERR_ARG);
2462 #else
2463   LWIP_ERROR("netif_set_mtu: invalid arguments", (netif_mtu >= IP_FRAG_MIN_MTU) && (netif_mtu <= IP_FRAG_MAX_MTU),
2464              return ERR_ARG);
2465 #endif
2466 
2467   netif->mtu = netif_mtu;
2468 #if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES
2469   netif->mtu6 = netif_mtu;
2470 #endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */
2471 
2472   LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif: MTU of interface %s%"U16_F" is changed to %d\n",
2473                 netif->name, netif->num, netif->mtu));
2474 
2475   return ERR_OK;
2476 }
2477 #endif
2478 
2479 #if DRIVER_STATUS_CHECK
2480 err_t
netif_stop_queue(struct netif * netif)2481 netif_stop_queue(struct netif *netif)
2482 {
2483   LWIP_ERROR("netif_set_driver_ready: invalid arguments", (netif != NULL), return ERR_ARG);
2484 
2485   if (!(netif->flags & NETIF_FLAG_DRIVER_RDY)) {
2486     LWIP_DEBUGF(NETIF_DEBUG, ("netif already stopped \n"));
2487     return ERR_ARG;
2488   }
2489 
2490   netif->flags = netif->flags & ~NETIF_FLAG_DRIVER_RDY;
2491 
2492   /* Start the waketimer for this netif */
2493   netif->waketime = 0;
2494 
2495   tcpip_upd_status_to_tcp_pcbs(netif, DRV_NOT_READY);
2496 
2497   return ERR_OK;
2498 }
2499 
2500 err_t
netif_wake_queue(struct netif * netif)2501 netif_wake_queue(struct netif *netif)
2502 {
2503   LWIP_ERROR("netif_set_driver_ready: invalid arguments", (netif != NULL), return ERR_ARG);
2504 
2505   if (netif->flags & NETIF_FLAG_DRIVER_RDY) {
2506     LWIP_DEBUGF(NETIF_DEBUG, ("netif already in ready state \n"));
2507     return ERR_ARG;
2508   }
2509 
2510   netif->flags |= NETIF_FLAG_DRIVER_RDY;
2511 
2512   tcp_ip_event_sendplus_on_wake_queue(netif);
2513 
2514   /* Stop the waketimer for this netif */
2515   netif->waketime = -1;
2516 
2517   tcpip_upd_status_to_tcp_pcbs(netif, DRV_READY);
2518 
2519   /* Need to send the buffered TCP segments */
2520   tcpip_flush_on_wake_queue(netif, DRV_READY);
2521 
2522   return ERR_OK;
2523 }
2524 #endif
2525 
2526 #if LWIP_NETIF_PROMISC
2527 /* Enables the promiscuous mode of the netif, if no pkt_raw_pcb are listening over it. */
netif_enable_promisc_mode(struct netif * netif)2528 static void netif_enable_promisc_mode(struct netif *netif)
2529 {
2530   struct netif *loc_netif = NULL;
2531   u8_t activ_flag = 0;
2532 
2533   LWIP_ERROR("netif_enable_promisc_mode : invalid arguments", (netif != NULL), return);
2534 
2535   /* Check the status of secondary netif */
2536   for (loc_netif = netif_list; loc_netif != NULL; loc_netif = loc_netif->next) {
2537     if (netif == loc_netif) {
2538       continue;
2539     }
2540     if ((strncmp(netif->name, loc_netif->name, NETIF_NAMESIZE) == 0) && (netif->num == loc_netif->num)) {
2541       if (loc_netif->flags_ext1 & NETIF_FLAG_PROMISC_RUNNING) {
2542         activ_flag = 1;
2543         break;
2544       }
2545     }
2546   }
2547 
2548   if (pkt_raw_pcbs_using_netif(netif->ifindex) >= 1) {
2549     netif->flags_ext1 |= NETIF_FLAG_PROMISC_RUNNING;
2550 
2551     /* enable promiscusous mode */
2552     if ((activ_flag == 0) && (netif->drv_config != NULL)) {
2553       netif->drv_config(netif, IFF_PROMISC, 1);
2554     } else {
2555       LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif: promiscuous mode support not found %s\n",
2556                   netif->name));
2557     }
2558   }
2559 
2560   return;
2561 }
2562 
2563 /* disables promiscuous mode of the netif, if no pkt_raw_pcb are listening over it. */
netif_disable_promisc_mode(struct netif * netif)2564 static void netif_disable_promisc_mode(struct netif *netif)
2565 {
2566   struct netif *loc_netif = NULL;
2567   u8_t activ_flag = 0;
2568 
2569   LWIP_ERROR("netif_disable_promisc_mode : invalid arguments", (netif != NULL), return);
2570 
2571   /* Check the status of secondary netif */
2572   for (loc_netif = netif_list; loc_netif != NULL; loc_netif = loc_netif->next) {
2573     if (netif == loc_netif) {
2574       continue;
2575     }
2576     if ((strncmp(netif->name, loc_netif->name, NETIF_NAMESIZE) == 0) && (netif->num == loc_netif->num)) {
2577       if (loc_netif->flags_ext1 & NETIF_FLAG_PROMISC_RUNNING) {
2578         activ_flag = 1;
2579         break;
2580       }
2581     }
2582   }
2583 
2584   /* disable promiscusous mode */
2585   if ((activ_flag == 0) && (netif->drv_config != NULL)) {
2586     netif->drv_config(netif, IFF_PROMISC, 0);
2587   }
2588 
2589   netif->flags_ext1 &= (u8_t)(~(NETIF_FLAG_PROMISC_RUNNING));
2590 
2591   return;
2592 }
2593 
2594 /*
2595  * Enable promiscuous mode on interface
2596  *
2597  * @note: Enabling promiscuous mode on interface will allow receiving all packets.
2598  * return 0 on success
2599  *
2600  */
netif_update_promiscuous_mode_status(struct netif * netif,u8_t set)2601 void netif_update_promiscuous_mode_status(struct netif *netif, u8_t set)
2602 {
2603   LWIP_ERROR("netif_update_promiscuous_mode_status : invalid arguments", (netif != NULL), return);
2604 
2605   /* return back if promiscuous mode is already enabled on netif */
2606   if ((set && ((atomic_read(&netif->flags_ext) == NETIF_FLAG_PROMISC))) ||
2607       (!set && !(atomic_read(&netif->flags_ext) == NETIF_FLAG_PROMISC))) {
2608     LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif: promiscuous mode is alredy %s\n",
2609                 (set ? "enabled" : "disabled")));
2610     return;
2611   }
2612 
2613   if (netif->drv_config != NULL) {
2614     if (set) {
2615       (void)atomic_set((&netif->flags_ext), NETIF_FLAG_PROMISC);
2616       netif_enable_promisc_mode(netif);
2617     } else {
2618       (void)atomic_set((&netif->flags_ext), 0);
2619       netif_disable_promisc_mode(netif);
2620     }
2621     LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif: promiscuous mode %s on interface %s\n",
2622                 set ? "enabled" : "disabled", netif->name));
2623   } else {
2624     LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif: promiscuous mode support not found %s\n",
2625                 netif->name));
2626   }
2627 }
2628 
2629 
netif_stop_promisc_mode(u8_t ifindex)2630 void netif_stop_promisc_mode(u8_t ifindex)
2631 {
2632   struct netif *tmp_if = NULL;
2633 
2634   /* Raw socket without bind and promisc enabled on interface. */
2635   if (!ifindex) {
2636     /* loop through netif's and disable promisc mode if this is the only PCB */
2637     for (tmp_if = netif_list; tmp_if != NULL; tmp_if = tmp_if->next) {
2638       if ((atomic_read(&tmp_if->flags_ext) == NETIF_FLAG_PROMISC) &&
2639           (!pkt_raw_pcbs_using_netif(tmp_if->ifindex))) {
2640         netif_disable_promisc_mode(tmp_if);
2641       }
2642     }
2643   } else { /* RAW socket withbind and promisc enabled on interface */
2644     tmp_if = netif_find_by_ifindex(ifindex);
2645     if (((tmp_if != NULL) && (atomic_read(&tmp_if->flags_ext) == NETIF_FLAG_PROMISC)) &&
2646         (!pkt_raw_pcbs_using_netif(tmp_if->ifindex))) {
2647       netif_disable_promisc_mode(tmp_if);
2648     }
2649   }
2650 }
2651 
2652 /* Enables the promiscuous mode of the netif, if no pkt_raw_pcb are listening over it. */
netif_start_promisc_if_not_running(struct netif * netif)2653 static void netif_start_promisc_if_not_running(struct netif *netif)
2654 {
2655   LWIP_ERROR("netif_start_promisc_if_not_running : invalid arguments", (netif != NULL), return);
2656 
2657   if ((!(netif->flags_ext1 & NETIF_FLAG_PROMISC_RUNNING))) {
2658     netif_enable_promisc_mode(netif);
2659   }
2660 
2661   return;
2662 }
2663 
netif_start_promisc_mode(u8_t ifindex)2664 void netif_start_promisc_mode(u8_t ifindex)
2665 {
2666   struct netif *tmp_if = NULL;
2667 
2668   /* Raw socket without bind and promisc enabled on interface. */
2669   if (!ifindex) {
2670     /* loop through netif's and start promisc mode if there is atleast one PCB binded to the netif */
2671     for (tmp_if = netif_list; tmp_if != NULL; tmp_if = tmp_if->next) {
2672       if (atomic_read(&tmp_if->flags_ext) == NETIF_FLAG_PROMISC) {
2673         netif_start_promisc_if_not_running(tmp_if);
2674       }
2675     }
2676   } else { /* RAW socket withbind and promisc enabled on interface */
2677     tmp_if = netif_find_by_ifindex(ifindex);
2678     if ((tmp_if != NULL) && (atomic_read(&tmp_if->flags_ext) == NETIF_FLAG_PROMISC)) {
2679       netif_start_promisc_if_not_running(tmp_if);
2680     }
2681   }
2682 
2683   return;
2684 }
2685 
2686 #endif /* LWIP_NETIF_PROMISC */
2687 
2688 struct netif *
netif_find_by_ipaddr(const ip_addr_t * ipaddr)2689 netif_find_by_ipaddr(const ip_addr_t *ipaddr)
2690 {
2691   LWIP_ERROR("netif_find_by_ipaddr : invalid arguments", (ipaddr != NULL), return NULL);
2692 #if LWIP_IPV4
2693   if (IP_IS_V4(ipaddr)) {
2694     return netif_find_by_ip4addr(ipaddr);
2695   }
2696 #endif
2697 
2698 #if LWIP_IPV6
2699   if (IP_IS_V6(ipaddr)) {
2700     return netif_find_by_ip6addr(ip_2_ip6(ipaddr));
2701   }
2702 #endif
2703 
2704   LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ipaddr: didn't find\n"));
2705   return NULL;
2706 }
2707 
2708 /**
2709 * @ingroup netif
2710 * Return the interface index for the netif with name
2711 * or NETIF_NO_INDEX if not found/on error
2712 *
2713 * @param name the name of the netif
2714 */
2715 u8_t
netif_name_to_index(const char * name)2716 netif_name_to_index(const char *name)
2717 {
2718   struct netif *netif = netif_find(name);
2719   if (netif != NULL) {
2720     return netif_get_index(netif);
2721   }
2722   /* No name found, return invalid index */
2723   return NETIF_NO_INDEX;
2724 }
2725 
2726 /**
2727 * @ingroup netif
2728 * Return the interface name for the netif matching index
2729 * or NULL if not found/on error
2730 *
2731 * @param idx the interface index of the netif
2732 * @param name char buffer of at least NETIF_NAMESIZE bytes
2733 */
2734 char *
netif_index_to_name(u8_t index,char * name)2735 netif_index_to_name(u8_t index, char *name)
2736 {
2737   int ret;
2738   struct netif *curif = netif_list;
2739   if (index == 0) {
2740     return NULL; /* indexes start at 1 */
2741   }
2742 
2743   /* find netif from num */
2744   while (curif != NULL) {
2745     if (curif->ifindex != index) {
2746       curif = curif->next;
2747       continue;
2748     }
2749     if (curif->link_layer_type == LOOPBACK_IF) {
2750       ret = snprintf_s(name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s", curif->name);
2751       if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) {
2752           return NULL;
2753       }
2754     } else {
2755       ret = snprintf_s(name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s%"U8_F, curif->name, curif->num);
2756     }
2757     if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) {
2758       return NULL;
2759     }
2760     return name;
2761   }
2762   return NULL;
2763 }
2764 
2765 /*
2766  * @ingroup netif_if
2767  * Return all the array of interfaces in the netif name and index pair .
2768  * or NULL if not found on error
2769  *
2770  * @param output : Array of all the interfaces available
2771  */
netif_get_nameindex_all(void * arg)2772 err_t netif_get_nameindex_all(void *arg)
2773 {
2774   struct netif *curif = NULL;
2775   struct if_nameindex *ifname_idx_list = NULL;
2776   struct if_nameindex *tmp_if = NULL;
2777   char *ifname = NULL;
2778   u16_t if_count = 1; /* One extra count for the last array which shows the end of the list */
2779   u16_t total_size;
2780   int ret;
2781   struct if_nameindex **if_list = (struct if_nameindex **)arg;
2782   for (curif = netif_list; curif != NULL; curif = curif->next) {
2783     if_count++;
2784   }
2785 
2786   /* This API allows to handle only 0xfe indexes as of now */
2787   LWIP_ERROR("Max number of interfaces reached.", (if_count <= LWIP_NETIF_IFINDEX_MAX_EX),
2788              return ERR_MEM);
2789 
2790   /* No overflow check required here */
2791   total_size = (u16_t)(if_count * IF_NAMEINDEX_ELE_SIZE);
2792   ifname_idx_list = (struct if_nameindex *)mem_malloc(total_size);
2793   if (ifname_idx_list == NULL) {
2794     *if_list = NULL;
2795     return ERR_MEM;
2796   }
2797 
2798   (void)memset_s((void *)ifname_idx_list, total_size, 0, total_size);
2799 
2800   ifname = ((char*)(ifname_idx_list) + (sizeof(struct if_nameindex) * if_count));
2801   tmp_if = ifname_idx_list;
2802 
2803   for (curif = netif_list; curif != NULL; curif = curif->next) {
2804     tmp_if->if_index = curif->ifindex;
2805     tmp_if->if_name = ifname;
2806     if (curif->link_layer_type == LOOPBACK_IF) {
2807       ret = snprintf_s(ifname, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s", curif->name);
2808       if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) {
2809         LWIP_DEBUGF(NETIF_DEBUG, ("netif_get_nameindex_all: name is too long \n"));
2810         return ERR_BUF;
2811       }
2812     } else {
2813       ret = snprintf_s(ifname, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s%"U8_F, curif->name, curif->num);
2814       if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) {
2815         LWIP_DEBUGF(NETIF_DEBUG, ("netif_get_nameindex_all: name is too long \n"));
2816         return ERR_BUF;
2817       }
2818     }
2819     tmp_if++;
2820     ifname = (char*)(ifname + NETIF_NAMESIZE + 4); // keep buffer of 4 bytes
2821   }
2822   tmp_if->if_index = 0;
2823   tmp_if->if_name = NULL;
2824 
2825   *if_list = ifname_idx_list;
2826 
2827   return ERR_OK;
2828 }
2829 
2830 /**
2831 * @ingroup netif
2832 * Return the interface for the netif index
2833 *
2834 * @param idx index of netif to find
2835 */
2836 struct netif *
netif_get_by_index(u8_t idx)2837 netif_get_by_index(u8_t idx)
2838 {
2839   struct netif *netif;
2840 
2841   LWIP_ASSERT_CORE_LOCKED();
2842 
2843   if (idx != NETIF_NO_INDEX) {
2844     NETIF_FOREACH(netif) {
2845       if (idx == netif_get_index(netif)) {
2846         return netif; /* found! */
2847       }
2848     }
2849   }
2850 
2851   return NULL;
2852 }
2853 
2854 #if LWIP_RIPPLE
2855 u8_t
netif_count(void)2856 netif_count(void)
2857 {
2858   struct netif *netif = NULL;
2859   u8_t cnt = 0;
2860 
2861   for (netif = netif_list; netif != NULL; netif = netif->next) {
2862     cnt++;
2863   }
2864 
2865   return cnt;
2866 }
2867 #endif /* LWIP_RIPPLE */
2868 
2869 #if LWIP_API_MESH
2870 #if LWIP_RIPPLE
2871 err_t
netif_remove_peer(struct netif * netif,struct linklayer_addr * peeraddr)2872 netif_remove_peer(struct netif *netif, struct linklayer_addr *peeraddr)
2873 {
2874   LWIP_ERROR("netif_remove_peer: invalid arguments", (netif != NULL), return ERR_ARG);
2875 
2876   LWIP_ERROR("netif_remove_peer: invalid arguments", (peeraddr != NULL), return ERR_ARG);
2877 
2878   if (netif->remove_peer != NULL) {
2879     return netif->remove_peer(netif, peeraddr);
2880   }
2881 
2882   LWIP_DEBUGF(NETIF_DEBUG, ("netif_remove_peer: not support\n"));
2883 
2884   return ERR_OPNOTSUPP;
2885 }
2886 
2887 err_t
netif_set_beacon_prio(struct netif * netif,u8_t prio)2888 netif_set_beacon_prio(struct netif *netif, u8_t prio)
2889 {
2890   LWIP_ERROR("netif_set_beacon_prio: invalid arguments", (netif != NULL), return ERR_ARG);
2891 
2892   if (netif->set_beacon_prio != NULL) {
2893     return netif->set_beacon_prio(netif, prio);
2894   }
2895 
2896   LWIP_DEBUGF(NETIF_DEBUG, ("netif_set_beacon_prio: not support\n"));
2897 
2898   return ERR_OPNOTSUPP;
2899 }
2900 
2901 err_t
netif_set_unique_id(struct netif * netif,uniqid_t id)2902 netif_set_unique_id(struct netif *netif, uniqid_t id)
2903 {
2904   LWIP_ERROR("netif_set_unique_id: invalid arguments", (netif != NULL), return ERR_ARG);
2905 
2906   if (netif->set_unique_id != NULL) {
2907     return netif->set_unique_id(netif, id);
2908   }
2909 
2910   LWIP_DEBUGF(NETIF_DEBUG, ("netif_set_unique_id: not support\n"));
2911 
2912   return ERR_OPNOTSUPP;
2913 }
2914 
2915 err_t
netif_get_peer_count(struct netif * netif,u16_t * count)2916 netif_get_peer_count(struct netif *netif, u16_t *count)
2917 {
2918   LWIP_ERROR("netif_get_peer_count: invalid arguments", ((netif != NULL) && (count != NULL)), return ERR_ARG);
2919 
2920   if (netif->get_peer_count != NULL) {
2921     return netif->get_peer_count(netif, count);
2922   }
2923 
2924   LWIP_DEBUGF(NETIF_DEBUG, ("netif_get_peer_count: not support\n"));
2925 
2926   return ERR_OPNOTSUPP;
2927 }
2928 
2929 err_t
netif_set_rank(struct netif * netif,u16_t rank)2930 netif_set_rank(struct netif *netif, u16_t rank)
2931 {
2932   LWIP_ERROR("netif_set_rank: invalid arguments", (netif != NULL), return ERR_ARG);
2933 
2934   if (netif->set_rank != NULL) {
2935     return netif->set_rank(netif, rank);
2936   }
2937 
2938   LWIP_DEBUGF(NETIF_DEBUG, ("netif_set_rank: not support\n"));
2939 
2940   return ERR_OPNOTSUPP;
2941 }
2942 
2943 err_t
netif_get_link_metric(struct netif * netif,u16_t * metric)2944 netif_get_link_metric(struct netif *netif, u16_t *metric)
2945 {
2946   LWIP_ERROR("netif_get_link_metric: invalid arguments", (netif != NULL), return ERR_ARG);
2947 
2948   if (netif->get_link_metric != NULL) {
2949     return netif->get_link_metric(netif, metric);
2950   }
2951 
2952   LWIP_DEBUGF(NETIF_DEBUG, ("netif_get_link_metric: not support\n"));
2953 
2954   return ERR_OPNOTSUPP;
2955 }
2956 
2957 #endif /* LWIP_RIPPLE */
2958 
2959 err_t
netif_linklayer_event_internal(struct tcpip_api_call_data * m)2960 netif_linklayer_event_internal(struct tcpip_api_call_data *m)
2961 {
2962   struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m;
2963   const struct linklayer_event_info *evt = msg->msg.linklayer_event.evt;
2964 
2965   switch (evt->type) {
2966     case LL_EVENT_DEL_PEER:
2967     case LL_EVENT_STA_DISCONN:
2968 #if LWIP_DHCPS
2969       dhcps_client_disconnect(msg->netif, (const u8_t *)evt->info.sta_conn.addr.addr, evt->info.sta_conn.addr.addrlen);
2970 #endif
2971       break;
2972     default:
2973       break;
2974   }
2975   return ERR_OK;
2976 }
2977 
2978 err_t
netif_linklayer_event(struct netif * netif,const struct linklayer_event_info * evt)2979 netif_linklayer_event(struct netif *netif, const struct linklayer_event_info *evt)
2980 {
2981   err_t err;
2982   LWIP_API_VAR_DECLARE(msg);
2983 
2984   LWIP_API_VAR_ALLOC(msg);
2985 
2986   LWIP_API_VAR_REF(msg).netif = netif;
2987   LWIP_API_VAR_REF(msg).msg.linklayer_event.evt = evt;
2988 
2989   err = tcpip_linklayer_event_call(netif_linklayer_event_internal, &API_VAR_REF(msg).call);
2990 
2991   LWIP_API_VAR_FREE(msg);
2992   return err;
2993 }
2994 
2995 struct linklayer_event_handle {
2996   void *dst;
2997   int copy_len;
2998 };
2999 
3000 err_t
netif_linklayer_event_callback(struct netif * netif,u8_t evt_type,const void * evt_info)3001 netif_linklayer_event_callback(struct netif *netif, u8_t evt_type, const void *evt_info)
3002 {
3003   struct linklayer_event_info evt;
3004 
3005   LWIP_ERROR("netif_linklayer_event_callback: invalid arguments",
3006              ((netif != NULL) && (evt_type < LL_EVENT_MAX)), return ERR_ARG);
3007 
3008   struct linklayer_event_handle handle[LL_EVENT_MAX] = {
3009 #if LWIP_RIPPLE
3010     {
3011       .dst = &evt.info.tx_info,
3012       .copy_len = sizeof(linklayer_event_tx_info_t),
3013     },
3014     {
3015       .dst = &evt.info.new_peer,
3016       .copy_len = sizeof(linklayer_event_new_peer_t),
3017     },
3018     {
3019       .dst = &evt.info.del_peer,
3020       .copy_len = sizeof(linklayer_event_del_peer_t),
3021     },
3022 #else
3023     {
3024       .dst = NULL,
3025       .copy_len = 0,
3026     },
3027     {
3028       .dst = NULL,
3029       .copy_len = 0,
3030     },
3031     {
3032       .dst = NULL,
3033       .copy_len = 0,
3034     },
3035 #endif /* LWIP_RIPPLE */
3036     {
3037       .dst = &evt.info.ap_conn,
3038       .copy_len = sizeof(linklayer_event_ap_conn_t),
3039     },
3040     {
3041       .dst = NULL,
3042       .copy_len = 0,
3043     },
3044     {
3045       .dst = &evt.info.sta_conn,
3046       .copy_len = sizeof(linklayer_event_sta_conn_t),
3047     },
3048     {
3049       .dst = &evt.info.sta_conn,
3050       .copy_len = sizeof(linklayer_event_sta_conn_t),
3051     },
3052   };
3053 
3054   evt.type = evt_type;
3055   LWIP_DEBUGF(NETIF_DEBUG, ("netif_linklayer_event_callback: %u\n", evt_type));
3056 
3057   if (handle[evt_type].dst != NULL) {
3058     LWIP_ERROR("netif_linklayer_event_callback: invalid arguments", (evt_info != NULL), return ERR_ARG);
3059     (void)memcpy_s(handle[evt_type].dst, handle[evt_type].copy_len, evt_info, handle[evt_type].copy_len);
3060   }
3061 
3062   err_t ret = netif_linklayer_event(netif, &evt);
3063 
3064 #if LWIP_RIPPLE
3065   ret = netif_linklayer_event_handler(netif, &evt);
3066 #endif /* LWIP_RIPPLE */
3067 
3068   return ret;
3069 }
3070 #endif /* LWIP_API_MESH */
3071 
3072 /**
3073  * @ingroup netif
3074  * Find a network interface by searching for its name
3075  *
3076  * @param name the name of the netif (like netif->name) plus concatenated number
3077  * in ascii representation (e.g. 'en0')
3078  */
3079 struct netif *
netif_find(const char * name)3080 netif_find(const char *name)
3081 {
3082   struct netif *netif = NULL;
3083   char candidate_name[NETIF_NAMESIZE];
3084   int ret;
3085 
3086   LWIP_ERROR("netif_find : invalid value.", (name != NULL), return NULL);
3087 
3088   NETIF_FOREACH(netif) {
3089     if (strncmp(name, netif->name, NETIF_NAMESIZE) == 0) {
3090       LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %s\n", name));
3091       return netif;
3092     }
3093 
3094     if (netif->link_layer_type != LOOPBACK_IF) {
3095       ret = snprintf_s(candidate_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s%"U8_F, netif->name, netif->num);
3096       if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) {
3097         LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: name '%s'is too long\n", netif->name));
3098         continue;
3099       }
3100       if (strncmp(name, candidate_name, NETIF_NAMESIZE) == 0) {
3101         LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %s\n", name));
3102         return netif;
3103       }
3104     }
3105   }
3106   LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %s\n", name));
3107   return NULL;
3108 }
3109 
3110 #if LWIP_NETIF_EXT_STATUS_CALLBACK
3111 /**
3112  * @ingroup netif
3113  * Add extended netif events listener
3114  * @param callback pointer to listener structure
3115  * @param fn callback function
3116  */
3117 void
netif_add_ext_callback(netif_ext_callback_t * callback,netif_ext_callback_fn fn)3118 netif_add_ext_callback(netif_ext_callback_t *callback, netif_ext_callback_fn fn)
3119 {
3120   LWIP_ASSERT_CORE_LOCKED();
3121   LWIP_ASSERT("callback must be != NULL", callback != NULL);
3122   LWIP_ASSERT("fn must be != NULL", fn != NULL);
3123 
3124   callback->callback_fn = fn;
3125   callback->next        = ext_callback;
3126   ext_callback          = callback;
3127 }
3128 
3129 /**
3130  * @ingroup netif
3131  * Remove extended netif events listener
3132  * @param callback pointer to listener structure
3133  */
3134 void
netif_remove_ext_callback(netif_ext_callback_t * callback)3135 netif_remove_ext_callback(netif_ext_callback_t* callback)
3136 {
3137   netif_ext_callback_t *last, *iter;
3138 
3139   LWIP_ASSERT_CORE_LOCKED();
3140   LWIP_ASSERT("callback must be != NULL", callback != NULL);
3141 
3142   if (ext_callback == NULL) {
3143     return;
3144   }
3145 
3146   if (callback == ext_callback) {
3147     ext_callback = ext_callback->next;
3148   } else {
3149     last = ext_callback;
3150     for (iter = ext_callback->next; iter != NULL; last = iter, iter = iter->next) {
3151       if (iter == callback) {
3152         LWIP_ASSERT("last != NULL", last != NULL);
3153         last->next = callback->next;
3154         callback->next = NULL;
3155         return;
3156       }
3157     }
3158   }
3159 }
3160 
3161 /**
3162  * Invoke extended netif status event
3163  * @param netif netif that is affected by change
3164  * @param reason change reason
3165  * @param args depends on reason, see reason description
3166  */
3167 void
netif_invoke_ext_callback(struct netif * netif,netif_nsc_reason_t reason,const netif_ext_callback_args_t * args)3168 netif_invoke_ext_callback(struct netif *netif, netif_nsc_reason_t reason, const netif_ext_callback_args_t *args)
3169 {
3170   netif_ext_callback_t *callback = ext_callback;
3171 
3172   LWIP_ASSERT("netif must be != NULL", netif != NULL);
3173 
3174   while (callback != NULL) {
3175     callback->callback_fn(netif, reason, args);
3176     callback = callback->next;
3177   }
3178 }
3179 #endif /* LWIP_NETIF_EXT_STATUS_CALLBACK */
3180