1/* 2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. 3 * Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this list of 9 * conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list 12 * of conditions and the following disclaimer in the documentation and/or other materials 13 * provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used 16 * to endorse or promote products derived from this software without specific prior written 17 * permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include "lwip/fixme.h" 33 34#include <lwip/sys.h> 35#include <lwip/snmp.h> 36#include <lwip/etharp.h> 37#include <lwip/netifapi.h> 38#include <lwip/priv/api_msg.h> 39 40#define NETIFAPI_VAR_REF(name) API_VAR_REF(name) 41#define NETIFAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct netifapi_msg, name) 42#define NETIFAPI_VAR_ALLOC(name) API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name, ERR_MEM) 43#define NETIFAPI_VAR_FREE(name) API_VAR_FREE(MEMP_NETIFAPI_MSG, name) 44 45#if LWIP_DHCP 46 47#include <lwip/dhcp.h> 48 49/* 50 * Close DHCP and set static network. 51 * @param netif a pre-allocated netif structure 52 * @return ERR_OK, or ERR_VAL if failed. 53 */ 54err_t netif_dhcp_off(struct netif *netif) 55{ 56 ip_addr_t old_ipaddr; 57 ip_addr_t old_netmask; 58 ip_addr_t old_gateway; 59 60 if (netif == NULL) { 61 return ERR_VAL; 62 } 63 old_ipaddr = netif->ip_addr; 64 old_netmask = netif->netmask; 65 old_gateway = netif->gw; 66 67 if (netif_dhcp_data(netif)) { 68 (void)dhcp_release(netif); 69 (void)dhcp_stop(netif); 70 (void)dhcp_cleanup(netif); 71 LWIP_DEBUGF(NETIF_DEBUG, ("DHCP is close;set static IP\n")); 72 } 73 74 ip_addr_set_val(&netif->ip_addr, &old_ipaddr); 75 ip_addr_set_val(&netif->netmask, &old_netmask); 76 ip_addr_set_val(&netif->gw, &old_gateway); 77 (void)netif_set_up(netif); 78 79 return ERR_OK; 80} 81 82err_t dhcp_is_bound(struct netif *netif) 83{ 84 struct dhcp *dhcp = NULL; 85 86 LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG); 87 88 dhcp = netif_dhcp_data(netif); 89 LWIP_ERROR("netif->dhcp != NULL", (dhcp != NULL), return ERR_ARG); 90 91 if (dhcp->state == DHCP_STATE_BOUND) { 92 return ERR_OK; 93 } else { 94 return ERR_INPROGRESS; 95 } 96} 97 98#endif /* LWIP_DHCP */ 99 100#if LWIP_DHCPS 101 102#include "lwip/dhcps.h" 103 104static err_t netifapi_do_dhcps_start(struct tcpip_api_call_data *m) 105{ 106 /* cast through void* to silence alignment warnings. 107 * We know it works because the structs have been instantiated as struct netifapi_msg */ 108 err_t ret; 109 struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m; 110 ret = dhcps_start(msg->netif, msg->msg.dhcp_start_params.start_ip, msg->msg.dhcp_start_params.ip_num); 111 return ret; 112} 113 114err_t netifapi_dhcps_start(struct netif *netif, char *start_ip, u16_t ip_num) 115{ 116 err_t err; 117 NETIFAPI_VAR_DECLARE(msg); 118 119 LWIP_ERROR("netifapi_dhcps_start : invalid arguments", (netif != NULL), return ERR_VAL); 120 NETIFAPI_VAR_ALLOC(msg); 121 122 NETIFAPI_VAR_REF(msg).netif = netif; 123 NETIFAPI_VAR_REF(msg).msg.dhcp_start_params.start_ip = start_ip; 124 NETIFAPI_VAR_REF(msg).msg.dhcp_start_params.ip_num = ip_num; 125 126 err = tcpip_api_call(netifapi_do_dhcps_start, &API_VAR_REF(msg).call); 127 128 NETIFAPI_VAR_FREE(msg); 129 return err; 130} 131 132err_t netifapi_dhcps_stop(struct netif *netif) 133{ 134 LWIP_ERROR("netifapi_dhcps_stop : invalid arguments", (netif != NULL), return ERR_VAL); 135 136 return netifapi_netif_common(netif, dhcps_stop, NULL); 137} 138 139#endif /* LWIP_DHCPS */ 140 141/* 142 * This function is for making sure that accept() should not block indefinetely 143 * when removing IPv6 address used for accept() by using API[netifapi_netif_rmv_ip6_address]. 144 */ 145static void tcp_unlock_accept(ip6_addr_t *ipaddr) 146{ 147 (void)ipaddr; 148} 149 150static void netif_ip6_addr_setinvalid(struct netif *netif, const ip6_addr_t *addr6) 151{ 152 s8_t idx; 153 LWIP_ERROR("netif_ip6_addr_set : invalid arguments", (netif != NULL), return); 154 LWIP_ERROR("netif_ip6_addr_set : invalid arguments", (addr6 != NULL), return); 155 156 idx = netif_get_ip6_addr_match(netif, addr6); 157 if (idx < 0) { 158 return; 159 } 160 161 netif_ip6_addr_set_state(netif, idx, IP6_ADDR_INVALID); 162 return; 163} 164 165err_t netif_do_rmv_ipv6_addr(struct netif *netif, void *arguments) 166{ 167 ip_addr_t *ipaddr = (ip_addr_t *)arguments; 168 169 if (IP_IS_V6(ipaddr)) { 170#if LWIP_TCP 171 tcp_unlock_accept(ip_2_ip6(ipaddr)); 172#endif 173 netif_ip6_addr_setinvalid(netif, ip_2_ip6(ipaddr)); 174 } 175 return ERR_OK; 176} 177 178static err_t netif_do_rmv_ip6_address(struct tcpip_api_call_data *m) 179{ 180 /* cast through void* to silence alignment warnings. 181 * We know it works because the structs have been instantiated as struct netifapi_msg */ 182 struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m; 183 184 return netif_do_rmv_ipv6_addr(msg->netif, (void *)msg->msg.add.ipaddr); 185} 186 187void netifapi_netif_rmv_ip6_address(struct netif *netif, ip_addr_t *ipaddr) 188{ 189 err_t err; 190 if (netif == NULL) { 191 return; 192 } 193 NETIFAPI_VAR_DECLARE(msg); 194 NETIFAPI_VAR_ALLOC(msg); 195 196 NETIFAPI_VAR_REF(msg).netif = netif; 197 NETIFAPI_VAR_REF(msg).msg.add.ipaddr = (void *)ipaddr; 198 199 err = tcpip_api_call(netif_do_rmv_ip6_address, &API_VAR_REF(msg).call); 200 201 NETIFAPI_VAR_FREE(msg); 202 (void)err; 203} 204 205#ifdef LOSCFG_NET_CONTAINER 206static struct netif *netif_find_by_name(const char *name, struct net_group *group) 207#else 208static struct netif *netif_find_by_name(const char *name) 209#endif 210{ 211 struct netif *netif = NULL; 212 213 LWIP_ASSERT_CORE_LOCKED(); 214 215 if (name == NULL) { 216 return NULL; 217 } 218 219#ifdef LOSCFG_NET_CONTAINER 220 NETIF_FOREACH(netif, group) { 221#else 222 NETIF_FOREACH(netif) { 223#endif 224 if (strcmp("lo", name) == 0 && (netif->name[0] == 'l' && netif->name[1] == 'o')) { 225 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_name: found lo\n")); 226 return netif; 227 } 228 229 if (strcmp(netif->full_name, name) == 0) { 230 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_name: found %s\n", name)); 231 return netif; 232 } 233 } 234 235 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_name: didn't find %s\n", name)); 236 return NULL; 237} 238 239static err_t netifapi_do_find_by_name(struct tcpip_api_call_data *m) 240{ 241 /* cast through void* to silence alignment warnings. 242 * We know it works because the structs have been instantiated as struct netifapi_msg */ 243 struct netifapi_msg *msg = (struct netifapi_msg *)(void *)m; 244 245#ifdef LOSCFG_NET_CONTAINER 246 struct net_group *group = get_curr_process_net_group(); 247 msg->netif = netif_find_by_name(msg->msg.ifs.name, group); 248#else 249 msg->netif = netif_find_by_name(msg->msg.ifs.name); 250#endif 251 return ERR_OK; 252} 253 254struct netif *netifapi_netif_find_by_name(const char *name) 255{ 256 struct netif *netif = NULL; 257 NETIFAPI_VAR_DECLARE(msg); 258 NETIFAPI_VAR_ALLOC(msg); 259 260 NETIFAPI_VAR_REF(msg).netif = NULL; 261#if LWIP_MPU_COMPATIBLE 262 if (strncpy_s(NETIFAPI_VAR_REF(msg).msg.ifs.name, NETIF_NAMESIZE, name, NETIF_NAMESIZE - 1)) { 263 NETIFAPI_VAR_FREE(msg); 264 return netif; 265 } 266 NETIFAPI_VAR_REF(msg).msg.ifs.name[NETIF_NAMESIZE - 1] = '\0'; 267#else 268 NETIFAPI_VAR_REF(msg).msg.ifs.name = (char *)name; 269#endif /* LWIP_MPU_COMPATIBLE */ 270 271 (void)tcpip_api_call(netifapi_do_find_by_name, &API_VAR_REF(msg).call); 272 273 netif = msg.netif; 274 NETIFAPI_VAR_FREE(msg); 275 return netif; 276} 277 278#define NETIF_MTU_MIN 1280 279#ifndef IP_FRAG_MIN_MTU 280#define IP_FRAG_MIN_MTU 68 281#endif 282 283err_t netif_set_mtu(struct netif *netif, u16_t netif_mtu) 284{ 285 /* 286 * As per RFC 791, "Every internet module must be able to forward a datagram of 68 287 * octets without further fragmentation. This is because an internet header 288 * may be up to 60 octets, and the minimum fragment is 8 octets." 289 */ 290 LWIP_ERROR("netif_set_mtu: invalid arguments", (netif != NULL), return ERR_VAL); 291 292#if LWIP_IPV6 293 LWIP_ERROR("netif_set_mtu: invalid arguments", (netif_mtu >= NETIF_MTU_MIN) && (netif_mtu <= IP_FRAG_MAX_MTU), 294 return ERR_ARG); 295#else 296 LWIP_ERROR("netif_set_mtu: invalid arguments", (netif_mtu >= IP_FRAG_MIN_MTU) && (netif_mtu <= IP_FRAG_MAX_MTU), 297 return ERR_ARG); 298#endif 299 300 netif->mtu = netif_mtu; 301#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES 302 netif->mtu6 = netif_mtu; 303#endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */ 304 305 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif: MTU of interface %s is changed to %d\n", 306 netif_get_name(netif), netif->mtu)); 307 return ERR_OK; 308} 309 310err_t netif_set_hwaddr(struct netif *netif, const unsigned char *hw_addr, int hw_len) 311{ 312 LWIP_ERROR("netif_set_hwaddr : invalid arguments", (netif != NULL), return ERR_VAL); 313 314 LWIP_ERROR("netif_set_hwaddr : invalid arguments", (hw_addr != NULL), return ERR_VAL); 315 316 LWIP_ERROR("netif_set_hwaddr: invalid arguments", 317 ((unsigned int)hw_len == NETIF_MAX_HWADDR_LEN), return ERR_VAL); 318 319 if (netif->drv_set_hwaddr == NULL) { 320 return ERR_IF; // ERR_OPNOTSUPP; 321 } 322 323 if (netif->drv_set_hwaddr(netif, (u8_t *)hw_addr, hw_len) != ERR_OK) { 324 return ERR_VAL; 325 } 326 327 if (memcpy_s(netif->hwaddr, NETIF_MAX_HWADDR_LEN, hw_addr, hw_len) != EOK) { 328 LWIP_DEBUGF(NETIF_DEBUG, ("netif_set_hwaddr: memcpy_s error\n")); 329 return ERR_VAL; 330 } 331 332 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, 333 ("netif: HW address of interface %s set to %02X:%02X:%02X:%02X:%02X:%02X\n", 334 netif_get_name(netif), 335 netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], 336 netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5])); 337 338 return ERR_OK; 339} 340 341err_t etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags) 342{ 343 (void)netif; 344 (void)ipaddr; 345 (void)ethaddr; 346 (void)flags; 347 return 0; 348} 349 350err_t etharp_delete_arp_entry(struct netif *netif, ip4_addr_t *ipaddr) 351{ 352 (void)netif; 353 (void)ipaddr; 354 return 0; 355} 356 357err_t lwip_dns_setserver(u8_t numdns, ip_addr_t *dnsserver) 358{ 359 (void)numdns; 360 (void)dnsserver; 361 return 0; 362} 363 364err_t lwip_dns_getserver(u8_t numdns, ip_addr_t *dnsserver) 365{ 366 (void)numdns; 367 (void)dnsserver; 368 return 0; 369} 370 371#if PF_PKT_SUPPORT 372struct raw_pcb *pkt_raw_pcbs; 373#endif 374 375#if LWIP_RAW 376struct raw_pcb *raw_pcbs; /* already defined in raw.c, but is static */ 377#endif 378 379#if LWIP_ENABLE_IP_CONFLICT_SIGNAL 380u32_t is_ip_conflict_signal = 0; 381sys_sem_t ip_conflict_detect; 382#endif 383 384u32_t is_dup_detect_initialized = 0; 385sys_sem_t dup_addr_detect; 386 387#if LWIP_SNTP 388 389#include <time.h> 390 391int lwip_sntp_start(int server_num, char **sntp_server, struct timeval *time) 392{ 393 (void)server_num; 394 (void)sntp_server; 395 (void)time; 396 return 0; 397} 398 399#endif 400 401const char *const tcp_state_str[] = { 402 "CLOSED", 403 "LISTEN", 404 "SYN_SENT", 405 "SYN_RCVD", 406 "ESTABLISHED", 407 "FIN_WAIT_1", 408 "FIN_WAIT_2", 409 "CLOSE_WAIT", 410 "CLOSING", 411 "LAST_ACK", 412 "TIME_WAIT" 413}; 414 415volatile int tcpip_init_finish = 1; // needed by api_shell.c 416 417int ip6addr_aton(const char *cp, ip6_addr_t *addr) 418{ 419 const int ipv6_blocks = 8; 420 u16_t current_block_index = 0; 421 u16_t current_block_value = 0; 422 u16_t addr16[ipv6_blocks]; 423 u16_t *a16 = (u16_t *)addr->addr; 424 int squash_pos = ipv6_blocks; 425 int i; 426 const char *s = cp; 427 const char *ss = cp - 1; 428 429 for (; ; s++) { 430 if (current_block_index >= ipv6_blocks) { 431 return 0; // address too long 432 } 433 if (*s == 0) { 434 if (s - ss == 1) { 435 if (squash_pos != current_block_index) { 436 return 0; // empty address or address ends with a single ':' 437 } // else address ends with one valid "::" 438 } else { 439 addr16[current_block_index++] = current_block_value; 440 } 441 break; 442 } else if (*s == ':') { 443 if (s - ss == 1) { 444 if (s != cp || s[1] != ':') { 445 return 0; // address begins with a single ':' or contains ":::" 446 } // else address begins with one valid "::" 447 } else { 448 addr16[current_block_index++] = current_block_value; 449 } 450 if (s[1] == ':') { 451 if (squash_pos != ipv6_blocks) { 452 return 0; // more than one "::" 453 } 454 squash_pos = current_block_index; 455 s++; 456 } 457 ss = s; // ss points to the recent ':' position 458 current_block_value = 0; 459 } else if (lwip_isxdigit(*s) && (s - ss) < 5) { // 4 hex-digits at most 460 current_block_value = (current_block_value << 4) + 461 ((u8_t)(*s) | ('a' - 'A')) - '0' - ('a' - '9' - 1) * (*s >= 'A'); 462#if LWIP_IPV4 463 } else if (*s == '.' && current_block_index < ipv6_blocks - 1) { 464 ip4_addr_t ip4; 465 int ret = ip4addr_aton(ss+1, &ip4); 466 if (!ret) { 467 return 0; 468 } 469 ip4.addr = lwip_ntohl(ip4.addr); 470 addr16[current_block_index++] = (u16_t)(ip4.addr >> 16); 471 addr16[current_block_index++] = (u16_t)(ip4.addr); 472 break; 473#endif /* LWIP_IPV4 */ 474 } else { 475 return 0; // unexpected char or too many digits 476 } 477 } 478 479 if (squash_pos == ipv6_blocks && current_block_index != ipv6_blocks) { 480 return 0; // address too short 481 } 482 if (squash_pos != ipv6_blocks && current_block_index == ipv6_blocks) { 483 return 0; // unexpected "::" in address 484 } 485 486 for (i = 0; i < squash_pos; ++i) { 487 a16[i] = lwip_htons(addr16[i]); 488 } 489 for (; i < ipv6_blocks - current_block_index + squash_pos; ++i) { 490 a16[i] = 0; 491 } 492 for (; i < ipv6_blocks; ++i) { 493 a16[i] = lwip_htons(addr16[i - ipv6_blocks + current_block_index]); 494 } 495 496 return 1; 497} 498