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 
126 static u8_t netif_num;
127 
128 #if LWIP_NUM_NETIF_CLIENT_DATA > 0
129 static u8_t netif_client_id;
130 #endif
131 
132 #define NETIF_REPORT_TYPE_IPV4 0x01
133 #define NETIF_REPORT_TYPE_IPV6 0x02
134 static void netif_issue_reports(struct netif* netif, u8_t report_type);
135 
136 #if LWIP_IPV6
137 static 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
142 static err_t netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t* addr);
143 #endif
144 #if LWIP_IPV6
145 static err_t netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* addr);
146 #endif
147 
148 
149 static struct netif loop_netif;
150 
158 static err_t
159 netif_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
175  netif->flags |= NETIF_FLAG_IGMP;
176 #endif
177  return ERR_OK;
178 }
179 #endif /* LWIP_HAVE_LOOPIF */
180 
181 void
182 netif_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 
221 err_t
222 netif_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 
259 struct 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
295  netif->rs_count = LWIP_ND6_MAX_MULTICAST_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 */
334  netif->next = netif_list;
335  netif_list = netif;
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
360 
370 void
371 netif_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 
395 void
396 netif_remove(struct netif *netif)
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) */
448  netif_set_down(netif);
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) {
460  netif_list = netif->next;
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 
490 struct netif *
491 netif_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
515 
525 void
526 netif_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 
575 void
576 netif_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 
598 void
599 netif_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 
622 void
623 netif_set_default(struct netif *netif)
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  }
632  netif_default = netif;
633  LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n",
634  netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));
635 }
636 
642 void
643 netif_set_up(struct netif *netif)
644 {
645  if (!(netif->flags & NETIF_FLAG_UP)) {
646  netif->flags |= NETIF_FLAG_UP;
647 
648  MIB2_COPY_SYSUPTIME_TO(&netif->ts);
649 
650  NETIF_STATUS_CALLBACK(netif);
651 
652  if (netif->flags & NETIF_FLAG_LINK_UP) {
653  netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6);
654  }
655  }
656 }
657 
660 static void
661 netif_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. */
690  netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT;
691 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */
692  }
693 #endif /* LWIP_IPV6 */
694 }
695 
700 void
701 netif_set_down(struct netif *netif)
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
708  if (netif->flags & NETIF_FLAG_ETHARP) {
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
722 
726 void
727 netif_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
736 
740 void
741 netif_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 
753 void
754 netif_set_link_up(struct netif *netif)
755 {
756  if (!(netif->flags & NETIF_FLAG_LINK_UP)) {
757  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 
778 void
779 netif_set_link_down(struct netif *netif )
780 {
781  if (netif->flags & NETIF_FLAG_LINK_UP) {
782  netif->flags &= ~NETIF_FLAG_LINK_UP;
783  NETIF_LINK_CALLBACK(netif);
784  }
785 }
786 
787 #if LWIP_NETIF_LINK_CALLBACK
788 
792 void
793 netif_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
802 
816 err_t
817 netif_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
898 static err_t
899 netif_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
907 static err_t
908 netif_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 
923 void
924 netif_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
986 
989 void
990 netif_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
1004 
1010 u8_t
1011 netif_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
1022 
1032 void
1033 netif_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  */
1050 void
1051 netif_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 
1104 void
1105 netif_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 
1166 s8_t
1167 netif_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 
1187 void
1188 netif_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 
1241 err_t
1242 netif_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 
1275 static err_t
1276 netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr)
1277 {
1278  LWIP_UNUSED_ARG(netif);
1279  LWIP_UNUSED_ARG(p);
1280  LWIP_UNUSED_ARG(ipaddr);
1281 
1282  return ERR_IF;
1283 }
1284 #endif /* LWIP_IPV6 */
err_t(* netif_input_fn)(struct pbuf *p, struct netif *inp)
Definition: netif.h:181
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]
Definition: netif.h:322
#define NETIF_FLAG_UP
Definition: netif.h:97
#define LWIP_IPV4
Definition: opt.h:659
u16_t tot_len
Definition: pbuf.h:175
struct netif * netif_list
Definition: netif.c:123
#define NETIF_FLAG_IGMP
Definition: netif.h:117
void(* netif_status_callback_fn)(struct netif *netif)
Definition: netif.h:217
struct pbuf * next
Definition: pbuf.h:163
u16_t pbuf_clen(const struct pbuf *p)
Definition: pbuf.c:819
u16_t len
Definition: pbuf.h:178
struct netif * netif_default
Definition: netif.c:124
void(* tcpip_callback_fn)(void *ctx)
Definition: tcpip.h:89
struct netif * netif_add(struct netif *netif, void *state, netif_init_fn init, netif_input_fn input)
Definition: netif.c:260
err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block)
Definition: tcpip.c:253
#define NETIF_FLAG_MLD6
Definition: netif.h:120
u8_t num
Definition: netif.h:328
err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
Definition: pbuf.c:967
err_t netif_input(struct pbuf *p, struct netif *inp)
Definition: netif.c:222
#define SYS_ARCH_DECL_PROTECT(lev)
Definition: sys.h:420
u8_t hwaddr_len
Definition: netif.h:320
Definition: err.h:84
#define LWIP_ND6_MAX_MULTICAST_SOLICIT
Definition: opt.h:2338
void netif_set_link_down(struct netif *netif)
Definition: netif.c:779
#define NETIF_FLAG_ETHERNET
Definition: netif.h:114
struct netif * next
Definition: netif.h:246
err_t tcpip_input(struct pbuf *p, struct netif *inp)
Definition: tcpip.c:231
#define NETIF_FLAG_LINK_UP
Definition: netif.h:106
Definition: pbuf.h:161
u8_t flags
Definition: netif.h:324
Definition: netif.h:244
err_t(* netif_init_fn)(struct netif *netif)
Definition: netif.h:174
Definition: err.h:106
void netif_set_up(struct netif *netif)
Definition: netif.c:643
void netif_remove(struct netif *netif)
Definition: netif.c:396
s8_t err_t
Definition: err.h:76
void netif_set_default(struct netif *netif)
Definition: netif.c:623
struct netif * netif_find(const char *name)
Definition: netif.c:491
#define LWIP_DEBUGF(debug, message)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:267
#define netif_is_up(netif)
Definition: netif.h:420
#define LWIP_NUM_NETIF_CLIENT_DATA
Definition: opt.h:1476
Definition: pbuf.h:127
#define NETIF_FLAG_ETHARP
Definition: netif.h:110
#define LWIP_LOOPBACK_MAX_PBUFS
Definition: opt.h:1521
Definition: err.h:94
void * state
Definition: netif.h:298
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:327
netif_input_fn input
Definition: netif.h:263
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:734
Definition: err.h:82
char name[2]
Definition: netif.h:326
#define LWIP_IPV6_NUM_ADDRESSES
Definition: opt.h:2179
void netif_set_down(struct netif *netif)
Definition: netif.c:701
#define NETIF_DEBUG
Definition: opt.h:2657
void netif_set_link_up(struct netif *netif)
Definition: netif.c:754