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