1195972f6Sopenharmony_ci/** 2195972f6Sopenharmony_ci * @file 3195972f6Sopenharmony_ci * lwIP network interface abstraction 4195972f6Sopenharmony_ci * 5195972f6Sopenharmony_ci * @defgroup netif Network interface (NETIF) 6195972f6Sopenharmony_ci * @ingroup callbackstyle_api 7195972f6Sopenharmony_ci * 8195972f6Sopenharmony_ci * @defgroup netif_ip4 IPv4 address handling 9195972f6Sopenharmony_ci * @ingroup netif 10195972f6Sopenharmony_ci * 11195972f6Sopenharmony_ci * @defgroup netif_ip6 IPv6 address handling 12195972f6Sopenharmony_ci * @ingroup netif 13195972f6Sopenharmony_ci * 14195972f6Sopenharmony_ci * @defgroup netif_cd Client data handling 15195972f6Sopenharmony_ci * Store data (void*) on a netif for application usage. 16195972f6Sopenharmony_ci * @see @ref LWIP_NUM_NETIF_CLIENT_DATA 17195972f6Sopenharmony_ci * @ingroup netif 18195972f6Sopenharmony_ci */ 19195972f6Sopenharmony_ci 20195972f6Sopenharmony_ci/* 21195972f6Sopenharmony_ci * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 22195972f6Sopenharmony_ci * All rights reserved. 23195972f6Sopenharmony_ci * 24195972f6Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 25195972f6Sopenharmony_ci * are permitted provided that the following conditions are met: 26195972f6Sopenharmony_ci * 27195972f6Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, 28195972f6Sopenharmony_ci * this list of conditions and the following disclaimer. 29195972f6Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, 30195972f6Sopenharmony_ci * this list of conditions and the following disclaimer in the documentation 31195972f6Sopenharmony_ci * and/or other materials provided with the distribution. 32195972f6Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote products 33195972f6Sopenharmony_ci * derived from this software without specific prior written permission. 34195972f6Sopenharmony_ci * 35195972f6Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 36195972f6Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 37195972f6Sopenharmony_ci * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 38195972f6Sopenharmony_ci * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 39195972f6Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 40195972f6Sopenharmony_ci * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 41195972f6Sopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 42195972f6Sopenharmony_ci * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 43195972f6Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 44195972f6Sopenharmony_ci * OF SUCH DAMAGE. 45195972f6Sopenharmony_ci * 46195972f6Sopenharmony_ci * This file is part of the lwIP TCP/IP stack. 47195972f6Sopenharmony_ci * 48195972f6Sopenharmony_ci * Author: Adam Dunkels <adam@sics.se> 49195972f6Sopenharmony_ci */ 50195972f6Sopenharmony_ci 51195972f6Sopenharmony_ci#include "lwip/opt.h" 52195972f6Sopenharmony_ci 53195972f6Sopenharmony_ci#include <string.h> /* memset */ 54195972f6Sopenharmony_ci#include <stdlib.h> /* atoi */ 55195972f6Sopenharmony_ci 56195972f6Sopenharmony_ci#include "lwip/def.h" 57195972f6Sopenharmony_ci#include "lwip/ip_addr.h" 58195972f6Sopenharmony_ci#include "lwip/ip6_addr.h" 59195972f6Sopenharmony_ci#include "lwip/netif.h" 60195972f6Sopenharmony_ci#include "lwip/priv/tcp_priv.h" 61195972f6Sopenharmony_ci#include "lwip/udp.h" 62195972f6Sopenharmony_ci#include "lwip/priv/raw_priv.h" 63195972f6Sopenharmony_ci#include "lwip/snmp.h" 64195972f6Sopenharmony_ci#include "lwip/igmp.h" 65195972f6Sopenharmony_ci#include "lwip/etharp.h" 66195972f6Sopenharmony_ci#include "lwip/stats.h" 67195972f6Sopenharmony_ci#include "lwip/sys.h" 68195972f6Sopenharmony_ci#include "lwip/ip.h" 69195972f6Sopenharmony_ci#if ENABLE_LOOPBACK 70195972f6Sopenharmony_ci#if LWIP_NETIF_LOOPBACK_MULTITHREADING 71195972f6Sopenharmony_ci#include "lwip/tcpip.h" 72195972f6Sopenharmony_ci#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 73195972f6Sopenharmony_ci#endif /* ENABLE_LOOPBACK */ 74195972f6Sopenharmony_ci 75195972f6Sopenharmony_ci#include "netif/ethernet.h" 76195972f6Sopenharmony_ci 77195972f6Sopenharmony_ci#if LWIP_AUTOIP 78195972f6Sopenharmony_ci#include "lwip/autoip.h" 79195972f6Sopenharmony_ci#endif /* LWIP_AUTOIP */ 80195972f6Sopenharmony_ci#if LWIP_DHCP 81195972f6Sopenharmony_ci#include "lwip/dhcp.h" 82195972f6Sopenharmony_ci#endif /* LWIP_DHCP */ 83195972f6Sopenharmony_ci#if LWIP_IPV6_DHCP6 84195972f6Sopenharmony_ci#include "lwip/dhcp6.h" 85195972f6Sopenharmony_ci#endif /* LWIP_IPV6_DHCP6 */ 86195972f6Sopenharmony_ci#if LWIP_IPV6_MLD 87195972f6Sopenharmony_ci#include "lwip/mld6.h" 88195972f6Sopenharmony_ci#endif /* LWIP_IPV6_MLD */ 89195972f6Sopenharmony_ci#if LWIP_IPV6 90195972f6Sopenharmony_ci#include "lwip/nd6.h" 91195972f6Sopenharmony_ci#endif 92195972f6Sopenharmony_ci 93195972f6Sopenharmony_ci#if LWIP_NETIF_STATUS_CALLBACK 94195972f6Sopenharmony_ci#define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0) 95195972f6Sopenharmony_ci#else 96195972f6Sopenharmony_ci#define NETIF_STATUS_CALLBACK(n) 97195972f6Sopenharmony_ci#endif /* LWIP_NETIF_STATUS_CALLBACK */ 98195972f6Sopenharmony_ci 99195972f6Sopenharmony_ci#if LWIP_NETIF_LINK_CALLBACK 100195972f6Sopenharmony_ci#define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0) 101195972f6Sopenharmony_ci#else 102195972f6Sopenharmony_ci#define NETIF_LINK_CALLBACK(n) 103195972f6Sopenharmony_ci#endif /* LWIP_NETIF_LINK_CALLBACK */ 104195972f6Sopenharmony_ci 105195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 106195972f6Sopenharmony_cistatic netif_ext_callback_t *ext_callback; 107195972f6Sopenharmony_ci#endif 108195972f6Sopenharmony_ci 109195972f6Sopenharmony_ci#ifndef LOSCFG_NET_CONTAINER 110195972f6Sopenharmony_ci#if !LWIP_SINGLE_NETIF 111195972f6Sopenharmony_cistruct netif *netif_list; 112195972f6Sopenharmony_ci#endif /* !LWIP_SINGLE_NETIF */ 113195972f6Sopenharmony_cistruct netif *netif_default; 114195972f6Sopenharmony_ci#endif 115195972f6Sopenharmony_ci 116195972f6Sopenharmony_ci#define netif_index_to_num(index) ((index) - 1) 117195972f6Sopenharmony_ci#ifndef LOSCFG_NET_CONTAINER 118195972f6Sopenharmony_cistatic u8_t netif_num; 119195972f6Sopenharmony_ci#endif 120195972f6Sopenharmony_ci 121195972f6Sopenharmony_ci#if LWIP_NUM_NETIF_CLIENT_DATA > 0 122195972f6Sopenharmony_cistatic u8_t netif_client_id; 123195972f6Sopenharmony_ci#endif 124195972f6Sopenharmony_ci 125195972f6Sopenharmony_ci#define NETIF_REPORT_TYPE_IPV4 0x01 126195972f6Sopenharmony_ci#define NETIF_REPORT_TYPE_IPV6 0x02 127195972f6Sopenharmony_cistatic void netif_issue_reports(struct netif *netif, u8_t report_type); 128195972f6Sopenharmony_ci 129195972f6Sopenharmony_ci#if LWIP_IPV6 130195972f6Sopenharmony_cistatic err_t netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr); 131195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 132195972f6Sopenharmony_ci#if LWIP_IPV4 133195972f6Sopenharmony_cistatic err_t netif_null_output_ip4(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr); 134195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 135195972f6Sopenharmony_ci 136195972f6Sopenharmony_ci#if LWIP_HAVE_LOOPIF 137195972f6Sopenharmony_ci#if LWIP_IPV4 138195972f6Sopenharmony_cistatic err_t netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr); 139195972f6Sopenharmony_ci#endif 140195972f6Sopenharmony_ci#if LWIP_IPV6 141195972f6Sopenharmony_cistatic err_t netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr); 142195972f6Sopenharmony_ci#endif 143195972f6Sopenharmony_ci 144195972f6Sopenharmony_ci 145195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 146195972f6Sopenharmony_cistruct net_group *get_net_group_from_netif(struct netif *netif) { 147195972f6Sopenharmony_ci if (netif != NULL) { 148195972f6Sopenharmony_ci return get_default_net_group_ops()->get_net_group_from_netif(netif); 149195972f6Sopenharmony_ci } 150195972f6Sopenharmony_ci return NULL; 151195972f6Sopenharmony_ci} 152195972f6Sopenharmony_ci#else 153195972f6Sopenharmony_cistatic struct netif loop_netif; 154195972f6Sopenharmony_ci#endif 155195972f6Sopenharmony_ci 156195972f6Sopenharmony_ci/** 157195972f6Sopenharmony_ci * Initialize a lwip network interface structure for a loopback interface 158195972f6Sopenharmony_ci * 159195972f6Sopenharmony_ci * @param netif the lwip network interface structure for this loopif 160195972f6Sopenharmony_ci * @return ERR_OK if the loopif is initialized 161195972f6Sopenharmony_ci * ERR_MEM if private data couldn't be allocated 162195972f6Sopenharmony_ci */ 163195972f6Sopenharmony_cistatic err_t 164195972f6Sopenharmony_cinetif_loopif_init(struct netif *netif) 165195972f6Sopenharmony_ci{ 166195972f6Sopenharmony_ci LWIP_ASSERT("netif_loopif_init: invalid netif", netif != NULL); 167195972f6Sopenharmony_ci 168195972f6Sopenharmony_ci /* initialize the snmp variables and counters inside the struct netif 169195972f6Sopenharmony_ci * ifSpeed: no assumption can be made! 170195972f6Sopenharmony_ci */ 171195972f6Sopenharmony_ci MIB2_INIT_NETIF(netif, snmp_ifType_softwareLoopback, 0); 172195972f6Sopenharmony_ci 173195972f6Sopenharmony_ci netif->name[0] = 'l'; 174195972f6Sopenharmony_ci netif->name[1] = 'o'; 175195972f6Sopenharmony_ci#if LWIP_IPV4 176195972f6Sopenharmony_ci netif->output = netif_loop_output_ipv4; 177195972f6Sopenharmony_ci#endif 178195972f6Sopenharmony_ci#if LWIP_IPV6 179195972f6Sopenharmony_ci netif->output_ip6 = netif_loop_output_ipv6; 180195972f6Sopenharmony_ci#endif 181195972f6Sopenharmony_ci#if LWIP_LOOPIF_MULTICAST 182195972f6Sopenharmony_ci netif_set_flags(netif, NETIF_FLAG_IGMP); 183195972f6Sopenharmony_ci#endif 184195972f6Sopenharmony_ci NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_DISABLE_ALL); 185195972f6Sopenharmony_ci return ERR_OK; 186195972f6Sopenharmony_ci} 187195972f6Sopenharmony_ci#endif /* LWIP_HAVE_LOOPIF */ 188195972f6Sopenharmony_ci 189195972f6Sopenharmony_civoid 190195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 191195972f6Sopenharmony_cinetif_init(struct net_group *group) 192195972f6Sopenharmony_ci#else 193195972f6Sopenharmony_cinetif_init(void) 194195972f6Sopenharmony_ci#endif 195195972f6Sopenharmony_ci{ 196195972f6Sopenharmony_ci#if LWIP_HAVE_LOOPIF 197195972f6Sopenharmony_ci#if LWIP_IPV4 198195972f6Sopenharmony_ci#define LOOPIF_ADDRINIT &loop_ipaddr, &loop_netmask, &loop_gw, 199195972f6Sopenharmony_ci ip4_addr_t loop_ipaddr, loop_netmask, loop_gw; 200195972f6Sopenharmony_ci IP4_ADDR(&loop_gw, 127, 0, 0, 1); 201195972f6Sopenharmony_ci IP4_ADDR(&loop_ipaddr, 127, 0, 0, 1); 202195972f6Sopenharmony_ci IP4_ADDR(&loop_netmask, 255, 0, 0, 0); 203195972f6Sopenharmony_ci#else /* LWIP_IPV4 */ 204195972f6Sopenharmony_ci#define LOOPIF_ADDRINIT 205195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 206195972f6Sopenharmony_ci 207195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 208195972f6Sopenharmony_cistruct netif *loop_netif = group->loop_netif; 209195972f6Sopenharmony_ci#endif 210195972f6Sopenharmony_ci 211195972f6Sopenharmony_ci#if NO_SYS 212195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 213195972f6Sopenharmony_ci netif_add(loop_netif, group, LOOPIF_ADDRINIT NULL, netif_loopif_init, ip_input); 214195972f6Sopenharmony_ci#else 215195972f6Sopenharmony_ci netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, ip_input); 216195972f6Sopenharmony_ci#endif 217195972f6Sopenharmony_ci#else /* NO_SYS */ 218195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 219195972f6Sopenharmony_ci netif_add(loop_netif, group, LOOPIF_ADDRINIT NULL, netif_loopif_init, tcpip_input); 220195972f6Sopenharmony_ci#else 221195972f6Sopenharmony_ci netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, tcpip_input); 222195972f6Sopenharmony_ci#endif 223195972f6Sopenharmony_ci#endif /* NO_SYS */ 224195972f6Sopenharmony_ci 225195972f6Sopenharmony_ci#if LWIP_IPV6 226195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 227195972f6Sopenharmony_ci IP_ADDR6_HOST(loop_netif->ip6_addr, 0, 0, 0, 0x00000001UL); 228195972f6Sopenharmony_ci loop_netif->ip6_addr_state[0] = IP6_ADDR_VALID; 229195972f6Sopenharmony_ci#else 230195972f6Sopenharmony_ci IP_ADDR6_HOST(loop_netif.ip6_addr, 0, 0, 0, 0x00000001UL); 231195972f6Sopenharmony_ci loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID; 232195972f6Sopenharmony_ci#endif 233195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 234195972f6Sopenharmony_ci 235195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 236195972f6Sopenharmony_ci netif_set_link_up(loop_netif); 237195972f6Sopenharmony_ci netif_set_up(loop_netif); 238195972f6Sopenharmony_ci#else 239195972f6Sopenharmony_ci netif_set_link_up(&loop_netif); 240195972f6Sopenharmony_ci netif_set_up(&loop_netif); 241195972f6Sopenharmony_ci#endif 242195972f6Sopenharmony_ci 243195972f6Sopenharmony_ci#endif /* LWIP_HAVE_LOOPIF */ 244195972f6Sopenharmony_ci} 245195972f6Sopenharmony_ci 246195972f6Sopenharmony_ci/** 247195972f6Sopenharmony_ci * @ingroup lwip_nosys 248195972f6Sopenharmony_ci * Forwards a received packet for input processing with 249195972f6Sopenharmony_ci * ethernet_input() or ip_input() depending on netif flags. 250195972f6Sopenharmony_ci * Don't call directly, pass to netif_add() and call 251195972f6Sopenharmony_ci * netif->input(). 252195972f6Sopenharmony_ci * Only works if the netif driver correctly sets 253195972f6Sopenharmony_ci * NETIF_FLAG_ETHARP and/or NETIF_FLAG_ETHERNET flag! 254195972f6Sopenharmony_ci */ 255195972f6Sopenharmony_cierr_t 256195972f6Sopenharmony_cinetif_input(struct pbuf *p, struct netif *inp) 257195972f6Sopenharmony_ci{ 258195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 259195972f6Sopenharmony_ci 260195972f6Sopenharmony_ci LWIP_ASSERT("netif_input: invalid pbuf", p != NULL); 261195972f6Sopenharmony_ci LWIP_ASSERT("netif_input: invalid netif", inp != NULL); 262195972f6Sopenharmony_ci 263195972f6Sopenharmony_ci#if LWIP_ETHERNET 264195972f6Sopenharmony_ci if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { 265195972f6Sopenharmony_ci return ethernet_input(p, inp); 266195972f6Sopenharmony_ci } else 267195972f6Sopenharmony_ci#endif /* LWIP_ETHERNET */ 268195972f6Sopenharmony_ci return ip_input(p, inp); 269195972f6Sopenharmony_ci} 270195972f6Sopenharmony_ci 271195972f6Sopenharmony_ci/** 272195972f6Sopenharmony_ci * @ingroup netif 273195972f6Sopenharmony_ci * Add a network interface to the list of lwIP netifs. 274195972f6Sopenharmony_ci * 275195972f6Sopenharmony_ci * Same as @ref netif_add but without IPv4 addresses 276195972f6Sopenharmony_ci */ 277195972f6Sopenharmony_cistruct netif * 278195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 279195972f6Sopenharmony_cinetif_add_noaddr(struct netif *netif, struct net_group *group, void *state, netif_init_fn init, netif_input_fn input) 280195972f6Sopenharmony_ci#else 281195972f6Sopenharmony_cinetif_add_noaddr(struct netif *netif, void *state, netif_init_fn init, netif_input_fn input) 282195972f6Sopenharmony_ci#endif 283195972f6Sopenharmony_ci{ 284195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 285195972f6Sopenharmony_ci return netif_add(netif, group, 286195972f6Sopenharmony_ci#else 287195972f6Sopenharmony_ci return netif_add(netif, 288195972f6Sopenharmony_ci#endif 289195972f6Sopenharmony_ci#if LWIP_IPV4 290195972f6Sopenharmony_ci NULL, NULL, NULL, 291195972f6Sopenharmony_ci#endif /* LWIP_IPV4*/ 292195972f6Sopenharmony_ci state, init, input); 293195972f6Sopenharmony_ci} 294195972f6Sopenharmony_ci 295195972f6Sopenharmony_ci/** 296195972f6Sopenharmony_ci * @ingroup netif 297195972f6Sopenharmony_ci * Add a network interface to the list of lwIP netifs. 298195972f6Sopenharmony_ci * 299195972f6Sopenharmony_ci * @param netif a pre-allocated netif structure 300195972f6Sopenharmony_ci * @param ipaddr IP address for the new netif 301195972f6Sopenharmony_ci * @param netmask network mask for the new netif 302195972f6Sopenharmony_ci * @param gw default gateway IP address for the new netif 303195972f6Sopenharmony_ci * @param state opaque data passed to the new netif 304195972f6Sopenharmony_ci * @param init callback function that initializes the interface 305195972f6Sopenharmony_ci * @param input callback function that is called to pass 306195972f6Sopenharmony_ci * ingress packets up in the protocol layer stack.\n 307195972f6Sopenharmony_ci * It is recommended to use a function that passes the input directly 308195972f6Sopenharmony_ci * to the stack (netif_input(), NO_SYS=1 mode) or via sending a 309195972f6Sopenharmony_ci * message to TCPIP thread (tcpip_input(), NO_SYS=0 mode).\n 310195972f6Sopenharmony_ci * These functions use netif flags NETIF_FLAG_ETHARP and NETIF_FLAG_ETHERNET 311195972f6Sopenharmony_ci * to decide whether to forward to ethernet_input() or ip_input(). 312195972f6Sopenharmony_ci * In other words, the functions only work when the netif 313195972f6Sopenharmony_ci * driver is implemented correctly!\n 314195972f6Sopenharmony_ci * Most members of struct netif should be be initialized by the 315195972f6Sopenharmony_ci * netif init function = netif driver (init parameter of this function).\n 316195972f6Sopenharmony_ci * IPv6: Don't forget to call netif_create_ip6_linklocal_address() after 317195972f6Sopenharmony_ci * setting the MAC address in struct netif.hwaddr 318195972f6Sopenharmony_ci * (IPv6 requires a link-local address). 319195972f6Sopenharmony_ci * 320195972f6Sopenharmony_ci * @return netif, or NULL if failed. 321195972f6Sopenharmony_ci */ 322195972f6Sopenharmony_cistruct netif * 323195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 324195972f6Sopenharmony_cinetif_add(struct netif *netif, struct net_group *group, 325195972f6Sopenharmony_ci#else 326195972f6Sopenharmony_cinetif_add(struct netif *netif, 327195972f6Sopenharmony_ci#endif 328195972f6Sopenharmony_ci#if LWIP_IPV4 329195972f6Sopenharmony_ci const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, 330195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 331195972f6Sopenharmony_ci void *state, netif_init_fn init, netif_input_fn input) 332195972f6Sopenharmony_ci{ 333195972f6Sopenharmony_ci#if LWIP_IPV6 334195972f6Sopenharmony_ci s8_t i; 335195972f6Sopenharmony_ci#endif 336195972f6Sopenharmony_ci 337195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 338195972f6Sopenharmony_ci 339195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 340195972f6Sopenharmony_ci get_default_net_group_ops()->set_netif_net_group(netif, group); 341195972f6Sopenharmony_ci#endif 342195972f6Sopenharmony_ci 343195972f6Sopenharmony_ci#if LWIP_SINGLE_NETIF 344195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 345195972f6Sopenharmony_ci if (group->loop_netif != NULL) { 346195972f6Sopenharmony_ci#else 347195972f6Sopenharmony_ci if (netif_default != NULL) { 348195972f6Sopenharmony_ci#endif 349195972f6Sopenharmony_ci LWIP_ASSERT("single netif already set", 0); 350195972f6Sopenharmony_ci return NULL; 351195972f6Sopenharmony_ci } 352195972f6Sopenharmony_ci#endif 353195972f6Sopenharmony_ci 354195972f6Sopenharmony_ci LWIP_ERROR("netif_add: invalid netif", netif != NULL, return NULL); 355195972f6Sopenharmony_ci LWIP_ERROR("netif_add: No init function given", init != NULL, return NULL); 356195972f6Sopenharmony_ci 357195972f6Sopenharmony_ci#if LWIP_IPV4 358195972f6Sopenharmony_ci if (ipaddr == NULL) { 359195972f6Sopenharmony_ci ipaddr = ip_2_ip4(IP4_ADDR_ANY); 360195972f6Sopenharmony_ci } 361195972f6Sopenharmony_ci if (netmask == NULL) { 362195972f6Sopenharmony_ci netmask = ip_2_ip4(IP4_ADDR_ANY); 363195972f6Sopenharmony_ci } 364195972f6Sopenharmony_ci if (gw == NULL) { 365195972f6Sopenharmony_ci gw = ip_2_ip4(IP4_ADDR_ANY); 366195972f6Sopenharmony_ci } 367195972f6Sopenharmony_ci 368195972f6Sopenharmony_ci /* reset new interface configuration state */ 369195972f6Sopenharmony_ci ip_addr_set_zero_ip4(&netif->ip_addr); 370195972f6Sopenharmony_ci ip_addr_set_zero_ip4(&netif->netmask); 371195972f6Sopenharmony_ci ip_addr_set_zero_ip4(&netif->gw); 372195972f6Sopenharmony_ci netif->output = netif_null_output_ip4; 373195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 374195972f6Sopenharmony_ci#if LWIP_IPV6 375195972f6Sopenharmony_ci for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 376195972f6Sopenharmony_ci ip_addr_set_zero_ip6(&netif->ip6_addr[i]); 377195972f6Sopenharmony_ci netif->ip6_addr_state[i] = IP6_ADDR_INVALID; 378195972f6Sopenharmony_ci#if LWIP_IPV6_ADDRESS_LIFETIMES 379195972f6Sopenharmony_ci netif->ip6_addr_valid_life[i] = IP6_ADDR_LIFE_STATIC; 380195972f6Sopenharmony_ci netif->ip6_addr_pref_life[i] = IP6_ADDR_LIFE_STATIC; 381195972f6Sopenharmony_ci#endif /* LWIP_IPV6_ADDRESS_LIFETIMES */ 382195972f6Sopenharmony_ci } 383195972f6Sopenharmony_ci netif->output_ip6 = netif_null_output_ip6; 384195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 385195972f6Sopenharmony_ci NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL); 386195972f6Sopenharmony_ci netif->mtu = 0; 387195972f6Sopenharmony_ci netif->flags = 0; 388195972f6Sopenharmony_ci#ifdef netif_get_client_data 389195972f6Sopenharmony_ci memset(netif->client_data, 0, sizeof(netif->client_data)); 390195972f6Sopenharmony_ci#endif /* LWIP_NUM_NETIF_CLIENT_DATA */ 391195972f6Sopenharmony_ci#if LWIP_IPV6 392195972f6Sopenharmony_ci#if LWIP_IPV6_AUTOCONFIG 393195972f6Sopenharmony_ci /* IPv6 address autoconfiguration not enabled by default */ 394195972f6Sopenharmony_ci netif->ip6_autoconfig_enabled = 0; 395195972f6Sopenharmony_ci#endif /* LWIP_IPV6_AUTOCONFIG */ 396195972f6Sopenharmony_ci nd6_restart_netif(netif); 397195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 398195972f6Sopenharmony_ci#if LWIP_NETIF_STATUS_CALLBACK 399195972f6Sopenharmony_ci netif->status_callback = NULL; 400195972f6Sopenharmony_ci#endif /* LWIP_NETIF_STATUS_CALLBACK */ 401195972f6Sopenharmony_ci#if LWIP_NETIF_LINK_CALLBACK 402195972f6Sopenharmony_ci netif->link_callback = NULL; 403195972f6Sopenharmony_ci#endif /* LWIP_NETIF_LINK_CALLBACK */ 404195972f6Sopenharmony_ci#if LWIP_IGMP 405195972f6Sopenharmony_ci netif->igmp_mac_filter = NULL; 406195972f6Sopenharmony_ci#endif /* LWIP_IGMP */ 407195972f6Sopenharmony_ci#if LWIP_IPV6 && LWIP_IPV6_MLD 408195972f6Sopenharmony_ci netif->mld_mac_filter = NULL; 409195972f6Sopenharmony_ci#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ 410195972f6Sopenharmony_ci 411195972f6Sopenharmony_ci /* remember netif specific state information data */ 412195972f6Sopenharmony_ci netif->state = state; 413195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 414195972f6Sopenharmony_ci netif->num = group->netif_num; 415195972f6Sopenharmony_ci#else 416195972f6Sopenharmony_ci netif->num = netif_num; 417195972f6Sopenharmony_ci#endif 418195972f6Sopenharmony_ci netif->input = input; 419195972f6Sopenharmony_ci 420195972f6Sopenharmony_ci NETIF_RESET_HINTS(netif); 421195972f6Sopenharmony_ci#if ENABLE_LOOPBACK 422195972f6Sopenharmony_ci netif->loop_first = NULL; 423195972f6Sopenharmony_ci netif->loop_last = NULL; 424195972f6Sopenharmony_ci#if LWIP_LOOPBACK_MAX_PBUFS 425195972f6Sopenharmony_ci netif->loop_cnt_current = 0; 426195972f6Sopenharmony_ci#endif /* LWIP_LOOPBACK_MAX_PBUFS */ 427195972f6Sopenharmony_ci#if LWIP_NETIF_LOOPBACK_MULTITHREADING 428195972f6Sopenharmony_ci netif->reschedule_poll = 0; 429195972f6Sopenharmony_ci#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 430195972f6Sopenharmony_ci#endif /* ENABLE_LOOPBACK */ 431195972f6Sopenharmony_ci 432195972f6Sopenharmony_ci#if LWIP_IPV4 433195972f6Sopenharmony_ci netif_set_addr(netif, ipaddr, netmask, gw); 434195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 435195972f6Sopenharmony_ci 436195972f6Sopenharmony_ci /* call user specified initialization function for netif */ 437195972f6Sopenharmony_ci if (init(netif) != ERR_OK) { 438195972f6Sopenharmony_ci return NULL; 439195972f6Sopenharmony_ci } 440195972f6Sopenharmony_ci#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES 441195972f6Sopenharmony_ci /* Initialize the MTU for IPv6 to the one set by the netif driver. 442195972f6Sopenharmony_ci This can be updated later by RA. */ 443195972f6Sopenharmony_ci netif->mtu6 = netif->mtu; 444195972f6Sopenharmony_ci#endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */ 445195972f6Sopenharmony_ci 446195972f6Sopenharmony_ci#if !LWIP_SINGLE_NETIF 447195972f6Sopenharmony_ci /* Assign a unique netif number in the range [0..254], so that (num+1) can 448195972f6Sopenharmony_ci serve as an interface index that fits in a u8_t. 449195972f6Sopenharmony_ci We assume that the new netif has not yet been added to the list here. 450195972f6Sopenharmony_ci This algorithm is O(n^2), but that should be OK for lwIP. 451195972f6Sopenharmony_ci */ 452195972f6Sopenharmony_ci { 453195972f6Sopenharmony_ci struct netif *netif2; 454195972f6Sopenharmony_ci int num_netifs; 455195972f6Sopenharmony_ci do { 456195972f6Sopenharmony_ci if (netif->num == 255) { 457195972f6Sopenharmony_ci netif->num = 0; 458195972f6Sopenharmony_ci } 459195972f6Sopenharmony_ci num_netifs = 0; 460195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 461195972f6Sopenharmony_ci for (netif2 = group->netif_list; netif2 != NULL; netif2 = netif2->next) { 462195972f6Sopenharmony_ci#else 463195972f6Sopenharmony_ci for (netif2 = netif_list; netif2 != NULL; netif2 = netif2->next) { 464195972f6Sopenharmony_ci#endif 465195972f6Sopenharmony_ci LWIP_ASSERT("netif already added", netif2 != netif); 466195972f6Sopenharmony_ci num_netifs++; 467195972f6Sopenharmony_ci LWIP_ASSERT("too many netifs, max. supported number is 255", num_netifs <= 255); 468195972f6Sopenharmony_ci if (netif2->num == netif->num) { 469195972f6Sopenharmony_ci netif->num++; 470195972f6Sopenharmony_ci break; 471195972f6Sopenharmony_ci } 472195972f6Sopenharmony_ci } 473195972f6Sopenharmony_ci } while (netif2 != NULL); 474195972f6Sopenharmony_ci } 475195972f6Sopenharmony_ci if (netif->num == 254) { 476195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 477195972f6Sopenharmony_ci group->netif_num = 0; 478195972f6Sopenharmony_ci#else 479195972f6Sopenharmony_ci netif_num = 0; 480195972f6Sopenharmony_ci#endif 481195972f6Sopenharmony_ci } else { 482195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 483195972f6Sopenharmony_ci group->netif_num = (u8_t)(netif->num + 1); 484195972f6Sopenharmony_ci#else 485195972f6Sopenharmony_ci netif_num = (u8_t)(netif->num + 1); 486195972f6Sopenharmony_ci#endif 487195972f6Sopenharmony_ci } 488195972f6Sopenharmony_ci 489195972f6Sopenharmony_ci /* add this netif to the list */ 490195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 491195972f6Sopenharmony_ci netif->next = group->netif_list; 492195972f6Sopenharmony_ci group->netif_list = netif; 493195972f6Sopenharmony_ci#else 494195972f6Sopenharmony_ci netif->next = netif_list; 495195972f6Sopenharmony_ci netif_list = netif; 496195972f6Sopenharmony_ci#endif 497195972f6Sopenharmony_ci#endif /* "LWIP_SINGLE_NETIF */ 498195972f6Sopenharmony_ci mib2_netif_added(netif); 499195972f6Sopenharmony_ci 500195972f6Sopenharmony_ci#if LWIP_IGMP 501195972f6Sopenharmony_ci /* start IGMP processing */ 502195972f6Sopenharmony_ci if (netif->flags & NETIF_FLAG_IGMP) { 503195972f6Sopenharmony_ci igmp_start(netif); 504195972f6Sopenharmony_ci } 505195972f6Sopenharmony_ci#endif /* LWIP_IGMP */ 506195972f6Sopenharmony_ci 507195972f6Sopenharmony_ci LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP", 508195972f6Sopenharmony_ci netif->name[0], netif->name[1])); 509195972f6Sopenharmony_ci#if LWIP_IPV4 510195972f6Sopenharmony_ci LWIP_DEBUGF(NETIF_DEBUG, (" addr ")); 511195972f6Sopenharmony_ci ip4_addr_debug_print(NETIF_DEBUG, ipaddr); 512195972f6Sopenharmony_ci LWIP_DEBUGF(NETIF_DEBUG, (" netmask ")); 513195972f6Sopenharmony_ci ip4_addr_debug_print(NETIF_DEBUG, netmask); 514195972f6Sopenharmony_ci LWIP_DEBUGF(NETIF_DEBUG, (" gw ")); 515195972f6Sopenharmony_ci ip4_addr_debug_print(NETIF_DEBUG, gw); 516195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 517195972f6Sopenharmony_ci LWIP_DEBUGF(NETIF_DEBUG, ("\n")); 518195972f6Sopenharmony_ci 519195972f6Sopenharmony_ci netif_invoke_ext_callback(netif, LWIP_NSC_NETIF_ADDED, NULL); 520195972f6Sopenharmony_ci 521195972f6Sopenharmony_ci return netif; 522195972f6Sopenharmony_ci} 523195972f6Sopenharmony_ci 524195972f6Sopenharmony_cistatic void 525195972f6Sopenharmony_cinetif_do_ip_addr_changed(const ip_addr_t *old_addr, const ip_addr_t *new_addr) 526195972f6Sopenharmony_ci{ 527195972f6Sopenharmony_ci#if LWIP_TCP 528195972f6Sopenharmony_ci tcp_netif_ip_addr_changed(old_addr, new_addr); 529195972f6Sopenharmony_ci#endif /* LWIP_TCP */ 530195972f6Sopenharmony_ci#if LWIP_UDP 531195972f6Sopenharmony_ci udp_netif_ip_addr_changed(old_addr, new_addr); 532195972f6Sopenharmony_ci#endif /* LWIP_UDP */ 533195972f6Sopenharmony_ci#if LWIP_RAW 534195972f6Sopenharmony_ci raw_netif_ip_addr_changed(old_addr, new_addr); 535195972f6Sopenharmony_ci#endif /* LWIP_RAW */ 536195972f6Sopenharmony_ci} 537195972f6Sopenharmony_ci 538195972f6Sopenharmony_ci#if LWIP_IPV4 539195972f6Sopenharmony_cistatic int 540195972f6Sopenharmony_cinetif_do_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr, ip_addr_t *old_addr) 541195972f6Sopenharmony_ci{ 542195972f6Sopenharmony_ci LWIP_ASSERT("invalid pointer", ipaddr != NULL); 543195972f6Sopenharmony_ci LWIP_ASSERT("invalid pointer", old_addr != NULL); 544195972f6Sopenharmony_ci 545195972f6Sopenharmony_ci /* address is actually being changed? */ 546195972f6Sopenharmony_ci if (ip4_addr_cmp(ipaddr, netif_ip4_addr(netif)) == 0) { 547195972f6Sopenharmony_ci ip_addr_t new_addr; 548195972f6Sopenharmony_ci *ip_2_ip4(&new_addr) = *ipaddr; 549195972f6Sopenharmony_ci IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_V4); 550195972f6Sopenharmony_ci 551195972f6Sopenharmony_ci ip_addr_copy(*old_addr, *netif_ip_addr4(netif)); 552195972f6Sopenharmony_ci 553195972f6Sopenharmony_ci LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); 554195972f6Sopenharmony_ci netif_do_ip_addr_changed(old_addr, &new_addr); 555195972f6Sopenharmony_ci 556195972f6Sopenharmony_ci mib2_remove_ip4(netif); 557195972f6Sopenharmony_ci mib2_remove_route_ip4(0, netif); 558195972f6Sopenharmony_ci /* set new IP address to netif */ 559195972f6Sopenharmony_ci ip4_addr_set(ip_2_ip4(&netif->ip_addr), ipaddr); 560195972f6Sopenharmony_ci IP_SET_TYPE_VAL(netif->ip_addr, IPADDR_TYPE_V4); 561195972f6Sopenharmony_ci mib2_add_ip4(netif); 562195972f6Sopenharmony_ci mib2_add_route_ip4(0, netif); 563195972f6Sopenharmony_ci 564195972f6Sopenharmony_ci netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4); 565195972f6Sopenharmony_ci 566195972f6Sopenharmony_ci NETIF_STATUS_CALLBACK(netif); 567195972f6Sopenharmony_ci return 1; /* address changed */ 568195972f6Sopenharmony_ci } 569195972f6Sopenharmony_ci return 0; /* address unchanged */ 570195972f6Sopenharmony_ci} 571195972f6Sopenharmony_ci 572195972f6Sopenharmony_ci/** 573195972f6Sopenharmony_ci * @ingroup netif_ip4 574195972f6Sopenharmony_ci * Change the IP address of a network interface 575195972f6Sopenharmony_ci * 576195972f6Sopenharmony_ci * @param netif the network interface to change 577195972f6Sopenharmony_ci * @param ipaddr the new IP address 578195972f6Sopenharmony_ci * 579195972f6Sopenharmony_ci * @note call netif_set_addr() if you also want to change netmask and 580195972f6Sopenharmony_ci * default gateway 581195972f6Sopenharmony_ci */ 582195972f6Sopenharmony_civoid 583195972f6Sopenharmony_cinetif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr) 584195972f6Sopenharmony_ci{ 585195972f6Sopenharmony_ci ip_addr_t old_addr; 586195972f6Sopenharmony_ci 587195972f6Sopenharmony_ci LWIP_ERROR("netif_set_ipaddr: invalid netif", netif != NULL, return); 588195972f6Sopenharmony_ci 589195972f6Sopenharmony_ci /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ 590195972f6Sopenharmony_ci if (ipaddr == NULL) { 591195972f6Sopenharmony_ci ipaddr = IP4_ADDR_ANY4; 592195972f6Sopenharmony_ci } 593195972f6Sopenharmony_ci 594195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 595195972f6Sopenharmony_ci 596195972f6Sopenharmony_ci if (netif_do_set_ipaddr(netif, ipaddr, &old_addr)) { 597195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 598195972f6Sopenharmony_ci netif_ext_callback_args_t args; 599195972f6Sopenharmony_ci args.ipv4_changed.old_address = &old_addr; 600195972f6Sopenharmony_ci netif_invoke_ext_callback(netif, LWIP_NSC_IPV4_ADDRESS_CHANGED, &args); 601195972f6Sopenharmony_ci#endif 602195972f6Sopenharmony_ci } 603195972f6Sopenharmony_ci} 604195972f6Sopenharmony_ci 605195972f6Sopenharmony_cistatic int 606195972f6Sopenharmony_cinetif_do_set_netmask(struct netif *netif, const ip4_addr_t *netmask, ip_addr_t *old_nm) 607195972f6Sopenharmony_ci{ 608195972f6Sopenharmony_ci /* address is actually being changed? */ 609195972f6Sopenharmony_ci if (ip4_addr_cmp(netmask, netif_ip4_netmask(netif)) == 0) { 610195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 611195972f6Sopenharmony_ci LWIP_ASSERT("invalid pointer", old_nm != NULL); 612195972f6Sopenharmony_ci ip_addr_copy(*old_nm, *netif_ip_netmask4(netif)); 613195972f6Sopenharmony_ci#else 614195972f6Sopenharmony_ci LWIP_UNUSED_ARG(old_nm); 615195972f6Sopenharmony_ci#endif 616195972f6Sopenharmony_ci mib2_remove_route_ip4(0, netif); 617195972f6Sopenharmony_ci /* set new netmask to netif */ 618195972f6Sopenharmony_ci ip4_addr_set(ip_2_ip4(&netif->netmask), netmask); 619195972f6Sopenharmony_ci IP_SET_TYPE_VAL(netif->netmask, IPADDR_TYPE_V4); 620195972f6Sopenharmony_ci mib2_add_route_ip4(0, netif); 621195972f6Sopenharmony_ci 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", 622195972f6Sopenharmony_ci netif->name[0], netif->name[1], 623195972f6Sopenharmony_ci ip4_addr1_16(netif_ip4_netmask(netif)), 624195972f6Sopenharmony_ci ip4_addr2_16(netif_ip4_netmask(netif)), 625195972f6Sopenharmony_ci ip4_addr3_16(netif_ip4_netmask(netif)), 626195972f6Sopenharmony_ci ip4_addr4_16(netif_ip4_netmask(netif)))); 627195972f6Sopenharmony_ci return 1; /* netmask changed */ 628195972f6Sopenharmony_ci } 629195972f6Sopenharmony_ci return 0; /* netmask unchanged */ 630195972f6Sopenharmony_ci} 631195972f6Sopenharmony_ci 632195972f6Sopenharmony_ci/** 633195972f6Sopenharmony_ci * @ingroup netif_ip4 634195972f6Sopenharmony_ci * Change the netmask of a network interface 635195972f6Sopenharmony_ci * 636195972f6Sopenharmony_ci * @param netif the network interface to change 637195972f6Sopenharmony_ci * @param netmask the new netmask 638195972f6Sopenharmony_ci * 639195972f6Sopenharmony_ci * @note call netif_set_addr() if you also want to change ip address and 640195972f6Sopenharmony_ci * default gateway 641195972f6Sopenharmony_ci */ 642195972f6Sopenharmony_civoid 643195972f6Sopenharmony_cinetif_set_netmask(struct netif *netif, const ip4_addr_t *netmask) 644195972f6Sopenharmony_ci{ 645195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 646195972f6Sopenharmony_ci ip_addr_t old_nm_val; 647195972f6Sopenharmony_ci ip_addr_t *old_nm = &old_nm_val; 648195972f6Sopenharmony_ci#else 649195972f6Sopenharmony_ci ip_addr_t *old_nm = NULL; 650195972f6Sopenharmony_ci#endif 651195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 652195972f6Sopenharmony_ci 653195972f6Sopenharmony_ci LWIP_ERROR("netif_set_netmask: invalid netif", netif != NULL, return); 654195972f6Sopenharmony_ci 655195972f6Sopenharmony_ci /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ 656195972f6Sopenharmony_ci if (netmask == NULL) { 657195972f6Sopenharmony_ci netmask = IP4_ADDR_ANY4; 658195972f6Sopenharmony_ci } 659195972f6Sopenharmony_ci 660195972f6Sopenharmony_ci if (netif_do_set_netmask(netif, netmask, old_nm)) { 661195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 662195972f6Sopenharmony_ci netif_ext_callback_args_t args; 663195972f6Sopenharmony_ci args.ipv4_changed.old_netmask = old_nm; 664195972f6Sopenharmony_ci netif_invoke_ext_callback(netif, LWIP_NSC_IPV4_NETMASK_CHANGED, &args); 665195972f6Sopenharmony_ci#endif 666195972f6Sopenharmony_ci } 667195972f6Sopenharmony_ci} 668195972f6Sopenharmony_ci 669195972f6Sopenharmony_cistatic int 670195972f6Sopenharmony_cinetif_do_set_gw(struct netif *netif, const ip4_addr_t *gw, ip_addr_t *old_gw) 671195972f6Sopenharmony_ci{ 672195972f6Sopenharmony_ci /* address is actually being changed? */ 673195972f6Sopenharmony_ci if (ip4_addr_cmp(gw, netif_ip4_gw(netif)) == 0) { 674195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 675195972f6Sopenharmony_ci LWIP_ASSERT("invalid pointer", old_gw != NULL); 676195972f6Sopenharmony_ci ip_addr_copy(*old_gw, *netif_ip_gw4(netif)); 677195972f6Sopenharmony_ci#else 678195972f6Sopenharmony_ci LWIP_UNUSED_ARG(old_gw); 679195972f6Sopenharmony_ci#endif 680195972f6Sopenharmony_ci 681195972f6Sopenharmony_ci ip4_addr_set(ip_2_ip4(&netif->gw), gw); 682195972f6Sopenharmony_ci IP_SET_TYPE_VAL(netif->gw, IPADDR_TYPE_V4); 683195972f6Sopenharmony_ci 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", 684195972f6Sopenharmony_ci netif->name[0], netif->name[1], 685195972f6Sopenharmony_ci ip4_addr1_16(netif_ip4_gw(netif)), 686195972f6Sopenharmony_ci ip4_addr2_16(netif_ip4_gw(netif)), 687195972f6Sopenharmony_ci ip4_addr3_16(netif_ip4_gw(netif)), 688195972f6Sopenharmony_ci ip4_addr4_16(netif_ip4_gw(netif)))); 689195972f6Sopenharmony_ci return 1; /* gateway changed */ 690195972f6Sopenharmony_ci } 691195972f6Sopenharmony_ci return 0; /* gateway unchanged */ 692195972f6Sopenharmony_ci} 693195972f6Sopenharmony_ci 694195972f6Sopenharmony_ci/** 695195972f6Sopenharmony_ci * @ingroup netif_ip4 696195972f6Sopenharmony_ci * Change the default gateway for a network interface 697195972f6Sopenharmony_ci * 698195972f6Sopenharmony_ci * @param netif the network interface to change 699195972f6Sopenharmony_ci * @param gw the new default gateway 700195972f6Sopenharmony_ci * 701195972f6Sopenharmony_ci * @note call netif_set_addr() if you also want to change ip address and netmask 702195972f6Sopenharmony_ci */ 703195972f6Sopenharmony_civoid 704195972f6Sopenharmony_cinetif_set_gw(struct netif *netif, const ip4_addr_t *gw) 705195972f6Sopenharmony_ci{ 706195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 707195972f6Sopenharmony_ci ip_addr_t old_gw_val; 708195972f6Sopenharmony_ci ip_addr_t *old_gw = &old_gw_val; 709195972f6Sopenharmony_ci#else 710195972f6Sopenharmony_ci ip_addr_t *old_gw = NULL; 711195972f6Sopenharmony_ci#endif 712195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 713195972f6Sopenharmony_ci 714195972f6Sopenharmony_ci LWIP_ERROR("netif_set_gw: invalid netif", netif != NULL, return); 715195972f6Sopenharmony_ci 716195972f6Sopenharmony_ci /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ 717195972f6Sopenharmony_ci if (gw == NULL) { 718195972f6Sopenharmony_ci gw = IP4_ADDR_ANY4; 719195972f6Sopenharmony_ci } 720195972f6Sopenharmony_ci 721195972f6Sopenharmony_ci if (netif_do_set_gw(netif, gw, old_gw)) { 722195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 723195972f6Sopenharmony_ci netif_ext_callback_args_t args; 724195972f6Sopenharmony_ci args.ipv4_changed.old_gw = old_gw; 725195972f6Sopenharmony_ci netif_invoke_ext_callback(netif, LWIP_NSC_IPV4_GATEWAY_CHANGED, &args); 726195972f6Sopenharmony_ci#endif 727195972f6Sopenharmony_ci } 728195972f6Sopenharmony_ci} 729195972f6Sopenharmony_ci 730195972f6Sopenharmony_ci/** 731195972f6Sopenharmony_ci * @ingroup netif_ip4 732195972f6Sopenharmony_ci * Change IP address configuration for a network interface (including netmask 733195972f6Sopenharmony_ci * and default gateway). 734195972f6Sopenharmony_ci * 735195972f6Sopenharmony_ci * @param netif the network interface to change 736195972f6Sopenharmony_ci * @param ipaddr the new IP address 737195972f6Sopenharmony_ci * @param netmask the new netmask 738195972f6Sopenharmony_ci * @param gw the new default gateway 739195972f6Sopenharmony_ci */ 740195972f6Sopenharmony_civoid 741195972f6Sopenharmony_cinetif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, 742195972f6Sopenharmony_ci const ip4_addr_t *gw) 743195972f6Sopenharmony_ci{ 744195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 745195972f6Sopenharmony_ci netif_nsc_reason_t change_reason = LWIP_NSC_NONE; 746195972f6Sopenharmony_ci netif_ext_callback_args_t cb_args; 747195972f6Sopenharmony_ci ip_addr_t old_nm_val; 748195972f6Sopenharmony_ci ip_addr_t old_gw_val; 749195972f6Sopenharmony_ci ip_addr_t *old_nm = &old_nm_val; 750195972f6Sopenharmony_ci ip_addr_t *old_gw = &old_gw_val; 751195972f6Sopenharmony_ci#else 752195972f6Sopenharmony_ci ip_addr_t *old_nm = NULL; 753195972f6Sopenharmony_ci ip_addr_t *old_gw = NULL; 754195972f6Sopenharmony_ci#endif 755195972f6Sopenharmony_ci ip_addr_t old_addr; 756195972f6Sopenharmony_ci int remove; 757195972f6Sopenharmony_ci 758195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 759195972f6Sopenharmony_ci 760195972f6Sopenharmony_ci /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ 761195972f6Sopenharmony_ci if (ipaddr == NULL) { 762195972f6Sopenharmony_ci ipaddr = IP4_ADDR_ANY4; 763195972f6Sopenharmony_ci } 764195972f6Sopenharmony_ci if (netmask == NULL) { 765195972f6Sopenharmony_ci netmask = IP4_ADDR_ANY4; 766195972f6Sopenharmony_ci } 767195972f6Sopenharmony_ci if (gw == NULL) { 768195972f6Sopenharmony_ci gw = IP4_ADDR_ANY4; 769195972f6Sopenharmony_ci } 770195972f6Sopenharmony_ci 771195972f6Sopenharmony_ci remove = ip4_addr_isany(ipaddr); 772195972f6Sopenharmony_ci if (remove) { 773195972f6Sopenharmony_ci /* when removing an address, we have to remove it *before* changing netmask/gw 774195972f6Sopenharmony_ci to ensure that tcp RST segment can be sent correctly */ 775195972f6Sopenharmony_ci if (netif_do_set_ipaddr(netif, ipaddr, &old_addr)) { 776195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 777195972f6Sopenharmony_ci change_reason |= LWIP_NSC_IPV4_ADDRESS_CHANGED; 778195972f6Sopenharmony_ci cb_args.ipv4_changed.old_address = &old_addr; 779195972f6Sopenharmony_ci#endif 780195972f6Sopenharmony_ci } 781195972f6Sopenharmony_ci } 782195972f6Sopenharmony_ci if (netif_do_set_netmask(netif, netmask, old_nm)) { 783195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 784195972f6Sopenharmony_ci change_reason |= LWIP_NSC_IPV4_NETMASK_CHANGED; 785195972f6Sopenharmony_ci cb_args.ipv4_changed.old_netmask = old_nm; 786195972f6Sopenharmony_ci#endif 787195972f6Sopenharmony_ci } 788195972f6Sopenharmony_ci if (netif_do_set_gw(netif, gw, old_gw)) { 789195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 790195972f6Sopenharmony_ci change_reason |= LWIP_NSC_IPV4_GATEWAY_CHANGED; 791195972f6Sopenharmony_ci cb_args.ipv4_changed.old_gw = old_gw; 792195972f6Sopenharmony_ci#endif 793195972f6Sopenharmony_ci } 794195972f6Sopenharmony_ci if (!remove) { 795195972f6Sopenharmony_ci /* set ipaddr last to ensure netmask/gw have been set when status callback is called */ 796195972f6Sopenharmony_ci if (netif_do_set_ipaddr(netif, ipaddr, &old_addr)) { 797195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 798195972f6Sopenharmony_ci change_reason |= LWIP_NSC_IPV4_ADDRESS_CHANGED; 799195972f6Sopenharmony_ci cb_args.ipv4_changed.old_address = &old_addr; 800195972f6Sopenharmony_ci#endif 801195972f6Sopenharmony_ci } 802195972f6Sopenharmony_ci } 803195972f6Sopenharmony_ci 804195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 805195972f6Sopenharmony_ci if (change_reason != LWIP_NSC_NONE) { 806195972f6Sopenharmony_ci change_reason |= LWIP_NSC_IPV4_SETTINGS_CHANGED; 807195972f6Sopenharmony_ci netif_invoke_ext_callback(netif, change_reason, &cb_args); 808195972f6Sopenharmony_ci } 809195972f6Sopenharmony_ci#endif 810195972f6Sopenharmony_ci} 811195972f6Sopenharmony_ci#endif /* LWIP_IPV4*/ 812195972f6Sopenharmony_ci 813195972f6Sopenharmony_ci/** 814195972f6Sopenharmony_ci * @ingroup netif 815195972f6Sopenharmony_ci * Remove a network interface from the list of lwIP netifs. 816195972f6Sopenharmony_ci * 817195972f6Sopenharmony_ci * @param netif the network interface to remove 818195972f6Sopenharmony_ci */ 819195972f6Sopenharmony_civoid 820195972f6Sopenharmony_cinetif_remove(struct netif *netif) 821195972f6Sopenharmony_ci{ 822195972f6Sopenharmony_ci#if LWIP_IPV6 823195972f6Sopenharmony_ci int i; 824195972f6Sopenharmony_ci#endif 825195972f6Sopenharmony_ci 826195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 827195972f6Sopenharmony_ci 828195972f6Sopenharmony_ci if (netif == NULL) { 829195972f6Sopenharmony_ci return; 830195972f6Sopenharmony_ci } 831195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 832195972f6Sopenharmony_ci struct net_group *group = get_net_group_from_netif(netif); 833195972f6Sopenharmony_ci 834195972f6Sopenharmony_ci if (group == NULL) { 835195972f6Sopenharmony_ci return; 836195972f6Sopenharmony_ci } 837195972f6Sopenharmony_ci#endif 838195972f6Sopenharmony_ci netif_invoke_ext_callback(netif, LWIP_NSC_NETIF_REMOVED, NULL); 839195972f6Sopenharmony_ci 840195972f6Sopenharmony_ci#if LWIP_IPV4 841195972f6Sopenharmony_ci if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { 842195972f6Sopenharmony_ci netif_do_ip_addr_changed(netif_ip_addr4(netif), NULL); 843195972f6Sopenharmony_ci } 844195972f6Sopenharmony_ci 845195972f6Sopenharmony_ci#if LWIP_IGMP 846195972f6Sopenharmony_ci /* stop IGMP processing */ 847195972f6Sopenharmony_ci if (netif->flags & NETIF_FLAG_IGMP) { 848195972f6Sopenharmony_ci igmp_stop(netif); 849195972f6Sopenharmony_ci } 850195972f6Sopenharmony_ci#endif /* LWIP_IGMP */ 851195972f6Sopenharmony_ci#endif /* LWIP_IPV4*/ 852195972f6Sopenharmony_ci 853195972f6Sopenharmony_ci#if LWIP_IPV6 854195972f6Sopenharmony_ci for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 855195972f6Sopenharmony_ci if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { 856195972f6Sopenharmony_ci netif_do_ip_addr_changed(netif_ip_addr6(netif, i), NULL); 857195972f6Sopenharmony_ci } 858195972f6Sopenharmony_ci } 859195972f6Sopenharmony_ci#if LWIP_IPV6_MLD 860195972f6Sopenharmony_ci /* stop MLD processing */ 861195972f6Sopenharmony_ci mld6_stop(netif); 862195972f6Sopenharmony_ci#endif /* LWIP_IPV6_MLD */ 863195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 864195972f6Sopenharmony_ci if (netif_is_up(netif)) { 865195972f6Sopenharmony_ci /* set netif down before removing (call callback function) */ 866195972f6Sopenharmony_ci netif_set_down(netif); 867195972f6Sopenharmony_ci } 868195972f6Sopenharmony_ci 869195972f6Sopenharmony_ci mib2_remove_ip4(netif); 870195972f6Sopenharmony_ci 871195972f6Sopenharmony_ci /* this netif is default? */ 872195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 873195972f6Sopenharmony_ci if (group->netif_default == netif) { 874195972f6Sopenharmony_ci#else 875195972f6Sopenharmony_ci if (netif_default == netif) { 876195972f6Sopenharmony_ci#endif 877195972f6Sopenharmony_ci /* reset default netif */ 878195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 879195972f6Sopenharmony_ci netif_set_default(NULL, group); 880195972f6Sopenharmony_ci#else 881195972f6Sopenharmony_ci netif_set_default(NULL); 882195972f6Sopenharmony_ci#endif 883195972f6Sopenharmony_ci } 884195972f6Sopenharmony_ci#if !LWIP_SINGLE_NETIF 885195972f6Sopenharmony_ci /* is it the first netif? */ 886195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 887195972f6Sopenharmony_ci if (group->netif_list == netif) { 888195972f6Sopenharmony_ci group->netif_list = netif->next; 889195972f6Sopenharmony_ci#else 890195972f6Sopenharmony_ci if (netif_list == netif) { 891195972f6Sopenharmony_ci netif_list = netif->next; 892195972f6Sopenharmony_ci#endif 893195972f6Sopenharmony_ci } else { 894195972f6Sopenharmony_ci /* look for netif further down the list */ 895195972f6Sopenharmony_ci struct netif *tmp_netif; 896195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 897195972f6Sopenharmony_ci NETIF_FOREACH(tmp_netif, group) { 898195972f6Sopenharmony_ci#else 899195972f6Sopenharmony_ci NETIF_FOREACH(tmp_netif) { 900195972f6Sopenharmony_ci#endif 901195972f6Sopenharmony_ci if (tmp_netif->next == netif) { 902195972f6Sopenharmony_ci tmp_netif->next = netif->next; 903195972f6Sopenharmony_ci break; 904195972f6Sopenharmony_ci } 905195972f6Sopenharmony_ci } 906195972f6Sopenharmony_ci if (tmp_netif == NULL) { 907195972f6Sopenharmony_ci return; /* netif is not on the list */ 908195972f6Sopenharmony_ci } 909195972f6Sopenharmony_ci } 910195972f6Sopenharmony_ci#endif /* !LWIP_SINGLE_NETIF */ 911195972f6Sopenharmony_ci mib2_netif_removed(netif); 912195972f6Sopenharmony_ci#if LWIP_NETIF_REMOVE_CALLBACK 913195972f6Sopenharmony_ci if (netif->remove_callback) { 914195972f6Sopenharmony_ci netif->remove_callback(netif); 915195972f6Sopenharmony_ci } 916195972f6Sopenharmony_ci#endif /* LWIP_NETIF_REMOVE_CALLBACK */ 917195972f6Sopenharmony_ci LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); 918195972f6Sopenharmony_ci} 919195972f6Sopenharmony_ci 920195972f6Sopenharmony_ci/** 921195972f6Sopenharmony_ci * @ingroup netif 922195972f6Sopenharmony_ci * Set a network interface as the default network interface 923195972f6Sopenharmony_ci * (used to output all packets for which no specific route is found) 924195972f6Sopenharmony_ci * 925195972f6Sopenharmony_ci * @param netif the default network interface 926195972f6Sopenharmony_ci */ 927195972f6Sopenharmony_civoid 928195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 929195972f6Sopenharmony_cinetif_set_default(struct netif *netif, struct net_group *group) 930195972f6Sopenharmony_ci#else 931195972f6Sopenharmony_cinetif_set_default(struct netif *netif) 932195972f6Sopenharmony_ci#endif 933195972f6Sopenharmony_ci{ 934195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 935195972f6Sopenharmony_ci 936195972f6Sopenharmony_ci if (netif == NULL) { 937195972f6Sopenharmony_ci /* remove default route */ 938195972f6Sopenharmony_ci mib2_remove_route_ip4(1, netif); 939195972f6Sopenharmony_ci } else { 940195972f6Sopenharmony_ci /* install default route */ 941195972f6Sopenharmony_ci mib2_add_route_ip4(1, netif); 942195972f6Sopenharmony_ci } 943195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 944195972f6Sopenharmony_ci group->netif_default = netif; 945195972f6Sopenharmony_ci#else 946195972f6Sopenharmony_ci netif_default = netif; 947195972f6Sopenharmony_ci#endif 948195972f6Sopenharmony_ci LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", 949195972f6Sopenharmony_ci netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); 950195972f6Sopenharmony_ci} 951195972f6Sopenharmony_ci 952195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 953195972f6Sopenharmony_civoid 954195972f6Sopenharmony_cinetif_set_default2(struct netif *netif) 955195972f6Sopenharmony_ci{ 956195972f6Sopenharmony_ci netif_set_default(netif, get_curr_process_net_group()); 957195972f6Sopenharmony_ci} 958195972f6Sopenharmony_ci#endif 959195972f6Sopenharmony_ci/** 960195972f6Sopenharmony_ci * @ingroup netif 961195972f6Sopenharmony_ci * Bring an interface up, available for processing 962195972f6Sopenharmony_ci * traffic. 963195972f6Sopenharmony_ci */ 964195972f6Sopenharmony_civoid 965195972f6Sopenharmony_cinetif_set_up(struct netif *netif) 966195972f6Sopenharmony_ci{ 967195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 968195972f6Sopenharmony_ci 969195972f6Sopenharmony_ci LWIP_ERROR("netif_set_up: invalid netif", netif != NULL, return); 970195972f6Sopenharmony_ci 971195972f6Sopenharmony_ci if (!(netif->flags & NETIF_FLAG_UP)) { 972195972f6Sopenharmony_ci netif_set_flags(netif, NETIF_FLAG_UP); 973195972f6Sopenharmony_ci 974195972f6Sopenharmony_ci MIB2_COPY_SYSUPTIME_TO(&netif->ts); 975195972f6Sopenharmony_ci 976195972f6Sopenharmony_ci NETIF_STATUS_CALLBACK(netif); 977195972f6Sopenharmony_ci 978195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 979195972f6Sopenharmony_ci { 980195972f6Sopenharmony_ci netif_ext_callback_args_t args; 981195972f6Sopenharmony_ci args.status_changed.state = 1; 982195972f6Sopenharmony_ci netif_invoke_ext_callback(netif, LWIP_NSC_STATUS_CHANGED, &args); 983195972f6Sopenharmony_ci } 984195972f6Sopenharmony_ci#endif 985195972f6Sopenharmony_ci 986195972f6Sopenharmony_ci netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4 | NETIF_REPORT_TYPE_IPV6); 987195972f6Sopenharmony_ci#if LWIP_IPV6 988195972f6Sopenharmony_ci nd6_restart_netif(netif); 989195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 990195972f6Sopenharmony_ci } 991195972f6Sopenharmony_ci} 992195972f6Sopenharmony_ci 993195972f6Sopenharmony_ci/** Send ARP/IGMP/MLD/RS events, e.g. on link-up/netif-up or addr-change 994195972f6Sopenharmony_ci */ 995195972f6Sopenharmony_cistatic void 996195972f6Sopenharmony_cinetif_issue_reports(struct netif *netif, u8_t report_type) 997195972f6Sopenharmony_ci{ 998195972f6Sopenharmony_ci LWIP_ASSERT("netif_issue_reports: invalid netif", netif != NULL); 999195972f6Sopenharmony_ci 1000195972f6Sopenharmony_ci /* Only send reports when both link and admin states are up */ 1001195972f6Sopenharmony_ci if (!(netif->flags & NETIF_FLAG_LINK_UP) || 1002195972f6Sopenharmony_ci !(netif->flags & NETIF_FLAG_UP)) { 1003195972f6Sopenharmony_ci return; 1004195972f6Sopenharmony_ci } 1005195972f6Sopenharmony_ci 1006195972f6Sopenharmony_ci#if LWIP_IPV4 1007195972f6Sopenharmony_ci if ((report_type & NETIF_REPORT_TYPE_IPV4) && 1008195972f6Sopenharmony_ci !ip4_addr_isany_val(*netif_ip4_addr(netif))) { 1009195972f6Sopenharmony_ci#if LWIP_ARP 1010195972f6Sopenharmony_ci /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ 1011195972f6Sopenharmony_ci if (netif->flags & (NETIF_FLAG_ETHARP)) { 1012195972f6Sopenharmony_ci etharp_gratuitous(netif); 1013195972f6Sopenharmony_ci } 1014195972f6Sopenharmony_ci#endif /* LWIP_ARP */ 1015195972f6Sopenharmony_ci 1016195972f6Sopenharmony_ci#if LWIP_IGMP 1017195972f6Sopenharmony_ci /* resend IGMP memberships */ 1018195972f6Sopenharmony_ci if (netif->flags & NETIF_FLAG_IGMP) { 1019195972f6Sopenharmony_ci igmp_report_groups(netif); 1020195972f6Sopenharmony_ci } 1021195972f6Sopenharmony_ci#endif /* LWIP_IGMP */ 1022195972f6Sopenharmony_ci } 1023195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 1024195972f6Sopenharmony_ci 1025195972f6Sopenharmony_ci#if LWIP_IPV6 1026195972f6Sopenharmony_ci if (report_type & NETIF_REPORT_TYPE_IPV6) { 1027195972f6Sopenharmony_ci#if LWIP_IPV6_MLD 1028195972f6Sopenharmony_ci /* send mld memberships */ 1029195972f6Sopenharmony_ci mld6_report_groups(netif); 1030195972f6Sopenharmony_ci#endif /* LWIP_IPV6_MLD */ 1031195972f6Sopenharmony_ci } 1032195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 1033195972f6Sopenharmony_ci} 1034195972f6Sopenharmony_ci 1035195972f6Sopenharmony_ci/** 1036195972f6Sopenharmony_ci * @ingroup netif 1037195972f6Sopenharmony_ci * Bring an interface down, disabling any traffic processing. 1038195972f6Sopenharmony_ci */ 1039195972f6Sopenharmony_civoid 1040195972f6Sopenharmony_cinetif_set_down(struct netif *netif) 1041195972f6Sopenharmony_ci{ 1042195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 1043195972f6Sopenharmony_ci 1044195972f6Sopenharmony_ci LWIP_ERROR("netif_set_down: invalid netif", netif != NULL, return); 1045195972f6Sopenharmony_ci 1046195972f6Sopenharmony_ci if (netif->flags & NETIF_FLAG_UP) { 1047195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 1048195972f6Sopenharmony_ci { 1049195972f6Sopenharmony_ci netif_ext_callback_args_t args; 1050195972f6Sopenharmony_ci args.status_changed.state = 0; 1051195972f6Sopenharmony_ci netif_invoke_ext_callback(netif, LWIP_NSC_STATUS_CHANGED, &args); 1052195972f6Sopenharmony_ci } 1053195972f6Sopenharmony_ci#endif 1054195972f6Sopenharmony_ci 1055195972f6Sopenharmony_ci netif_clear_flags(netif, NETIF_FLAG_UP); 1056195972f6Sopenharmony_ci MIB2_COPY_SYSUPTIME_TO(&netif->ts); 1057195972f6Sopenharmony_ci 1058195972f6Sopenharmony_ci#if LWIP_IPV4 && LWIP_ARP 1059195972f6Sopenharmony_ci if (netif->flags & NETIF_FLAG_ETHARP) { 1060195972f6Sopenharmony_ci etharp_cleanup_netif(netif); 1061195972f6Sopenharmony_ci } 1062195972f6Sopenharmony_ci#endif /* LWIP_IPV4 && LWIP_ARP */ 1063195972f6Sopenharmony_ci 1064195972f6Sopenharmony_ci#if LWIP_IPV6 1065195972f6Sopenharmony_ci nd6_cleanup_netif(netif); 1066195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 1067195972f6Sopenharmony_ci 1068195972f6Sopenharmony_ci NETIF_STATUS_CALLBACK(netif); 1069195972f6Sopenharmony_ci } 1070195972f6Sopenharmony_ci} 1071195972f6Sopenharmony_ci 1072195972f6Sopenharmony_ci#if LWIP_NETIF_STATUS_CALLBACK 1073195972f6Sopenharmony_ci/** 1074195972f6Sopenharmony_ci * @ingroup netif 1075195972f6Sopenharmony_ci * Set callback to be called when interface is brought up/down or address is changed while up 1076195972f6Sopenharmony_ci */ 1077195972f6Sopenharmony_civoid 1078195972f6Sopenharmony_cinetif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback) 1079195972f6Sopenharmony_ci{ 1080195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 1081195972f6Sopenharmony_ci 1082195972f6Sopenharmony_ci if (netif) { 1083195972f6Sopenharmony_ci netif->status_callback = status_callback; 1084195972f6Sopenharmony_ci } 1085195972f6Sopenharmony_ci} 1086195972f6Sopenharmony_ci#endif /* LWIP_NETIF_STATUS_CALLBACK */ 1087195972f6Sopenharmony_ci 1088195972f6Sopenharmony_ci#if LWIP_NETIF_REMOVE_CALLBACK 1089195972f6Sopenharmony_ci/** 1090195972f6Sopenharmony_ci * @ingroup netif 1091195972f6Sopenharmony_ci * Set callback to be called when the interface has been removed 1092195972f6Sopenharmony_ci */ 1093195972f6Sopenharmony_civoid 1094195972f6Sopenharmony_cinetif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback) 1095195972f6Sopenharmony_ci{ 1096195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 1097195972f6Sopenharmony_ci 1098195972f6Sopenharmony_ci if (netif) { 1099195972f6Sopenharmony_ci netif->remove_callback = remove_callback; 1100195972f6Sopenharmony_ci } 1101195972f6Sopenharmony_ci} 1102195972f6Sopenharmony_ci#endif /* LWIP_NETIF_REMOVE_CALLBACK */ 1103195972f6Sopenharmony_ci 1104195972f6Sopenharmony_ci/** 1105195972f6Sopenharmony_ci * @ingroup netif 1106195972f6Sopenharmony_ci * Called by a driver when its link goes up 1107195972f6Sopenharmony_ci */ 1108195972f6Sopenharmony_civoid 1109195972f6Sopenharmony_cinetif_set_link_up(struct netif *netif) 1110195972f6Sopenharmony_ci{ 1111195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 1112195972f6Sopenharmony_ci 1113195972f6Sopenharmony_ci LWIP_ERROR("netif_set_link_up: invalid netif", netif != NULL, return); 1114195972f6Sopenharmony_ci 1115195972f6Sopenharmony_ci if (!(netif->flags & NETIF_FLAG_LINK_UP)) { 1116195972f6Sopenharmony_ci netif_set_flags(netif, NETIF_FLAG_LINK_UP); 1117195972f6Sopenharmony_ci 1118195972f6Sopenharmony_ci#if LWIP_DHCP 1119195972f6Sopenharmony_ci dhcp_network_changed(netif); 1120195972f6Sopenharmony_ci#endif /* LWIP_DHCP */ 1121195972f6Sopenharmony_ci 1122195972f6Sopenharmony_ci#if LWIP_AUTOIP 1123195972f6Sopenharmony_ci autoip_network_changed(netif); 1124195972f6Sopenharmony_ci#endif /* LWIP_AUTOIP */ 1125195972f6Sopenharmony_ci 1126195972f6Sopenharmony_ci netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4 | NETIF_REPORT_TYPE_IPV6); 1127195972f6Sopenharmony_ci#if LWIP_IPV6 1128195972f6Sopenharmony_ci nd6_restart_netif(netif); 1129195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 1130195972f6Sopenharmony_ci 1131195972f6Sopenharmony_ci NETIF_LINK_CALLBACK(netif); 1132195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 1133195972f6Sopenharmony_ci { 1134195972f6Sopenharmony_ci netif_ext_callback_args_t args; 1135195972f6Sopenharmony_ci args.link_changed.state = 1; 1136195972f6Sopenharmony_ci netif_invoke_ext_callback(netif, LWIP_NSC_LINK_CHANGED, &args); 1137195972f6Sopenharmony_ci } 1138195972f6Sopenharmony_ci#endif 1139195972f6Sopenharmony_ci } 1140195972f6Sopenharmony_ci} 1141195972f6Sopenharmony_ci 1142195972f6Sopenharmony_ci/** 1143195972f6Sopenharmony_ci * @ingroup netif 1144195972f6Sopenharmony_ci * Called by a driver when its link goes down 1145195972f6Sopenharmony_ci */ 1146195972f6Sopenharmony_civoid 1147195972f6Sopenharmony_cinetif_set_link_down(struct netif *netif) 1148195972f6Sopenharmony_ci{ 1149195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 1150195972f6Sopenharmony_ci 1151195972f6Sopenharmony_ci LWIP_ERROR("netif_set_link_down: invalid netif", netif != NULL, return); 1152195972f6Sopenharmony_ci 1153195972f6Sopenharmony_ci if (netif->flags & NETIF_FLAG_LINK_UP) { 1154195972f6Sopenharmony_ci netif_clear_flags(netif, NETIF_FLAG_LINK_UP); 1155195972f6Sopenharmony_ci#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES 1156195972f6Sopenharmony_ci netif->mtu6 = netif->mtu; 1157195972f6Sopenharmony_ci#endif 1158195972f6Sopenharmony_ci 1159195972f6Sopenharmony_ci NETIF_LINK_CALLBACK(netif); 1160195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 1161195972f6Sopenharmony_ci { 1162195972f6Sopenharmony_ci netif_ext_callback_args_t args; 1163195972f6Sopenharmony_ci args.link_changed.state = 0; 1164195972f6Sopenharmony_ci netif_invoke_ext_callback(netif, LWIP_NSC_LINK_CHANGED, &args); 1165195972f6Sopenharmony_ci } 1166195972f6Sopenharmony_ci#endif 1167195972f6Sopenharmony_ci } 1168195972f6Sopenharmony_ci} 1169195972f6Sopenharmony_ci 1170195972f6Sopenharmony_ci#if LWIP_NETIF_LINK_CALLBACK 1171195972f6Sopenharmony_ci/** 1172195972f6Sopenharmony_ci * @ingroup netif 1173195972f6Sopenharmony_ci * Set callback to be called when link is brought up/down 1174195972f6Sopenharmony_ci */ 1175195972f6Sopenharmony_civoid 1176195972f6Sopenharmony_cinetif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback) 1177195972f6Sopenharmony_ci{ 1178195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 1179195972f6Sopenharmony_ci 1180195972f6Sopenharmony_ci if (netif) { 1181195972f6Sopenharmony_ci netif->link_callback = link_callback; 1182195972f6Sopenharmony_ci } 1183195972f6Sopenharmony_ci} 1184195972f6Sopenharmony_ci#endif /* LWIP_NETIF_LINK_CALLBACK */ 1185195972f6Sopenharmony_ci 1186195972f6Sopenharmony_ci#if ENABLE_LOOPBACK 1187195972f6Sopenharmony_ci/** 1188195972f6Sopenharmony_ci * @ingroup netif 1189195972f6Sopenharmony_ci * Send an IP packet to be received on the same netif (loopif-like). 1190195972f6Sopenharmony_ci * The pbuf is copied and added to an internal queue which is fed to 1191195972f6Sopenharmony_ci * netif->input by netif_poll(). 1192195972f6Sopenharmony_ci * In multithreaded mode, the call to netif_poll() is queued to be done on the 1193195972f6Sopenharmony_ci * TCP/IP thread. 1194195972f6Sopenharmony_ci * In callback mode, the user has the responsibility to call netif_poll() in 1195195972f6Sopenharmony_ci * the main loop of their application. 1196195972f6Sopenharmony_ci * 1197195972f6Sopenharmony_ci * @param netif the lwip network interface structure 1198195972f6Sopenharmony_ci * @param p the (IP) packet to 'send' 1199195972f6Sopenharmony_ci * @return ERR_OK if the packet has been sent 1200195972f6Sopenharmony_ci * ERR_MEM if the pbuf used to copy the packet couldn't be allocated 1201195972f6Sopenharmony_ci */ 1202195972f6Sopenharmony_cierr_t 1203195972f6Sopenharmony_cinetif_loop_output(struct netif *netif, struct pbuf *p) 1204195972f6Sopenharmony_ci{ 1205195972f6Sopenharmony_ci struct pbuf *r; 1206195972f6Sopenharmony_ci err_t err; 1207195972f6Sopenharmony_ci struct pbuf *last; 1208195972f6Sopenharmony_ci#if LWIP_LOOPBACK_MAX_PBUFS 1209195972f6Sopenharmony_ci u16_t clen = 0; 1210195972f6Sopenharmony_ci#endif /* LWIP_LOOPBACK_MAX_PBUFS */ 1211195972f6Sopenharmony_ci /* If we have a loopif, SNMP counters are adjusted for it, 1212195972f6Sopenharmony_ci * if not they are adjusted for 'netif'. */ 1213195972f6Sopenharmony_ci#if MIB2_STATS 1214195972f6Sopenharmony_ci#if LWIP_HAVE_LOOPIF 1215195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 1216195972f6Sopenharmony_ci struct netif *stats_if = get_net_group_from_netif(netif)->loop_netif; 1217195972f6Sopenharmony_ci#else 1218195972f6Sopenharmony_ci struct netif *stats_if = &loop_netif; 1219195972f6Sopenharmony_ci#endif 1220195972f6Sopenharmony_ci#else /* LWIP_HAVE_LOOPIF */ 1221195972f6Sopenharmony_ci struct netif *stats_if = netif; 1222195972f6Sopenharmony_ci#endif /* LWIP_HAVE_LOOPIF */ 1223195972f6Sopenharmony_ci#endif /* MIB2_STATS */ 1224195972f6Sopenharmony_ci#if LWIP_NETIF_LOOPBACK_MULTITHREADING 1225195972f6Sopenharmony_ci u8_t schedule_poll = 0; 1226195972f6Sopenharmony_ci#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 1227195972f6Sopenharmony_ci SYS_ARCH_DECL_PROTECT(lev); 1228195972f6Sopenharmony_ci 1229195972f6Sopenharmony_ci LWIP_ASSERT("netif_loop_output: invalid netif", netif != NULL); 1230195972f6Sopenharmony_ci LWIP_ASSERT("netif_loop_output: invalid pbuf", p != NULL); 1231195972f6Sopenharmony_ci 1232195972f6Sopenharmony_ci /* Allocate a new pbuf */ 1233195972f6Sopenharmony_ci r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); 1234195972f6Sopenharmony_ci if (r == NULL) { 1235195972f6Sopenharmony_ci LINK_STATS_INC(link.memerr); 1236195972f6Sopenharmony_ci LINK_STATS_INC(link.drop); 1237195972f6Sopenharmony_ci MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); 1238195972f6Sopenharmony_ci return ERR_MEM; 1239195972f6Sopenharmony_ci } 1240195972f6Sopenharmony_ci#if LWIP_LOOPBACK_MAX_PBUFS 1241195972f6Sopenharmony_ci clen = pbuf_clen(r); 1242195972f6Sopenharmony_ci /* check for overflow or too many pbuf on queue */ 1243195972f6Sopenharmony_ci if (((netif->loop_cnt_current + clen) < netif->loop_cnt_current) || 1244195972f6Sopenharmony_ci ((netif->loop_cnt_current + clen) > LWIP_MIN(LWIP_LOOPBACK_MAX_PBUFS, 0xFFFF))) { 1245195972f6Sopenharmony_ci pbuf_free(r); 1246195972f6Sopenharmony_ci LINK_STATS_INC(link.memerr); 1247195972f6Sopenharmony_ci LINK_STATS_INC(link.drop); 1248195972f6Sopenharmony_ci MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); 1249195972f6Sopenharmony_ci return ERR_MEM; 1250195972f6Sopenharmony_ci } 1251195972f6Sopenharmony_ci netif->loop_cnt_current = (u16_t)(netif->loop_cnt_current + clen); 1252195972f6Sopenharmony_ci#endif /* LWIP_LOOPBACK_MAX_PBUFS */ 1253195972f6Sopenharmony_ci 1254195972f6Sopenharmony_ci /* Copy the whole pbuf queue p into the single pbuf r */ 1255195972f6Sopenharmony_ci if ((err = pbuf_copy(r, p)) != ERR_OK) { 1256195972f6Sopenharmony_ci pbuf_free(r); 1257195972f6Sopenharmony_ci LINK_STATS_INC(link.memerr); 1258195972f6Sopenharmony_ci LINK_STATS_INC(link.drop); 1259195972f6Sopenharmony_ci MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); 1260195972f6Sopenharmony_ci return err; 1261195972f6Sopenharmony_ci } 1262195972f6Sopenharmony_ci 1263195972f6Sopenharmony_ci /* Put the packet on a linked list which gets emptied through calling 1264195972f6Sopenharmony_ci netif_poll(). */ 1265195972f6Sopenharmony_ci 1266195972f6Sopenharmony_ci /* let last point to the last pbuf in chain r */ 1267195972f6Sopenharmony_ci for (last = r; last->next != NULL; last = last->next) { 1268195972f6Sopenharmony_ci /* nothing to do here, just get to the last pbuf */ 1269195972f6Sopenharmony_ci } 1270195972f6Sopenharmony_ci 1271195972f6Sopenharmony_ci SYS_ARCH_PROTECT(lev); 1272195972f6Sopenharmony_ci if (netif->loop_first != NULL) { 1273195972f6Sopenharmony_ci LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); 1274195972f6Sopenharmony_ci netif->loop_last->next = r; 1275195972f6Sopenharmony_ci netif->loop_last = last; 1276195972f6Sopenharmony_ci#if LWIP_NETIF_LOOPBACK_MULTITHREADING 1277195972f6Sopenharmony_ci if (netif->reschedule_poll) { 1278195972f6Sopenharmony_ci schedule_poll = 1; 1279195972f6Sopenharmony_ci netif->reschedule_poll = 0; 1280195972f6Sopenharmony_ci } 1281195972f6Sopenharmony_ci#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 1282195972f6Sopenharmony_ci } else { 1283195972f6Sopenharmony_ci netif->loop_first = r; 1284195972f6Sopenharmony_ci netif->loop_last = last; 1285195972f6Sopenharmony_ci#if LWIP_NETIF_LOOPBACK_MULTITHREADING 1286195972f6Sopenharmony_ci /* No existing packets queued, schedule poll */ 1287195972f6Sopenharmony_ci schedule_poll = 1; 1288195972f6Sopenharmony_ci#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 1289195972f6Sopenharmony_ci } 1290195972f6Sopenharmony_ci SYS_ARCH_UNPROTECT(lev); 1291195972f6Sopenharmony_ci 1292195972f6Sopenharmony_ci LINK_STATS_INC(link.xmit); 1293195972f6Sopenharmony_ci MIB2_STATS_NETIF_ADD(stats_if, ifoutoctets, p->tot_len); 1294195972f6Sopenharmony_ci MIB2_STATS_NETIF_INC(stats_if, ifoutucastpkts); 1295195972f6Sopenharmony_ci 1296195972f6Sopenharmony_ci#if LWIP_NETIF_LOOPBACK_MULTITHREADING 1297195972f6Sopenharmony_ci /* For multithreading environment, schedule a call to netif_poll */ 1298195972f6Sopenharmony_ci if (schedule_poll) { 1299195972f6Sopenharmony_ci if (tcpip_try_callback((tcpip_callback_fn)netif_poll, netif) != ERR_OK) { 1300195972f6Sopenharmony_ci SYS_ARCH_PROTECT(lev); 1301195972f6Sopenharmony_ci netif->reschedule_poll = 1; 1302195972f6Sopenharmony_ci SYS_ARCH_UNPROTECT(lev); 1303195972f6Sopenharmony_ci } 1304195972f6Sopenharmony_ci } 1305195972f6Sopenharmony_ci#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 1306195972f6Sopenharmony_ci 1307195972f6Sopenharmony_ci return ERR_OK; 1308195972f6Sopenharmony_ci} 1309195972f6Sopenharmony_ci 1310195972f6Sopenharmony_ci#if LWIP_HAVE_LOOPIF 1311195972f6Sopenharmony_ci#if LWIP_IPV4 1312195972f6Sopenharmony_cistatic err_t 1313195972f6Sopenharmony_cinetif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) 1314195972f6Sopenharmony_ci{ 1315195972f6Sopenharmony_ci LWIP_UNUSED_ARG(addr); 1316195972f6Sopenharmony_ci return netif_loop_output(netif, p); 1317195972f6Sopenharmony_ci} 1318195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 1319195972f6Sopenharmony_ci 1320195972f6Sopenharmony_ci#if LWIP_IPV6 1321195972f6Sopenharmony_cistatic err_t 1322195972f6Sopenharmony_cinetif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr) 1323195972f6Sopenharmony_ci{ 1324195972f6Sopenharmony_ci LWIP_UNUSED_ARG(addr); 1325195972f6Sopenharmony_ci return netif_loop_output(netif, p); 1326195972f6Sopenharmony_ci} 1327195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 1328195972f6Sopenharmony_ci#endif /* LWIP_HAVE_LOOPIF */ 1329195972f6Sopenharmony_ci 1330195972f6Sopenharmony_ci 1331195972f6Sopenharmony_ci/** 1332195972f6Sopenharmony_ci * Call netif_poll() in the main loop of your application. This is to prevent 1333195972f6Sopenharmony_ci * reentering non-reentrant functions like tcp_input(). Packets passed to 1334195972f6Sopenharmony_ci * netif_loop_output() are put on a list that is passed to netif->input() by 1335195972f6Sopenharmony_ci * netif_poll(). 1336195972f6Sopenharmony_ci */ 1337195972f6Sopenharmony_civoid 1338195972f6Sopenharmony_cinetif_poll(struct netif *netif) 1339195972f6Sopenharmony_ci{ 1340195972f6Sopenharmony_ci /* If we have a loopif, SNMP counters are adjusted for it, 1341195972f6Sopenharmony_ci * if not they are adjusted for 'netif'. */ 1342195972f6Sopenharmony_ci#if MIB2_STATS 1343195972f6Sopenharmony_ci#if LWIP_HAVE_LOOPIF 1344195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 1345195972f6Sopenharmony_ci struct netif *stats_if = get_net_group_from_netif(netif)->loop_netif; 1346195972f6Sopenharmony_ci#else 1347195972f6Sopenharmony_ci struct netif *stats_if = &loop_netif; 1348195972f6Sopenharmony_ci#endif 1349195972f6Sopenharmony_ci#else /* LWIP_HAVE_LOOPIF */ 1350195972f6Sopenharmony_ci struct netif *stats_if = netif; 1351195972f6Sopenharmony_ci#endif /* LWIP_HAVE_LOOPIF */ 1352195972f6Sopenharmony_ci#endif /* MIB2_STATS */ 1353195972f6Sopenharmony_ci SYS_ARCH_DECL_PROTECT(lev); 1354195972f6Sopenharmony_ci 1355195972f6Sopenharmony_ci LWIP_ASSERT("netif_poll: invalid netif", netif != NULL); 1356195972f6Sopenharmony_ci 1357195972f6Sopenharmony_ci /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ 1358195972f6Sopenharmony_ci SYS_ARCH_PROTECT(lev); 1359195972f6Sopenharmony_ci while (netif->loop_first != NULL) { 1360195972f6Sopenharmony_ci struct pbuf *in, *in_end; 1361195972f6Sopenharmony_ci#if LWIP_LOOPBACK_MAX_PBUFS 1362195972f6Sopenharmony_ci u8_t clen = 1; 1363195972f6Sopenharmony_ci#endif /* LWIP_LOOPBACK_MAX_PBUFS */ 1364195972f6Sopenharmony_ci 1365195972f6Sopenharmony_ci in = in_end = netif->loop_first; 1366195972f6Sopenharmony_ci while (in_end->len != in_end->tot_len) { 1367195972f6Sopenharmony_ci LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); 1368195972f6Sopenharmony_ci in_end = in_end->next; 1369195972f6Sopenharmony_ci#if LWIP_LOOPBACK_MAX_PBUFS 1370195972f6Sopenharmony_ci clen++; 1371195972f6Sopenharmony_ci#endif /* LWIP_LOOPBACK_MAX_PBUFS */ 1372195972f6Sopenharmony_ci } 1373195972f6Sopenharmony_ci#if LWIP_LOOPBACK_MAX_PBUFS 1374195972f6Sopenharmony_ci /* adjust the number of pbufs on queue */ 1375195972f6Sopenharmony_ci LWIP_ASSERT("netif->loop_cnt_current underflow", 1376195972f6Sopenharmony_ci ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); 1377195972f6Sopenharmony_ci netif->loop_cnt_current = (u16_t)(netif->loop_cnt_current - clen); 1378195972f6Sopenharmony_ci#endif /* LWIP_LOOPBACK_MAX_PBUFS */ 1379195972f6Sopenharmony_ci 1380195972f6Sopenharmony_ci /* 'in_end' now points to the last pbuf from 'in' */ 1381195972f6Sopenharmony_ci if (in_end == netif->loop_last) { 1382195972f6Sopenharmony_ci /* this was the last pbuf in the list */ 1383195972f6Sopenharmony_ci netif->loop_first = netif->loop_last = NULL; 1384195972f6Sopenharmony_ci } else { 1385195972f6Sopenharmony_ci /* pop the pbuf off the list */ 1386195972f6Sopenharmony_ci netif->loop_first = in_end->next; 1387195972f6Sopenharmony_ci LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL); 1388195972f6Sopenharmony_ci } 1389195972f6Sopenharmony_ci /* De-queue the pbuf from its successors on the 'loop_' list. */ 1390195972f6Sopenharmony_ci in_end->next = NULL; 1391195972f6Sopenharmony_ci SYS_ARCH_UNPROTECT(lev); 1392195972f6Sopenharmony_ci 1393195972f6Sopenharmony_ci in->if_idx = netif_get_index(netif); 1394195972f6Sopenharmony_ci 1395195972f6Sopenharmony_ci LINK_STATS_INC(link.recv); 1396195972f6Sopenharmony_ci MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len); 1397195972f6Sopenharmony_ci MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts); 1398195972f6Sopenharmony_ci /* loopback packets are always IP packets! */ 1399195972f6Sopenharmony_ci if (ip_input(in, netif) != ERR_OK) { 1400195972f6Sopenharmony_ci pbuf_free(in); 1401195972f6Sopenharmony_ci } 1402195972f6Sopenharmony_ci SYS_ARCH_PROTECT(lev); 1403195972f6Sopenharmony_ci } 1404195972f6Sopenharmony_ci SYS_ARCH_UNPROTECT(lev); 1405195972f6Sopenharmony_ci} 1406195972f6Sopenharmony_ci 1407195972f6Sopenharmony_ci#if !LWIP_NETIF_LOOPBACK_MULTITHREADING 1408195972f6Sopenharmony_ci/** 1409195972f6Sopenharmony_ci * Calls netif_poll() for every netif on the netif_list. 1410195972f6Sopenharmony_ci */ 1411195972f6Sopenharmony_civoid 1412195972f6Sopenharmony_cinetif_poll_all(void) 1413195972f6Sopenharmony_ci{ 1414195972f6Sopenharmony_ci struct netif *netif; 1415195972f6Sopenharmony_ci /* loop through netifs */ 1416195972f6Sopenharmony_ci NETIF_FOREACH(netif) { 1417195972f6Sopenharmony_ci netif_poll(netif); 1418195972f6Sopenharmony_ci } 1419195972f6Sopenharmony_ci} 1420195972f6Sopenharmony_ci#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ 1421195972f6Sopenharmony_ci#endif /* ENABLE_LOOPBACK */ 1422195972f6Sopenharmony_ci 1423195972f6Sopenharmony_ci#if LWIP_NUM_NETIF_CLIENT_DATA > 0 1424195972f6Sopenharmony_ci/** 1425195972f6Sopenharmony_ci * @ingroup netif_cd 1426195972f6Sopenharmony_ci * Allocate an index to store data in client_data member of struct netif. 1427195972f6Sopenharmony_ci * Returned value is an index in mentioned array. 1428195972f6Sopenharmony_ci * @see LWIP_NUM_NETIF_CLIENT_DATA 1429195972f6Sopenharmony_ci */ 1430195972f6Sopenharmony_ciu8_t 1431195972f6Sopenharmony_cinetif_alloc_client_data_id(void) 1432195972f6Sopenharmony_ci{ 1433195972f6Sopenharmony_ci u8_t result = netif_client_id; 1434195972f6Sopenharmony_ci netif_client_id++; 1435195972f6Sopenharmony_ci 1436195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 1437195972f6Sopenharmony_ci 1438195972f6Sopenharmony_ci#if LWIP_NUM_NETIF_CLIENT_DATA > 256 1439195972f6Sopenharmony_ci#error LWIP_NUM_NETIF_CLIENT_DATA must be <= 256 1440195972f6Sopenharmony_ci#endif 1441195972f6Sopenharmony_ci LWIP_ASSERT("Increase LWIP_NUM_NETIF_CLIENT_DATA in lwipopts.h", result < LWIP_NUM_NETIF_CLIENT_DATA); 1442195972f6Sopenharmony_ci return (u8_t)(result + LWIP_NETIF_CLIENT_DATA_INDEX_MAX); 1443195972f6Sopenharmony_ci} 1444195972f6Sopenharmony_ci#endif 1445195972f6Sopenharmony_ci 1446195972f6Sopenharmony_ci#if LWIP_IPV6 1447195972f6Sopenharmony_ci/** 1448195972f6Sopenharmony_ci * @ingroup netif_ip6 1449195972f6Sopenharmony_ci * Change an IPv6 address of a network interface 1450195972f6Sopenharmony_ci * 1451195972f6Sopenharmony_ci * @param netif the network interface to change 1452195972f6Sopenharmony_ci * @param addr_idx index of the IPv6 address 1453195972f6Sopenharmony_ci * @param addr6 the new IPv6 address 1454195972f6Sopenharmony_ci * 1455195972f6Sopenharmony_ci * @note call netif_ip6_addr_set_state() to set the address valid/temptative 1456195972f6Sopenharmony_ci */ 1457195972f6Sopenharmony_civoid 1458195972f6Sopenharmony_cinetif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6) 1459195972f6Sopenharmony_ci{ 1460195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 1461195972f6Sopenharmony_ci 1462195972f6Sopenharmony_ci LWIP_ASSERT("netif_ip6_addr_set: invalid netif", netif != NULL); 1463195972f6Sopenharmony_ci LWIP_ASSERT("netif_ip6_addr_set: invalid addr6", addr6 != NULL); 1464195972f6Sopenharmony_ci 1465195972f6Sopenharmony_ci netif_ip6_addr_set_parts(netif, addr_idx, addr6->addr[0], addr6->addr[1], 1466195972f6Sopenharmony_ci addr6->addr[2], addr6->addr[3]); 1467195972f6Sopenharmony_ci} 1468195972f6Sopenharmony_ci 1469195972f6Sopenharmony_ci/* 1470195972f6Sopenharmony_ci * Change an IPv6 address of a network interface (internal version taking 4 * u32_t) 1471195972f6Sopenharmony_ci * 1472195972f6Sopenharmony_ci * @param netif the network interface to change 1473195972f6Sopenharmony_ci * @param addr_idx index of the IPv6 address 1474195972f6Sopenharmony_ci * @param i0 word0 of the new IPv6 address 1475195972f6Sopenharmony_ci * @param i1 word1 of the new IPv6 address 1476195972f6Sopenharmony_ci * @param i2 word2 of the new IPv6 address 1477195972f6Sopenharmony_ci * @param i3 word3 of the new IPv6 address 1478195972f6Sopenharmony_ci */ 1479195972f6Sopenharmony_civoid 1480195972f6Sopenharmony_cinetif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3) 1481195972f6Sopenharmony_ci{ 1482195972f6Sopenharmony_ci ip_addr_t old_addr; 1483195972f6Sopenharmony_ci ip_addr_t new_ipaddr; 1484195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 1485195972f6Sopenharmony_ci LWIP_ASSERT("netif != NULL", netif != NULL); 1486195972f6Sopenharmony_ci LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); 1487195972f6Sopenharmony_ci 1488195972f6Sopenharmony_ci ip6_addr_copy(*ip_2_ip6(&old_addr), *netif_ip6_addr(netif, addr_idx)); 1489195972f6Sopenharmony_ci IP_SET_TYPE_VAL(old_addr, IPADDR_TYPE_V6); 1490195972f6Sopenharmony_ci 1491195972f6Sopenharmony_ci /* address is actually being changed? */ 1492195972f6Sopenharmony_ci if ((ip_2_ip6(&old_addr)->addr[0] != i0) || (ip_2_ip6(&old_addr)->addr[1] != i1) || 1493195972f6Sopenharmony_ci (ip_2_ip6(&old_addr)->addr[2] != i2) || (ip_2_ip6(&old_addr)->addr[3] != i3)) { 1494195972f6Sopenharmony_ci LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set: netif address being changed\n")); 1495195972f6Sopenharmony_ci 1496195972f6Sopenharmony_ci IP_ADDR6(&new_ipaddr, i0, i1, i2, i3); 1497195972f6Sopenharmony_ci ip6_addr_assign_zone(ip_2_ip6(&new_ipaddr), IP6_UNICAST, netif); 1498195972f6Sopenharmony_ci 1499195972f6Sopenharmony_ci if (ip6_addr_isvalid(netif_ip6_addr_state(netif, addr_idx))) { 1500195972f6Sopenharmony_ci netif_do_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); 1501195972f6Sopenharmony_ci } 1502195972f6Sopenharmony_ci /* @todo: remove/readd mib2 ip6 entries? */ 1503195972f6Sopenharmony_ci 1504195972f6Sopenharmony_ci ip_addr_copy(netif->ip6_addr[addr_idx], new_ipaddr); 1505195972f6Sopenharmony_ci 1506195972f6Sopenharmony_ci if (ip6_addr_isvalid(netif_ip6_addr_state(netif, addr_idx))) { 1507195972f6Sopenharmony_ci netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); 1508195972f6Sopenharmony_ci NETIF_STATUS_CALLBACK(netif); 1509195972f6Sopenharmony_ci } 1510195972f6Sopenharmony_ci 1511195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 1512195972f6Sopenharmony_ci { 1513195972f6Sopenharmony_ci netif_ext_callback_args_t args; 1514195972f6Sopenharmony_ci args.ipv6_set.addr_index = addr_idx; 1515195972f6Sopenharmony_ci args.ipv6_set.old_address = &old_addr; 1516195972f6Sopenharmony_ci netif_invoke_ext_callback(netif, LWIP_NSC_IPV6_SET, &args); 1517195972f6Sopenharmony_ci } 1518195972f6Sopenharmony_ci#endif 1519195972f6Sopenharmony_ci } 1520195972f6Sopenharmony_ci 1521195972f6Sopenharmony_ci 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", 1522195972f6Sopenharmony_ci addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), 1523195972f6Sopenharmony_ci netif_ip6_addr_state(netif, addr_idx))); 1524195972f6Sopenharmony_ci} 1525195972f6Sopenharmony_ci 1526195972f6Sopenharmony_ci/** 1527195972f6Sopenharmony_ci * @ingroup netif_ip6 1528195972f6Sopenharmony_ci * Change the state of an IPv6 address of a network interface 1529195972f6Sopenharmony_ci * (INVALID, TEMPTATIVE, PREFERRED, DEPRECATED, where TEMPTATIVE 1530195972f6Sopenharmony_ci * includes the number of checks done, see ip6_addr.h) 1531195972f6Sopenharmony_ci * 1532195972f6Sopenharmony_ci * @param netif the network interface to change 1533195972f6Sopenharmony_ci * @param addr_idx index of the IPv6 address 1534195972f6Sopenharmony_ci * @param state the new IPv6 address state 1535195972f6Sopenharmony_ci */ 1536195972f6Sopenharmony_civoid 1537195972f6Sopenharmony_cinetif_ip6_addr_set_state(struct netif *netif, s8_t addr_idx, u8_t state) 1538195972f6Sopenharmony_ci{ 1539195972f6Sopenharmony_ci u8_t old_state; 1540195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 1541195972f6Sopenharmony_ci LWIP_ASSERT("netif != NULL", netif != NULL); 1542195972f6Sopenharmony_ci LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); 1543195972f6Sopenharmony_ci 1544195972f6Sopenharmony_ci old_state = netif_ip6_addr_state(netif, addr_idx); 1545195972f6Sopenharmony_ci /* state is actually being changed? */ 1546195972f6Sopenharmony_ci if (old_state != state) { 1547195972f6Sopenharmony_ci u8_t old_valid = old_state & IP6_ADDR_VALID; 1548195972f6Sopenharmony_ci u8_t new_valid = state & IP6_ADDR_VALID; 1549195972f6Sopenharmony_ci LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n")); 1550195972f6Sopenharmony_ci 1551195972f6Sopenharmony_ci#if LWIP_IPV6_MLD 1552195972f6Sopenharmony_ci /* Reevaluate solicited-node multicast group membership. */ 1553195972f6Sopenharmony_ci if (netif->flags & NETIF_FLAG_MLD6) { 1554195972f6Sopenharmony_ci nd6_adjust_mld_membership(netif, addr_idx, state); 1555195972f6Sopenharmony_ci } 1556195972f6Sopenharmony_ci#endif /* LWIP_IPV6_MLD */ 1557195972f6Sopenharmony_ci 1558195972f6Sopenharmony_ci if (old_valid && !new_valid) { 1559195972f6Sopenharmony_ci /* address about to be removed by setting invalid */ 1560195972f6Sopenharmony_ci netif_do_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); 1561195972f6Sopenharmony_ci /* @todo: remove mib2 ip6 entries? */ 1562195972f6Sopenharmony_ci } 1563195972f6Sopenharmony_ci netif->ip6_addr_state[addr_idx] = state; 1564195972f6Sopenharmony_ci 1565195972f6Sopenharmony_ci if (!old_valid && new_valid) { 1566195972f6Sopenharmony_ci /* address added by setting valid */ 1567195972f6Sopenharmony_ci /* This is a good moment to check that the address is properly zoned. */ 1568195972f6Sopenharmony_ci IP6_ADDR_ZONECHECK_NETIF(netif_ip6_addr(netif, addr_idx), netif); 1569195972f6Sopenharmony_ci /* @todo: add mib2 ip6 entries? */ 1570195972f6Sopenharmony_ci netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); 1571195972f6Sopenharmony_ci } 1572195972f6Sopenharmony_ci if ((old_state & ~IP6_ADDR_TENTATIVE_COUNT_MASK) != 1573195972f6Sopenharmony_ci (state & ~IP6_ADDR_TENTATIVE_COUNT_MASK)) { 1574195972f6Sopenharmony_ci /* address state has changed -> call the callback function */ 1575195972f6Sopenharmony_ci NETIF_STATUS_CALLBACK(netif); 1576195972f6Sopenharmony_ci } 1577195972f6Sopenharmony_ci 1578195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 1579195972f6Sopenharmony_ci { 1580195972f6Sopenharmony_ci netif_ext_callback_args_t args; 1581195972f6Sopenharmony_ci args.ipv6_addr_state_changed.addr_index = addr_idx; 1582195972f6Sopenharmony_ci args.ipv6_addr_state_changed.old_state = old_state; 1583195972f6Sopenharmony_ci args.ipv6_addr_state_changed.address = netif_ip_addr6(netif, addr_idx); 1584195972f6Sopenharmony_ci netif_invoke_ext_callback(netif, LWIP_NSC_IPV6_ADDR_STATE_CHANGED, &args); 1585195972f6Sopenharmony_ci } 1586195972f6Sopenharmony_ci#endif 1587195972f6Sopenharmony_ci } 1588195972f6Sopenharmony_ci 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", 1589195972f6Sopenharmony_ci addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), 1590195972f6Sopenharmony_ci netif_ip6_addr_state(netif, addr_idx))); 1591195972f6Sopenharmony_ci} 1592195972f6Sopenharmony_ci 1593195972f6Sopenharmony_ci/** 1594195972f6Sopenharmony_ci * Checks if a specific local address is present on the netif and returns its 1595195972f6Sopenharmony_ci * index. Depending on its state, it may or may not be assigned to the 1596195972f6Sopenharmony_ci * interface (as per RFC terminology). 1597195972f6Sopenharmony_ci * 1598195972f6Sopenharmony_ci * The given address may or may not be zoned (i.e., have a zone index other 1599195972f6Sopenharmony_ci * than IP6_NO_ZONE). If the address is zoned, it must have the correct zone 1600195972f6Sopenharmony_ci * for the given netif, or no match will be found. 1601195972f6Sopenharmony_ci * 1602195972f6Sopenharmony_ci * @param netif the netif to check 1603195972f6Sopenharmony_ci * @param ip6addr the IPv6 address to find 1604195972f6Sopenharmony_ci * @return >= 0: address found, this is its index 1605195972f6Sopenharmony_ci * -1: address not found on this netif 1606195972f6Sopenharmony_ci */ 1607195972f6Sopenharmony_cis8_t 1608195972f6Sopenharmony_cinetif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr) 1609195972f6Sopenharmony_ci{ 1610195972f6Sopenharmony_ci s8_t i; 1611195972f6Sopenharmony_ci 1612195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 1613195972f6Sopenharmony_ci 1614195972f6Sopenharmony_ci LWIP_ASSERT("netif_get_ip6_addr_match: invalid netif", netif != NULL); 1615195972f6Sopenharmony_ci LWIP_ASSERT("netif_get_ip6_addr_match: invalid ip6addr", ip6addr != NULL); 1616195972f6Sopenharmony_ci 1617195972f6Sopenharmony_ci#if LWIP_IPV6_SCOPES 1618195972f6Sopenharmony_ci if (ip6_addr_has_zone(ip6addr) && !ip6_addr_test_zone(ip6addr, netif)) { 1619195972f6Sopenharmony_ci return -1; /* wrong zone, no match */ 1620195972f6Sopenharmony_ci } 1621195972f6Sopenharmony_ci#endif /* LWIP_IPV6_SCOPES */ 1622195972f6Sopenharmony_ci 1623195972f6Sopenharmony_ci for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 1624195972f6Sopenharmony_ci if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) && 1625195972f6Sopenharmony_ci ip6_addr_cmp_zoneless(netif_ip6_addr(netif, i), ip6addr)) { 1626195972f6Sopenharmony_ci return i; 1627195972f6Sopenharmony_ci } 1628195972f6Sopenharmony_ci } 1629195972f6Sopenharmony_ci return -1; 1630195972f6Sopenharmony_ci} 1631195972f6Sopenharmony_ci 1632195972f6Sopenharmony_ci/** 1633195972f6Sopenharmony_ci * @ingroup netif_ip6 1634195972f6Sopenharmony_ci * Create a link-local IPv6 address on a netif (stored in slot 0) 1635195972f6Sopenharmony_ci * 1636195972f6Sopenharmony_ci * @param netif the netif to create the address on 1637195972f6Sopenharmony_ci * @param from_mac_48bit if != 0, assume hwadr is a 48-bit MAC address (std conversion) 1638195972f6Sopenharmony_ci * if == 0, use hwaddr directly as interface ID 1639195972f6Sopenharmony_ci */ 1640195972f6Sopenharmony_civoid 1641195972f6Sopenharmony_cinetif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit) 1642195972f6Sopenharmony_ci{ 1643195972f6Sopenharmony_ci u8_t i, addr_index; 1644195972f6Sopenharmony_ci 1645195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 1646195972f6Sopenharmony_ci 1647195972f6Sopenharmony_ci LWIP_ASSERT("netif_create_ip6_linklocal_address: invalid netif", netif != NULL); 1648195972f6Sopenharmony_ci 1649195972f6Sopenharmony_ci /* Link-local prefix. */ 1650195972f6Sopenharmony_ci ip_2_ip6(&netif->ip6_addr[0])->addr[0] = PP_HTONL(0xfe800000ul); 1651195972f6Sopenharmony_ci ip_2_ip6(&netif->ip6_addr[0])->addr[1] = 0; 1652195972f6Sopenharmony_ci 1653195972f6Sopenharmony_ci /* Generate interface ID. */ 1654195972f6Sopenharmony_ci if (from_mac_48bit) { 1655195972f6Sopenharmony_ci /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */ 1656195972f6Sopenharmony_ci ip_2_ip6(&netif->ip6_addr[0])->addr[2] = lwip_htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) | 1657195972f6Sopenharmony_ci ((u32_t)(netif->hwaddr[1]) << 16) | 1658195972f6Sopenharmony_ci ((u32_t)(netif->hwaddr[2]) << 8) | 1659195972f6Sopenharmony_ci (0xff)); 1660195972f6Sopenharmony_ci ip_2_ip6(&netif->ip6_addr[0])->addr[3] = lwip_htonl((u32_t)(0xfeul << 24) | 1661195972f6Sopenharmony_ci ((u32_t)(netif->hwaddr[3]) << 16) | 1662195972f6Sopenharmony_ci ((u32_t)(netif->hwaddr[4]) << 8) | 1663195972f6Sopenharmony_ci (netif->hwaddr[5])); 1664195972f6Sopenharmony_ci } else { 1665195972f6Sopenharmony_ci /* Use hwaddr directly as interface ID. */ 1666195972f6Sopenharmony_ci ip_2_ip6(&netif->ip6_addr[0])->addr[2] = 0; 1667195972f6Sopenharmony_ci ip_2_ip6(&netif->ip6_addr[0])->addr[3] = 0; 1668195972f6Sopenharmony_ci 1669195972f6Sopenharmony_ci addr_index = 3; 1670195972f6Sopenharmony_ci for (i = 0; (i < 8) && (i < netif->hwaddr_len); i++) { 1671195972f6Sopenharmony_ci if (i == 4) { 1672195972f6Sopenharmony_ci addr_index--; 1673195972f6Sopenharmony_ci } 1674195972f6Sopenharmony_ci ip_2_ip6(&netif->ip6_addr[0])->addr[addr_index] |= lwip_htonl(((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03))); 1675195972f6Sopenharmony_ci } 1676195972f6Sopenharmony_ci } 1677195972f6Sopenharmony_ci 1678195972f6Sopenharmony_ci /* Set a link-local zone. Even though the zone is implied by the owning 1679195972f6Sopenharmony_ci * netif, setting the zone anyway has two important conceptual advantages: 1680195972f6Sopenharmony_ci * 1) it avoids the need for a ton of exceptions in internal code, allowing 1681195972f6Sopenharmony_ci * e.g. ip6_addr_cmp() to be used on local addresses; 1682195972f6Sopenharmony_ci * 2) the properly zoned address is visible externally, e.g. when any outside 1683195972f6Sopenharmony_ci * code enumerates available addresses or uses one to bind a socket. 1684195972f6Sopenharmony_ci * Any external code unaware of address scoping is likely to just ignore the 1685195972f6Sopenharmony_ci * zone field, so this should not create any compatibility problems. */ 1686195972f6Sopenharmony_ci ip6_addr_assign_zone(ip_2_ip6(&netif->ip6_addr[0]), IP6_UNICAST, netif); 1687195972f6Sopenharmony_ci 1688195972f6Sopenharmony_ci /* Set address state. */ 1689195972f6Sopenharmony_ci#if LWIP_IPV6_DUP_DETECT_ATTEMPTS 1690195972f6Sopenharmony_ci /* Will perform duplicate address detection (DAD). */ 1691195972f6Sopenharmony_ci netif_ip6_addr_set_state(netif, 0, IP6_ADDR_TENTATIVE); 1692195972f6Sopenharmony_ci#else 1693195972f6Sopenharmony_ci /* Consider address valid. */ 1694195972f6Sopenharmony_ci netif_ip6_addr_set_state(netif, 0, IP6_ADDR_PREFERRED); 1695195972f6Sopenharmony_ci#endif /* LWIP_IPV6_AUTOCONFIG */ 1696195972f6Sopenharmony_ci} 1697195972f6Sopenharmony_ci 1698195972f6Sopenharmony_ci/** 1699195972f6Sopenharmony_ci * @ingroup netif_ip6 1700195972f6Sopenharmony_ci * This function allows for the easy addition of a new IPv6 address to an interface. 1701195972f6Sopenharmony_ci * It takes care of finding an empty slot and then sets the address tentative 1702195972f6Sopenharmony_ci * (to make sure that all the subsequent processing happens). 1703195972f6Sopenharmony_ci * 1704195972f6Sopenharmony_ci * @param netif netif to add the address on 1705195972f6Sopenharmony_ci * @param ip6addr address to add 1706195972f6Sopenharmony_ci * @param chosen_idx if != NULL, the chosen IPv6 address index will be stored here 1707195972f6Sopenharmony_ci */ 1708195972f6Sopenharmony_cierr_t 1709195972f6Sopenharmony_cinetif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx) 1710195972f6Sopenharmony_ci{ 1711195972f6Sopenharmony_ci s8_t i; 1712195972f6Sopenharmony_ci 1713195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 1714195972f6Sopenharmony_ci 1715195972f6Sopenharmony_ci LWIP_ASSERT("netif_add_ip6_address: invalid netif", netif != NULL); 1716195972f6Sopenharmony_ci LWIP_ASSERT("netif_add_ip6_address: invalid ip6addr", ip6addr != NULL); 1717195972f6Sopenharmony_ci 1718195972f6Sopenharmony_ci i = netif_get_ip6_addr_match(netif, ip6addr); 1719195972f6Sopenharmony_ci if (i >= 0) { 1720195972f6Sopenharmony_ci /* Address already added */ 1721195972f6Sopenharmony_ci if (chosen_idx != NULL) { 1722195972f6Sopenharmony_ci *chosen_idx = i; 1723195972f6Sopenharmony_ci } 1724195972f6Sopenharmony_ci return ERR_OK; 1725195972f6Sopenharmony_ci } 1726195972f6Sopenharmony_ci 1727195972f6Sopenharmony_ci /* Find a free slot. The first one is reserved for link-local addresses. */ 1728195972f6Sopenharmony_ci for (i = ip6_addr_islinklocal(ip6addr) ? 0 : 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 1729195972f6Sopenharmony_ci if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) { 1730195972f6Sopenharmony_ci ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr); 1731195972f6Sopenharmony_ci ip6_addr_assign_zone(ip_2_ip6(&netif->ip6_addr[i]), IP6_UNICAST, netif); 1732195972f6Sopenharmony_ci netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE); 1733195972f6Sopenharmony_ci if (chosen_idx != NULL) { 1734195972f6Sopenharmony_ci *chosen_idx = i; 1735195972f6Sopenharmony_ci } 1736195972f6Sopenharmony_ci return ERR_OK; 1737195972f6Sopenharmony_ci } 1738195972f6Sopenharmony_ci } 1739195972f6Sopenharmony_ci 1740195972f6Sopenharmony_ci if (chosen_idx != NULL) { 1741195972f6Sopenharmony_ci *chosen_idx = -1; 1742195972f6Sopenharmony_ci } 1743195972f6Sopenharmony_ci return ERR_VAL; 1744195972f6Sopenharmony_ci} 1745195972f6Sopenharmony_ci 1746195972f6Sopenharmony_ci/** Dummy IPv6 output function for netifs not supporting IPv6 1747195972f6Sopenharmony_ci */ 1748195972f6Sopenharmony_cistatic err_t 1749195972f6Sopenharmony_cinetif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr) 1750195972f6Sopenharmony_ci{ 1751195972f6Sopenharmony_ci LWIP_UNUSED_ARG(netif); 1752195972f6Sopenharmony_ci LWIP_UNUSED_ARG(p); 1753195972f6Sopenharmony_ci LWIP_UNUSED_ARG(ipaddr); 1754195972f6Sopenharmony_ci 1755195972f6Sopenharmony_ci return ERR_IF; 1756195972f6Sopenharmony_ci} 1757195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 1758195972f6Sopenharmony_ci 1759195972f6Sopenharmony_ci#if LWIP_IPV4 1760195972f6Sopenharmony_ci/** Dummy IPv4 output function for netifs not supporting IPv4 1761195972f6Sopenharmony_ci */ 1762195972f6Sopenharmony_cistatic err_t 1763195972f6Sopenharmony_cinetif_null_output_ip4(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr) 1764195972f6Sopenharmony_ci{ 1765195972f6Sopenharmony_ci LWIP_UNUSED_ARG(netif); 1766195972f6Sopenharmony_ci LWIP_UNUSED_ARG(p); 1767195972f6Sopenharmony_ci LWIP_UNUSED_ARG(ipaddr); 1768195972f6Sopenharmony_ci 1769195972f6Sopenharmony_ci return ERR_IF; 1770195972f6Sopenharmony_ci} 1771195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 1772195972f6Sopenharmony_ci 1773195972f6Sopenharmony_ci/** 1774195972f6Sopenharmony_ci* @ingroup netif 1775195972f6Sopenharmony_ci* Return the interface index for the netif with name 1776195972f6Sopenharmony_ci* or NETIF_NO_INDEX if not found/on error 1777195972f6Sopenharmony_ci* 1778195972f6Sopenharmony_ci* @param name the name of the netif 1779195972f6Sopenharmony_ci*/ 1780195972f6Sopenharmony_ciu8_t 1781195972f6Sopenharmony_cinetif_name_to_index(const char *name) 1782195972f6Sopenharmony_ci{ 1783195972f6Sopenharmony_ci struct netif *netif = netif_find(name); 1784195972f6Sopenharmony_ci if (netif != NULL) { 1785195972f6Sopenharmony_ci return netif_get_index(netif); 1786195972f6Sopenharmony_ci } 1787195972f6Sopenharmony_ci /* No name found, return invalid index */ 1788195972f6Sopenharmony_ci return NETIF_NO_INDEX; 1789195972f6Sopenharmony_ci} 1790195972f6Sopenharmony_ci 1791195972f6Sopenharmony_ci/** 1792195972f6Sopenharmony_ci* @ingroup netif 1793195972f6Sopenharmony_ci* Return the interface name for the netif matching index 1794195972f6Sopenharmony_ci* or NULL if not found/on error 1795195972f6Sopenharmony_ci* 1796195972f6Sopenharmony_ci* @param idx the interface index of the netif 1797195972f6Sopenharmony_ci* @param name char buffer of at least NETIF_NAMESIZE bytes 1798195972f6Sopenharmony_ci*/ 1799195972f6Sopenharmony_cichar * 1800195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 1801195972f6Sopenharmony_cinetif_index_to_name(u8_t idx, char *name, struct net_group *group) 1802195972f6Sopenharmony_ci#else 1803195972f6Sopenharmony_cinetif_index_to_name(u8_t idx, char *name) 1804195972f6Sopenharmony_ci#endif 1805195972f6Sopenharmony_ci{ 1806195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 1807195972f6Sopenharmony_ci struct netif *netif = netif_get_by_index(idx, group); 1808195972f6Sopenharmony_ci#else 1809195972f6Sopenharmony_ci struct netif *netif = netif_get_by_index(idx); 1810195972f6Sopenharmony_ci#endif 1811195972f6Sopenharmony_ci 1812195972f6Sopenharmony_ci if (netif != NULL) { 1813195972f6Sopenharmony_ci name[0] = netif->name[0]; 1814195972f6Sopenharmony_ci name[1] = netif->name[1]; 1815195972f6Sopenharmony_ci lwip_itoa(&name[2], NETIF_NAMESIZE - 2, netif_index_to_num(idx)); 1816195972f6Sopenharmony_ci return name; 1817195972f6Sopenharmony_ci } 1818195972f6Sopenharmony_ci return NULL; 1819195972f6Sopenharmony_ci} 1820195972f6Sopenharmony_ci 1821195972f6Sopenharmony_ci/** 1822195972f6Sopenharmony_ci* @ingroup netif 1823195972f6Sopenharmony_ci* Return the interface for the netif index 1824195972f6Sopenharmony_ci* 1825195972f6Sopenharmony_ci* @param idx index of netif to find 1826195972f6Sopenharmony_ci*/ 1827195972f6Sopenharmony_cistruct netif * 1828195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 1829195972f6Sopenharmony_cinetif_get_by_index(u8_t idx, struct net_group *group) 1830195972f6Sopenharmony_ci#else 1831195972f6Sopenharmony_cinetif_get_by_index(u8_t idx) 1832195972f6Sopenharmony_ci#endif 1833195972f6Sopenharmony_ci{ 1834195972f6Sopenharmony_ci struct netif *netif; 1835195972f6Sopenharmony_ci 1836195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 1837195972f6Sopenharmony_ci 1838195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 1839195972f6Sopenharmony_ci if (idx != NETIF_NO_INDEX && group != NULL) { 1840195972f6Sopenharmony_ci NETIF_FOREACH(netif, group) { 1841195972f6Sopenharmony_ci#else 1842195972f6Sopenharmony_ci if (idx != NETIF_NO_INDEX) { 1843195972f6Sopenharmony_ci NETIF_FOREACH(netif) { 1844195972f6Sopenharmony_ci#endif 1845195972f6Sopenharmony_ci if (idx == netif_get_index(netif)) { 1846195972f6Sopenharmony_ci return netif; /* found! */ 1847195972f6Sopenharmony_ci } 1848195972f6Sopenharmony_ci } 1849195972f6Sopenharmony_ci } 1850195972f6Sopenharmony_ci 1851195972f6Sopenharmony_ci return NULL; 1852195972f6Sopenharmony_ci} 1853195972f6Sopenharmony_ci 1854195972f6Sopenharmony_ci#ifndef netif_find 1855195972f6Sopenharmony_ci/** 1856195972f6Sopenharmony_ci * @ingroup netif 1857195972f6Sopenharmony_ci * Find a network interface by searching for its name 1858195972f6Sopenharmony_ci * 1859195972f6Sopenharmony_ci * @param name the name of the netif (like netif->name) plus concatenated number 1860195972f6Sopenharmony_ci * in ascii representation (e.g. 'en0') 1861195972f6Sopenharmony_ci */ 1862195972f6Sopenharmony_cistruct netif * 1863195972f6Sopenharmony_cinetif_find(const char *name) 1864195972f6Sopenharmony_ci{ 1865195972f6Sopenharmony_ci struct netif *netif; 1866195972f6Sopenharmony_ci u8_t num; 1867195972f6Sopenharmony_ci 1868195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 1869195972f6Sopenharmony_ci 1870195972f6Sopenharmony_ci if (name == NULL) { 1871195972f6Sopenharmony_ci return NULL; 1872195972f6Sopenharmony_ci } 1873195972f6Sopenharmony_ci 1874195972f6Sopenharmony_ci num = (u8_t)atoi(&name[2]); 1875195972f6Sopenharmony_ci if (!num && (name[2] != '0')) { 1876195972f6Sopenharmony_ci /* this means atoi has failed */ 1877195972f6Sopenharmony_ci return NULL; 1878195972f6Sopenharmony_ci } 1879195972f6Sopenharmony_ci 1880195972f6Sopenharmony_ci NETIF_FOREACH(netif) { 1881195972f6Sopenharmony_ci if (num == netif->num && 1882195972f6Sopenharmony_ci name[0] == netif->name[0] && 1883195972f6Sopenharmony_ci name[1] == netif->name[1]) { 1884195972f6Sopenharmony_ci LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); 1885195972f6Sopenharmony_ci return netif; 1886195972f6Sopenharmony_ci } 1887195972f6Sopenharmony_ci } 1888195972f6Sopenharmony_ci LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); 1889195972f6Sopenharmony_ci return NULL; 1890195972f6Sopenharmony_ci} 1891195972f6Sopenharmony_ci#endif 1892195972f6Sopenharmony_ci 1893195972f6Sopenharmony_ci#if LWIP_NETIF_EXT_STATUS_CALLBACK 1894195972f6Sopenharmony_ci/** 1895195972f6Sopenharmony_ci * @ingroup netif 1896195972f6Sopenharmony_ci * Add extended netif events listener 1897195972f6Sopenharmony_ci * @param callback pointer to listener structure 1898195972f6Sopenharmony_ci * @param fn callback function 1899195972f6Sopenharmony_ci */ 1900195972f6Sopenharmony_civoid 1901195972f6Sopenharmony_cinetif_add_ext_callback(netif_ext_callback_t *callback, netif_ext_callback_fn fn) 1902195972f6Sopenharmony_ci{ 1903195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 1904195972f6Sopenharmony_ci LWIP_ASSERT("callback must be != NULL", callback != NULL); 1905195972f6Sopenharmony_ci LWIP_ASSERT("fn must be != NULL", fn != NULL); 1906195972f6Sopenharmony_ci 1907195972f6Sopenharmony_ci callback->callback_fn = fn; 1908195972f6Sopenharmony_ci callback->next = ext_callback; 1909195972f6Sopenharmony_ci ext_callback = callback; 1910195972f6Sopenharmony_ci} 1911195972f6Sopenharmony_ci 1912195972f6Sopenharmony_ci/** 1913195972f6Sopenharmony_ci * @ingroup netif 1914195972f6Sopenharmony_ci * Remove extended netif events listener 1915195972f6Sopenharmony_ci * @param callback pointer to listener structure 1916195972f6Sopenharmony_ci */ 1917195972f6Sopenharmony_civoid 1918195972f6Sopenharmony_cinetif_remove_ext_callback(netif_ext_callback_t* callback) 1919195972f6Sopenharmony_ci{ 1920195972f6Sopenharmony_ci netif_ext_callback_t *last, *iter; 1921195972f6Sopenharmony_ci 1922195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 1923195972f6Sopenharmony_ci LWIP_ASSERT("callback must be != NULL", callback != NULL); 1924195972f6Sopenharmony_ci 1925195972f6Sopenharmony_ci if (ext_callback == NULL) { 1926195972f6Sopenharmony_ci return; 1927195972f6Sopenharmony_ci } 1928195972f6Sopenharmony_ci 1929195972f6Sopenharmony_ci if (callback == ext_callback) { 1930195972f6Sopenharmony_ci ext_callback = ext_callback->next; 1931195972f6Sopenharmony_ci } else { 1932195972f6Sopenharmony_ci last = ext_callback; 1933195972f6Sopenharmony_ci for (iter = ext_callback->next; iter != NULL; last = iter, iter = iter->next) { 1934195972f6Sopenharmony_ci if (iter == callback) { 1935195972f6Sopenharmony_ci LWIP_ASSERT("last != NULL", last != NULL); 1936195972f6Sopenharmony_ci last->next = callback->next; 1937195972f6Sopenharmony_ci callback->next = NULL; 1938195972f6Sopenharmony_ci return; 1939195972f6Sopenharmony_ci } 1940195972f6Sopenharmony_ci } 1941195972f6Sopenharmony_ci } 1942195972f6Sopenharmony_ci} 1943195972f6Sopenharmony_ci 1944195972f6Sopenharmony_ci/** 1945195972f6Sopenharmony_ci * Invoke extended netif status event 1946195972f6Sopenharmony_ci * @param netif netif that is affected by change 1947195972f6Sopenharmony_ci * @param reason change reason 1948195972f6Sopenharmony_ci * @param args depends on reason, see reason description 1949195972f6Sopenharmony_ci */ 1950195972f6Sopenharmony_civoid 1951195972f6Sopenharmony_cinetif_invoke_ext_callback(struct netif *netif, netif_nsc_reason_t reason, const netif_ext_callback_args_t *args) 1952195972f6Sopenharmony_ci{ 1953195972f6Sopenharmony_ci netif_ext_callback_t *callback = ext_callback; 1954195972f6Sopenharmony_ci 1955195972f6Sopenharmony_ci LWIP_ASSERT("netif must be != NULL", netif != NULL); 1956195972f6Sopenharmony_ci 1957195972f6Sopenharmony_ci while (callback != NULL) { 1958195972f6Sopenharmony_ci callback->callback_fn(netif, reason, args); 1959195972f6Sopenharmony_ci callback = callback->next; 1960195972f6Sopenharmony_ci } 1961195972f6Sopenharmony_ci} 1962195972f6Sopenharmony_ci#endif /* LWIP_NETIF_EXT_STATUS_CALLBACK */ 1963