ReactOS 0.4.16-dev-340-g0540c21
netif.c
Go to the documentation of this file.
1
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/snmp.h"
64#include "lwip/igmp.h"
65#include "lwip/etharp.h"
66#include "lwip/stats.h"
67#include "lwip/sys.h"
68#include "lwip/ip.h"
69#if ENABLE_LOOPBACK
70#if LWIP_NETIF_LOOPBACK_MULTITHREADING
71#include "lwip/tcpip.h"
72#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
73#endif /* ENABLE_LOOPBACK */
74
75#include "netif/ethernet.h"
76
77#if LWIP_AUTOIP
78#include "lwip/autoip.h"
79#endif /* LWIP_AUTOIP */
80#if LWIP_DHCP
81#include "lwip/dhcp.h"
82#endif /* LWIP_DHCP */
83#if LWIP_ACD
84#include "lwip/acd.h"
85#endif /* LWIP_ACD */
86#if LWIP_IPV6_DHCP6
87#include "lwip/dhcp6.h"
88#endif /* LWIP_IPV6_DHCP6 */
89#if LWIP_IPV6_MLD
90#include "lwip/mld6.h"
91#endif /* LWIP_IPV6_MLD */
92#if LWIP_IPV6
93#include "lwip/nd6.h"
94#endif
95
96#if LWIP_NETIF_STATUS_CALLBACK
97#define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0)
98#else
99#define NETIF_STATUS_CALLBACK(n)
100#endif /* LWIP_NETIF_STATUS_CALLBACK */
101
102#if LWIP_NETIF_LINK_CALLBACK
103#define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0)
104#else
105#define NETIF_LINK_CALLBACK(n)
106#endif /* LWIP_NETIF_LINK_CALLBACK */
107
108#if LWIP_NETIF_EXT_STATUS_CALLBACK
109static netif_ext_callback_t *ext_callback;
110#endif
111
112#if !LWIP_SINGLE_NETIF
114#endif /* !LWIP_SINGLE_NETIF */
116
117#define netif_index_to_num(index) ((index) - 1)
119
120#if LWIP_NUM_NETIF_CLIENT_DATA > 0
121static u8_t netif_client_id;
122#endif
123
124#define NETIF_REPORT_TYPE_IPV4 0x01
125#define NETIF_REPORT_TYPE_IPV6 0x02
126static void netif_issue_reports(struct netif *netif, u8_t report_type);
127
128#if LWIP_IPV6
129static err_t netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr);
130#endif /* LWIP_IPV6 */
131#if LWIP_IPV4
132static err_t netif_null_output_ip4(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr);
133#endif /* LWIP_IPV4 */
134
135#if LWIP_HAVE_LOOPIF
136#if LWIP_IPV4
137static err_t netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr);
138#endif
139#if LWIP_IPV6
140static err_t netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr);
141#endif
142
143
144static struct netif loop_netif;
145
146#if LWIP_TESTMODE
147struct netif* netif_get_loopif(void)
148{
149 return &loop_netif;
150}
151#endif
152
153
161static err_t
162netif_loopif_init(struct netif *netif)
163{
164 LWIP_ASSERT("netif_loopif_init: invalid netif", netif != NULL);
165
166 /* initialize the snmp variables and counters inside the struct netif
167 * ifSpeed: no assumption can be made!
168 */
169 MIB2_INIT_NETIF(netif, snmp_ifType_softwareLoopback, 0);
170
171 netif->name[0] = 'l';
172 netif->name[1] = 'o';
173#if LWIP_IPV4
174 netif->output = netif_loop_output_ipv4;
175#endif
176#if LWIP_IPV6
177 netif->output_ip6 = netif_loop_output_ipv6;
178#endif
179#if LWIP_LOOPIF_MULTICAST
181#endif
182 NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_DISABLE_ALL);
183 return ERR_OK;
184}
185#endif /* LWIP_HAVE_LOOPIF */
186
187void
189{
190#if LWIP_HAVE_LOOPIF
191#if LWIP_IPV4
192#define LOOPIF_ADDRINIT &loop_ipaddr, &loop_netmask, &loop_gw,
193 ip4_addr_t loop_ipaddr, loop_netmask, loop_gw;
194 IP4_ADDR(&loop_gw, 127, 0, 0, 1);
195 IP4_ADDR(&loop_ipaddr, 127, 0, 0, 1);
196 IP4_ADDR(&loop_netmask, 255, 0, 0, 0);
197#else /* LWIP_IPV4 */
198#define LOOPIF_ADDRINIT
199#endif /* LWIP_IPV4 */
200
201#if NO_SYS
202 netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, ip_input);
203#else /* NO_SYS */
204 netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, tcpip_input);
205#endif /* NO_SYS */
206
207#if LWIP_IPV6
208 IP_ADDR6_HOST(loop_netif.ip6_addr, 0, 0, 0, 0x00000001UL);
209 loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID;
210#endif /* LWIP_IPV6 */
211
212 netif_set_link_up(&loop_netif);
213 netif_set_up(&loop_netif);
214
215#endif /* LWIP_HAVE_LOOPIF */
216}
217
227err_t
228netif_input(struct pbuf *p, struct netif *inp)
229{
231
232 LWIP_ASSERT("netif_input: invalid pbuf", p != NULL);
233 LWIP_ASSERT("netif_input: invalid netif", inp != NULL);
234
235#if LWIP_ETHERNET
237 return ethernet_input(p, inp);
238 } else
239#endif /* LWIP_ETHERNET */
240 return ip_input(p, inp);
241}
242
249struct netif *
251{
252 return netif_add(netif,
253#if LWIP_IPV4
254 NULL, NULL, NULL,
255#endif /* LWIP_IPV4*/
256 state, init, input);
257}
258
286struct netif *
288#if LWIP_IPV4
289 const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw,
290#endif /* LWIP_IPV4 */
292{
293#if LWIP_IPV6
294 s8_t i;
295#endif
296
298
299#if LWIP_SINGLE_NETIF
300 if (netif_default != NULL) {
301 LWIP_ASSERT("single netif already set", 0);
302 return NULL;
303 }
304#endif
305
306 LWIP_ERROR("netif_add: invalid netif", netif != NULL, return NULL);
307 LWIP_ERROR("netif_add: No init function given", init != NULL, return NULL);
308
309#if LWIP_IPV4
310 if (ipaddr == NULL) {
311 ipaddr = ip_2_ip4(IP4_ADDR_ANY);
312 }
313 if (netmask == NULL) {
314 netmask = ip_2_ip4(IP4_ADDR_ANY);
315 }
316 if (gw == NULL) {
317 gw = ip_2_ip4(IP4_ADDR_ANY);
318 }
319
320 /* reset new interface configuration state */
321 ip_addr_set_zero_ip4(&netif->ip_addr);
322 ip_addr_set_zero_ip4(&netif->netmask);
323 ip_addr_set_zero_ip4(&netif->gw);
324 netif->output = netif_null_output_ip4;
325#endif /* LWIP_IPV4 */
326#if LWIP_IPV6
327 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
328 ip_addr_set_zero_ip6(&netif->ip6_addr[i]);
329 netif->ip6_addr_state[i] = IP6_ADDR_INVALID;
330#if LWIP_IPV6_ADDRESS_LIFETIMES
331 netif->ip6_addr_valid_life[i] = IP6_ADDR_LIFE_STATIC;
332 netif->ip6_addr_pref_life[i] = IP6_ADDR_LIFE_STATIC;
333#endif /* LWIP_IPV6_ADDRESS_LIFETIMES */
334 }
335 netif->output_ip6 = netif_null_output_ip6;
336#endif /* LWIP_IPV6 */
337 NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL);
338 netif->mtu = 0;
339 netif->flags = 0;
340#ifdef netif_get_client_data
341 memset(netif->client_data, 0, sizeof(netif->client_data));
342#endif /* LWIP_NUM_NETIF_CLIENT_DATA */
343#if LWIP_IPV6
344#if LWIP_IPV6_AUTOCONFIG
345 /* IPv6 address autoconfiguration should be enabled by default */
346 netif->ip6_autoconfig_enabled = 1;
347#endif /* LWIP_IPV6_AUTOCONFIG */
348 nd6_restart_netif(netif);
349#endif /* LWIP_IPV6 */
350#if LWIP_NETIF_STATUS_CALLBACK
351 netif->status_callback = NULL;
352#endif /* LWIP_NETIF_STATUS_CALLBACK */
353#if LWIP_NETIF_LINK_CALLBACK
354 netif->link_callback = NULL;
355#endif /* LWIP_NETIF_LINK_CALLBACK */
356#if LWIP_IGMP
357 netif->igmp_mac_filter = NULL;
358#endif /* LWIP_IGMP */
359#if LWIP_IPV6 && LWIP_IPV6_MLD
360 netif->mld_mac_filter = NULL;
361#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
362
363 /* remember netif specific state information data */
364 netif->state = state;
366 netif->input = input;
367
368#if LWIP_ACD
369 netif->acd_list = NULL;
370#endif /* LWIP_ACD */
372#if ENABLE_LOOPBACK
373 netif->loop_first = NULL;
374 netif->loop_last = NULL;
375#if LWIP_LOOPBACK_MAX_PBUFS
376 netif->loop_cnt_current = 0;
377#endif /* LWIP_LOOPBACK_MAX_PBUFS */
378#if LWIP_NETIF_LOOPBACK_MULTITHREADING
379 netif->reschedule_poll = 0;
380#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
381#endif /* ENABLE_LOOPBACK */
382
383#if LWIP_IPV4
384 netif_set_addr(netif, ipaddr, netmask, gw);
385#endif /* LWIP_IPV4 */
386
387 /* call user specified initialization function for netif */
388 if (init(netif) != ERR_OK) {
389 return NULL;
390 }
391#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES
392 /* Initialize the MTU for IPv6 to the one set by the netif driver.
393 This can be updated later by RA. */
394 netif->mtu6 = netif->mtu;
395#endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */
396
397#if !LWIP_SINGLE_NETIF
398 /* Assign a unique netif number in the range [0..254], so that (num+1) can
399 serve as an interface index that fits in a u8_t.
400 We assume that the new netif has not yet been added to the list here.
401 This algorithm is O(n^2), but that should be OK for lwIP.
402 */
403 {
404 struct netif *netif2;
405 int num_netifs;
406 do {
407 if (netif->num == 255) {
408 netif->num = 0;
409 }
410 num_netifs = 0;
411 for (netif2 = netif_list; netif2 != NULL; netif2 = netif2->next) {
412 LWIP_ASSERT("netif already added", netif2 != netif);
413 num_netifs++;
414 LWIP_ASSERT("too many netifs, max. supported number is 255", num_netifs <= 255);
415 if (netif2->num == netif->num) {
416 netif->num++;
417 break;
418 }
419 }
420 } while (netif2 != NULL);
421 }
422 if (netif->num == 254) {
423 netif_num = 0;
424 } else {
425 netif_num = (u8_t)(netif->num + 1);
426 }
427
428 /* add this netif to the list */
431#endif /* "LWIP_SINGLE_NETIF */
433
434#if LWIP_IGMP
435 /* start IGMP processing */
436 if (netif->flags & NETIF_FLAG_IGMP) {
437 igmp_start(netif);
438 }
439#endif /* LWIP_IGMP */
440
441 LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP",
442 netif->name[0], netif->name[1]));
443#if LWIP_IPV4
444 LWIP_DEBUGF(NETIF_DEBUG, (" addr "));
445 ip4_addr_debug_print(NETIF_DEBUG, ipaddr);
446 LWIP_DEBUGF(NETIF_DEBUG, (" netmask "));
447 ip4_addr_debug_print(NETIF_DEBUG, netmask);
448 LWIP_DEBUGF(NETIF_DEBUG, (" gw "));
449 ip4_addr_debug_print(NETIF_DEBUG, gw);
450#endif /* LWIP_IPV4 */
451 LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
452
454
455 return netif;
456}
457
458static void
459netif_do_ip_addr_changed(const ip_addr_t *old_addr, const ip_addr_t *new_addr)
460{
461#if LWIP_TCP
462 tcp_netif_ip_addr_changed(old_addr, new_addr);
463#endif /* LWIP_TCP */
464#if LWIP_UDP
465 udp_netif_ip_addr_changed(old_addr, new_addr);
466#endif /* LWIP_UDP */
467#if LWIP_RAW
468 raw_netif_ip_addr_changed(old_addr, new_addr);
469#endif /* LWIP_RAW */
470}
471
472#if LWIP_IPV4
473static int
474netif_do_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr, ip_addr_t *old_addr)
475{
476 LWIP_ASSERT("invalid pointer", ipaddr != NULL);
477 LWIP_ASSERT("invalid pointer", old_addr != NULL);
478
479 /* address is actually being changed? */
480 if (ip4_addr_eq(ipaddr, netif_ip4_addr(netif)) == 0) {
481 ip_addr_t new_addr;
482 *ip_2_ip4(&new_addr) = *ipaddr;
484
485 ip_addr_copy(*old_addr, *netif_ip_addr4(netif));
486
487 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n"));
488 netif_do_ip_addr_changed(old_addr, &new_addr);
489
490#if LWIP_ACD
491 acd_netif_ip_addr_changed(netif, old_addr, &new_addr);
492#endif /* LWIP_ACD */
493
496 /* set new IP address to netif */
497 ip4_addr_set(ip_2_ip4(&netif->ip_addr), ipaddr);
501
503
505 return 1; /* address changed */
506 }
507 return 0; /* address unchanged */
508}
509
520void
521netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr)
522{
523 ip_addr_t old_addr;
524
525 LWIP_ERROR("netif_set_ipaddr: invalid netif", netif != NULL, return);
526
527 /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */
528 if (ipaddr == NULL) {
529 ipaddr = IP4_ADDR_ANY4;
530 }
531
533
534 if (netif_do_set_ipaddr(netif, ipaddr, &old_addr)) {
535#if LWIP_NETIF_EXT_STATUS_CALLBACK
537 args.ipv4_changed.old_address = &old_addr;
539#endif
540 }
541}
542
543static int
544netif_do_set_netmask(struct netif *netif, const ip4_addr_t *netmask, ip_addr_t *old_nm)
545{
546 /* address is actually being changed? */
547 if (ip4_addr_eq(netmask, netif_ip4_netmask(netif)) == 0) {
548#if LWIP_NETIF_EXT_STATUS_CALLBACK
549 LWIP_ASSERT("invalid pointer", old_nm != NULL);
550 ip_addr_copy(*old_nm, *netif_ip_netmask4(netif));
551#else
552 LWIP_UNUSED_ARG(old_nm);
553#endif
555 /* set new netmask to netif */
556 ip4_addr_set(ip_2_ip4(&netif->netmask), netmask);
559 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
560 netif->name[0], netif->name[1],
561 ip4_addr1_16(netif_ip4_netmask(netif)),
562 ip4_addr2_16(netif_ip4_netmask(netif)),
563 ip4_addr3_16(netif_ip4_netmask(netif)),
564 ip4_addr4_16(netif_ip4_netmask(netif))));
565 return 1; /* netmask changed */
566 }
567 return 0; /* netmask unchanged */
568}
569
580void
581netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask)
582{
583#if LWIP_NETIF_EXT_STATUS_CALLBACK
584 ip_addr_t old_nm_val;
585 ip_addr_t *old_nm = &old_nm_val;
586#else
587 ip_addr_t *old_nm = NULL;
588#endif
590
591 LWIP_ERROR("netif_set_netmask: invalid netif", netif != NULL, return);
592
593 /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */
594 if (netmask == NULL) {
595 netmask = IP4_ADDR_ANY4;
596 }
597
598 if (netif_do_set_netmask(netif, netmask, old_nm)) {
599#if LWIP_NETIF_EXT_STATUS_CALLBACK
601 args.ipv4_changed.old_netmask = old_nm;
603#endif
604 }
605}
606
607static int
608netif_do_set_gw(struct netif *netif, const ip4_addr_t *gw, ip_addr_t *old_gw)
609{
610 /* address is actually being changed? */
611 if (ip4_addr_eq(gw, netif_ip4_gw(netif)) == 0) {
612#if LWIP_NETIF_EXT_STATUS_CALLBACK
613 LWIP_ASSERT("invalid pointer", old_gw != NULL);
614 ip_addr_copy(*old_gw, *netif_ip_gw4(netif));
615#else
616 LWIP_UNUSED_ARG(old_gw);
617#endif
618
619 ip4_addr_set(ip_2_ip4(&netif->gw), gw);
621 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
622 netif->name[0], netif->name[1],
623 ip4_addr1_16(netif_ip4_gw(netif)),
624 ip4_addr2_16(netif_ip4_gw(netif)),
625 ip4_addr3_16(netif_ip4_gw(netif)),
626 ip4_addr4_16(netif_ip4_gw(netif))));
627 return 1; /* gateway changed */
628 }
629 return 0; /* gateway unchanged */
630}
631
641void
642netif_set_gw(struct netif *netif, const ip4_addr_t *gw)
643{
644#if LWIP_NETIF_EXT_STATUS_CALLBACK
645 ip_addr_t old_gw_val;
646 ip_addr_t *old_gw = &old_gw_val;
647#else
648 ip_addr_t *old_gw = NULL;
649#endif
651
652 LWIP_ERROR("netif_set_gw: invalid netif", netif != NULL, return);
653
654 /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */
655 if (gw == NULL) {
656 gw = IP4_ADDR_ANY4;
657 }
658
659 if (netif_do_set_gw(netif, gw, old_gw)) {
660#if LWIP_NETIF_EXT_STATUS_CALLBACK
662 args.ipv4_changed.old_gw = old_gw;
664#endif
665 }
666}
667
678void
679netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask,
680 const ip4_addr_t *gw)
681{
682#if LWIP_NETIF_EXT_STATUS_CALLBACK
683 netif_nsc_reason_t change_reason = LWIP_NSC_NONE;
685 ip_addr_t old_nm_val;
686 ip_addr_t old_gw_val;
687 ip_addr_t *old_nm = &old_nm_val;
688 ip_addr_t *old_gw = &old_gw_val;
689#else
690 ip_addr_t *old_nm = NULL;
691 ip_addr_t *old_gw = NULL;
692#endif
693 ip_addr_t old_addr;
694 int remove;
695
697
698 /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */
699 if (ipaddr == NULL) {
700 ipaddr = IP4_ADDR_ANY4;
701 }
702 if (netmask == NULL) {
703 netmask = IP4_ADDR_ANY4;
704 }
705 if (gw == NULL) {
706 gw = IP4_ADDR_ANY4;
707 }
708
709 remove = ip4_addr_isany(ipaddr);
710 if (remove) {
711 /* when removing an address, we have to remove it *before* changing netmask/gw
712 to ensure that tcp RST segment can be sent correctly */
713 if (netif_do_set_ipaddr(netif, ipaddr, &old_addr)) {
714#if LWIP_NETIF_EXT_STATUS_CALLBACK
715 change_reason |= LWIP_NSC_IPV4_ADDRESS_CHANGED;
716 cb_args.ipv4_changed.old_address = &old_addr;
717#endif
718 }
719 }
720 if (netif_do_set_netmask(netif, netmask, old_nm)) {
721#if LWIP_NETIF_EXT_STATUS_CALLBACK
722 change_reason |= LWIP_NSC_IPV4_NETMASK_CHANGED;
723 cb_args.ipv4_changed.old_netmask = old_nm;
724#endif
725 }
726 if (netif_do_set_gw(netif, gw, old_gw)) {
727#if LWIP_NETIF_EXT_STATUS_CALLBACK
728 change_reason |= LWIP_NSC_IPV4_GATEWAY_CHANGED;
729 cb_args.ipv4_changed.old_gw = old_gw;
730#endif
731 }
732 if (!remove) {
733 /* set ipaddr last to ensure netmask/gw have been set when status callback is called */
734 if (netif_do_set_ipaddr(netif, ipaddr, &old_addr)) {
735#if LWIP_NETIF_EXT_STATUS_CALLBACK
736 change_reason |= LWIP_NSC_IPV4_ADDRESS_CHANGED;
737 cb_args.ipv4_changed.old_address = &old_addr;
738#endif
739 }
740 }
741
742#if LWIP_NETIF_EXT_STATUS_CALLBACK
743 if (change_reason != LWIP_NSC_NONE) {
744 change_reason |= LWIP_NSC_IPV4_SETTINGS_CHANGED;
745 }
746 if (!remove) {
747 /* Issue a callback even if the address hasn't changed, eg. DHCP reboot */
748 change_reason |= LWIP_NSC_IPV4_ADDR_VALID;
749 }
750 if (change_reason != LWIP_NSC_NONE) {
751 netif_invoke_ext_callback(netif, change_reason, &cb_args);
752 }
753#endif
754}
755#endif /* LWIP_IPV4*/
756
763void
765{
766#if LWIP_IPV6
767 int i;
768#endif
769
771
772 if (netif == NULL) {
773 return;
774 }
775
777
778#if LWIP_IPV4
779 if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) {
780 netif_do_ip_addr_changed(netif_ip_addr4(netif), NULL);
781 }
782
783#if LWIP_IGMP
784 /* stop IGMP processing */
785 if (netif->flags & NETIF_FLAG_IGMP) {
786 igmp_stop(netif);
787 }
788#endif /* LWIP_IGMP */
789#endif /* LWIP_IPV4*/
790
791#if LWIP_IPV6
792 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
793 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) {
794 netif_do_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
795 }
796 }
797#if LWIP_IPV6_MLD
798 /* stop MLD processing */
799 mld6_stop(netif);
800#endif /* LWIP_IPV6_MLD */
801#endif /* LWIP_IPV6 */
802 if (netif_is_up(netif)) {
803 /* set netif down before removing (call callback function) */
805 }
806
808
809 /* this netif is default? */
810 if (netif_default == netif) {
811 /* reset default netif */
813 }
814#if !LWIP_SINGLE_NETIF
815 /* is it the first netif? */
816 if (netif_list == netif) {
818 } else {
819 /* look for netif further down the list */
820 struct netif *tmp_netif;
821 NETIF_FOREACH(tmp_netif) {
822 if (tmp_netif->next == netif) {
823 tmp_netif->next = netif->next;
824 break;
825 }
826 }
827 if (tmp_netif == NULL) {
828 return; /* netif is not on the list */
829 }
830 }
831#endif /* !LWIP_SINGLE_NETIF */
833#if LWIP_NETIF_REMOVE_CALLBACK
834 if (netif->remove_callback) {
835 netif->remove_callback(netif);
836 }
837#endif /* LWIP_NETIF_REMOVE_CALLBACK */
838 LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") );
839}
840
848void
850{
852
853 if (netif == NULL) {
854 /* remove default route */
856 } else {
857 /* install default route */
859 }
861 LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n",
862 netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));
863}
864
870void
872{
874
875 LWIP_ERROR("netif_set_up: invalid netif", netif != NULL, return);
876
877 if (!(netif->flags & NETIF_FLAG_UP)) {
879
881
883
884#if LWIP_NETIF_EXT_STATUS_CALLBACK
885 {
887 args.status_changed.state = 1;
889 }
890#endif
891
893#if LWIP_IPV6
894 nd6_restart_netif(netif);
895#endif /* LWIP_IPV6 */
896 }
897}
898
901static void
903{
904 LWIP_ASSERT("netif_issue_reports: invalid netif", netif != NULL);
905
906 /* Only send reports when both link and admin states are up */
907 if (!(netif->flags & NETIF_FLAG_LINK_UP) ||
908 !(netif->flags & NETIF_FLAG_UP)) {
909 return;
910 }
911
912#if LWIP_IPV4
914 !ip4_addr_isany_val(*netif_ip4_addr(netif))) {
915#if LWIP_ARP && !LWIP_ACD
916 /* For Ethernet network interfaces:
917 * we would like to send a "gratuitous ARP".
918 * Only needs to be done here if ACD isn't configured.
919 */
920 if (netif->flags & (NETIF_FLAG_ETHARP)) {
921 etharp_gratuitous(netif);
922 }
923#endif /* LWIP_ARP */
924
925#if LWIP_IGMP
926 /* resend IGMP memberships */
927 if (netif->flags & NETIF_FLAG_IGMP) {
928 igmp_report_groups(netif);
929 }
930#endif /* LWIP_IGMP */
931 }
932#endif /* LWIP_IPV4 */
933
934#if LWIP_IPV6
936#if LWIP_IPV6_MLD
937 /* send mld memberships */
938 mld6_report_groups(netif);
939#endif /* LWIP_IPV6_MLD */
940 }
941#endif /* LWIP_IPV6 */
942}
943
948void
950{
952
953 LWIP_ERROR("netif_set_down: invalid netif", netif != NULL, return);
954
955 if (netif->flags & NETIF_FLAG_UP) {
956#if LWIP_NETIF_EXT_STATUS_CALLBACK
957 {
959 args.status_changed.state = 0;
961 }
962#endif
963
966
967#if LWIP_IPV4 && LWIP_ARP
969 etharp_cleanup_netif(netif);
970 }
971#endif /* LWIP_IPV4 && LWIP_ARP */
972
973#if LWIP_IPV6
974 nd6_cleanup_netif(netif);
975#endif /* LWIP_IPV6 */
976
978 }
979}
980
981#if LWIP_NETIF_STATUS_CALLBACK
986void
987netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback)
988{
990
991 if (netif) {
992 netif->status_callback = status_callback;
993 }
994}
995#endif /* LWIP_NETIF_STATUS_CALLBACK */
996
997#if LWIP_NETIF_REMOVE_CALLBACK
1002void
1003netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback)
1004{
1006
1007 if (netif) {
1008 netif->remove_callback = remove_callback;
1009 }
1010}
1011#endif /* LWIP_NETIF_REMOVE_CALLBACK */
1012
1017void
1019{
1021
1022 LWIP_ERROR("netif_set_link_up: invalid netif", netif != NULL, return);
1023
1024 if (!(netif->flags & NETIF_FLAG_LINK_UP)) {
1026
1027#if LWIP_DHCP
1028 dhcp_network_changed_link_up(netif);
1029#endif /* LWIP_DHCP */
1030
1031#if LWIP_AUTOIP
1032 autoip_network_changed_link_up(netif);
1033#endif /* LWIP_AUTOIP */
1034
1036#if LWIP_IPV6
1037 nd6_restart_netif(netif);
1038#endif /* LWIP_IPV6 */
1039
1041#if LWIP_NETIF_EXT_STATUS_CALLBACK
1042 {
1044 args.link_changed.state = 1;
1046 }
1047#endif
1048 }
1049}
1050
1055void
1057{
1059
1060 LWIP_ERROR("netif_set_link_down: invalid netif", netif != NULL, return);
1061
1064
1065#if LWIP_AUTOIP
1066 autoip_network_changed_link_down(netif);
1067#endif /* LWIP_AUTOIP */
1068
1069#if LWIP_ACD
1070 acd_network_changed_link_down(netif);
1071#endif /* LWIP_ACD */
1072
1073#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES
1074 netif->mtu6 = netif->mtu;
1075#endif
1076
1078#if LWIP_NETIF_EXT_STATUS_CALLBACK
1079 {
1081 args.link_changed.state = 0;
1083 }
1084#endif
1085 }
1086}
1087
1088#if LWIP_NETIF_LINK_CALLBACK
1093void
1094netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback)
1095{
1097
1098 if (netif) {
1099 netif->link_callback = link_callback;
1100 }
1101}
1102#endif /* LWIP_NETIF_LINK_CALLBACK */
1103
1104#if ENABLE_LOOPBACK
1120err_t
1121netif_loop_output(struct netif *netif, struct pbuf *p)
1122{
1123 struct pbuf *r;
1124 err_t err;
1125 struct pbuf *last;
1126#if LWIP_LOOPBACK_MAX_PBUFS
1127 u16_t clen = 0;
1128#endif /* LWIP_LOOPBACK_MAX_PBUFS */
1129 /* If we have a loopif, SNMP counters are adjusted for it,
1130 * if not they are adjusted for 'netif'. */
1131#if MIB2_STATS
1132#if LWIP_HAVE_LOOPIF
1133 struct netif *stats_if = &loop_netif;
1134#else /* LWIP_HAVE_LOOPIF */
1135 struct netif *stats_if = netif;
1136#endif /* LWIP_HAVE_LOOPIF */
1137#endif /* MIB2_STATS */
1138#if LWIP_NETIF_LOOPBACK_MULTITHREADING
1139 u8_t schedule_poll = 0;
1140#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
1142
1143 LWIP_ASSERT("netif_loop_output: invalid netif", netif != NULL);
1144 LWIP_ASSERT("netif_loop_output: invalid pbuf", p != NULL);
1145
1146 /* Allocate a new pbuf */
1147 r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
1148 if (r == NULL) {
1149 LINK_STATS_INC(link.memerr);
1150 LINK_STATS_INC(link.drop);
1151 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards);
1152 return ERR_MEM;
1153 }
1154#if LWIP_LOOPBACK_MAX_PBUFS
1155 clen = pbuf_clen(r);
1156 /* check for overflow or too many pbuf on queue */
1157 if (((netif->loop_cnt_current + clen) < netif->loop_cnt_current) ||
1158 ((netif->loop_cnt_current + clen) > LWIP_MIN(LWIP_LOOPBACK_MAX_PBUFS, 0xFFFF))) {
1159 pbuf_free(r);
1160 LINK_STATS_INC(link.memerr);
1161 LINK_STATS_INC(link.drop);
1162 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards);
1163 return ERR_MEM;
1164 }
1165 netif->loop_cnt_current = (u16_t)(netif->loop_cnt_current + clen);
1166#endif /* LWIP_LOOPBACK_MAX_PBUFS */
1167
1168 /* Copy the whole pbuf queue p into the single pbuf r */
1169 if ((err = pbuf_copy(r, p)) != ERR_OK) {
1170 pbuf_free(r);
1171 LINK_STATS_INC(link.memerr);
1172 LINK_STATS_INC(link.drop);
1173 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards);
1174 return err;
1175 }
1176
1177 /* Put the packet on a linked list which gets emptied through calling
1178 netif_poll(). */
1179
1180 /* let last point to the last pbuf in chain r */
1181 for (last = r; last->next != NULL; last = last->next) {
1182 /* nothing to do here, just get to the last pbuf */
1183 }
1184
1185 SYS_ARCH_PROTECT(lev);
1186 if (netif->loop_first != NULL) {
1187 LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL);
1188 netif->loop_last->next = r;
1189 netif->loop_last = last;
1190#if LWIP_NETIF_LOOPBACK_MULTITHREADING
1191 if (netif->reschedule_poll) {
1192 schedule_poll = 1;
1193 netif->reschedule_poll = 0;
1194 }
1195#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
1196 } else {
1197 netif->loop_first = r;
1198 netif->loop_last = last;
1199#if LWIP_NETIF_LOOPBACK_MULTITHREADING
1200 /* No existing packets queued, schedule poll */
1201 schedule_poll = 1;
1202#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
1203 }
1204 SYS_ARCH_UNPROTECT(lev);
1205
1206 LINK_STATS_INC(link.xmit);
1207 MIB2_STATS_NETIF_ADD(stats_if, ifoutoctets, p->tot_len);
1208 MIB2_STATS_NETIF_INC(stats_if, ifoutucastpkts);
1209
1210#if LWIP_NETIF_LOOPBACK_MULTITHREADING
1211 /* For multithreading environment, schedule a call to netif_poll */
1212 if (schedule_poll) {
1213 if (tcpip_try_callback((tcpip_callback_fn)netif_poll, netif) != ERR_OK) {
1214 SYS_ARCH_PROTECT(lev);
1215 netif->reschedule_poll = 1;
1216 SYS_ARCH_UNPROTECT(lev);
1217 }
1218 }
1219#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
1220
1221 return ERR_OK;
1222}
1223
1224#if LWIP_HAVE_LOOPIF
1225#if LWIP_IPV4
1226static err_t
1227netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr)
1228{
1230 return netif_loop_output(netif, p);
1231}
1232#endif /* LWIP_IPV4 */
1233
1234#if LWIP_IPV6
1235static err_t
1236netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr)
1237{
1239 return netif_loop_output(netif, p);
1240}
1241#endif /* LWIP_IPV6 */
1242#endif /* LWIP_HAVE_LOOPIF */
1243
1244
1251void
1252netif_poll(struct netif *netif)
1253{
1254 /* If we have a loopif, SNMP counters are adjusted for it,
1255 * if not they are adjusted for 'netif'. */
1256#if MIB2_STATS
1257#if LWIP_HAVE_LOOPIF
1258 struct netif *stats_if = &loop_netif;
1259#else /* LWIP_HAVE_LOOPIF */
1260 struct netif *stats_if = netif;
1261#endif /* LWIP_HAVE_LOOPIF */
1262#endif /* MIB2_STATS */
1264
1265 LWIP_ASSERT("netif_poll: invalid netif", netif != NULL);
1266
1267 /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
1268 SYS_ARCH_PROTECT(lev);
1269 while (netif->loop_first != NULL) {
1270 struct pbuf *in, *in_end;
1271#if LWIP_LOOPBACK_MAX_PBUFS
1272 u8_t clen = 1;
1273#endif /* LWIP_LOOPBACK_MAX_PBUFS */
1274
1275 in = in_end = netif->loop_first;
1276 while (in_end->len != in_end->tot_len) {
1277 LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
1278 in_end = in_end->next;
1279#if LWIP_LOOPBACK_MAX_PBUFS
1280 clen++;
1281#endif /* LWIP_LOOPBACK_MAX_PBUFS */
1282 }
1283#if LWIP_LOOPBACK_MAX_PBUFS
1284 /* adjust the number of pbufs on queue */
1285 LWIP_ASSERT("netif->loop_cnt_current underflow",
1286 ((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
1287 netif->loop_cnt_current = (u16_t)(netif->loop_cnt_current - clen);
1288#endif /* LWIP_LOOPBACK_MAX_PBUFS */
1289
1290 /* 'in_end' now points to the last pbuf from 'in' */
1291 if (in_end == netif->loop_last) {
1292 /* this was the last pbuf in the list */
1293 netif->loop_first = netif->loop_last = NULL;
1294 } else {
1295 /* pop the pbuf off the list */
1296 netif->loop_first = in_end->next;
1297 LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
1298 }
1299 /* De-queue the pbuf from its successors on the 'loop_' list. */
1300 in_end->next = NULL;
1301 SYS_ARCH_UNPROTECT(lev);
1302
1303 in->if_idx = netif_get_index(netif);
1304
1305 LINK_STATS_INC(link.recv);
1306 MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len);
1307 MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts);
1308 /* loopback packets are always IP packets! */
1309 if (ip_input(in, netif) != ERR_OK) {
1310 pbuf_free(in);
1311 }
1312 SYS_ARCH_PROTECT(lev);
1313 }
1314 SYS_ARCH_UNPROTECT(lev);
1315}
1316
1317#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
1321void
1322netif_poll_all(void)
1323{
1324 struct netif *netif;
1325 /* loop through netifs */
1327 netif_poll(netif);
1328 }
1329}
1330#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
1331#endif /* ENABLE_LOOPBACK */
1332
1333#if LWIP_NUM_NETIF_CLIENT_DATA > 0
1340u8_t
1341netif_alloc_client_data_id(void)
1342{
1343 u8_t result = netif_client_id;
1344 netif_client_id++;
1345
1347
1348#if LWIP_NUM_NETIF_CLIENT_DATA > 256
1349#error LWIP_NUM_NETIF_CLIENT_DATA must be <= 256
1350#endif
1351 LWIP_ASSERT("Increase LWIP_NUM_NETIF_CLIENT_DATA in lwipopts.h", result < LWIP_NUM_NETIF_CLIENT_DATA);
1353}
1354#endif
1355
1356#if LWIP_IPV6
1367void
1368netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6)
1369{
1371
1372 LWIP_ASSERT("netif_ip6_addr_set: invalid netif", netif != NULL);
1373 LWIP_ASSERT("netif_ip6_addr_set: invalid addr6", addr6 != NULL);
1374
1375 netif_ip6_addr_set_parts(netif, addr_idx, addr6->addr[0], addr6->addr[1],
1376 addr6->addr[2], addr6->addr[3]);
1377}
1378
1379/*
1380 * Change an IPv6 address of a network interface (internal version taking 4 * u32_t)
1381 *
1382 * @param netif the network interface to change
1383 * @param addr_idx index of the IPv6 address
1384 * @param i0 word0 of the new IPv6 address
1385 * @param i1 word1 of the new IPv6 address
1386 * @param i2 word2 of the new IPv6 address
1387 * @param i3 word3 of the new IPv6 address
1388 */
1389void
1390netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3)
1391{
1392 ip_addr_t old_addr;
1393 ip_addr_t new_ipaddr;
1395 LWIP_ASSERT("netif != NULL", netif != NULL);
1396 LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES);
1397
1398 ip6_addr_copy(*ip_2_ip6(&old_addr), *netif_ip6_addr(netif, addr_idx));
1400
1401 /* address is actually being changed? */
1402 if ((ip_2_ip6(&old_addr)->addr[0] != i0) || (ip_2_ip6(&old_addr)->addr[1] != i1) ||
1403 (ip_2_ip6(&old_addr)->addr[2] != i2) || (ip_2_ip6(&old_addr)->addr[3] != i3)) {
1404 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set: netif address being changed\n"));
1405
1406 IP_ADDR6(&new_ipaddr, i0, i1, i2, i3);
1407 ip6_addr_assign_zone(ip_2_ip6(&new_ipaddr), IP6_UNICAST, netif);
1408
1409 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, addr_idx))) {
1410 netif_do_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
1411 }
1412 /* @todo: remove/readd mib2 ip6 entries? */
1413
1414 ip_addr_copy(netif->ip6_addr[addr_idx], new_ipaddr);
1415
1416 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, addr_idx))) {
1419 }
1420
1421#if LWIP_NETIF_EXT_STATUS_CALLBACK
1422 {
1424 args.ipv6_set.addr_index = addr_idx;
1425 args.ipv6_set.old_address = &old_addr;
1427 }
1428#endif
1429 }
1430
1431 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IPv6 address %d of interface %c%c set to %s/0x%"X8_F"\n",
1432 addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)),
1433 netif_ip6_addr_state(netif, addr_idx)));
1434}
1435
1446void
1447netif_ip6_addr_set_state(struct netif *netif, s8_t addr_idx, u8_t state)
1448{
1449 u8_t old_state;
1451 LWIP_ASSERT("netif != NULL", netif != NULL);
1452 LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES);
1453
1454 old_state = netif_ip6_addr_state(netif, addr_idx);
1455 /* state is actually being changed? */
1456 if (old_state != state) {
1457 u8_t old_valid = old_state & IP6_ADDR_VALID;
1458 u8_t new_valid = state & IP6_ADDR_VALID;
1459 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n"));
1460
1461#if LWIP_IPV6_MLD
1462 /* Reevaluate solicited-node multicast group membership. */
1463 if (netif->flags & NETIF_FLAG_MLD6) {
1464 nd6_adjust_mld_membership(netif, addr_idx, state);
1465 }
1466#endif /* LWIP_IPV6_MLD */
1467
1468 if (old_valid && !new_valid) {
1469 /* address about to be removed by setting invalid */
1470 netif_do_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
1471 /* @todo: remove mib2 ip6 entries? */
1472 }
1473 netif->ip6_addr_state[addr_idx] = state;
1474
1475 if (!old_valid && new_valid) {
1476 /* address added by setting valid */
1477 /* This is a good moment to check that the address is properly zoned. */
1478 IP6_ADDR_ZONECHECK_NETIF(netif_ip6_addr(netif, addr_idx), netif);
1479 /* @todo: add mib2 ip6 entries? */
1481 }
1482 if ((old_state & ~IP6_ADDR_TENTATIVE_COUNT_MASK) !=
1483 (state & ~IP6_ADDR_TENTATIVE_COUNT_MASK)) {
1484 /* address state has changed -> call the callback function */
1486 }
1487
1488#if LWIP_NETIF_EXT_STATUS_CALLBACK
1489 {
1491 args.ipv6_addr_state_changed.addr_index = addr_idx;
1492 args.ipv6_addr_state_changed.old_state = old_state;
1493 args.ipv6_addr_state_changed.address = netif_ip_addr6(netif, addr_idx);
1495 }
1496#endif
1497 }
1498 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IPv6 address %d of interface %c%c set to %s/0x%"X8_F"\n",
1499 addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)),
1500 netif_ip6_addr_state(netif, addr_idx)));
1501}
1502
1517s8_t
1518netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr)
1519{
1520 s8_t i;
1521
1523
1524 LWIP_ASSERT("netif_get_ip6_addr_match: invalid netif", netif != NULL);
1525 LWIP_ASSERT("netif_get_ip6_addr_match: invalid ip6addr", ip6addr != NULL);
1526
1527#if LWIP_IPV6_SCOPES
1528 if (ip6_addr_has_zone(ip6addr) && !ip6_addr_test_zone(ip6addr, netif)) {
1529 return -1; /* wrong zone, no match */
1530 }
1531#endif /* LWIP_IPV6_SCOPES */
1532
1533 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1534 if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) &&
1535 ip6_addr_zoneless_eq(netif_ip6_addr(netif, i), ip6addr)) {
1536 return i;
1537 }
1538 }
1539 return -1;
1540}
1541
1550void
1551netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit)
1552{
1553 u8_t i, addr_index;
1554
1556
1557 LWIP_ASSERT("netif_create_ip6_linklocal_address: invalid netif", netif != NULL);
1558
1559 /* Link-local prefix. */
1560 ip_2_ip6(&netif->ip6_addr[0])->addr[0] = PP_HTONL(0xfe800000ul);
1561 ip_2_ip6(&netif->ip6_addr[0])->addr[1] = 0;
1562
1563 /* Generate interface ID. */
1564 if (from_mac_48bit) {
1565 /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */
1566 ip_2_ip6(&netif->ip6_addr[0])->addr[2] = lwip_htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) |
1567 ((u32_t)(netif->hwaddr[1]) << 16) |
1568 ((u32_t)(netif->hwaddr[2]) << 8) |
1569 (0xff));
1570 ip_2_ip6(&netif->ip6_addr[0])->addr[3] = lwip_htonl((u32_t)(0xfeul << 24) |
1571 ((u32_t)(netif->hwaddr[3]) << 16) |
1572 ((u32_t)(netif->hwaddr[4]) << 8) |
1573 (netif->hwaddr[5]));
1574 } else {
1575 /* Use hwaddr directly as interface ID. */
1576 ip_2_ip6(&netif->ip6_addr[0])->addr[2] = 0;
1577 ip_2_ip6(&netif->ip6_addr[0])->addr[3] = 0;
1578
1579 addr_index = 3;
1580 for (i = 0; (i < 8) && (i < netif->hwaddr_len); i++) {
1581 if (i == 4) {
1582 addr_index--;
1583 }
1584 ip_2_ip6(&netif->ip6_addr[0])->addr[addr_index] |= lwip_htonl(((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03)));
1585 }
1586 }
1587
1588 /* Set a link-local zone. Even though the zone is implied by the owning
1589 * netif, setting the zone anyway has two important conceptual advantages:
1590 * 1) it avoids the need for a ton of exceptions in internal code, allowing
1591 * e.g. ip6_addr_eq() to be used on local addresses;
1592 * 2) the properly zoned address is visible externally, e.g. when any outside
1593 * code enumerates available addresses or uses one to bind a socket.
1594 * Any external code unaware of address scoping is likely to just ignore the
1595 * zone field, so this should not create any compatibility problems. */
1596 ip6_addr_assign_zone(ip_2_ip6(&netif->ip6_addr[0]), IP6_UNICAST, netif);
1597
1598 /* Set address state. */
1599#if LWIP_IPV6_DUP_DETECT_ATTEMPTS
1600 /* Will perform duplicate address detection (DAD). */
1601 netif_ip6_addr_set_state(netif, 0, IP6_ADDR_TENTATIVE);
1602#else
1603 /* Consider address valid. */
1604 netif_ip6_addr_set_state(netif, 0, IP6_ADDR_PREFERRED);
1605#endif /* LWIP_IPV6_AUTOCONFIG */
1606}
1607
1618err_t
1619netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx)
1620{
1621 s8_t i;
1622
1624
1625 LWIP_ASSERT("netif_add_ip6_address: invalid netif", netif != NULL);
1626 LWIP_ASSERT("netif_add_ip6_address: invalid ip6addr", ip6addr != NULL);
1627
1628 i = netif_get_ip6_addr_match(netif, ip6addr);
1629 if (i >= 0) {
1630 /* Address already added */
1631 if (chosen_idx != NULL) {
1632 *chosen_idx = i;
1633 }
1634 return ERR_OK;
1635 }
1636
1637 /* Find a free slot. The first one is reserved for link-local addresses. */
1638 for (i = ip6_addr_islinklocal(ip6addr) ? 0 : 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1639 if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) {
1640 ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr);
1641 ip6_addr_assign_zone(ip_2_ip6(&netif->ip6_addr[i]), IP6_UNICAST, netif);
1642 netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE);
1643 if (chosen_idx != NULL) {
1644 *chosen_idx = i;
1645 }
1646 return ERR_OK;
1647 }
1648 }
1649
1650 if (chosen_idx != NULL) {
1651 *chosen_idx = -1;
1652 }
1653 return ERR_VAL;
1654}
1655
1658static err_t
1659netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr)
1660{
1663 LWIP_UNUSED_ARG(ipaddr);
1664
1665 return ERR_IF;
1666}
1667#endif /* LWIP_IPV6 */
1668
1669#if LWIP_IPV4
1672static err_t
1673netif_null_output_ip4(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr)
1674{
1677 LWIP_UNUSED_ARG(ipaddr);
1678
1679 return ERR_IF;
1680}
1681#endif /* LWIP_IPV4 */
1682
1690u8_t
1692{
1693 struct netif *netif = netif_find(name);
1694 if (netif != NULL) {
1695 return netif_get_index(netif);
1696 }
1697 /* No name found, return invalid index */
1698 return NETIF_NO_INDEX;
1699}
1700
1709char *
1711{
1712 struct netif *netif = netif_get_by_index(idx);
1713
1714 if (netif != NULL) {
1715 name[0] = netif->name[0];
1716 name[1] = netif->name[1];
1718 return name;
1719 }
1720 return NULL;
1721}
1722
1729struct netif *
1731{
1732 struct netif *netif;
1733
1735
1736 if (idx != NETIF_NO_INDEX) {
1738 if (idx == netif_get_index(netif)) {
1739 return netif; /* found! */
1740 }
1741 }
1742 }
1743
1744 return NULL;
1745}
1746
1754struct netif *
1755netif_find(const char *name)
1756{
1757 struct netif *netif;
1758 u8_t num;
1759
1761
1762 if (name == NULL) {
1763 return NULL;
1764 }
1765
1766 num = (u8_t)atoi(&name[2]);
1767 if (!num && (name[2] != '0')) {
1768 /* this means atoi has failed */
1769 return NULL;
1770 }
1771
1773 if (num == netif->num &&
1774 name[0] == netif->name[0] &&
1775 name[1] == netif->name[1]) {
1776 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1]));
1777 return netif;
1778 }
1779 }
1780 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1]));
1781 return NULL;
1782}
1783
1784#if LWIP_NETIF_EXT_STATUS_CALLBACK
1791void
1793{
1795 LWIP_ASSERT("callback must be != NULL", callback != NULL);
1796 LWIP_ASSERT("fn must be != NULL", fn != NULL);
1797
1798 callback->callback_fn = fn;
1799 callback->next = ext_callback;
1800 ext_callback = callback;
1801}
1802
1808void
1809netif_remove_ext_callback(netif_ext_callback_t* callback)
1810{
1811 netif_ext_callback_t *last, *iter;
1812
1814 LWIP_ASSERT("callback must be != NULL", callback != NULL);
1815
1816 if (ext_callback == NULL) {
1817 return;
1818 }
1819
1820 if (callback == ext_callback) {
1821 ext_callback = ext_callback->next;
1822 } else {
1823 last = ext_callback;
1824 for (iter = ext_callback->next; iter != NULL; last = iter, iter = iter->next) {
1825 if (iter == callback) {
1826 LWIP_ASSERT("last != NULL", last != NULL);
1827 last->next = callback->next;
1828 break;
1829 }
1830 }
1831 }
1832 callback->next = NULL;
1833}
1834
1841void
1843{
1844 netif_ext_callback_t *callback = ext_callback;
1845
1846 LWIP_ASSERT("netif must be != NULL", netif != NULL);
1847
1848 while (callback != NULL) {
1849 /* cache next pointer: the callback might unregister itself */
1850 netif_ext_callback_t *next = callback->next;
1851 callback->callback_fn(netif, reason, args);
1852 callback = next;
1853 }
1854}
1855#endif /* LWIP_NETIF_EXT_STATUS_CALLBACK */
static int state
Definition: maze.c:121
const WCHAR * link
Definition: db.cpp:997
#define LWIP_MIN(x, y)
Definition: def.h:66
#define lwip_htonl(x)
Definition: def.h:88
#define PP_HTONL(x)
Definition: def.h:92
#define NULL
Definition: types.h:112
unsigned int idx
Definition: utils.c:41
static WCHAR reason[MAX_STRING_RESOURCE_LEN]
Definition: object.c:1904
#define SYS_ARCH_UNPROTECT(lev)
Definition: cc.h:39
#define SYS_ARCH_PROTECT(lev)
Definition: cc.h:38
#define SYS_ARCH_DECL_PROTECT(lev)
Definition: cc.h:37
#define U16_F
Definition: cc.h:19
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:158
#define LWIP_ERROR(message, expression, handler)
Definition: debug.h:130
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:116
#define MIB2_STATS_NETIF_ADD(n, x, val)
Definition: snmp.h:140
#define mib2_netif_added(ni)
Definition: snmp.h:177
#define MIB2_STATS_NETIF_INC(n, x)
Definition: snmp.h:139
#define mib2_add_route_ip4(dflt, ni)
Definition: snmp.h:187
#define MIB2_INIT_NETIF(netif, type, speed)
Definition: snmp.h:138
#define mib2_netif_removed(ni)
Definition: snmp.h:178
#define mib2_remove_route_ip4(dflt, ni)
Definition: snmp.h:188
#define MIB2_COPY_SYSUPTIME_TO(ptrToVal)
Definition: snmp.h:136
#define mib2_remove_ip4(ni)
Definition: snmp.h:186
#define mib2_add_ip4(ni)
Definition: snmp.h:185
void(* tcpip_callback_fn)(void *ctx)
Definition: tcpip.h:72
#define ERR_MEM
Definition: fontsub.h:52
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLuint in
Definition: glext.h:9616
GLenum const GLvoid * addr
Definition: glext.h:9621
GLfloat GLfloat p
Definition: glext.h:8902
GLuint GLuint num
Definition: glext.h:9618
GLenum GLenum GLenum input
Definition: glext.h:9031
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
uint32_t u32_t
Definition: arch.h:129
uint8_t u8_t
Definition: arch.h:125
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:373
uint16_t u16_t
Definition: arch.h:127
#define X8_F
Definition: arch.h:150
int8_t s8_t
Definition: arch.h:126
#define LWIP_DBG_STATE
Definition: debug.h:85
#define LWIP_DBG_TRACE
Definition: debug.h:83
s8_t err_t
Definition: err.h:96
@ ERR_IF
Definition: err.h:79
@ ERR_OK
Definition: err.h:55
@ ERR_VAL
Definition: err.h:67
@ IPADDR_TYPE_V6
Definition: ip_addr.h:58
@ IPADDR_TYPE_V4
Definition: ip_addr.h:56
err_t netif_input(struct pbuf *p, struct netif *inp)
Definition: netif.c:228
#define NETIF_DEBUG
Definition: opt.h:3336
#define LWIP_IPV4
Definition: opt.h:734
#define LWIP_IPV6_NUM_ADDRESSES
Definition: opt.h:2487
#define LWIP_ASSERT_CORE_LOCKED()
Definition: opt.h:227
#define LWIP_LOOPBACK_MAX_PBUFS
Definition: opt.h:1770
#define LWIP_NUM_NETIF_CLIENT_DATA
Definition: opt.h:1725
err_t tcpip_input(struct pbuf *p, struct netif *inp)
Definition: tcpip.c:288
err_t tcpip_try_callback(tcpip_callback_fn function, void *ctx)
Definition: tcpip.c:350
#define NETIF_FLAG_LINK_UP
Definition: netif.h:93
#define NETIF_FLAG_ETHERNET
Definition: netif.h:101
#define NETIF_FLAG_ETHARP
Definition: netif.h:97
#define NETIF_FLAG_MLD6
Definition: netif.h:107
#define NETIF_FLAG_UP
Definition: netif.h:84
#define NETIF_FLAG_IGMP
Definition: netif.h:104
char * netif_index_to_name(u8_t idx, char *name)
Definition: netif.c:1710
void netif_set_link_down(struct netif *netif)
Definition: netif.c:1056
struct netif * netif_find(const char *name)
Definition: netif.c:1755
void(* netif_ext_callback_fn)(struct netif *netif, netif_nsc_reason_t reason, const netif_ext_callback_args_t *args)
Definition: netif.h:668
void netif_set_down(struct netif *netif)
Definition: netif.c:949
#define netif_is_up(netif)
Definition: netif.h:479
void netif_remove(struct netif *netif)
Definition: netif.c:764
struct netif * netif_get_by_index(u8_t idx)
Definition: netif.c:1730
u16_t netif_nsc_reason_t
Definition: netif.h:586
struct netif * netif_add(struct netif *netif, void *state, netif_init_fn init, netif_input_fn input)
Definition: netif.c:287
u8_t netif_name_to_index(const char *name)
Definition: netif.c:1691
void netif_set_default(struct netif *netif)
Definition: netif.c:849
void netif_set_link_up(struct netif *netif)
Definition: netif.c:1018
void netif_set_up(struct netif *netif)
Definition: netif.c:871
struct netif * netif_add_noaddr(struct netif *netif, void *state, netif_init_fn init, netif_input_fn input)
Definition: netif.c:250
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:224
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:727
err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
Definition: pbuf.c:959
@ PBUF_RAM
Definition: pbuf.h:152
@ PBUF_LINK
Definition: pbuf.h:102
void lwip_itoa(char *result, size_t bufsize, int number)
Definition: def.c:222
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
#define ip_2_ip6(ipaddr)
Definition: ip_addr.h:356
#define ip_addr_copy(dest, src)
Definition: ip_addr.h:360
ip6_addr_t ip_addr_t
Definition: ip_addr.h:344
#define IP_ADDR6(ipaddr, i0, i1, i2, i3)
Definition: ip_addr.h:357
#define IP_SET_TYPE_VAL(ipaddr, iptype)
Definition: ip_addr.h:352
#define ip_addr_copy_from_ip6(dest, src)
Definition: ip_addr.h:361
#define IP_ADDR6_HOST(ipaddr, i0, i1, i2, i3)
Definition: ip_addr.h:358
#define ip_addr_set_zero_ip6(ipaddr)
Definition: ip_addr.h:366
static IPrintDialogCallback callback
Definition: printdlg.c:326
static UINT UINT last
Definition: font.c:45
static void WINAPI status_callback(HINTERNET handle, DWORD_PTR ctx, DWORD status, LPVOID info, DWORD info_len)
Definition: ftp.c:948
int remove
Definition: msacm.c:1366
void netif_init(void)
Definition: netif.c:188
static void netif_do_ip_addr_changed(const ip_addr_t *old_addr, const ip_addr_t *new_addr)
Definition: netif.c:459
struct netif * netif_list
Definition: netif.c:113
#define NETIF_REPORT_TYPE_IPV4
Definition: netif.c:124
struct netif * netif_default
Definition: netif.c:115
static u8_t netif_num
Definition: netif.c:118
#define netif_index_to_num(index)
Definition: netif.c:117
#define NETIF_STATUS_CALLBACK(n)
Definition: netif.c:99
#define NETIF_REPORT_TYPE_IPV6
Definition: netif.c:125
#define NETIF_LINK_CALLBACK(n)
Definition: netif.c:105
static void netif_issue_reports(struct netif *netif, u8_t report_type)
Definition: netif.c:902
#define LWIP_NSC_IPV6_ADDR_STATE_CHANGED
Definition: netif.h:611
#define LWIP_NSC_IPV4_GATEWAY_CHANGED
Definition: netif.h:603
err_t(* netif_init_fn)(struct netif *netif)
Definition: netif.h:171
#define NETIF_NAMESIZE
Definition: netif.h:70
#define netif_set_flags(netif, set_flags)
Definition: netif.h:470
#define LWIP_NSC_NONE
Definition: netif.h:589
void(* netif_status_callback_fn)(struct netif *netif)
Definition: netif.h:217
#define LWIP_NSC_IPV4_SETTINGS_CHANGED
Definition: netif.h:607
@ LWIP_NETIF_CLIENT_DATA_INDEX_MAX
Definition: netif.h:137
#define LWIP_NSC_LINK_CHANGED
Definition: netif.h:595
#define netif_invoke_ext_callback(netif, reason, args)
Definition: netif.h:686
#define LWIP_NSC_STATUS_CHANGED
Definition: netif.h:599
#define LWIP_NSC_IPV4_ADDR_VALID
Definition: netif.h:613
#define netif_add_ext_callback(callback, fn)
Definition: netif.h:684
#define LWIP_NSC_IPV6_SET
Definition: netif.h:609
#define NETIF_FOREACH(netif)
Definition: netif.h:424
#define NETIF_RESET_HINTS(netif)
Definition: netif.h:570
#define NETIF_NO_INDEX
Definition: netif.h:579
err_t(* netif_input_fn)(struct pbuf *p, struct netif *inp)
Definition: netif.h:181
#define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags)
Definition: netif.h:415
#define netif_get_index(netif)
Definition: netif.h:578
#define netif_clear_flags(netif, clr_flags)
Definition: netif.h:471
#define LWIP_NSC_IPV4_NETMASK_CHANGED
Definition: netif.h:605
#define LWIP_NSC_NETIF_ADDED
Definition: netif.h:591
#define netif_remove_ext_callback(callback)
Definition: netif.h:685
#define LWIP_NSC_NETIF_REMOVED
Definition: netif.h:593
#define LWIP_NSC_IPV4_ADDRESS_CHANGED
Definition: netif.h:601
u16_t pbuf_clen(const struct pbuf *p)
Definition: pbuf.c:811
static unsigned __int64 next
Definition: rand_nt.c:6
#define err(...)
#define memset(x, y, z)
Definition: compat.h:39
#define args
Definition: format.c:66
#define LINK_STATS_INC(x)
Definition: stats.h:384
Definition: match.c:390
Definition: name.c:39
Definition: netif.h:269
u8_t flags
Definition: netif.h:354
char name[2]
Definition: netif.h:356
void * state
Definition: netif.h:332
netif_input_fn input
Definition: netif.h:297
u8_t num
Definition: netif.h:359
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]
Definition: netif.h:350
u16_t mtu
Definition: netif.h:344
struct netif * next
Definition: netif.h:272
u8_t hwaddr_len
Definition: netif.h:352
Definition: pbuf.h:186
u16_t tot_len
Definition: pbuf.h:200
struct pbuf * next
Definition: pbuf.h:188
u16_t len
Definition: pbuf.h:203
struct netif_ext_callback_args_t::ipv4_changed_s ipv4_changed
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
report_type
Definition: winetest.h:46
static int init
Definition: wintirpc.c:33