Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more
lwip_netif.c
00001 /** 00002 * @file 00003 * lwIP network interface abstraction 00004 * 00005 * @defgroup netif Network interface (NETIF) 00006 * @ingroup callbackstyle_api 00007 * 00008 * @defgroup netif_ip4 IPv4 address handling 00009 * @ingroup netif 00010 * 00011 * @defgroup netif_ip6 IPv6 address handling 00012 * @ingroup netif 00013 * 00014 * @defgroup netif_cd Client data handling 00015 * Store data (void*) on a netif for application usage. 00016 * @see @ref LWIP_NUM_NETIF_CLIENT_DATA 00017 * @ingroup netif 00018 */ 00019 00020 /* 00021 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 00022 * All rights reserved. 00023 * 00024 * Redistribution and use in source and binary forms, with or without modification, 00025 * are permitted provided that the following conditions are met: 00026 * 00027 * 1. Redistributions of source code must retain the above copyright notice, 00028 * this list of conditions and the following disclaimer. 00029 * 2. Redistributions in binary form must reproduce the above copyright notice, 00030 * this list of conditions and the following disclaimer in the documentation 00031 * and/or other materials provided with the distribution. 00032 * 3. The name of the author may not be used to endorse or promote products 00033 * derived from this software without specific prior written permission. 00034 * 00035 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00036 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00037 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00038 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00039 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00040 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00041 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00042 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00043 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00044 * OF SUCH DAMAGE. 00045 * 00046 * This file is part of the lwIP TCP/IP stack. 00047 * 00048 * Author: Adam Dunkels <adam@sics.se> 00049 */ 00050 00051 #include "lwip/opt.h" 00052 00053 #include <string.h> 00054 00055 #include "lwip/def.h" 00056 #include "lwip/ip_addr.h" 00057 #include "lwip/ip6_addr.h" 00058 #include "lwip/netif.h" 00059 #include "lwip/priv/tcp_priv.h" 00060 #include "lwip/udp.h" 00061 #include "lwip/raw.h" 00062 #include "lwip/snmp.h" 00063 #include "lwip/igmp.h" 00064 #include "lwip/etharp.h" 00065 #include "lwip/stats.h" 00066 #include "lwip/sys.h" 00067 #include "lwip/ip.h" 00068 #if ENABLE_LOOPBACK 00069 #if LWIP_NETIF_LOOPBACK_MULTITHREADING 00070 #include "lwip/tcpip.h" 00071 #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 00072 #endif /* ENABLE_LOOPBACK */ 00073 00074 #include "netif/lwip_ethernet.h" 00075 00076 #if LWIP_AUTOIP 00077 #include "lwip/autoip.h" 00078 #endif /* LWIP_AUTOIP */ 00079 #if LWIP_DHCP 00080 #include "lwip/dhcp.h" 00081 #endif /* LWIP_DHCP */ 00082 #if LWIP_IPV6_DHCP6 00083 #include "lwip/dhcp6.h" 00084 #endif /* LWIP_IPV6_DHCP6 */ 00085 #if LWIP_IPV6_MLD 00086 #include "lwip/mld6.h" 00087 #endif /* LWIP_IPV6_MLD */ 00088 #if LWIP_IPV6 00089 #include "lwip/nd6.h" 00090 #endif 00091 00092 #if LWIP_NETIF_STATUS_CALLBACK 00093 #define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0) 00094 #else 00095 #define NETIF_STATUS_CALLBACK(n) 00096 #endif /* LWIP_NETIF_STATUS_CALLBACK */ 00097 00098 #if LWIP_NETIF_LINK_CALLBACK 00099 #define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0) 00100 #else 00101 #define NETIF_LINK_CALLBACK(n) 00102 #endif /* LWIP_NETIF_LINK_CALLBACK */ 00103 00104 struct netif *netif_list; 00105 struct netif *netif_default; 00106 00107 static u8_t netif_num; 00108 00109 #if LWIP_NUM_NETIF_CLIENT_DATA > 0 00110 static u8_t netif_client_id; 00111 #endif 00112 00113 #define NETIF_REPORT_TYPE_IPV4 0x01 00114 #define NETIF_REPORT_TYPE_IPV6 0x02 00115 static void netif_issue_reports(struct netif* netif, u8_t report_type); 00116 00117 #if LWIP_IPV6 00118 static err_t netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr); 00119 #endif /* LWIP_IPV6 */ 00120 00121 #if LWIP_HAVE_LOOPIF 00122 #if LWIP_IPV4 00123 static err_t netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t* addr); 00124 #endif 00125 #if LWIP_IPV6 00126 static err_t netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* addr); 00127 #endif 00128 00129 00130 static struct netif loop_netif; 00131 00132 /** 00133 * Initialize a lwip network interface structure for a loopback interface 00134 * 00135 * @param netif the lwip network interface structure for this loopif 00136 * @return ERR_OK if the loopif is initialized 00137 * ERR_MEM if private data couldn't be allocated 00138 */ 00139 static err_t 00140 netif_loopif_init(struct netif *netif) 00141 { 00142 /* initialize the snmp variables and counters inside the struct netif 00143 * ifSpeed: no assumption can be made! 00144 */ 00145 MIB2_INIT_NETIF(netif, snmp_ifType_softwareLoopback, 0); 00146 00147 netif->name[0] = 'l'; 00148 netif->name[1] = 'o'; 00149 #if LWIP_IPV4 00150 netif->output = netif_loop_output_ipv4; 00151 #endif 00152 #if LWIP_IPV6 00153 netif->output_ip6 = netif_loop_output_ipv6; 00154 #endif 00155 #if LWIP_LOOPIF_MULTICAST 00156 netif->flags |= NETIF_FLAG_IGMP; 00157 #endif 00158 return ERR_OK; 00159 } 00160 #endif /* LWIP_HAVE_LOOPIF */ 00161 00162 void 00163 netif_init(void) 00164 { 00165 #if LWIP_HAVE_LOOPIF 00166 #if LWIP_IPV4 00167 #define LOOPIF_ADDRINIT &loop_ipaddr, &loop_netmask, &loop_gw, 00168 ip4_addr_t loop_ipaddr, loop_netmask, loop_gw; 00169 IP4_ADDR(&loop_gw, 127,0,0,1); 00170 IP4_ADDR(&loop_ipaddr, 127,0,0,1); 00171 IP4_ADDR(&loop_netmask, 255,0,0,0); 00172 #else /* LWIP_IPV4 */ 00173 #define LOOPIF_ADDRINIT 00174 #endif /* LWIP_IPV4 */ 00175 00176 #if NO_SYS 00177 netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, ip_input); 00178 #else /* NO_SYS */ 00179 netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, tcpip_input); 00180 #endif /* NO_SYS */ 00181 00182 #if LWIP_IPV6 00183 IP_ADDR6_HOST(loop_netif.ip6_addr, 0, 0, 0, 0x00000001UL); 00184 loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID; 00185 #endif /* LWIP_IPV6 */ 00186 00187 netif_set_link_up(&loop_netif); 00188 netif_set_up(&loop_netif); 00189 00190 #endif /* LWIP_HAVE_LOOPIF */ 00191 } 00192 00193 /** 00194 * @ingroup lwip_nosys 00195 * Forwards a received packet for input processing with 00196 * ethernet_input() or ip_input() depending on netif flags. 00197 * Don't call directly, pass to netif_add() and call 00198 * netif->input(). 00199 * Only works if the netif driver correctly sets 00200 * NETIF_FLAG_ETHARP and/or NETIF_FLAG_ETHERNET flag! 00201 */ 00202 err_t 00203 netif_input(struct pbuf *p, struct netif *inp) 00204 { 00205 #if LWIP_ETHERNET 00206 if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { 00207 return ethernet_input(p, inp); 00208 } else 00209 #endif /* LWIP_ETHERNET */ 00210 return ip_input(p, inp); 00211 } 00212 00213 /** 00214 * @ingroup netif 00215 * Add a network interface to the list of lwIP netifs. 00216 * 00217 * @param netif a pre-allocated netif structure 00218 * @param ipaddr IP address for the new netif 00219 * @param netmask network mask for the new netif 00220 * @param gw default gateway IP address for the new netif 00221 * @param state opaque data passed to the new netif 00222 * @param init callback function that initializes the interface 00223 * @param input callback function that is called to pass 00224 * ingress packets up in the protocol layer stack.\n 00225 * It is recommended to use a function that passes the input directly 00226 * to the stack (netif_input(), NO_SYS=1 mode) or via sending a 00227 * message to TCPIP thread (tcpip_input(), NO_SYS=0 mode).\n 00228 * These functions use netif flags NETIF_FLAG_ETHARP and NETIF_FLAG_ETHERNET 00229 * to decide whether to forward to ethernet_input() or ip_input(). 00230 * In other words, the functions only work when the netif 00231 * driver is implemented correctly!\n 00232 * Most members of struct netif should be be initialized by the 00233 * netif init function = netif driver (init parameter of this function).\n 00234 * IPv6: Don't forget to call netif_create_ip6_linklocal_address() after 00235 * setting the MAC address in struct netif.hwaddr 00236 * (IPv6 requires a link-local address). 00237 * 00238 * @return netif, or NULL if failed. 00239 */ 00240 struct netif * 00241 netif_add(struct netif *netif, 00242 #if LWIP_IPV4 00243 const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, 00244 #endif /* LWIP_IPV4 */ 00245 void *state, netif_init_fn init, netif_input_fn input) 00246 { 00247 #if LWIP_IPV6 00248 s8_t i; 00249 #endif 00250 00251 LWIP_ASSERT("No init function given", init != NULL); 00252 00253 /* reset new interface configuration state */ 00254 #if LWIP_IPV4 00255 ip_addr_set_zero_ip4(&netif->ip_addr); 00256 ip_addr_set_zero_ip4(&netif->netmask); 00257 ip_addr_set_zero_ip4(&netif->gw); 00258 #endif /* LWIP_IPV4 */ 00259 #if LWIP_IPV6 00260 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00261 ip_addr_set_zero_ip6(&netif->ip6_addr[i]); 00262 netif->ip6_addr_state[i] = IP6_ADDR_INVALID; 00263 } 00264 netif->output_ip6 = netif_null_output_ip6; 00265 #endif /* LWIP_IPV6 */ 00266 NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL); 00267 netif->flags = 0; 00268 #ifdef netif_get_client_data 00269 memset(netif->client_data, 0, sizeof(netif->client_data)); 00270 #endif /* LWIP_NUM_NETIF_CLIENT_DATA */ 00271 #if LWIP_IPV6_AUTOCONFIG 00272 /* IPv6 address autoconfiguration not enabled by default */ 00273 netif->ip6_autoconfig_enabled = 0; 00274 #endif /* LWIP_IPV6_AUTOCONFIG */ 00275 #if LWIP_IPV6_SEND_ROUTER_SOLICIT 00276 netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; 00277 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ 00278 #if LWIP_NETIF_STATUS_CALLBACK 00279 netif->status_callback = NULL; 00280 #endif /* LWIP_NETIF_STATUS_CALLBACK */ 00281 #if LWIP_NETIF_LINK_CALLBACK 00282 netif->link_callback = NULL; 00283 #endif /* LWIP_NETIF_LINK_CALLBACK */ 00284 #if LWIP_IGMP 00285 netif->igmp_mac_filter = NULL; 00286 #endif /* LWIP_IGMP */ 00287 #if LWIP_IPV6 && LWIP_IPV6_MLD 00288 netif->mld_mac_filter = NULL; 00289 #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ 00290 #if ENABLE_LOOPBACK 00291 netif->loop_first = NULL; 00292 netif->loop_last = NULL; 00293 #endif /* ENABLE_LOOPBACK */ 00294 00295 /* remember netif specific state information data */ 00296 netif->state = state; 00297 netif->num = netif_num++; 00298 netif->input = input; 00299 00300 NETIF_SET_HWADDRHINT(netif, NULL); 00301 #if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS 00302 netif->loop_cnt_current = 0; 00303 #endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */ 00304 00305 #if LWIP_IPV4 00306 netif_set_addr(netif, ipaddr, netmask, gw); 00307 #endif /* LWIP_IPV4 */ 00308 00309 /* call user specified initialization function for netif */ 00310 if (init(netif) != ERR_OK) { 00311 return NULL; 00312 } 00313 00314 /* add this netif to the list */ 00315 netif->next = netif_list; 00316 netif_list = netif; 00317 mib2_netif_added(netif); 00318 00319 #if LWIP_IGMP 00320 /* start IGMP processing */ 00321 if (netif->flags & NETIF_FLAG_IGMP) { 00322 igmp_start(netif); 00323 } 00324 #endif /* LWIP_IGMP */ 00325 00326 LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP", 00327 netif->name[0], netif->name[1])); 00328 #if LWIP_IPV4 00329 LWIP_DEBUGF(NETIF_DEBUG, (" addr ")); 00330 ip4_addr_debug_print(NETIF_DEBUG, ipaddr); 00331 LWIP_DEBUGF(NETIF_DEBUG, (" netmask ")); 00332 ip4_addr_debug_print(NETIF_DEBUG, netmask); 00333 LWIP_DEBUGF(NETIF_DEBUG, (" gw ")); 00334 ip4_addr_debug_print(NETIF_DEBUG, gw); 00335 #endif /* LWIP_IPV4 */ 00336 LWIP_DEBUGF(NETIF_DEBUG, ("\n")); 00337 return netif; 00338 } 00339 00340 #if LWIP_IPV4 00341 /** 00342 * @ingroup netif_ip4 00343 * Change IP address configuration for a network interface (including netmask 00344 * and default gateway). 00345 * 00346 * @param netif the network interface to change 00347 * @param ipaddr the new IP address 00348 * @param netmask the new netmask 00349 * @param gw the new default gateway 00350 */ 00351 void 00352 netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, 00353 const ip4_addr_t *gw) 00354 { 00355 if (ip4_addr_isany(ipaddr)) { 00356 /* when removing an address, we have to remove it *before* changing netmask/gw 00357 to ensure that tcp RST segment can be sent correctly */ 00358 netif_set_ipaddr(netif, ipaddr); 00359 netif_set_netmask(netif, netmask); 00360 netif_set_gw(netif, gw); 00361 } else { 00362 netif_set_netmask(netif, netmask); 00363 netif_set_gw(netif, gw); 00364 /* set ipaddr last to ensure netmask/gw have been set when status callback is called */ 00365 netif_set_ipaddr(netif, ipaddr); 00366 } 00367 } 00368 #endif /* LWIP_IPV4*/ 00369 00370 /** 00371 * @ingroup netif 00372 * Remove a network interface from the list of lwIP netifs. 00373 * 00374 * @param netif the network interface to remove 00375 */ 00376 void 00377 netif_remove(struct netif *netif) 00378 { 00379 #if LWIP_IPV6 00380 int i; 00381 #endif 00382 00383 if (netif == NULL) { 00384 return; 00385 } 00386 00387 #if LWIP_IPV4 00388 if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { 00389 #if LWIP_TCP 00390 tcp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); 00391 #endif /* LWIP_TCP */ 00392 #if LWIP_UDP 00393 udp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); 00394 #endif /* LWIP_UDP */ 00395 #if LWIP_RAW 00396 raw_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); 00397 #endif /* LWIP_RAW */ 00398 } 00399 00400 #if LWIP_IGMP 00401 /* stop IGMP processing */ 00402 if (netif->flags & NETIF_FLAG_IGMP) { 00403 igmp_stop(netif); 00404 } 00405 #endif /* LWIP_IGMP */ 00406 #endif /* LWIP_IPV4*/ 00407 00408 #if LWIP_IPV6 00409 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00410 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { 00411 #if LWIP_TCP 00412 tcp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); 00413 #endif /* LWIP_TCP */ 00414 #if LWIP_UDP 00415 udp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); 00416 #endif /* LWIP_UDP */ 00417 #if LWIP_RAW 00418 raw_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); 00419 #endif /* LWIP_RAW */ 00420 } 00421 } 00422 #if LWIP_IPV6_MLD 00423 /* stop MLD processing */ 00424 mld6_stop(netif); 00425 #endif /* LWIP_IPV6_MLD */ 00426 #endif /* LWIP_IPV6 */ 00427 if (netif_is_up(netif)) { 00428 /* set netif down before removing (call callback function) */ 00429 netif_set_down(netif); 00430 } 00431 00432 mib2_remove_ip4(netif); 00433 00434 /* this netif is default? */ 00435 if (netif_default == netif) { 00436 /* reset default netif */ 00437 netif_set_default(NULL); 00438 } 00439 /* is it the first netif? */ 00440 if (netif_list == netif) { 00441 netif_list = netif->next; 00442 } else { 00443 /* look for netif further down the list */ 00444 struct netif * tmp_netif; 00445 for (tmp_netif = netif_list; tmp_netif != NULL; tmp_netif = tmp_netif->next) { 00446 if (tmp_netif->next == netif) { 00447 tmp_netif->next = netif->next; 00448 break; 00449 } 00450 } 00451 if (tmp_netif == NULL) { 00452 return; /* netif is not on the list */ 00453 } 00454 } 00455 mib2_netif_removed(netif); 00456 #if LWIP_NETIF_REMOVE_CALLBACK 00457 if (netif->remove_callback) { 00458 netif->remove_callback(netif); 00459 } 00460 #endif /* LWIP_NETIF_REMOVE_CALLBACK */ 00461 LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); 00462 } 00463 00464 /** 00465 * @ingroup netif 00466 * Find a network interface by searching for its name 00467 * 00468 * @param name the name of the netif (like netif->name) plus concatenated number 00469 * in ascii representation (e.g. 'en0') 00470 */ 00471 struct netif * 00472 netif_find(const char *name) 00473 { 00474 struct netif *netif; 00475 u8_t num; 00476 00477 if (name == NULL) { 00478 return NULL; 00479 } 00480 00481 num = (u8_t)(name[2] - '0'); 00482 00483 for (netif = netif_list; netif != NULL; netif = netif->next) { 00484 if (num == netif->num && 00485 name[0] == netif->name[0] && 00486 name[1] == netif->name[1]) { 00487 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); 00488 return netif; 00489 } 00490 } 00491 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); 00492 return NULL; 00493 } 00494 00495 #if LWIP_IPV4 00496 /** 00497 * @ingroup netif_ip4 00498 * Change the IP address of a network interface 00499 * 00500 * @param netif the network interface to change 00501 * @param ipaddr the new IP address 00502 * 00503 * @note call netif_set_addr() if you also want to change netmask and 00504 * default gateway 00505 */ 00506 void 00507 netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr) 00508 { 00509 ip_addr_t new_addr; 00510 *ip_2_ip4(&new_addr) = (ipaddr ? *ipaddr : *IP4_ADDR_ANY4); 00511 IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_V4); 00512 00513 /* address is actually being changed? */ 00514 if (ip4_addr_cmp(ip_2_ip4(&new_addr), netif_ip4_addr(netif)) == 0) { 00515 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); 00516 #if LWIP_TCP 00517 tcp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); 00518 #endif /* LWIP_TCP */ 00519 #if LWIP_UDP 00520 udp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); 00521 #endif /* LWIP_UDP */ 00522 #if LWIP_RAW 00523 raw_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); 00524 #endif /* LWIP_RAW */ 00525 00526 mib2_remove_ip4(netif); 00527 mib2_remove_route_ip4(0, netif); 00528 /* set new IP address to netif */ 00529 ip4_addr_set(ip_2_ip4(&netif->ip_addr), ipaddr); 00530 IP_SET_TYPE_VAL(netif->ip_addr, IPADDR_TYPE_V4); 00531 mib2_add_ip4(netif); 00532 mib2_add_route_ip4(0, netif); 00533 00534 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4); 00535 00536 NETIF_STATUS_CALLBACK(netif); 00537 } 00538 00539 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", 00540 netif->name[0], netif->name[1], 00541 ip4_addr1_16(netif_ip4_addr(netif)), 00542 ip4_addr2_16(netif_ip4_addr(netif)), 00543 ip4_addr3_16(netif_ip4_addr(netif)), 00544 ip4_addr4_16(netif_ip4_addr(netif)))); 00545 } 00546 00547 /** 00548 * @ingroup netif_ip4 00549 * Change the default gateway for a network interface 00550 * 00551 * @param netif the network interface to change 00552 * @param gw the new default gateway 00553 * 00554 * @note call netif_set_addr() if you also want to change ip address and netmask 00555 */ 00556 void 00557 netif_set_gw(struct netif *netif, const ip4_addr_t *gw) 00558 { 00559 ip4_addr_set(ip_2_ip4(&netif->gw), gw); 00560 IP_SET_TYPE_VAL(netif->gw, IPADDR_TYPE_V4); 00561 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", 00562 netif->name[0], netif->name[1], 00563 ip4_addr1_16(netif_ip4_gw(netif)), 00564 ip4_addr2_16(netif_ip4_gw(netif)), 00565 ip4_addr3_16(netif_ip4_gw(netif)), 00566 ip4_addr4_16(netif_ip4_gw(netif)))); 00567 } 00568 00569 /** 00570 * @ingroup netif_ip4 00571 * Change the netmask of a network interface 00572 * 00573 * @param netif the network interface to change 00574 * @param netmask the new netmask 00575 * 00576 * @note call netif_set_addr() if you also want to change ip address and 00577 * default gateway 00578 */ 00579 void 00580 netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask) 00581 { 00582 mib2_remove_route_ip4(0, netif); 00583 /* set new netmask to netif */ 00584 ip4_addr_set(ip_2_ip4(&netif->netmask), netmask); 00585 IP_SET_TYPE_VAL(netif->netmask, IPADDR_TYPE_V4); 00586 mib2_add_route_ip4(0, netif); 00587 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", 00588 netif->name[0], netif->name[1], 00589 ip4_addr1_16(netif_ip4_netmask(netif)), 00590 ip4_addr2_16(netif_ip4_netmask(netif)), 00591 ip4_addr3_16(netif_ip4_netmask(netif)), 00592 ip4_addr4_16(netif_ip4_netmask(netif)))); 00593 } 00594 #endif /* LWIP_IPV4 */ 00595 00596 /** 00597 * @ingroup netif 00598 * Set a network interface as the default network interface 00599 * (used to output all packets for which no specific route is found) 00600 * 00601 * @param netif the default network interface 00602 */ 00603 void 00604 netif_set_default(struct netif *netif) 00605 { 00606 if (netif == NULL) { 00607 /* remove default route */ 00608 mib2_remove_route_ip4(1, netif); 00609 } else { 00610 /* install default route */ 00611 mib2_add_route_ip4(1, netif); 00612 } 00613 netif_default = netif; 00614 LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", 00615 netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); 00616 } 00617 00618 /** 00619 * @ingroup netif 00620 * Bring an interface up, available for processing 00621 * traffic. 00622 */ 00623 void 00624 netif_set_up(struct netif *netif) 00625 { 00626 if (!(netif->flags & NETIF_FLAG_UP)) { 00627 netif->flags |= NETIF_FLAG_UP; 00628 00629 MIB2_COPY_SYSUPTIME_TO(&netif->ts); 00630 00631 NETIF_STATUS_CALLBACK(netif); 00632 00633 if (netif->flags & NETIF_FLAG_LINK_UP) { 00634 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6); 00635 } 00636 } 00637 } 00638 00639 /** Send ARP/IGMP/MLD/RS events, e.g. on link-up/netif-up or addr-change 00640 */ 00641 static void 00642 netif_issue_reports(struct netif* netif, u8_t report_type) 00643 { 00644 #if LWIP_IPV4 00645 if ((report_type & NETIF_REPORT_TYPE_IPV4) && 00646 !ip4_addr_isany_val(*netif_ip4_addr(netif))) { 00647 #if LWIP_ARP 00648 /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ 00649 if (netif->flags & (NETIF_FLAG_ETHARP)) { 00650 etharp_gratuitous(netif); 00651 } 00652 #endif /* LWIP_ARP */ 00653 00654 #if LWIP_IGMP 00655 /* resend IGMP memberships */ 00656 if (netif->flags & NETIF_FLAG_IGMP) { 00657 igmp_report_groups(netif); 00658 } 00659 #endif /* LWIP_IGMP */ 00660 } 00661 #endif /* LWIP_IPV4 */ 00662 00663 #if LWIP_IPV6 00664 if (report_type & NETIF_REPORT_TYPE_IPV6) { 00665 #if LWIP_IPV6_MLD 00666 /* send mld memberships */ 00667 mld6_report_groups(netif); 00668 #endif /* LWIP_IPV6_MLD */ 00669 #if LWIP_IPV6_SEND_ROUTER_SOLICIT 00670 /* Send Router Solicitation messages. */ 00671 netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; 00672 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ 00673 } 00674 #endif /* LWIP_IPV6 */ 00675 } 00676 00677 /** 00678 * @ingroup netif 00679 * Bring an interface down, disabling any traffic processing. 00680 */ 00681 void 00682 netif_set_down(struct netif *netif) 00683 { 00684 if (netif->flags & NETIF_FLAG_UP) { 00685 netif->flags &= ~NETIF_FLAG_UP; 00686 MIB2_COPY_SYSUPTIME_TO(&netif->ts); 00687 00688 #if LWIP_IPV4 && LWIP_ARP 00689 if (netif->flags & NETIF_FLAG_ETHARP) { 00690 etharp_cleanup_netif(netif); 00691 } 00692 #endif /* LWIP_IPV4 && LWIP_ARP */ 00693 00694 #if LWIP_IPV6 00695 nd6_cleanup_netif(netif); 00696 #endif /* LWIP_IPV6 */ 00697 00698 NETIF_STATUS_CALLBACK(netif); 00699 } 00700 } 00701 00702 #if LWIP_NETIF_STATUS_CALLBACK 00703 /** 00704 * @ingroup netif 00705 * Set callback to be called when interface is brought up/down or address is changed while up 00706 */ 00707 void 00708 netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback) 00709 { 00710 if (netif) { 00711 netif->status_callback = status_callback; 00712 } 00713 } 00714 #endif /* LWIP_NETIF_STATUS_CALLBACK */ 00715 00716 #if LWIP_NETIF_REMOVE_CALLBACK 00717 /** 00718 * @ingroup netif 00719 * Set callback to be called when the interface has been removed 00720 */ 00721 void 00722 netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback) 00723 { 00724 if (netif) { 00725 netif->remove_callback = remove_callback; 00726 } 00727 } 00728 #endif /* LWIP_NETIF_REMOVE_CALLBACK */ 00729 00730 /** 00731 * @ingroup netif 00732 * Called by a driver when its link goes up 00733 */ 00734 void 00735 netif_set_link_up(struct netif *netif) 00736 { 00737 if (!(netif->flags & NETIF_FLAG_LINK_UP)) { 00738 netif->flags |= NETIF_FLAG_LINK_UP; 00739 00740 #if LWIP_DHCP 00741 dhcp_network_changed(netif); 00742 #endif /* LWIP_DHCP */ 00743 00744 #if LWIP_AUTOIP 00745 autoip_network_changed(netif); 00746 #endif /* LWIP_AUTOIP */ 00747 00748 if (netif->flags & NETIF_FLAG_UP) { 00749 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6); 00750 } 00751 NETIF_LINK_CALLBACK(netif); 00752 } 00753 } 00754 00755 /** 00756 * @ingroup netif 00757 * Called by a driver when its link goes down 00758 */ 00759 void 00760 netif_set_link_down(struct netif *netif ) 00761 { 00762 if (netif->flags & NETIF_FLAG_LINK_UP) { 00763 netif->flags &= ~NETIF_FLAG_LINK_UP; 00764 NETIF_LINK_CALLBACK(netif); 00765 } 00766 } 00767 00768 #if LWIP_NETIF_LINK_CALLBACK 00769 /** 00770 * @ingroup netif 00771 * Set callback to be called when link is brought up/down 00772 */ 00773 void 00774 netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback) 00775 { 00776 if (netif) { 00777 netif->link_callback = link_callback; 00778 } 00779 } 00780 #endif /* LWIP_NETIF_LINK_CALLBACK */ 00781 00782 #if ENABLE_LOOPBACK 00783 /** 00784 * @ingroup netif 00785 * Send an IP packet to be received on the same netif (loopif-like). 00786 * The pbuf is simply copied and handed back to netif->input. 00787 * In multithreaded mode, this is done directly since netif->input must put 00788 * the packet on a queue. 00789 * In callback mode, the packet is put on an internal queue and is fed to 00790 * netif->input by netif_poll(). 00791 * 00792 * @param netif the lwip network interface structure 00793 * @param p the (IP) packet to 'send' 00794 * @return ERR_OK if the packet has been sent 00795 * ERR_MEM if the pbuf used to copy the packet couldn't be allocated 00796 */ 00797 err_t 00798 netif_loop_output(struct netif *netif, struct pbuf *p) 00799 { 00800 struct pbuf *r; 00801 err_t err; 00802 struct pbuf *last; 00803 #if LWIP_LOOPBACK_MAX_PBUFS 00804 u16_t clen = 0; 00805 #endif /* LWIP_LOOPBACK_MAX_PBUFS */ 00806 /* If we have a loopif, SNMP counters are adjusted for it, 00807 * if not they are adjusted for 'netif'. */ 00808 #if MIB2_STATS 00809 #if LWIP_HAVE_LOOPIF 00810 struct netif *stats_if = &loop_netif; 00811 #else /* LWIP_HAVE_LOOPIF */ 00812 struct netif *stats_if = netif; 00813 #endif /* LWIP_HAVE_LOOPIF */ 00814 #endif /* MIB2_STATS */ 00815 SYS_ARCH_DECL_PROTECT(lev); 00816 00817 /* Allocate a new pbuf */ 00818 r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); 00819 if (r == NULL) { 00820 LINK_STATS_INC(link.memerr); 00821 LINK_STATS_INC(link.drop); 00822 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); 00823 return ERR_MEM; 00824 } 00825 #if LWIP_LOOPBACK_MAX_PBUFS 00826 clen = pbuf_clen(r); 00827 /* check for overflow or too many pbuf on queue */ 00828 if (((netif->loop_cnt_current + clen) < netif->loop_cnt_current) || 00829 ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) { 00830 pbuf_free(r); 00831 LINK_STATS_INC(link.memerr); 00832 LINK_STATS_INC(link.drop); 00833 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); 00834 return ERR_MEM; 00835 } 00836 netif->loop_cnt_current += clen; 00837 #endif /* LWIP_LOOPBACK_MAX_PBUFS */ 00838 00839 /* Copy the whole pbuf queue p into the single pbuf r */ 00840 if ((err = pbuf_copy(r, p)) != ERR_OK) { 00841 pbuf_free(r); 00842 LINK_STATS_INC(link.memerr); 00843 LINK_STATS_INC(link.drop); 00844 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); 00845 return err; 00846 } 00847 00848 /* Put the packet on a linked list which gets emptied through calling 00849 netif_poll(). */ 00850 00851 /* let last point to the last pbuf in chain r */ 00852 for (last = r; last->next != NULL; last = last->next); 00853 00854 SYS_ARCH_PROTECT(lev); 00855 if (netif->loop_first != NULL) { 00856 LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); 00857 netif->loop_last->next = r; 00858 netif->loop_last = last; 00859 } else { 00860 netif->loop_first = r; 00861 netif->loop_last = last; 00862 } 00863 SYS_ARCH_UNPROTECT(lev); 00864 00865 LINK_STATS_INC(link.xmit); 00866 MIB2_STATS_NETIF_ADD(stats_if, ifoutoctets, p->tot_len); 00867 MIB2_STATS_NETIF_INC(stats_if, ifoutucastpkts); 00868 00869 #if LWIP_NETIF_LOOPBACK_MULTITHREADING 00870 /* For multithreading environment, schedule a call to netif_poll */ 00871 tcpip_callback_with_block((tcpip_callback_fn)netif_poll, netif, 0); 00872 #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 00873 00874 return ERR_OK; 00875 } 00876 00877 #if LWIP_HAVE_LOOPIF 00878 #if LWIP_IPV4 00879 static err_t 00880 netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t* addr) 00881 { 00882 LWIP_UNUSED_ARG(addr); 00883 return netif_loop_output(netif, p); 00884 } 00885 #endif /* LWIP_IPV4 */ 00886 00887 #if LWIP_IPV6 00888 static err_t 00889 netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* addr) 00890 { 00891 LWIP_UNUSED_ARG(addr); 00892 return netif_loop_output(netif, p); 00893 } 00894 #endif /* LWIP_IPV6 */ 00895 #endif /* LWIP_HAVE_LOOPIF */ 00896 00897 00898 /** 00899 * Call netif_poll() in the main loop of your application. This is to prevent 00900 * reentering non-reentrant functions like tcp_input(). Packets passed to 00901 * netif_loop_output() are put on a list that is passed to netif->input() by 00902 * netif_poll(). 00903 */ 00904 void 00905 netif_poll(struct netif *netif) 00906 { 00907 /* If we have a loopif, SNMP counters are adjusted for it, 00908 * if not they are adjusted for 'netif'. */ 00909 #if MIB2_STATS 00910 #if LWIP_HAVE_LOOPIF 00911 struct netif *stats_if = &loop_netif; 00912 #else /* LWIP_HAVE_LOOPIF */ 00913 struct netif *stats_if = netif; 00914 #endif /* LWIP_HAVE_LOOPIF */ 00915 #endif /* MIB2_STATS */ 00916 SYS_ARCH_DECL_PROTECT(lev); 00917 00918 /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ 00919 SYS_ARCH_PROTECT(lev); 00920 while (netif->loop_first != NULL) { 00921 struct pbuf *in, *in_end; 00922 #if LWIP_LOOPBACK_MAX_PBUFS 00923 u8_t clen = 1; 00924 #endif /* LWIP_LOOPBACK_MAX_PBUFS */ 00925 00926 in = in_end = netif->loop_first; 00927 while (in_end->len != in_end->tot_len) { 00928 LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); 00929 in_end = in_end->next; 00930 #if LWIP_LOOPBACK_MAX_PBUFS 00931 clen++; 00932 #endif /* LWIP_LOOPBACK_MAX_PBUFS */ 00933 } 00934 #if LWIP_LOOPBACK_MAX_PBUFS 00935 /* adjust the number of pbufs on queue */ 00936 LWIP_ASSERT("netif->loop_cnt_current underflow", 00937 ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); 00938 netif->loop_cnt_current -= clen; 00939 #endif /* LWIP_LOOPBACK_MAX_PBUFS */ 00940 00941 /* 'in_end' now points to the last pbuf from 'in' */ 00942 if (in_end == netif->loop_last) { 00943 /* this was the last pbuf in the list */ 00944 netif->loop_first = netif->loop_last = NULL; 00945 } else { 00946 /* pop the pbuf off the list */ 00947 netif->loop_first = in_end->next; 00948 LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL); 00949 } 00950 /* De-queue the pbuf from its successors on the 'loop_' list. */ 00951 in_end->next = NULL; 00952 SYS_ARCH_UNPROTECT(lev); 00953 00954 LINK_STATS_INC(link.recv); 00955 MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len); 00956 MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts); 00957 /* loopback packets are always IP packets! */ 00958 if (ip_input(in, netif) != ERR_OK) { 00959 pbuf_free(in); 00960 } 00961 SYS_ARCH_PROTECT(lev); 00962 } 00963 SYS_ARCH_UNPROTECT(lev); 00964 } 00965 00966 #if !LWIP_NETIF_LOOPBACK_MULTITHREADING 00967 /** 00968 * Calls netif_poll() for every netif on the netif_list. 00969 */ 00970 void 00971 netif_poll_all(void) 00972 { 00973 struct netif *netif = netif_list; 00974 /* loop through netifs */ 00975 while (netif != NULL) { 00976 netif_poll(netif); 00977 /* proceed to next network interface */ 00978 netif = netif->next; 00979 } 00980 } 00981 #endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ 00982 #endif /* ENABLE_LOOPBACK */ 00983 00984 #if LWIP_NUM_NETIF_CLIENT_DATA > 0 00985 /** 00986 * @ingroup netif_cd 00987 * Allocate an index to store data in client_data member of struct netif. 00988 * Returned value is an index in mentioned array. 00989 * @see LWIP_NUM_NETIF_CLIENT_DATA 00990 */ 00991 u8_t 00992 netif_alloc_client_data_id(void) 00993 { 00994 u8_t result = netif_client_id; 00995 netif_client_id++; 00996 00997 LWIP_ASSERT("Increase LWIP_NUM_NETIF_CLIENT_DATA in lwipopts.h", result < LWIP_NUM_NETIF_CLIENT_DATA); 00998 return result + LWIP_NETIF_CLIENT_DATA_INDEX_MAX; 00999 } 01000 #endif 01001 01002 #if LWIP_IPV6 01003 /** 01004 * @ingroup netif_ip6 01005 * Change an IPv6 address of a network interface 01006 * 01007 * @param netif the network interface to change 01008 * @param addr_idx index of the IPv6 address 01009 * @param addr6 the new IPv6 address 01010 * 01011 * @note call netif_ip6_addr_set_state() to set the address valid/temptative 01012 */ 01013 void 01014 netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6) 01015 { 01016 LWIP_ASSERT("addr6 != NULL", addr6 != NULL); 01017 netif_ip6_addr_set_parts(netif, addr_idx, addr6->addr[0], addr6->addr[1], 01018 addr6->addr[2], addr6->addr[3]); 01019 } 01020 01021 /* 01022 * Change an IPv6 address of a network interface (internal version taking 4 * u32_t) 01023 * 01024 * @param netif the network interface to change 01025 * @param addr_idx index of the IPv6 address 01026 * @param i0 word0 of the new IPv6 address 01027 * @param i1 word1 of the new IPv6 address 01028 * @param i2 word2 of the new IPv6 address 01029 * @param i3 word3 of the new IPv6 address 01030 */ 01031 void 01032 netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3) 01033 { 01034 const ip6_addr_t *old_addr; 01035 LWIP_ASSERT("netif != NULL", netif != NULL); 01036 LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); 01037 01038 old_addr = netif_ip6_addr(netif, addr_idx); 01039 /* address is actually being changed? */ 01040 if ((old_addr->addr[0] != i0) || (old_addr->addr[1] != i1) || 01041 (old_addr->addr[2] != i2) || (old_addr->addr[3] != i3)) { 01042 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set: netif address being changed\n")); 01043 01044 if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) { 01045 #if LWIP_TCP || LWIP_UDP 01046 ip_addr_t new_ipaddr; 01047 IP_ADDR6(&new_ipaddr, i0, i1, i2, i3); 01048 #endif /* LWIP_TCP || LWIP_UDP */ 01049 #if LWIP_TCP 01050 tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); 01051 #endif /* LWIP_TCP */ 01052 #if LWIP_UDP 01053 udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); 01054 #endif /* LWIP_UDP */ 01055 #if LWIP_RAW 01056 raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); 01057 #endif /* LWIP_RAW */ 01058 } 01059 /* @todo: remove/readd mib2 ip6 entries? */ 01060 01061 IP6_ADDR(ip_2_ip6(&(netif->ip6_addr[addr_idx])), i0, i1, i2, i3); 01062 IP_SET_TYPE_VAL(netif->ip6_addr[addr_idx], IPADDR_TYPE_V6); 01063 01064 if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) { 01065 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); 01066 NETIF_STATUS_CALLBACK(netif); 01067 } 01068 } 01069 01070 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", 01071 addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), 01072 netif_ip6_addr_state(netif, addr_idx))); 01073 } 01074 01075 /** 01076 * @ingroup netif_ip6 01077 * Change the state of an IPv6 address of a network interface 01078 * (INVALID, TEMPTATIVE, PREFERRED, DEPRECATED, where TEMPTATIVE 01079 * includes the number of checks done, see ip6_addr.h) 01080 * 01081 * @param netif the network interface to change 01082 * @param addr_idx index of the IPv6 address 01083 * @param state the new IPv6 address state 01084 */ 01085 void 01086 netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state) 01087 { 01088 u8_t old_state; 01089 LWIP_ASSERT("netif != NULL", netif != NULL); 01090 LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); 01091 01092 old_state = netif_ip6_addr_state(netif, addr_idx); 01093 /* state is actually being changed? */ 01094 if (old_state != state) { 01095 u8_t old_valid = old_state & IP6_ADDR_VALID; 01096 u8_t new_valid = state & IP6_ADDR_VALID; 01097 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n")); 01098 01099 #if LWIP_IPV6_MLD 01100 /* Reevaluate solicited-node multicast group membership. */ 01101 if (netif->flags & NETIF_FLAG_MLD6) { 01102 nd6_adjust_mld_membership(netif, addr_idx, state); 01103 } 01104 #endif /* LWIP_IPV6_MLD */ 01105 01106 if (old_valid && !new_valid) { 01107 /* address about to be removed by setting invalid */ 01108 #if LWIP_TCP 01109 tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); 01110 #endif /* LWIP_TCP */ 01111 #if LWIP_UDP 01112 udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); 01113 #endif /* LWIP_UDP */ 01114 #if LWIP_RAW 01115 raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); 01116 #endif /* LWIP_RAW */ 01117 /* @todo: remove mib2 ip6 entries? */ 01118 } 01119 netif->ip6_addr_state[addr_idx] = state; 01120 01121 if (!old_valid && new_valid) { 01122 /* address added by setting valid */ 01123 /* @todo: add mib2 ip6 entries? */ 01124 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); 01125 } 01126 if ((old_state & IP6_ADDR_PREFERRED) != (state & IP6_ADDR_PREFERRED)) { 01127 /* address state has changed (valid flag changed or switched between 01128 preferred and deprecated) -> call the callback function */ 01129 NETIF_STATUS_CALLBACK(netif); 01130 } 01131 } 01132 01133 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", 01134 addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), 01135 netif_ip6_addr_state(netif, addr_idx))); 01136 } 01137 01138 /** 01139 * Checks if a specific address is assigned to the netif and returns its 01140 * index. 01141 * 01142 * @param netif the netif to check 01143 * @param ip6addr the IPv6 address to find 01144 * @return >= 0: address found, this is its index 01145 * -1: address not found on this netif 01146 */ 01147 s8_t 01148 netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr) 01149 { 01150 s8_t i; 01151 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 01152 if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) && 01153 ip6_addr_cmp(netif_ip6_addr(netif, i), ip6addr)) { 01154 return i; 01155 } 01156 } 01157 return -1; 01158 } 01159 01160 /** 01161 * @ingroup netif_ip6 01162 * Create a link-local IPv6 address on a netif (stored in slot 0) 01163 * 01164 * @param netif the netif to create the address on 01165 * @param from_mac_48bit if != 0, assume hwadr is a 48-bit MAC address (std conversion) 01166 * if == 0, use hwaddr directly as interface ID 01167 */ 01168 void 01169 netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit) 01170 { 01171 u8_t i, addr_index; 01172 01173 /* Link-local prefix. */ 01174 ip_2_ip6(&netif->ip6_addr[0])->addr[0] = PP_HTONL(0xfe800000ul); 01175 ip_2_ip6(&netif->ip6_addr[0])->addr[1] = 0; 01176 01177 /* Generate interface ID. */ 01178 if (from_mac_48bit) { 01179 /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */ 01180 ip_2_ip6(&netif->ip6_addr[0])->addr[2] = lwip_htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) | 01181 ((u32_t)(netif->hwaddr[1]) << 16) | 01182 ((u32_t)(netif->hwaddr[2]) << 8) | 01183 (0xff)); 01184 ip_2_ip6(&netif->ip6_addr[0])->addr[3] = lwip_htonl((0xfeul << 24) | 01185 ((u32_t)(netif->hwaddr[3]) << 16) | 01186 ((u32_t)(netif->hwaddr[4]) << 8) | 01187 (netif->hwaddr[5])); 01188 } else { 01189 /* Use hwaddr directly as interface ID. */ 01190 ip_2_ip6(&netif->ip6_addr[0])->addr[2] = 0; 01191 ip_2_ip6(&netif->ip6_addr[0])->addr[3] = 0; 01192 01193 addr_index = 3; 01194 for (i = 0; (i < 8) && (i < netif->hwaddr_len); i++) { 01195 if (i == 4) { 01196 addr_index--; 01197 } 01198 ip_2_ip6(&netif->ip6_addr[0])->addr[addr_index] |= ((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03)); 01199 } 01200 } 01201 01202 /* Set address state. */ 01203 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS 01204 /* Will perform duplicate address detection (DAD). */ 01205 netif_ip6_addr_set_state(netif, 0, IP6_ADDR_TENTATIVE); 01206 #else 01207 /* Consider address valid. */ 01208 netif_ip6_addr_set_state(netif, 0, IP6_ADDR_PREFERRED); 01209 #endif /* LWIP_IPV6_AUTOCONFIG */ 01210 } 01211 01212 /** 01213 * @ingroup netif_ip6 01214 * This function allows for the easy addition of a new IPv6 address to an interface. 01215 * It takes care of finding an empty slot and then sets the address tentative 01216 * (to make sure that all the subsequent processing happens). 01217 * 01218 * @param netif netif to add the address on 01219 * @param ip6addr address to add 01220 * @param chosen_idx if != NULL, the chosen IPv6 address index will be stored here 01221 */ 01222 err_t 01223 netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx) 01224 { 01225 s8_t i; 01226 01227 i = netif_get_ip6_addr_match(netif, ip6addr); 01228 if (i >= 0) { 01229 /* Address already added */ 01230 if (chosen_idx != NULL) { 01231 *chosen_idx = i; 01232 } 01233 return ERR_OK; 01234 } 01235 01236 /* Find a free slot -- musn't be the first one (reserved for link local) */ 01237 for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 01238 if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) { 01239 ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr); 01240 netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE); 01241 if (chosen_idx != NULL) { 01242 *chosen_idx = i; 01243 } 01244 return ERR_OK; 01245 } 01246 } 01247 01248 if (chosen_idx != NULL) { 01249 *chosen_idx = -1; 01250 } 01251 return ERR_VAL; 01252 } 01253 01254 /** Dummy IPv6 output function for netifs not supporting IPv6 01255 */ 01256 static err_t 01257 netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr) 01258 { 01259 LWIP_UNUSED_ARG(netif); 01260 LWIP_UNUSED_ARG(p); 01261 LWIP_UNUSED_ARG(ipaddr); 01262 01263 return ERR_IF; 01264 } 01265 #endif /* LWIP_IPV6 */
Generated on Tue Jul 12 2022 11:02:27 by
1.7.2