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