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