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> 54#include <net/net.h> 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/raw.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 105struct netif *netif_list; 106struct netif *netif_default; 107 108static u8_t netif_num; 109 110#if LWIP_NUM_NETIF_CLIENT_DATA > 0 111static u8_t netif_client_id; 112#endif 113 114#define NETIF_REPORT_TYPE_IPV4 0x01 115#define NETIF_REPORT_TYPE_IPV6 0x02 116static void netif_issue_reports(struct netif* netif, u8_t report_type); 117 118#if LWIP_IPV6 119static err_t netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr); 120#endif /* LWIP_IPV6 */ 121 122#if LWIP_HAVE_LOOPIF 123#if LWIP_IPV4 124static err_t netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t* addr); 125#endif 126#if LWIP_IPV6 127static err_t netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* addr); 128#endif 129 130 131static struct netif loop_netif; 132 133/** 134 * Initialize a lwip network interface structure for a loopback interface 135 * 136 * @param netif the lwip network interface structure for this loopif 137 * @return ERR_OK if the loopif is initialized 138 * ERR_MEM if private data couldn't be allocated 139 */ 140static err_t 141netif_loopif_init(struct netif *netif) 142{ 143 /* initialize the snmp variables and counters inside the struct netif 144 * ifSpeed: no assumption can be made! 145 */ 146 MIB2_INIT_NETIF(netif, snmp_ifType_softwareLoopback, 0); 147 148 netif->name[0] = 'l'; 149 netif->name[1] = 'o'; 150#if LWIP_IPV4 151 netif->output = netif_loop_output_ipv4; 152#endif 153#if LWIP_IPV6 154 netif->output_ip6 = netif_loop_output_ipv6; 155#endif 156#if LWIP_LOOPIF_MULTICAST 157 netif->flags |= NETIF_FLAG_IGMP; 158#endif 159 return ERR_OK; 160} 161#endif /* LWIP_HAVE_LOOPIF */ 162 163void 164netif_init(void) 165{ 166#if LWIP_HAVE_LOOPIF 167#if LWIP_IPV4 168#define LOOPIF_ADDRINIT &loop_ipaddr, &loop_netmask, &loop_gw, 169 ip4_addr_t loop_ipaddr, loop_netmask, loop_gw; 170 IP4_ADDR(&loop_gw, 127,0,0,1); 171 IP4_ADDR(&loop_ipaddr, 127,0,0,1); 172 IP4_ADDR(&loop_netmask, 255,0,0,0); 173#else /* LWIP_IPV4 */ 174#define LOOPIF_ADDRINIT 175#endif /* LWIP_IPV4 */ 176 177#if NO_SYS 178 netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, ip_input); 179#else /* NO_SYS */ 180 netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, tcpip_input); 181#endif /* NO_SYS */ 182 183#if LWIP_IPV6 184 IP_ADDR6_HOST(loop_netif.ip6_addr, 0, 0, 0, 0x00000001UL); 185 loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID; 186#endif /* LWIP_IPV6 */ 187 188 netif_set_link_up(&loop_netif); 189 netif_set_up(&loop_netif); 190 191#endif /* LWIP_HAVE_LOOPIF */ 192} 193 194/** 195 * @ingroup lwip_nosys 196 * Forwards a received packet for input processing with 197 * ethernet_input() or ip_input() depending on netif flags. 198 * Don't call directly, pass to netif_add() and call 199 * netif->input(). 200 * Only works if the netif driver correctly sets 201 * NETIF_FLAG_ETHARP and/or NETIF_FLAG_ETHERNET flag! 202 */ 203err_t 204netif_input(struct pbuf *p, struct netif *inp) 205{ 206#if LWIP_ETHERNET 207 if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { 208 return ethernet_input(p, inp); 209 } else 210#endif /* LWIP_ETHERNET */ 211 return ip_input(p, inp); 212} 213 214/** 215 * @ingroup netif 216 * Add a network interface to the list of lwIP netifs. 217 * 218 * @param netif a pre-allocated netif structure 219 * @param ipaddr IP address for the new netif 220 * @param netmask network mask for the new netif 221 * @param gw default gateway IP address for the new netif 222 * @param state opaque data passed to the new netif 223 * @param init callback function that initializes the interface 224 * @param input callback function that is called to pass 225 * ingress packets up in the protocol layer stack.\n 226 * It is recommended to use a function that passes the input directly 227 * to the stack (netif_input(), NO_SYS=1 mode) or via sending a 228 * message to TCPIP thread (tcpip_input(), NO_SYS=0 mode).\n 229 * These functions use netif flags NETIF_FLAG_ETHARP and NETIF_FLAG_ETHERNET 230 * to decide whether to forward to ethernet_input() or ip_input(). 231 * In other words, the functions only work when the netif 232 * driver is implemented correctly!\n 233 * Most members of struct netif should be be initialized by the 234 * netif init function = netif driver (init parameter of this function).\n 235 * IPv6: Don't forget to call netif_create_ip6_linklocal_address() after 236 * setting the MAC address in struct netif.hwaddr 237 * (IPv6 requires a link-local address). 238 * 239 * @return netif, or NULL if failed. 240 */ 241struct netif * 242netif_add(struct netif *netif, 243#if LWIP_IPV4 244 const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, 245#endif /* LWIP_IPV4 */ 246 void *state, netif_init_fn init, netif_input_fn input) 247{ 248#if LWIP_IPV6 249 s8_t i; 250#endif 251 252 LWIP_ASSERT("No init function given", init != NULL); 253 254 /* reset new interface configuration state */ 255#if LWIP_IPV4 256 ip_addr_set_zero_ip4(&netif->ip_addr); 257 ip_addr_set_zero_ip4(&netif->netmask); 258 ip_addr_set_zero_ip4(&netif->gw); 259#endif /* LWIP_IPV4 */ 260#if LWIP_IPV6 261 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 262 ip_addr_set_zero_ip6(&netif->ip6_addr[i]); 263 netif->ip6_addr_state[i] = IP6_ADDR_INVALID; 264 } 265 netif->output_ip6 = netif_null_output_ip6; 266#endif /* LWIP_IPV6 */ 267 NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL); 268 netif->flags = 0; 269#ifdef netif_get_client_data 270 memset(netif->client_data, 0, sizeof(netif->client_data)); 271#endif /* LWIP_NUM_NETIF_CLIENT_DATA */ 272#if LWIP_IPV6_AUTOCONFIG 273 /* IPv6 address autoconfiguration not enabled by default */ 274 netif->ip6_autoconfig_enabled = 0; 275#endif /* LWIP_IPV6_AUTOCONFIG */ 276#if LWIP_IPV6_SEND_ROUTER_SOLICIT 277 netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; 278#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ 279#if LWIP_NETIF_STATUS_CALLBACK 280 netif->status_callback = NULL; 281#endif /* LWIP_NETIF_STATUS_CALLBACK */ 282#if LWIP_NETIF_LINK_CALLBACK 283 netif->link_callback = NULL; 284#endif /* LWIP_NETIF_LINK_CALLBACK */ 285#if LWIP_IGMP 286 netif->igmp_mac_filter = NULL; 287#endif /* LWIP_IGMP */ 288#if LWIP_IPV6 && LWIP_IPV6_MLD 289 netif->mld_mac_filter = NULL; 290#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ 291#if ENABLE_LOOPBACK 292 netif->loop_first = NULL; 293 netif->loop_last = NULL; 294#endif /* ENABLE_LOOPBACK */ 295 296 /* remember netif specific state information data */ 297 netif->state = state; 298 netif->num = netif_num++; 299 netif->input = input; 300 301 NETIF_SET_HWADDRHINT(netif, NULL); 302#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS 303 netif->loop_cnt_current = 0; 304#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */ 305 306#if LWIP_IPV4 307 netif_set_addr(netif, ipaddr, netmask, gw); 308#endif /* LWIP_IPV4 */ 309 310 /* call user specified initialization function for netif */ 311 if (init(netif) != ERR_OK) { 312 return NULL; 313 } 314 315 /* add this netif to the list */ 316 netif->next = netif_list; 317 netif_list = netif; 318 mib2_netif_added(netif); 319 320#if LWIP_IGMP 321 /* start IGMP processing */ 322 if (netif->flags & NETIF_FLAG_IGMP) { 323 igmp_start(netif); 324 } 325#endif /* LWIP_IGMP */ 326 327 LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP", 328 netif->name[0], netif->name[1])); 329#if LWIP_IPV4 330 LWIP_DEBUGF(NETIF_DEBUG, (" addr ")); 331 ip4_addr_debug_print(NETIF_DEBUG, ipaddr); 332 LWIP_DEBUGF(NETIF_DEBUG, (" netmask ")); 333 ip4_addr_debug_print(NETIF_DEBUG, netmask); 334 LWIP_DEBUGF(NETIF_DEBUG, (" gw ")); 335 ip4_addr_debug_print(NETIF_DEBUG, gw); 336#endif /* LWIP_IPV4 */ 337 LWIP_DEBUGF(NETIF_DEBUG, ("\n")); 338 return netif; 339} 340 341#if LWIP_IPV4 342/** 343 * @ingroup netif_ip4 344 * Change IP address configuration for a network interface (including netmask 345 * and default gateway). 346 * 347 * @param netif the network interface to change 348 * @param ipaddr the new IP address 349 * @param netmask the new netmask 350 * @param gw the new default gateway 351 */ 352void 353netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, 354 const ip4_addr_t *gw) 355{ 356 if (ip4_addr_isany(ipaddr)) { 357 /* when removing an address, we have to remove it *before* changing netmask/gw 358 to ensure that tcp RST segment can be sent correctly */ 359 netif_set_ipaddr(netif, ipaddr); 360 netif_set_netmask(netif, netmask); 361 netif_set_gw(netif, gw); 362 } else { 363 netif_set_netmask(netif, netmask); 364 netif_set_gw(netif, gw); 365 /* set ipaddr last to ensure netmask/gw have been set when status callback is called */ 366 netif_set_ipaddr(netif, ipaddr); 367 } 368} 369#endif /* LWIP_IPV4*/ 370 371/** 372 * @ingroup netif 373 * Remove a network interface from the list of lwIP netifs. 374 * 375 * @param netif the network interface to remove 376 */ 377void 378netif_remove(struct netif *netif) 379{ 380#if LWIP_IPV6 381 int i; 382#endif 383 384 if (netif == NULL) { 385 return; 386 } 387 388#if LWIP_IPV4 389 if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { 390#if LWIP_TCP 391 tcp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); 392#endif /* LWIP_TCP */ 393#if LWIP_UDP 394 udp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); 395#endif /* LWIP_UDP */ 396#if LWIP_RAW 397 raw_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); 398#endif /* LWIP_RAW */ 399 } 400 401#if LWIP_IGMP 402 /* stop IGMP processing */ 403 if (netif->flags & NETIF_FLAG_IGMP) { 404 igmp_stop(netif); 405 } 406#endif /* LWIP_IGMP */ 407#endif /* LWIP_IPV4*/ 408 409#if LWIP_IPV6 410 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 411 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { 412#if LWIP_TCP 413 tcp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); 414#endif /* LWIP_TCP */ 415#if LWIP_UDP 416 udp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); 417#endif /* LWIP_UDP */ 418#if LWIP_RAW 419 raw_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); 420#endif /* LWIP_RAW */ 421 } 422 } 423#if LWIP_IPV6_MLD 424 /* stop MLD processing */ 425 mld6_stop(netif); 426#endif /* LWIP_IPV6_MLD */ 427#endif /* LWIP_IPV6 */ 428 if (netif_is_up(netif)) { 429 /* set netif down before removing (call callback function) */ 430 netif_set_down(netif); 431 } 432 433 mib2_remove_ip4(netif); 434 435 /* this netif is default? */ 436 if (netif_default == netif) { 437 /* reset default netif */ 438 netif_set_default(NULL); 439 } 440 /* is it the first netif? */ 441 if (netif_list == netif) { 442 netif_list = netif->next; 443 } else { 444 /* look for netif further down the list */ 445 struct netif * tmp_netif; 446 for (tmp_netif = netif_list; tmp_netif != NULL; tmp_netif = tmp_netif->next) { 447 if (tmp_netif->next == netif) { 448 tmp_netif->next = netif->next; 449 break; 450 } 451 } 452 if (tmp_netif == NULL) { 453 return; /* netif is not on the list */ 454 } 455 } 456 mib2_netif_removed(netif); 457#if LWIP_NETIF_REMOVE_CALLBACK 458 if (netif->remove_callback) { 459 netif->remove_callback(netif); 460 } 461#endif /* LWIP_NETIF_REMOVE_CALLBACK */ 462 LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); 463} 464 465/** 466 * @ingroup netif 467 * Find a network interface by searching for its name 468 * 469 * @param name the name of the netif (like netif->name) plus concatenated number 470 * in ascii representation (e.g. 'en0') 471 */ 472struct netif * 473netif_find(const char *name) 474{ 475 struct netif *netif; 476 u8_t num; 477 478 if (name == NULL) { 479 return NULL; 480 } 481 482 num = (u8_t)(name[2] - '0'); 483 484 for (netif = netif_list; netif != NULL; netif = netif->next) { 485 if (num == netif->num && 486 name[0] == netif->name[0] && 487 name[1] == netif->name[1]) { 488 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); 489 return netif; 490 } 491 } 492 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); 493 return NULL; 494} 495 496#if LWIP_IPV4 497/** 498 * @ingroup netif_ip4 499 * Change the IP address of a network interface 500 * 501 * @param netif the network interface to change 502 * @param ipaddr the new IP address 503 * 504 * @note call netif_set_addr() if you also want to change netmask and 505 * default gateway 506 */ 507void 508netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr) 509{ 510 ip_addr_t new_addr; 511 *ip_2_ip4(&new_addr) = (ipaddr ? *ipaddr : *IP4_ADDR_ANY4); 512 IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_V4); 513 514 /* address is actually being changed? */ 515 if (ip4_addr_cmp(ip_2_ip4(&new_addr), netif_ip4_addr(netif)) == 0) { 516 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); 517#if LWIP_TCP 518 tcp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); 519#endif /* LWIP_TCP */ 520#if LWIP_UDP 521 udp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); 522#endif /* LWIP_UDP */ 523#if LWIP_RAW 524 raw_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); 525#endif /* LWIP_RAW */ 526 527 mib2_remove_ip4(netif); 528 mib2_remove_route_ip4(0, netif); 529 /* set new IP address to netif */ 530 ip4_addr_set(ip_2_ip4(&netif->ip_addr), ipaddr); 531 IP_SET_TYPE_VAL(netif->ip_addr, IPADDR_TYPE_V4); 532 mib2_add_ip4(netif); 533 mib2_add_route_ip4(0, netif); 534 535 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4); 536 537 NETIF_STATUS_CALLBACK(netif); 538 } 539 540 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", 541 netif->name[0], netif->name[1], 542 ip4_addr1_16(netif_ip4_addr(netif)), 543 ip4_addr2_16(netif_ip4_addr(netif)), 544 ip4_addr3_16(netif_ip4_addr(netif)), 545 ip4_addr4_16(netif_ip4_addr(netif)))); 546} 547 548/** 549 * @ingroup netif_ip4 550 * Change the default gateway for a network interface 551 * 552 * @param netif the network interface to change 553 * @param gw the new default gateway 554 * 555 * @note call netif_set_addr() if you also want to change ip address and netmask 556 */ 557void 558netif_set_gw(struct netif *netif, const ip4_addr_t *gw) 559{ 560 ip4_addr_set(ip_2_ip4(&netif->gw), gw); 561 IP_SET_TYPE_VAL(netif->gw, IPADDR_TYPE_V4); 562 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", 563 netif->name[0], netif->name[1], 564 ip4_addr1_16(netif_ip4_gw(netif)), 565 ip4_addr2_16(netif_ip4_gw(netif)), 566 ip4_addr3_16(netif_ip4_gw(netif)), 567 ip4_addr4_16(netif_ip4_gw(netif)))); 568} 569 570/** 571 * @ingroup netif_ip4 572 * Change the netmask of a network interface 573 * 574 * @param netif the network interface to change 575 * @param netmask the new netmask 576 * 577 * @note call netif_set_addr() if you also want to change ip address and 578 * default gateway 579 */ 580void 581netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask) 582{ 583 mib2_remove_route_ip4(0, netif); 584 /* set new netmask to netif */ 585 ip4_addr_set(ip_2_ip4(&netif->netmask), netmask); 586 IP_SET_TYPE_VAL(netif->netmask, IPADDR_TYPE_V4); 587 mib2_add_route_ip4(0, netif); 588 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", 589 netif->name[0], netif->name[1], 590 ip4_addr1_16(netif_ip4_netmask(netif)), 591 ip4_addr2_16(netif_ip4_netmask(netif)), 592 ip4_addr3_16(netif_ip4_netmask(netif)), 593 ip4_addr4_16(netif_ip4_netmask(netif)))); 594} 595#endif /* LWIP_IPV4 */ 596 597/** 598 * @ingroup netif 599 * Set a network interface as the default network interface 600 * (used to output all packets for which no specific route is found) 601 * 602 * @param netif the default network interface 603 */ 604void 605netif_set_default(struct netif *netif) 606{ 607 if (netif == NULL) { 608 /* remove default route */ 609 mib2_remove_route_ip4(1, netif); 610 } else { 611 /* install default route */ 612 mib2_add_route_ip4(1, netif); 613 } 614 netif_default = netif; 615 LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", 616 netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); 617} 618 619/** 620 * @ingroup netif 621 * Bring an interface up, available for processing 622 * traffic. 623 */ 624void 625netif_set_up(struct netif *netif) 626{ 627 if (!(netif->flags & NETIF_FLAG_UP)) { 628 netif->flags |= NETIF_FLAG_UP; 629 630 MIB2_COPY_SYSUPTIME_TO(&netif->ts); 631 632 NETIF_STATUS_CALLBACK(netif); 633 634 if (netif->flags & NETIF_FLAG_LINK_UP) { 635 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6); 636 } 637 } 638} 639 640/** Send ARP/IGMP/MLD/RS events, e.g. on link-up/netif-up or addr-change 641 */ 642static void 643netif_issue_reports(struct netif* netif, u8_t report_type) 644{ 645#if LWIP_IPV4 646 if ((report_type & NETIF_REPORT_TYPE_IPV4) && 647 !ip4_addr_isany_val(*netif_ip4_addr(netif))) { 648#if LWIP_ARP 649 /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ 650 if (netif->flags & (NETIF_FLAG_ETHARP)) { 651 etharp_gratuitous(netif); 652 } 653#endif /* LWIP_ARP */ 654 655#if LWIP_IGMP 656 /* resend IGMP memberships */ 657 if (netif->flags & NETIF_FLAG_IGMP) { 658 igmp_report_groups(netif); 659 } 660#endif /* LWIP_IGMP */ 661 } 662#endif /* LWIP_IPV4 */ 663 664#if LWIP_IPV6 665 if (report_type & NETIF_REPORT_TYPE_IPV6) { 666#if LWIP_IPV6_MLD 667 /* send mld memberships */ 668 mld6_report_groups(netif); 669#endif /* LWIP_IPV6_MLD */ 670#if LWIP_IPV6_SEND_ROUTER_SOLICIT 671 /* Send Router Solicitation messages. */ 672 netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; 673#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ 674 } 675#endif /* LWIP_IPV6 */ 676} 677 678/** 679 * @ingroup netif 680 * Bring an interface down, disabling any traffic processing. 681 */ 682void 683netif_set_down(struct netif *netif) 684{ 685 if (netif->flags & NETIF_FLAG_UP) { 686 netif->flags &= ~NETIF_FLAG_UP; 687 MIB2_COPY_SYSUPTIME_TO(&netif->ts); 688 689#if LWIP_IPV4 && LWIP_ARP 690 if (netif->flags & NETIF_FLAG_ETHARP) { 691 etharp_cleanup_netif(netif); 692 } 693#endif /* LWIP_IPV4 && LWIP_ARP */ 694 695#if LWIP_IPV6 696 nd6_cleanup_netif(netif); 697#endif /* LWIP_IPV6 */ 698 699 NETIF_STATUS_CALLBACK(netif); 700 } 701} 702 703#if LWIP_NETIF_STATUS_CALLBACK 704/** 705 * @ingroup netif 706 * Set callback to be called when interface is brought up/down or address is changed while up 707 */ 708void 709netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback) 710{ 711 if (netif) { 712 netif->status_callback = status_callback; 713 } 714} 715#endif /* LWIP_NETIF_STATUS_CALLBACK */ 716 717#if LWIP_NETIF_REMOVE_CALLBACK 718/** 719 * @ingroup netif 720 * Set callback to be called when the interface has been removed 721 */ 722void 723netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback) 724{ 725 if (netif) { 726 netif->remove_callback = remove_callback; 727 } 728} 729#endif /* LWIP_NETIF_REMOVE_CALLBACK */ 730 731/** 732 * @ingroup netif 733 * Called by a driver when its link goes up 734 */ 735void 736netif_set_link_up(struct netif *netif) 737{ 738 if (!(netif->flags & NETIF_FLAG_LINK_UP)) { 739 netif->flags |= NETIF_FLAG_LINK_UP; 740 741#if LWIP_DHCP 742 dhcp_network_changed(netif); 743#endif /* LWIP_DHCP */ 744 745#if LWIP_AUTOIP 746 autoip_network_changed(netif); 747#endif /* LWIP_AUTOIP */ 748 749 if (netif->flags & NETIF_FLAG_UP) { 750 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6); 751 } 752 NETIF_LINK_CALLBACK(netif); 753 } 754} 755 756/** 757 * @ingroup netif 758 * Called by a driver when its link goes down 759 */ 760void 761netif_set_link_down(struct netif *netif ) 762{ 763 if (netif->flags & NETIF_FLAG_LINK_UP) { 764 netif->flags &= ~NETIF_FLAG_LINK_UP; 765 NETIF_LINK_CALLBACK(netif); 766 } 767} 768 769#if LWIP_NETIF_LINK_CALLBACK 770/** 771 * @ingroup netif 772 * Set callback to be called when link is brought up/down 773 */ 774void 775netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback) 776{ 777 if (netif) { 778 netif->link_callback = link_callback; 779 } 780} 781#endif /* LWIP_NETIF_LINK_CALLBACK */ 782 783#if ENABLE_LOOPBACK 784/** 785 * @ingroup netif 786 * Send an IP packet to be received on the same netif (loopif-like). 787 * The pbuf is simply copied and handed back to netif->input. 788 * In multithreaded mode, this is done directly since netif->input must put 789 * the packet on a queue. 790 * In callback mode, the packet is put on an internal queue and is fed to 791 * netif->input by netif_poll(). 792 * 793 * @param netif the lwip network interface structure 794 * @param p the (IP) packet to 'send' 795 * @return ERR_OK if the packet has been sent 796 * ERR_MEM if the pbuf used to copy the packet couldn't be allocated 797 */ 798err_t 799netif_loop_output(struct netif *netif, struct pbuf *p) 800{ 801 struct pbuf *r; 802 err_t err; 803 struct pbuf *last; 804#if LWIP_LOOPBACK_MAX_PBUFS 805 u16_t clen = 0; 806#endif /* LWIP_LOOPBACK_MAX_PBUFS */ 807 /* If we have a loopif, SNMP counters are adjusted for it, 808 * if not they are adjusted for 'netif'. */ 809#if MIB2_STATS 810#if LWIP_HAVE_LOOPIF 811 struct netif *stats_if = &loop_netif; 812#else /* LWIP_HAVE_LOOPIF */ 813 struct netif *stats_if = netif; 814#endif /* LWIP_HAVE_LOOPIF */ 815#endif /* MIB2_STATS */ 816 SYS_ARCH_DECL_PROTECT(lev); 817 818 /* Allocate a new pbuf */ 819 r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); 820 if (r == NULL) { 821 LINK_STATS_INC(link.memerr); 822 LINK_STATS_INC(link.drop); 823 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); 824 return ERR_MEM; 825 } 826#if LWIP_LOOPBACK_MAX_PBUFS 827 clen = pbuf_clen(r); 828 /* check for overflow or too many pbuf on queue */ 829 if (((netif->loop_cnt_current + clen) < netif->loop_cnt_current) || 830 ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) { 831 pbuf_free(r); 832 LINK_STATS_INC(link.memerr); 833 LINK_STATS_INC(link.drop); 834 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); 835 return ERR_MEM; 836 } 837 netif->loop_cnt_current += clen; 838#endif /* LWIP_LOOPBACK_MAX_PBUFS */ 839 840 /* Copy the whole pbuf queue p into the single pbuf r */ 841 if ((err = pbuf_copy(r, p)) != ERR_OK) { 842 pbuf_free(r); 843 LINK_STATS_INC(link.memerr); 844 LINK_STATS_INC(link.drop); 845 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); 846 return err; 847 } 848 849 /* Put the packet on a linked list which gets emptied through calling 850 netif_poll(). */ 851 852 /* let last point to the last pbuf in chain r */ 853 for (last = r; last->next != NULL; last = last->next); 854 855 SYS_ARCH_PROTECT(lev); 856 if (netif->loop_first != NULL) { 857 LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); 858 netif->loop_last->next = r; 859 netif->loop_last = last; 860 } else { 861 netif->loop_first = r; 862 netif->loop_last = last; 863 } 864 SYS_ARCH_UNPROTECT(lev); 865 866 LINK_STATS_INC(link.xmit); 867 MIB2_STATS_NETIF_ADD(stats_if, ifoutoctets, p->tot_len); 868 MIB2_STATS_NETIF_INC(stats_if, ifoutucastpkts); 869 870#if LWIP_NETIF_LOOPBACK_MULTITHREADING 871 /* For multithreading environment, schedule a call to netif_poll */ 872 tcpip_callback_with_block((tcpip_callback_fn)netif_poll, netif, 0); 873#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 874 net_if_trigger_loopback(); 875 876 return ERR_OK; 877} 878 879#if LWIP_HAVE_LOOPIF 880#if LWIP_IPV4 881static err_t 882netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t* addr) 883{ 884 LWIP_UNUSED_ARG(addr); 885 return netif_loop_output(netif, p); 886} 887#endif /* LWIP_IPV4 */ 888 889#if LWIP_IPV6 890static err_t 891netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* addr) 892{ 893 LWIP_UNUSED_ARG(addr); 894 return netif_loop_output(netif, p); 895} 896#endif /* LWIP_IPV6 */ 897#endif /* LWIP_HAVE_LOOPIF */ 898 899 900/** 901 * Call netif_poll() in the main loop of your application. This is to prevent 902 * reentering non-reentrant functions like tcp_input(). Packets passed to 903 * netif_loop_output() are put on a list that is passed to netif->input() by 904 * netif_poll(). 905 */ 906void 907netif_poll(struct netif *netif) 908{ 909 /* If we have a loopif, SNMP counters are adjusted for it, 910 * if not they are adjusted for 'netif'. */ 911#if MIB2_STATS 912#if LWIP_HAVE_LOOPIF 913 struct netif *stats_if = &loop_netif; 914#else /* LWIP_HAVE_LOOPIF */ 915 struct netif *stats_if = netif; 916#endif /* LWIP_HAVE_LOOPIF */ 917#endif /* MIB2_STATS */ 918 SYS_ARCH_DECL_PROTECT(lev); 919 920 /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ 921 SYS_ARCH_PROTECT(lev); 922 while (netif->loop_first != NULL) { 923 struct pbuf *in, *in_end; 924#if LWIP_LOOPBACK_MAX_PBUFS 925 u8_t clen = 1; 926#endif /* LWIP_LOOPBACK_MAX_PBUFS */ 927 928 in = in_end = netif->loop_first; 929 while (in_end->len != in_end->tot_len) { 930 LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); 931 in_end = in_end->next; 932#if LWIP_LOOPBACK_MAX_PBUFS 933 clen++; 934#endif /* LWIP_LOOPBACK_MAX_PBUFS */ 935 } 936#if LWIP_LOOPBACK_MAX_PBUFS 937 /* adjust the number of pbufs on queue */ 938 LWIP_ASSERT("netif->loop_cnt_current underflow", 939 ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); 940 netif->loop_cnt_current -= clen; 941#endif /* LWIP_LOOPBACK_MAX_PBUFS */ 942 943 /* 'in_end' now points to the last pbuf from 'in' */ 944 if (in_end == netif->loop_last) { 945 /* this was the last pbuf in the list */ 946 netif->loop_first = netif->loop_last = NULL; 947 } else { 948 /* pop the pbuf off the list */ 949 netif->loop_first = in_end->next; 950 LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL); 951 } 952 /* De-queue the pbuf from its successors on the 'loop_' list. */ 953 in_end->next = NULL; 954 SYS_ARCH_UNPROTECT(lev); 955 956 LINK_STATS_INC(link.recv); 957 MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len); 958 MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts); 959 /* loopback packets are always IP packets! */ 960 if (ip_input(in, netif) != ERR_OK) { 961 pbuf_free(in); 962 } 963 SYS_ARCH_PROTECT(lev); 964 } 965 SYS_ARCH_UNPROTECT(lev); 966} 967 968#if !LWIP_NETIF_LOOPBACK_MULTITHREADING 969/** 970 * Calls netif_poll() for every netif on the netif_list. 971 */ 972void 973netif_poll_all(void) 974{ 975 struct netif *netif = netif_list; 976 /* loop through netifs */ 977 while (netif != NULL) { 978 netif_poll(netif); 979 /* proceed to next network interface */ 980 netif = netif->next; 981 } 982} 983#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ 984#endif /* ENABLE_LOOPBACK */ 985 986#if LWIP_NUM_NETIF_CLIENT_DATA > 0 987/** 988 * @ingroup netif_cd 989 * Allocate an index to store data in client_data member of struct netif. 990 * Returned value is an index in mentioned array. 991 * @see LWIP_NUM_NETIF_CLIENT_DATA 992 */ 993u8_t 994netif_alloc_client_data_id(void) 995{ 996 u8_t result = netif_client_id; 997 netif_client_id++; 998 999 LWIP_ASSERT("Increase LWIP_NUM_NETIF_CLIENT_DATA in lwipopts.h", result < LWIP_NUM_NETIF_CLIENT_DATA); 1000 return result + LWIP_NETIF_CLIENT_DATA_INDEX_MAX; 1001} 1002#endif 1003 1004#if LWIP_IPV6 1005/** 1006 * @ingroup netif_ip6 1007 * Change an IPv6 address of a network interface 1008 * 1009 * @param netif the network interface to change 1010 * @param addr_idx index of the IPv6 address 1011 * @param addr6 the new IPv6 address 1012 * 1013 * @note call netif_ip6_addr_set_state() to set the address valid/temptative 1014 */ 1015void 1016netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6) 1017{ 1018 LWIP_ASSERT("addr6 != NULL", addr6 != NULL); 1019 netif_ip6_addr_set_parts(netif, addr_idx, addr6->addr[0], addr6->addr[1], 1020 addr6->addr[2], addr6->addr[3]); 1021} 1022 1023/* 1024 * Change an IPv6 address of a network interface (internal version taking 4 * u32_t) 1025 * 1026 * @param netif the network interface to change 1027 * @param addr_idx index of the IPv6 address 1028 * @param i0 word0 of the new IPv6 address 1029 * @param i1 word1 of the new IPv6 address 1030 * @param i2 word2 of the new IPv6 address 1031 * @param i3 word3 of the new IPv6 address 1032 */ 1033void 1034netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3) 1035{ 1036 const ip6_addr_t *old_addr; 1037 LWIP_ASSERT("netif != NULL", netif != NULL); 1038 LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); 1039 1040 old_addr = netif_ip6_addr(netif, addr_idx); 1041 /* address is actually being changed? */ 1042 if ((old_addr->addr[0] != i0) || (old_addr->addr[1] != i1) || 1043 (old_addr->addr[2] != i2) || (old_addr->addr[3] != i3)) { 1044 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set: netif address being changed\n")); 1045 1046 if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) { 1047#if LWIP_TCP || LWIP_UDP 1048 ip_addr_t new_ipaddr; 1049 IP_ADDR6(&new_ipaddr, i0, i1, i2, i3); 1050#endif /* LWIP_TCP || LWIP_UDP */ 1051#if LWIP_TCP 1052 tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); 1053#endif /* LWIP_TCP */ 1054#if LWIP_UDP 1055 udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); 1056#endif /* LWIP_UDP */ 1057#if LWIP_RAW 1058 raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); 1059#endif /* LWIP_RAW */ 1060 } 1061 /* @todo: remove/readd mib2 ip6 entries? */ 1062 1063 IP6_ADDR(ip_2_ip6(&(netif->ip6_addr[addr_idx])), i0, i1, i2, i3); 1064 IP_SET_TYPE_VAL(netif->ip6_addr[addr_idx], IPADDR_TYPE_V6); 1065 1066 if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) { 1067 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); 1068 NETIF_STATUS_CALLBACK(netif); 1069 } 1070 } 1071 1072 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", 1073 addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), 1074 netif_ip6_addr_state(netif, addr_idx))); 1075} 1076 1077/** 1078 * @ingroup netif_ip6 1079 * Change the state of an IPv6 address of a network interface 1080 * (INVALID, TEMPTATIVE, PREFERRED, DEPRECATED, where TEMPTATIVE 1081 * includes the number of checks done, see ip6_addr.h) 1082 * 1083 * @param netif the network interface to change 1084 * @param addr_idx index of the IPv6 address 1085 * @param state the new IPv6 address state 1086 */ 1087void 1088netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state) 1089{ 1090 u8_t old_state; 1091 LWIP_ASSERT("netif != NULL", netif != NULL); 1092 LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); 1093 1094 old_state = netif_ip6_addr_state(netif, addr_idx); 1095 /* state is actually being changed? */ 1096 if (old_state != state) { 1097 u8_t old_valid = old_state & IP6_ADDR_VALID; 1098 u8_t new_valid = state & IP6_ADDR_VALID; 1099 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n")); 1100 1101#if LWIP_IPV6_MLD 1102 /* Reevaluate solicited-node multicast group membership. */ 1103 if (netif->flags & NETIF_FLAG_MLD6) { 1104 nd6_adjust_mld_membership(netif, addr_idx, state); 1105 } 1106#endif /* LWIP_IPV6_MLD */ 1107 1108 if (old_valid && !new_valid) { 1109 /* address about to be removed by setting invalid */ 1110#if LWIP_TCP 1111 tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); 1112#endif /* LWIP_TCP */ 1113#if LWIP_UDP 1114 udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); 1115#endif /* LWIP_UDP */ 1116#if LWIP_RAW 1117 raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); 1118#endif /* LWIP_RAW */ 1119 /* @todo: remove mib2 ip6 entries? */ 1120 } 1121 netif->ip6_addr_state[addr_idx] = state; 1122 1123 if (!old_valid && new_valid) { 1124 /* address added by setting valid */ 1125 /* @todo: add mib2 ip6 entries? */ 1126 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); 1127 } 1128 if ((old_state & IP6_ADDR_PREFERRED) != (state & IP6_ADDR_PREFERRED)) { 1129 /* address state has changed (valid flag changed or switched between 1130 preferred and deprecated) -> call the callback function */ 1131 NETIF_STATUS_CALLBACK(netif); 1132 } 1133 } 1134 1135 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", 1136 addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), 1137 netif_ip6_addr_state(netif, addr_idx))); 1138} 1139 1140/** 1141 * Checks if a specific address is assigned to the netif and returns its 1142 * index. 1143 * 1144 * @param netif the netif to check 1145 * @param ip6addr the IPv6 address to find 1146 * @return >= 0: address found, this is its index 1147 * -1: address not found on this netif 1148 */ 1149s8_t 1150netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr) 1151{ 1152 s8_t i; 1153 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 1154 if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) && 1155 ip6_addr_cmp(netif_ip6_addr(netif, i), ip6addr)) { 1156 return i; 1157 } 1158 } 1159 return -1; 1160} 1161 1162/** 1163 * @ingroup netif_ip6 1164 * Create a link-local IPv6 address on a netif (stored in slot 0) 1165 * 1166 * @param netif the netif to create the address on 1167 * @param from_mac_48bit if != 0, assume hwadr is a 48-bit MAC address (std conversion) 1168 * if == 0, use hwaddr directly as interface ID 1169 */ 1170void 1171netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit) 1172{ 1173 u8_t i, addr_index; 1174 1175 /* Link-local prefix. */ 1176 ip_2_ip6(&netif->ip6_addr[0])->addr[0] = PP_HTONL(0xfe800000ul); 1177 ip_2_ip6(&netif->ip6_addr[0])->addr[1] = 0; 1178 1179 /* Generate interface ID. */ 1180 if (from_mac_48bit) { 1181 /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */ 1182 ip_2_ip6(&netif->ip6_addr[0])->addr[2] = lwip_htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) | 1183 ((u32_t)(netif->hwaddr[1]) << 16) | 1184 ((u32_t)(netif->hwaddr[2]) << 8) | 1185 (0xff)); 1186 ip_2_ip6(&netif->ip6_addr[0])->addr[3] = lwip_htonl((0xfeul << 24) | 1187 ((u32_t)(netif->hwaddr[3]) << 16) | 1188 ((u32_t)(netif->hwaddr[4]) << 8) | 1189 (netif->hwaddr[5])); 1190 } else { 1191 /* Use hwaddr directly as interface ID. */ 1192 ip_2_ip6(&netif->ip6_addr[0])->addr[2] = 0; 1193 ip_2_ip6(&netif->ip6_addr[0])->addr[3] = 0; 1194 1195 addr_index = 3; 1196 for (i = 0; (i < 8) && (i < netif->hwaddr_len); i++) { 1197 if (i == 4) { 1198 addr_index--; 1199 } 1200 ip_2_ip6(&netif->ip6_addr[0])->addr[addr_index] |= ((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03)); 1201 } 1202 } 1203 1204 /* Set address state. */ 1205#if LWIP_IPV6_DUP_DETECT_ATTEMPTS 1206 /* Will perform duplicate address detection (DAD). */ 1207 netif_ip6_addr_set_state(netif, 0, IP6_ADDR_TENTATIVE); 1208#else 1209 /* Consider address valid. */ 1210 netif_ip6_addr_set_state(netif, 0, IP6_ADDR_PREFERRED); 1211#endif /* LWIP_IPV6_AUTOCONFIG */ 1212} 1213 1214/** 1215 * @ingroup netif_ip6 1216 * This function allows for the easy addition of a new IPv6 address to an interface. 1217 * It takes care of finding an empty slot and then sets the address tentative 1218 * (to make sure that all the subsequent processing happens). 1219 * 1220 * @param netif netif to add the address on 1221 * @param ip6addr address to add 1222 * @param chosen_idx if != NULL, the chosen IPv6 address index will be stored here 1223 */ 1224err_t 1225netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx) 1226{ 1227 s8_t i; 1228 1229 i = netif_get_ip6_addr_match(netif, ip6addr); 1230 if (i >= 0) { 1231 /* Address already added */ 1232 if (chosen_idx != NULL) { 1233 *chosen_idx = i; 1234 } 1235 return ERR_OK; 1236 } 1237 1238 /* Find a free slot -- musn't be the first one (reserved for link local) */ 1239 for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 1240 if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) { 1241 ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr); 1242 netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE); 1243 if (chosen_idx != NULL) { 1244 *chosen_idx = i; 1245 } 1246 return ERR_OK; 1247 } 1248 } 1249 1250 if (chosen_idx != NULL) { 1251 *chosen_idx = -1; 1252 } 1253 return ERR_VAL; 1254} 1255 1256/** Dummy IPv6 output function for netifs not supporting IPv6 1257 */ 1258static err_t 1259netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr) 1260{ 1261 LWIP_UNUSED_ARG(netif); 1262 LWIP_UNUSED_ARG(p); 1263 LWIP_UNUSED_ARG(ipaddr); 1264 1265 return ERR_IF; 1266} 1267#endif /* LWIP_IPV6 */ 1268