sdk-core v2026.11.05
PS2 SDK - core tier (build-critical EE/IOP modules)
Loading...
Searching...
No Matches
netif.c
Go to the documentation of this file.
1
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/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)
118static u8_t netif_num;
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
180 netif_set_flags(netif, NETIF_FLAG_IGMP);
181#endif
182 NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_DISABLE_ALL);
183 return ERR_OK;
184}
185#endif /* LWIP_HAVE_LOOPIF */
186
187void
188netif_init(void)
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;
365 netif->num = netif_num;
366 netif->input = input;
367
368#if LWIP_ACD
369 netif->acd_list = NULL;
370#endif /* LWIP_ACD */
371 NETIF_RESET_HINTS(netif);
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 */
432 mib2_netif_added(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
453 netif_invoke_ext_callback(netif, LWIP_NSC_NETIF_ADDED, NULL);
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;
483 IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_V4);
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
494 mib2_remove_ip4(netif);
495 mib2_remove_route_ip4(0, netif);
496 /* set new IP address to netif */
497 ip4_addr_set(ip_2_ip4(&netif->ip_addr), ipaddr);
498 IP_SET_TYPE_VAL(netif->ip_addr, IPADDR_TYPE_V4);
499 mib2_add_ip4(netif);
500 mib2_add_route_ip4(0, netif);
501
502 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4);
503
504 NETIF_STATUS_CALLBACK(netif);
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;
538 netif_invoke_ext_callback(netif, LWIP_NSC_IPV4_ADDRESS_CHANGED, &args);
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
554 mib2_remove_route_ip4(0, netif);
555 /* set new netmask to netif */
556 ip4_addr_set(ip_2_ip4(&netif->netmask), netmask);
557 IP_SET_TYPE_VAL(netif->netmask, IPADDR_TYPE_V4);
558 mib2_add_route_ip4(0, netif);
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;
602 netif_invoke_ext_callback(netif, LWIP_NSC_IPV4_NETMASK_CHANGED, &args);
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);
620 IP_SET_TYPE_VAL(netif->gw, IPADDR_TYPE_V4);
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;
663 netif_invoke_ext_callback(netif, LWIP_NSC_IPV4_GATEWAY_CHANGED, &args);
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
776 netif_invoke_ext_callback(netif, LWIP_NSC_NETIF_REMOVED, NULL);
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
807 mib2_remove_ip4(netif);
808
809 /* this netif is default? */
810 if (netif_default == netif) {
811 /* reset default netif */
812 netif_set_default(NULL);
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 */
832 mib2_netif_removed(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 */
855 mib2_remove_route_ip4(1, netif);
856 } else {
857 /* install default route */
858 mib2_add_route_ip4(1, netif);
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)) {
878 netif_set_flags(netif, NETIF_FLAG_UP);
879
880 MIB2_COPY_SYSUPTIME_TO(&netif->ts);
881
882 NETIF_STATUS_CALLBACK(netif);
883
884#if LWIP_NETIF_EXT_STATUS_CALLBACK
885 {
887 args.status_changed.state = 1;
888 netif_invoke_ext_callback(netif, LWIP_NSC_STATUS_CHANGED, &args);
889 }
890#endif
891
892 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4 | NETIF_REPORT_TYPE_IPV6);
893#if LWIP_IPV6
894 nd6_restart_netif(netif);
895#endif /* LWIP_IPV6 */
896 }
897}
898
901static void
902netif_issue_reports(struct netif *netif, u8_t report_type)
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
913 if ((report_type & NETIF_REPORT_TYPE_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
935 if (report_type & NETIF_REPORT_TYPE_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;
960 netif_invoke_ext_callback(netif, LWIP_NSC_STATUS_CHANGED, &args);
961 }
962#endif
963
964 netif_clear_flags(netif, NETIF_FLAG_UP);
965 MIB2_COPY_SYSUPTIME_TO(&netif->ts);
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
977 NETIF_STATUS_CALLBACK(netif);
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)) {
1025 netif_set_flags(netif, 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
1035 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4 | NETIF_REPORT_TYPE_IPV6);
1036#if LWIP_IPV6
1037 nd6_restart_netif(netif);
1038#endif /* LWIP_IPV6 */
1039
1040 NETIF_LINK_CALLBACK(netif);
1041#if LWIP_NETIF_EXT_STATUS_CALLBACK
1042 {
1044 args.link_changed.state = 1;
1045 netif_invoke_ext_callback(netif, LWIP_NSC_LINK_CHANGED, &args);
1046 }
1047#endif
1048 }
1049}
1050
1055void
1057{
1059
1060 LWIP_ERROR("netif_set_link_down: invalid netif", netif != NULL, return);
1061
1063 netif_clear_flags(netif, NETIF_FLAG_LINK_UP);
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
1077 NETIF_LINK_CALLBACK(netif);
1078#if LWIP_NETIF_EXT_STATUS_CALLBACK
1079 {
1081 args.link_changed.state = 0;
1082 netif_invoke_ext_callback(netif, LWIP_NSC_LINK_CHANGED, &args);
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{
1229 LWIP_UNUSED_ARG(addr);
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{
1238 LWIP_UNUSED_ARG(addr);
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 */
1326 NETIF_FOREACH(netif) {
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);
1352 return (u8_t)(result + LWIP_NETIF_CLIENT_DATA_INDEX_MAX);
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));
1399 IP_SET_TYPE_VAL(old_addr, IPADDR_TYPE_V6);
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/re-add 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))) {
1417 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6);
1418 NETIF_STATUS_CALLBACK(netif);
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;
1426 netif_invoke_ext_callback(netif, LWIP_NSC_IPV6_SET, &args);
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? */
1480 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6);
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 */
1485 NETIF_STATUS_CALLBACK(netif);
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);
1494 netif_invoke_ext_callback(netif, LWIP_NSC_IPV6_ADDR_STATE_CHANGED, &args);
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{
1662 LWIP_UNUSED_ARG(p);
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{
1676 LWIP_UNUSED_ARG(p);
1677 LWIP_UNUSED_ARG(ipaddr);
1678
1679 return ERR_IF;
1680}
1681#endif /* LWIP_IPV4 */
1682
1690u8_t
1691netif_name_to_index(const char *name)
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 *
1710netif_index_to_name(u8_t idx, char *name)
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];
1717 lwip_itoa(&name[2], NETIF_NAMESIZE - 2, netif_index_to_num(idx));
1718 return name;
1719 }
1720 return NULL;
1721}
1722
1729struct netif *
1731{
1732 struct netif *netif;
1733
1735
1736 if (idx != NETIF_NO_INDEX) {
1737 NETIF_FOREACH(netif) {
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
1772 NETIF_FOREACH(netif) {
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
1792netif_add_ext_callback(netif_ext_callback_t *callback, netif_ext_callback_fn fn)
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
1842netif_invoke_ext_callback(struct netif *netif, netif_nsc_reason_t reason, const netif_ext_callback_args_t *args)
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 */
struct netif * netif_list
Definition netif.c:113
#define ip4_addr_set(dest, src)
Definition tcpip.h:344
void(*) netif_status_callback_fn(struct netif *netif)
Definition tcpip.h:1243
struct netif * netif_default
Definition netif.c:115
#define IP4_ADDR(ipaddr, a, b, c, d)
Definition tcpip.h:328
err_t(*) netif_input_fn(struct pbuf *p, struct netif *inp)
Definition tcpip.h:1207
#define ip6_addr_copy(dest, src)
Definition tcpip.h:473
struct ip6_addr ip6_addr_t
Definition tcpip.h:434
err_t(*) netif_init_fn(struct netif *netif)
Definition tcpip.h:1200
#define LWIP_UNUSED_ARG(x)
Definition arch.h:373
err_t netif_input(struct pbuf *p, struct netif *inp)
Definition netif.c:228
err_t tcpip_input(struct pbuf *p, struct netif *inp)
Definition tcpip.c:297
err_t tcpip_try_callback(tcpip_callback_fn function, void *ctx)
Definition tcpip.c:359
#define LWIP_DBG_STATE
Definition debug.h:85
#define LWIP_DBG_TRACE
Definition debug.h:83
@ ERR_IF
Definition err.h:79
@ ERR_OK
Definition err.h:55
@ ERR_VAL
Definition err.h:67
@ ERR_MEM
Definition err.h:57
#define IP4_ADDR_ANY4
Definition tcpip.h:1059
#define IP4_ADDR_ANY
Definition tcpip.h:1053
@ IPADDR_TYPE_V6
Definition tcpip.h:684
@ IPADDR_TYPE_V4
Definition tcpip.h:682
#define NETIF_DEBUG
Definition opt.h:3366
#define LWIP_IPV6_NUM_ADDRESSES
Definition opt.h:2517
#define LWIP_ASSERT_CORE_LOCKED()
Definition opt.h:227
#define NETIF_FLAG_LINK_UP
Definition tcpip.h:1133
#define NETIF_FLAG_ETHERNET
Definition tcpip.h:1141
#define NETIF_FLAG_ETHARP
Definition tcpip.h:1137
#define NETIF_FLAG_MLD6
Definition tcpip.h:1147
#define NETIF_FLAG_UP
Definition tcpip.h:1124
#define NETIF_FLAG_IGMP
Definition tcpip.h:1144
char * netif_index_to_name(u8_t idx, char *name)
Definition netif.c:1710
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_link_down(struct netif *netif)
Definition netif.c:1056
struct netif * netif_find(const char *name)
Definition netif.c:1755
void netif_set_down(struct netif *netif)
Definition netif.c:949
#define netif_is_up(netif)
Definition tcpip.h:1423
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
u8 pbuf_free(struct pbuf *p)
Definition pbuf.c:729
err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
Definition pbuf.c:962
@ PBUF_RAM
Definition tcpip.h:214
@ PBUF_LINK
Definition tcpip.h:191
void lwip_itoa(char *result, size_t bufsize, int number)
Definition def.c:222
#define LWIP_NSC_IPV6_ADDR_STATE_CHANGED
Definition netif.h:611
#define LWIP_NSC_IPV4_GATEWAY_CHANGED
Definition netif.h:603
#define NETIF_NAMESIZE
Definition netif.h:70
#define LWIP_NSC_IPV4_SETTINGS_CHANGED
Definition netif.h:607
#define LWIP_NSC_LINK_CHANGED
Definition netif.h:595
#define LWIP_NSC_STATUS_CHANGED
Definition netif.h:599
#define LWIP_NSC_IPV4_ADDR_VALID
Definition netif.h:613
#define LWIP_NSC_IPV6_SET
Definition netif.h:609
#define LWIP_NSC_IPV4_NETMASK_CHANGED
Definition netif.h:605
#define LWIP_NSC_NETIF_ADDED
Definition netif.h:591
#define LWIP_NSC_NETIF_REMOVED
Definition netif.h:593
#define LWIP_NSC_IPV4_ADDRESS_CHANGED
Definition netif.h:601
void(*) tcpip_callback_fn(void *ctx)
Definition ps2ip.h:74
struct ip4_addr ip4_addr_t
Definition ps2ip_rpc.h:41
u8 hwaddr_len
Definition tcpip.h:1347
u8 num
Definition tcpip.h:1355
netif_output_fn output
Definition tcpip.h:1296
netif_input_fn input
Definition tcpip.h:1290
ip_addr_t ip_addr
Definition tcpip.h:1277
char name[2]
Definition tcpip.h:1353
u8 hwaddr[NETIF_MAX_HWADDR_LEN]
Definition tcpip.h:1349
u8 flags
Definition tcpip.h:1351
void * state
Definition tcpip.h:1325
struct netif * next
Definition tcpip.h:1273
u16 mtu
Definition tcpip.h:1345
Definition tcpip.h:234
struct pbuf * next
Definition tcpip.h:236
u16 tot_len
Definition tcpip.h:248
u16 len
Definition tcpip.h:251
#define SYS_ARCH_DECL_PROTECT(lev)
Definition sys.h:512