Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510
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 11:02:42 by
