10d163575Sopenharmony_ci/* 20d163575Sopenharmony_ci * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. 30d163575Sopenharmony_ci * Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved. 40d163575Sopenharmony_ci * 50d163575Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 60d163575Sopenharmony_ci * are permitted provided that the following conditions are met: 70d163575Sopenharmony_ci * 80d163575Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of 90d163575Sopenharmony_ci * conditions and the following disclaimer. 100d163575Sopenharmony_ci * 110d163575Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list 120d163575Sopenharmony_ci * of conditions and the following disclaimer in the documentation and/or other materials 130d163575Sopenharmony_ci * provided with the distribution. 140d163575Sopenharmony_ci * 150d163575Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used 160d163575Sopenharmony_ci * to endorse or promote products derived from this software without specific prior written 170d163575Sopenharmony_ci * permission. 180d163575Sopenharmony_ci * 190d163575Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 200d163575Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 210d163575Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 220d163575Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 230d163575Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 240d163575Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 250d163575Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 260d163575Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 270d163575Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 280d163575Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 290d163575Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 300d163575Sopenharmony_ci */ 310d163575Sopenharmony_ci 320d163575Sopenharmony_ci#include <lwip/sockets.h> 330d163575Sopenharmony_ci#include <lwip/priv/tcpip_priv.h> 340d163575Sopenharmony_ci#include <lwip/fixme.h> 350d163575Sopenharmony_ci 360d163575Sopenharmony_ci#if LWIP_ENABLE_NET_CAPABILITY 370d163575Sopenharmony_ci#include "capability_type.h" 380d163575Sopenharmony_ci#include "capability_api.h" 390d163575Sopenharmony_ci#define BIND_SERVICE_CAP_MIN_PORT 1024 400d163575Sopenharmony_ci#endif 410d163575Sopenharmony_ci 420d163575Sopenharmony_ci#define IOCTL_CMD_CASE_HANDLER() \ 430d163575Sopenharmony_ci { \ 440d163575Sopenharmony_ci err_t err; \ 450d163575Sopenharmony_ci struct lwip_ioctl_apimsg msg; \ 460d163575Sopenharmony_ci msg.sock = sock; \ 470d163575Sopenharmony_ci msg.cmd = cmd; \ 480d163575Sopenharmony_ci msg.argp = argp; \ 490d163575Sopenharmony_ci \ 500d163575Sopenharmony_ci err = tcpip_api_call(lwip_do_ioctl_impl, &msg.call); \ 510d163575Sopenharmony_ci if (err != ENOSYS) { \ 520d163575Sopenharmony_ci sock_set_errno(sock, err); \ 530d163575Sopenharmony_ci done_socket(sock); \ 540d163575Sopenharmony_ci return -(err != ERR_OK); \ 550d163575Sopenharmony_ci } \ 560d163575Sopenharmony_ci } 570d163575Sopenharmony_ci 580d163575Sopenharmony_cistruct lwip_ioctl_apimsg { 590d163575Sopenharmony_ci struct tcpip_api_call_data call; 600d163575Sopenharmony_ci struct lwip_sock *sock; 610d163575Sopenharmony_ci long cmd; 620d163575Sopenharmony_ci void *argp; 630d163575Sopenharmony_ci}; 640d163575Sopenharmony_ci 650d163575Sopenharmony_cistatic err_t lwip_do_ioctl_impl(struct tcpip_api_call_data *call); 660d163575Sopenharmony_ci 670d163575Sopenharmony_cistatic void poll_check_waiters(int s, int check_waiters); 680d163575Sopenharmony_ci 690d163575Sopenharmony_cistatic int lwip_socket_wrap(int domain, int type, int protocol); 700d163575Sopenharmony_ciint lwip_socket(int domain, int type, int protocol) 710d163575Sopenharmony_ci{ 720d163575Sopenharmony_ci return lwip_socket_wrap(domain, type, protocol); 730d163575Sopenharmony_ci} 740d163575Sopenharmony_ci 750d163575Sopenharmony_cistatic int lwip_setsockopt_wrap(int s, int level, int optname, const void *optval, socklen_t optlen); 760d163575Sopenharmony_ciint lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) 770d163575Sopenharmony_ci{ 780d163575Sopenharmony_ci return lwip_setsockopt_wrap(s, level, optname, optval, optlen); 790d163575Sopenharmony_ci} 800d163575Sopenharmony_ci 810d163575Sopenharmony_cistatic int lwip_bind_wrap(int s, const struct sockaddr *name, socklen_t namelen); 820d163575Sopenharmony_ciint lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) 830d163575Sopenharmony_ci{ 840d163575Sopenharmony_ci return lwip_bind_wrap(s, name, namelen); 850d163575Sopenharmony_ci} 860d163575Sopenharmony_ci 870d163575Sopenharmony_cistatic ssize_t lwip_sendto_wrap(int s, const void *dataptr, size_t size, int flags, 880d163575Sopenharmony_ci const struct sockaddr *to, socklen_t tolen); 890d163575Sopenharmony_cissize_t lwip_sendto(int s, const void *dataptr, size_t size, int flags, const struct sockaddr *to, socklen_t tolen) 900d163575Sopenharmony_ci{ 910d163575Sopenharmony_ci return lwip_sendto_wrap(s, dataptr, size, flags, to, tolen); 920d163575Sopenharmony_ci} 930d163575Sopenharmony_ci 940d163575Sopenharmony_ci#ifdef lwip_socket 950d163575Sopenharmony_ci#undef lwip_socket 960d163575Sopenharmony_ci#endif 970d163575Sopenharmony_ci#define lwip_socket static lwip_socket2 980d163575Sopenharmony_cistatic int lwip_socket2(int domain, int type, int protocol); 990d163575Sopenharmony_ci 1000d163575Sopenharmony_ci#ifdef lwip_setsockopt 1010d163575Sopenharmony_ci#undef lwip_setsockopt 1020d163575Sopenharmony_ci#endif 1030d163575Sopenharmony_ci#define lwip_setsockopt static lwip_setsockopt2 1040d163575Sopenharmony_cistatic int lwip_setsockopt2(int s, int level, int optname, const void *optval, socklen_t optlen); 1050d163575Sopenharmony_ci 1060d163575Sopenharmony_ci#ifdef lwip_bind 1070d163575Sopenharmony_ci#undef lwip_bind 1080d163575Sopenharmony_ci#endif 1090d163575Sopenharmony_ci#define lwip_bind static lwip_bind2 1100d163575Sopenharmony_cistatic int lwip_bind2(int s, const struct sockaddr *name, socklen_t namelen); 1110d163575Sopenharmony_ci 1120d163575Sopenharmony_ci#ifdef lwip_sendto 1130d163575Sopenharmony_ci#undef lwip_sendto 1140d163575Sopenharmony_ci#endif 1150d163575Sopenharmony_ci#define lwip_sendto lwip_sendto2 1160d163575Sopenharmony_cissize_t lwip_sendto2(int s, const void *dataptr, size_t size, int flags, const struct sockaddr *to, socklen_t tolen); 1170d163575Sopenharmony_ci 1180d163575Sopenharmony_ci#include "../api/sockets.c" 1190d163575Sopenharmony_ci 1200d163575Sopenharmony_ci#undef lwip_socket 1210d163575Sopenharmony_ci#undef lwip_setsockopt 1220d163575Sopenharmony_ci#undef lwip_bind 1230d163575Sopenharmony_ci#undef lwip_sendto 1240d163575Sopenharmony_ci 1250d163575Sopenharmony_cistatic int lwip_socket_wrap(int domain, int type, int protocol) 1260d163575Sopenharmony_ci{ 1270d163575Sopenharmony_ci if (domain != AF_INET && domain != AF_INET6) { 1280d163575Sopenharmony_ci set_errno(EAFNOSUPPORT); 1290d163575Sopenharmony_ci return -1; 1300d163575Sopenharmony_ci } 1310d163575Sopenharmony_ci#if LWIP_ENABLE_NET_CAPABILITY 1320d163575Sopenharmony_ci if (type == SOCK_RAW && !IsCapPermit(CAP_NET_RAW)) { 1330d163575Sopenharmony_ci set_errno(EPERM); 1340d163575Sopenharmony_ci return -1; 1350d163575Sopenharmony_ci } 1360d163575Sopenharmony_ci#endif 1370d163575Sopenharmony_ci return lwip_socket2(domain, type, protocol); 1380d163575Sopenharmony_ci} 1390d163575Sopenharmony_ci 1400d163575Sopenharmony_cistatic int lwip_setsockopt_wrap(int s, int level, int optname, const void *optval, socklen_t optlen) 1410d163575Sopenharmony_ci{ 1420d163575Sopenharmony_ci#if LWIP_ENABLE_NET_CAPABILITY 1430d163575Sopenharmony_ci if (level == SOL_SOCKET) { 1440d163575Sopenharmony_ci switch (optname) { 1450d163575Sopenharmony_ci#if LWIP_ENABLE_CAP_NET_BROADCAST 1460d163575Sopenharmony_ci case SO_BROADCAST: 1470d163575Sopenharmony_ci if (!IsCapPermit(CAP_NET_BROADCAST)) { 1480d163575Sopenharmony_ci set_errno(EPERM); 1490d163575Sopenharmony_ci return -1; 1500d163575Sopenharmony_ci } 1510d163575Sopenharmony_ci break; 1520d163575Sopenharmony_ci#endif 1530d163575Sopenharmony_ci case SO_DEBUG: 1540d163575Sopenharmony_ci case SO_MARK: 1550d163575Sopenharmony_ci case SO_PRIORITY: 1560d163575Sopenharmony_ci case SO_RCVBUFFORCE: 1570d163575Sopenharmony_ci case SO_SNDBUFFORCE: 1580d163575Sopenharmony_ci if (!IsCapPermit(CAP_NET_ADMIN)) { 1590d163575Sopenharmony_ci set_errno(EPERM); 1600d163575Sopenharmony_ci return -1; 1610d163575Sopenharmony_ci } 1620d163575Sopenharmony_ci break; 1630d163575Sopenharmony_ci default: 1640d163575Sopenharmony_ci break; 1650d163575Sopenharmony_ci } 1660d163575Sopenharmony_ci } 1670d163575Sopenharmony_ci#endif 1680d163575Sopenharmony_ci return lwip_setsockopt2(s, level, optname, optval, optlen); 1690d163575Sopenharmony_ci} 1700d163575Sopenharmony_ci 1710d163575Sopenharmony_ci#if LWIP_ENABLE_NET_CAPABILITY && LWIP_ENABLE_CAP_NET_BROADCAST 1720d163575Sopenharmony_cistatic int ip_addr_isbroadcast_bysock(const ip_addr_t *ipaddr, int s) 1730d163575Sopenharmony_ci{ 1740d163575Sopenharmony_ci struct sockaddr sa; 1750d163575Sopenharmony_ci socklen_t salen = sizeof(sa); 1760d163575Sopenharmony_ci 1770d163575Sopenharmony_ci if (ipaddr == NULL) { 1780d163575Sopenharmony_ci return 0; 1790d163575Sopenharmony_ci } 1800d163575Sopenharmony_ci 1810d163575Sopenharmony_ci if (lwip_getsockname(s, &sa, &salen) == -1) { 1820d163575Sopenharmony_ci return 0; 1830d163575Sopenharmony_ci } 1840d163575Sopenharmony_ci 1850d163575Sopenharmony_ci ip_addr_t addr; 1860d163575Sopenharmony_ci u16_t port; 1870d163575Sopenharmony_ci 1880d163575Sopenharmony_ci SOCKADDR_TO_IPADDR_PORT(&sa, &addr, port); 1890d163575Sopenharmony_ci 1900d163575Sopenharmony_ci struct netif *netif = NULL; 1910d163575Sopenharmony_ci NETIF_FOREACH(netif) { 1920d163575Sopenharmony_ci if (ip_addr_cmp(&netif->ip_addr, &addr)) { 1930d163575Sopenharmony_ci return ip_addr_isbroadcast(ipaddr, netif); 1940d163575Sopenharmony_ci } 1950d163575Sopenharmony_ci for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 1960d163575Sopenharmony_ci if (ip_addr_cmp(&netif->ip6_addr[i], &addr)) { 1970d163575Sopenharmony_ci return ip_addr_isbroadcast(ipaddr, netif); 1980d163575Sopenharmony_ci } 1990d163575Sopenharmony_ci } 2000d163575Sopenharmony_ci } 2010d163575Sopenharmony_ci 2020d163575Sopenharmony_ci return 0; 2030d163575Sopenharmony_ci} 2040d163575Sopenharmony_ci#endif 2050d163575Sopenharmony_ci 2060d163575Sopenharmony_cistatic int lwip_bind_wrap(int s, const struct sockaddr *name, socklen_t namelen) 2070d163575Sopenharmony_ci{ 2080d163575Sopenharmony_ci#if LWIP_ENABLE_NET_CAPABILITY 2090d163575Sopenharmony_ci if ((name->sa_family == AF_INET && namelen >= sizeof(struct sockaddr_in)) || 2100d163575Sopenharmony_ci (name->sa_family == AF_INET6 && namelen >= sizeof(struct sockaddr_in6))) { 2110d163575Sopenharmony_ci ip_addr_t ipaddr; 2120d163575Sopenharmony_ci u16_t port; 2130d163575Sopenharmony_ci 2140d163575Sopenharmony_ci SOCKADDR_TO_IPADDR_PORT(name, &ipaddr, port); 2150d163575Sopenharmony_ci 2160d163575Sopenharmony_ci if (port != 0 && port < BIND_SERVICE_CAP_MIN_PORT) { 2170d163575Sopenharmony_ci LWIP_ERROR("permission deny: NET_BIND_SERVICE\n", IsCapPermit(CAP_NET_BIND_SERVICE), 2180d163575Sopenharmony_ci set_errno(EPERM); return -1); 2190d163575Sopenharmony_ci } 2200d163575Sopenharmony_ci#if LWIP_ENABLE_CAP_NET_BROADCAST 2210d163575Sopenharmony_ci if (ip_addr_ismulticast(&ipaddr) || ip_addr_isbroadcast_bysock(&ipaddr, s)) { 2220d163575Sopenharmony_ci LWIP_ERROR("permission deny: NET_BROADCAST\n", IsCapPermit(CAP_NET_BROADCAST), 2230d163575Sopenharmony_ci set_errno(EPERM); return -1); 2240d163575Sopenharmony_ci } 2250d163575Sopenharmony_ci#endif 2260d163575Sopenharmony_ci } 2270d163575Sopenharmony_ci#endif 2280d163575Sopenharmony_ci 2290d163575Sopenharmony_ci return lwip_bind2(s, name, namelen); 2300d163575Sopenharmony_ci} 2310d163575Sopenharmony_ci 2320d163575Sopenharmony_cistatic ssize_t lwip_sendto_wrap(int s, const void *dataptr, size_t size, int flags, 2330d163575Sopenharmony_ci const struct sockaddr *to, socklen_t tolen) 2340d163575Sopenharmony_ci{ 2350d163575Sopenharmony_ci#if LWIP_ENABLE_NET_CAPABILITY 2360d163575Sopenharmony_ci if (to && 2370d163575Sopenharmony_ci ((to->sa_family == AF_INET && tolen >= sizeof(struct sockaddr_in)) || 2380d163575Sopenharmony_ci (to->sa_family == AF_INET6 && tolen >= sizeof(struct sockaddr_in6)))) { 2390d163575Sopenharmony_ci ip_addr_t ipaddr; 2400d163575Sopenharmony_ci u16_t port; 2410d163575Sopenharmony_ci 2420d163575Sopenharmony_ci SOCKADDR_TO_IPADDR_PORT(to, &ipaddr, port); 2430d163575Sopenharmony_ci#if LWIP_ENABLE_CAP_NET_BROADCAST 2440d163575Sopenharmony_ci if (ip_addr_ismulticast(&ipaddr) || ip_addr_isbroadcast_bysock(&ipaddr, s)) { 2450d163575Sopenharmony_ci LWIP_ERROR("permission deny: NET_BROADCAST\n", IsCapPermit(CAP_NET_BROADCAST), 2460d163575Sopenharmony_ci set_errno(EPERM); return -1); 2470d163575Sopenharmony_ci } 2480d163575Sopenharmony_ci#endif 2490d163575Sopenharmony_ci } 2500d163575Sopenharmony_ci#endif 2510d163575Sopenharmony_ci 2520d163575Sopenharmony_ci return lwip_sendto2(s, dataptr, size, flags, to, tolen); 2530d163575Sopenharmony_ci} 2540d163575Sopenharmony_ci 2550d163575Sopenharmony_ci#if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL 2560d163575Sopenharmony_ci 2570d163575Sopenharmony_cistruct file; 2580d163575Sopenharmony_ciextern void poll_wait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p); 2590d163575Sopenharmony_ciextern void __wake_up_interruptible_poll(wait_queue_head_t *wait, pollevent_t key); 2600d163575Sopenharmony_ci 2610d163575Sopenharmony_cistatic void poll_check_waiters(int s, int check_waiters) 2620d163575Sopenharmony_ci{ 2630d163575Sopenharmony_ci unsigned long int_save, wq_empty; 2640d163575Sopenharmony_ci pollevent_t mask = 0; 2650d163575Sopenharmony_ci struct lwip_sock *sock; 2660d163575Sopenharmony_ci SYS_ARCH_DECL_PROTECT(lev); 2670d163575Sopenharmony_ci 2680d163575Sopenharmony_ci if (!check_waiters) { 2690d163575Sopenharmony_ci return; 2700d163575Sopenharmony_ci } 2710d163575Sopenharmony_ci 2720d163575Sopenharmony_ci sock = get_socket(s); 2730d163575Sopenharmony_ci if (!sock) { 2740d163575Sopenharmony_ci return; 2750d163575Sopenharmony_ci } 2760d163575Sopenharmony_ci 2770d163575Sopenharmony_ci SYS_ARCH_PROTECT(lev); 2780d163575Sopenharmony_ci 2790d163575Sopenharmony_ci mask |= (sock->rcvevent > 0) ? (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND) : 0; 2800d163575Sopenharmony_ci mask |= (sock->sendevent != 0) ? (POLLOUT | POLLWRNORM | POLLWRBAND) : 0; 2810d163575Sopenharmony_ci mask |= (sock->errevent != 0) ? (POLLERR) : 0; 2820d163575Sopenharmony_ci 2830d163575Sopenharmony_ci SYS_ARCH_UNPROTECT(lev); 2840d163575Sopenharmony_ci 2850d163575Sopenharmony_ci spin_lock_irqsave(&sock->wq.lock, int_save); 2860d163575Sopenharmony_ci wq_empty = LOS_ListEmpty(&(sock->wq.poll_queue)); 2870d163575Sopenharmony_ci spin_unlock_irqrestore(&sock->wq.lock, int_save); 2880d163575Sopenharmony_ci 2890d163575Sopenharmony_ci if (mask && !wq_empty) { 2900d163575Sopenharmony_ci __wake_up_interruptible_poll(&sock->wq, mask); 2910d163575Sopenharmony_ci } 2920d163575Sopenharmony_ci 2930d163575Sopenharmony_ci done_socket(sock); 2940d163575Sopenharmony_ci} 2950d163575Sopenharmony_ci 2960d163575Sopenharmony_ciint socks_poll(int s, poll_table *wait) 2970d163575Sopenharmony_ci{ 2980d163575Sopenharmony_ci int ret; 2990d163575Sopenharmony_ci pollevent_t mask = 0; 3000d163575Sopenharmony_ci struct lwip_sock *sock; 3010d163575Sopenharmony_ci SYS_ARCH_DECL_PROTECT(lev); 3020d163575Sopenharmony_ci 3030d163575Sopenharmony_ci LWIP_ERROR("sock_poll: invalid poll_table", (wait != NULL), return -EINVAL;); 3040d163575Sopenharmony_ci 3050d163575Sopenharmony_ci sock = get_socket(s); 3060d163575Sopenharmony_ci if (!sock) { 3070d163575Sopenharmony_ci LWIP_DEBUGF(SOCKETS_DEBUG, ("sock_poll: Invalid socket")); 3080d163575Sopenharmony_ci set_errno(EBADF); 3090d163575Sopenharmony_ci return -EBADF; /* compatible with file poll */ 3100d163575Sopenharmony_ci } 3110d163575Sopenharmony_ci 3120d163575Sopenharmony_ci SYS_ARCH_PROTECT(lev); 3130d163575Sopenharmony_ci 3140d163575Sopenharmony_ci mask |= (sock->rcvevent > 0 || sock->lastdata.pbuf) ? (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND) : 0; 3150d163575Sopenharmony_ci mask |= (sock->sendevent != 0) ? (POLLOUT | POLLWRNORM | POLLWRBAND) : 0; 3160d163575Sopenharmony_ci mask |= (sock->errevent != 0) ? (POLLERR) : 0; 3170d163575Sopenharmony_ci 3180d163575Sopenharmony_ci SYS_ARCH_UNPROTECT(lev); 3190d163575Sopenharmony_ci 3200d163575Sopenharmony_ci ret = wait->key & mask; 3210d163575Sopenharmony_ci if (!ret) { 3220d163575Sopenharmony_ci poll_wait(NULL, &sock->wq, wait); 3230d163575Sopenharmony_ci } 3240d163575Sopenharmony_ci 3250d163575Sopenharmony_ci done_socket(sock); 3260d163575Sopenharmony_ci return ret; 3270d163575Sopenharmony_ci} 3280d163575Sopenharmony_ci 3290d163575Sopenharmony_ci#endif /* LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL */ 3300d163575Sopenharmony_ci 3310d163575Sopenharmony_ci#if !LWIP_COMPAT_SOCKETS 3320d163575Sopenharmony_ci 3330d163575Sopenharmony_ci#define API_ALIAS(old, new) \ 3340d163575Sopenharmony_ci extern __typeof(old) new __attribute__((__weak__, __alias__(#old))) 3350d163575Sopenharmony_ci 3360d163575Sopenharmony_ciAPI_ALIAS(lwip_ioctl, ioctlsocket); 3370d163575Sopenharmony_ci 3380d163575Sopenharmony_ci#endif /* !LWIP_COMPAT_SOCKETS */ 3390d163575Sopenharmony_ci 3400d163575Sopenharmony_ci#if LWIP_ENABLE_LOS_SHELL_CMD 3410d163575Sopenharmony_ci/* get numbers of unused sockets */ 3420d163575Sopenharmony_ciint get_unused_socket_num(void) 3430d163575Sopenharmony_ci{ 3440d163575Sopenharmony_ci int unused = 0; 3450d163575Sopenharmony_ci SYS_ARCH_DECL_PROTECT(lev); 3460d163575Sopenharmony_ci 3470d163575Sopenharmony_ci SYS_ARCH_PROTECT(lev); 3480d163575Sopenharmony_ci 3490d163575Sopenharmony_ci for (int i = 0; i < NUM_SOCKETS; i++) { 3500d163575Sopenharmony_ci if (sockets[i].conn == NULL) { 3510d163575Sopenharmony_ci#if LWIP_NETCONN_FULLDUPLEX 3520d163575Sopenharmony_ci if (sockets[i].fd_used) { 3530d163575Sopenharmony_ci continue; 3540d163575Sopenharmony_ci } 3550d163575Sopenharmony_ci#endif 3560d163575Sopenharmony_ci unused++; 3570d163575Sopenharmony_ci } 3580d163575Sopenharmony_ci } 3590d163575Sopenharmony_ci 3600d163575Sopenharmony_ci SYS_ARCH_UNPROTECT(lev); 3610d163575Sopenharmony_ci 3620d163575Sopenharmony_ci return unused; 3630d163575Sopenharmony_ci} 3640d163575Sopenharmony_ci#endif 3650d163575Sopenharmony_ci 3660d163575Sopenharmony_ci/** 3670d163575Sopenharmony_ci * socket ioctl 3680d163575Sopenharmony_ci */ 3690d163575Sopenharmony_ci 3700d163575Sopenharmony_ci// Options for lwip ioctl 3710d163575Sopenharmony_ci#define LWIP_IOCTL_ROUTE 1 3720d163575Sopenharmony_ci#define LWIP_IOCTL_IF 1 3730d163575Sopenharmony_ci#define LWIP_NETIF_ETHTOOL 0 3740d163575Sopenharmony_ci#define LWIP_IOCTL_IPV6DPCTD 0 3750d163575Sopenharmony_ci#undef LWIP_IPV6_DUP_DETECT_ATTEMPTS 3760d163575Sopenharmony_ci#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 0 3770d163575Sopenharmony_ci 3780d163575Sopenharmony_ci#ifndef SIOCSIPV6DAD 3790d163575Sopenharmony_ci#define SIOCSIPV6DAD _IOW('z', 0, unsigned long) /* set DAD enable/disable on netif */ 3800d163575Sopenharmony_ci#endif 3810d163575Sopenharmony_ci 3820d163575Sopenharmony_ci#ifndef SIOCGIPV6DAD 3830d163575Sopenharmony_ci#define SIOCGIPV6DAD _IOR('z', 1, unsigned long) /* get DAD status on netif */ 3840d163575Sopenharmony_ci#endif 3850d163575Sopenharmony_ci 3860d163575Sopenharmony_ci#ifndef SIOCSIPV6DPCTD 3870d163575Sopenharmony_ci#define SIOCSIPV6DPCTD _IOW('z', 2, unsigned long) 3880d163575Sopenharmony_ci#endif 3890d163575Sopenharmony_ci 3900d163575Sopenharmony_ci#ifndef SIOCGIPV6DPCTD 3910d163575Sopenharmony_ci#define SIOCGIPV6DPCTD _IOR('z', 3, unsigned long) 3920d163575Sopenharmony_ci#endif 3930d163575Sopenharmony_ci 3940d163575Sopenharmony_ci#ifndef SIOCETHTOOL 3950d163575Sopenharmony_ci#define SIOCETHTOOL 0x8946 3960d163575Sopenharmony_ci#endif 3970d163575Sopenharmony_ci 3980d163575Sopenharmony_ci#if LWIP_NETIF_PROMISC 3990d163575Sopenharmony_ci#define NETIF_FLAG_PROMISC 0x80U 4000d163575Sopenharmony_ci#endif /* LWIP_NETIF_PROMISC */ 4010d163575Sopenharmony_ci 4020d163575Sopenharmony_ci 4030d163575Sopenharmony_ci#if LWIP_IOCTL_ROUTE 4040d163575Sopenharmony_ci 4050d163575Sopenharmony_ci#include <net/route.h> 4060d163575Sopenharmony_ci 4070d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 4080d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCADDRT(struct rtentry *rmten, struct net_group *group) 4090d163575Sopenharmony_ci#else 4100d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCADDRT(struct rtentry *rmten) 4110d163575Sopenharmony_ci#endif 4120d163575Sopenharmony_ci{ 4130d163575Sopenharmony_ci struct netif *netif = NULL; 4140d163575Sopenharmony_ci ip_addr_t rtgw_addr; 4150d163575Sopenharmony_ci u16_t rtgw_port; 4160d163575Sopenharmony_ci 4170d163575Sopenharmony_ci#if LWIP_ENABLE_NET_CAPABILITY 4180d163575Sopenharmony_ci if (!IsCapPermit(CAP_NET_ADMIN)) { 4190d163575Sopenharmony_ci return EPERM; 4200d163575Sopenharmony_ci } 4210d163575Sopenharmony_ci#endif 4220d163575Sopenharmony_ci 4230d163575Sopenharmony_ci SOCKADDR_TO_IPADDR_PORT(&rmten->rt_gateway, &rtgw_addr, rtgw_port); 4240d163575Sopenharmony_ci 4250d163575Sopenharmony_ci if (!IP_IS_V4_VAL(rtgw_addr)) { 4260d163575Sopenharmony_ci return EINVAL; 4270d163575Sopenharmony_ci } 4280d163575Sopenharmony_ci 4290d163575Sopenharmony_ci /* check if multicast/0/loopback */ 4300d163575Sopenharmony_ci if (ip_addr_ismulticast(&rtgw_addr) || ip_addr_isany(&rtgw_addr) || 4310d163575Sopenharmony_ci ip_addr_isloopback(&rtgw_addr)) { 4320d163575Sopenharmony_ci return EINVAL; 4330d163575Sopenharmony_ci } 4340d163575Sopenharmony_ci 4350d163575Sopenharmony_ci /* check if reachable */ 4360d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 4370d163575Sopenharmony_ci for (netif = group->netif_list; netif != NULL; netif = netif->next) { 4380d163575Sopenharmony_ci#else 4390d163575Sopenharmony_ci for (netif = netif_list; netif != NULL; netif = netif->next) { 4400d163575Sopenharmony_ci#endif 4410d163575Sopenharmony_ci if (ip_addr_netcmp(&rtgw_addr, &netif->ip_addr, ip_2_ip4(&netif->netmask))) { 4420d163575Sopenharmony_ci break; 4430d163575Sopenharmony_ci } 4440d163575Sopenharmony_ci } 4450d163575Sopenharmony_ci 4460d163575Sopenharmony_ci if (netif == NULL) { 4470d163575Sopenharmony_ci return EHOSTUNREACH; 4480d163575Sopenharmony_ci } 4490d163575Sopenharmony_ci 4500d163575Sopenharmony_ci /* check if broadcast */ 4510d163575Sopenharmony_ci if (ip_addr_isbroadcast(&rtgw_addr, netif) != 0) { 4520d163575Sopenharmony_ci return EINVAL; 4530d163575Sopenharmony_ci } 4540d163575Sopenharmony_ci 4550d163575Sopenharmony_ci /* Check flags */ 4560d163575Sopenharmony_ci if ((rmten->rt_flags & RTF_GATEWAY) == 0) { 4570d163575Sopenharmony_ci return EINVAL; 4580d163575Sopenharmony_ci } 4590d163575Sopenharmony_ci 4600d163575Sopenharmony_ci /* Add validation */ 4610d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 4620d163575Sopenharmony_ci if ((group->netif_default != NULL) && (group->netif_default != netif)) { 4630d163575Sopenharmony_ci ip_addr_set_zero(&group->netif_default->gw); 4640d163575Sopenharmony_ci (void)netif_set_default(netif, group); 4650d163575Sopenharmony_ci#else 4660d163575Sopenharmony_ci if ((netif_default != NULL) && (netif_default != netif)) { 4670d163575Sopenharmony_ci ip_addr_set_zero(&netif_default->gw); 4680d163575Sopenharmony_ci (void)netif_set_default(netif); 4690d163575Sopenharmony_ci#endif 4700d163575Sopenharmony_ci } 4710d163575Sopenharmony_ci netif_set_gw(netif, ip_2_ip4(&rtgw_addr)); 4720d163575Sopenharmony_ci 4730d163575Sopenharmony_ci return 0; 4740d163575Sopenharmony_ci} 4750d163575Sopenharmony_ci 4760d163575Sopenharmony_ci#endif 4770d163575Sopenharmony_ci 4780d163575Sopenharmony_ci#if LWIP_IOCTL_IF 4790d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 4800d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCGIFCONF(struct ifreq *ifr, struct net_group *group) 4810d163575Sopenharmony_ci#else 4820d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCGIFCONF(struct ifreq *ifr) 4830d163575Sopenharmony_ci#endif 4840d163575Sopenharmony_ci{ 4850d163575Sopenharmony_ci struct ifconf *ifc = NULL; 4860d163575Sopenharmony_ci struct netif *netif = NULL; 4870d163575Sopenharmony_ci struct ifreq ifreq; 4880d163575Sopenharmony_ci struct sockaddr_in *sock_in = NULL; 4890d163575Sopenharmony_ci int pos; 4900d163575Sopenharmony_ci int len; 4910d163575Sopenharmony_ci int ret; 4920d163575Sopenharmony_ci 4930d163575Sopenharmony_ci /* Format the caller's buffer. */ 4940d163575Sopenharmony_ci ifc = (struct ifconf *)ifr; 4950d163575Sopenharmony_ci len = ifc->ifc_len; 4960d163575Sopenharmony_ci 4970d163575Sopenharmony_ci /* Loop over the interfaces, and write an info block for each. */ 4980d163575Sopenharmony_ci pos = 0; 4990d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 5000d163575Sopenharmony_ci for (netif = group->netif_list; netif != NULL; netif = netif->next) { 5010d163575Sopenharmony_ci#else 5020d163575Sopenharmony_ci for (netif = netif_list; netif != NULL; netif = netif->next) { 5030d163575Sopenharmony_ci#endif 5040d163575Sopenharmony_ci if (ifc->ifc_buf == NULL) { 5050d163575Sopenharmony_ci pos = (pos + (int)sizeof(struct ifreq)); 5060d163575Sopenharmony_ci continue; 5070d163575Sopenharmony_ci } 5080d163575Sopenharmony_ci 5090d163575Sopenharmony_ci if (len < (int)sizeof(ifreq)) { 5100d163575Sopenharmony_ci break; 5110d163575Sopenharmony_ci } 5120d163575Sopenharmony_ci (void)memset_s(&ifreq, sizeof(struct ifreq), 0, sizeof(struct ifreq)); 5130d163575Sopenharmony_ci if (netif->link_layer_type == LOOPBACK_IF) { 5140d163575Sopenharmony_ci ret = snprintf_s(ifreq.ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%.2s", netif->name); 5150d163575Sopenharmony_ci if ((ret <= 0) || (ret >= IFNAMSIZ)) { 5160d163575Sopenharmony_ci LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed.")); 5170d163575Sopenharmony_ci return ENOBUFS; 5180d163575Sopenharmony_ci } 5190d163575Sopenharmony_ci } else { 5200d163575Sopenharmony_ci ret = snprintf_s(ifreq.ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%s", netif_get_name(netif)); 5210d163575Sopenharmony_ci if ((ret <= 0) || (ret >= IFNAMSIZ)) { 5220d163575Sopenharmony_ci LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed.")); 5230d163575Sopenharmony_ci return ENOBUFS; 5240d163575Sopenharmony_ci } 5250d163575Sopenharmony_ci } 5260d163575Sopenharmony_ci 5270d163575Sopenharmony_ci sock_in = (struct sockaddr_in *)&ifreq.ifr_addr; 5280d163575Sopenharmony_ci sock_in->sin_family = AF_INET; 5290d163575Sopenharmony_ci sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr; 5300d163575Sopenharmony_ci if (memcpy_s(ifc->ifc_buf + pos, sizeof(struct ifreq), &ifreq, sizeof(struct ifreq)) != EOK) { 5310d163575Sopenharmony_ci return ENOBUFS; 5320d163575Sopenharmony_ci } 5330d163575Sopenharmony_ci pos = pos + (int)sizeof(struct ifreq); 5340d163575Sopenharmony_ci len = len - (int)sizeof(struct ifreq); 5350d163575Sopenharmony_ci } 5360d163575Sopenharmony_ci 5370d163575Sopenharmony_ci ifc->ifc_len = pos; 5380d163575Sopenharmony_ci 5390d163575Sopenharmony_ci return 0; 5400d163575Sopenharmony_ci} 5410d163575Sopenharmony_ci 5420d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCGIFADDR(struct ifreq *ifr) 5430d163575Sopenharmony_ci{ 5440d163575Sopenharmony_ci struct netif *netif = NULL; 5450d163575Sopenharmony_ci struct sockaddr_in *sock_in = NULL; 5460d163575Sopenharmony_ci 5470d163575Sopenharmony_ci /* get netif ipaddr */ 5480d163575Sopenharmony_ci netif = netif_find(ifr->ifr_name); 5490d163575Sopenharmony_ci if (netif == NULL) { 5500d163575Sopenharmony_ci return ENODEV; 5510d163575Sopenharmony_ci } else { 5520d163575Sopenharmony_ci sock_in = (struct sockaddr_in *)&ifr->ifr_addr; 5530d163575Sopenharmony_ci sock_in->sin_family = AF_INET; 5540d163575Sopenharmony_ci sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr; 5550d163575Sopenharmony_ci return 0; 5560d163575Sopenharmony_ci } 5570d163575Sopenharmony_ci} 5580d163575Sopenharmony_ci 5590d163575Sopenharmony_ci#ifndef LWIP_IPV6_PREFIX_LEN 5600d163575Sopenharmony_ci#define LWIP_IPV6_PREFIX_LEN 64 5610d163575Sopenharmony_ci#endif 5620d163575Sopenharmony_ci 5630d163575Sopenharmony_ci#ifndef LWIP_NETIF_IFINDEX_MAX_EX 5640d163575Sopenharmony_ci#define LWIP_NETIF_IFINDEX_MAX_EX 255 5650d163575Sopenharmony_ci#endif 5660d163575Sopenharmony_ci 5670d163575Sopenharmony_ci#include "lwip/dhcp.h" 5680d163575Sopenharmony_ci#include "lwip/dhcp6.h" 5690d163575Sopenharmony_ci#include "lwip/prot/dhcp.h" 5700d163575Sopenharmony_ci#include "lwip/prot/dhcp6.h" 5710d163575Sopenharmony_ci 5720d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCSIFADDR_6(struct ifreq *ifr) 5730d163575Sopenharmony_ci{ 5740d163575Sopenharmony_ci (void)ifr; 5750d163575Sopenharmony_ci return ENOSYS; 5760d163575Sopenharmony_ci} 5770d163575Sopenharmony_ci 5780d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 5790d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCSIFADDR(struct ifreq *ifr, struct net_group *group) 5800d163575Sopenharmony_ci#else 5810d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCSIFADDR(struct ifreq *ifr) 5820d163575Sopenharmony_ci#endif 5830d163575Sopenharmony_ci{ 5840d163575Sopenharmony_ci struct netif *netif = NULL; 5850d163575Sopenharmony_ci 5860d163575Sopenharmony_ci struct netif *loc_netif = NULL; 5870d163575Sopenharmony_ci ip_addr_t taget_addr; 5880d163575Sopenharmony_ci u16_t taget_port; 5890d163575Sopenharmony_ci SOCKADDR_TO_IPADDR_PORT(&ifr->ifr_addr, &taget_addr, taget_port); 5900d163575Sopenharmony_ci 5910d163575Sopenharmony_ci#if LWIP_ENABLE_NET_CAPABILITY 5920d163575Sopenharmony_ci if (!IsCapPermit(CAP_NET_ADMIN)) { 5930d163575Sopenharmony_ci return EPERM; 5940d163575Sopenharmony_ci } 5950d163575Sopenharmony_ci#endif 5960d163575Sopenharmony_ci 5970d163575Sopenharmony_ci /* set netif ipaddr */ 5980d163575Sopenharmony_ci netif = netif_find(ifr->ifr_name); 5990d163575Sopenharmony_ci if (netif == NULL) { 6000d163575Sopenharmony_ci return ENODEV; 6010d163575Sopenharmony_ci } 6020d163575Sopenharmony_ci#if LWIP_HAVE_LOOPIF 6030d163575Sopenharmony_ci else if (netif->link_layer_type == LOOPBACK_IF) { 6040d163575Sopenharmony_ci return EPERM; 6050d163575Sopenharmony_ci } 6060d163575Sopenharmony_ci#endif 6070d163575Sopenharmony_ci else { 6080d163575Sopenharmony_ci /* check the address is not multicast/broadcast/0/loopback */ 6090d163575Sopenharmony_ci if (!IP_IS_V4(&taget_addr) || ip_addr_ismulticast(&taget_addr) || 6100d163575Sopenharmony_ci ip_addr_isbroadcast(&taget_addr, netif) || 6110d163575Sopenharmony_ci ip_addr_isany(&taget_addr) || 6120d163575Sopenharmony_ci ip_addr_isloopback(&taget_addr)) { 6130d163575Sopenharmony_ci return EINVAL; 6140d163575Sopenharmony_ci } 6150d163575Sopenharmony_ci 6160d163575Sopenharmony_ci /* reset gateway if new and previous ipaddr not in same net */ 6170d163575Sopenharmony_ci if (ip_addr_netcmp(&taget_addr, &netif->ip_addr, ip_2_ip4(&netif->netmask)) == 0) { 6180d163575Sopenharmony_ci ip_addr_set_zero(&netif->gw); 6190d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 6200d163575Sopenharmony_ci if (netif == group->netif_default) { 6210d163575Sopenharmony_ci (void)netif_set_default(NULL, group); 6220d163575Sopenharmony_ci#else 6230d163575Sopenharmony_ci if (netif == netif_default) { 6240d163575Sopenharmony_ci (void)netif_set_default(NULL); 6250d163575Sopenharmony_ci#endif 6260d163575Sopenharmony_ci } 6270d163575Sopenharmony_ci } 6280d163575Sopenharmony_ci 6290d163575Sopenharmony_ci /* lwip disallow two netif sit in same net at the same time */ 6300d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 6310d163575Sopenharmony_ci loc_netif = group->netif_list; 6320d163575Sopenharmony_ci#else 6330d163575Sopenharmony_ci loc_netif = netif_list; 6340d163575Sopenharmony_ci#endif 6350d163575Sopenharmony_ci while (loc_netif != NULL) { 6360d163575Sopenharmony_ci if (loc_netif == netif) { 6370d163575Sopenharmony_ci loc_netif = loc_netif->next; 6380d163575Sopenharmony_ci continue; 6390d163575Sopenharmony_ci } 6400d163575Sopenharmony_ci if (ip_addr_cmp(&netif->netmask, &loc_netif->netmask) && 6410d163575Sopenharmony_ci ip_addr_netcmp(&loc_netif->ip_addr, &taget_addr, 6420d163575Sopenharmony_ci ip_2_ip4(&netif->netmask))) { 6430d163575Sopenharmony_ci return EINVAL; 6440d163575Sopenharmony_ci } 6450d163575Sopenharmony_ci loc_netif = loc_netif->next; 6460d163575Sopenharmony_ci } 6470d163575Sopenharmony_ci 6480d163575Sopenharmony_ci#if LWIP_DHCP 6490d163575Sopenharmony_ci if ((netif_dhcp_data(netif) != NULL) && 6500d163575Sopenharmony_ci (netif_dhcp_data(netif)->state != DHCP_STATE_OFF)) { 6510d163575Sopenharmony_ci (void)netif_dhcp_off(netif); 6520d163575Sopenharmony_ci } 6530d163575Sopenharmony_ci#endif 6540d163575Sopenharmony_ci 6550d163575Sopenharmony_ci#if LWIP_ARP 6560d163575Sopenharmony_ci /* clear ARP cache when IP address changed */ 6570d163575Sopenharmony_ci if ((netif->flags & NETIF_FLAG_ETHARP) != 0) { 6580d163575Sopenharmony_ci etharp_cleanup_netif(netif); 6590d163575Sopenharmony_ci } 6600d163575Sopenharmony_ci#endif /* LWIP_ARP */ 6610d163575Sopenharmony_ci 6620d163575Sopenharmony_ci netif_set_ipaddr(netif, ip_2_ip4(&taget_addr)); 6630d163575Sopenharmony_ci 6640d163575Sopenharmony_ci return 0; 6650d163575Sopenharmony_ci } 6660d163575Sopenharmony_ci} 6670d163575Sopenharmony_ci 6680d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCDIFADDR_6(struct ifreq *ifr) 6690d163575Sopenharmony_ci{ 6700d163575Sopenharmony_ci (void)ifr; 6710d163575Sopenharmony_ci return ENOSYS; 6720d163575Sopenharmony_ci} 6730d163575Sopenharmony_ci 6740d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 6750d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCDIFADDR(struct ifreq *ifr, struct net_group *group) 6760d163575Sopenharmony_ci#else 6770d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCDIFADDR(struct ifreq *ifr) 6780d163575Sopenharmony_ci#endif 6790d163575Sopenharmony_ci{ 6800d163575Sopenharmony_ci struct netif *netif = NULL; 6810d163575Sopenharmony_ci 6820d163575Sopenharmony_ci ip_addr_t target_addr; 6830d163575Sopenharmony_ci u16_t target_port; 6840d163575Sopenharmony_ci 6850d163575Sopenharmony_ci SOCKADDR_TO_IPADDR_PORT(&ifr->ifr_addr, &target_addr, target_port); 6860d163575Sopenharmony_ci 6870d163575Sopenharmony_ci#if LWIP_ENABLE_NET_CAPABILITY 6880d163575Sopenharmony_ci if (!IsCapPermit(CAP_NET_ADMIN)) { 6890d163575Sopenharmony_ci return EPERM; 6900d163575Sopenharmony_ci } 6910d163575Sopenharmony_ci#endif 6920d163575Sopenharmony_ci 6930d163575Sopenharmony_ci /* set netif ipaddr */ 6940d163575Sopenharmony_ci netif = netif_find(ifr->ifr_name); 6950d163575Sopenharmony_ci if (netif == NULL) { 6960d163575Sopenharmony_ci return ENODEV; 6970d163575Sopenharmony_ci } 6980d163575Sopenharmony_ci#if LWIP_HAVE_LOOPIF 6990d163575Sopenharmony_ci else if (netif->link_layer_type == LOOPBACK_IF) { 7000d163575Sopenharmony_ci return EPERM; 7010d163575Sopenharmony_ci } 7020d163575Sopenharmony_ci#endif 7030d163575Sopenharmony_ci 7040d163575Sopenharmony_ci /* check the address is not loopback */ 7050d163575Sopenharmony_ci if (!IP_IS_V4(&target_addr) || ip_addr_isloopback(&target_addr)) { 7060d163575Sopenharmony_ci return EINVAL; 7070d163575Sopenharmony_ci } 7080d163575Sopenharmony_ci 7090d163575Sopenharmony_ci#if LWIP_DHCP 7100d163575Sopenharmony_ci if ((netif_dhcp_data(netif) != NULL) && 7110d163575Sopenharmony_ci (netif_dhcp_data(netif)->state != DHCP_STATE_OFF)) { 7120d163575Sopenharmony_ci (void)netif_dhcp_off(netif); 7130d163575Sopenharmony_ci } 7140d163575Sopenharmony_ci#endif 7150d163575Sopenharmony_ci 7160d163575Sopenharmony_ci ip_addr_set_zero(&netif->gw); 7170d163575Sopenharmony_ci ip_addr_set_zero(&netif->ip_addr); 7180d163575Sopenharmony_ci ip_addr_set_zero(&netif->netmask); 7190d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 7200d163575Sopenharmony_ci if (netif == group->netif_default) { 7210d163575Sopenharmony_ci (void)netif_set_default(NULL, group); 7220d163575Sopenharmony_ci#else 7230d163575Sopenharmony_ci if (netif == netif_default) { 7240d163575Sopenharmony_ci (void)netif_set_default(NULL); 7250d163575Sopenharmony_ci#endif 7260d163575Sopenharmony_ci } 7270d163575Sopenharmony_ci 7280d163575Sopenharmony_ci#if LWIP_IPV4 && LWIP_ARP 7290d163575Sopenharmony_ci if ((netif->flags & NETIF_FLAG_ETHARP) != 0) { 7300d163575Sopenharmony_ci etharp_cleanup_netif(netif); 7310d163575Sopenharmony_ci } 7320d163575Sopenharmony_ci#endif /* LWIP_IPV4 && LWIP_ARP */ 7330d163575Sopenharmony_ci 7340d163575Sopenharmony_ci return ERR_OK; 7350d163575Sopenharmony_ci} 7360d163575Sopenharmony_ci 7370d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCGIFNETMASK(struct ifreq *ifr) 7380d163575Sopenharmony_ci{ 7390d163575Sopenharmony_ci struct netif *netif = NULL; 7400d163575Sopenharmony_ci struct sockaddr_in *sock_in = NULL; 7410d163575Sopenharmony_ci 7420d163575Sopenharmony_ci /* get netif netmask */ 7430d163575Sopenharmony_ci netif = netif_find(ifr->ifr_name); 7440d163575Sopenharmony_ci if (netif == NULL) { 7450d163575Sopenharmony_ci return ENODEV; 7460d163575Sopenharmony_ci } else { 7470d163575Sopenharmony_ci sock_in = (struct sockaddr_in *)&ifr->ifr_netmask; 7480d163575Sopenharmony_ci sock_in->sin_family = AF_INET; 7490d163575Sopenharmony_ci sock_in->sin_addr.s_addr = ip_2_ip4(&netif->netmask)->addr; 7500d163575Sopenharmony_ci return 0; 7510d163575Sopenharmony_ci } 7520d163575Sopenharmony_ci} 7530d163575Sopenharmony_ci 7540d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 7550d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCSIFNETMASK(struct ifreq *ifr, struct net_group *group) 7560d163575Sopenharmony_ci#else 7570d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCSIFNETMASK(struct ifreq *ifr) 7580d163575Sopenharmony_ci#endif 7590d163575Sopenharmony_ci{ 7600d163575Sopenharmony_ci struct netif *netif = NULL; 7610d163575Sopenharmony_ci 7620d163575Sopenharmony_ci struct netif *loc_netif = NULL; 7630d163575Sopenharmony_ci ip_addr_t taget_addr; 7640d163575Sopenharmony_ci u16_t taget_port; 7650d163575Sopenharmony_ci SOCKADDR_TO_IPADDR_PORT(&ifr->ifr_addr, &taget_addr, taget_port); 7660d163575Sopenharmony_ci 7670d163575Sopenharmony_ci#if LWIP_ENABLE_NET_CAPABILITY 7680d163575Sopenharmony_ci if (!IsCapPermit(CAP_NET_ADMIN)) { 7690d163575Sopenharmony_ci return EPERM; 7700d163575Sopenharmony_ci } 7710d163575Sopenharmony_ci#endif 7720d163575Sopenharmony_ci 7730d163575Sopenharmony_ci if (!IP_IS_V4(&taget_addr)) { 7740d163575Sopenharmony_ci return EINVAL; 7750d163575Sopenharmony_ci } 7760d163575Sopenharmony_ci 7770d163575Sopenharmony_ci /* set netif netmask */ 7780d163575Sopenharmony_ci netif = netif_find(ifr->ifr_name); 7790d163575Sopenharmony_ci if (netif == NULL) { 7800d163575Sopenharmony_ci return ENODEV; 7810d163575Sopenharmony_ci } 7820d163575Sopenharmony_ci#if LWIP_HAVE_LOOPIF 7830d163575Sopenharmony_ci else if (netif->link_layer_type == LOOPBACK_IF) { 7840d163575Sopenharmony_ci return EPERM; 7850d163575Sopenharmony_ci } 7860d163575Sopenharmony_ci#endif 7870d163575Sopenharmony_ci else { 7880d163575Sopenharmony_ci if (ip_addr_cmp(&netif->netmask, &taget_addr)) { 7890d163575Sopenharmony_ci return 0; 7900d163575Sopenharmony_ci } 7910d163575Sopenharmony_ci /* check data valid */ 7920d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 7930d163575Sopenharmony_ci if (ip_addr_netmask_valid(ip_2_ip4(&taget_addr)) == 0) { 7940d163575Sopenharmony_ci#else 7950d163575Sopenharmony_ci if (ip_addr_netmask_valid(ip_2_ip4(&taget_addr)) != 0) { 7960d163575Sopenharmony_ci#endif 7970d163575Sopenharmony_ci return EINVAL; 7980d163575Sopenharmony_ci } 7990d163575Sopenharmony_ci 8000d163575Sopenharmony_ci /* lwip disallow two netif sit in same net at the same time */ 8010d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 8020d163575Sopenharmony_ci loc_netif = group->netif_list; 8030d163575Sopenharmony_ci#else 8040d163575Sopenharmony_ci loc_netif = netif_list; 8050d163575Sopenharmony_ci#endif 8060d163575Sopenharmony_ci while (loc_netif != NULL) { 8070d163575Sopenharmony_ci if (loc_netif == netif) { 8080d163575Sopenharmony_ci loc_netif = loc_netif->next; 8090d163575Sopenharmony_ci continue; 8100d163575Sopenharmony_ci } 8110d163575Sopenharmony_ci if (ip_addr_cmp(&loc_netif->netmask, &taget_addr) && 8120d163575Sopenharmony_ci ip_addr_netcmp(&loc_netif->ip_addr, 8130d163575Sopenharmony_ci &netif->ip_addr, ip_2_ip4(&loc_netif->netmask))) { 8140d163575Sopenharmony_ci return EINVAL; 8150d163575Sopenharmony_ci } 8160d163575Sopenharmony_ci loc_netif = loc_netif->next; 8170d163575Sopenharmony_ci } 8180d163575Sopenharmony_ci 8190d163575Sopenharmony_ci#if LWIP_DHCP 8200d163575Sopenharmony_ci if ((netif_dhcp_data(netif) != NULL) && 8210d163575Sopenharmony_ci (netif_dhcp_data(netif)->state != DHCP_STATE_OFF)) { 8220d163575Sopenharmony_ci (void)netif_dhcp_off(netif); 8230d163575Sopenharmony_ci } 8240d163575Sopenharmony_ci#endif 8250d163575Sopenharmony_ci 8260d163575Sopenharmony_ci netif_set_netmask(netif, ip_2_ip4(&taget_addr)); 8270d163575Sopenharmony_ci 8280d163575Sopenharmony_ci /* check if gateway still reachable */ 8290d163575Sopenharmony_ci if (!ip_addr_netcmp(&netif->gw, &netif->ip_addr, ip_2_ip4(&taget_addr))) { 8300d163575Sopenharmony_ci ip_addr_set_zero(&(netif->gw)); 8310d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 8320d163575Sopenharmony_ci if (netif == group->netif_default) { 8330d163575Sopenharmony_ci (void)netif_set_default(NULL, group); 8340d163575Sopenharmony_ci#else 8350d163575Sopenharmony_ci if (netif == netif_default) { 8360d163575Sopenharmony_ci (void)netif_set_default(NULL); 8370d163575Sopenharmony_ci#endif 8380d163575Sopenharmony_ci } 8390d163575Sopenharmony_ci } 8400d163575Sopenharmony_ci return 0; 8410d163575Sopenharmony_ci } 8420d163575Sopenharmony_ci} 8430d163575Sopenharmony_ci 8440d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCSIFHWADDR(struct ifreq *ifr) 8450d163575Sopenharmony_ci{ 8460d163575Sopenharmony_ci struct netif *netif = NULL; 8470d163575Sopenharmony_ci err_t ret; 8480d163575Sopenharmony_ci 8490d163575Sopenharmony_ci#if LWIP_ENABLE_NET_CAPABILITY 8500d163575Sopenharmony_ci if (!IsCapPermit(CAP_NET_ADMIN)) { 8510d163575Sopenharmony_ci return EPERM; 8520d163575Sopenharmony_ci } 8530d163575Sopenharmony_ci#endif 8540d163575Sopenharmony_ci 8550d163575Sopenharmony_ci /* set netif hw addr */ 8560d163575Sopenharmony_ci netif = netif_find(ifr->ifr_name); 8570d163575Sopenharmony_ci if (netif == NULL) { 8580d163575Sopenharmony_ci return ENODEV; 8590d163575Sopenharmony_ci } 8600d163575Sopenharmony_ci#if LWIP_HAVE_LOOPIF 8610d163575Sopenharmony_ci else if (netif->link_layer_type == LOOPBACK_IF) { 8620d163575Sopenharmony_ci return EPERM; 8630d163575Sopenharmony_ci } 8640d163575Sopenharmony_ci#endif 8650d163575Sopenharmony_ci else { 8660d163575Sopenharmony_ci /* bring netif down to clear all Neighbor Cache Entry */ 8670d163575Sopenharmony_ci (void)netif_set_down(netif); 8680d163575Sopenharmony_ci 8690d163575Sopenharmony_ci ret = netif_set_hwaddr(netif, (const unsigned char *)ifr->ifr_hwaddr.sa_data, netif->hwaddr_len); 8700d163575Sopenharmony_ci if (ret != ERR_OK) { 8710d163575Sopenharmony_ci (void)netif_set_up(netif); 8720d163575Sopenharmony_ci return err_to_errno(ret); 8730d163575Sopenharmony_ci } 8740d163575Sopenharmony_ci 8750d163575Sopenharmony_ci /* 8760d163575Sopenharmony_ci * bring netif up to try to send GARP/IGMP/NA/MLD/RS. GARP and NA would 8770d163575Sopenharmony_ci * make the neighboring nodes update their Neighbor Cache immediately. 8780d163575Sopenharmony_ci */ 8790d163575Sopenharmony_ci (void)netif_set_up(netif); 8800d163575Sopenharmony_ci return 0; 8810d163575Sopenharmony_ci } 8820d163575Sopenharmony_ci} 8830d163575Sopenharmony_ci 8840d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCGIFHWADDR(struct ifreq *ifr) 8850d163575Sopenharmony_ci{ 8860d163575Sopenharmony_ci struct netif *netif = NULL; 8870d163575Sopenharmony_ci 8880d163575Sopenharmony_ci /* get netif hw addr */ 8890d163575Sopenharmony_ci netif = netif_find(ifr->ifr_name); 8900d163575Sopenharmony_ci if (netif == NULL) { 8910d163575Sopenharmony_ci return ENODEV; 8920d163575Sopenharmony_ci } 8930d163575Sopenharmony_ci#if LWIP_HAVE_LOOPIF 8940d163575Sopenharmony_ci else if (netif->link_layer_type == LOOPBACK_IF) { 8950d163575Sopenharmony_ci return EPERM; 8960d163575Sopenharmony_ci } 8970d163575Sopenharmony_ci#endif /* LWIP_HAVE_LOOPIF */ 8980d163575Sopenharmony_ci else { 8990d163575Sopenharmony_ci if (memcpy_s((void *)ifr->ifr_hwaddr.sa_data, sizeof(ifr->ifr_hwaddr.sa_data), 9000d163575Sopenharmony_ci (void *)netif->hwaddr, netif->hwaddr_len) != EOK) { 9010d163575Sopenharmony_ci return EINVAL; 9020d163575Sopenharmony_ci } 9030d163575Sopenharmony_ci return 0; 9040d163575Sopenharmony_ci } 9050d163575Sopenharmony_ci} 9060d163575Sopenharmony_ci 9070d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCSIFFLAGS(struct ifreq *ifr) 9080d163575Sopenharmony_ci{ 9090d163575Sopenharmony_ci struct netif *netif = NULL; 9100d163575Sopenharmony_ci 9110d163575Sopenharmony_ci#if LWIP_ENABLE_NET_CAPABILITY 9120d163575Sopenharmony_ci if (!IsCapPermit(CAP_NET_ADMIN)) { 9130d163575Sopenharmony_ci return EPERM; 9140d163575Sopenharmony_ci } 9150d163575Sopenharmony_ci#endif 9160d163575Sopenharmony_ci 9170d163575Sopenharmony_ci /* set netif hw addr */ 9180d163575Sopenharmony_ci netif = netif_find(ifr->ifr_name); 9190d163575Sopenharmony_ci if (netif == NULL) { 9200d163575Sopenharmony_ci return ENODEV; 9210d163575Sopenharmony_ci } 9220d163575Sopenharmony_ci#if LWIP_HAVE_LOOPIF 9230d163575Sopenharmony_ci else if (netif->link_layer_type == LOOPBACK_IF) { 9240d163575Sopenharmony_ci return EPERM; 9250d163575Sopenharmony_ci } 9260d163575Sopenharmony_ci#endif /* LWIP_HAVE_LOOPIF */ 9270d163575Sopenharmony_ci else { 9280d163575Sopenharmony_ci if (((unsigned short)ifr->ifr_flags & IFF_UP) && !(netif->flags & NETIF_FLAG_UP)) { 9290d163575Sopenharmony_ci (void)netif_set_up(netif); 9300d163575Sopenharmony_ci } else if (!((unsigned short)ifr->ifr_flags & IFF_UP) && (netif->flags & NETIF_FLAG_UP)) { 9310d163575Sopenharmony_ci (void)netif_set_down(netif); 9320d163575Sopenharmony_ci } 9330d163575Sopenharmony_ci if (((unsigned short)ifr->ifr_flags & IFF_RUNNING) && !(netif->flags & NETIF_FLAG_LINK_UP)) { 9340d163575Sopenharmony_ci (void)netif_set_link_up(netif); 9350d163575Sopenharmony_ci } else if (!((unsigned short)ifr->ifr_flags & IFF_RUNNING) && (netif->flags & NETIF_FLAG_LINK_UP)) { 9360d163575Sopenharmony_ci (void)netif_set_link_down(netif); 9370d163575Sopenharmony_ci } 9380d163575Sopenharmony_ci 9390d163575Sopenharmony_ci if ((unsigned short)ifr->ifr_flags & IFF_BROADCAST) { 9400d163575Sopenharmony_ci netif->flags |= NETIF_FLAG_BROADCAST; 9410d163575Sopenharmony_ci } else { 9420d163575Sopenharmony_ci netif->flags = netif->flags & (~NETIF_FLAG_BROADCAST); 9430d163575Sopenharmony_ci } 9440d163575Sopenharmony_ci if ((unsigned short)ifr->ifr_flags & IFF_NOARP) { 9450d163575Sopenharmony_ci netif->flags = (netif->flags & (~NETIF_FLAG_ETHARP)); 9460d163575Sopenharmony_ci } else { 9470d163575Sopenharmony_ci netif->flags |= NETIF_FLAG_ETHARP; 9480d163575Sopenharmony_ci } 9490d163575Sopenharmony_ci 9500d163575Sopenharmony_ci if ((unsigned short)ifr->ifr_flags & IFF_MULTICAST) { 9510d163575Sopenharmony_ci#if LWIP_IGMP 9520d163575Sopenharmony_ci netif->flags |= NETIF_FLAG_IGMP; 9530d163575Sopenharmony_ci#endif /* LWIP_IGMP */ 9540d163575Sopenharmony_ci#if LWIP_IPV6 && LWIP_IPV6_MLD 9550d163575Sopenharmony_ci netif->flags |= NETIF_FLAG_MLD6; 9560d163575Sopenharmony_ci#endif /* LWIP_IPV6_MLD */ 9570d163575Sopenharmony_ci } else { 9580d163575Sopenharmony_ci#if LWIP_IGMP 9590d163575Sopenharmony_ci netif->flags = (netif->flags & ~NETIF_FLAG_IGMP); 9600d163575Sopenharmony_ci#endif /* LWIP_IGMP */ 9610d163575Sopenharmony_ci#if LWIP_IPV6 && LWIP_IPV6_MLD 9620d163575Sopenharmony_ci netif->flags = (netif->flags & ~NETIF_FLAG_MLD6); 9630d163575Sopenharmony_ci#endif /* LWIP_IPV6_MLD */ 9640d163575Sopenharmony_ci } 9650d163575Sopenharmony_ci 9660d163575Sopenharmony_ci#if LWIP_DHCP 9670d163575Sopenharmony_ci if ((unsigned short)ifr->ifr_flags & IFF_DYNAMIC) { 9680d163575Sopenharmony_ci (void)dhcp_start(netif); 9690d163575Sopenharmony_ci } else { 9700d163575Sopenharmony_ci dhcp_stop(netif); 9710d163575Sopenharmony_ci#if !LWIP_DHCP_SUBSTITUTE 9720d163575Sopenharmony_ci dhcp_cleanup(netif); 9730d163575Sopenharmony_ci#endif 9740d163575Sopenharmony_ci } 9750d163575Sopenharmony_ci#endif 9760d163575Sopenharmony_ci 9770d163575Sopenharmony_ci#if LWIP_NETIF_PROMISC 9780d163575Sopenharmony_ci if (((unsigned short)ifr->ifr_flags & IFF_PROMISC)) { 9790d163575Sopenharmony_ci netif->flags |= NETIF_FLAG_PROMISC; 9800d163575Sopenharmony_ci } else { 9810d163575Sopenharmony_ci netif->flags &= ~NETIF_FLAG_PROMISC; 9820d163575Sopenharmony_ci } 9830d163575Sopenharmony_ci if (netif->drv_config) { 9840d163575Sopenharmony_ci netif->drv_config(netif, IFF_PROMISC, !!((unsigned short)ifr->ifr_flags & IFF_PROMISC)); 9850d163575Sopenharmony_ci } 9860d163575Sopenharmony_ci#endif /* LWIP_NETIF_PROMISC */ 9870d163575Sopenharmony_ci return 0; 9880d163575Sopenharmony_ci } 9890d163575Sopenharmony_ci} 9900d163575Sopenharmony_ci 9910d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCGIFFLAGS(struct ifreq *ifr) 9920d163575Sopenharmony_ci{ 9930d163575Sopenharmony_ci struct netif *netif = NULL; 9940d163575Sopenharmony_ci 9950d163575Sopenharmony_ci /* set netif hw addr */ 9960d163575Sopenharmony_ci netif = netif_find(ifr->ifr_name); 9970d163575Sopenharmony_ci if (netif == NULL) { 9980d163575Sopenharmony_ci return ENODEV; 9990d163575Sopenharmony_ci } else { 10000d163575Sopenharmony_ci if (netif->flags & NETIF_FLAG_UP) { 10010d163575Sopenharmony_ci ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_UP; 10020d163575Sopenharmony_ci } else { 10030d163575Sopenharmony_ci ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_UP; 10040d163575Sopenharmony_ci } 10050d163575Sopenharmony_ci if (netif->flags & NETIF_FLAG_LINK_UP) { 10060d163575Sopenharmony_ci ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_RUNNING; 10070d163575Sopenharmony_ci } else { 10080d163575Sopenharmony_ci ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_RUNNING; 10090d163575Sopenharmony_ci } 10100d163575Sopenharmony_ci if (netif->flags & NETIF_FLAG_BROADCAST) { 10110d163575Sopenharmony_ci ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_BROADCAST; 10120d163575Sopenharmony_ci } else { 10130d163575Sopenharmony_ci ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_BROADCAST; 10140d163575Sopenharmony_ci } 10150d163575Sopenharmony_ci if (netif->flags & NETIF_FLAG_ETHARP) { 10160d163575Sopenharmony_ci ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_NOARP; 10170d163575Sopenharmony_ci } else { 10180d163575Sopenharmony_ci ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_NOARP; 10190d163575Sopenharmony_ci } 10200d163575Sopenharmony_ci 10210d163575Sopenharmony_ci#if LWIP_IGMP || LWIP_IPV6_MLD 10220d163575Sopenharmony_ci if ( 10230d163575Sopenharmony_ci#if LWIP_IGMP 10240d163575Sopenharmony_ci (netif->flags & NETIF_FLAG_IGMP) 10250d163575Sopenharmony_ci#endif /* LWIP_IGMP */ 10260d163575Sopenharmony_ci#if LWIP_IGMP && LWIP_IPV6_MLD 10270d163575Sopenharmony_ci || 10280d163575Sopenharmony_ci#endif /* LWIP_IGMP && LWIP_IPV6_MLD */ 10290d163575Sopenharmony_ci#if LWIP_IPV6_MLD 10300d163575Sopenharmony_ci (netif->flags & NETIF_FLAG_MLD6) 10310d163575Sopenharmony_ci#endif /* LWIP_IPV6_MLD */ 10320d163575Sopenharmony_ci ) { 10330d163575Sopenharmony_ci ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_MULTICAST); 10340d163575Sopenharmony_ci } else { 10350d163575Sopenharmony_ci ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_MULTICAST)); 10360d163575Sopenharmony_ci } 10370d163575Sopenharmony_ci#endif /* LWIP_IGMP || LWIP_IPV6_MLD */ 10380d163575Sopenharmony_ci 10390d163575Sopenharmony_ci#if LWIP_DHCP 10400d163575Sopenharmony_ci if (dhcp_supplied_address(netif)) { 10410d163575Sopenharmony_ci ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_DYNAMIC); 10420d163575Sopenharmony_ci } else { 10430d163575Sopenharmony_ci ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_DYNAMIC)); 10440d163575Sopenharmony_ci } 10450d163575Sopenharmony_ci#endif 10460d163575Sopenharmony_ci 10470d163575Sopenharmony_ci#if LWIP_HAVE_LOOPIF 10480d163575Sopenharmony_ci if (netif->link_layer_type == LOOPBACK_IF) { 10490d163575Sopenharmony_ci ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_LOOPBACK; 10500d163575Sopenharmony_ci } 10510d163575Sopenharmony_ci#endif 10520d163575Sopenharmony_ci 10530d163575Sopenharmony_ci#if LWIP_NETIF_PROMISC 10540d163575Sopenharmony_ci if (netif->flags & NETIF_FLAG_PROMISC) { 10550d163575Sopenharmony_ci ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_PROMISC; 10560d163575Sopenharmony_ci } else { 10570d163575Sopenharmony_ci ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_PROMISC; 10580d163575Sopenharmony_ci } 10590d163575Sopenharmony_ci#endif /* LWIP_NETIF_PROMISC */ 10600d163575Sopenharmony_ci 10610d163575Sopenharmony_ci return 0; 10620d163575Sopenharmony_ci } 10630d163575Sopenharmony_ci} 10640d163575Sopenharmony_ci 10650d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 10660d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCGIFNAME(struct ifreq *ifr, struct net_group *group) 10670d163575Sopenharmony_ci#else 10680d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCGIFNAME(struct ifreq *ifr) 10690d163575Sopenharmony_ci#endif 10700d163575Sopenharmony_ci{ 10710d163575Sopenharmony_ci struct netif *netif = NULL; 10720d163575Sopenharmony_ci int ret; 10730d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 10740d163575Sopenharmony_ci for (netif = group->netif_list; netif != NULL; netif = netif->next) { 10750d163575Sopenharmony_ci#else 10760d163575Sopenharmony_ci for (netif = netif_list; netif != NULL; netif = netif->next) { 10770d163575Sopenharmony_ci#endif 10780d163575Sopenharmony_ci if (ifr->ifr_ifindex == netif_get_index(netif)) { 10790d163575Sopenharmony_ci break; 10800d163575Sopenharmony_ci } 10810d163575Sopenharmony_ci } 10820d163575Sopenharmony_ci 10830d163575Sopenharmony_ci if (netif == NULL) { 10840d163575Sopenharmony_ci return ENODEV; 10850d163575Sopenharmony_ci } else { 10860d163575Sopenharmony_ci if (netif->link_layer_type == LOOPBACK_IF) { 10870d163575Sopenharmony_ci ret = snprintf_s(ifr->ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%.2s", netif->name); 10880d163575Sopenharmony_ci if ((ret <= 0) || (ret >= IFNAMSIZ)) { 10890d163575Sopenharmony_ci return ENOBUFS; 10900d163575Sopenharmony_ci } 10910d163575Sopenharmony_ci } else { 10920d163575Sopenharmony_ci ret = snprintf_s(ifr->ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%s", netif_get_name(netif)); 10930d163575Sopenharmony_ci if ((ret <= 0) || (ret >= IFNAMSIZ)) { 10940d163575Sopenharmony_ci return ENOBUFS; 10950d163575Sopenharmony_ci } 10960d163575Sopenharmony_ci } 10970d163575Sopenharmony_ci return 0; 10980d163575Sopenharmony_ci } 10990d163575Sopenharmony_ci} 11000d163575Sopenharmony_ci 11010d163575Sopenharmony_cistatic bool lwip_validate_ifname(const char *name, u8_t *let_pos) 11020d163575Sopenharmony_ci{ 11030d163575Sopenharmony_ci unsigned short num_pos = 0; 11040d163575Sopenharmony_ci unsigned short letter_pos = 0; 11050d163575Sopenharmony_ci unsigned short pos = 0; 11060d163575Sopenharmony_ci bool have_num = 0; 11070d163575Sopenharmony_ci 11080d163575Sopenharmony_ci /* if the first position of variable name is not letter, such as '6eth2' */ 11090d163575Sopenharmony_ci if (((*name >= 'a') && (*name <= 'z')) || ((*name >= 'A') && (*name <= 'Z'))) { 11100d163575Sopenharmony_ci return 0; 11110d163575Sopenharmony_ci } 11120d163575Sopenharmony_ci 11130d163575Sopenharmony_ci /* check if the position of letter is bigger than the the position of digital */ 11140d163575Sopenharmony_ci while (*name != '\0') { 11150d163575Sopenharmony_ci if ((*name >= '0') && (*name <= '9')) { 11160d163575Sopenharmony_ci num_pos = pos; 11170d163575Sopenharmony_ci have_num = 1; 11180d163575Sopenharmony_ci } else if (((*name >= 'a') && (*name <= 'z')) || ((*name >= 'A') && (*name <= 'Z'))) { 11190d163575Sopenharmony_ci letter_pos = pos; 11200d163575Sopenharmony_ci if (have_num != 0) { 11210d163575Sopenharmony_ci return 0; 11220d163575Sopenharmony_ci } 11230d163575Sopenharmony_ci } else { 11240d163575Sopenharmony_ci return 0; 11250d163575Sopenharmony_ci } 11260d163575Sopenharmony_ci pos++; 11270d163575Sopenharmony_ci name++; 11280d163575Sopenharmony_ci } 11290d163575Sopenharmony_ci 11300d163575Sopenharmony_ci /* for the speacil case as all position of variable name is letter, such as 'ethabc' */ 11310d163575Sopenharmony_ci if (num_pos == 0) { 11320d163575Sopenharmony_ci return 0; 11330d163575Sopenharmony_ci } 11340d163575Sopenharmony_ci 11350d163575Sopenharmony_ci /* cheak if the digital in the variable name is bigger than 255, such as 'eth266' */ 11360d163575Sopenharmony_ci if (atoi(name - (pos - letter_pos - 1)) > 255) { 11370d163575Sopenharmony_ci return 0; 11380d163575Sopenharmony_ci } 11390d163575Sopenharmony_ci 11400d163575Sopenharmony_ci *let_pos = (u8_t)letter_pos; 11410d163575Sopenharmony_ci 11420d163575Sopenharmony_ci return 1; 11430d163575Sopenharmony_ci} 11440d163575Sopenharmony_ci 11450d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCSIFNAME(struct ifreq *ifr) 11460d163575Sopenharmony_ci{ 11470d163575Sopenharmony_ci struct netif *netif = NULL; 11480d163575Sopenharmony_ci u8_t letter_pos = 0; 11490d163575Sopenharmony_ci 11500d163575Sopenharmony_ci#if LWIP_ENABLE_NET_CAPABILITY 11510d163575Sopenharmony_ci if (!IsCapPermit(CAP_NET_ADMIN)) { 11520d163575Sopenharmony_ci return EPERM; 11530d163575Sopenharmony_ci } 11540d163575Sopenharmony_ci#endif 11550d163575Sopenharmony_ci 11560d163575Sopenharmony_ci netif = netif_find(ifr->ifr_name); 11570d163575Sopenharmony_ci if (netif == NULL) { 11580d163575Sopenharmony_ci return ENODEV; 11590d163575Sopenharmony_ci } else if (netif->link_layer_type == LOOPBACK_IF) { 11600d163575Sopenharmony_ci return EPERM; 11610d163575Sopenharmony_ci } else if ((netif->flags & IFF_UP) != 0) { 11620d163575Sopenharmony_ci return EBUSY; 11630d163575Sopenharmony_ci } else { 11640d163575Sopenharmony_ci if (strncmp(ifr->ifr_name, ifr->ifr_newname, IFNAMSIZ) == 0) { 11650d163575Sopenharmony_ci /* not change */ 11660d163575Sopenharmony_ci return 0; 11670d163575Sopenharmony_ci } 11680d163575Sopenharmony_ci 11690d163575Sopenharmony_ci ifr->ifr_newname[IFNAMSIZ - 1] = '\0'; 11700d163575Sopenharmony_ci if ((lwip_validate_ifname(ifr->ifr_newname, &letter_pos) == 0) || (strlen(ifr->ifr_newname) > (IFNAMSIZ - 1))) { 11710d163575Sopenharmony_ci return EINVAL; 11720d163575Sopenharmony_ci } 11730d163575Sopenharmony_ci 11740d163575Sopenharmony_ci if (strncpy_s(netif->full_name, sizeof(netif->full_name), ifr->ifr_newname, strlen(ifr->ifr_newname)) != EOK) { 11750d163575Sopenharmony_ci return EINVAL; 11760d163575Sopenharmony_ci } 11770d163575Sopenharmony_ci } 11780d163575Sopenharmony_ci 11790d163575Sopenharmony_ci return 0; 11800d163575Sopenharmony_ci} 11810d163575Sopenharmony_ci 11820d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCGIFINDEX(struct ifreq *ifr) 11830d163575Sopenharmony_ci{ 11840d163575Sopenharmony_ci struct netif *netif = NULL; 11850d163575Sopenharmony_ci 11860d163575Sopenharmony_ci netif = netif_find(ifr->ifr_name); 11870d163575Sopenharmony_ci if (netif == NULL) { 11880d163575Sopenharmony_ci return ENODEV; 11890d163575Sopenharmony_ci } else { 11900d163575Sopenharmony_ci ifr->ifr_ifindex = netif_get_index(netif); 11910d163575Sopenharmony_ci return 0; 11920d163575Sopenharmony_ci } 11930d163575Sopenharmony_ci} 11940d163575Sopenharmony_ci 11950d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCSIFMTU(struct ifreq *ifr) 11960d163575Sopenharmony_ci{ 11970d163575Sopenharmony_ci struct netif *netif = NULL; 11980d163575Sopenharmony_ci 11990d163575Sopenharmony_ci#if LWIP_ENABLE_NET_CAPABILITY 12000d163575Sopenharmony_ci if (!IsCapPermit(CAP_NET_ADMIN)) { 12010d163575Sopenharmony_ci return EPERM; 12020d163575Sopenharmony_ci } 12030d163575Sopenharmony_ci#endif 12040d163575Sopenharmony_ci 12050d163575Sopenharmony_ci /* set netif hw addr */ 12060d163575Sopenharmony_ci netif = netif_find(ifr->ifr_name); 12070d163575Sopenharmony_ci if (netif == NULL) { 12080d163575Sopenharmony_ci return ENODEV; 12090d163575Sopenharmony_ci } 12100d163575Sopenharmony_ci#if LWIP_HAVE_LOOPIF 12110d163575Sopenharmony_ci /* the mtu of loopif is not used. */ 12120d163575Sopenharmony_ci else if (netif->link_layer_type == LOOPBACK_IF) { 12130d163575Sopenharmony_ci return EPERM; 12140d163575Sopenharmony_ci } 12150d163575Sopenharmony_ci#endif 12160d163575Sopenharmony_ci else { 12170d163575Sopenharmony_ci if (ERR_OK != netif_set_mtu(netif, (u16_t)ifr->ifr_mtu)) { 12180d163575Sopenharmony_ci return EINVAL; 12190d163575Sopenharmony_ci } 12200d163575Sopenharmony_ci 12210d163575Sopenharmony_ci return 0; 12220d163575Sopenharmony_ci } 12230d163575Sopenharmony_ci} 12240d163575Sopenharmony_ci 12250d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCGIFMTU(struct ifreq *ifr) 12260d163575Sopenharmony_ci{ 12270d163575Sopenharmony_ci struct netif *netif = NULL; 12280d163575Sopenharmony_ci 12290d163575Sopenharmony_ci /* get netif hw addr */ 12300d163575Sopenharmony_ci netif = netif_find(ifr->ifr_name); 12310d163575Sopenharmony_ci if (netif == NULL) { 12320d163575Sopenharmony_ci return ENODEV; 12330d163575Sopenharmony_ci } else { 12340d163575Sopenharmony_ci ifr->ifr_mtu = netif->mtu; 12350d163575Sopenharmony_ci return 0; 12360d163575Sopenharmony_ci } 12370d163575Sopenharmony_ci} 12380d163575Sopenharmony_ci 12390d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCGIFBRDADDR(struct ifreq *ifr) 12400d163575Sopenharmony_ci{ 12410d163575Sopenharmony_ci struct netif *netif = NULL; 12420d163575Sopenharmony_ci struct sockaddr_in *sock_in = NULL; 12430d163575Sopenharmony_ci 12440d163575Sopenharmony_ci /* get netif subnet broadcast addr */ 12450d163575Sopenharmony_ci netif = netif_find(ifr->ifr_name); 12460d163575Sopenharmony_ci if (netif == NULL) { 12470d163575Sopenharmony_ci return ENODEV; 12480d163575Sopenharmony_ci } 12490d163575Sopenharmony_ci if (ip4_addr_isany_val(*(ip_2_ip4(&netif->netmask)))) { 12500d163575Sopenharmony_ci return ENXIO; 12510d163575Sopenharmony_ci } 12520d163575Sopenharmony_ci sock_in = (struct sockaddr_in *)&ifr->ifr_addr; 12530d163575Sopenharmony_ci sock_in->sin_family = AF_INET; 12540d163575Sopenharmony_ci sock_in->sin_addr.s_addr = (ip_2_ip4(&((netif)->ip_addr))->addr | ~(ip_2_ip4(&netif->netmask)->addr)); 12550d163575Sopenharmony_ci return 0; 12560d163575Sopenharmony_ci} 12570d163575Sopenharmony_ci 12580d163575Sopenharmony_ci#endif /* LWIP_IOCTL_IF */ 12590d163575Sopenharmony_ci 12600d163575Sopenharmony_ci#if LWIP_NETIF_ETHTOOL 12610d163575Sopenharmony_ci 12620d163575Sopenharmony_cistatic s32_t lwip_ioctl_internal_SIOCETHTOOL(struct ifreq *ifr) 12630d163575Sopenharmony_ci{ 12640d163575Sopenharmony_ci struct netif *netif; 12650d163575Sopenharmony_ci 12660d163575Sopenharmony_ci#if LWIP_ENABLE_NET_CAPABILITY 12670d163575Sopenharmony_ci if (!IsCapPermit(CAP_NET_ADMIN)) { 12680d163575Sopenharmony_ci return EPERM; 12690d163575Sopenharmony_ci } 12700d163575Sopenharmony_ci#endif 12710d163575Sopenharmony_ci 12720d163575Sopenharmony_ci netif = netif_find(ifr->ifr_name); 12730d163575Sopenharmony_ci if (netif == NULL) { 12740d163575Sopenharmony_ci return ENODEV; 12750d163575Sopenharmony_ci } else { 12760d163575Sopenharmony_ci return dev_ethtool(netif, ifr); 12770d163575Sopenharmony_ci } 12780d163575Sopenharmony_ci} 12790d163575Sopenharmony_ci 12800d163575Sopenharmony_ci#endif 12810d163575Sopenharmony_ci 12820d163575Sopenharmony_ci#if LWIP_IPV6 12830d163575Sopenharmony_ci#if LWIP_IPV6_DUP_DETECT_ATTEMPTS 12840d163575Sopenharmony_ci 12850d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCSIPV6DAD(struct ifreq *ifr) 12860d163575Sopenharmony_ci{ 12870d163575Sopenharmony_ci#if LWIP_ENABLE_NET_CAPABILITY 12880d163575Sopenharmony_ci if (!IsCapPermit(CAP_NET_ADMIN)) { 12890d163575Sopenharmony_ci return EPERM; 12900d163575Sopenharmony_ci } 12910d163575Sopenharmony_ci#endif 12920d163575Sopenharmony_ci 12930d163575Sopenharmony_ci struct netif *tmpnetif = netif_find(ifr->ifr_name); 12940d163575Sopenharmony_ci if (tmpnetif == NULL) { 12950d163575Sopenharmony_ci LWIP_DEBUGF(SOCKETS_DEBUG, ("Interface not found.\n")); 12960d163575Sopenharmony_ci return ENODEV; 12970d163575Sopenharmony_ci } 12980d163575Sopenharmony_ci 12990d163575Sopenharmony_ci if ((ifr->ifr_ifru.ifru_ivalue != 0) && (ifr->ifr_ifru.ifru_ivalue != 1)) { 13000d163575Sopenharmony_ci LWIP_DEBUGF(SOCKETS_DEBUG, ("Invalid ioctl argument(ifru_ivalue 0/1).\n")); 13010d163575Sopenharmony_ci return EBADRQC; 13020d163575Sopenharmony_ci } 13030d163575Sopenharmony_ci 13040d163575Sopenharmony_ci if (ifr->ifr_ifru.ifru_ivalue == 1) { 13050d163575Sopenharmony_ci tmpnetif->ipv6_flags = (tmpnetif->ipv6_flags | LWIP_IPV6_ND6_FLAG_DAD); 13060d163575Sopenharmony_ci 13070d163575Sopenharmony_ci LWIP_DEBUGF(SOCKETS_DEBUG, ("DAD turned on through ioctl for %s iface index %u \n", 13080d163575Sopenharmony_ci tmpnetif->name, tmpnetif->num)); 13090d163575Sopenharmony_ci } else { 13100d163575Sopenharmony_ci tmpnetif->ipv6_flags = (tmpnetif->ipv6_flags & ((~LWIP_IPV6_ND6_FLAG_DAD) & 0xffU)); 13110d163575Sopenharmony_ci 13120d163575Sopenharmony_ci LWIP_DEBUGF(SOCKETS_DEBUG, ("DAD turned off through ioctl for %s iface index %u \n", 13130d163575Sopenharmony_ci tmpnetif->name, tmpnetif->num)); 13140d163575Sopenharmony_ci } 13150d163575Sopenharmony_ci return 0; 13160d163575Sopenharmony_ci} 13170d163575Sopenharmony_ci 13180d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCGIPV6DAD(struct ifreq *ifr) 13190d163575Sopenharmony_ci{ 13200d163575Sopenharmony_ci struct netif *tmpnetif = netif_find(ifr->ifr_name); 13210d163575Sopenharmony_ci if (tmpnetif == NULL) { 13220d163575Sopenharmony_ci LWIP_DEBUGF(SOCKETS_DEBUG, ("Interface not found.\n")); 13230d163575Sopenharmony_ci return ENODEV; 13240d163575Sopenharmony_ci } 13250d163575Sopenharmony_ci ifr->ifr_ifru.ifru_ivalue = (tmpnetif->ipv6_flags & LWIP_IPV6_ND6_FLAG_DAD) ? 1 : 0; 13260d163575Sopenharmony_ci return 0; 13270d163575Sopenharmony_ci} 13280d163575Sopenharmony_ci 13290d163575Sopenharmony_ci#endif 13300d163575Sopenharmony_ci 13310d163575Sopenharmony_ci#if LWIP_IOCTL_IPV6DPCTD 13320d163575Sopenharmony_ci 13330d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCSIPV6DPCTD(struct ifreq *ifr) 13340d163575Sopenharmony_ci{ 13350d163575Sopenharmony_ci#if LWIP_ENABLE_NET_CAPABILITY 13360d163575Sopenharmony_ci if (!IsCapPermit(CAP_NET_ADMIN)) { 13370d163575Sopenharmony_ci return EPERM; 13380d163575Sopenharmony_ci } 13390d163575Sopenharmony_ci#endif 13400d163575Sopenharmony_ci 13410d163575Sopenharmony_ci struct netif *tmpnetif = netif_find(ifr->ifr_name); 13420d163575Sopenharmony_ci if (tmpnetif == NULL) { 13430d163575Sopenharmony_ci LWIP_DEBUGF(SOCKETS_DEBUG, ("Interface not found.\n")); 13440d163575Sopenharmony_ci return ENODEV; 13450d163575Sopenharmony_ci } 13460d163575Sopenharmony_ci if ((ifr->ifr_ifru.ifru_ivalue != 0) && (ifr->ifr_ifru.ifru_ivalue != 1)) { 13470d163575Sopenharmony_ci LWIP_DEBUGF(SOCKETS_DEBUG, ("Invalid ioctl argument(ifru_ivalue 0/1).\n")); 13480d163575Sopenharmony_ci return EBADRQC; 13490d163575Sopenharmony_ci } 13500d163575Sopenharmony_ci if (ifr->ifr_ifru.ifru_ivalue == 1) { 13510d163575Sopenharmony_ci tmpnetif->ipv6_flags = (tmpnetif->ipv6_flags | LWIP_IPV6_ND6_FLAG_DEPRECATED); 13520d163575Sopenharmony_ci LWIP_DEBUGF(SOCKETS_DEBUG, ("Deprecation turned on through ioctl for %s iface index %u \n", 13530d163575Sopenharmony_ci tmpnetif->name, tmpnetif->num)); 13540d163575Sopenharmony_ci } else { 13550d163575Sopenharmony_ci tmpnetif->ipv6_flags = (tmpnetif->ipv6_flags & ((~LWIP_IPV6_ND6_FLAG_DEPRECATED) & 0xffU)); 13560d163575Sopenharmony_ci LWIP_DEBUGF(SOCKETS_DEBUG, ("Deprecation turned off through ioctl for %s iface index %u \n", 13570d163575Sopenharmony_ci tmpnetif->name, tmpnetif->num)); 13580d163575Sopenharmony_ci } 13590d163575Sopenharmony_ci return 0; 13600d163575Sopenharmony_ci} 13610d163575Sopenharmony_ci 13620d163575Sopenharmony_cistatic u8_t lwip_ioctl_internal_SIOCGIPV6DPCTD(struct ifreq *ifr) 13630d163575Sopenharmony_ci{ 13640d163575Sopenharmony_ci struct netif *tmpnetif = netif_find(ifr->ifr_name); 13650d163575Sopenharmony_ci if (tmpnetif == NULL) { 13660d163575Sopenharmony_ci LWIP_DEBUGF(SOCKETS_DEBUG, ("Interface not found.\n")); 13670d163575Sopenharmony_ci return ENODEV; 13680d163575Sopenharmony_ci } 13690d163575Sopenharmony_ci 13700d163575Sopenharmony_ci ifr->ifr_ifru.ifru_ivalue = (tmpnetif->ipv6_flags & LWIP_IPV6_ND6_FLAG_DEPRECATED) ? 1 : 0; 13710d163575Sopenharmony_ci return 0; 13720d163575Sopenharmony_ci} 13730d163575Sopenharmony_ci 13740d163575Sopenharmony_ci#endif /* LWIP_IOCTL_IPV6DPCTD */ 13750d163575Sopenharmony_ci#endif 13760d163575Sopenharmony_ci 13770d163575Sopenharmony_cistatic u8_t lwip_ioctl_impl(const struct lwip_sock *sock, long cmd, void *argp) 13780d163575Sopenharmony_ci{ 13790d163575Sopenharmony_ci u8_t err = 0; 13800d163575Sopenharmony_ci#if LWIP_NETIF_ETHTOOL 13810d163575Sopenharmony_ci s32_t ret; 13820d163575Sopenharmony_ci#endif 13830d163575Sopenharmony_ci#if LWIP_IPV6_DUP_DETECT_ATTEMPTS || LWIP_IOCTL_IPV6DPCTD || LWIP_IOCTL_IF || LWIP_NETIF_ETHTOOL 13840d163575Sopenharmony_ci struct ifreq *ifr = (struct ifreq *)argp; 13850d163575Sopenharmony_ci#endif 13860d163575Sopenharmony_ci#if LWIP_IOCTL_ROUTE 13870d163575Sopenharmony_ci struct rtentry *rmten = (struct rtentry *)argp; 13880d163575Sopenharmony_ci#endif 13890d163575Sopenharmony_ci#if LWIP_IPV6_DUP_DETECT_ATTEMPTS || LWIP_IOCTL_IPV6DPCTD || LWIP_IOCTL_ROUTE || LWIP_IOCTL_IF 13900d163575Sopenharmony_ci bool is_ipv6 = 0; 13910d163575Sopenharmony_ci 13920d163575Sopenharmony_ci /* allow it only on IPv6 sockets... */ 13930d163575Sopenharmony_ci is_ipv6 = NETCONNTYPE_ISIPV6((unsigned int)(sock->conn->type)); 13940d163575Sopenharmony_ci#endif 13950d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 13960d163575Sopenharmony_ci struct net_group *group = get_net_group_from_ippcb(sock->conn->pcb.ip); 13970d163575Sopenharmony_ci#endif 13980d163575Sopenharmony_ci switch ((u32_t)cmd) { 13990d163575Sopenharmony_ci#if LWIP_IPV6 14000d163575Sopenharmony_ci#if LWIP_IPV6_DUP_DETECT_ATTEMPTS 14010d163575Sopenharmony_ci case SIOCSIPV6DAD: 14020d163575Sopenharmony_ci /* allow it only on IPv6 sockets... */ 14030d163575Sopenharmony_ci if (is_ipv6 == 0) { 14040d163575Sopenharmony_ci err = EINVAL; 14050d163575Sopenharmony_ci } else { 14060d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCSIPV6DAD(ifr); 14070d163575Sopenharmony_ci } 14080d163575Sopenharmony_ci break; 14090d163575Sopenharmony_ci case SIOCGIPV6DAD: 14100d163575Sopenharmony_ci /* allow it only on IPv6 sockets... */ 14110d163575Sopenharmony_ci if (is_ipv6 == 0) { 14120d163575Sopenharmony_ci err = EINVAL; 14130d163575Sopenharmony_ci } else { 14140d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCGIPV6DAD(ifr); 14150d163575Sopenharmony_ci } 14160d163575Sopenharmony_ci break; 14170d163575Sopenharmony_ci#endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */ 14180d163575Sopenharmony_ci#if LWIP_IOCTL_IPV6DPCTD 14190d163575Sopenharmony_ci case SIOCSIPV6DPCTD: 14200d163575Sopenharmony_ci /* allow it only on IPv6 sockets... */ 14210d163575Sopenharmony_ci if (is_ipv6 == 0) { 14220d163575Sopenharmony_ci err = EINVAL; 14230d163575Sopenharmony_ci } else { 14240d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCSIPV6DPCTD(ifr); 14250d163575Sopenharmony_ci } 14260d163575Sopenharmony_ci break; 14270d163575Sopenharmony_ci case SIOCGIPV6DPCTD: 14280d163575Sopenharmony_ci /* allow it only on IPv6 sockets... */ 14290d163575Sopenharmony_ci if (is_ipv6 == 0) { 14300d163575Sopenharmony_ci err = EINVAL; 14310d163575Sopenharmony_ci } else { 14320d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCGIPV6DPCTD(ifr); 14330d163575Sopenharmony_ci } 14340d163575Sopenharmony_ci break; 14350d163575Sopenharmony_ci#endif 14360d163575Sopenharmony_ci#endif /* LWIP_IPV6 */ 14370d163575Sopenharmony_ci#if LWIP_IOCTL_ROUTE 14380d163575Sopenharmony_ci case SIOCADDRT: 14390d163575Sopenharmony_ci /* Do not allow if socket is AF_INET6 */ 14400d163575Sopenharmony_ci if (is_ipv6 != 0) { 14410d163575Sopenharmony_ci err = EINVAL; 14420d163575Sopenharmony_ci } else { 14430d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 14440d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCADDRT(rmten, group); 14450d163575Sopenharmony_ci#else 14460d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCADDRT(rmten); 14470d163575Sopenharmony_ci#endif 14480d163575Sopenharmony_ci } 14490d163575Sopenharmony_ci break; 14500d163575Sopenharmony_ci#endif 14510d163575Sopenharmony_ci#if LWIP_IOCTL_IF 14520d163575Sopenharmony_ci case SIOCGIFCONF: 14530d163575Sopenharmony_ci /* Do not allow if socket is AF_INET6 */ 14540d163575Sopenharmony_ci if (is_ipv6 != 0) { 14550d163575Sopenharmony_ci err = EINVAL; 14560d163575Sopenharmony_ci } else { 14570d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 14580d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCGIFCONF(ifr, group); 14590d163575Sopenharmony_ci#else 14600d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCGIFCONF(ifr); 14610d163575Sopenharmony_ci#endif 14620d163575Sopenharmony_ci } 14630d163575Sopenharmony_ci break; 14640d163575Sopenharmony_ci case SIOCGIFADDR: 14650d163575Sopenharmony_ci if (is_ipv6 != 0) { 14660d163575Sopenharmony_ci err = EINVAL; 14670d163575Sopenharmony_ci } else { 14680d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCGIFADDR(ifr); 14690d163575Sopenharmony_ci } 14700d163575Sopenharmony_ci break; 14710d163575Sopenharmony_ci case SIOCSIFADDR: 14720d163575Sopenharmony_ci if (is_ipv6 != 0) { 14730d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCSIFADDR_6(ifr); 14740d163575Sopenharmony_ci } else { 14750d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 14760d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCSIFADDR(ifr, group); 14770d163575Sopenharmony_ci#else 14780d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCSIFADDR(ifr); 14790d163575Sopenharmony_ci#endif 14800d163575Sopenharmony_ci } 14810d163575Sopenharmony_ci break; 14820d163575Sopenharmony_ci case SIOCDIFADDR: 14830d163575Sopenharmony_ci /* Delete interface address */ 14840d163575Sopenharmony_ci if (is_ipv6 != 0) { 14850d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCDIFADDR_6(ifr); 14860d163575Sopenharmony_ci } else { 14870d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 14880d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCDIFADDR(ifr, group); 14890d163575Sopenharmony_ci#else 14900d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCDIFADDR(ifr); 14910d163575Sopenharmony_ci#endif 14920d163575Sopenharmony_ci } 14930d163575Sopenharmony_ci break; 14940d163575Sopenharmony_ci case SIOCGIFNETMASK: 14950d163575Sopenharmony_ci if (is_ipv6 != 0) { 14960d163575Sopenharmony_ci err = EINVAL; 14970d163575Sopenharmony_ci } else { 14980d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCGIFNETMASK(ifr); 14990d163575Sopenharmony_ci } 15000d163575Sopenharmony_ci break; 15010d163575Sopenharmony_ci case SIOCSIFNETMASK: 15020d163575Sopenharmony_ci if (is_ipv6 != 0) { 15030d163575Sopenharmony_ci err = EINVAL; 15040d163575Sopenharmony_ci } else { 15050d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 15060d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCSIFNETMASK(ifr, group); 15070d163575Sopenharmony_ci#else 15080d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCSIFNETMASK(ifr); 15090d163575Sopenharmony_ci#endif 15100d163575Sopenharmony_ci } 15110d163575Sopenharmony_ci break; 15120d163575Sopenharmony_ci case SIOCSIFHWADDR: 15130d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCSIFHWADDR(ifr); 15140d163575Sopenharmony_ci break; 15150d163575Sopenharmony_ci case SIOCGIFHWADDR: 15160d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCGIFHWADDR(ifr); 15170d163575Sopenharmony_ci break; 15180d163575Sopenharmony_ci case SIOCSIFFLAGS: 15190d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCSIFFLAGS(ifr); 15200d163575Sopenharmony_ci break; 15210d163575Sopenharmony_ci case SIOCGIFFLAGS: 15220d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCGIFFLAGS(ifr); 15230d163575Sopenharmony_ci break; 15240d163575Sopenharmony_ci case SIOCGIFNAME: 15250d163575Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 15260d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCGIFNAME(ifr, group); 15270d163575Sopenharmony_ci#else 15280d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCGIFNAME(ifr); 15290d163575Sopenharmony_ci#endif 15300d163575Sopenharmony_ci break; 15310d163575Sopenharmony_ci case SIOCSIFNAME: 15320d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCSIFNAME(ifr); 15330d163575Sopenharmony_ci break; 15340d163575Sopenharmony_ci /* Need to support the get index through ioctl 15350d163575Sopenharmony_ci * As of now the options is restricted to PF_PACKET scenario , so removed the compiler flag Begin 15360d163575Sopenharmony_ci */ 15370d163575Sopenharmony_ci case SIOCGIFINDEX: 15380d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCGIFINDEX(ifr); 15390d163575Sopenharmony_ci break; 15400d163575Sopenharmony_ci case SIOCGIFMTU: 15410d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCGIFMTU(ifr); 15420d163575Sopenharmony_ci break; 15430d163575Sopenharmony_ci case SIOCSIFMTU: 15440d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCSIFMTU(ifr); 15450d163575Sopenharmony_ci break; 15460d163575Sopenharmony_ci case SIOCGIFBRDADDR: 15470d163575Sopenharmony_ci if (is_ipv6 != 0) { 15480d163575Sopenharmony_ci err = EINVAL; 15490d163575Sopenharmony_ci } else { 15500d163575Sopenharmony_ci err = lwip_ioctl_internal_SIOCGIFBRDADDR(ifr); 15510d163575Sopenharmony_ci } 15520d163575Sopenharmony_ci break; 15530d163575Sopenharmony_ci#endif /* LWIP_IOCTL_IF */ 15540d163575Sopenharmony_ci#if LWIP_NETIF_ETHTOOL 15550d163575Sopenharmony_ci case SIOCETHTOOL: 15560d163575Sopenharmony_ci ret = lwip_ioctl_internal_SIOCETHTOOL(ifr); 15570d163575Sopenharmony_ci if (ret != 0) { 15580d163575Sopenharmony_ci /* an IO error happened */ 15590d163575Sopenharmony_ci err = EIO; 15600d163575Sopenharmony_ci } 15610d163575Sopenharmony_ci break; 15620d163575Sopenharmony_ci#endif 15630d163575Sopenharmony_ci /* START For cmd = -1 stack has to treat it as Invalid Input and return EINVAL */ 15640d163575Sopenharmony_ci case 0xFFFFFFFF: 15650d163575Sopenharmony_ci err = EINVAL; 15660d163575Sopenharmony_ci LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl_impl(INVALID: 0x%lx)\n", cmd)); 15670d163575Sopenharmony_ci break; 15680d163575Sopenharmony_ci default: 15690d163575Sopenharmony_ci err = ENOSYS; 15700d163575Sopenharmony_ci LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(UNIMPL: 0x%lx)\n", cmd)); 15710d163575Sopenharmony_ci break; 15720d163575Sopenharmony_ci } 15730d163575Sopenharmony_ci 15740d163575Sopenharmony_ci return err; 15750d163575Sopenharmony_ci} 15760d163575Sopenharmony_ci 15770d163575Sopenharmony_cistatic err_t lwip_do_ioctl_impl(struct tcpip_api_call_data *call) 15780d163575Sopenharmony_ci{ 15790d163575Sopenharmony_ci struct lwip_ioctl_apimsg *msg = (struct lwip_ioctl_apimsg *)(void *)call; 15800d163575Sopenharmony_ci return lwip_ioctl_impl(msg->sock, msg->cmd, msg->argp); 15810d163575Sopenharmony_ci} 15820d163575Sopenharmony_ci 15830d163575Sopenharmony_ci#include "los_vm_map.h" 15840d163575Sopenharmony_ci#include "user_copy.h" 15850d163575Sopenharmony_cistatic int do_ioctl_SIOCGIFCONF(int sockfd, long cmd, void *argp) 15860d163575Sopenharmony_ci{ 15870d163575Sopenharmony_ci int nbytes; 15880d163575Sopenharmony_ci struct ifconf ifc; 15890d163575Sopenharmony_ci char *buf_bak = NULL; 15900d163575Sopenharmony_ci int ret; 15910d163575Sopenharmony_ci 15920d163575Sopenharmony_ci if (LOS_ArchCopyFromUser(&ifc, argp, sizeof(struct ifconf)) != 0) { 15930d163575Sopenharmony_ci set_errno(EFAULT); 15940d163575Sopenharmony_ci return -1; 15950d163575Sopenharmony_ci } 15960d163575Sopenharmony_ci nbytes = ifc.ifc_len; 15970d163575Sopenharmony_ci if (nbytes <= 0) { 15980d163575Sopenharmony_ci set_errno(EINVAL); 15990d163575Sopenharmony_ci return -1; 16000d163575Sopenharmony_ci } 16010d163575Sopenharmony_ci buf_bak = ifc.ifc_buf; 16020d163575Sopenharmony_ci if (!LOS_IsUserAddress((VADDR_T)(uintptr_t)buf_bak)) { 16030d163575Sopenharmony_ci set_errno(EFAULT); 16040d163575Sopenharmony_ci return -1; 16050d163575Sopenharmony_ci } 16060d163575Sopenharmony_ci ifc.ifc_buf = malloc(nbytes); 16070d163575Sopenharmony_ci if (ifc.ifc_buf == NULL) { 16080d163575Sopenharmony_ci set_errno(ENOMEM); 16090d163575Sopenharmony_ci return -1; 16100d163575Sopenharmony_ci } 16110d163575Sopenharmony_ci (void)memset_s(ifc.ifc_buf, nbytes, 0, nbytes); 16120d163575Sopenharmony_ci 16130d163575Sopenharmony_ci ret = lwip_ioctl(sockfd, cmd, &ifc); 16140d163575Sopenharmony_ci if (ret == 0) { 16150d163575Sopenharmony_ci if (LOS_ArchCopyToUser(buf_bak, ifc.ifc_buf, nbytes) != 0) { 16160d163575Sopenharmony_ci set_errno(EFAULT); 16170d163575Sopenharmony_ci ret = -1; 16180d163575Sopenharmony_ci } 16190d163575Sopenharmony_ci } 16200d163575Sopenharmony_ci 16210d163575Sopenharmony_ci free(ifc.ifc_buf); 16220d163575Sopenharmony_ci ifc.ifc_buf = buf_bak; 16230d163575Sopenharmony_ci if (LOS_ArchCopyToUser(argp, &ifc, sizeof(struct ifconf)) != 0) { 16240d163575Sopenharmony_ci set_errno(EFAULT); 16250d163575Sopenharmony_ci ret = -1; 16260d163575Sopenharmony_ci } 16270d163575Sopenharmony_ci return ret; 16280d163575Sopenharmony_ci} 16290d163575Sopenharmony_ci 16300d163575Sopenharmony_ciint socks_ioctl(int sockfd, long cmd, void *argp) 16310d163575Sopenharmony_ci{ 16320d163575Sopenharmony_ci void *argpbak = argp; 16330d163575Sopenharmony_ci int ret; 16340d163575Sopenharmony_ci size_t nbytes = 0; 16350d163575Sopenharmony_ci 16360d163575Sopenharmony_ci if (LOS_IsUserAddress((VADDR_T)(uintptr_t)argp)) { 16370d163575Sopenharmony_ci switch (cmd) { 16380d163575Sopenharmony_ci case FIONREAD: 16390d163575Sopenharmony_ci case FIONBIO: 16400d163575Sopenharmony_ci nbytes = sizeof(int); 16410d163575Sopenharmony_ci break; 16420d163575Sopenharmony_ci case SIOCADDRT: 16430d163575Sopenharmony_ci nbytes = sizeof(struct rtentry); 16440d163575Sopenharmony_ci break; 16450d163575Sopenharmony_ci case SIOCGIFCONF: 16460d163575Sopenharmony_ci return do_ioctl_SIOCGIFCONF(sockfd, cmd, argp); 16470d163575Sopenharmony_ci case SIOCSIPV6DAD: 16480d163575Sopenharmony_ci case SIOCGIPV6DAD: 16490d163575Sopenharmony_ci case SIOCSIPV6DPCTD: 16500d163575Sopenharmony_ci case SIOCGIPV6DPCTD: 16510d163575Sopenharmony_ci case SIOCGIFADDR: 16520d163575Sopenharmony_ci case SIOCSIFADDR: 16530d163575Sopenharmony_ci case SIOCDIFADDR: 16540d163575Sopenharmony_ci case SIOCGIFNETMASK: 16550d163575Sopenharmony_ci case SIOCSIFNETMASK: 16560d163575Sopenharmony_ci case SIOCSIFHWADDR: 16570d163575Sopenharmony_ci case SIOCGIFHWADDR: 16580d163575Sopenharmony_ci case SIOCSIFFLAGS: 16590d163575Sopenharmony_ci case SIOCGIFFLAGS: 16600d163575Sopenharmony_ci case SIOCGIFNAME: 16610d163575Sopenharmony_ci case SIOCSIFNAME: 16620d163575Sopenharmony_ci case SIOCGIFINDEX: 16630d163575Sopenharmony_ci case SIOCGIFMTU: 16640d163575Sopenharmony_ci case SIOCSIFMTU: 16650d163575Sopenharmony_ci case SIOCETHTOOL: 16660d163575Sopenharmony_ci case SIOCGIFBRDADDR: 16670d163575Sopenharmony_ci nbytes = sizeof(struct ifreq); 16680d163575Sopenharmony_ci break; 16690d163575Sopenharmony_ci default: 16700d163575Sopenharmony_ci nbytes = 0; 16710d163575Sopenharmony_ci } 16720d163575Sopenharmony_ci if (argp != NULL && nbytes > 0) { 16730d163575Sopenharmony_ci argp = malloc(nbytes); 16740d163575Sopenharmony_ci if (argp == NULL) { 16750d163575Sopenharmony_ci set_errno(ENOMEM); 16760d163575Sopenharmony_ci return -1; 16770d163575Sopenharmony_ci } 16780d163575Sopenharmony_ci if (LOS_ArchCopyFromUser(argp, argpbak, nbytes) != 0) { 16790d163575Sopenharmony_ci free(argp); 16800d163575Sopenharmony_ci set_errno(EFAULT); 16810d163575Sopenharmony_ci return -1; 16820d163575Sopenharmony_ci } 16830d163575Sopenharmony_ci } 16840d163575Sopenharmony_ci } 16850d163575Sopenharmony_ci ret = lwip_ioctl(sockfd, cmd, argp); 16860d163575Sopenharmony_ci if (ret == 0 && argp != argpbak) { 16870d163575Sopenharmony_ci if (LOS_ArchCopyToUser(argpbak, argp, nbytes) != 0) { 16880d163575Sopenharmony_ci /* how to rollback ioctl ? */ 16890d163575Sopenharmony_ci set_errno(EFAULT); 16900d163575Sopenharmony_ci ret = -1; 16910d163575Sopenharmony_ci } 16920d163575Sopenharmony_ci } 16930d163575Sopenharmony_ci if (argp != argpbak) { 16940d163575Sopenharmony_ci free(argp); 16950d163575Sopenharmony_ci } 16960d163575Sopenharmony_ci return ret; 16970d163575Sopenharmony_ci} 16980d163575Sopenharmony_ci 16990d163575Sopenharmony_civoid socks_refer(int sockfd) 17000d163575Sopenharmony_ci{ 17010d163575Sopenharmony_ci struct lwip_sock *sock = NULL; 17020d163575Sopenharmony_ci SYS_ARCH_DECL_PROTECT(lev); 17030d163575Sopenharmony_ci 17040d163575Sopenharmony_ci sock = get_socket(sockfd); 17050d163575Sopenharmony_ci if (!sock) { 17060d163575Sopenharmony_ci return; 17070d163575Sopenharmony_ci } 17080d163575Sopenharmony_ci 17090d163575Sopenharmony_ci SYS_ARCH_PROTECT(lev); 17100d163575Sopenharmony_ci 17110d163575Sopenharmony_ci sock->s_refcount++; 17120d163575Sopenharmony_ci 17130d163575Sopenharmony_ci SYS_ARCH_UNPROTECT(lev); 17140d163575Sopenharmony_ci 17150d163575Sopenharmony_ci done_socket(sock); 17160d163575Sopenharmony_ci} 17170d163575Sopenharmony_ci 17180d163575Sopenharmony_ciint socks_close(int sockfd) 17190d163575Sopenharmony_ci{ 17200d163575Sopenharmony_ci struct lwip_sock *sock = NULL; 17210d163575Sopenharmony_ci SYS_ARCH_DECL_PROTECT(lev); 17220d163575Sopenharmony_ci 17230d163575Sopenharmony_ci sock = get_socket(sockfd); 17240d163575Sopenharmony_ci if (!sock) { 17250d163575Sopenharmony_ci return -1; 17260d163575Sopenharmony_ci } 17270d163575Sopenharmony_ci 17280d163575Sopenharmony_ci SYS_ARCH_PROTECT(lev); 17290d163575Sopenharmony_ci 17300d163575Sopenharmony_ci if (sock->s_refcount == 0) { 17310d163575Sopenharmony_ci SYS_ARCH_UNPROTECT(lev); 17320d163575Sopenharmony_ci done_socket(sock); 17330d163575Sopenharmony_ci return lwip_close(sockfd); 17340d163575Sopenharmony_ci } 17350d163575Sopenharmony_ci 17360d163575Sopenharmony_ci sock->s_refcount--; 17370d163575Sopenharmony_ci 17380d163575Sopenharmony_ci SYS_ARCH_UNPROTECT(lev); 17390d163575Sopenharmony_ci done_socket(sock); 17400d163575Sopenharmony_ci return 0; 17410d163575Sopenharmony_ci} 1742