Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
lwip_netif.c
Go to the documentation of this file.
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 Sun Jul 17 2022 08:25:24 by 1.7.2