1/** 2 * @file 3 * lwIP network interface abstraction 4 * 5 * @defgroup netif Network interface (NETIF) 6 * @ingroup callbackstyle_api 7 * 8 * @defgroup netif_ip4 IPv4 address handling 9 * @ingroup netif 10 * 11 * @defgroup netif_ip6 IPv6 address handling 12 * @ingroup netif 13 * 14 * @defgroup netif_cd Client data handling 15 * Store data (void*) on a netif for application usage. 16 * @see @ref LWIP_NUM_NETIF_CLIENT_DATA 17 * @ingroup netif 18 */ 19 20/* 21 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 22 * All rights reserved. 23 * 24 * Redistribution and use in source and binary forms, with or without modification, 25 * are permitted provided that the following conditions are met: 26 * 27 * 1. Redistributions of source code must retain the above copyright notice, 28 * this list of conditions and the following disclaimer. 29 * 2. Redistributions in binary form must reproduce the above copyright notice, 30 * this list of conditions and the following disclaimer in the documentation 31 * and/or other materials provided with the distribution. 32 * 3. The name of the author may not be used to endorse or promote products 33 * derived from this software without specific prior written permission. 34 * 35 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 37 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 38 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 39 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 40 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 41 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 42 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 43 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 44 * OF SUCH DAMAGE. 45 * 46 * This file is part of the lwIP TCP/IP stack. 47 * 48 * Author: Adam Dunkels <adam@sics.se> 49 */ 50 51#include "lwip/opt.h" 52 53#include <string.h> /* memset */ 54#include <stdlib.h> /* atoi */ 55 56#include "lwip/def.h" 57#include "lwip/ip_addr.h" 58#include "lwip/ip6_addr.h" 59#include "lwip/netif.h" 60#include "lwip/priv/tcp_priv.h" 61#include "lwip/udp.h" 62#include "lwip/priv/raw_priv.h" 63#include "lwip/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_IPV6_DHCP6 84#include "lwip/dhcp6.h" 85#endif /* LWIP_IPV6_DHCP6 */ 86#if LWIP_IPV6_MLD 87#include "lwip/mld6.h" 88#endif /* LWIP_IPV6_MLD */ 89#if LWIP_IPV6 90#include "lwip/nd6.h" 91#endif 92 93#if LWIP_NETIF_STATUS_CALLBACK 94#define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0) 95#else 96#define NETIF_STATUS_CALLBACK(n) 97#endif /* LWIP_NETIF_STATUS_CALLBACK */ 98 99#if LWIP_NETIF_LINK_CALLBACK 100#define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0) 101#else 102#define NETIF_LINK_CALLBACK(n) 103#endif /* LWIP_NETIF_LINK_CALLBACK */ 104 105#if LWIP_NETIF_EXT_STATUS_CALLBACK 106static netif_ext_callback_t *ext_callback; 107#endif 108 109#ifndef LOSCFG_NET_CONTAINER 110#if !LWIP_SINGLE_NETIF 111struct netif *netif_list; 112#endif /* !LWIP_SINGLE_NETIF */ 113struct netif *netif_default; 114#endif 115 116#define netif_index_to_num(index) ((index) - 1) 117#ifndef LOSCFG_NET_CONTAINER 118static u8_t netif_num; 119#endif 120 121#if LWIP_NUM_NETIF_CLIENT_DATA > 0 122static u8_t netif_client_id; 123#endif 124 125#define NETIF_REPORT_TYPE_IPV4 0x01 126#define NETIF_REPORT_TYPE_IPV6 0x02 127static void netif_issue_reports(struct netif *netif, u8_t report_type); 128 129#if LWIP_IPV6 130static err_t netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr); 131#endif /* LWIP_IPV6 */ 132#if LWIP_IPV4 133static err_t netif_null_output_ip4(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr); 134#endif /* LWIP_IPV4 */ 135 136#if LWIP_HAVE_LOOPIF 137#if LWIP_IPV4 138static err_t netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr); 139#endif 140#if LWIP_IPV6 141static err_t netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr); 142#endif 143 144 145#ifdef LOSCFG_NET_CONTAINER 146struct net_group *get_net_group_from_netif(struct netif *netif) { 147 if (netif != NULL) { 148 return get_default_net_group_ops()->get_net_group_from_netif(netif); 149 } 150 return NULL; 151} 152#else 153static struct netif loop_netif; 154#endif 155 156/** 157 * Initialize a lwip network interface structure for a loopback interface 158 * 159 * @param netif the lwip network interface structure for this loopif 160 * @return ERR_OK if the loopif is initialized 161 * ERR_MEM if private data couldn't be allocated 162 */ 163static err_t 164netif_loopif_init(struct netif *netif) 165{ 166 LWIP_ASSERT("netif_loopif_init: invalid netif", netif != NULL); 167 168 /* initialize the snmp variables and counters inside the struct netif 169 * ifSpeed: no assumption can be made! 170 */ 171 MIB2_INIT_NETIF(netif, snmp_ifType_softwareLoopback, 0); 172 173 netif->name[0] = 'l'; 174 netif->name[1] = 'o'; 175#if LWIP_IPV4 176 netif->output = netif_loop_output_ipv4; 177#endif 178#if LWIP_IPV6 179 netif->output_ip6 = netif_loop_output_ipv6; 180#endif 181#if LWIP_LOOPIF_MULTICAST 182 netif_set_flags(netif, NETIF_FLAG_IGMP); 183#endif 184 NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_DISABLE_ALL); 185 return ERR_OK; 186} 187#endif /* LWIP_HAVE_LOOPIF */ 188 189void 190#ifdef LOSCFG_NET_CONTAINER 191netif_init(struct net_group *group) 192#else 193netif_init(void) 194#endif 195{ 196#if LWIP_HAVE_LOOPIF 197#if LWIP_IPV4 198#define LOOPIF_ADDRINIT &loop_ipaddr, &loop_netmask, &loop_gw, 199 ip4_addr_t loop_ipaddr, loop_netmask, loop_gw; 200 IP4_ADDR(&loop_gw, 127, 0, 0, 1); 201 IP4_ADDR(&loop_ipaddr, 127, 0, 0, 1); 202 IP4_ADDR(&loop_netmask, 255, 0, 0, 0); 203#else /* LWIP_IPV4 */ 204#define LOOPIF_ADDRINIT 205#endif /* LWIP_IPV4 */ 206 207#ifdef LOSCFG_NET_CONTAINER 208struct netif *loop_netif = group->loop_netif; 209#endif 210 211#if NO_SYS 212#ifdef LOSCFG_NET_CONTAINER 213 netif_add(loop_netif, group, LOOPIF_ADDRINIT NULL, netif_loopif_init, ip_input); 214#else 215 netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, ip_input); 216#endif 217#else /* NO_SYS */ 218#ifdef LOSCFG_NET_CONTAINER 219 netif_add(loop_netif, group, LOOPIF_ADDRINIT NULL, netif_loopif_init, tcpip_input); 220#else 221 netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, tcpip_input); 222#endif 223#endif /* NO_SYS */ 224 225#if LWIP_IPV6 226#ifdef LOSCFG_NET_CONTAINER 227 IP_ADDR6_HOST(loop_netif->ip6_addr, 0, 0, 0, 0x00000001UL); 228 loop_netif->ip6_addr_state[0] = IP6_ADDR_VALID; 229#else 230 IP_ADDR6_HOST(loop_netif.ip6_addr, 0, 0, 0, 0x00000001UL); 231 loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID; 232#endif 233#endif /* LWIP_IPV6 */ 234 235#ifdef LOSCFG_NET_CONTAINER 236 netif_set_link_up(loop_netif); 237 netif_set_up(loop_netif); 238#else 239 netif_set_link_up(&loop_netif); 240 netif_set_up(&loop_netif); 241#endif 242 243#endif /* LWIP_HAVE_LOOPIF */ 244} 245 246/** 247 * @ingroup lwip_nosys 248 * Forwards a received packet for input processing with 249 * ethernet_input() or ip_input() depending on netif flags. 250 * Don't call directly, pass to netif_add() and call 251 * netif->input(). 252 * Only works if the netif driver correctly sets 253 * NETIF_FLAG_ETHARP and/or NETIF_FLAG_ETHERNET flag! 254 */ 255err_t 256netif_input(struct pbuf *p, struct netif *inp) 257{ 258 LWIP_ASSERT_CORE_LOCKED(); 259 260 LWIP_ASSERT("netif_input: invalid pbuf", p != NULL); 261 LWIP_ASSERT("netif_input: invalid netif", inp != NULL); 262 263#if LWIP_ETHERNET 264 if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { 265 return ethernet_input(p, inp); 266 } else 267#endif /* LWIP_ETHERNET */ 268 return ip_input(p, inp); 269} 270 271/** 272 * @ingroup netif 273 * Add a network interface to the list of lwIP netifs. 274 * 275 * Same as @ref netif_add but without IPv4 addresses 276 */ 277struct netif * 278#ifdef LOSCFG_NET_CONTAINER 279netif_add_noaddr(struct netif *netif, struct net_group *group, void *state, netif_init_fn init, netif_input_fn input) 280#else 281netif_add_noaddr(struct netif *netif, void *state, netif_init_fn init, netif_input_fn input) 282#endif 283{ 284#ifdef LOSCFG_NET_CONTAINER 285 return netif_add(netif, group, 286#else 287 return netif_add(netif, 288#endif 289#if LWIP_IPV4 290 NULL, NULL, NULL, 291#endif /* LWIP_IPV4*/ 292 state, init, input); 293} 294 295/** 296 * @ingroup netif 297 * Add a network interface to the list of lwIP netifs. 298 * 299 * @param netif a pre-allocated netif structure 300 * @param ipaddr IP address for the new netif 301 * @param netmask network mask for the new netif 302 * @param gw default gateway IP address for the new netif 303 * @param state opaque data passed to the new netif 304 * @param init callback function that initializes the interface 305 * @param input callback function that is called to pass 306 * ingress packets up in the protocol layer stack.\n 307 * It is recommended to use a function that passes the input directly 308 * to the stack (netif_input(), NO_SYS=1 mode) or via sending a 309 * message to TCPIP thread (tcpip_input(), NO_SYS=0 mode).\n 310 * These functions use netif flags NETIF_FLAG_ETHARP and NETIF_FLAG_ETHERNET 311 * to decide whether to forward to ethernet_input() or ip_input(). 312 * In other words, the functions only work when the netif 313 * driver is implemented correctly!\n 314 * Most members of struct netif should be be initialized by the 315 * netif init function = netif driver (init parameter of this function).\n 316 * IPv6: Don't forget to call netif_create_ip6_linklocal_address() after 317 * setting the MAC address in struct netif.hwaddr 318 * (IPv6 requires a link-local address). 319 * 320 * @return netif, or NULL if failed. 321 */ 322struct netif * 323#ifdef LOSCFG_NET_CONTAINER 324netif_add(struct netif *netif, struct net_group *group, 325#else 326netif_add(struct netif *netif, 327#endif 328#if LWIP_IPV4 329 const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, 330#endif /* LWIP_IPV4 */ 331 void *state, netif_init_fn init, netif_input_fn input) 332{ 333#if LWIP_IPV6 334 s8_t i; 335#endif 336 337 LWIP_ASSERT_CORE_LOCKED(); 338 339#ifdef LOSCFG_NET_CONTAINER 340 get_default_net_group_ops()->set_netif_net_group(netif, group); 341#endif 342 343#if LWIP_SINGLE_NETIF 344#ifdef LOSCFG_NET_CONTAINER 345 if (group->loop_netif != NULL) { 346#else 347 if (netif_default != NULL) { 348#endif 349 LWIP_ASSERT("single netif already set", 0); 350 return NULL; 351 } 352#endif 353 354 LWIP_ERROR("netif_add: invalid netif", netif != NULL, return NULL); 355 LWIP_ERROR("netif_add: No init function given", init != NULL, return NULL); 356 357#if LWIP_IPV4 358 if (ipaddr == NULL) { 359 ipaddr = ip_2_ip4(IP4_ADDR_ANY); 360 } 361 if (netmask == NULL) { 362 netmask = ip_2_ip4(IP4_ADDR_ANY); 363 } 364 if (gw == NULL) { 365 gw = ip_2_ip4(IP4_ADDR_ANY); 366 } 367 368 /* reset new interface configuration state */ 369 ip_addr_set_zero_ip4(&netif->ip_addr); 370 ip_addr_set_zero_ip4(&netif->netmask); 371 ip_addr_set_zero_ip4(&netif->gw); 372 netif->output = netif_null_output_ip4; 373#endif /* LWIP_IPV4 */ 374#if LWIP_IPV6 375 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 376 ip_addr_set_zero_ip6(&netif->ip6_addr[i]); 377 netif->ip6_addr_state[i] = IP6_ADDR_INVALID; 378#if LWIP_IPV6_ADDRESS_LIFETIMES 379 netif->ip6_addr_valid_life[i] = IP6_ADDR_LIFE_STATIC; 380 netif->ip6_addr_pref_life[i] = IP6_ADDR_LIFE_STATIC; 381#endif /* LWIP_IPV6_ADDRESS_LIFETIMES */ 382 } 383 netif->output_ip6 = netif_null_output_ip6; 384#endif /* LWIP_IPV6 */ 385 NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL); 386 netif->mtu = 0; 387 netif->flags = 0; 388#ifdef netif_get_client_data 389 memset(netif->client_data, 0, sizeof(netif->client_data)); 390#endif /* LWIP_NUM_NETIF_CLIENT_DATA */ 391#if LWIP_IPV6 392#if LWIP_IPV6_AUTOCONFIG 393 /* IPv6 address autoconfiguration not enabled by default */ 394 netif->ip6_autoconfig_enabled = 0; 395#endif /* LWIP_IPV6_AUTOCONFIG */ 396 nd6_restart_netif(netif); 397#endif /* LWIP_IPV6 */ 398#if LWIP_NETIF_STATUS_CALLBACK 399 netif->status_callback = NULL; 400#endif /* LWIP_NETIF_STATUS_CALLBACK */ 401#if LWIP_NETIF_LINK_CALLBACK 402 netif->link_callback = NULL; 403#endif /* LWIP_NETIF_LINK_CALLBACK */ 404#if LWIP_IGMP 405 netif->igmp_mac_filter = NULL; 406#endif /* LWIP_IGMP */ 407#if LWIP_IPV6 && LWIP_IPV6_MLD 408 netif->mld_mac_filter = NULL; 409#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ 410 411 /* remember netif specific state information data */ 412 netif->state = state; 413#ifdef LOSCFG_NET_CONTAINER 414 netif->num = group->netif_num; 415#else 416 netif->num = netif_num; 417#endif 418 netif->input = input; 419 420 NETIF_RESET_HINTS(netif); 421#if ENABLE_LOOPBACK 422 netif->loop_first = NULL; 423 netif->loop_last = NULL; 424#if LWIP_LOOPBACK_MAX_PBUFS 425 netif->loop_cnt_current = 0; 426#endif /* LWIP_LOOPBACK_MAX_PBUFS */ 427#if LWIP_NETIF_LOOPBACK_MULTITHREADING 428 netif->reschedule_poll = 0; 429#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 430#endif /* ENABLE_LOOPBACK */ 431 432#if LWIP_IPV4 433 netif_set_addr(netif, ipaddr, netmask, gw); 434#endif /* LWIP_IPV4 */ 435 436 /* call user specified initialization function for netif */ 437 if (init(netif) != ERR_OK) { 438 return NULL; 439 } 440#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES 441 /* Initialize the MTU for IPv6 to the one set by the netif driver. 442 This can be updated later by RA. */ 443 netif->mtu6 = netif->mtu; 444#endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */ 445 446#if !LWIP_SINGLE_NETIF 447 /* Assign a unique netif number in the range [0..254], so that (num+1) can 448 serve as an interface index that fits in a u8_t. 449 We assume that the new netif has not yet been added to the list here. 450 This algorithm is O(n^2), but that should be OK for lwIP. 451 */ 452 { 453 struct netif *netif2; 454 int num_netifs; 455 do { 456 if (netif->num == 255) { 457 netif->num = 0; 458 } 459 num_netifs = 0; 460#ifdef LOSCFG_NET_CONTAINER 461 for (netif2 = group->netif_list; netif2 != NULL; netif2 = netif2->next) { 462#else 463 for (netif2 = netif_list; netif2 != NULL; netif2 = netif2->next) { 464#endif 465 LWIP_ASSERT("netif already added", netif2 != netif); 466 num_netifs++; 467 LWIP_ASSERT("too many netifs, max. supported number is 255", num_netifs <= 255); 468 if (netif2->num == netif->num) { 469 netif->num++; 470 break; 471 } 472 } 473 } while (netif2 != NULL); 474 } 475 if (netif->num == 254) { 476#ifdef LOSCFG_NET_CONTAINER 477 group->netif_num = 0; 478#else 479 netif_num = 0; 480#endif 481 } else { 482#ifdef LOSCFG_NET_CONTAINER 483 group->netif_num = (u8_t)(netif->num + 1); 484#else 485 netif_num = (u8_t)(netif->num + 1); 486#endif 487 } 488 489 /* add this netif to the list */ 490#ifdef LOSCFG_NET_CONTAINER 491 netif->next = group->netif_list; 492 group->netif_list = netif; 493#else 494 netif->next = netif_list; 495 netif_list = netif; 496#endif 497#endif /* "LWIP_SINGLE_NETIF */ 498 mib2_netif_added(netif); 499 500#if LWIP_IGMP 501 /* start IGMP processing */ 502 if (netif->flags & NETIF_FLAG_IGMP) { 503 igmp_start(netif); 504 } 505#endif /* LWIP_IGMP */ 506 507 LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP", 508 netif->name[0], netif->name[1])); 509#if LWIP_IPV4 510 LWIP_DEBUGF(NETIF_DEBUG, (" addr ")); 511 ip4_addr_debug_print(NETIF_DEBUG, ipaddr); 512 LWIP_DEBUGF(NETIF_DEBUG, (" netmask ")); 513 ip4_addr_debug_print(NETIF_DEBUG, netmask); 514 LWIP_DEBUGF(NETIF_DEBUG, (" gw ")); 515 ip4_addr_debug_print(NETIF_DEBUG, gw); 516#endif /* LWIP_IPV4 */ 517 LWIP_DEBUGF(NETIF_DEBUG, ("\n")); 518 519 netif_invoke_ext_callback(netif, LWIP_NSC_NETIF_ADDED, NULL); 520 521 return netif; 522} 523 524static void 525netif_do_ip_addr_changed(const ip_addr_t *old_addr, const ip_addr_t *new_addr) 526{ 527#if LWIP_TCP 528 tcp_netif_ip_addr_changed(old_addr, new_addr); 529#endif /* LWIP_TCP */ 530#if LWIP_UDP 531 udp_netif_ip_addr_changed(old_addr, new_addr); 532#endif /* LWIP_UDP */ 533#if LWIP_RAW 534 raw_netif_ip_addr_changed(old_addr, new_addr); 535#endif /* LWIP_RAW */ 536} 537 538#if LWIP_IPV4 539static int 540netif_do_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr, ip_addr_t *old_addr) 541{ 542 LWIP_ASSERT("invalid pointer", ipaddr != NULL); 543 LWIP_ASSERT("invalid pointer", old_addr != NULL); 544 545 /* address is actually being changed? */ 546 if (ip4_addr_cmp(ipaddr, netif_ip4_addr(netif)) == 0) { 547 ip_addr_t new_addr; 548 *ip_2_ip4(&new_addr) = *ipaddr; 549 IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_V4); 550 551 ip_addr_copy(*old_addr, *netif_ip_addr4(netif)); 552 553 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); 554 netif_do_ip_addr_changed(old_addr, &new_addr); 555 556 mib2_remove_ip4(netif); 557 mib2_remove_route_ip4(0, netif); 558 /* set new IP address to netif */ 559 ip4_addr_set(ip_2_ip4(&netif->ip_addr), ipaddr); 560 IP_SET_TYPE_VAL(netif->ip_addr, IPADDR_TYPE_V4); 561 mib2_add_ip4(netif); 562 mib2_add_route_ip4(0, netif); 563 564 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4); 565 566 NETIF_STATUS_CALLBACK(netif); 567 return 1; /* address changed */ 568 } 569 return 0; /* address unchanged */ 570} 571 572/** 573 * @ingroup netif_ip4 574 * Change the IP address of a network interface 575 * 576 * @param netif the network interface to change 577 * @param ipaddr the new IP address 578 * 579 * @note call netif_set_addr() if you also want to change netmask and 580 * default gateway 581 */ 582void 583netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr) 584{ 585 ip_addr_t old_addr; 586 587 LWIP_ERROR("netif_set_ipaddr: invalid netif", netif != NULL, return); 588 589 /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ 590 if (ipaddr == NULL) { 591 ipaddr = IP4_ADDR_ANY4; 592 } 593 594 LWIP_ASSERT_CORE_LOCKED(); 595 596 if (netif_do_set_ipaddr(netif, ipaddr, &old_addr)) { 597#if LWIP_NETIF_EXT_STATUS_CALLBACK 598 netif_ext_callback_args_t args; 599 args.ipv4_changed.old_address = &old_addr; 600 netif_invoke_ext_callback(netif, LWIP_NSC_IPV4_ADDRESS_CHANGED, &args); 601#endif 602 } 603} 604 605static int 606netif_do_set_netmask(struct netif *netif, const ip4_addr_t *netmask, ip_addr_t *old_nm) 607{ 608 /* address is actually being changed? */ 609 if (ip4_addr_cmp(netmask, netif_ip4_netmask(netif)) == 0) { 610#if LWIP_NETIF_EXT_STATUS_CALLBACK 611 LWIP_ASSERT("invalid pointer", old_nm != NULL); 612 ip_addr_copy(*old_nm, *netif_ip_netmask4(netif)); 613#else 614 LWIP_UNUSED_ARG(old_nm); 615#endif 616 mib2_remove_route_ip4(0, netif); 617 /* set new netmask to netif */ 618 ip4_addr_set(ip_2_ip4(&netif->netmask), netmask); 619 IP_SET_TYPE_VAL(netif->netmask, IPADDR_TYPE_V4); 620 mib2_add_route_ip4(0, netif); 621 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", 622 netif->name[0], netif->name[1], 623 ip4_addr1_16(netif_ip4_netmask(netif)), 624 ip4_addr2_16(netif_ip4_netmask(netif)), 625 ip4_addr3_16(netif_ip4_netmask(netif)), 626 ip4_addr4_16(netif_ip4_netmask(netif)))); 627 return 1; /* netmask changed */ 628 } 629 return 0; /* netmask unchanged */ 630} 631 632/** 633 * @ingroup netif_ip4 634 * Change the netmask of a network interface 635 * 636 * @param netif the network interface to change 637 * @param netmask the new netmask 638 * 639 * @note call netif_set_addr() if you also want to change ip address and 640 * default gateway 641 */ 642void 643netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask) 644{ 645#if LWIP_NETIF_EXT_STATUS_CALLBACK 646 ip_addr_t old_nm_val; 647 ip_addr_t *old_nm = &old_nm_val; 648#else 649 ip_addr_t *old_nm = NULL; 650#endif 651 LWIP_ASSERT_CORE_LOCKED(); 652 653 LWIP_ERROR("netif_set_netmask: invalid netif", netif != NULL, return); 654 655 /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ 656 if (netmask == NULL) { 657 netmask = IP4_ADDR_ANY4; 658 } 659 660 if (netif_do_set_netmask(netif, netmask, old_nm)) { 661#if LWIP_NETIF_EXT_STATUS_CALLBACK 662 netif_ext_callback_args_t args; 663 args.ipv4_changed.old_netmask = old_nm; 664 netif_invoke_ext_callback(netif, LWIP_NSC_IPV4_NETMASK_CHANGED, &args); 665#endif 666 } 667} 668 669static int 670netif_do_set_gw(struct netif *netif, const ip4_addr_t *gw, ip_addr_t *old_gw) 671{ 672 /* address is actually being changed? */ 673 if (ip4_addr_cmp(gw, netif_ip4_gw(netif)) == 0) { 674#if LWIP_NETIF_EXT_STATUS_CALLBACK 675 LWIP_ASSERT("invalid pointer", old_gw != NULL); 676 ip_addr_copy(*old_gw, *netif_ip_gw4(netif)); 677#else 678 LWIP_UNUSED_ARG(old_gw); 679#endif 680 681 ip4_addr_set(ip_2_ip4(&netif->gw), gw); 682 IP_SET_TYPE_VAL(netif->gw, IPADDR_TYPE_V4); 683 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", 684 netif->name[0], netif->name[1], 685 ip4_addr1_16(netif_ip4_gw(netif)), 686 ip4_addr2_16(netif_ip4_gw(netif)), 687 ip4_addr3_16(netif_ip4_gw(netif)), 688 ip4_addr4_16(netif_ip4_gw(netif)))); 689 return 1; /* gateway changed */ 690 } 691 return 0; /* gateway unchanged */ 692} 693 694/** 695 * @ingroup netif_ip4 696 * Change the default gateway for a network interface 697 * 698 * @param netif the network interface to change 699 * @param gw the new default gateway 700 * 701 * @note call netif_set_addr() if you also want to change ip address and netmask 702 */ 703void 704netif_set_gw(struct netif *netif, const ip4_addr_t *gw) 705{ 706#if LWIP_NETIF_EXT_STATUS_CALLBACK 707 ip_addr_t old_gw_val; 708 ip_addr_t *old_gw = &old_gw_val; 709#else 710 ip_addr_t *old_gw = NULL; 711#endif 712 LWIP_ASSERT_CORE_LOCKED(); 713 714 LWIP_ERROR("netif_set_gw: invalid netif", netif != NULL, return); 715 716 /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ 717 if (gw == NULL) { 718 gw = IP4_ADDR_ANY4; 719 } 720 721 if (netif_do_set_gw(netif, gw, old_gw)) { 722#if LWIP_NETIF_EXT_STATUS_CALLBACK 723 netif_ext_callback_args_t args; 724 args.ipv4_changed.old_gw = old_gw; 725 netif_invoke_ext_callback(netif, LWIP_NSC_IPV4_GATEWAY_CHANGED, &args); 726#endif 727 } 728} 729 730/** 731 * @ingroup netif_ip4 732 * Change IP address configuration for a network interface (including netmask 733 * and default gateway). 734 * 735 * @param netif the network interface to change 736 * @param ipaddr the new IP address 737 * @param netmask the new netmask 738 * @param gw the new default gateway 739 */ 740void 741netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, 742 const ip4_addr_t *gw) 743{ 744#if LWIP_NETIF_EXT_STATUS_CALLBACK 745 netif_nsc_reason_t change_reason = LWIP_NSC_NONE; 746 netif_ext_callback_args_t cb_args; 747 ip_addr_t old_nm_val; 748 ip_addr_t old_gw_val; 749 ip_addr_t *old_nm = &old_nm_val; 750 ip_addr_t *old_gw = &old_gw_val; 751#else 752 ip_addr_t *old_nm = NULL; 753 ip_addr_t *old_gw = NULL; 754#endif 755 ip_addr_t old_addr; 756 int remove; 757 758 LWIP_ASSERT_CORE_LOCKED(); 759 760 /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ 761 if (ipaddr == NULL) { 762 ipaddr = IP4_ADDR_ANY4; 763 } 764 if (netmask == NULL) { 765 netmask = IP4_ADDR_ANY4; 766 } 767 if (gw == NULL) { 768 gw = IP4_ADDR_ANY4; 769 } 770 771 remove = ip4_addr_isany(ipaddr); 772 if (remove) { 773 /* when removing an address, we have to remove it *before* changing netmask/gw 774 to ensure that tcp RST segment can be sent correctly */ 775 if (netif_do_set_ipaddr(netif, ipaddr, &old_addr)) { 776#if LWIP_NETIF_EXT_STATUS_CALLBACK 777 change_reason |= LWIP_NSC_IPV4_ADDRESS_CHANGED; 778 cb_args.ipv4_changed.old_address = &old_addr; 779#endif 780 } 781 } 782 if (netif_do_set_netmask(netif, netmask, old_nm)) { 783#if LWIP_NETIF_EXT_STATUS_CALLBACK 784 change_reason |= LWIP_NSC_IPV4_NETMASK_CHANGED; 785 cb_args.ipv4_changed.old_netmask = old_nm; 786#endif 787 } 788 if (netif_do_set_gw(netif, gw, old_gw)) { 789#if LWIP_NETIF_EXT_STATUS_CALLBACK 790 change_reason |= LWIP_NSC_IPV4_GATEWAY_CHANGED; 791 cb_args.ipv4_changed.old_gw = old_gw; 792#endif 793 } 794 if (!remove) { 795 /* set ipaddr last to ensure netmask/gw have been set when status callback is called */ 796 if (netif_do_set_ipaddr(netif, ipaddr, &old_addr)) { 797#if LWIP_NETIF_EXT_STATUS_CALLBACK 798 change_reason |= LWIP_NSC_IPV4_ADDRESS_CHANGED; 799 cb_args.ipv4_changed.old_address = &old_addr; 800#endif 801 } 802 } 803 804#if LWIP_NETIF_EXT_STATUS_CALLBACK 805 if (change_reason != LWIP_NSC_NONE) { 806 change_reason |= LWIP_NSC_IPV4_SETTINGS_CHANGED; 807 netif_invoke_ext_callback(netif, change_reason, &cb_args); 808 } 809#endif 810} 811#endif /* LWIP_IPV4*/ 812 813/** 814 * @ingroup netif 815 * Remove a network interface from the list of lwIP netifs. 816 * 817 * @param netif the network interface to remove 818 */ 819void 820netif_remove(struct netif *netif) 821{ 822#if LWIP_IPV6 823 int i; 824#endif 825 826 LWIP_ASSERT_CORE_LOCKED(); 827 828 if (netif == NULL) { 829 return; 830 } 831#ifdef LOSCFG_NET_CONTAINER 832 struct net_group *group = get_net_group_from_netif(netif); 833 834 if (group == NULL) { 835 return; 836 } 837#endif 838 netif_invoke_ext_callback(netif, LWIP_NSC_NETIF_REMOVED, NULL); 839 840#if LWIP_IPV4 841 if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { 842 netif_do_ip_addr_changed(netif_ip_addr4(netif), NULL); 843 } 844 845#if LWIP_IGMP 846 /* stop IGMP processing */ 847 if (netif->flags & NETIF_FLAG_IGMP) { 848 igmp_stop(netif); 849 } 850#endif /* LWIP_IGMP */ 851#endif /* LWIP_IPV4*/ 852 853#if LWIP_IPV6 854 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 855 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { 856 netif_do_ip_addr_changed(netif_ip_addr6(netif, i), NULL); 857 } 858 } 859#if LWIP_IPV6_MLD 860 /* stop MLD processing */ 861 mld6_stop(netif); 862#endif /* LWIP_IPV6_MLD */ 863#endif /* LWIP_IPV6 */ 864 if (netif_is_up(netif)) { 865 /* set netif down before removing (call callback function) */ 866 netif_set_down(netif); 867 } 868 869 mib2_remove_ip4(netif); 870 871 /* this netif is default? */ 872#ifdef LOSCFG_NET_CONTAINER 873 if (group->netif_default == netif) { 874#else 875 if (netif_default == netif) { 876#endif 877 /* reset default netif */ 878#ifdef LOSCFG_NET_CONTAINER 879 netif_set_default(NULL, group); 880#else 881 netif_set_default(NULL); 882#endif 883 } 884#if !LWIP_SINGLE_NETIF 885 /* is it the first netif? */ 886#ifdef LOSCFG_NET_CONTAINER 887 if (group->netif_list == netif) { 888 group->netif_list = netif->next; 889#else 890 if (netif_list == netif) { 891 netif_list = netif->next; 892#endif 893 } else { 894 /* look for netif further down the list */ 895 struct netif *tmp_netif; 896#ifdef LOSCFG_NET_CONTAINER 897 NETIF_FOREACH(tmp_netif, group) { 898#else 899 NETIF_FOREACH(tmp_netif) { 900#endif 901 if (tmp_netif->next == netif) { 902 tmp_netif->next = netif->next; 903 break; 904 } 905 } 906 if (tmp_netif == NULL) { 907 return; /* netif is not on the list */ 908 } 909 } 910#endif /* !LWIP_SINGLE_NETIF */ 911 mib2_netif_removed(netif); 912#if LWIP_NETIF_REMOVE_CALLBACK 913 if (netif->remove_callback) { 914 netif->remove_callback(netif); 915 } 916#endif /* LWIP_NETIF_REMOVE_CALLBACK */ 917 LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); 918} 919 920/** 921 * @ingroup netif 922 * Set a network interface as the default network interface 923 * (used to output all packets for which no specific route is found) 924 * 925 * @param netif the default network interface 926 */ 927void 928#ifdef LOSCFG_NET_CONTAINER 929netif_set_default(struct netif *netif, struct net_group *group) 930#else 931netif_set_default(struct netif *netif) 932#endif 933{ 934 LWIP_ASSERT_CORE_LOCKED(); 935 936 if (netif == NULL) { 937 /* remove default route */ 938 mib2_remove_route_ip4(1, netif); 939 } else { 940 /* install default route */ 941 mib2_add_route_ip4(1, netif); 942 } 943#ifdef LOSCFG_NET_CONTAINER 944 group->netif_default = netif; 945#else 946 netif_default = netif; 947#endif 948 LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", 949 netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); 950} 951 952#ifdef LOSCFG_NET_CONTAINER 953void 954netif_set_default2(struct netif *netif) 955{ 956 netif_set_default(netif, get_curr_process_net_group()); 957} 958#endif 959/** 960 * @ingroup netif 961 * Bring an interface up, available for processing 962 * traffic. 963 */ 964void 965netif_set_up(struct netif *netif) 966{ 967 LWIP_ASSERT_CORE_LOCKED(); 968 969 LWIP_ERROR("netif_set_up: invalid netif", netif != NULL, return); 970 971 if (!(netif->flags & NETIF_FLAG_UP)) { 972 netif_set_flags(netif, NETIF_FLAG_UP); 973 974 MIB2_COPY_SYSUPTIME_TO(&netif->ts); 975 976 NETIF_STATUS_CALLBACK(netif); 977 978#if LWIP_NETIF_EXT_STATUS_CALLBACK 979 { 980 netif_ext_callback_args_t args; 981 args.status_changed.state = 1; 982 netif_invoke_ext_callback(netif, LWIP_NSC_STATUS_CHANGED, &args); 983 } 984#endif 985 986 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4 | NETIF_REPORT_TYPE_IPV6); 987#if LWIP_IPV6 988 nd6_restart_netif(netif); 989#endif /* LWIP_IPV6 */ 990 } 991} 992 993/** Send ARP/IGMP/MLD/RS events, e.g. on link-up/netif-up or addr-change 994 */ 995static void 996netif_issue_reports(struct netif *netif, u8_t report_type) 997{ 998 LWIP_ASSERT("netif_issue_reports: invalid netif", netif != NULL); 999 1000 /* Only send reports when both link and admin states are up */ 1001 if (!(netif->flags & NETIF_FLAG_LINK_UP) || 1002 !(netif->flags & NETIF_FLAG_UP)) { 1003 return; 1004 } 1005 1006#if LWIP_IPV4 1007 if ((report_type & NETIF_REPORT_TYPE_IPV4) && 1008 !ip4_addr_isany_val(*netif_ip4_addr(netif))) { 1009#if LWIP_ARP 1010 /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ 1011 if (netif->flags & (NETIF_FLAG_ETHARP)) { 1012 etharp_gratuitous(netif); 1013 } 1014#endif /* LWIP_ARP */ 1015 1016#if LWIP_IGMP 1017 /* resend IGMP memberships */ 1018 if (netif->flags & NETIF_FLAG_IGMP) { 1019 igmp_report_groups(netif); 1020 } 1021#endif /* LWIP_IGMP */ 1022 } 1023#endif /* LWIP_IPV4 */ 1024 1025#if LWIP_IPV6 1026 if (report_type & NETIF_REPORT_TYPE_IPV6) { 1027#if LWIP_IPV6_MLD 1028 /* send mld memberships */ 1029 mld6_report_groups(netif); 1030#endif /* LWIP_IPV6_MLD */ 1031 } 1032#endif /* LWIP_IPV6 */ 1033} 1034 1035/** 1036 * @ingroup netif 1037 * Bring an interface down, disabling any traffic processing. 1038 */ 1039void 1040netif_set_down(struct netif *netif) 1041{ 1042 LWIP_ASSERT_CORE_LOCKED(); 1043 1044 LWIP_ERROR("netif_set_down: invalid netif", netif != NULL, return); 1045 1046 if (netif->flags & NETIF_FLAG_UP) { 1047#if LWIP_NETIF_EXT_STATUS_CALLBACK 1048 { 1049 netif_ext_callback_args_t args; 1050 args.status_changed.state = 0; 1051 netif_invoke_ext_callback(netif, LWIP_NSC_STATUS_CHANGED, &args); 1052 } 1053#endif 1054 1055 netif_clear_flags(netif, NETIF_FLAG_UP); 1056 MIB2_COPY_SYSUPTIME_TO(&netif->ts); 1057 1058#if LWIP_IPV4 && LWIP_ARP 1059 if (netif->flags & NETIF_FLAG_ETHARP) { 1060 etharp_cleanup_netif(netif); 1061 } 1062#endif /* LWIP_IPV4 && LWIP_ARP */ 1063 1064#if LWIP_IPV6 1065 nd6_cleanup_netif(netif); 1066#endif /* LWIP_IPV6 */ 1067 1068 NETIF_STATUS_CALLBACK(netif); 1069 } 1070} 1071 1072#if LWIP_NETIF_STATUS_CALLBACK 1073/** 1074 * @ingroup netif 1075 * Set callback to be called when interface is brought up/down or address is changed while up 1076 */ 1077void 1078netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback) 1079{ 1080 LWIP_ASSERT_CORE_LOCKED(); 1081 1082 if (netif) { 1083 netif->status_callback = status_callback; 1084 } 1085} 1086#endif /* LWIP_NETIF_STATUS_CALLBACK */ 1087 1088#if LWIP_NETIF_REMOVE_CALLBACK 1089/** 1090 * @ingroup netif 1091 * Set callback to be called when the interface has been removed 1092 */ 1093void 1094netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback) 1095{ 1096 LWIP_ASSERT_CORE_LOCKED(); 1097 1098 if (netif) { 1099 netif->remove_callback = remove_callback; 1100 } 1101} 1102#endif /* LWIP_NETIF_REMOVE_CALLBACK */ 1103 1104/** 1105 * @ingroup netif 1106 * Called by a driver when its link goes up 1107 */ 1108void 1109netif_set_link_up(struct netif *netif) 1110{ 1111 LWIP_ASSERT_CORE_LOCKED(); 1112 1113 LWIP_ERROR("netif_set_link_up: invalid netif", netif != NULL, return); 1114 1115 if (!(netif->flags & NETIF_FLAG_LINK_UP)) { 1116 netif_set_flags(netif, NETIF_FLAG_LINK_UP); 1117 1118#if LWIP_DHCP 1119 dhcp_network_changed(netif); 1120#endif /* LWIP_DHCP */ 1121 1122#if LWIP_AUTOIP 1123 autoip_network_changed(netif); 1124#endif /* LWIP_AUTOIP */ 1125 1126 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4 | NETIF_REPORT_TYPE_IPV6); 1127#if LWIP_IPV6 1128 nd6_restart_netif(netif); 1129#endif /* LWIP_IPV6 */ 1130 1131 NETIF_LINK_CALLBACK(netif); 1132#if LWIP_NETIF_EXT_STATUS_CALLBACK 1133 { 1134 netif_ext_callback_args_t args; 1135 args.link_changed.state = 1; 1136 netif_invoke_ext_callback(netif, LWIP_NSC_LINK_CHANGED, &args); 1137 } 1138#endif 1139 } 1140} 1141 1142/** 1143 * @ingroup netif 1144 * Called by a driver when its link goes down 1145 */ 1146void 1147netif_set_link_down(struct netif *netif) 1148{ 1149 LWIP_ASSERT_CORE_LOCKED(); 1150 1151 LWIP_ERROR("netif_set_link_down: invalid netif", netif != NULL, return); 1152 1153 if (netif->flags & NETIF_FLAG_LINK_UP) { 1154 netif_clear_flags(netif, NETIF_FLAG_LINK_UP); 1155#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES 1156 netif->mtu6 = netif->mtu; 1157#endif 1158 1159 NETIF_LINK_CALLBACK(netif); 1160#if LWIP_NETIF_EXT_STATUS_CALLBACK 1161 { 1162 netif_ext_callback_args_t args; 1163 args.link_changed.state = 0; 1164 netif_invoke_ext_callback(netif, LWIP_NSC_LINK_CHANGED, &args); 1165 } 1166#endif 1167 } 1168} 1169 1170#if LWIP_NETIF_LINK_CALLBACK 1171/** 1172 * @ingroup netif 1173 * Set callback to be called when link is brought up/down 1174 */ 1175void 1176netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback) 1177{ 1178 LWIP_ASSERT_CORE_LOCKED(); 1179 1180 if (netif) { 1181 netif->link_callback = link_callback; 1182 } 1183} 1184#endif /* LWIP_NETIF_LINK_CALLBACK */ 1185 1186#if ENABLE_LOOPBACK 1187/** 1188 * @ingroup netif 1189 * Send an IP packet to be received on the same netif (loopif-like). 1190 * The pbuf is copied and added to an internal queue which is fed to 1191 * netif->input by netif_poll(). 1192 * In multithreaded mode, the call to netif_poll() is queued to be done on the 1193 * TCP/IP thread. 1194 * In callback mode, the user has the responsibility to call netif_poll() in 1195 * the main loop of their application. 1196 * 1197 * @param netif the lwip network interface structure 1198 * @param p the (IP) packet to 'send' 1199 * @return ERR_OK if the packet has been sent 1200 * ERR_MEM if the pbuf used to copy the packet couldn't be allocated 1201 */ 1202err_t 1203netif_loop_output(struct netif *netif, struct pbuf *p) 1204{ 1205 struct pbuf *r; 1206 err_t err; 1207 struct pbuf *last; 1208#if LWIP_LOOPBACK_MAX_PBUFS 1209 u16_t clen = 0; 1210#endif /* LWIP_LOOPBACK_MAX_PBUFS */ 1211 /* If we have a loopif, SNMP counters are adjusted for it, 1212 * if not they are adjusted for 'netif'. */ 1213#if MIB2_STATS 1214#if LWIP_HAVE_LOOPIF 1215#ifdef LOSCFG_NET_CONTAINER 1216 struct netif *stats_if = get_net_group_from_netif(netif)->loop_netif; 1217#else 1218 struct netif *stats_if = &loop_netif; 1219#endif 1220#else /* LWIP_HAVE_LOOPIF */ 1221 struct netif *stats_if = netif; 1222#endif /* LWIP_HAVE_LOOPIF */ 1223#endif /* MIB2_STATS */ 1224#if LWIP_NETIF_LOOPBACK_MULTITHREADING 1225 u8_t schedule_poll = 0; 1226#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 1227 SYS_ARCH_DECL_PROTECT(lev); 1228 1229 LWIP_ASSERT("netif_loop_output: invalid netif", netif != NULL); 1230 LWIP_ASSERT("netif_loop_output: invalid pbuf", p != NULL); 1231 1232 /* Allocate a new pbuf */ 1233 r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); 1234 if (r == NULL) { 1235 LINK_STATS_INC(link.memerr); 1236 LINK_STATS_INC(link.drop); 1237 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); 1238 return ERR_MEM; 1239 } 1240#if LWIP_LOOPBACK_MAX_PBUFS 1241 clen = pbuf_clen(r); 1242 /* check for overflow or too many pbuf on queue */ 1243 if (((netif->loop_cnt_current + clen) < netif->loop_cnt_current) || 1244 ((netif->loop_cnt_current + clen) > LWIP_MIN(LWIP_LOOPBACK_MAX_PBUFS, 0xFFFF))) { 1245 pbuf_free(r); 1246 LINK_STATS_INC(link.memerr); 1247 LINK_STATS_INC(link.drop); 1248 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); 1249 return ERR_MEM; 1250 } 1251 netif->loop_cnt_current = (u16_t)(netif->loop_cnt_current + clen); 1252#endif /* LWIP_LOOPBACK_MAX_PBUFS */ 1253 1254 /* Copy the whole pbuf queue p into the single pbuf r */ 1255 if ((err = pbuf_copy(r, p)) != ERR_OK) { 1256 pbuf_free(r); 1257 LINK_STATS_INC(link.memerr); 1258 LINK_STATS_INC(link.drop); 1259 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); 1260 return err; 1261 } 1262 1263 /* Put the packet on a linked list which gets emptied through calling 1264 netif_poll(). */ 1265 1266 /* let last point to the last pbuf in chain r */ 1267 for (last = r; last->next != NULL; last = last->next) { 1268 /* nothing to do here, just get to the last pbuf */ 1269 } 1270 1271 SYS_ARCH_PROTECT(lev); 1272 if (netif->loop_first != NULL) { 1273 LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); 1274 netif->loop_last->next = r; 1275 netif->loop_last = last; 1276#if LWIP_NETIF_LOOPBACK_MULTITHREADING 1277 if (netif->reschedule_poll) { 1278 schedule_poll = 1; 1279 netif->reschedule_poll = 0; 1280 } 1281#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 1282 } else { 1283 netif->loop_first = r; 1284 netif->loop_last = last; 1285#if LWIP_NETIF_LOOPBACK_MULTITHREADING 1286 /* No existing packets queued, schedule poll */ 1287 schedule_poll = 1; 1288#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 1289 } 1290 SYS_ARCH_UNPROTECT(lev); 1291 1292 LINK_STATS_INC(link.xmit); 1293 MIB2_STATS_NETIF_ADD(stats_if, ifoutoctets, p->tot_len); 1294 MIB2_STATS_NETIF_INC(stats_if, ifoutucastpkts); 1295 1296#if LWIP_NETIF_LOOPBACK_MULTITHREADING 1297 /* For multithreading environment, schedule a call to netif_poll */ 1298 if (schedule_poll) { 1299 if (tcpip_try_callback((tcpip_callback_fn)netif_poll, netif) != ERR_OK) { 1300 SYS_ARCH_PROTECT(lev); 1301 netif->reschedule_poll = 1; 1302 SYS_ARCH_UNPROTECT(lev); 1303 } 1304 } 1305#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 1306 1307 return ERR_OK; 1308} 1309 1310#if LWIP_HAVE_LOOPIF 1311#if LWIP_IPV4 1312static err_t 1313netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) 1314{ 1315 LWIP_UNUSED_ARG(addr); 1316 return netif_loop_output(netif, p); 1317} 1318#endif /* LWIP_IPV4 */ 1319 1320#if LWIP_IPV6 1321static err_t 1322netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr) 1323{ 1324 LWIP_UNUSED_ARG(addr); 1325 return netif_loop_output(netif, p); 1326} 1327#endif /* LWIP_IPV6 */ 1328#endif /* LWIP_HAVE_LOOPIF */ 1329 1330 1331/** 1332 * Call netif_poll() in the main loop of your application. This is to prevent 1333 * reentering non-reentrant functions like tcp_input(). Packets passed to 1334 * netif_loop_output() are put on a list that is passed to netif->input() by 1335 * netif_poll(). 1336 */ 1337void 1338netif_poll(struct netif *netif) 1339{ 1340 /* If we have a loopif, SNMP counters are adjusted for it, 1341 * if not they are adjusted for 'netif'. */ 1342#if MIB2_STATS 1343#if LWIP_HAVE_LOOPIF 1344#ifdef LOSCFG_NET_CONTAINER 1345 struct netif *stats_if = get_net_group_from_netif(netif)->loop_netif; 1346#else 1347 struct netif *stats_if = &loop_netif; 1348#endif 1349#else /* LWIP_HAVE_LOOPIF */ 1350 struct netif *stats_if = netif; 1351#endif /* LWIP_HAVE_LOOPIF */ 1352#endif /* MIB2_STATS */ 1353 SYS_ARCH_DECL_PROTECT(lev); 1354 1355 LWIP_ASSERT("netif_poll: invalid netif", netif != NULL); 1356 1357 /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ 1358 SYS_ARCH_PROTECT(lev); 1359 while (netif->loop_first != NULL) { 1360 struct pbuf *in, *in_end; 1361#if LWIP_LOOPBACK_MAX_PBUFS 1362 u8_t clen = 1; 1363#endif /* LWIP_LOOPBACK_MAX_PBUFS */ 1364 1365 in = in_end = netif->loop_first; 1366 while (in_end->len != in_end->tot_len) { 1367 LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); 1368 in_end = in_end->next; 1369#if LWIP_LOOPBACK_MAX_PBUFS 1370 clen++; 1371#endif /* LWIP_LOOPBACK_MAX_PBUFS */ 1372 } 1373#if LWIP_LOOPBACK_MAX_PBUFS 1374 /* adjust the number of pbufs on queue */ 1375 LWIP_ASSERT("netif->loop_cnt_current underflow", 1376 ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); 1377 netif->loop_cnt_current = (u16_t)(netif->loop_cnt_current - clen); 1378#endif /* LWIP_LOOPBACK_MAX_PBUFS */ 1379 1380 /* 'in_end' now points to the last pbuf from 'in' */ 1381 if (in_end == netif->loop_last) { 1382 /* this was the last pbuf in the list */ 1383 netif->loop_first = netif->loop_last = NULL; 1384 } else { 1385 /* pop the pbuf off the list */ 1386 netif->loop_first = in_end->next; 1387 LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL); 1388 } 1389 /* De-queue the pbuf from its successors on the 'loop_' list. */ 1390 in_end->next = NULL; 1391 SYS_ARCH_UNPROTECT(lev); 1392 1393 in->if_idx = netif_get_index(netif); 1394 1395 LINK_STATS_INC(link.recv); 1396 MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len); 1397 MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts); 1398 /* loopback packets are always IP packets! */ 1399 if (ip_input(in, netif) != ERR_OK) { 1400 pbuf_free(in); 1401 } 1402 SYS_ARCH_PROTECT(lev); 1403 } 1404 SYS_ARCH_UNPROTECT(lev); 1405} 1406 1407#if !LWIP_NETIF_LOOPBACK_MULTITHREADING 1408/** 1409 * Calls netif_poll() for every netif on the netif_list. 1410 */ 1411void 1412netif_poll_all(void) 1413{ 1414 struct netif *netif; 1415 /* loop through netifs */ 1416 NETIF_FOREACH(netif) { 1417 netif_poll(netif); 1418 } 1419} 1420#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ 1421#endif /* ENABLE_LOOPBACK */ 1422 1423#if LWIP_NUM_NETIF_CLIENT_DATA > 0 1424/** 1425 * @ingroup netif_cd 1426 * Allocate an index to store data in client_data member of struct netif. 1427 * Returned value is an index in mentioned array. 1428 * @see LWIP_NUM_NETIF_CLIENT_DATA 1429 */ 1430u8_t 1431netif_alloc_client_data_id(void) 1432{ 1433 u8_t result = netif_client_id; 1434 netif_client_id++; 1435 1436 LWIP_ASSERT_CORE_LOCKED(); 1437 1438#if LWIP_NUM_NETIF_CLIENT_DATA > 256 1439#error LWIP_NUM_NETIF_CLIENT_DATA must be <= 256 1440#endif 1441 LWIP_ASSERT("Increase LWIP_NUM_NETIF_CLIENT_DATA in lwipopts.h", result < LWIP_NUM_NETIF_CLIENT_DATA); 1442 return (u8_t)(result + LWIP_NETIF_CLIENT_DATA_INDEX_MAX); 1443} 1444#endif 1445 1446#if LWIP_IPV6 1447/** 1448 * @ingroup netif_ip6 1449 * Change an IPv6 address of a network interface 1450 * 1451 * @param netif the network interface to change 1452 * @param addr_idx index of the IPv6 address 1453 * @param addr6 the new IPv6 address 1454 * 1455 * @note call netif_ip6_addr_set_state() to set the address valid/temptative 1456 */ 1457void 1458netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6) 1459{ 1460 LWIP_ASSERT_CORE_LOCKED(); 1461 1462 LWIP_ASSERT("netif_ip6_addr_set: invalid netif", netif != NULL); 1463 LWIP_ASSERT("netif_ip6_addr_set: invalid addr6", addr6 != NULL); 1464 1465 netif_ip6_addr_set_parts(netif, addr_idx, addr6->addr[0], addr6->addr[1], 1466 addr6->addr[2], addr6->addr[3]); 1467} 1468 1469/* 1470 * Change an IPv6 address of a network interface (internal version taking 4 * u32_t) 1471 * 1472 * @param netif the network interface to change 1473 * @param addr_idx index of the IPv6 address 1474 * @param i0 word0 of the new IPv6 address 1475 * @param i1 word1 of the new IPv6 address 1476 * @param i2 word2 of the new IPv6 address 1477 * @param i3 word3 of the new IPv6 address 1478 */ 1479void 1480netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3) 1481{ 1482 ip_addr_t old_addr; 1483 ip_addr_t new_ipaddr; 1484 LWIP_ASSERT_CORE_LOCKED(); 1485 LWIP_ASSERT("netif != NULL", netif != NULL); 1486 LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); 1487 1488 ip6_addr_copy(*ip_2_ip6(&old_addr), *netif_ip6_addr(netif, addr_idx)); 1489 IP_SET_TYPE_VAL(old_addr, IPADDR_TYPE_V6); 1490 1491 /* address is actually being changed? */ 1492 if ((ip_2_ip6(&old_addr)->addr[0] != i0) || (ip_2_ip6(&old_addr)->addr[1] != i1) || 1493 (ip_2_ip6(&old_addr)->addr[2] != i2) || (ip_2_ip6(&old_addr)->addr[3] != i3)) { 1494 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set: netif address being changed\n")); 1495 1496 IP_ADDR6(&new_ipaddr, i0, i1, i2, i3); 1497 ip6_addr_assign_zone(ip_2_ip6(&new_ipaddr), IP6_UNICAST, netif); 1498 1499 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, addr_idx))) { 1500 netif_do_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); 1501 } 1502 /* @todo: remove/readd mib2 ip6 entries? */ 1503 1504 ip_addr_copy(netif->ip6_addr[addr_idx], new_ipaddr); 1505 1506 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, addr_idx))) { 1507 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); 1508 NETIF_STATUS_CALLBACK(netif); 1509 } 1510 1511#if LWIP_NETIF_EXT_STATUS_CALLBACK 1512 { 1513 netif_ext_callback_args_t args; 1514 args.ipv6_set.addr_index = addr_idx; 1515 args.ipv6_set.old_address = &old_addr; 1516 netif_invoke_ext_callback(netif, LWIP_NSC_IPV6_SET, &args); 1517 } 1518#endif 1519 } 1520 1521 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", 1522 addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), 1523 netif_ip6_addr_state(netif, addr_idx))); 1524} 1525 1526/** 1527 * @ingroup netif_ip6 1528 * Change the state of an IPv6 address of a network interface 1529 * (INVALID, TEMPTATIVE, PREFERRED, DEPRECATED, where TEMPTATIVE 1530 * includes the number of checks done, see ip6_addr.h) 1531 * 1532 * @param netif the network interface to change 1533 * @param addr_idx index of the IPv6 address 1534 * @param state the new IPv6 address state 1535 */ 1536void 1537netif_ip6_addr_set_state(struct netif *netif, s8_t addr_idx, u8_t state) 1538{ 1539 u8_t old_state; 1540 LWIP_ASSERT_CORE_LOCKED(); 1541 LWIP_ASSERT("netif != NULL", netif != NULL); 1542 LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); 1543 1544 old_state = netif_ip6_addr_state(netif, addr_idx); 1545 /* state is actually being changed? */ 1546 if (old_state != state) { 1547 u8_t old_valid = old_state & IP6_ADDR_VALID; 1548 u8_t new_valid = state & IP6_ADDR_VALID; 1549 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n")); 1550 1551#if LWIP_IPV6_MLD 1552 /* Reevaluate solicited-node multicast group membership. */ 1553 if (netif->flags & NETIF_FLAG_MLD6) { 1554 nd6_adjust_mld_membership(netif, addr_idx, state); 1555 } 1556#endif /* LWIP_IPV6_MLD */ 1557 1558 if (old_valid && !new_valid) { 1559 /* address about to be removed by setting invalid */ 1560 netif_do_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); 1561 /* @todo: remove mib2 ip6 entries? */ 1562 } 1563 netif->ip6_addr_state[addr_idx] = state; 1564 1565 if (!old_valid && new_valid) { 1566 /* address added by setting valid */ 1567 /* This is a good moment to check that the address is properly zoned. */ 1568 IP6_ADDR_ZONECHECK_NETIF(netif_ip6_addr(netif, addr_idx), netif); 1569 /* @todo: add mib2 ip6 entries? */ 1570 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); 1571 } 1572 if ((old_state & ~IP6_ADDR_TENTATIVE_COUNT_MASK) != 1573 (state & ~IP6_ADDR_TENTATIVE_COUNT_MASK)) { 1574 /* address state has changed -> call the callback function */ 1575 NETIF_STATUS_CALLBACK(netif); 1576 } 1577 1578#if LWIP_NETIF_EXT_STATUS_CALLBACK 1579 { 1580 netif_ext_callback_args_t args; 1581 args.ipv6_addr_state_changed.addr_index = addr_idx; 1582 args.ipv6_addr_state_changed.old_state = old_state; 1583 args.ipv6_addr_state_changed.address = netif_ip_addr6(netif, addr_idx); 1584 netif_invoke_ext_callback(netif, LWIP_NSC_IPV6_ADDR_STATE_CHANGED, &args); 1585 } 1586#endif 1587 } 1588 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", 1589 addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), 1590 netif_ip6_addr_state(netif, addr_idx))); 1591} 1592 1593/** 1594 * Checks if a specific local address is present on the netif and returns its 1595 * index. Depending on its state, it may or may not be assigned to the 1596 * interface (as per RFC terminology). 1597 * 1598 * The given address may or may not be zoned (i.e., have a zone index other 1599 * than IP6_NO_ZONE). If the address is zoned, it must have the correct zone 1600 * for the given netif, or no match will be found. 1601 * 1602 * @param netif the netif to check 1603 * @param ip6addr the IPv6 address to find 1604 * @return >= 0: address found, this is its index 1605 * -1: address not found on this netif 1606 */ 1607s8_t 1608netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr) 1609{ 1610 s8_t i; 1611 1612 LWIP_ASSERT_CORE_LOCKED(); 1613 1614 LWIP_ASSERT("netif_get_ip6_addr_match: invalid netif", netif != NULL); 1615 LWIP_ASSERT("netif_get_ip6_addr_match: invalid ip6addr", ip6addr != NULL); 1616 1617#if LWIP_IPV6_SCOPES 1618 if (ip6_addr_has_zone(ip6addr) && !ip6_addr_test_zone(ip6addr, netif)) { 1619 return -1; /* wrong zone, no match */ 1620 } 1621#endif /* LWIP_IPV6_SCOPES */ 1622 1623 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 1624 if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) && 1625 ip6_addr_cmp_zoneless(netif_ip6_addr(netif, i), ip6addr)) { 1626 return i; 1627 } 1628 } 1629 return -1; 1630} 1631 1632/** 1633 * @ingroup netif_ip6 1634 * Create a link-local IPv6 address on a netif (stored in slot 0) 1635 * 1636 * @param netif the netif to create the address on 1637 * @param from_mac_48bit if != 0, assume hwadr is a 48-bit MAC address (std conversion) 1638 * if == 0, use hwaddr directly as interface ID 1639 */ 1640void 1641netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit) 1642{ 1643 u8_t i, addr_index; 1644 1645 LWIP_ASSERT_CORE_LOCKED(); 1646 1647 LWIP_ASSERT("netif_create_ip6_linklocal_address: invalid netif", netif != NULL); 1648 1649 /* Link-local prefix. */ 1650 ip_2_ip6(&netif->ip6_addr[0])->addr[0] = PP_HTONL(0xfe800000ul); 1651 ip_2_ip6(&netif->ip6_addr[0])->addr[1] = 0; 1652 1653 /* Generate interface ID. */ 1654 if (from_mac_48bit) { 1655 /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */ 1656 ip_2_ip6(&netif->ip6_addr[0])->addr[2] = lwip_htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) | 1657 ((u32_t)(netif->hwaddr[1]) << 16) | 1658 ((u32_t)(netif->hwaddr[2]) << 8) | 1659 (0xff)); 1660 ip_2_ip6(&netif->ip6_addr[0])->addr[3] = lwip_htonl((u32_t)(0xfeul << 24) | 1661 ((u32_t)(netif->hwaddr[3]) << 16) | 1662 ((u32_t)(netif->hwaddr[4]) << 8) | 1663 (netif->hwaddr[5])); 1664 } else { 1665 /* Use hwaddr directly as interface ID. */ 1666 ip_2_ip6(&netif->ip6_addr[0])->addr[2] = 0; 1667 ip_2_ip6(&netif->ip6_addr[0])->addr[3] = 0; 1668 1669 addr_index = 3; 1670 for (i = 0; (i < 8) && (i < netif->hwaddr_len); i++) { 1671 if (i == 4) { 1672 addr_index--; 1673 } 1674 ip_2_ip6(&netif->ip6_addr[0])->addr[addr_index] |= lwip_htonl(((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03))); 1675 } 1676 } 1677 1678 /* Set a link-local zone. Even though the zone is implied by the owning 1679 * netif, setting the zone anyway has two important conceptual advantages: 1680 * 1) it avoids the need for a ton of exceptions in internal code, allowing 1681 * e.g. ip6_addr_cmp() to be used on local addresses; 1682 * 2) the properly zoned address is visible externally, e.g. when any outside 1683 * code enumerates available addresses or uses one to bind a socket. 1684 * Any external code unaware of address scoping is likely to just ignore the 1685 * zone field, so this should not create any compatibility problems. */ 1686 ip6_addr_assign_zone(ip_2_ip6(&netif->ip6_addr[0]), IP6_UNICAST, netif); 1687 1688 /* Set address state. */ 1689#if LWIP_IPV6_DUP_DETECT_ATTEMPTS 1690 /* Will perform duplicate address detection (DAD). */ 1691 netif_ip6_addr_set_state(netif, 0, IP6_ADDR_TENTATIVE); 1692#else 1693 /* Consider address valid. */ 1694 netif_ip6_addr_set_state(netif, 0, IP6_ADDR_PREFERRED); 1695#endif /* LWIP_IPV6_AUTOCONFIG */ 1696} 1697 1698/** 1699 * @ingroup netif_ip6 1700 * This function allows for the easy addition of a new IPv6 address to an interface. 1701 * It takes care of finding an empty slot and then sets the address tentative 1702 * (to make sure that all the subsequent processing happens). 1703 * 1704 * @param netif netif to add the address on 1705 * @param ip6addr address to add 1706 * @param chosen_idx if != NULL, the chosen IPv6 address index will be stored here 1707 */ 1708err_t 1709netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx) 1710{ 1711 s8_t i; 1712 1713 LWIP_ASSERT_CORE_LOCKED(); 1714 1715 LWIP_ASSERT("netif_add_ip6_address: invalid netif", netif != NULL); 1716 LWIP_ASSERT("netif_add_ip6_address: invalid ip6addr", ip6addr != NULL); 1717 1718 i = netif_get_ip6_addr_match(netif, ip6addr); 1719 if (i >= 0) { 1720 /* Address already added */ 1721 if (chosen_idx != NULL) { 1722 *chosen_idx = i; 1723 } 1724 return ERR_OK; 1725 } 1726 1727 /* Find a free slot. The first one is reserved for link-local addresses. */ 1728 for (i = ip6_addr_islinklocal(ip6addr) ? 0 : 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 1729 if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) { 1730 ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr); 1731 ip6_addr_assign_zone(ip_2_ip6(&netif->ip6_addr[i]), IP6_UNICAST, netif); 1732 netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE); 1733 if (chosen_idx != NULL) { 1734 *chosen_idx = i; 1735 } 1736 return ERR_OK; 1737 } 1738 } 1739 1740 if (chosen_idx != NULL) { 1741 *chosen_idx = -1; 1742 } 1743 return ERR_VAL; 1744} 1745 1746/** Dummy IPv6 output function for netifs not supporting IPv6 1747 */ 1748static err_t 1749netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr) 1750{ 1751 LWIP_UNUSED_ARG(netif); 1752 LWIP_UNUSED_ARG(p); 1753 LWIP_UNUSED_ARG(ipaddr); 1754 1755 return ERR_IF; 1756} 1757#endif /* LWIP_IPV6 */ 1758 1759#if LWIP_IPV4 1760/** Dummy IPv4 output function for netifs not supporting IPv4 1761 */ 1762static err_t 1763netif_null_output_ip4(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr) 1764{ 1765 LWIP_UNUSED_ARG(netif); 1766 LWIP_UNUSED_ARG(p); 1767 LWIP_UNUSED_ARG(ipaddr); 1768 1769 return ERR_IF; 1770} 1771#endif /* LWIP_IPV4 */ 1772 1773/** 1774* @ingroup netif 1775* Return the interface index for the netif with name 1776* or NETIF_NO_INDEX if not found/on error 1777* 1778* @param name the name of the netif 1779*/ 1780u8_t 1781netif_name_to_index(const char *name) 1782{ 1783 struct netif *netif = netif_find(name); 1784 if (netif != NULL) { 1785 return netif_get_index(netif); 1786 } 1787 /* No name found, return invalid index */ 1788 return NETIF_NO_INDEX; 1789} 1790 1791/** 1792* @ingroup netif 1793* Return the interface name for the netif matching index 1794* or NULL if not found/on error 1795* 1796* @param idx the interface index of the netif 1797* @param name char buffer of at least NETIF_NAMESIZE bytes 1798*/ 1799char * 1800#ifdef LOSCFG_NET_CONTAINER 1801netif_index_to_name(u8_t idx, char *name, struct net_group *group) 1802#else 1803netif_index_to_name(u8_t idx, char *name) 1804#endif 1805{ 1806#ifdef LOSCFG_NET_CONTAINER 1807 struct netif *netif = netif_get_by_index(idx, group); 1808#else 1809 struct netif *netif = netif_get_by_index(idx); 1810#endif 1811 1812 if (netif != NULL) { 1813 name[0] = netif->name[0]; 1814 name[1] = netif->name[1]; 1815 lwip_itoa(&name[2], NETIF_NAMESIZE - 2, netif_index_to_num(idx)); 1816 return name; 1817 } 1818 return NULL; 1819} 1820 1821/** 1822* @ingroup netif 1823* Return the interface for the netif index 1824* 1825* @param idx index of netif to find 1826*/ 1827struct netif * 1828#ifdef LOSCFG_NET_CONTAINER 1829netif_get_by_index(u8_t idx, struct net_group *group) 1830#else 1831netif_get_by_index(u8_t idx) 1832#endif 1833{ 1834 struct netif *netif; 1835 1836 LWIP_ASSERT_CORE_LOCKED(); 1837 1838#ifdef LOSCFG_NET_CONTAINER 1839 if (idx != NETIF_NO_INDEX && group != NULL) { 1840 NETIF_FOREACH(netif, group) { 1841#else 1842 if (idx != NETIF_NO_INDEX) { 1843 NETIF_FOREACH(netif) { 1844#endif 1845 if (idx == netif_get_index(netif)) { 1846 return netif; /* found! */ 1847 } 1848 } 1849 } 1850 1851 return NULL; 1852} 1853 1854#ifndef netif_find 1855/** 1856 * @ingroup netif 1857 * Find a network interface by searching for its name 1858 * 1859 * @param name the name of the netif (like netif->name) plus concatenated number 1860 * in ascii representation (e.g. 'en0') 1861 */ 1862struct netif * 1863netif_find(const char *name) 1864{ 1865 struct netif *netif; 1866 u8_t num; 1867 1868 LWIP_ASSERT_CORE_LOCKED(); 1869 1870 if (name == NULL) { 1871 return NULL; 1872 } 1873 1874 num = (u8_t)atoi(&name[2]); 1875 if (!num && (name[2] != '0')) { 1876 /* this means atoi has failed */ 1877 return NULL; 1878 } 1879 1880 NETIF_FOREACH(netif) { 1881 if (num == netif->num && 1882 name[0] == netif->name[0] && 1883 name[1] == netif->name[1]) { 1884 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); 1885 return netif; 1886 } 1887 } 1888 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); 1889 return NULL; 1890} 1891#endif 1892 1893#if LWIP_NETIF_EXT_STATUS_CALLBACK 1894/** 1895 * @ingroup netif 1896 * Add extended netif events listener 1897 * @param callback pointer to listener structure 1898 * @param fn callback function 1899 */ 1900void 1901netif_add_ext_callback(netif_ext_callback_t *callback, netif_ext_callback_fn fn) 1902{ 1903 LWIP_ASSERT_CORE_LOCKED(); 1904 LWIP_ASSERT("callback must be != NULL", callback != NULL); 1905 LWIP_ASSERT("fn must be != NULL", fn != NULL); 1906 1907 callback->callback_fn = fn; 1908 callback->next = ext_callback; 1909 ext_callback = callback; 1910} 1911 1912/** 1913 * @ingroup netif 1914 * Remove extended netif events listener 1915 * @param callback pointer to listener structure 1916 */ 1917void 1918netif_remove_ext_callback(netif_ext_callback_t* callback) 1919{ 1920 netif_ext_callback_t *last, *iter; 1921 1922 LWIP_ASSERT_CORE_LOCKED(); 1923 LWIP_ASSERT("callback must be != NULL", callback != NULL); 1924 1925 if (ext_callback == NULL) { 1926 return; 1927 } 1928 1929 if (callback == ext_callback) { 1930 ext_callback = ext_callback->next; 1931 } else { 1932 last = ext_callback; 1933 for (iter = ext_callback->next; iter != NULL; last = iter, iter = iter->next) { 1934 if (iter == callback) { 1935 LWIP_ASSERT("last != NULL", last != NULL); 1936 last->next = callback->next; 1937 callback->next = NULL; 1938 return; 1939 } 1940 } 1941 } 1942} 1943 1944/** 1945 * Invoke extended netif status event 1946 * @param netif netif that is affected by change 1947 * @param reason change reason 1948 * @param args depends on reason, see reason description 1949 */ 1950void 1951netif_invoke_ext_callback(struct netif *netif, netif_nsc_reason_t reason, const netif_ext_callback_args_t *args) 1952{ 1953 netif_ext_callback_t *callback = ext_callback; 1954 1955 LWIP_ASSERT("netif must be != NULL", netif != NULL); 1956 1957 while (callback != NULL) { 1958 callback->callback_fn(netif, reason, args); 1959 callback = callback->next; 1960 } 1961} 1962#endif /* LWIP_NETIF_EXT_STATUS_CALLBACK */ 1963