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.
Fork of OmniWheels by
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 #if LWIP_IPV6_ADDRESS_LIFETIMES 00264 netif->ip6_addr_valid_life[i] = IP6_ADDR_LIFE_STATIC; 00265 netif->ip6_addr_pref_life[i] = IP6_ADDR_LIFE_STATIC; 00266 #endif /* LWIP_IPV6_ADDRESS_LIFETIMES */ 00267 } 00268 netif->output_ip6 = netif_null_output_ip6; 00269 #endif /* LWIP_IPV6 */ 00270 NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL); 00271 netif->flags = 0; 00272 #ifdef netif_get_client_data 00273 memset(netif->client_data, 0, sizeof(netif->client_data)); 00274 #endif /* LWIP_NUM_NETIF_CLIENT_DATA */ 00275 #if LWIP_IPV6_AUTOCONFIG 00276 /* IPv6 address autoconfiguration not enabled by default */ 00277 netif->ip6_autoconfig_enabled = 0; 00278 #endif /* LWIP_IPV6_AUTOCONFIG */ 00279 #if LWIP_IPV6_SEND_ROUTER_SOLICIT 00280 netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; 00281 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ 00282 #if LWIP_NETIF_STATUS_CALLBACK 00283 netif->status_callback = NULL; 00284 #endif /* LWIP_NETIF_STATUS_CALLBACK */ 00285 #if LWIP_NETIF_LINK_CALLBACK 00286 netif->link_callback = NULL; 00287 #endif /* LWIP_NETIF_LINK_CALLBACK */ 00288 #if LWIP_IGMP 00289 netif->igmp_mac_filter = NULL; 00290 #endif /* LWIP_IGMP */ 00291 #if LWIP_IPV6 && LWIP_IPV6_MLD 00292 netif->mld_mac_filter = NULL; 00293 #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ 00294 #if ENABLE_LOOPBACK 00295 netif->loop_first = NULL; 00296 netif->loop_last = NULL; 00297 #endif /* ENABLE_LOOPBACK */ 00298 00299 /* remember netif specific state information data */ 00300 netif->state = state; 00301 netif->num = netif_num++; 00302 netif->input = input; 00303 00304 NETIF_SET_HWADDRHINT(netif, NULL); 00305 #if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS 00306 netif->loop_cnt_current = 0; 00307 #endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */ 00308 00309 #if LWIP_IPV4 00310 netif_set_addr(netif, ipaddr, netmask, gw); 00311 #endif /* LWIP_IPV4 */ 00312 00313 /* call user specified initialization function for netif */ 00314 if (init(netif) != ERR_OK) { 00315 return NULL; 00316 } 00317 00318 /* add this netif to the list */ 00319 netif->next = netif_list; 00320 netif_list = netif; 00321 mib2_netif_added(netif); 00322 00323 #if LWIP_IGMP 00324 /* start IGMP processing */ 00325 if (netif->flags & NETIF_FLAG_IGMP) { 00326 igmp_start(netif); 00327 } 00328 #endif /* LWIP_IGMP */ 00329 00330 LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP", 00331 netif->name[0], netif->name[1])); 00332 #if LWIP_IPV4 00333 LWIP_DEBUGF(NETIF_DEBUG, (" addr ")); 00334 ip4_addr_debug_print(NETIF_DEBUG, ipaddr); 00335 LWIP_DEBUGF(NETIF_DEBUG, (" netmask ")); 00336 ip4_addr_debug_print(NETIF_DEBUG, netmask); 00337 LWIP_DEBUGF(NETIF_DEBUG, (" gw ")); 00338 ip4_addr_debug_print(NETIF_DEBUG, gw); 00339 #endif /* LWIP_IPV4 */ 00340 LWIP_DEBUGF(NETIF_DEBUG, ("\n")); 00341 return netif; 00342 } 00343 00344 #if LWIP_IPV4 00345 /** 00346 * @ingroup netif_ip4 00347 * Change IP address configuration for a network interface (including netmask 00348 * and default gateway). 00349 * 00350 * @param netif the network interface to change 00351 * @param ipaddr the new IP address 00352 * @param netmask the new netmask 00353 * @param gw the new default gateway 00354 */ 00355 void 00356 netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, 00357 const ip4_addr_t *gw) 00358 { 00359 if (ip4_addr_isany(ipaddr)) { 00360 /* when removing an address, we have to remove it *before* changing netmask/gw 00361 to ensure that tcp RST segment can be sent correctly */ 00362 netif_set_ipaddr(netif, ipaddr); 00363 netif_set_netmask(netif, netmask); 00364 netif_set_gw(netif, gw); 00365 } else { 00366 netif_set_netmask(netif, netmask); 00367 netif_set_gw(netif, gw); 00368 /* set ipaddr last to ensure netmask/gw have been set when status callback is called */ 00369 netif_set_ipaddr(netif, ipaddr); 00370 } 00371 } 00372 #endif /* LWIP_IPV4*/ 00373 00374 /** 00375 * @ingroup netif 00376 * Remove a network interface from the list of lwIP netifs. 00377 * 00378 * @param netif the network interface to remove 00379 */ 00380 void 00381 netif_remove(struct netif *netif) 00382 { 00383 #if LWIP_IPV6 00384 int i; 00385 #endif 00386 00387 if (netif == NULL) { 00388 return; 00389 } 00390 00391 #if LWIP_IPV4 00392 if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { 00393 #if LWIP_TCP 00394 tcp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); 00395 #endif /* LWIP_TCP */ 00396 #if LWIP_UDP 00397 udp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); 00398 #endif /* LWIP_UDP */ 00399 #if LWIP_RAW 00400 raw_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); 00401 #endif /* LWIP_RAW */ 00402 } 00403 00404 #if LWIP_IGMP 00405 /* stop IGMP processing */ 00406 if (netif->flags & NETIF_FLAG_IGMP) { 00407 igmp_stop(netif); 00408 } 00409 #endif /* LWIP_IGMP */ 00410 #endif /* LWIP_IPV4*/ 00411 00412 #if LWIP_IPV6 00413 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00414 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { 00415 #if LWIP_TCP 00416 tcp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); 00417 #endif /* LWIP_TCP */ 00418 #if LWIP_UDP 00419 udp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); 00420 #endif /* LWIP_UDP */ 00421 #if LWIP_RAW 00422 raw_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); 00423 #endif /* LWIP_RAW */ 00424 } 00425 } 00426 #if LWIP_IPV6_MLD 00427 /* stop MLD processing */ 00428 mld6_stop(netif); 00429 #endif /* LWIP_IPV6_MLD */ 00430 #endif /* LWIP_IPV6 */ 00431 if (netif_is_up(netif)) { 00432 /* set netif down before removing (call callback function) */ 00433 netif_set_down(netif); 00434 } 00435 00436 mib2_remove_ip4(netif); 00437 00438 /* this netif is default? */ 00439 if (netif_default == netif) { 00440 /* reset default netif */ 00441 netif_set_default(NULL); 00442 } 00443 /* is it the first netif? */ 00444 if (netif_list == netif) { 00445 netif_list = netif->next; 00446 } else { 00447 /* look for netif further down the list */ 00448 struct netif * tmp_netif; 00449 for (tmp_netif = netif_list; tmp_netif != NULL; tmp_netif = tmp_netif->next) { 00450 if (tmp_netif->next == netif) { 00451 tmp_netif->next = netif->next; 00452 break; 00453 } 00454 } 00455 if (tmp_netif == NULL) { 00456 return; /* netif is not on the list */ 00457 } 00458 } 00459 mib2_netif_removed(netif); 00460 #if LWIP_NETIF_REMOVE_CALLBACK 00461 if (netif->remove_callback) { 00462 netif->remove_callback(netif); 00463 } 00464 #endif /* LWIP_NETIF_REMOVE_CALLBACK */ 00465 LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); 00466 } 00467 00468 /** 00469 * @ingroup netif 00470 * Find a network interface by searching for its name 00471 * 00472 * @param name the name of the netif (like netif->name) plus concatenated number 00473 * in ascii representation (e.g. 'en0') 00474 */ 00475 struct netif * 00476 netif_find(const char *name) 00477 { 00478 struct netif *netif; 00479 u8_t num; 00480 00481 if (name == NULL) { 00482 return NULL; 00483 } 00484 00485 num = (u8_t)(name[2] - '0'); 00486 00487 for (netif = netif_list; netif != NULL; netif = netif->next) { 00488 if (num == netif->num && 00489 name[0] == netif->name[0] && 00490 name[1] == netif->name[1]) { 00491 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); 00492 return netif; 00493 } 00494 } 00495 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); 00496 return NULL; 00497 } 00498 00499 #if LWIP_IPV4 00500 /** 00501 * @ingroup netif_ip4 00502 * Change the IP address of a network interface 00503 * 00504 * @param netif the network interface to change 00505 * @param ipaddr the new IP address 00506 * 00507 * @note call netif_set_addr() if you also want to change netmask and 00508 * default gateway 00509 */ 00510 void 00511 netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr) 00512 { 00513 ip_addr_t new_addr; 00514 *ip_2_ip4(&new_addr) = (ipaddr ? *ipaddr : *IP4_ADDR_ANY4); 00515 IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_V4); 00516 00517 /* address is actually being changed? */ 00518 if (ip4_addr_cmp(ip_2_ip4(&new_addr), netif_ip4_addr(netif)) == 0) { 00519 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); 00520 #if LWIP_TCP 00521 tcp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); 00522 #endif /* LWIP_TCP */ 00523 #if LWIP_UDP 00524 udp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); 00525 #endif /* LWIP_UDP */ 00526 #if LWIP_RAW 00527 raw_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); 00528 #endif /* LWIP_RAW */ 00529 00530 mib2_remove_ip4(netif); 00531 mib2_remove_route_ip4(0, netif); 00532 /* set new IP address to netif */ 00533 ip4_addr_set(ip_2_ip4(&netif->ip_addr), ipaddr); 00534 IP_SET_TYPE_VAL(netif->ip_addr, IPADDR_TYPE_V4); 00535 mib2_add_ip4(netif); 00536 mib2_add_route_ip4(0, netif); 00537 00538 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4); 00539 00540 NETIF_STATUS_CALLBACK(netif); 00541 } 00542 00543 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", 00544 netif->name[0], netif->name[1], 00545 ip4_addr1_16(netif_ip4_addr(netif)), 00546 ip4_addr2_16(netif_ip4_addr(netif)), 00547 ip4_addr3_16(netif_ip4_addr(netif)), 00548 ip4_addr4_16(netif_ip4_addr(netif)))); 00549 } 00550 00551 /** 00552 * @ingroup netif_ip4 00553 * Change the default gateway for a network interface 00554 * 00555 * @param netif the network interface to change 00556 * @param gw the new default gateway 00557 * 00558 * @note call netif_set_addr() if you also want to change ip address and netmask 00559 */ 00560 void 00561 netif_set_gw(struct netif *netif, const ip4_addr_t *gw) 00562 { 00563 ip4_addr_set(ip_2_ip4(&netif->gw), gw); 00564 IP_SET_TYPE_VAL(netif->gw, IPADDR_TYPE_V4); 00565 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", 00566 netif->name[0], netif->name[1], 00567 ip4_addr1_16(netif_ip4_gw(netif)), 00568 ip4_addr2_16(netif_ip4_gw(netif)), 00569 ip4_addr3_16(netif_ip4_gw(netif)), 00570 ip4_addr4_16(netif_ip4_gw(netif)))); 00571 } 00572 00573 /** 00574 * @ingroup netif_ip4 00575 * Change the netmask of a network interface 00576 * 00577 * @param netif the network interface to change 00578 * @param netmask the new netmask 00579 * 00580 * @note call netif_set_addr() if you also want to change ip address and 00581 * default gateway 00582 */ 00583 void 00584 netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask) 00585 { 00586 mib2_remove_route_ip4(0, netif); 00587 /* set new netmask to netif */ 00588 ip4_addr_set(ip_2_ip4(&netif->netmask), netmask); 00589 IP_SET_TYPE_VAL(netif->netmask, IPADDR_TYPE_V4); 00590 mib2_add_route_ip4(0, netif); 00591 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", 00592 netif->name[0], netif->name[1], 00593 ip4_addr1_16(netif_ip4_netmask(netif)), 00594 ip4_addr2_16(netif_ip4_netmask(netif)), 00595 ip4_addr3_16(netif_ip4_netmask(netif)), 00596 ip4_addr4_16(netif_ip4_netmask(netif)))); 00597 } 00598 #endif /* LWIP_IPV4 */ 00599 00600 /** 00601 * @ingroup netif 00602 * Set a network interface as the default network interface 00603 * (used to output all packets for which no specific route is found) 00604 * 00605 * @param netif the default network interface 00606 */ 00607 void 00608 netif_set_default(struct netif *netif) 00609 { 00610 if (netif == NULL) { 00611 /* remove default route */ 00612 mib2_remove_route_ip4(1, netif); 00613 } else { 00614 /* install default route */ 00615 mib2_add_route_ip4(1, netif); 00616 } 00617 netif_default = netif; 00618 LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", 00619 netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); 00620 } 00621 00622 /** 00623 * @ingroup netif 00624 * Bring an interface up, available for processing 00625 * traffic. 00626 */ 00627 void 00628 netif_set_up(struct netif *netif) 00629 { 00630 if (!(netif->flags & NETIF_FLAG_UP)) { 00631 netif->flags |= NETIF_FLAG_UP; 00632 00633 MIB2_COPY_SYSUPTIME_TO(&netif->ts); 00634 00635 NETIF_STATUS_CALLBACK(netif); 00636 00637 if (netif->flags & NETIF_FLAG_LINK_UP) { 00638 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6); 00639 } 00640 } 00641 } 00642 00643 /** Send ARP/IGMP/MLD/RS events, e.g. on link-up/netif-up or addr-change 00644 */ 00645 static void 00646 netif_issue_reports(struct netif* netif, u8_t report_type) 00647 { 00648 #if LWIP_IPV4 00649 if ((report_type & NETIF_REPORT_TYPE_IPV4) && 00650 !ip4_addr_isany_val(*netif_ip4_addr(netif))) { 00651 #if LWIP_ARP 00652 /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ 00653 if (netif->flags & (NETIF_FLAG_ETHARP)) { 00654 etharp_gratuitous(netif); 00655 } 00656 #endif /* LWIP_ARP */ 00657 00658 #if LWIP_IGMP 00659 /* resend IGMP memberships */ 00660 if (netif->flags & NETIF_FLAG_IGMP) { 00661 igmp_report_groups(netif); 00662 } 00663 #endif /* LWIP_IGMP */ 00664 } 00665 #endif /* LWIP_IPV4 */ 00666 00667 #if LWIP_IPV6 00668 if (report_type & NETIF_REPORT_TYPE_IPV6) { 00669 #if LWIP_IPV6_MLD 00670 /* send mld memberships */ 00671 mld6_report_groups(netif); 00672 #endif /* LWIP_IPV6_MLD */ 00673 #if LWIP_IPV6_SEND_ROUTER_SOLICIT 00674 /* Send Router Solicitation messages. */ 00675 netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; 00676 #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ 00677 } 00678 #endif /* LWIP_IPV6 */ 00679 } 00680 00681 /** 00682 * @ingroup netif 00683 * Bring an interface down, disabling any traffic processing. 00684 */ 00685 void 00686 netif_set_down(struct netif *netif) 00687 { 00688 if (netif->flags & NETIF_FLAG_UP) { 00689 netif->flags &= ~NETIF_FLAG_UP; 00690 MIB2_COPY_SYSUPTIME_TO(&netif->ts); 00691 00692 #if LWIP_IPV4 && LWIP_ARP 00693 if (netif->flags & NETIF_FLAG_ETHARP) { 00694 etharp_cleanup_netif(netif); 00695 } 00696 #endif /* LWIP_IPV4 && LWIP_ARP */ 00697 00698 #if LWIP_IPV6 00699 nd6_cleanup_netif(netif); 00700 #endif /* LWIP_IPV6 */ 00701 00702 NETIF_STATUS_CALLBACK(netif); 00703 } 00704 } 00705 00706 #if LWIP_NETIF_STATUS_CALLBACK 00707 /** 00708 * @ingroup netif 00709 * Set callback to be called when interface is brought up/down or address is changed while up 00710 */ 00711 void 00712 netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback) 00713 { 00714 if (netif) { 00715 netif->status_callback = status_callback; 00716 } 00717 } 00718 #endif /* LWIP_NETIF_STATUS_CALLBACK */ 00719 00720 #if LWIP_NETIF_REMOVE_CALLBACK 00721 /** 00722 * @ingroup netif 00723 * Set callback to be called when the interface has been removed 00724 */ 00725 void 00726 netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback) 00727 { 00728 if (netif) { 00729 netif->remove_callback = remove_callback; 00730 } 00731 } 00732 #endif /* LWIP_NETIF_REMOVE_CALLBACK */ 00733 00734 /** 00735 * @ingroup netif 00736 * Called by a driver when its link goes up 00737 */ 00738 void 00739 netif_set_link_up(struct netif *netif) 00740 { 00741 if (!(netif->flags & NETIF_FLAG_LINK_UP)) { 00742 netif->flags |= NETIF_FLAG_LINK_UP; 00743 00744 #if LWIP_DHCP 00745 dhcp_network_changed(netif); 00746 #endif /* LWIP_DHCP */ 00747 00748 #if LWIP_AUTOIP 00749 autoip_network_changed(netif); 00750 #endif /* LWIP_AUTOIP */ 00751 00752 if (netif->flags & NETIF_FLAG_UP) { 00753 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6); 00754 } 00755 NETIF_LINK_CALLBACK(netif); 00756 } 00757 } 00758 00759 /** 00760 * @ingroup netif 00761 * Called by a driver when its link goes down 00762 */ 00763 void 00764 netif_set_link_down(struct netif *netif ) 00765 { 00766 if (netif->flags & NETIF_FLAG_LINK_UP) { 00767 netif->flags &= ~NETIF_FLAG_LINK_UP; 00768 NETIF_LINK_CALLBACK(netif); 00769 } 00770 } 00771 00772 #if LWIP_NETIF_LINK_CALLBACK 00773 /** 00774 * @ingroup netif 00775 * Set callback to be called when link is brought up/down 00776 */ 00777 void 00778 netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback) 00779 { 00780 if (netif) { 00781 netif->link_callback = link_callback; 00782 } 00783 } 00784 #endif /* LWIP_NETIF_LINK_CALLBACK */ 00785 00786 #if ENABLE_LOOPBACK 00787 /** 00788 * @ingroup netif 00789 * Send an IP packet to be received on the same netif (loopif-like). 00790 * The pbuf is simply copied and handed back to netif->input. 00791 * In multithreaded mode, this is done directly since netif->input must put 00792 * the packet on a queue. 00793 * In callback mode, the packet is put on an internal queue and is fed to 00794 * netif->input by netif_poll(). 00795 * 00796 * @param netif the lwip network interface structure 00797 * @param p the (IP) packet to 'send' 00798 * @return ERR_OK if the packet has been sent 00799 * ERR_MEM if the pbuf used to copy the packet couldn't be allocated 00800 */ 00801 err_t 00802 netif_loop_output(struct netif *netif, struct pbuf *p) 00803 { 00804 struct pbuf *r; 00805 err_t err; 00806 struct pbuf *last; 00807 #if LWIP_LOOPBACK_MAX_PBUFS 00808 u16_t clen = 0; 00809 #endif /* LWIP_LOOPBACK_MAX_PBUFS */ 00810 /* If we have a loopif, SNMP counters are adjusted for it, 00811 * if not they are adjusted for 'netif'. */ 00812 #if MIB2_STATS 00813 #if LWIP_HAVE_LOOPIF 00814 struct netif *stats_if = &loop_netif; 00815 #else /* LWIP_HAVE_LOOPIF */ 00816 struct netif *stats_if = netif; 00817 #endif /* LWIP_HAVE_LOOPIF */ 00818 #endif /* MIB2_STATS */ 00819 SYS_ARCH_DECL_PROTECT(lev); 00820 00821 /* Allocate a new pbuf */ 00822 r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); 00823 if (r == NULL) { 00824 LINK_STATS_INC(link.memerr); 00825 LINK_STATS_INC(link.drop); 00826 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); 00827 return ERR_MEM; 00828 } 00829 #if LWIP_LOOPBACK_MAX_PBUFS 00830 clen = pbuf_clen(r); 00831 /* check for overflow or too many pbuf on queue */ 00832 if (((netif->loop_cnt_current + clen) < netif->loop_cnt_current) || 00833 ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) { 00834 pbuf_free(r); 00835 LINK_STATS_INC(link.memerr); 00836 LINK_STATS_INC(link.drop); 00837 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); 00838 return ERR_MEM; 00839 } 00840 netif->loop_cnt_current += clen; 00841 #endif /* LWIP_LOOPBACK_MAX_PBUFS */ 00842 00843 /* Copy the whole pbuf queue p into the single pbuf r */ 00844 if ((err = pbuf_copy(r, p)) != ERR_OK) { 00845 pbuf_free(r); 00846 LINK_STATS_INC(link.memerr); 00847 LINK_STATS_INC(link.drop); 00848 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); 00849 return err; 00850 } 00851 00852 /* Put the packet on a linked list which gets emptied through calling 00853 netif_poll(). */ 00854 00855 /* let last point to the last pbuf in chain r */ 00856 for (last = r; last->next != NULL; last = last->next); 00857 00858 SYS_ARCH_PROTECT(lev); 00859 if (netif->loop_first != NULL) { 00860 LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); 00861 netif->loop_last->next = r; 00862 netif->loop_last = last; 00863 } else { 00864 netif->loop_first = r; 00865 netif->loop_last = last; 00866 } 00867 SYS_ARCH_UNPROTECT(lev); 00868 00869 LINK_STATS_INC(link.xmit); 00870 MIB2_STATS_NETIF_ADD(stats_if, ifoutoctets, p->tot_len); 00871 MIB2_STATS_NETIF_INC(stats_if, ifoutucastpkts); 00872 00873 #if LWIP_NETIF_LOOPBACK_MULTITHREADING 00874 /* For multithreading environment, schedule a call to netif_poll */ 00875 tcpip_callback_with_block((tcpip_callback_fn)netif_poll, netif, 0); 00876 #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 00877 00878 return ERR_OK; 00879 } 00880 00881 #if LWIP_HAVE_LOOPIF 00882 #if LWIP_IPV4 00883 static err_t 00884 netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t* addr) 00885 { 00886 LWIP_UNUSED_ARG(addr); 00887 return netif_loop_output(netif, p); 00888 } 00889 #endif /* LWIP_IPV4 */ 00890 00891 #if LWIP_IPV6 00892 static err_t 00893 netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* addr) 00894 { 00895 LWIP_UNUSED_ARG(addr); 00896 return netif_loop_output(netif, p); 00897 } 00898 #endif /* LWIP_IPV6 */ 00899 #endif /* LWIP_HAVE_LOOPIF */ 00900 00901 00902 /** 00903 * Call netif_poll() in the main loop of your application. This is to prevent 00904 * reentering non-reentrant functions like tcp_input(). Packets passed to 00905 * netif_loop_output() are put on a list that is passed to netif->input() by 00906 * netif_poll(). 00907 */ 00908 void 00909 netif_poll(struct netif *netif) 00910 { 00911 /* If we have a loopif, SNMP counters are adjusted for it, 00912 * if not they are adjusted for 'netif'. */ 00913 #if MIB2_STATS 00914 #if LWIP_HAVE_LOOPIF 00915 struct netif *stats_if = &loop_netif; 00916 #else /* LWIP_HAVE_LOOPIF */ 00917 struct netif *stats_if = netif; 00918 #endif /* LWIP_HAVE_LOOPIF */ 00919 #endif /* MIB2_STATS */ 00920 SYS_ARCH_DECL_PROTECT(lev); 00921 00922 /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ 00923 SYS_ARCH_PROTECT(lev); 00924 while (netif->loop_first != NULL) { 00925 struct pbuf *in, *in_end; 00926 #if LWIP_LOOPBACK_MAX_PBUFS 00927 u8_t clen = 1; 00928 #endif /* LWIP_LOOPBACK_MAX_PBUFS */ 00929 00930 in = in_end = netif->loop_first; 00931 while (in_end->len != in_end->tot_len) { 00932 LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); 00933 in_end = in_end->next; 00934 #if LWIP_LOOPBACK_MAX_PBUFS 00935 clen++; 00936 #endif /* LWIP_LOOPBACK_MAX_PBUFS */ 00937 } 00938 #if LWIP_LOOPBACK_MAX_PBUFS 00939 /* adjust the number of pbufs on queue */ 00940 LWIP_ASSERT("netif->loop_cnt_current underflow", 00941 ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); 00942 netif->loop_cnt_current -= clen; 00943 #endif /* LWIP_LOOPBACK_MAX_PBUFS */ 00944 00945 /* 'in_end' now points to the last pbuf from 'in' */ 00946 if (in_end == netif->loop_last) { 00947 /* this was the last pbuf in the list */ 00948 netif->loop_first = netif->loop_last = NULL; 00949 } else { 00950 /* pop the pbuf off the list */ 00951 netif->loop_first = in_end->next; 00952 LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL); 00953 } 00954 /* De-queue the pbuf from its successors on the 'loop_' list. */ 00955 in_end->next = NULL; 00956 SYS_ARCH_UNPROTECT(lev); 00957 00958 LINK_STATS_INC(link.recv); 00959 MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len); 00960 MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts); 00961 /* loopback packets are always IP packets! */ 00962 if (ip_input(in, netif) != ERR_OK) { 00963 pbuf_free(in); 00964 } 00965 SYS_ARCH_PROTECT(lev); 00966 } 00967 SYS_ARCH_UNPROTECT(lev); 00968 } 00969 00970 #if !LWIP_NETIF_LOOPBACK_MULTITHREADING 00971 /** 00972 * Calls netif_poll() for every netif on the netif_list. 00973 */ 00974 void 00975 netif_poll_all(void) 00976 { 00977 struct netif *netif = netif_list; 00978 /* loop through netifs */ 00979 while (netif != NULL) { 00980 netif_poll(netif); 00981 /* proceed to next network interface */ 00982 netif = netif->next; 00983 } 00984 } 00985 #endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ 00986 #endif /* ENABLE_LOOPBACK */ 00987 00988 #if LWIP_NUM_NETIF_CLIENT_DATA > 0 00989 /** 00990 * @ingroup netif_cd 00991 * Allocate an index to store data in client_data member of struct netif. 00992 * Returned value is an index in mentioned array. 00993 * @see LWIP_NUM_NETIF_CLIENT_DATA 00994 */ 00995 u8_t 00996 netif_alloc_client_data_id(void) 00997 { 00998 u8_t result = netif_client_id; 00999 netif_client_id++; 01000 01001 LWIP_ASSERT("Increase LWIP_NUM_NETIF_CLIENT_DATA in lwipopts.h", result < LWIP_NUM_NETIF_CLIENT_DATA); 01002 return result + LWIP_NETIF_CLIENT_DATA_INDEX_MAX; 01003 } 01004 #endif 01005 01006 #if LWIP_IPV6 01007 /** 01008 * @ingroup netif_ip6 01009 * Change an IPv6 address of a network interface 01010 * 01011 * @param netif the network interface to change 01012 * @param addr_idx index of the IPv6 address 01013 * @param addr6 the new IPv6 address 01014 * 01015 * @note call netif_ip6_addr_set_state() to set the address valid/temptative 01016 */ 01017 void 01018 netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6) 01019 { 01020 LWIP_ASSERT("addr6 != NULL", addr6 != NULL); 01021 netif_ip6_addr_set_parts(netif, addr_idx, addr6->addr[0], addr6->addr[1], 01022 addr6->addr[2], addr6->addr[3]); 01023 } 01024 01025 /* 01026 * Change an IPv6 address of a network interface (internal version taking 4 * u32_t) 01027 * 01028 * @param netif the network interface to change 01029 * @param addr_idx index of the IPv6 address 01030 * @param i0 word0 of the new IPv6 address 01031 * @param i1 word1 of the new IPv6 address 01032 * @param i2 word2 of the new IPv6 address 01033 * @param i3 word3 of the new IPv6 address 01034 */ 01035 void 01036 netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3) 01037 { 01038 const ip6_addr_t *old_addr; 01039 LWIP_ASSERT("netif != NULL", netif != NULL); 01040 LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); 01041 01042 old_addr = netif_ip6_addr(netif, addr_idx); 01043 /* address is actually being changed? */ 01044 if ((old_addr->addr[0] != i0) || (old_addr->addr[1] != i1) || 01045 (old_addr->addr[2] != i2) || (old_addr->addr[3] != i3)) { 01046 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set: netif address being changed\n")); 01047 01048 if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) { 01049 #if LWIP_TCP || LWIP_UDP 01050 ip_addr_t new_ipaddr; 01051 IP_ADDR6(&new_ipaddr, i0, i1, i2, i3); 01052 #endif /* LWIP_TCP || LWIP_UDP */ 01053 #if LWIP_TCP 01054 tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); 01055 #endif /* LWIP_TCP */ 01056 #if LWIP_UDP 01057 udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); 01058 #endif /* LWIP_UDP */ 01059 #if LWIP_RAW 01060 raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); 01061 #endif /* LWIP_RAW */ 01062 } 01063 /* @todo: remove/readd mib2 ip6 entries? */ 01064 01065 IP6_ADDR(ip_2_ip6(&(netif->ip6_addr[addr_idx])), i0, i1, i2, i3); 01066 IP_SET_TYPE_VAL(netif->ip6_addr[addr_idx], IPADDR_TYPE_V6); 01067 01068 if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) { 01069 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); 01070 NETIF_STATUS_CALLBACK(netif); 01071 } 01072 } 01073 01074 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", 01075 addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), 01076 netif_ip6_addr_state(netif, addr_idx))); 01077 } 01078 01079 /** 01080 * @ingroup netif_ip6 01081 * Change the state of an IPv6 address of a network interface 01082 * (INVALID, TEMPTATIVE, PREFERRED, DEPRECATED, where TEMPTATIVE 01083 * includes the number of checks done, see ip6_addr.h) 01084 * 01085 * @param netif the network interface to change 01086 * @param addr_idx index of the IPv6 address 01087 * @param state the new IPv6 address state 01088 */ 01089 void 01090 netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state) 01091 { 01092 u8_t old_state; 01093 LWIP_ASSERT("netif != NULL", netif != NULL); 01094 LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); 01095 01096 old_state = netif_ip6_addr_state(netif, addr_idx); 01097 /* state is actually being changed? */ 01098 if (old_state != state) { 01099 u8_t old_valid = old_state & IP6_ADDR_VALID; 01100 u8_t new_valid = state & IP6_ADDR_VALID; 01101 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n")); 01102 01103 #if LWIP_IPV6_MLD 01104 /* Reevaluate solicited-node multicast group membership. */ 01105 if (netif->flags & NETIF_FLAG_MLD6) { 01106 nd6_adjust_mld_membership(netif, addr_idx, state); 01107 } 01108 #endif /* LWIP_IPV6_MLD */ 01109 01110 if (old_valid && !new_valid) { 01111 /* address about to be removed by setting invalid */ 01112 #if LWIP_TCP 01113 tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); 01114 #endif /* LWIP_TCP */ 01115 #if LWIP_UDP 01116 udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); 01117 #endif /* LWIP_UDP */ 01118 #if LWIP_RAW 01119 raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); 01120 #endif /* LWIP_RAW */ 01121 /* @todo: remove mib2 ip6 entries? */ 01122 } 01123 netif->ip6_addr_state[addr_idx] = state; 01124 01125 if (!old_valid && new_valid) { 01126 /* address added by setting valid */ 01127 /* @todo: add mib2 ip6 entries? */ 01128 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); 01129 } 01130 if ((old_state & ~IP6_ADDR_TENTATIVE_COUNT_MASK) != 01131 (state & ~IP6_ADDR_TENTATIVE_COUNT_MASK)) { 01132 /* address state has changed -> call the callback function */ 01133 NETIF_STATUS_CALLBACK(netif); 01134 } 01135 } 01136 01137 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", 01138 addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), 01139 netif_ip6_addr_state(netif, addr_idx))); 01140 } 01141 01142 /** 01143 * Checks if a specific local address is present on the netif and returns its 01144 * index. Depending on its state, it may or may not be assigned to the 01145 * interface (as per RFC terminology). 01146 * 01147 * @param netif the netif to check 01148 * @param ip6addr the IPv6 address to find 01149 * @return >= 0: address found, this is its index 01150 * -1: address not found on this netif 01151 */ 01152 s8_t 01153 netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr) 01154 { 01155 s8_t i; 01156 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 01157 if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) && 01158 ip6_addr_cmp(netif_ip6_addr(netif, i), ip6addr)) { 01159 return i; 01160 } 01161 } 01162 return -1; 01163 } 01164 01165 /** 01166 * @ingroup netif_ip6 01167 * Create a link-local IPv6 address on a netif (stored in slot 0) 01168 * 01169 * @param netif the netif to create the address on 01170 * @param from_mac_48bit if != 0, assume hwadr is a 48-bit MAC address (std conversion) 01171 * if == 0, use hwaddr directly as interface ID 01172 */ 01173 void 01174 netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit) 01175 { 01176 u8_t i, addr_index; 01177 01178 /* Link-local prefix. */ 01179 ip_2_ip6(&netif->ip6_addr[0])->addr[0] = PP_HTONL(0xfe800000ul); 01180 ip_2_ip6(&netif->ip6_addr[0])->addr[1] = 0; 01181 01182 /* Generate interface ID. */ 01183 if (from_mac_48bit) { 01184 /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */ 01185 ip_2_ip6(&netif->ip6_addr[0])->addr[2] = lwip_htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) | 01186 ((u32_t)(netif->hwaddr[1]) << 16) | 01187 ((u32_t)(netif->hwaddr[2]) << 8) | 01188 (0xff)); 01189 ip_2_ip6(&netif->ip6_addr[0])->addr[3] = lwip_htonl((0xfeul << 24) | 01190 ((u32_t)(netif->hwaddr[3]) << 16) | 01191 ((u32_t)(netif->hwaddr[4]) << 8) | 01192 (netif->hwaddr[5])); 01193 } else { 01194 /* Use hwaddr directly as interface ID. */ 01195 ip_2_ip6(&netif->ip6_addr[0])->addr[2] = 0; 01196 ip_2_ip6(&netif->ip6_addr[0])->addr[3] = 0; 01197 01198 addr_index = 3; 01199 for (i = 0; (i < 8) && (i < netif->hwaddr_len); i++) { 01200 if (i == 4) { 01201 addr_index--; 01202 } 01203 ip_2_ip6(&netif->ip6_addr[0])->addr[addr_index] |= ((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03)); 01204 } 01205 } 01206 01207 /* Set address state. */ 01208 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS 01209 /* Will perform duplicate address detection (DAD). */ 01210 netif_ip6_addr_set_state(netif, 0, IP6_ADDR_TENTATIVE); 01211 #else 01212 /* Consider address valid. */ 01213 netif_ip6_addr_set_state(netif, 0, IP6_ADDR_PREFERRED); 01214 #endif /* LWIP_IPV6_AUTOCONFIG */ 01215 } 01216 01217 /** 01218 * @ingroup netif_ip6 01219 * This function allows for the easy addition of a new IPv6 address to an interface. 01220 * It takes care of finding an empty slot and then sets the address tentative 01221 * (to make sure that all the subsequent processing happens). 01222 * 01223 * @param netif netif to add the address on 01224 * @param ip6addr address to add 01225 * @param chosen_idx if != NULL, the chosen IPv6 address index will be stored here 01226 */ 01227 err_t 01228 netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx) 01229 { 01230 s8_t i; 01231 01232 i = netif_get_ip6_addr_match(netif, ip6addr); 01233 if (i >= 0) { 01234 /* Address already added */ 01235 if (chosen_idx != NULL) { 01236 *chosen_idx = i; 01237 } 01238 return ERR_OK; 01239 } 01240 01241 /* Find a free slot -- musn't be the first one (reserved for link local) */ 01242 for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 01243 if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) { 01244 ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr); 01245 netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE); 01246 if (chosen_idx != NULL) { 01247 *chosen_idx = i; 01248 } 01249 return ERR_OK; 01250 } 01251 } 01252 01253 if (chosen_idx != NULL) { 01254 *chosen_idx = -1; 01255 } 01256 return ERR_VAL; 01257 } 01258 01259 /** Dummy IPv6 output function for netifs not supporting IPv6 01260 */ 01261 static err_t 01262 netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr) 01263 { 01264 LWIP_UNUSED_ARG(netif); 01265 LWIP_UNUSED_ARG(p); 01266 LWIP_UNUSED_ARG(ipaddr); 01267 01268 return ERR_IF; 01269 } 01270 #endif /* LWIP_IPV6 */
Generated on Fri Jul 22 2022 04:53:52 by
 1.7.2
 1.7.2 
    