The Pedigree Project 0.1
netif.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
39/*
40 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
41 * All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without modification,
44 * are permitted provided that the following conditions are met:
45 *
46 * 1. Redistributions of source code must retain the above copyright notice,
47 * this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright notice,
49 * this list of conditions and the following disclaimer in the documentation
50 * and/or other materials provided with the distribution.
51 * 3. The name of the author may not be used to endorse or promote products
52 * derived from this software without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
55 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
56 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
57 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
58 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
59 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
61 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
62 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
63 * OF SUCH DAMAGE.
64 *
65 * This file is part of the lwIP TCP/IP stack.
66 *
67 * Author: Adam Dunkels <adam@sics.se>
68 */
69
70#include "lwip/opt.h"
71
72#include <string.h>
73
74#include "lwip/def.h"
75#include "lwip/ip_addr.h"
76#include "lwip/ip6_addr.h"
77#include "lwip/netif.h"
78#include "lwip/priv/tcp_priv.h"
79#include "lwip/udp.h"
80#include "lwip/raw.h"
81#include "lwip/snmp.h"
82#include "lwip/igmp.h"
83#include "lwip/etharp.h"
84#include "lwip/stats.h"
85#include "lwip/sys.h"
86#include "lwip/ip.h"
87#if ENABLE_LOOPBACK
88#if LWIP_NETIF_LOOPBACK_MULTITHREADING
89#include "lwip/tcpip.h"
90#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
91#endif /* ENABLE_LOOPBACK */
92
93#include "netif/ethernet.h"
94
95#if LWIP_AUTOIP
96#include "lwip/autoip.h"
97#endif /* LWIP_AUTOIP */
98#if LWIP_DHCP
99#include "lwip/dhcp.h"
100#endif /* LWIP_DHCP */
101#if LWIP_IPV6_DHCP6
102#include "lwip/dhcp6.h"
103#endif /* LWIP_IPV6_DHCP6 */
104#if LWIP_IPV6_MLD
105#include "lwip/mld6.h"
106#endif /* LWIP_IPV6_MLD */
107#if LWIP_IPV6
108#include "lwip/nd6.h"
109#endif
110
111#if LWIP_NETIF_STATUS_CALLBACK
112#define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0)
113#else
114#define NETIF_STATUS_CALLBACK(n)
115#endif /* LWIP_NETIF_STATUS_CALLBACK */
116
117#if LWIP_NETIF_LINK_CALLBACK
118#define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0)
119#else
120#define NETIF_LINK_CALLBACK(n)
121#endif /* LWIP_NETIF_LINK_CALLBACK */
122
125
126static u8_t netif_num;
127
128#if LWIP_NUM_NETIF_CLIENT_DATA > 0
129static u8_t netif_client_id;
130#endif
131
132#define NETIF_REPORT_TYPE_IPV4 0x01
133#define NETIF_REPORT_TYPE_IPV6 0x02
134static void netif_issue_reports(struct netif* netif, u8_t report_type);
135
136#if LWIP_IPV6
137static err_t netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr);
138#endif /* LWIP_IPV6 */
139
140#if LWIP_HAVE_LOOPIF
141#if LWIP_IPV4
142static err_t netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t* addr);
143#endif
144#if LWIP_IPV6
145static err_t netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* addr);
146#endif
147
148
149static struct netif loop_netif;
150
158static err_t
159netif_loopif_init(struct netif *netif)
160{
161 /* initialize the snmp variables and counters inside the struct netif
162 * ifSpeed: no assumption can be made!
163 */
164 MIB2_INIT_NETIF(netif, snmp_ifType_softwareLoopback, 0);
165
166 netif->name[0] = 'l';
167 netif->name[1] = 'o';
168#if LWIP_IPV4
169 netif->output = netif_loop_output_ipv4;
170#endif
171#if LWIP_IPV6
172 netif->output_ip6 = netif_loop_output_ipv6;
173#endif
174#if LWIP_LOOPIF_MULTICAST
176#endif
177 return ERR_OK;
178}
179#endif /* LWIP_HAVE_LOOPIF */
180
181void
182netif_init(void)
183{
184#if LWIP_HAVE_LOOPIF
185#if LWIP_IPV4
186#define LOOPIF_ADDRINIT &loop_ipaddr, &loop_netmask, &loop_gw,
187 ip4_addr_t loop_ipaddr, loop_netmask, loop_gw;
188 IP4_ADDR(&loop_gw, 127,0,0,1);
189 IP4_ADDR(&loop_ipaddr, 127,0,0,1);
190 IP4_ADDR(&loop_netmask, 255,0,0,0);
191#else /* LWIP_IPV4 */
192#define LOOPIF_ADDRINIT
193#endif /* LWIP_IPV4 */
194
195#if NO_SYS
196 netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, ip_input);
197#else /* NO_SYS */
198 netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, tcpip_input);
199#endif /* NO_SYS */
200
201#if LWIP_IPV6
202 IP_ADDR6_HOST(loop_netif.ip6_addr, 0, 0, 0, 0x00000001UL);
203 loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID;
204#endif /* LWIP_IPV6 */
205
206 netif_set_link_up(&loop_netif);
207 netif_set_up(&loop_netif);
208
209#endif /* LWIP_HAVE_LOOPIF */
210}
211
221err_t
222netif_input(struct pbuf *p, struct netif *inp)
223{
224#if LWIP_ETHERNET
226 return ethernet_input(p, inp);
227 } else
228#endif /* LWIP_ETHERNET */
229 return ip_input(p, inp);
230}
231
259struct netif *
261#if LWIP_IPV4
262 const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw,
263#endif /* LWIP_IPV4 */
265{
266#if LWIP_IPV6
267 s8_t i;
268#endif
269
270 LWIP_ASSERT("No init function given", init != NULL);
271
272 /* reset new interface configuration state */
273#if LWIP_IPV4
274 ip_addr_set_zero_ip4(&netif->ip_addr);
275 ip_addr_set_zero_ip4(&netif->netmask);
276 ip_addr_set_zero_ip4(&netif->gw);
277#endif /* LWIP_IPV4 */
278#if LWIP_IPV6
279 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
280 ip_addr_set_zero_ip6(&netif->ip6_addr[i]);
281 netif->ip6_addr_state[i] = IP6_ADDR_INVALID;
282 }
283 netif->output_ip6 = netif_null_output_ip6;
284#endif /* LWIP_IPV6 */
285 NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL);
286 netif->flags = 0;
287#ifdef netif_get_client_data
288 memset(netif->client_data, 0, sizeof(netif->client_data));
289#endif /* LWIP_NUM_NETIF_CLIENT_DATA */
290#if LWIP_IPV6_AUTOCONFIG
291 /* IPv6 address autoconfiguration not enabled by default */
292 netif->ip6_autoconfig_enabled = 0;
293#endif /* LWIP_IPV6_AUTOCONFIG */
294#if LWIP_IPV6_SEND_ROUTER_SOLICIT
296#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
297#if LWIP_NETIF_STATUS_CALLBACK
298 netif->status_callback = NULL;
299#endif /* LWIP_NETIF_STATUS_CALLBACK */
300#if LWIP_NETIF_LINK_CALLBACK
301 netif->link_callback = NULL;
302#endif /* LWIP_NETIF_LINK_CALLBACK */
303#if LWIP_IGMP
304 netif->igmp_mac_filter = NULL;
305#endif /* LWIP_IGMP */
306#if LWIP_IPV6 && LWIP_IPV6_MLD
307 netif->mld_mac_filter = NULL;
308#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
309#if ENABLE_LOOPBACK
310 netif->loop_first = NULL;
311 netif->loop_last = NULL;
312#endif /* ENABLE_LOOPBACK */
313
314 /* remember netif specific state information data */
315 netif->state = state;
316 netif->num = netif_num++;
317 netif->input = input;
318
319 NETIF_SET_HWADDRHINT(netif, NULL);
320#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS
321 netif->loop_cnt_current = 0;
322#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */
323
324#if LWIP_IPV4
325 netif_set_addr(netif, ipaddr, netmask, gw);
326#endif /* LWIP_IPV4 */
327
328 /* call user specified initialization function for netif */
329 if (init(netif) != ERR_OK) {
330 return NULL;
331 }
332
333 /* add this netif to the list */
336 mib2_netif_added(netif);
337
338#if LWIP_IGMP
339 /* start IGMP processing */
340 if (netif->flags & NETIF_FLAG_IGMP) {
341 igmp_start(netif);
342 }
343#endif /* LWIP_IGMP */
344
345 LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP",
346 netif->name[0], netif->name[1]));
347#if LWIP_IPV4
348 LWIP_DEBUGF(NETIF_DEBUG, (" addr "));
349 ip4_addr_debug_print(NETIF_DEBUG, ipaddr);
350 LWIP_DEBUGF(NETIF_DEBUG, (" netmask "));
351 ip4_addr_debug_print(NETIF_DEBUG, netmask);
352 LWIP_DEBUGF(NETIF_DEBUG, (" gw "));
353 ip4_addr_debug_print(NETIF_DEBUG, gw);
354#endif /* LWIP_IPV4 */
355 LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
356 return netif;
357}
358
359#if LWIP_IPV4
370void
371netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask,
372 const ip4_addr_t *gw)
373{
374 if (ip4_addr_isany(ipaddr)) {
375 /* when removing an address, we have to remove it *before* changing netmask/gw
376 to ensure that tcp RST segment can be sent correctly */
377 netif_set_ipaddr(netif, ipaddr);
378 netif_set_netmask(netif, netmask);
379 netif_set_gw(netif, gw);
380 } else {
381 netif_set_netmask(netif, netmask);
382 netif_set_gw(netif, gw);
383 /* set ipaddr last to ensure netmask/gw have been set when status callback is called */
384 netif_set_ipaddr(netif, ipaddr);
385 }
386}
387#endif /* LWIP_IPV4*/
388
395void
397{
398#if LWIP_IPV6
399 int i;
400#endif
401
402 if (netif == NULL) {
403 return;
404 }
405
406#if LWIP_IPV4
407 if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) {
408#if LWIP_TCP
409 tcp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL);
410#endif /* LWIP_TCP */
411#if LWIP_UDP
412 udp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL);
413#endif /* LWIP_UDP */
414#if LWIP_RAW
415 raw_netif_ip_addr_changed(netif_ip_addr4(netif), NULL);
416#endif /* LWIP_RAW */
417 }
418
419#if LWIP_IGMP
420 /* stop IGMP processing */
421 if (netif->flags & NETIF_FLAG_IGMP) {
422 igmp_stop(netif);
423 }
424#endif /* LWIP_IGMP */
425#endif /* LWIP_IPV4*/
426
427#if LWIP_IPV6
428 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
429 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) {
430#if LWIP_TCP
431 tcp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
432#endif /* LWIP_TCP */
433#if LWIP_UDP
434 udp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
435#endif /* LWIP_UDP */
436#if LWIP_RAW
437 raw_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
438#endif /* LWIP_RAW */
439 }
440 }
441#if LWIP_IPV6_MLD
442 /* stop MLD processing */
443 mld6_stop(netif);
444#endif /* LWIP_IPV6_MLD */
445#endif /* LWIP_IPV6 */
446 if (netif_is_up(netif)) {
447 /* set netif down before removing (call callback function) */
449 }
450
451 mib2_remove_ip4(netif);
452
453 /* this netif is default? */
454 if (netif_default == netif) {
455 /* reset default netif */
456 netif_set_default(NULL);
457 }
458 /* is it the first netif? */
459 if (netif_list == netif) {
461 } else {
462 /* look for netif further down the list */
463 struct netif * tmp_netif;
464 for (tmp_netif = netif_list; tmp_netif != NULL; tmp_netif = tmp_netif->next) {
465 if (tmp_netif->next == netif) {
466 tmp_netif->next = netif->next;
467 break;
468 }
469 }
470 if (tmp_netif == NULL) {
471 return; /* netif is not on the list */
472 }
473 }
474 mib2_netif_removed(netif);
475#if LWIP_NETIF_REMOVE_CALLBACK
476 if (netif->remove_callback) {
477 netif->remove_callback(netif);
478 }
479#endif /* LWIP_NETIF_REMOVE_CALLBACK */
480 LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") );
481}
482
490struct netif *
491netif_find(const char *name)
492{
493 struct netif *netif;
494 u8_t num;
495
496 if (name == NULL) {
497 return NULL;
498 }
499
500 num = (u8_t)(name[2] - '0');
501
502 for (netif = netif_list; netif != NULL; netif = netif->next) {
503 if (num == netif->num &&
504 name[0] == netif->name[0] &&
505 name[1] == netif->name[1]) {
506 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1]));
507 return netif;
508 }
509 }
510 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1]));
511 return NULL;
512}
513
514#if LWIP_IPV4
525void
526netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr)
527{
528 ip_addr_t new_addr;
529 *ip_2_ip4(&new_addr) = (ipaddr ? *ipaddr : *IP4_ADDR_ANY4);
530 IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_V4);
531
532 /* address is actually being changed? */
533 if (ip4_addr_cmp(ip_2_ip4(&new_addr), netif_ip4_addr(netif)) == 0) {
534 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n"));
535#if LWIP_TCP
536 tcp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr);
537#endif /* LWIP_TCP */
538#if LWIP_UDP
539 udp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr);
540#endif /* LWIP_UDP */
541#if LWIP_RAW
542 raw_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr);
543#endif /* LWIP_RAW */
544
545 mib2_remove_ip4(netif);
546 mib2_remove_route_ip4(0, netif);
547 /* set new IP address to netif */
548 ip4_addr_set(ip_2_ip4(&netif->ip_addr), ipaddr);
549 IP_SET_TYPE_VAL(netif->ip_addr, IPADDR_TYPE_V4);
550 mib2_add_ip4(netif);
551 mib2_add_route_ip4(0, netif);
552
553 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4);
554
555 NETIF_STATUS_CALLBACK(netif);
556 }
557
558 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
559 netif->name[0], netif->name[1],
560 ip4_addr1_16(netif_ip4_addr(netif)),
561 ip4_addr2_16(netif_ip4_addr(netif)),
562 ip4_addr3_16(netif_ip4_addr(netif)),
563 ip4_addr4_16(netif_ip4_addr(netif))));
564}
565
575void
576netif_set_gw(struct netif *netif, const ip4_addr_t *gw)
577{
578 ip4_addr_set(ip_2_ip4(&netif->gw), gw);
579 IP_SET_TYPE_VAL(netif->gw, IPADDR_TYPE_V4);
580 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",
581 netif->name[0], netif->name[1],
582 ip4_addr1_16(netif_ip4_gw(netif)),
583 ip4_addr2_16(netif_ip4_gw(netif)),
584 ip4_addr3_16(netif_ip4_gw(netif)),
585 ip4_addr4_16(netif_ip4_gw(netif))));
586}
587
598void
599netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask)
600{
601 mib2_remove_route_ip4(0, netif);
602 /* set new netmask to netif */
603 ip4_addr_set(ip_2_ip4(&netif->netmask), netmask);
604 IP_SET_TYPE_VAL(netif->netmask, IPADDR_TYPE_V4);
605 mib2_add_route_ip4(0, netif);
606 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",
607 netif->name[0], netif->name[1],
608 ip4_addr1_16(netif_ip4_netmask(netif)),
609 ip4_addr2_16(netif_ip4_netmask(netif)),
610 ip4_addr3_16(netif_ip4_netmask(netif)),
611 ip4_addr4_16(netif_ip4_netmask(netif))));
612}
613#endif /* LWIP_IPV4 */
614
622void
624{
625 if (netif == NULL) {
626 /* remove default route */
627 mib2_remove_route_ip4(1, netif);
628 } else {
629 /* install default route */
630 mib2_add_route_ip4(1, netif);
631 }
633 LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n",
634 netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));
635}
636
642void
644{
645 if (!(netif->flags & NETIF_FLAG_UP)) {
647
648 MIB2_COPY_SYSUPTIME_TO(&netif->ts);
649
650 NETIF_STATUS_CALLBACK(netif);
651
653 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6);
654 }
655 }
656}
657
660static void
661netif_issue_reports(struct netif* netif, u8_t report_type)
662{
663#if LWIP_IPV4
664 if ((report_type & NETIF_REPORT_TYPE_IPV4) &&
665 !ip4_addr_isany_val(*netif_ip4_addr(netif))) {
666#if LWIP_ARP
667 /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
668 if (netif->flags & (NETIF_FLAG_ETHARP)) {
669 etharp_gratuitous(netif);
670 }
671#endif /* LWIP_ARP */
672
673#if LWIP_IGMP
674 /* resend IGMP memberships */
675 if (netif->flags & NETIF_FLAG_IGMP) {
676 igmp_report_groups(netif);
677 }
678#endif /* LWIP_IGMP */
679 }
680#endif /* LWIP_IPV4 */
681
682#if LWIP_IPV6
683 if (report_type & NETIF_REPORT_TYPE_IPV6) {
684#if LWIP_IPV6_MLD
685 /* send mld memberships */
686 mld6_report_groups(netif);
687#endif /* LWIP_IPV6_MLD */
688#if LWIP_IPV6_SEND_ROUTER_SOLICIT
689 /* Send Router Solicitation messages. */
691#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
692 }
693#endif /* LWIP_IPV6 */
694}
695
700void
702{
703 if (netif->flags & NETIF_FLAG_UP) {
704 netif->flags &= ~NETIF_FLAG_UP;
705 MIB2_COPY_SYSUPTIME_TO(&netif->ts);
706
707#if LWIP_IPV4 && LWIP_ARP
709 etharp_cleanup_netif(netif);
710 }
711#endif /* LWIP_IPV4 && LWIP_ARP */
712
713#if LWIP_IPV6
714 nd6_cleanup_netif(netif);
715#endif /* LWIP_IPV6 */
716
717 NETIF_STATUS_CALLBACK(netif);
718 }
719}
720
721#if LWIP_NETIF_STATUS_CALLBACK
726void
727netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback)
728{
729 if (netif) {
730 netif->status_callback = status_callback;
731 }
732}
733#endif /* LWIP_NETIF_STATUS_CALLBACK */
734
735#if LWIP_NETIF_REMOVE_CALLBACK
740void
741netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback)
742{
743 if (netif) {
744 netif->remove_callback = remove_callback;
745 }
746}
747#endif /* LWIP_NETIF_REMOVE_CALLBACK */
748
753void
755{
756 if (!(netif->flags & NETIF_FLAG_LINK_UP)) {
758
759#if LWIP_DHCP
760 dhcp_network_changed(netif);
761#endif /* LWIP_DHCP */
762
763#if LWIP_AUTOIP
764 autoip_network_changed(netif);
765#endif /* LWIP_AUTOIP */
766
767 if (netif->flags & NETIF_FLAG_UP) {
768 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6);
769 }
770 NETIF_LINK_CALLBACK(netif);
771 }
772}
773
778void
780{
782 netif->flags &= ~NETIF_FLAG_LINK_UP;
783 NETIF_LINK_CALLBACK(netif);
784 }
785}
786
787#if LWIP_NETIF_LINK_CALLBACK
792void
793netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback)
794{
795 if (netif) {
796 netif->link_callback = link_callback;
797 }
798}
799#endif /* LWIP_NETIF_LINK_CALLBACK */
800
801#if ENABLE_LOOPBACK
816err_t
817netif_loop_output(struct netif *netif, struct pbuf *p)
818{
819 struct pbuf *r;
820 err_t err;
821 struct pbuf *last;
822#if LWIP_LOOPBACK_MAX_PBUFS
823 u16_t clen = 0;
824#endif /* LWIP_LOOPBACK_MAX_PBUFS */
825 /* If we have a loopif, SNMP counters are adjusted for it,
826 * if not they are adjusted for 'netif'. */
827#if MIB2_STATS
828#if LWIP_HAVE_LOOPIF
829 struct netif *stats_if = &loop_netif;
830#else /* LWIP_HAVE_LOOPIF */
831 struct netif *stats_if = netif;
832#endif /* LWIP_HAVE_LOOPIF */
833#endif /* MIB2_STATS */
835
836 /* Allocate a new pbuf */
838 if (r == NULL) {
839 LINK_STATS_INC(link.memerr);
840 LINK_STATS_INC(link.drop);
841 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards);
842 return ERR_MEM;
843 }
844#if LWIP_LOOPBACK_MAX_PBUFS
845 clen = pbuf_clen(r);
846 /* check for overflow or too many pbuf on queue */
847 if (((netif->loop_cnt_current + clen) < netif->loop_cnt_current) ||
848 ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) {
849 pbuf_free(r);
850 LINK_STATS_INC(link.memerr);
851 LINK_STATS_INC(link.drop);
852 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards);
853 return ERR_MEM;
854 }
855 netif->loop_cnt_current += clen;
856#endif /* LWIP_LOOPBACK_MAX_PBUFS */
857
858 /* Copy the whole pbuf queue p into the single pbuf r */
859 if ((err = pbuf_copy(r, p)) != ERR_OK) {
860 pbuf_free(r);
861 LINK_STATS_INC(link.memerr);
862 LINK_STATS_INC(link.drop);
863 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards);
864 return err;
865 }
866
867 /* Put the packet on a linked list which gets emptied through calling
868 netif_poll(). */
869
870 /* let last point to the last pbuf in chain r */
871 for (last = r; last->next != NULL; last = last->next);
872
873 SYS_ARCH_PROTECT(lev);
874 if (netif->loop_first != NULL) {
875 LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL);
876 netif->loop_last->next = r;
877 netif->loop_last = last;
878 } else {
879 netif->loop_first = r;
880 netif->loop_last = last;
881 }
882 SYS_ARCH_UNPROTECT(lev);
883
884 LINK_STATS_INC(link.xmit);
885 MIB2_STATS_NETIF_ADD(stats_if, ifoutoctets, p->tot_len);
886 MIB2_STATS_NETIF_INC(stats_if, ifoutucastpkts);
887
888#if LWIP_NETIF_LOOPBACK_MULTITHREADING
889 /* For multithreading environment, schedule a call to netif_poll */
890 tcpip_callback_with_block((tcpip_callback_fn)netif_poll, netif, 0);
891#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
892
893 return ERR_OK;
894}
895
896#if LWIP_HAVE_LOOPIF
897#if LWIP_IPV4
898static err_t
899netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t* addr)
900{
901 LWIP_UNUSED_ARG(addr);
902 return netif_loop_output(netif, p);
903}
904#endif /* LWIP_IPV4 */
905
906#if LWIP_IPV6
907static err_t
908netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* addr)
909{
910 LWIP_UNUSED_ARG(addr);
911 return netif_loop_output(netif, p);
912}
913#endif /* LWIP_IPV6 */
914#endif /* LWIP_HAVE_LOOPIF */
915
916
923void
924netif_poll(struct netif *netif)
925{
926 /* If we have a loopif, SNMP counters are adjusted for it,
927 * if not they are adjusted for 'netif'. */
928#if MIB2_STATS
929#if LWIP_HAVE_LOOPIF
930 struct netif *stats_if = &loop_netif;
931#else /* LWIP_HAVE_LOOPIF */
932 struct netif *stats_if = netif;
933#endif /* LWIP_HAVE_LOOPIF */
934#endif /* MIB2_STATS */
936
937 /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
938 SYS_ARCH_PROTECT(lev);
939 while (netif->loop_first != NULL) {
940 struct pbuf *in, *in_end;
941#if LWIP_LOOPBACK_MAX_PBUFS
942 u8_t clen = 1;
943#endif /* LWIP_LOOPBACK_MAX_PBUFS */
944
945 in = in_end = netif->loop_first;
946 while (in_end->len != in_end->tot_len) {
947 LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
948 in_end = in_end->next;
949#if LWIP_LOOPBACK_MAX_PBUFS
950 clen++;
951#endif /* LWIP_LOOPBACK_MAX_PBUFS */
952 }
953#if LWIP_LOOPBACK_MAX_PBUFS
954 /* adjust the number of pbufs on queue */
955 LWIP_ASSERT("netif->loop_cnt_current underflow",
956 ((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
957 netif->loop_cnt_current -= clen;
958#endif /* LWIP_LOOPBACK_MAX_PBUFS */
959
960 /* 'in_end' now points to the last pbuf from 'in' */
961 if (in_end == netif->loop_last) {
962 /* this was the last pbuf in the list */
963 netif->loop_first = netif->loop_last = NULL;
964 } else {
965 /* pop the pbuf off the list */
966 netif->loop_first = in_end->next;
967 LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
968 }
969 /* De-queue the pbuf from its successors on the 'loop_' list. */
970 in_end->next = NULL;
971 SYS_ARCH_UNPROTECT(lev);
972
973 LINK_STATS_INC(link.recv);
974 MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len);
975 MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts);
976 /* loopback packets are always IP packets! */
977 if (ip_input(in, netif) != ERR_OK) {
978 pbuf_free(in);
979 }
980 SYS_ARCH_PROTECT(lev);
981 }
982 SYS_ARCH_UNPROTECT(lev);
983}
984
985#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
989void
990netif_poll_all(void)
991{
992 struct netif *netif = netif_list;
993 /* loop through netifs */
994 while (netif != NULL) {
995 netif_poll(netif);
996 /* proceed to next network interface */
997 netif = netif->next;
998 }
999}
1000#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
1001#endif /* ENABLE_LOOPBACK */
1002
1003#if LWIP_NUM_NETIF_CLIENT_DATA > 0
1010u8_t
1011netif_alloc_client_data_id(void)
1012{
1013 u8_t result = netif_client_id;
1014 netif_client_id++;
1015
1016 LWIP_ASSERT("Increase LWIP_NUM_NETIF_CLIENT_DATA in lwipopts.h", result < LWIP_NUM_NETIF_CLIENT_DATA);
1017 return result + LWIP_NETIF_CLIENT_DATA_INDEX_MAX;
1018}
1019#endif
1020
1021#if LWIP_IPV6
1032void
1033netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6)
1034{
1035 LWIP_ASSERT("addr6 != NULL", addr6 != NULL);
1036 netif_ip6_addr_set_parts(netif, addr_idx, addr6->addr[0], addr6->addr[1],
1037 addr6->addr[2], addr6->addr[3]);
1038}
1039
1040/*
1041 * Change an IPv6 address of a network interface (internal version taking 4 * u32_t)
1042 *
1043 * @param netif the network interface to change
1044 * @param addr_idx index of the IPv6 address
1045 * @param i0 word0 of the new IPv6 address
1046 * @param i1 word1 of the new IPv6 address
1047 * @param i2 word2 of the new IPv6 address
1048 * @param i3 word3 of the new IPv6 address
1049 */
1050void
1051netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3)
1052{
1053 const ip6_addr_t *old_addr;
1054 LWIP_ASSERT("netif != NULL", netif != NULL);
1055 LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES);
1056
1057 old_addr = netif_ip6_addr(netif, addr_idx);
1058 /* address is actually being changed? */
1059 if ((old_addr->addr[0] != i0) || (old_addr->addr[1] != i1) ||
1060 (old_addr->addr[2] != i2) || (old_addr->addr[3] != i3)) {
1061 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set: netif address being changed\n"));
1062
1063 if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) {
1064#if LWIP_TCP || LWIP_UDP
1065 ip_addr_t new_ipaddr;
1066 IP_ADDR6(&new_ipaddr, i0, i1, i2, i3);
1067#endif /* LWIP_TCP || LWIP_UDP */
1068#if LWIP_TCP
1069 tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
1070#endif /* LWIP_TCP */
1071#if LWIP_UDP
1072 udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
1073#endif /* LWIP_UDP */
1074#if LWIP_RAW
1075 raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
1076#endif /* LWIP_RAW */
1077 }
1078 /* @todo: remove/readd mib2 ip6 entries? */
1079
1080 IP6_ADDR(ip_2_ip6(&(netif->ip6_addr[addr_idx])), i0, i1, i2, i3);
1081 IP_SET_TYPE_VAL(netif->ip6_addr[addr_idx], IPADDR_TYPE_V6);
1082
1083 if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) {
1084 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6);
1085 NETIF_STATUS_CALLBACK(netif);
1086 }
1087 }
1088
1089 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",
1090 addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)),
1091 netif_ip6_addr_state(netif, addr_idx)));
1092}
1093
1104void
1105netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state)
1106{
1107 u8_t old_state;
1108 LWIP_ASSERT("netif != NULL", netif != NULL);
1109 LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES);
1110
1111 old_state = netif_ip6_addr_state(netif, addr_idx);
1112 /* state is actually being changed? */
1113 if (old_state != state) {
1114 u8_t old_valid = old_state & IP6_ADDR_VALID;
1115 u8_t new_valid = state & IP6_ADDR_VALID;
1116 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n"));
1117
1118#if LWIP_IPV6_MLD
1119 /* Reevaluate solicited-node multicast group membership. */
1120 if (netif->flags & NETIF_FLAG_MLD6) {
1121 nd6_adjust_mld_membership(netif, addr_idx, state);
1122 }
1123#endif /* LWIP_IPV6_MLD */
1124
1125 if (old_valid && !new_valid) {
1126 /* address about to be removed by setting invalid */
1127#if LWIP_TCP
1128 tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
1129#endif /* LWIP_TCP */
1130#if LWIP_UDP
1131 udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
1132#endif /* LWIP_UDP */
1133#if LWIP_RAW
1134 raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
1135#endif /* LWIP_RAW */
1136 /* @todo: remove mib2 ip6 entries? */
1137 }
1138 netif->ip6_addr_state[addr_idx] = state;
1139
1140 if (!old_valid && new_valid) {
1141 /* address added by setting valid */
1142 /* @todo: add mib2 ip6 entries? */
1143 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6);
1144 }
1145 if ((old_state & IP6_ADDR_PREFERRED) != (state & IP6_ADDR_PREFERRED)) {
1146 /* address state has changed (valid flag changed or switched between
1147 preferred and deprecated) -> call the callback function */
1148 NETIF_STATUS_CALLBACK(netif);
1149 }
1150 }
1151
1152 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",
1153 addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)),
1154 netif_ip6_addr_state(netif, addr_idx)));
1155}
1156
1166s8_t
1167netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr)
1168{
1169 s8_t i;
1170 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1171 if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) &&
1172 ip6_addr_cmp(netif_ip6_addr(netif, i), ip6addr)) {
1173 return i;
1174 }
1175 }
1176 return -1;
1177}
1178
1187void
1188netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit)
1189{
1190 u8_t i, addr_index;
1191
1192 /* Link-local prefix. */
1193 ip_2_ip6(&netif->ip6_addr[0])->addr[0] = PP_HTONL(0xfe800000ul);
1194 ip_2_ip6(&netif->ip6_addr[0])->addr[1] = 0;
1195
1196 /* Generate interface ID. */
1197 if (from_mac_48bit) {
1198 /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */
1199 ip_2_ip6(&netif->ip6_addr[0])->addr[2] = lwip_htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) |
1200 ((u32_t)(netif->hwaddr[1]) << 16) |
1201 ((u32_t)(netif->hwaddr[2]) << 8) |
1202 (0xff));
1203 ip_2_ip6(&netif->ip6_addr[0])->addr[3] = lwip_htonl((0xfeul << 24) |
1204 ((u32_t)(netif->hwaddr[3]) << 16) |
1205 ((u32_t)(netif->hwaddr[4]) << 8) |
1206 (netif->hwaddr[5]));
1207 } else {
1208 /* Use hwaddr directly as interface ID. */
1209 ip_2_ip6(&netif->ip6_addr[0])->addr[2] = 0;
1210 ip_2_ip6(&netif->ip6_addr[0])->addr[3] = 0;
1211
1212 addr_index = 3;
1213 for (i = 0; (i < 8) && (i < netif->hwaddr_len); i++) {
1214 if (i == 4) {
1215 addr_index--;
1216 }
1217 ip_2_ip6(&netif->ip6_addr[0])->addr[addr_index] |= ((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03));
1218 }
1219 }
1220
1221 /* Set address state. */
1222#if LWIP_IPV6_DUP_DETECT_ATTEMPTS
1223 /* Will perform duplicate address detection (DAD). */
1224 netif_ip6_addr_set_state(netif, 0, IP6_ADDR_TENTATIVE);
1225#else
1226 /* Consider address valid. */
1227 netif_ip6_addr_set_state(netif, 0, IP6_ADDR_PREFERRED);
1228#endif /* LWIP_IPV6_AUTOCONFIG */
1229}
1230
1241err_t
1242netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx)
1243{
1244 s8_t i;
1245
1246 i = netif_get_ip6_addr_match(netif, ip6addr);
1247 if (i >= 0) {
1248 /* Address already added */
1249 if (chosen_idx != NULL) {
1250 *chosen_idx = i;
1251 }
1252 return ERR_OK;
1253 }
1254
1255 /* Find a free slot -- musn't be the first one (reserved for link local) */
1256 for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1257 if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) {
1258 ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr);
1259 netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE);
1260 if (chosen_idx != NULL) {
1261 *chosen_idx = i;
1262 }
1263 return ERR_OK;
1264 }
1265 }
1266
1267 if (chosen_idx != NULL) {
1268 *chosen_idx = -1;
1269 }
1270 return ERR_VAL;
1271}
1272
1275static err_t
1276netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr)
1277{
1279 LWIP_UNUSED_ARG(p);
1280 LWIP_UNUSED_ARG(ipaddr);
1281
1282 return ERR_IF;
1283}
1284#endif /* LWIP_IPV6 */
#define LWIP_DEBUGF(debug, message)
Definition debug.h:183
#define LWIP_UNUSED_ARG(x)
Definition arch.h:327
#define LWIP_DBG_STATE
Definition debug.h:104
#define LWIP_DBG_TRACE
Definition debug.h:102
s8_t err_t
Definition err.h:76
@ ERR_IF
Definition err.h:106
@ ERR_OK
Definition err.h:82
@ ERR_VAL
Definition err.h:94
@ ERR_MEM
Definition err.h:84
@ IPADDR_TYPE_V6
Definition ip_addr.h:77
@ IPADDR_TYPE_V4
Definition ip_addr.h:75
#define NETIF_DEBUG
Definition opt.h:2657
#define LWIP_IPV4
Definition opt.h:659
#define LWIP_IPV6_NUM_ADDRESSES
Definition opt.h:2179
#define LWIP_LOOPBACK_MAX_PBUFS
Definition opt.h:1521
#define LWIP_ND6_MAX_MULTICAST_SOLICIT
Definition opt.h:2338
#define LWIP_NUM_NETIF_CLIENT_DATA
Definition opt.h:1476
#define NETIF_FLAG_LINK_UP
Definition netif.h:106
#define NETIF_FLAG_ETHERNET
Definition netif.h:114
#define NETIF_FLAG_ETHARP
Definition netif.h:110
#define NETIF_FLAG_MLD6
Definition netif.h:120
#define NETIF_FLAG_UP
Definition netif.h:97
#define NETIF_FLAG_IGMP
Definition netif.h:117
void netif_set_link_down(struct netif *netif)
Definition netif.c:779
struct netif * netif_find(const char *name)
Definition netif.c:491
void netif_set_down(struct netif *netif)
Definition netif.c:701
#define netif_is_up(netif)
Definition netif.h:420
void netif_remove(struct netif *netif)
Definition netif.c:396
struct netif * netif_add(struct netif *netif, void *state, netif_init_fn init, netif_input_fn input)
Definition netif.c:260
void netif_set_default(struct netif *netif)
Definition netif.c:623
void netif_set_link_up(struct netif *netif)
Definition netif.c:754
void netif_set_up(struct netif *netif)
Definition netif.c:643
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition pbuf.c:267
u8_t pbuf_free(struct pbuf *p)
Definition pbuf.c:734
err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
Definition pbuf.c:967
@ PBUF_RAM
Definition pbuf.h:127
@ PBUF_LINK
Definition pbuf.h:104
struct netif * netif_list
Definition netif.c:123
struct netif * netif_default
Definition netif.c:124
err_t netif_input(struct pbuf *p, struct netif *inp)
Definition netif.c:222
err_t(* netif_init_fn)(struct netif *netif)
Definition netif.h:174
void(* netif_status_callback_fn)(struct netif *netif)
Definition netif.h:217
err_t(* netif_input_fn)(struct pbuf *p, struct netif *inp)
Definition netif.h:181
u16_t pbuf_clen(const struct pbuf *p)
Definition pbuf.c:819
Definition netif.h:244
u8_t flags
Definition netif.h:324
char name[2]
Definition netif.h:326
void * state
Definition netif.h:298
netif_input_fn input
Definition netif.h:263
u8_t num
Definition netif.h:328
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]
Definition netif.h:322
struct netif * next
Definition netif.h:246
u8_t hwaddr_len
Definition netif.h:320
Definition pbuf.h:161
u16_t tot_len
Definition pbuf.h:175
struct pbuf * next
Definition pbuf.h:163
u16_t len
Definition pbuf.h:178
#define SYS_ARCH_DECL_PROTECT(lev)
Definition sys.h:426
err_t tcpip_input(struct pbuf *p, struct netif *inp)
Definition tcpip.c:286
void(* tcpip_callback_fn)(void *ctx)
Definition tcpip.h:89