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: TYBLE16_simple_data_logger TYBLE16_MP3_Air
lwip_netif.c
00001 /** 00002 * @file 00003 * lwIP network interface abstraction 00004 * 00005 * @defgroup netif Network interface (NETIF) 00006 * @ingroup callbackstyle_api 00007 * 00008 * @defgroup netif_ip4 IPv4 address handling 00009 * @ingroup netif 00010 * 00011 * @defgroup netif_ip6 IPv6 address handling 00012 * @ingroup netif 00013 * 00014 * @defgroup netif_cd Client data handling 00015 * Store data (void*) on a netif for application usage. 00016 * @see @ref LWIP_NUM_NETIF_CLIENT_DATA 00017 * @ingroup netif 00018 */ 00019 00020 /* 00021 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 00022 * All rights reserved. 00023 * 00024 * Redistribution and use in source and binary forms, with or without modification, 00025 * are permitted provided that the following conditions are met: 00026 * 00027 * 1. Redistributions of source code must retain the above copyright notice, 00028 * this list of conditions and the following disclaimer. 00029 * 2. Redistributions in binary form must reproduce the above copyright notice, 00030 * this list of conditions and the following disclaimer in the documentation 00031 * and/or other materials provided with the distribution. 00032 * 3. The name of the author may not be used to endorse or promote products 00033 * derived from this software without specific prior written permission. 00034 * 00035 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00036 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00037 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00038 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00039 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00040 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00041 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00042 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00043 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00044 * OF SUCH DAMAGE. 00045 * 00046 * This file is part of the lwIP TCP/IP stack. 00047 * 00048 * Author: Adam Dunkels <adam@sics.se> 00049 */ 00050 00051 #include "lwip/opt.h" 00052 00053 #include <string.h> /* memset */ 00054 #include <stdlib.h> /* atoi */ 00055 00056 #include "lwip/def.h" 00057 #include "lwip/ip_addr.h" 00058 #include "lwip/ip6_addr.h" 00059 #include "lwip/netif.h" 00060 #include "lwip/priv/tcp_priv.h" 00061 #include "lwip/udp.h" 00062 #include "lwip/priv/raw_priv.h" 00063 #include "lwip/snmp.h" 00064 #include "lwip/igmp.h" 00065 #include "lwip/etharp.h" 00066 #include "lwip/stats.h" 00067 #include "lwip/sys.h" 00068 #include "lwip/ip.h" 00069 #if ENABLE_LOOPBACK 00070 #if LWIP_NETIF_LOOPBACK_MULTITHREADING 00071 #include "lwip/tcpip.h" 00072 #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 00073 #endif /* ENABLE_LOOPBACK */ 00074 00075 #include "netif/ethernet.h" 00076 00077 #if LWIP_AUTOIP 00078 #include "lwip/autoip.h" 00079 #endif /* LWIP_AUTOIP */ 00080 #if LWIP_DHCP 00081 #include "lwip/dhcp.h" 00082 #endif /* LWIP_DHCP */ 00083 #if LWIP_IPV6_DHCP6 00084 #include "lwip/dhcp6.h" 00085 #endif /* LWIP_IPV6_DHCP6 */ 00086 #if LWIP_IPV6_MLD 00087 #include "lwip/mld6.h" 00088 #endif /* LWIP_IPV6_MLD */ 00089 #if LWIP_IPV6 00090 #include "lwip/nd6.h" 00091 #endif 00092 00093 #if LWIP_NETIF_STATUS_CALLBACK 00094 #define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0) 00095 #else 00096 #define NETIF_STATUS_CALLBACK(n) 00097 #endif /* LWIP_NETIF_STATUS_CALLBACK */ 00098 00099 #if LWIP_NETIF_LINK_CALLBACK 00100 #define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0) 00101 #else 00102 #define NETIF_LINK_CALLBACK(n) 00103 #endif /* LWIP_NETIF_LINK_CALLBACK */ 00104 00105 #if LWIP_NETIF_EXT_STATUS_CALLBACK 00106 static netif_ext_callback_t *ext_callback; 00107 #endif 00108 00109 #if !LWIP_SINGLE_NETIF 00110 struct netif *netif_list; 00111 #endif /* !LWIP_SINGLE_NETIF */ 00112 struct netif *netif_default; 00113 00114 #define netif_index_to_num(index) ((index) - 1) 00115 static u8_t netif_num; 00116 static char netif_name [INTERFACE_NAME_MAX_SIZE]; 00117 00118 #if LWIP_NUM_NETIF_CLIENT_DATA > 0 00119 static u8_t netif_client_id; 00120 #endif 00121 00122 #define NETIF_REPORT_TYPE_IPV4 0x01 00123 #define NETIF_REPORT_TYPE_IPV6 0x02 00124 static void netif_issue_reports(struct netif *netif, u8_t report_type); 00125 00126 #if LWIP_IPV6 00127 static err_t netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr); 00128 #endif /* LWIP_IPV6 */ 00129 #if LWIP_IPV4 00130 static err_t netif_null_output_ip4(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr); 00131 #endif /* LWIP_IPV4 */ 00132 00133 #if LWIP_HAVE_LOOPIF 00134 #if LWIP_IPV4 00135 static err_t netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr); 00136 #endif 00137 #if LWIP_IPV6 00138 static err_t netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr); 00139 #endif 00140 00141 00142 static struct netif loop_netif; 00143 00144 /** 00145 * Initialize a lwip network interface structure for a loopback interface 00146 * 00147 * @param netif the lwip network interface structure for this loopif 00148 * @return ERR_OK if the loopif is initialized 00149 * ERR_MEM if private data couldn't be allocated 00150 */ 00151 static err_t 00152 netif_loopif_init(struct netif *netif) 00153 { 00154 LWIP_ASSERT("netif_loopif_init: invalid netif", netif != NULL); 00155 00156 /* initialize the snmp variables and counters inside the struct netif 00157 * ifSpeed: no assumption can be made! 00158 */ 00159 MIB2_INIT_NETIF(netif, snmp_ifType_softwareLoopback, 0); 00160 00161 netif->name[0] = 'l'; 00162 netif->name[1] = 'o'; 00163 #if LWIP_IPV4 00164 netif->output = netif_loop_output_ipv4; 00165 #endif 00166 #if LWIP_IPV6 00167 netif->output_ip6 = netif_loop_output_ipv6; 00168 #endif 00169 #if LWIP_LOOPIF_MULTICAST 00170 netif_set_flags(netif, NETIF_FLAG_IGMP); 00171 #endif 00172 NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_DISABLE_ALL); 00173 return ERR_OK; 00174 } 00175 #endif /* LWIP_HAVE_LOOPIF */ 00176 00177 void 00178 netif_init(void) 00179 { 00180 #if LWIP_HAVE_LOOPIF 00181 #if LWIP_IPV4 00182 #define LOOPIF_ADDRINIT &loop_ipaddr, &loop_netmask, &loop_gw, 00183 ip4_addr_t loop_ipaddr, loop_netmask, loop_gw; 00184 IP4_ADDR(&loop_gw, 127, 0, 0, 1); 00185 IP4_ADDR(&loop_ipaddr, 127, 0, 0, 1); 00186 IP4_ADDR(&loop_netmask, 255, 0, 0, 0); 00187 #else /* LWIP_IPV4 */ 00188 #define LOOPIF_ADDRINIT 00189 #endif /* LWIP_IPV4 */ 00190 00191 #if NO_SYS 00192 netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, ip_input); 00193 #else /* NO_SYS */ 00194 netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, tcpip_input); 00195 #endif /* NO_SYS */ 00196 00197 #if LWIP_IPV6 00198 IP_ADDR6_HOST(loop_netif.ip6_addr, 0, 0, 0, 0x00000001UL); 00199 loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID; 00200 #endif /* LWIP_IPV6 */ 00201 00202 netif_set_link_up(&loop_netif); 00203 netif_set_up(&loop_netif); 00204 00205 #endif /* LWIP_HAVE_LOOPIF */ 00206 } 00207 00208 /** 00209 * @ingroup lwip_nosys 00210 * Forwards a received packet for input processing with 00211 * ethernet_input() or ip_input() depending on netif flags. 00212 * Don't call directly, pass to netif_add() and call 00213 * netif->input(). 00214 * Only works if the netif driver correctly sets 00215 * NETIF_FLAG_ETHARP and/or NETIF_FLAG_ETHERNET flag! 00216 */ 00217 err_t 00218 netif_input(struct pbuf *p, struct netif *inp) 00219 { 00220 LWIP_ASSERT_CORE_LOCKED(); 00221 00222 LWIP_ASSERT("netif_input: invalid pbuf", p != NULL); 00223 LWIP_ASSERT("netif_input: invalid netif", inp != NULL); 00224 00225 #if LWIP_ETHERNET 00226 if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { 00227 return ethernet_input(p, inp); 00228 } else 00229 #endif /* LWIP_ETHERNET */ 00230 return ip_input(p, inp); 00231 } 00232 00233 /** 00234 * @ingroup netif 00235 * Add a network interface to the list of lwIP netifs. 00236 * 00237 * Same as @ref netif_add but without IPv4 addresses 00238 */ 00239 struct netif * 00240 netif_add_noaddr(struct netif *netif, void *state, netif_init_fn init, netif_input_fn input) 00241 { 00242 return netif_add(netif, 00243 #if LWIP_IPV4 00244 NULL, NULL, NULL, 00245 #endif /* LWIP_IPV4*/ 00246 state, init, input); 00247 } 00248 00249 /** 00250 * @ingroup netif 00251 * Add a network interface to the list of lwIP netifs. 00252 * 00253 * @param netif a pre-allocated netif structure 00254 * @param ipaddr IP address for the new netif 00255 * @param netmask network mask for the new netif 00256 * @param gw default gateway IP address for the new netif 00257 * @param state opaque data passed to the new netif 00258 * @param init callback function that initializes the interface 00259 * @param input callback function that is called to pass 00260 * ingress packets up in the protocol layer stack.\n 00261 * It is recommended to use a function that passes the input directly 00262 * to the stack (netif_input(), NO_SYS=1 mode) or via sending a 00263 * message to TCPIP thread (tcpip_input(), NO_SYS=0 mode).\n 00264 * These functions use netif flags NETIF_FLAG_ETHARP and NETIF_FLAG_ETHERNET 00265 * to decide whether to forward to ethernet_input() or ip_input(). 00266 * In other words, the functions only work when the netif 00267 * driver is implemented correctly!\n 00268 * Most members of struct netif should be be initialized by the 00269 * netif init function = netif driver (init parameter of this function).\n 00270 * IPv6: Don't forget to call netif_create_ip6_linklocal_address() after 00271 * setting the MAC address in struct netif.hwaddr 00272 * (IPv6 requires a link-local address). 00273 * 00274 * @return netif, or NULL if failed. 00275 */ 00276 struct netif * 00277 netif_add(struct netif *netif, 00278 #if LWIP_IPV4 00279 const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, 00280 #endif /* LWIP_IPV4 */ 00281 void *state, netif_init_fn init, netif_input_fn input) 00282 { 00283 #if LWIP_IPV6 00284 s8_t i; 00285 #endif 00286 00287 LWIP_ASSERT_CORE_LOCKED(); 00288 00289 #if LWIP_SINGLE_NETIF 00290 if (netif_default != NULL) { 00291 LWIP_ASSERT("single netif already set", 0); 00292 return NULL; 00293 } 00294 #endif 00295 00296 LWIP_ERROR("netif_add: invalid netif", netif != NULL, return NULL); 00297 LWIP_ERROR("netif_add: No init function given", init != NULL, return NULL); 00298 00299 #if LWIP_IPV4 00300 if (ipaddr == NULL) { 00301 ipaddr = ip_2_ip4(IP4_ADDR_ANY); 00302 } 00303 if (netmask == NULL) { 00304 netmask = ip_2_ip4(IP4_ADDR_ANY); 00305 } 00306 if (gw == NULL) { 00307 gw = ip_2_ip4(IP4_ADDR_ANY); 00308 } 00309 00310 /* reset new interface configuration state */ 00311 ip_addr_set_zero_ip4(&netif->ip_addr); 00312 ip_addr_set_zero_ip4(&netif->netmask); 00313 ip_addr_set_zero_ip4(&netif->gw); 00314 netif->output = netif_null_output_ip4; 00315 #endif /* LWIP_IPV4 */ 00316 #if LWIP_IPV6 00317 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00318 ip_addr_set_zero_ip6(&netif->ip6_addr[i]); 00319 netif->ip6_addr_state[i] = IP6_ADDR_INVALID; 00320 #if LWIP_IPV6_ADDRESS_LIFETIMES 00321 netif->ip6_addr_valid_life[i] = IP6_ADDR_LIFE_STATIC; 00322 netif->ip6_addr_pref_life[i] = IP6_ADDR_LIFE_STATIC; 00323 #endif /* LWIP_IPV6_ADDRESS_LIFETIMES */ 00324 } 00325 netif->output_ip6 = netif_null_output_ip6; 00326 #endif /* LWIP_IPV6 */ 00327 NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL); 00328 netif->mtu = 0; 00329 netif->flags = 0; 00330 #ifdef netif_get_client_data 00331 memset(netif->client_data, 0, sizeof(netif->client_data)); 00332 #endif /* LWIP_NUM_NETIF_CLIENT_DATA */ 00333 #if LWIP_IPV6 00334 #if LWIP_IPV6_AUTOCONFIG 00335 /* IPv6 address autoconfiguration not enabled by default */ 00336 netif->ip6_autoconfig_enabled = 0; 00337 #endif /* LWIP_IPV6_AUTOCONFIG */ 00338 nd6_restart_netif(netif); 00339 #endif /* LWIP_IPV6 */ 00340 #if LWIP_NETIF_STATUS_CALLBACK 00341 netif->status_callback = NULL; 00342 #endif /* LWIP_NETIF_STATUS_CALLBACK */ 00343 #if LWIP_NETIF_LINK_CALLBACK 00344 netif->link_callback = NULL; 00345 #endif /* LWIP_NETIF_LINK_CALLBACK */ 00346 #if LWIP_IGMP 00347 netif->igmp_mac_filter = NULL; 00348 #endif /* LWIP_IGMP */ 00349 #if LWIP_IPV6 && LWIP_IPV6_MLD 00350 netif->mld_mac_filter = NULL; 00351 #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ 00352 #if ENABLE_LOOPBACK 00353 netif->loop_first = NULL; 00354 netif->loop_last = NULL; 00355 #endif /* ENABLE_LOOPBACK */ 00356 00357 /* remember netif specific state information data */ 00358 netif->state = state; 00359 netif->num = netif_num; 00360 netif->input = input; 00361 00362 NETIF_RESET_HINTS(netif); 00363 #if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS 00364 netif->loop_cnt_current = 0; 00365 #endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */ 00366 00367 #if LWIP_IPV4 00368 netif_set_addr(netif, ipaddr, netmask, gw); 00369 #endif /* LWIP_IPV4 */ 00370 00371 /* call user specified initialization function for netif */ 00372 if (init(netif) != ERR_OK) { 00373 return NULL; 00374 } 00375 #if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES 00376 /* Initialize the MTU for IPv6 to the one set by the netif driver. 00377 This can be updated later by RA. */ 00378 netif->mtu6 = netif->mtu; 00379 #endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */ 00380 00381 #if !LWIP_SINGLE_NETIF 00382 /* Assign a unique netif number in the range [0..254], so that (num+1) can 00383 serve as an interface index that fits in a u8_t. 00384 We assume that the new netif has not yet been added to the list here. 00385 This algorithm is O(n^2), but that should be OK for lwIP. 00386 */ 00387 { 00388 struct netif *netif2; 00389 int num_netifs; 00390 do { 00391 if (netif->num == 255) { 00392 netif->num = 0; 00393 } 00394 num_netifs = 0; 00395 for (netif2 = netif_list; netif2 != NULL; netif2 = netif2->next) { 00396 LWIP_ASSERT("netif already added", netif2 != netif); 00397 num_netifs++; 00398 LWIP_ASSERT("too many netifs, max. supported number is 255", num_netifs <= 255); 00399 if (netif2->num == netif->num) { 00400 netif->num++; 00401 break; 00402 } 00403 } 00404 } while (netif2 != NULL); 00405 } 00406 if (netif->num == 254) { 00407 netif_num = 0; 00408 } else { 00409 netif_num = (u8_t)(netif->num + 1); 00410 } 00411 00412 /* add this netif to the list */ 00413 netif->next = netif_list; 00414 netif_list = netif; 00415 #endif /* "LWIP_SINGLE_NETIF */ 00416 mib2_netif_added(netif); 00417 00418 #if LWIP_IGMP 00419 /* start IGMP processing */ 00420 if (netif->flags & NETIF_FLAG_IGMP) { 00421 igmp_start(netif); 00422 } 00423 #endif /* LWIP_IGMP */ 00424 00425 LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP", 00426 netif->name[0], netif->name[1])); 00427 #if LWIP_IPV4 00428 LWIP_DEBUGF(NETIF_DEBUG, (" addr ")); 00429 ip4_addr_debug_print(NETIF_DEBUG, ipaddr); 00430 LWIP_DEBUGF(NETIF_DEBUG, (" netmask ")); 00431 ip4_addr_debug_print(NETIF_DEBUG, netmask); 00432 LWIP_DEBUGF(NETIF_DEBUG, (" gw ")); 00433 ip4_addr_debug_print(NETIF_DEBUG, gw); 00434 #endif /* LWIP_IPV4 */ 00435 LWIP_DEBUGF(NETIF_DEBUG, ("\n")); 00436 00437 netif_invoke_ext_callback(netif, LWIP_NSC_NETIF_ADDED, NULL); 00438 00439 return netif; 00440 } 00441 00442 static void 00443 netif_do_ip_addr_changed(const ip_addr_t *old_addr, const ip_addr_t *new_addr) 00444 { 00445 #if LWIP_TCP 00446 tcp_netif_ip_addr_changed(old_addr, new_addr); 00447 #endif /* LWIP_TCP */ 00448 #if LWIP_UDP 00449 udp_netif_ip_addr_changed(old_addr, new_addr); 00450 #endif /* LWIP_UDP */ 00451 #if LWIP_RAW 00452 raw_netif_ip_addr_changed(old_addr, new_addr); 00453 #endif /* LWIP_RAW */ 00454 } 00455 00456 #if LWIP_IPV4 00457 static int 00458 netif_do_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr, ip_addr_t *old_addr) 00459 { 00460 LWIP_ASSERT("invalid pointer", ipaddr != NULL); 00461 LWIP_ASSERT("invalid pointer", old_addr != NULL); 00462 00463 /* address is actually being changed? */ 00464 if (ip4_addr_cmp(ipaddr, netif_ip4_addr(netif)) == 0) { 00465 ip_addr_t new_addr; 00466 *ip_2_ip4(&new_addr) = *ipaddr; 00467 IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_V4); 00468 00469 ip_addr_copy(*old_addr, *netif_ip_addr4(netif)); 00470 00471 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); 00472 netif_do_ip_addr_changed(old_addr, &new_addr); 00473 00474 mib2_remove_ip4(netif); 00475 mib2_remove_route_ip4(0, netif); 00476 /* set new IP address to netif */ 00477 ip4_addr_set(ip_2_ip4(&netif->ip_addr), ipaddr); 00478 IP_SET_TYPE_VAL(netif->ip_addr, IPADDR_TYPE_V4); 00479 mib2_add_ip4(netif); 00480 mib2_add_route_ip4(0, netif); 00481 00482 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4); 00483 00484 NETIF_STATUS_CALLBACK(netif); 00485 return 1; /* address changed */ 00486 } 00487 return 0; /* address unchanged */ 00488 } 00489 00490 /** 00491 * @ingroup netif_ip4 00492 * Change the IP address of a network interface 00493 * 00494 * @param netif the network interface to change 00495 * @param ipaddr the new IP address 00496 * 00497 * @note call netif_set_addr() if you also want to change netmask and 00498 * default gateway 00499 */ 00500 void 00501 netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr) 00502 { 00503 ip_addr_t old_addr; 00504 00505 LWIP_ERROR("netif_set_ipaddr: invalid netif", netif != NULL, return); 00506 00507 /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ 00508 if (ipaddr == NULL) { 00509 ipaddr = IP4_ADDR_ANY4; 00510 } 00511 00512 LWIP_ASSERT_CORE_LOCKED(); 00513 00514 if (netif_do_set_ipaddr(netif, ipaddr, &old_addr)) { 00515 #if LWIP_NETIF_EXT_STATUS_CALLBACK 00516 netif_ext_callback_args_t args; 00517 args.ipv4_changed.old_address = &old_addr; 00518 netif_invoke_ext_callback(netif, LWIP_NSC_IPV4_ADDRESS_CHANGED, &args); 00519 #endif 00520 } 00521 } 00522 00523 static int 00524 netif_do_set_netmask(struct netif *netif, const ip4_addr_t *netmask, ip_addr_t *old_nm) 00525 { 00526 /* address is actually being changed? */ 00527 if (ip4_addr_cmp(netmask, netif_ip4_netmask(netif)) == 0) { 00528 #if LWIP_NETIF_EXT_STATUS_CALLBACK 00529 LWIP_ASSERT("invalid pointer", old_nm != NULL); 00530 ip_addr_copy(*old_nm, *netif_ip_netmask4(netif)); 00531 #else 00532 LWIP_UNUSED_ARG(old_nm); 00533 #endif 00534 mib2_remove_route_ip4(0, netif); 00535 /* set new netmask to netif */ 00536 ip4_addr_set(ip_2_ip4(&netif->netmask), netmask); 00537 IP_SET_TYPE_VAL(netif->netmask, IPADDR_TYPE_V4); 00538 mib2_add_route_ip4(0, netif); 00539 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", 00540 netif->name[0], netif->name[1], 00541 ip4_addr1_16(netif_ip4_netmask(netif)), 00542 ip4_addr2_16(netif_ip4_netmask(netif)), 00543 ip4_addr3_16(netif_ip4_netmask(netif)), 00544 ip4_addr4_16(netif_ip4_netmask(netif)))); 00545 return 1; /* netmask changed */ 00546 } 00547 return 0; /* netmask unchanged */ 00548 } 00549 00550 /** 00551 * @ingroup netif_ip4 00552 * Change the netmask of a network interface 00553 * 00554 * @param netif the network interface to change 00555 * @param netmask the new netmask 00556 * 00557 * @note call netif_set_addr() if you also want to change ip address and 00558 * default gateway 00559 */ 00560 void 00561 netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask) 00562 { 00563 #if LWIP_NETIF_EXT_STATUS_CALLBACK 00564 ip_addr_t old_nm_val; 00565 ip_addr_t *old_nm = &old_nm_val; 00566 #else 00567 ip_addr_t *old_nm = NULL; 00568 #endif 00569 LWIP_ASSERT_CORE_LOCKED(); 00570 00571 LWIP_ERROR("netif_set_netmask: invalid netif", netif != NULL, return); 00572 00573 /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ 00574 if (netmask == NULL) { 00575 netmask = IP4_ADDR_ANY4; 00576 } 00577 00578 if (netif_do_set_netmask(netif, netmask, old_nm)) { 00579 #if LWIP_NETIF_EXT_STATUS_CALLBACK 00580 netif_ext_callback_args_t args; 00581 args.ipv4_changed.old_netmask = old_nm; 00582 netif_invoke_ext_callback(netif, LWIP_NSC_IPV4_NETMASK_CHANGED, &args); 00583 #endif 00584 } 00585 } 00586 00587 static int 00588 netif_do_set_gw(struct netif *netif, const ip4_addr_t *gw, ip_addr_t *old_gw) 00589 { 00590 /* address is actually being changed? */ 00591 if (ip4_addr_cmp(gw, netif_ip4_gw(netif)) == 0) { 00592 #if LWIP_NETIF_EXT_STATUS_CALLBACK 00593 LWIP_ASSERT("invalid pointer", old_gw != NULL); 00594 ip_addr_copy(*old_gw, *netif_ip_gw4(netif)); 00595 #else 00596 LWIP_UNUSED_ARG(old_gw); 00597 #endif 00598 00599 ip4_addr_set(ip_2_ip4(&netif->gw), gw); 00600 IP_SET_TYPE_VAL(netif->gw, IPADDR_TYPE_V4); 00601 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", 00602 netif->name[0], netif->name[1], 00603 ip4_addr1_16(netif_ip4_gw(netif)), 00604 ip4_addr2_16(netif_ip4_gw(netif)), 00605 ip4_addr3_16(netif_ip4_gw(netif)), 00606 ip4_addr4_16(netif_ip4_gw(netif)))); 00607 return 1; /* gateway changed */ 00608 } 00609 return 0; /* gateway unchanged */ 00610 } 00611 00612 /** 00613 * @ingroup netif_ip4 00614 * Change the default gateway for a network interface 00615 * 00616 * @param netif the network interface to change 00617 * @param gw the new default gateway 00618 * 00619 * @note call netif_set_addr() if you also want to change ip address and netmask 00620 */ 00621 void 00622 netif_set_gw(struct netif *netif, const ip4_addr_t *gw) 00623 { 00624 #if LWIP_NETIF_EXT_STATUS_CALLBACK 00625 ip_addr_t old_gw_val; 00626 ip_addr_t *old_gw = &old_gw_val; 00627 #else 00628 ip_addr_t *old_gw = NULL; 00629 #endif 00630 LWIP_ASSERT_CORE_LOCKED(); 00631 00632 LWIP_ERROR("netif_set_gw: invalid netif", netif != NULL, return); 00633 00634 /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ 00635 if (gw == NULL) { 00636 gw = IP4_ADDR_ANY4; 00637 } 00638 00639 if (netif_do_set_gw(netif, gw, old_gw)) { 00640 #if LWIP_NETIF_EXT_STATUS_CALLBACK 00641 netif_ext_callback_args_t args; 00642 args.ipv4_changed.old_gw = old_gw; 00643 netif_invoke_ext_callback(netif, LWIP_NSC_IPV4_GATEWAY_CHANGED, &args); 00644 #endif 00645 } 00646 } 00647 00648 /** 00649 * @ingroup netif_ip4 00650 * Change IP address configuration for a network interface (including netmask 00651 * and default gateway). 00652 * 00653 * @param netif the network interface to change 00654 * @param ipaddr the new IP address 00655 * @param netmask the new netmask 00656 * @param gw the new default gateway 00657 */ 00658 void 00659 netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, 00660 const ip4_addr_t *gw) 00661 { 00662 #if LWIP_NETIF_EXT_STATUS_CALLBACK 00663 netif_nsc_reason_t change_reason = LWIP_NSC_NONE; 00664 netif_ext_callback_args_t cb_args; 00665 ip_addr_t old_nm_val; 00666 ip_addr_t old_gw_val; 00667 ip_addr_t *old_nm = &old_nm_val; 00668 ip_addr_t *old_gw = &old_gw_val; 00669 #else 00670 ip_addr_t *old_nm = NULL; 00671 ip_addr_t *old_gw = NULL; 00672 #endif 00673 ip_addr_t old_addr; 00674 int remove; 00675 00676 LWIP_ASSERT_CORE_LOCKED(); 00677 00678 /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ 00679 if (ipaddr == NULL) { 00680 ipaddr = IP4_ADDR_ANY4; 00681 } 00682 if (netmask == NULL) { 00683 netmask = IP4_ADDR_ANY4; 00684 } 00685 if (gw == NULL) { 00686 gw = IP4_ADDR_ANY4; 00687 } 00688 00689 remove = ip4_addr_isany(ipaddr); 00690 if (remove) { 00691 /* when removing an address, we have to remove it *before* changing netmask/gw 00692 to ensure that tcp RST segment can be sent correctly */ 00693 if (netif_do_set_ipaddr(netif, ipaddr, &old_addr)) { 00694 #if LWIP_NETIF_EXT_STATUS_CALLBACK 00695 change_reason |= LWIP_NSC_IPV4_ADDRESS_CHANGED; 00696 cb_args.ipv4_changed.old_address = &old_addr; 00697 #endif 00698 } 00699 } 00700 if (netif_do_set_netmask(netif, netmask, old_nm)) { 00701 #if LWIP_NETIF_EXT_STATUS_CALLBACK 00702 change_reason |= LWIP_NSC_IPV4_NETMASK_CHANGED; 00703 cb_args.ipv4_changed.old_netmask = old_nm; 00704 #endif 00705 } 00706 if (netif_do_set_gw(netif, gw, old_gw)) { 00707 #if LWIP_NETIF_EXT_STATUS_CALLBACK 00708 change_reason |= LWIP_NSC_IPV4_GATEWAY_CHANGED; 00709 cb_args.ipv4_changed.old_gw = old_gw; 00710 #endif 00711 } 00712 if (!remove) { 00713 /* set ipaddr last to ensure netmask/gw have been set when status callback is called */ 00714 if (netif_do_set_ipaddr(netif, ipaddr, &old_addr)) { 00715 #if LWIP_NETIF_EXT_STATUS_CALLBACK 00716 change_reason |= LWIP_NSC_IPV4_ADDRESS_CHANGED; 00717 cb_args.ipv4_changed.old_address = &old_addr; 00718 #endif 00719 } 00720 } 00721 00722 #if LWIP_NETIF_EXT_STATUS_CALLBACK 00723 if (change_reason != LWIP_NSC_NONE) { 00724 change_reason |= LWIP_NSC_IPV4_SETTINGS_CHANGED; 00725 netif_invoke_ext_callback(netif, change_reason, &cb_args); 00726 } 00727 #endif 00728 } 00729 #endif /* LWIP_IPV4*/ 00730 00731 /** 00732 * @ingroup netif 00733 * Remove a network interface from the list of lwIP netifs. 00734 * 00735 * @param netif the network interface to remove 00736 */ 00737 void 00738 netif_remove(struct netif *netif) 00739 { 00740 #if LWIP_IPV6 00741 int i; 00742 #endif 00743 00744 LWIP_ASSERT_CORE_LOCKED(); 00745 00746 if (netif == NULL) { 00747 return; 00748 } 00749 00750 netif_invoke_ext_callback(netif, LWIP_NSC_NETIF_REMOVED, NULL); 00751 00752 #if LWIP_IPV4 00753 if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { 00754 netif_do_ip_addr_changed(netif_ip_addr4(netif), NULL); 00755 } 00756 00757 #if LWIP_IGMP 00758 /* stop IGMP processing */ 00759 if (netif->flags & NETIF_FLAG_IGMP) { 00760 igmp_stop(netif); 00761 } 00762 #endif /* LWIP_IGMP */ 00763 #endif /* LWIP_IPV4*/ 00764 00765 #if LWIP_IPV6 00766 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00767 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { 00768 netif_do_ip_addr_changed(netif_ip_addr6(netif, i), NULL); 00769 } 00770 } 00771 #if LWIP_IPV6_MLD 00772 /* stop MLD processing */ 00773 mld6_stop(netif); 00774 #endif /* LWIP_IPV6_MLD */ 00775 #endif /* LWIP_IPV6 */ 00776 if (netif_is_up(netif)) { 00777 /* set netif down before removing (call callback function) */ 00778 netif_set_down(netif); 00779 } 00780 00781 mib2_remove_ip4(netif); 00782 00783 /* this netif is default? */ 00784 if (netif_default == netif) { 00785 /* reset default netif */ 00786 netif_set_default(NULL); 00787 } 00788 #if !LWIP_SINGLE_NETIF 00789 /* is it the first netif? */ 00790 if (netif_list == netif) { 00791 netif_list = netif->next; 00792 } else { 00793 /* look for netif further down the list */ 00794 struct netif *tmp_netif; 00795 NETIF_FOREACH(tmp_netif) { 00796 if (tmp_netif->next == netif) { 00797 tmp_netif->next = netif->next; 00798 break; 00799 } 00800 } 00801 if (tmp_netif == NULL) { 00802 return; /* netif is not on the list */ 00803 } 00804 } 00805 #endif /* !LWIP_SINGLE_NETIF */ 00806 mib2_netif_removed(netif); 00807 #if LWIP_NETIF_REMOVE_CALLBACK 00808 if (netif->remove_callback) { 00809 netif->remove_callback(netif); 00810 } 00811 #endif /* LWIP_NETIF_REMOVE_CALLBACK */ 00812 LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); 00813 } 00814 00815 /** 00816 * @ingroup netif 00817 * Set a network interface as the default network interface 00818 * (used to output all packets for which no specific route is found) 00819 * 00820 * @param netif the default network interface 00821 */ 00822 void 00823 netif_set_default(struct netif *netif) 00824 { 00825 LWIP_ASSERT_CORE_LOCKED(); 00826 00827 if (netif == NULL) { 00828 /* remove default route */ 00829 mib2_remove_route_ip4(1, netif); 00830 } else { 00831 /* install default route */ 00832 mib2_add_route_ip4(1, netif); 00833 } 00834 netif_default = netif; 00835 LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", 00836 netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); 00837 } 00838 00839 /** 00840 * @ingroup netif 00841 * Checks if network interface is the default network interface 00842 * @param netif the default network interface 00843 * @return true if netif is set to default one 00844 * otherwise return false 00845 */ 00846 bool 00847 netif_check_default(struct netif *netif) 00848 { 00849 if (netif == NULL) { 00850 return false; 00851 } 00852 if (netif_default == netif) { 00853 return true; 00854 } else { 00855 return false; 00856 } 00857 } 00858 00859 /** 00860 * @ingroup netif 00861 * Bring an interface up, available for processing 00862 * traffic. 00863 */ 00864 void 00865 netif_set_up(struct netif *netif) 00866 { 00867 LWIP_ASSERT_CORE_LOCKED(); 00868 00869 LWIP_ERROR("netif_set_up: invalid netif", netif != NULL, return); 00870 00871 if (!(netif->flags & NETIF_FLAG_UP)) { 00872 netif_set_flags(netif, NETIF_FLAG_UP); 00873 00874 MIB2_COPY_SYSUPTIME_TO(&netif->ts); 00875 00876 NETIF_STATUS_CALLBACK(netif); 00877 00878 #if LWIP_NETIF_EXT_STATUS_CALLBACK 00879 { 00880 netif_ext_callback_args_t args; 00881 args.status_changed.state = 1; 00882 netif_invoke_ext_callback(netif, LWIP_NSC_STATUS_CHANGED, &args); 00883 } 00884 #endif 00885 00886 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4 | NETIF_REPORT_TYPE_IPV6); 00887 #if LWIP_IPV6 00888 nd6_restart_netif(netif); 00889 #endif /* LWIP_IPV6 */ 00890 } 00891 } 00892 00893 /** Send ARP/IGMP/MLD/RS events, e.g. on link-up/netif-up or addr-change 00894 */ 00895 static void 00896 netif_issue_reports(struct netif *netif, u8_t report_type) 00897 { 00898 LWIP_ASSERT("netif_issue_reports: invalid netif", netif != NULL); 00899 00900 /* Only send reports when both link and admin states are up */ 00901 if (!(netif->flags & NETIF_FLAG_LINK_UP) || 00902 !(netif->flags & NETIF_FLAG_UP)) { 00903 return; 00904 } 00905 00906 #if LWIP_IPV4 00907 if ((report_type & NETIF_REPORT_TYPE_IPV4) && 00908 !ip4_addr_isany_val(*netif_ip4_addr(netif))) { 00909 #if LWIP_ARP 00910 /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ 00911 if (netif->flags & (NETIF_FLAG_ETHARP)) { 00912 etharp_gratuitous(netif); 00913 } 00914 #endif /* LWIP_ARP */ 00915 00916 #if LWIP_IGMP 00917 /* resend IGMP memberships */ 00918 if (netif->flags & NETIF_FLAG_IGMP) { 00919 igmp_report_groups(netif); 00920 } 00921 #endif /* LWIP_IGMP */ 00922 } 00923 #endif /* LWIP_IPV4 */ 00924 00925 #if LWIP_IPV6 00926 if (report_type & NETIF_REPORT_TYPE_IPV6) { 00927 #if LWIP_IPV6_MLD 00928 /* send mld memberships */ 00929 mld6_report_groups(netif); 00930 #endif /* LWIP_IPV6_MLD */ 00931 } 00932 #endif /* LWIP_IPV6 */ 00933 } 00934 00935 /** 00936 * @ingroup netif 00937 * Bring an interface down, disabling any traffic processing. 00938 */ 00939 void 00940 netif_set_down(struct netif *netif) 00941 { 00942 LWIP_ASSERT_CORE_LOCKED(); 00943 00944 LWIP_ERROR("netif_set_down: invalid netif", netif != NULL, return); 00945 00946 if (netif->flags & NETIF_FLAG_UP) { 00947 #if LWIP_NETIF_EXT_STATUS_CALLBACK 00948 { 00949 netif_ext_callback_args_t args; 00950 args.status_changed.state = 0; 00951 netif_invoke_ext_callback(netif, LWIP_NSC_STATUS_CHANGED, &args); 00952 } 00953 #endif 00954 00955 netif_clear_flags(netif, NETIF_FLAG_UP); 00956 MIB2_COPY_SYSUPTIME_TO(&netif->ts); 00957 00958 #if LWIP_IPV4 && LWIP_ARP 00959 if (netif->flags & NETIF_FLAG_ETHARP) { 00960 etharp_cleanup_netif(netif); 00961 } 00962 #endif /* LWIP_IPV4 && LWIP_ARP */ 00963 00964 #if LWIP_IPV6 00965 nd6_cleanup_netif(netif); 00966 #endif /* LWIP_IPV6 */ 00967 00968 NETIF_STATUS_CALLBACK(netif); 00969 } 00970 } 00971 00972 #if LWIP_NETIF_STATUS_CALLBACK 00973 /** 00974 * @ingroup netif 00975 * Set callback to be called when interface is brought up/down or address is changed while up 00976 */ 00977 void 00978 netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback) 00979 { 00980 LWIP_ASSERT_CORE_LOCKED(); 00981 00982 if (netif) { 00983 netif->status_callback = status_callback; 00984 } 00985 } 00986 #endif /* LWIP_NETIF_STATUS_CALLBACK */ 00987 00988 #if LWIP_NETIF_REMOVE_CALLBACK 00989 /** 00990 * @ingroup netif 00991 * Set callback to be called when the interface has been removed 00992 */ 00993 void 00994 netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback) 00995 { 00996 LWIP_ASSERT_CORE_LOCKED(); 00997 00998 if (netif) { 00999 netif->remove_callback = remove_callback; 01000 } 01001 } 01002 #endif /* LWIP_NETIF_REMOVE_CALLBACK */ 01003 01004 /** 01005 * @ingroup netif 01006 * Called by a driver when its link goes up 01007 */ 01008 void 01009 netif_set_link_up(struct netif *netif) 01010 { 01011 LWIP_ASSERT_CORE_LOCKED(); 01012 01013 LWIP_ERROR("netif_set_link_up: invalid netif", netif != NULL, return); 01014 01015 if (!(netif->flags & NETIF_FLAG_LINK_UP)) { 01016 netif_set_flags(netif, NETIF_FLAG_LINK_UP); 01017 01018 #if LWIP_DHCP 01019 dhcp_network_changed(netif); 01020 #endif /* LWIP_DHCP */ 01021 01022 #if LWIP_AUTOIP 01023 autoip_network_changed(netif); 01024 #endif /* LWIP_AUTOIP */ 01025 01026 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4 | NETIF_REPORT_TYPE_IPV6); 01027 #if LWIP_IPV6 01028 nd6_restart_netif(netif); 01029 #endif /* LWIP_IPV6 */ 01030 01031 NETIF_LINK_CALLBACK(netif); 01032 #if LWIP_NETIF_EXT_STATUS_CALLBACK 01033 { 01034 netif_ext_callback_args_t args; 01035 args.link_changed.state = 1; 01036 netif_invoke_ext_callback(netif, LWIP_NSC_LINK_CHANGED, &args); 01037 } 01038 #endif 01039 } 01040 } 01041 01042 /** 01043 * @ingroup netif 01044 * Called by a driver when its link goes down 01045 */ 01046 void 01047 netif_set_link_down(struct netif *netif) 01048 { 01049 LWIP_ASSERT_CORE_LOCKED(); 01050 01051 LWIP_ERROR("netif_set_link_down: invalid netif", netif != NULL, return); 01052 01053 if (netif->flags & NETIF_FLAG_LINK_UP) { 01054 netif_clear_flags(netif, NETIF_FLAG_LINK_UP); 01055 NETIF_LINK_CALLBACK(netif); 01056 #if LWIP_NETIF_EXT_STATUS_CALLBACK 01057 { 01058 netif_ext_callback_args_t args; 01059 args.link_changed.state = 0; 01060 netif_invoke_ext_callback(netif, LWIP_NSC_LINK_CHANGED, &args); 01061 } 01062 #endif 01063 } 01064 } 01065 01066 #if LWIP_NETIF_LINK_CALLBACK 01067 /** 01068 * @ingroup netif 01069 * Set callback to be called when link is brought up/down 01070 */ 01071 void 01072 netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback) 01073 { 01074 LWIP_ASSERT_CORE_LOCKED(); 01075 01076 if (netif) { 01077 netif->link_callback = link_callback; 01078 } 01079 } 01080 #endif /* LWIP_NETIF_LINK_CALLBACK */ 01081 01082 #if ENABLE_LOOPBACK 01083 /** 01084 * @ingroup netif 01085 * Send an IP packet to be received on the same netif (loopif-like). 01086 * The pbuf is simply copied and handed back to netif->input. 01087 * In multithreaded mode, this is done directly since netif->input must put 01088 * the packet on a queue. 01089 * In callback mode, the packet is put on an internal queue and is fed to 01090 * netif->input by netif_poll(). 01091 * 01092 * @param netif the lwip network interface structure 01093 * @param p the (IP) packet to 'send' 01094 * @return ERR_OK if the packet has been sent 01095 * ERR_MEM if the pbuf used to copy the packet couldn't be allocated 01096 */ 01097 err_t 01098 netif_loop_output(struct netif *netif, struct pbuf *p) 01099 { 01100 struct pbuf *r; 01101 err_t err; 01102 struct pbuf *last; 01103 #if LWIP_LOOPBACK_MAX_PBUFS 01104 u16_t clen = 0; 01105 #endif /* LWIP_LOOPBACK_MAX_PBUFS */ 01106 /* If we have a loopif, SNMP counters are adjusted for it, 01107 * if not they are adjusted for 'netif'. */ 01108 #if MIB2_STATS 01109 #if LWIP_HAVE_LOOPIF 01110 struct netif *stats_if = &loop_netif; 01111 #else /* LWIP_HAVE_LOOPIF */ 01112 struct netif *stats_if = netif; 01113 #endif /* LWIP_HAVE_LOOPIF */ 01114 #endif /* MIB2_STATS */ 01115 #if LWIP_NETIF_LOOPBACK_MULTITHREADING 01116 u8_t schedule_poll = 0; 01117 #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 01118 SYS_ARCH_DECL_PROTECT(lev); 01119 01120 LWIP_ASSERT("netif_loop_output: invalid netif", netif != NULL); 01121 LWIP_ASSERT("netif_loop_output: invalid pbuf", p != NULL); 01122 01123 /* Allocate a new pbuf */ 01124 r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); 01125 if (r == NULL) { 01126 LINK_STATS_INC(link.memerr); 01127 LINK_STATS_INC(link.drop); 01128 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); 01129 return ERR_MEM; 01130 } 01131 #if LWIP_LOOPBACK_MAX_PBUFS 01132 clen = pbuf_clen(r); 01133 /* check for overflow or too many pbuf on queue */ 01134 if (((netif->loop_cnt_current + clen) < netif->loop_cnt_current) || 01135 ((netif->loop_cnt_current + clen) > LWIP_MIN(LWIP_LOOPBACK_MAX_PBUFS, 0xFFFF))) { 01136 pbuf_free(r); 01137 LINK_STATS_INC(link.memerr); 01138 LINK_STATS_INC(link.drop); 01139 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); 01140 return ERR_MEM; 01141 } 01142 netif->loop_cnt_current = (u16_t)(netif->loop_cnt_current + clen); 01143 #endif /* LWIP_LOOPBACK_MAX_PBUFS */ 01144 01145 /* Copy the whole pbuf queue p into the single pbuf r */ 01146 if ((err = pbuf_copy(r, p)) != ERR_OK) { 01147 pbuf_free(r); 01148 LINK_STATS_INC(link.memerr); 01149 LINK_STATS_INC(link.drop); 01150 MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); 01151 return err; 01152 } 01153 01154 /* Put the packet on a linked list which gets emptied through calling 01155 netif_poll(). */ 01156 01157 /* let last point to the last pbuf in chain r */ 01158 for (last = r; last->next != NULL; last = last->next) { 01159 /* nothing to do here, just get to the last pbuf */ 01160 } 01161 01162 SYS_ARCH_PROTECT(lev); 01163 if (netif->loop_first != NULL) { 01164 LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); 01165 netif->loop_last->next = r; 01166 netif->loop_last = last; 01167 } else { 01168 netif->loop_first = r; 01169 netif->loop_last = last; 01170 #if LWIP_NETIF_LOOPBACK_MULTITHREADING 01171 /* No existing packets queued, schedule poll */ 01172 schedule_poll = 1; 01173 #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 01174 } 01175 SYS_ARCH_UNPROTECT(lev); 01176 01177 LINK_STATS_INC(link.xmit); 01178 MIB2_STATS_NETIF_ADD(stats_if, ifoutoctets, p->tot_len); 01179 MIB2_STATS_NETIF_INC(stats_if, ifoutucastpkts); 01180 01181 #if LWIP_NETIF_LOOPBACK_MULTITHREADING 01182 /* For multithreading environment, schedule a call to netif_poll */ 01183 if (schedule_poll) { 01184 tcpip_try_callback((tcpip_callback_fn)netif_poll, netif); 01185 } 01186 #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 01187 01188 return ERR_OK; 01189 } 01190 01191 #if LWIP_HAVE_LOOPIF 01192 #if LWIP_IPV4 01193 static err_t 01194 netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) 01195 { 01196 LWIP_UNUSED_ARG(addr); 01197 return netif_loop_output(netif, p); 01198 } 01199 #endif /* LWIP_IPV4 */ 01200 01201 #if LWIP_IPV6 01202 static err_t 01203 netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr) 01204 { 01205 LWIP_UNUSED_ARG(addr); 01206 return netif_loop_output(netif, p); 01207 } 01208 #endif /* LWIP_IPV6 */ 01209 #endif /* LWIP_HAVE_LOOPIF */ 01210 01211 01212 /** 01213 * Call netif_poll() in the main loop of your application. This is to prevent 01214 * reentering non-reentrant functions like tcp_input(). Packets passed to 01215 * netif_loop_output() are put on a list that is passed to netif->input() by 01216 * netif_poll(). 01217 */ 01218 void 01219 netif_poll(struct netif *netif) 01220 { 01221 /* If we have a loopif, SNMP counters are adjusted for it, 01222 * if not they are adjusted for 'netif'. */ 01223 #if MIB2_STATS 01224 #if LWIP_HAVE_LOOPIF 01225 struct netif *stats_if = &loop_netif; 01226 #else /* LWIP_HAVE_LOOPIF */ 01227 struct netif *stats_if = netif; 01228 #endif /* LWIP_HAVE_LOOPIF */ 01229 #endif /* MIB2_STATS */ 01230 SYS_ARCH_DECL_PROTECT(lev); 01231 01232 LWIP_ASSERT("netif_poll: invalid netif", netif != NULL); 01233 01234 /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ 01235 SYS_ARCH_PROTECT(lev); 01236 while (netif->loop_first != NULL) { 01237 struct pbuf *in, *in_end; 01238 #if LWIP_LOOPBACK_MAX_PBUFS 01239 u8_t clen = 1; 01240 #endif /* LWIP_LOOPBACK_MAX_PBUFS */ 01241 01242 in = in_end = netif->loop_first; 01243 while (in_end->len != in_end->tot_len) { 01244 LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); 01245 in_end = in_end->next; 01246 #if LWIP_LOOPBACK_MAX_PBUFS 01247 clen++; 01248 #endif /* LWIP_LOOPBACK_MAX_PBUFS */ 01249 } 01250 #if LWIP_LOOPBACK_MAX_PBUFS 01251 /* adjust the number of pbufs on queue */ 01252 LWIP_ASSERT("netif->loop_cnt_current underflow", 01253 ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); 01254 netif->loop_cnt_current = (u16_t)(netif->loop_cnt_current - clen); 01255 #endif /* LWIP_LOOPBACK_MAX_PBUFS */ 01256 01257 /* 'in_end' now points to the last pbuf from 'in' */ 01258 if (in_end == netif->loop_last) { 01259 /* this was the last pbuf in the list */ 01260 netif->loop_first = netif->loop_last = NULL; 01261 } else { 01262 /* pop the pbuf off the list */ 01263 netif->loop_first = in_end->next; 01264 LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL); 01265 } 01266 /* De-queue the pbuf from its successors on the 'loop_' list. */ 01267 in_end->next = NULL; 01268 SYS_ARCH_UNPROTECT(lev); 01269 01270 in->if_idx = netif_get_index(netif); 01271 01272 LINK_STATS_INC(link.recv); 01273 MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len); 01274 MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts); 01275 /* loopback packets are always IP packets! */ 01276 if (ip_input(in, netif) != ERR_OK) { 01277 pbuf_free(in); 01278 } 01279 SYS_ARCH_PROTECT(lev); 01280 } 01281 SYS_ARCH_UNPROTECT(lev); 01282 } 01283 01284 #if !LWIP_NETIF_LOOPBACK_MULTITHREADING 01285 /** 01286 * Calls netif_poll() for every netif on the netif_list. 01287 */ 01288 void 01289 netif_poll_all(void) 01290 { 01291 struct netif *netif; 01292 /* loop through netifs */ 01293 NETIF_FOREACH(netif) { 01294 netif_poll(netif); 01295 } 01296 } 01297 #endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ 01298 #endif /* ENABLE_LOOPBACK */ 01299 01300 #if LWIP_NUM_NETIF_CLIENT_DATA > 0 01301 /** 01302 * @ingroup netif_cd 01303 * Allocate an index to store data in client_data member of struct netif. 01304 * Returned value is an index in mentioned array. 01305 * @see LWIP_NUM_NETIF_CLIENT_DATA 01306 */ 01307 u8_t 01308 netif_alloc_client_data_id(void) 01309 { 01310 u8_t result = netif_client_id; 01311 netif_client_id++; 01312 01313 LWIP_ASSERT_CORE_LOCKED(); 01314 01315 #if LWIP_NUM_NETIF_CLIENT_DATA > 256 01316 #error LWIP_NUM_NETIF_CLIENT_DATA must be <= 256 01317 #endif 01318 LWIP_ASSERT("Increase LWIP_NUM_NETIF_CLIENT_DATA in lwipopts.h", result < LWIP_NUM_NETIF_CLIENT_DATA); 01319 return (u8_t)(result + LWIP_NETIF_CLIENT_DATA_INDEX_MAX); 01320 } 01321 #endif 01322 01323 #if LWIP_IPV6 01324 /** 01325 * @ingroup netif_ip6 01326 * Change an IPv6 address of a network interface 01327 * 01328 * @param netif the network interface to change 01329 * @param addr_idx index of the IPv6 address 01330 * @param addr6 the new IPv6 address 01331 * 01332 * @note call netif_ip6_addr_set_state() to set the address valid/temptative 01333 */ 01334 void 01335 netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6) 01336 { 01337 LWIP_ASSERT_CORE_LOCKED(); 01338 01339 LWIP_ASSERT("netif_ip6_addr_set: invalid netif", netif != NULL); 01340 LWIP_ASSERT("netif_ip6_addr_set: invalid addr6", addr6 != NULL); 01341 01342 netif_ip6_addr_set_parts(netif, addr_idx, addr6->addr[0], addr6->addr[1], 01343 addr6->addr[2], addr6->addr[3]); 01344 } 01345 01346 /* 01347 * Change an IPv6 address of a network interface (internal version taking 4 * u32_t) 01348 * 01349 * @param netif the network interface to change 01350 * @param addr_idx index of the IPv6 address 01351 * @param i0 word0 of the new IPv6 address 01352 * @param i1 word1 of the new IPv6 address 01353 * @param i2 word2 of the new IPv6 address 01354 * @param i3 word3 of the new IPv6 address 01355 */ 01356 void 01357 netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3) 01358 { 01359 ip_addr_t old_addr; 01360 ip_addr_t new_ipaddr; 01361 LWIP_ASSERT_CORE_LOCKED(); 01362 LWIP_ASSERT("netif != NULL", netif != NULL); 01363 LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); 01364 01365 ip6_addr_copy(*ip_2_ip6(&old_addr), *netif_ip6_addr(netif, addr_idx)); 01366 IP_SET_TYPE_VAL(old_addr, IPADDR_TYPE_V6); 01367 01368 /* address is actually being changed? */ 01369 if ((ip_2_ip6(&old_addr)->addr[0] != i0) || (ip_2_ip6(&old_addr)->addr[1] != i1) || 01370 (ip_2_ip6(&old_addr)->addr[2] != i2) || (ip_2_ip6(&old_addr)->addr[3] != i3)) { 01371 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set: netif address being changed\n")); 01372 01373 IP_ADDR6(&new_ipaddr, i0, i1, i2, i3); 01374 ip6_addr_assign_zone(ip_2_ip6(&new_ipaddr), IP6_UNICAST, netif); 01375 01376 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, addr_idx))) { 01377 netif_do_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); 01378 } 01379 /* @todo: remove/readd mib2 ip6 entries? */ 01380 01381 ip_addr_copy(netif->ip6_addr[addr_idx], new_ipaddr); 01382 01383 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, addr_idx))) { 01384 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); 01385 NETIF_STATUS_CALLBACK(netif); 01386 } 01387 01388 #if LWIP_NETIF_EXT_STATUS_CALLBACK 01389 { 01390 netif_ext_callback_args_t args; 01391 args.ipv6_set.addr_index = addr_idx; 01392 args.ipv6_set.old_address = &old_addr; 01393 netif_invoke_ext_callback(netif, LWIP_NSC_IPV6_SET, &args); 01394 } 01395 #endif 01396 } 01397 01398 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", 01399 addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), 01400 netif_ip6_addr_state(netif, addr_idx))); 01401 } 01402 01403 /** 01404 * @ingroup netif_ip6 01405 * Change the state of an IPv6 address of a network interface 01406 * (INVALID, TEMPTATIVE, PREFERRED, DEPRECATED, where TEMPTATIVE 01407 * includes the number of checks done, see ip6_addr.h) 01408 * 01409 * @param netif the network interface to change 01410 * @param addr_idx index of the IPv6 address 01411 * @param state the new IPv6 address state 01412 */ 01413 void 01414 netif_ip6_addr_set_state(struct netif *netif, s8_t addr_idx, u8_t state) 01415 { 01416 u8_t old_state; 01417 LWIP_ASSERT_CORE_LOCKED(); 01418 LWIP_ASSERT("netif != NULL", netif != NULL); 01419 LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); 01420 01421 old_state = netif_ip6_addr_state(netif, addr_idx); 01422 /* state is actually being changed? */ 01423 if (old_state != state) { 01424 u8_t old_valid = old_state & IP6_ADDR_VALID; 01425 u8_t new_valid = state & IP6_ADDR_VALID; 01426 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n")); 01427 01428 #if LWIP_IPV6_MLD 01429 /* Reevaluate solicited-node multicast group membership. */ 01430 if (netif->flags & NETIF_FLAG_MLD6) { 01431 nd6_adjust_mld_membership(netif, addr_idx, state); 01432 } 01433 #endif /* LWIP_IPV6_MLD */ 01434 01435 if (old_valid && !new_valid) { 01436 /* address about to be removed by setting invalid */ 01437 netif_do_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); 01438 /* @todo: remove mib2 ip6 entries? */ 01439 } 01440 netif->ip6_addr_state[addr_idx] = state; 01441 01442 if (!old_valid && new_valid) { 01443 /* address added by setting valid */ 01444 /* This is a good moment to check that the address is properly zoned. */ 01445 IP6_ADDR_ZONECHECK_NETIF(netif_ip6_addr(netif, addr_idx), netif); 01446 /* @todo: add mib2 ip6 entries? */ 01447 netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); 01448 } 01449 if ((old_state & ~IP6_ADDR_TENTATIVE_COUNT_MASK) != 01450 (state & ~IP6_ADDR_TENTATIVE_COUNT_MASK)) { 01451 /* address state has changed -> call the callback function */ 01452 NETIF_STATUS_CALLBACK(netif); 01453 } 01454 01455 #if LWIP_NETIF_EXT_STATUS_CALLBACK 01456 { 01457 netif_ext_callback_args_t args; 01458 args.ipv6_addr_state_changed.addr_index = addr_idx; 01459 args.ipv6_addr_state_changed.old_state = old_state; 01460 args.ipv6_addr_state_changed.address = netif_ip_addr6(netif, addr_idx); 01461 netif_invoke_ext_callback(netif, LWIP_NSC_IPV6_ADDR_STATE_CHANGED, &args); 01462 } 01463 #endif 01464 } 01465 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", 01466 addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), 01467 netif_ip6_addr_state(netif, addr_idx))); 01468 } 01469 01470 /** 01471 * Checks if a specific local address is present on the netif and returns its 01472 * index. Depending on its state, it may or may not be assigned to the 01473 * interface (as per RFC terminology). 01474 * 01475 * The given address may or may not be zoned (i.e., have a zone index other 01476 * than IP6_NO_ZONE). If the address is zoned, it must have the correct zone 01477 * for the given netif, or no match will be found. 01478 * 01479 * @param netif the netif to check 01480 * @param ip6addr the IPv6 address to find 01481 * @return >= 0: address found, this is its index 01482 * -1: address not found on this netif 01483 */ 01484 s8_t 01485 netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr) 01486 { 01487 s8_t i; 01488 01489 LWIP_ASSERT_CORE_LOCKED(); 01490 01491 LWIP_ASSERT("netif_get_ip6_addr_match: invalid netif", netif != NULL); 01492 LWIP_ASSERT("netif_get_ip6_addr_match: invalid ip6addr", ip6addr != NULL); 01493 01494 #if LWIP_IPV6_SCOPES 01495 if (ip6_addr_has_zone(ip6addr) && !ip6_addr_test_zone(ip6addr, netif)) { 01496 return -1; /* wrong zone, no match */ 01497 } 01498 #endif /* LWIP_IPV6_SCOPES */ 01499 01500 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 01501 if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) && 01502 ip6_addr_cmp_zoneless(netif_ip6_addr(netif, i), ip6addr)) { 01503 return i; 01504 } 01505 } 01506 return -1; 01507 } 01508 01509 /** 01510 * @ingroup netif_ip6 01511 * Create a link-local IPv6 address on a netif (stored in slot 0) 01512 * 01513 * @param netif the netif to create the address on 01514 * @param from_mac_48bit if != 0, assume hwadr is a 48-bit MAC address (std conversion) 01515 * if == 0, use hwaddr directly as interface ID 01516 */ 01517 void 01518 netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit) 01519 { 01520 u8_t i, addr_index; 01521 01522 LWIP_ASSERT_CORE_LOCKED(); 01523 01524 LWIP_ASSERT("netif_create_ip6_linklocal_address: invalid netif", netif != NULL); 01525 01526 /* Link-local prefix. */ 01527 ip_2_ip6(&netif->ip6_addr[0])->addr[0] = PP_HTONL(0xfe800000ul); 01528 ip_2_ip6(&netif->ip6_addr[0])->addr[1] = 0; 01529 01530 /* Generate interface ID. */ 01531 if (from_mac_48bit) { 01532 /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */ 01533 ip_2_ip6(&netif->ip6_addr[0])->addr[2] = lwip_htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) | 01534 ((u32_t)(netif->hwaddr[1]) << 16) | 01535 ((u32_t)(netif->hwaddr[2]) << 8) | 01536 (0xff)); 01537 ip_2_ip6(&netif->ip6_addr[0])->addr[3] = lwip_htonl((u32_t)(0xfeul << 24) | 01538 ((u32_t)(netif->hwaddr[3]) << 16) | 01539 ((u32_t)(netif->hwaddr[4]) << 8) | 01540 (netif->hwaddr[5])); 01541 } else { 01542 /* Use hwaddr directly as interface ID. */ 01543 ip_2_ip6(&netif->ip6_addr[0])->addr[2] = 0; 01544 ip_2_ip6(&netif->ip6_addr[0])->addr[3] = 0; 01545 01546 addr_index = 3; 01547 for (i = 0; (i < 8) && (i < netif->hwaddr_len); i++) { 01548 if (i == 4) { 01549 addr_index--; 01550 } 01551 ip_2_ip6(&netif->ip6_addr[0])->addr[addr_index] |= lwip_htonl(((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03))); 01552 } 01553 } 01554 01555 /* Set a link-local zone. Even though the zone is implied by the owning 01556 * netif, setting the zone anyway has two important conceptual advantages: 01557 * 1) it avoids the need for a ton of exceptions in internal code, allowing 01558 * e.g. ip6_addr_cmp() to be used on local addresses; 01559 * 2) the properly zoned address is visible externally, e.g. when any outside 01560 * code enumerates available addresses or uses one to bind a socket. 01561 * Any external code unaware of address scoping is likely to just ignore the 01562 * zone field, so this should not create any compatibility problems. */ 01563 ip6_addr_assign_zone(ip_2_ip6(&netif->ip6_addr[0]), IP6_UNICAST, netif); 01564 01565 /* Set address state. */ 01566 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS 01567 /* Will perform duplicate address detection (DAD). */ 01568 netif_ip6_addr_set_state(netif, 0, IP6_ADDR_TENTATIVE); 01569 #else 01570 /* Consider address valid. */ 01571 netif_ip6_addr_set_state(netif, 0, IP6_ADDR_PREFERRED); 01572 #endif /* LWIP_IPV6_AUTOCONFIG */ 01573 } 01574 01575 /** 01576 * @ingroup netif_ip6 01577 * This function allows for the easy addition of a new IPv6 address to an interface. 01578 * It takes care of finding an empty slot and then sets the address tentative 01579 * (to make sure that all the subsequent processing happens). 01580 * 01581 * @param netif netif to add the address on 01582 * @param ip6addr address to add 01583 * @param chosen_idx if != NULL, the chosen IPv6 address index will be stored here 01584 */ 01585 err_t 01586 netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx) 01587 { 01588 s8_t i; 01589 01590 LWIP_ASSERT_CORE_LOCKED(); 01591 01592 LWIP_ASSERT("netif_add_ip6_address: invalid netif", netif != NULL); 01593 LWIP_ASSERT("netif_add_ip6_address: invalid ip6addr", ip6addr != NULL); 01594 01595 i = netif_get_ip6_addr_match(netif, ip6addr); 01596 if (i >= 0) { 01597 /* Address already added */ 01598 if (chosen_idx != NULL) { 01599 *chosen_idx = i; 01600 } 01601 return ERR_OK; 01602 } 01603 01604 /* Find a free slot. The first one is reserved for link-local addresses. */ 01605 for (i = ip6_addr_islinklocal(ip6addr) ? 0 : 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 01606 if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) { 01607 ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr); 01608 ip6_addr_assign_zone(ip_2_ip6(&netif->ip6_addr[i]), IP6_UNICAST, netif); 01609 netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE); 01610 if (chosen_idx != NULL) { 01611 *chosen_idx = i; 01612 } 01613 return ERR_OK; 01614 } 01615 } 01616 01617 if (chosen_idx != NULL) { 01618 *chosen_idx = -1; 01619 } 01620 return ERR_VAL; 01621 } 01622 01623 /** Dummy IPv6 output function for netifs not supporting IPv6 01624 */ 01625 static err_t 01626 netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr) 01627 { 01628 LWIP_UNUSED_ARG(netif); 01629 LWIP_UNUSED_ARG(p); 01630 LWIP_UNUSED_ARG(ipaddr); 01631 01632 return ERR_IF; 01633 } 01634 #endif /* LWIP_IPV6 */ 01635 01636 #if LWIP_IPV4 01637 /** Dummy IPv4 output function for netifs not supporting IPv4 01638 */ 01639 static err_t 01640 netif_null_output_ip4(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr) 01641 { 01642 LWIP_UNUSED_ARG(netif); 01643 LWIP_UNUSED_ARG(p); 01644 LWIP_UNUSED_ARG(ipaddr); 01645 01646 return ERR_IF; 01647 } 01648 #endif /* LWIP_IPV4 */ 01649 01650 /** 01651 * @ingroup netif 01652 * Return the interface index for the netif with name 01653 * or NETIF_NO_INDEX if not found/on error 01654 * 01655 * @param name the name of the netif 01656 */ 01657 u8_t 01658 netif_name_to_index(const char *name) 01659 { 01660 struct netif *netif = netif_find(name); 01661 if (netif != NULL) { 01662 return netif_get_index(netif); 01663 } 01664 /* No name found, return invalid index */ 01665 return NETIF_NO_INDEX; 01666 } 01667 01668 /** 01669 * @ingroup netif 01670 * Return the interface name for the netif matching index 01671 * or NULL if not found/on error 01672 * 01673 * @param idx the interface index of the netif 01674 * @param name char buffer of at least NETIF_NAMESIZE bytes 01675 */ 01676 char * 01677 netif_index_to_name(u8_t idx, char *name) 01678 { 01679 struct netif *netif = netif_get_by_index(idx); 01680 01681 if (netif != NULL) { 01682 name[0] = netif->name[0]; 01683 name[1] = netif->name[1]; 01684 lwip_itoa(&name[2], NETIF_NAMESIZE - 2, netif_index_to_num(idx)); 01685 return name; 01686 } 01687 return NULL; 01688 } 01689 01690 /** 01691 * @ingroup netif 01692 * Return the interface for the netif index 01693 * 01694 * @param idx index of netif to find 01695 */ 01696 struct netif * 01697 netif_get_by_index(u8_t idx) 01698 { 01699 struct netif *netif; 01700 01701 LWIP_ASSERT_CORE_LOCKED(); 01702 01703 if (idx != NETIF_NO_INDEX) { 01704 NETIF_FOREACH(netif) { 01705 if (idx == netif_get_index(netif)) { 01706 return netif; /* found! */ 01707 } 01708 } 01709 } 01710 01711 return NULL; 01712 } 01713 01714 /** 01715 * @ingroup netif 01716 * Find a network interface by searching for its name 01717 * 01718 * @param name the name of the netif (like netif->name) plus concatenated number 01719 * in ascii representation (e.g. 'en0') 01720 */ 01721 struct netif * 01722 netif_find(const char *name) 01723 { 01724 struct netif *netif; 01725 u8_t num; 01726 01727 LWIP_ASSERT_CORE_LOCKED(); 01728 01729 if (name == NULL) { 01730 return NULL; 01731 } 01732 01733 num = (u8_t)atoi(&name[2]); 01734 01735 NETIF_FOREACH(netif) { 01736 if (num == netif->num && 01737 name[0] == netif->name[0] && 01738 name[1] == netif->name[1]) { 01739 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); 01740 return netif; 01741 } 01742 } 01743 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); 01744 return NULL; 01745 } 01746 01747 /** 01748 * @ingroup netif 01749 * Get a network interface name 01750 * @param netif 01751 * @return name the name of the netif (like netif->name) plus concatenated number 01752 * in ascii representation (e.g. 'en0') 01753 */ 01754 const char * 01755 netif_get_name(struct netif *netif) 01756 { 01757 if (netif == NULL) { 01758 return NULL; 01759 } 01760 sprintf(netif_name, "%c%c%d", netif->name[0], netif->name[1], netif->num); 01761 return netif_name; 01762 } 01763 01764 #if LWIP_NETIF_EXT_STATUS_CALLBACK 01765 /** 01766 * @ingroup netif 01767 * Add extended netif events listener 01768 * @param callback pointer to listener structure 01769 * @param fn callback function 01770 */ 01771 void 01772 netif_add_ext_callback(netif_ext_callback_t *callback, netif_ext_callback_fn fn) 01773 { 01774 LWIP_ASSERT_CORE_LOCKED(); 01775 LWIP_ASSERT("callback must be != NULL", callback != NULL); 01776 LWIP_ASSERT("fn must be != NULL", fn != NULL); 01777 01778 callback->callback_fn = fn; 01779 callback->next = ext_callback; 01780 ext_callback = callback; 01781 } 01782 01783 /** 01784 * @ingroup netif 01785 * Remove extended netif events listener 01786 * @param callback pointer to listener structure 01787 */ 01788 void 01789 netif_remove_ext_callback(netif_ext_callback_t* callback) 01790 { 01791 netif_ext_callback_t *last, *iter; 01792 01793 LWIP_ASSERT_CORE_LOCKED(); 01794 LWIP_ASSERT("callback must be != NULL", callback != NULL); 01795 01796 if (ext_callback == NULL) { 01797 return; 01798 } 01799 01800 if (callback == ext_callback) { 01801 ext_callback = ext_callback->next; 01802 } else { 01803 last = ext_callback; 01804 for (iter = ext_callback->next; iter != NULL; last = iter, iter = iter->next) { 01805 if (iter == callback) { 01806 LWIP_ASSERT("last != NULL", last != NULL); 01807 last->next = callback->next; 01808 callback->next = NULL; 01809 return; 01810 } 01811 } 01812 } 01813 } 01814 01815 /** 01816 * Invoke extended netif status event 01817 * @param netif netif that is affected by change 01818 * @param reason change reason 01819 * @param args depends on reason, see reason description 01820 */ 01821 void 01822 netif_invoke_ext_callback(struct netif *netif, netif_nsc_reason_t reason, const netif_ext_callback_args_t *args) 01823 { 01824 netif_ext_callback_t *callback = ext_callback; 01825 01826 LWIP_ASSERT("netif must be != NULL", netif != NULL); 01827 01828 while (callback != NULL) { 01829 callback->callback_fn(netif, reason, args); 01830 callback = callback->next; 01831 } 01832 } 01833 #endif /* LWIP_NETIF_EXT_STATUS_CALLBACK */
Generated on Tue Jul 12 2022 13:54:29 by
