• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <lwip/sockets.h>
33 #include <lwip/priv/tcpip_priv.h>
34 #include <lwip/fixme.h>
35 
36 #if LWIP_ENABLE_NET_CAPABILITY
37 #include "capability_type.h"
38 #include "capability_api.h"
39 #define BIND_SERVICE_CAP_MIN_PORT 1024
40 #endif
41 
42 #define IOCTL_CMD_CASE_HANDLER() \
43     {                                                          \
44         err_t  err;                                            \
45         struct lwip_ioctl_apimsg msg;                          \
46         msg.sock = sock;                                       \
47         msg.cmd = cmd;                                         \
48         msg.argp = argp;                                       \
49                                                                \
50         err = tcpip_api_call(lwip_do_ioctl_impl, &msg.call);   \
51         if (err != ENOSYS) {                                   \
52             sock_set_errno(sock, err);                         \
53             done_socket(sock);                                 \
54             return -(err != ERR_OK);                           \
55         }                                                      \
56     }
57 
58 struct lwip_ioctl_apimsg {
59     struct tcpip_api_call_data call;
60     struct lwip_sock *sock;
61     long cmd;
62     void *argp;
63 };
64 
65 static err_t lwip_do_ioctl_impl(struct tcpip_api_call_data *call);
66 
67 static void poll_check_waiters(int s, int check_waiters);
68 
69 static int lwip_socket_wrap(int domain, int type, int protocol);
lwip_socket(int domain,int type,int protocol)70 int lwip_socket(int domain, int type, int protocol)
71 {
72     return lwip_socket_wrap(domain, type, protocol);
73 }
74 
75 static int lwip_setsockopt_wrap(int s, int level, int optname, const void *optval, socklen_t optlen);
lwip_setsockopt(int s,int level,int optname,const void * optval,socklen_t optlen)76 int lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
77 {
78     return lwip_setsockopt_wrap(s, level, optname, optval, optlen);
79 }
80 
81 static int lwip_bind_wrap(int s, const struct sockaddr *name, socklen_t namelen);
lwip_bind(int s,const struct sockaddr * name,socklen_t namelen)82 int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
83 {
84     return lwip_bind_wrap(s, name, namelen);
85 }
86 
87 static ssize_t lwip_sendto_wrap(int s, const void *dataptr, size_t size, int flags,
88                                 const struct sockaddr *to, socklen_t tolen);
lwip_sendto(int s,const void * dataptr,size_t size,int flags,const struct sockaddr * to,socklen_t tolen)89 ssize_t lwip_sendto(int s, const void *dataptr, size_t size, int flags, const struct sockaddr *to, socklen_t tolen)
90 {
91     return lwip_sendto_wrap(s, dataptr, size, flags, to, tolen);
92 }
93 
94 #ifdef lwip_socket
95 #undef lwip_socket
96 #endif
97 #define lwip_socket static lwip_socket2
98 static int lwip_socket2(int domain, int type, int protocol);
99 
100 #ifdef lwip_setsockopt
101 #undef lwip_setsockopt
102 #endif
103 #define lwip_setsockopt static lwip_setsockopt2
104 static int lwip_setsockopt2(int s, int level, int optname, const void *optval, socklen_t optlen);
105 
106 #ifdef lwip_bind
107 #undef lwip_bind
108 #endif
109 #define lwip_bind static lwip_bind2
110 static int lwip_bind2(int s, const struct sockaddr *name, socklen_t namelen);
111 
112 #ifdef lwip_sendto
113 #undef lwip_sendto
114 #endif
115 #define lwip_sendto lwip_sendto2
116 ssize_t lwip_sendto2(int s, const void *dataptr, size_t size, int flags, const struct sockaddr *to, socklen_t tolen);
117 
118 #include "../api/sockets.c"
119 
120 #undef lwip_socket
121 #undef lwip_setsockopt
122 #undef lwip_bind
123 #undef lwip_sendto
124 
lwip_socket_wrap(int domain,int type,int protocol)125 static int lwip_socket_wrap(int domain, int type, int protocol)
126 {
127     if (domain != AF_INET && domain != AF_INET6) {
128         set_errno(EAFNOSUPPORT);
129         return -1;
130     }
131 #if LWIP_ENABLE_NET_CAPABILITY
132     if (type == SOCK_RAW && !IsCapPermit(CAP_NET_RAW)) {
133         set_errno(EPERM);
134         return -1;
135     }
136 #endif
137     return lwip_socket2(domain, type, protocol);
138 }
139 
lwip_setsockopt_wrap(int s,int level,int optname,const void * optval,socklen_t optlen)140 static int lwip_setsockopt_wrap(int s, int level, int optname, const void *optval, socklen_t optlen)
141 {
142 #if LWIP_ENABLE_NET_CAPABILITY
143     if (level == SOL_SOCKET) {
144         switch (optname) {
145 #if LWIP_ENABLE_CAP_NET_BROADCAST
146             case SO_BROADCAST:
147                 if (!IsCapPermit(CAP_NET_BROADCAST)) {
148                     set_errno(EPERM);
149                     return -1;
150                 }
151                 break;
152 #endif
153             case SO_DEBUG:
154             case SO_MARK:
155             case SO_PRIORITY:
156             case SO_RCVBUFFORCE:
157             case SO_SNDBUFFORCE:
158                 if (!IsCapPermit(CAP_NET_ADMIN)) {
159                     set_errno(EPERM);
160                     return -1;
161                 }
162                 break;
163             default:
164                 break;
165         }
166     }
167 #endif
168     return lwip_setsockopt2(s, level, optname, optval, optlen);
169 }
170 
171 #if LWIP_ENABLE_NET_CAPABILITY && LWIP_ENABLE_CAP_NET_BROADCAST
ip_addr_isbroadcast_bysock(const ip_addr_t * ipaddr,int s)172 static int ip_addr_isbroadcast_bysock(const ip_addr_t *ipaddr, int s)
173 {
174     struct sockaddr sa;
175     socklen_t salen = sizeof(sa);
176 
177     if (ipaddr == NULL) {
178         return 0;
179     }
180 
181     if (lwip_getsockname(s, &sa, &salen) == -1) {
182         return 0;
183     }
184 
185     ip_addr_t addr;
186     u16_t port;
187 
188     SOCKADDR_TO_IPADDR_PORT(&sa, &addr, port);
189 
190     struct netif *netif = NULL;
191     NETIF_FOREACH(netif) {
192         if (ip_addr_cmp(&netif->ip_addr, &addr)) {
193             return ip_addr_isbroadcast(ipaddr, netif);
194         }
195         for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
196             if (ip_addr_cmp(&netif->ip6_addr[i], &addr)) {
197                 return ip_addr_isbroadcast(ipaddr, netif);
198             }
199         }
200     }
201 
202     return 0;
203 }
204 #endif
205 
lwip_bind_wrap(int s,const struct sockaddr * name,socklen_t namelen)206 static int lwip_bind_wrap(int s, const struct sockaddr *name, socklen_t namelen)
207 {
208 #if LWIP_ENABLE_NET_CAPABILITY
209     if ((name->sa_family == AF_INET && namelen >= sizeof(struct sockaddr_in)) ||
210         (name->sa_family == AF_INET6 && namelen >= sizeof(struct sockaddr_in6))) {
211         ip_addr_t ipaddr;
212         u16_t port;
213 
214         SOCKADDR_TO_IPADDR_PORT(name, &ipaddr, port);
215 
216         if (port != 0 && port < BIND_SERVICE_CAP_MIN_PORT) {
217             LWIP_ERROR("permission deny: NET_BIND_SERVICE\n", IsCapPermit(CAP_NET_BIND_SERVICE),
218                        set_errno(EPERM); return -1);
219         }
220 #if LWIP_ENABLE_CAP_NET_BROADCAST
221         if (ip_addr_ismulticast(&ipaddr) || ip_addr_isbroadcast_bysock(&ipaddr, s)) {
222             LWIP_ERROR("permission deny: NET_BROADCAST\n", IsCapPermit(CAP_NET_BROADCAST),
223                        set_errno(EPERM); return -1);
224         }
225 #endif
226     }
227 #endif
228 
229     return lwip_bind2(s, name, namelen);
230 }
231 
lwip_sendto_wrap(int s,const void * dataptr,size_t size,int flags,const struct sockaddr * to,socklen_t tolen)232 static ssize_t lwip_sendto_wrap(int s, const void *dataptr, size_t size, int flags,
233                                 const struct sockaddr *to, socklen_t tolen)
234 {
235 #if LWIP_ENABLE_NET_CAPABILITY
236     if (to &&
237         ((to->sa_family == AF_INET && tolen >= sizeof(struct sockaddr_in)) ||
238          (to->sa_family == AF_INET6 && tolen >= sizeof(struct sockaddr_in6)))) {
239         ip_addr_t ipaddr;
240         u16_t port;
241 
242         SOCKADDR_TO_IPADDR_PORT(to, &ipaddr, port);
243 #if LWIP_ENABLE_CAP_NET_BROADCAST
244         if (ip_addr_ismulticast(&ipaddr) || ip_addr_isbroadcast_bysock(&ipaddr, s)) {
245             LWIP_ERROR("permission deny: NET_BROADCAST\n", IsCapPermit(CAP_NET_BROADCAST),
246                        set_errno(EPERM); return -1);
247         }
248 #endif
249     }
250 #endif
251 
252     return lwip_sendto2(s, dataptr, size, flags, to, tolen);
253 }
254 
255 #if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
256 
257 struct file;
258 extern void poll_wait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p);
259 extern void __wake_up_interruptible_poll(wait_queue_head_t *wait, pollevent_t key);
260 
poll_check_waiters(int s,int check_waiters)261 static void poll_check_waiters(int s, int check_waiters)
262 {
263     unsigned long int_save, wq_empty;
264     pollevent_t mask = 0;
265     struct lwip_sock *sock;
266     SYS_ARCH_DECL_PROTECT(lev);
267 
268     if (!check_waiters) {
269         return;
270     }
271 
272     sock = get_socket(s);
273     if (!sock) {
274         return;
275     }
276 
277     SYS_ARCH_PROTECT(lev);
278 
279     mask |= (sock->rcvevent > 0) ? (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND) : 0;
280     mask |= (sock->sendevent != 0) ? (POLLOUT | POLLWRNORM | POLLWRBAND) : 0;
281     mask |= (sock->errevent != 0) ? (POLLERR) : 0;
282 
283     SYS_ARCH_UNPROTECT(lev);
284 
285     spin_lock_irqsave(&sock->wq.lock, int_save);
286     wq_empty = LOS_ListEmpty(&(sock->wq.poll_queue));
287     spin_unlock_irqrestore(&sock->wq.lock, int_save);
288 
289     if (mask && !wq_empty) {
290         __wake_up_interruptible_poll(&sock->wq, mask);
291     }
292 
293     done_socket(sock);
294 }
295 
socks_poll(int s,poll_table * wait)296 int socks_poll(int s, poll_table *wait)
297 {
298     int ret;
299     pollevent_t mask = 0;
300     struct lwip_sock *sock;
301     SYS_ARCH_DECL_PROTECT(lev);
302 
303     LWIP_ERROR("sock_poll: invalid poll_table", (wait != NULL), return -EINVAL;);
304 
305     sock = get_socket(s);
306     if (!sock) {
307         LWIP_DEBUGF(SOCKETS_DEBUG, ("sock_poll: Invalid socket"));
308         set_errno(EBADF);
309         return -EBADF; /* compatible with file poll */
310     }
311 
312     SYS_ARCH_PROTECT(lev);
313 
314     mask |= (sock->rcvevent > 0 || sock->lastdata.pbuf) ? (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND) : 0;
315     mask |= (sock->sendevent != 0) ? (POLLOUT | POLLWRNORM | POLLWRBAND) : 0;
316     mask |= (sock->errevent != 0) ? (POLLERR) : 0;
317 
318     SYS_ARCH_UNPROTECT(lev);
319 
320     ret = wait->key & mask;
321     if (!ret) {
322         poll_wait(NULL, &sock->wq, wait);
323     }
324 
325     done_socket(sock);
326     return ret;
327 }
328 
329 #endif /* LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL */
330 
331 #if !LWIP_COMPAT_SOCKETS
332 
333 #define API_ALIAS(old, new) \
334     extern __typeof(old) new __attribute__((__weak__, __alias__(#old)))
335 
336 API_ALIAS(lwip_ioctl, ioctlsocket);
337 
338 #endif /* !LWIP_COMPAT_SOCKETS */
339 
340 #if LWIP_ENABLE_LOS_SHELL_CMD
341 /* get numbers of unused sockets */
get_unused_socket_num(void)342 int get_unused_socket_num(void)
343 {
344     int unused = 0;
345     SYS_ARCH_DECL_PROTECT(lev);
346 
347     SYS_ARCH_PROTECT(lev);
348 
349     for (int i = 0; i < NUM_SOCKETS; i++) {
350         if (sockets[i].conn == NULL) {
351 #if LWIP_NETCONN_FULLDUPLEX
352             if (sockets[i].fd_used) {
353                 continue;
354             }
355 #endif
356             unused++;
357         }
358     }
359 
360     SYS_ARCH_UNPROTECT(lev);
361 
362     return unused;
363 }
364 #endif
365 
366 /**
367  * socket ioctl
368  */
369 
370 // Options for lwip ioctl
371 #define LWIP_IOCTL_ROUTE                1
372 #define LWIP_IOCTL_IF                   1
373 #define LWIP_NETIF_ETHTOOL              0
374 #define LWIP_IOCTL_IPV6DPCTD            0
375 #undef LWIP_IPV6_DUP_DETECT_ATTEMPTS
376 #define LWIP_IPV6_DUP_DETECT_ATTEMPTS   0
377 
378 #ifndef SIOCSIPV6DAD
379 #define SIOCSIPV6DAD _IOW('z', 0, unsigned long) /* set DAD enable/disable on netif */
380 #endif
381 
382 #ifndef SIOCGIPV6DAD
383 #define SIOCGIPV6DAD _IOR('z', 1, unsigned long) /* get DAD status on netif */
384 #endif
385 
386 #ifndef SIOCSIPV6DPCTD
387 #define SIOCSIPV6DPCTD _IOW('z', 2, unsigned long)
388 #endif
389 
390 #ifndef SIOCGIPV6DPCTD
391 #define SIOCGIPV6DPCTD _IOR('z', 3, unsigned long)
392 #endif
393 
394 #ifndef SIOCETHTOOL
395 #define SIOCETHTOOL 0x8946
396 #endif
397 
398 #if LWIP_NETIF_PROMISC
399 #define NETIF_FLAG_PROMISC 0x80U
400 #endif /* LWIP_NETIF_PROMISC */
401 
402 
403 #if LWIP_IOCTL_ROUTE
404 
405 #include <net/route.h>
406 
407 #ifdef LOSCFG_NET_CONTAINER
lwip_ioctl_internal_SIOCADDRT(struct rtentry * rmten,struct net_group * group)408 static u8_t lwip_ioctl_internal_SIOCADDRT(struct rtentry *rmten, struct net_group *group)
409 #else
410 static u8_t lwip_ioctl_internal_SIOCADDRT(struct rtentry *rmten)
411 #endif
412 {
413     struct netif *netif = NULL;
414     ip_addr_t rtgw_addr;
415     u16_t rtgw_port;
416 
417 #if LWIP_ENABLE_NET_CAPABILITY
418     if (!IsCapPermit(CAP_NET_ADMIN)) {
419         return EPERM;
420     }
421 #endif
422 
423     SOCKADDR_TO_IPADDR_PORT(&rmten->rt_gateway, &rtgw_addr, rtgw_port);
424 
425     if (!IP_IS_V4_VAL(rtgw_addr)) {
426         return EINVAL;
427     }
428 
429     /* check if multicast/0/loopback */
430     if (ip_addr_ismulticast(&rtgw_addr) || ip_addr_isany(&rtgw_addr) ||
431         ip_addr_isloopback(&rtgw_addr)) {
432         return EINVAL;
433     }
434 
435     /* check if reachable */
436 #ifdef LOSCFG_NET_CONTAINER
437     for (netif = group->netif_list; netif != NULL; netif = netif->next) {
438 #else
439     for (netif = netif_list; netif != NULL; netif = netif->next) {
440 #endif
441         if (ip_addr_netcmp(&rtgw_addr, &netif->ip_addr, ip_2_ip4(&netif->netmask))) {
442             break;
443         }
444     }
445 
446     if (netif == NULL) {
447         return EHOSTUNREACH;
448     }
449 
450     /* check if broadcast */
451     if (ip_addr_isbroadcast(&rtgw_addr, netif) != 0) {
452         return EINVAL;
453     }
454 
455     /* Check flags */
456     if ((rmten->rt_flags & RTF_GATEWAY) == 0) {
457         return EINVAL;
458     }
459 
460     /* Add validation */
461 #ifdef LOSCFG_NET_CONTAINER
462     if ((group->netif_default != NULL) && (group->netif_default != netif)) {
463         ip_addr_set_zero(&group->netif_default->gw);
464         (void)netif_set_default(netif, group);
465 #else
466     if ((netif_default != NULL) && (netif_default != netif)) {
467         ip_addr_set_zero(&netif_default->gw);
468         (void)netif_set_default(netif);
469 #endif
470     }
471     netif_set_gw(netif, ip_2_ip4(&rtgw_addr));
472 
473     return 0;
474 }
475 
476 #endif
477 
478 #if LWIP_IOCTL_IF
479 #ifdef LOSCFG_NET_CONTAINER
480 static u8_t lwip_ioctl_internal_SIOCGIFCONF(struct ifreq *ifr, struct net_group *group)
481 #else
482 static u8_t lwip_ioctl_internal_SIOCGIFCONF(struct ifreq *ifr)
483 #endif
484 {
485     struct ifconf *ifc = NULL;
486     struct netif *netif = NULL;
487     struct ifreq ifreq;
488     struct sockaddr_in *sock_in = NULL;
489     int pos;
490     int len;
491     int ret;
492 
493     /* Format the caller's buffer. */
494     ifc = (struct ifconf *)ifr;
495     len = ifc->ifc_len;
496 
497     /* Loop over the interfaces, and write an info block for each. */
498     pos = 0;
499 #ifdef LOSCFG_NET_CONTAINER
500     for (netif = group->netif_list; netif != NULL; netif = netif->next) {
501 #else
502     for (netif = netif_list; netif != NULL; netif = netif->next) {
503 #endif
504         if (ifc->ifc_buf == NULL) {
505             pos = (pos + (int)sizeof(struct ifreq));
506             continue;
507         }
508 
509         if (len < (int)sizeof(ifreq)) {
510             break;
511         }
512         (void)memset_s(&ifreq, sizeof(struct ifreq), 0, sizeof(struct ifreq));
513         if (netif->link_layer_type == LOOPBACK_IF) {
514             ret = snprintf_s(ifreq.ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%.2s", netif->name);
515             if ((ret <= 0) || (ret >= IFNAMSIZ)) {
516                 LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed."));
517                 return ENOBUFS;
518             }
519         } else {
520             ret = snprintf_s(ifreq.ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%s", netif_get_name(netif));
521             if ((ret <= 0) || (ret >= IFNAMSIZ)) {
522                 LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed."));
523                 return ENOBUFS;
524             }
525         }
526 
527         sock_in = (struct sockaddr_in *)&ifreq.ifr_addr;
528         sock_in->sin_family = AF_INET;
529         sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr;
530         if (memcpy_s(ifc->ifc_buf + pos, sizeof(struct ifreq), &ifreq, sizeof(struct ifreq)) != EOK) {
531             return ENOBUFS;
532         }
533         pos = pos + (int)sizeof(struct ifreq);
534         len = len - (int)sizeof(struct ifreq);
535     }
536 
537     ifc->ifc_len = pos;
538 
539     return 0;
540 }
541 
542 static u8_t lwip_ioctl_internal_SIOCGIFADDR(struct ifreq *ifr)
543 {
544     struct netif *netif = NULL;
545     struct sockaddr_in *sock_in = NULL;
546 
547     /* get netif ipaddr */
548     netif = netif_find(ifr->ifr_name);
549     if (netif == NULL) {
550         return ENODEV;
551     } else {
552         sock_in = (struct sockaddr_in *)&ifr->ifr_addr;
553         sock_in->sin_family = AF_INET;
554         sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr;
555         return 0;
556     }
557 }
558 
559 #ifndef LWIP_IPV6_PREFIX_LEN
560 #define LWIP_IPV6_PREFIX_LEN 64
561 #endif
562 
563 #ifndef LWIP_NETIF_IFINDEX_MAX_EX
564 #define LWIP_NETIF_IFINDEX_MAX_EX 255
565 #endif
566 
567 #include "lwip/dhcp.h"
568 #include "lwip/dhcp6.h"
569 #include "lwip/prot/dhcp.h"
570 #include "lwip/prot/dhcp6.h"
571 
572 static u8_t lwip_ioctl_internal_SIOCSIFADDR_6(struct ifreq *ifr)
573 {
574     (void)ifr;
575     return ENOSYS;
576 }
577 
578 #ifdef LOSCFG_NET_CONTAINER
579 static u8_t lwip_ioctl_internal_SIOCSIFADDR(struct ifreq *ifr, struct net_group *group)
580 #else
581 static u8_t lwip_ioctl_internal_SIOCSIFADDR(struct ifreq *ifr)
582 #endif
583 {
584     struct netif *netif = NULL;
585 
586     struct netif *loc_netif = NULL;
587     ip_addr_t taget_addr;
588     u16_t taget_port;
589     SOCKADDR_TO_IPADDR_PORT(&ifr->ifr_addr, &taget_addr, taget_port);
590 
591 #if LWIP_ENABLE_NET_CAPABILITY
592     if (!IsCapPermit(CAP_NET_ADMIN)) {
593         return EPERM;
594     }
595 #endif
596 
597     /* set netif ipaddr */
598     netif = netif_find(ifr->ifr_name);
599     if (netif == NULL) {
600         return ENODEV;
601     }
602 #if LWIP_HAVE_LOOPIF
603     else if (netif->link_layer_type == LOOPBACK_IF) {
604         return EPERM;
605     }
606 #endif
607     else {
608         /* check the address is not multicast/broadcast/0/loopback */
609         if (!IP_IS_V4(&taget_addr) || ip_addr_ismulticast(&taget_addr) ||
610             ip_addr_isbroadcast(&taget_addr, netif) ||
611             ip_addr_isany(&taget_addr) ||
612             ip_addr_isloopback(&taget_addr)) {
613             return EINVAL;
614         }
615 
616         /* reset gateway if new and previous ipaddr not in same net */
617         if (ip_addr_netcmp(&taget_addr, &netif->ip_addr, ip_2_ip4(&netif->netmask)) == 0) {
618             ip_addr_set_zero(&netif->gw);
619 #ifdef LOSCFG_NET_CONTAINER
620             if (netif == group->netif_default) {
621                 (void)netif_set_default(NULL, group);
622 #else
623             if (netif == netif_default) {
624                 (void)netif_set_default(NULL);
625 #endif
626             }
627         }
628 
629         /* lwip disallow two netif sit in same net at the same time */
630 #ifdef LOSCFG_NET_CONTAINER
631         loc_netif = group->netif_list;
632 #else
633         loc_netif = netif_list;
634 #endif
635         while (loc_netif != NULL) {
636             if (loc_netif == netif) {
637                 loc_netif = loc_netif->next;
638                 continue;
639             }
640             if (ip_addr_cmp(&netif->netmask, &loc_netif->netmask) &&
641                 ip_addr_netcmp(&loc_netif->ip_addr, &taget_addr,
642                                ip_2_ip4(&netif->netmask))) {
643                 return EINVAL;
644             }
645             loc_netif = loc_netif->next;
646         }
647 
648 #if LWIP_DHCP
649         if ((netif_dhcp_data(netif) != NULL) &&
650             (netif_dhcp_data(netif)->state != DHCP_STATE_OFF)) {
651             (void)netif_dhcp_off(netif);
652         }
653 #endif
654 
655 #if LWIP_ARP
656         /* clear ARP cache when IP address changed */
657         if ((netif->flags & NETIF_FLAG_ETHARP) != 0) {
658             etharp_cleanup_netif(netif);
659         }
660 #endif /* LWIP_ARP */
661 
662         netif_set_ipaddr(netif, ip_2_ip4(&taget_addr));
663 
664         return 0;
665     }
666 }
667 
668 static u8_t lwip_ioctl_internal_SIOCDIFADDR_6(struct ifreq *ifr)
669 {
670     (void)ifr;
671     return ENOSYS;
672 }
673 
674 #ifdef LOSCFG_NET_CONTAINER
675 static u8_t lwip_ioctl_internal_SIOCDIFADDR(struct ifreq *ifr, struct net_group *group)
676 #else
677 static u8_t lwip_ioctl_internal_SIOCDIFADDR(struct ifreq *ifr)
678 #endif
679 {
680     struct netif *netif = NULL;
681 
682     ip_addr_t target_addr;
683     u16_t target_port;
684 
685     SOCKADDR_TO_IPADDR_PORT(&ifr->ifr_addr, &target_addr, target_port);
686 
687 #if LWIP_ENABLE_NET_CAPABILITY
688     if (!IsCapPermit(CAP_NET_ADMIN)) {
689         return EPERM;
690     }
691 #endif
692 
693     /* set netif ipaddr */
694     netif = netif_find(ifr->ifr_name);
695     if (netif == NULL) {
696         return ENODEV;
697     }
698 #if LWIP_HAVE_LOOPIF
699     else if (netif->link_layer_type == LOOPBACK_IF) {
700         return EPERM;
701     }
702 #endif
703 
704     /* check the address is not loopback */
705     if (!IP_IS_V4(&target_addr) || ip_addr_isloopback(&target_addr)) {
706         return EINVAL;
707     }
708 
709 #if LWIP_DHCP
710     if ((netif_dhcp_data(netif) != NULL) &&
711         (netif_dhcp_data(netif)->state != DHCP_STATE_OFF)) {
712         (void)netif_dhcp_off(netif);
713     }
714 #endif
715 
716     ip_addr_set_zero(&netif->gw);
717     ip_addr_set_zero(&netif->ip_addr);
718     ip_addr_set_zero(&netif->netmask);
719 #ifdef LOSCFG_NET_CONTAINER
720     if (netif == group->netif_default) {
721         (void)netif_set_default(NULL, group);
722 #else
723     if (netif == netif_default) {
724         (void)netif_set_default(NULL);
725 #endif
726     }
727 
728 #if LWIP_IPV4 && LWIP_ARP
729     if ((netif->flags & NETIF_FLAG_ETHARP) != 0) {
730         etharp_cleanup_netif(netif);
731     }
732 #endif /* LWIP_IPV4 && LWIP_ARP */
733 
734     return ERR_OK;
735 }
736 
737 static u8_t lwip_ioctl_internal_SIOCGIFNETMASK(struct ifreq *ifr)
738 {
739     struct netif *netif = NULL;
740     struct sockaddr_in *sock_in = NULL;
741 
742     /* get netif netmask */
743     netif = netif_find(ifr->ifr_name);
744     if (netif == NULL) {
745         return ENODEV;
746     } else {
747         sock_in = (struct sockaddr_in *)&ifr->ifr_netmask;
748         sock_in->sin_family = AF_INET;
749         sock_in->sin_addr.s_addr = ip_2_ip4(&netif->netmask)->addr;
750         return 0;
751     }
752 }
753 
754 #ifdef LOSCFG_NET_CONTAINER
755 static u8_t lwip_ioctl_internal_SIOCSIFNETMASK(struct ifreq *ifr, struct net_group *group)
756 #else
757 static u8_t lwip_ioctl_internal_SIOCSIFNETMASK(struct ifreq *ifr)
758 #endif
759 {
760     struct netif *netif = NULL;
761 
762     struct netif *loc_netif = NULL;
763     ip_addr_t taget_addr;
764     u16_t taget_port;
765     SOCKADDR_TO_IPADDR_PORT(&ifr->ifr_addr, &taget_addr, taget_port);
766 
767 #if LWIP_ENABLE_NET_CAPABILITY
768     if (!IsCapPermit(CAP_NET_ADMIN)) {
769         return EPERM;
770     }
771 #endif
772 
773     if (!IP_IS_V4(&taget_addr)) {
774         return EINVAL;
775     }
776 
777     /* set netif netmask */
778     netif = netif_find(ifr->ifr_name);
779     if (netif == NULL) {
780         return ENODEV;
781     }
782 #if LWIP_HAVE_LOOPIF
783     else if (netif->link_layer_type == LOOPBACK_IF) {
784         return EPERM;
785     }
786 #endif
787     else {
788         if (ip_addr_cmp(&netif->netmask, &taget_addr)) {
789             return 0;
790         }
791         /* check data valid */
792 #ifdef LOSCFG_NET_CONTAINER
793         if (ip_addr_netmask_valid(ip_2_ip4(&taget_addr)) == 0) {
794 #else
795         if (ip_addr_netmask_valid(ip_2_ip4(&taget_addr)) != 0) {
796 #endif
797             return EINVAL;
798         }
799 
800         /* lwip disallow two netif sit in same net at the same time */
801 #ifdef LOSCFG_NET_CONTAINER
802         loc_netif = group->netif_list;
803 #else
804         loc_netif = netif_list;
805 #endif
806         while (loc_netif != NULL) {
807             if (loc_netif == netif) {
808                 loc_netif = loc_netif->next;
809                 continue;
810             }
811             if (ip_addr_cmp(&loc_netif->netmask, &taget_addr) &&
812                 ip_addr_netcmp(&loc_netif->ip_addr,
813                                &netif->ip_addr, ip_2_ip4(&loc_netif->netmask))) {
814                 return EINVAL;
815             }
816             loc_netif = loc_netif->next;
817         }
818 
819 #if LWIP_DHCP
820         if ((netif_dhcp_data(netif) != NULL) &&
821             (netif_dhcp_data(netif)->state != DHCP_STATE_OFF)) {
822             (void)netif_dhcp_off(netif);
823         }
824 #endif
825 
826         netif_set_netmask(netif, ip_2_ip4(&taget_addr));
827 
828         /* check if gateway still reachable */
829         if (!ip_addr_netcmp(&netif->gw, &netif->ip_addr, ip_2_ip4(&taget_addr))) {
830             ip_addr_set_zero(&(netif->gw));
831 #ifdef LOSCFG_NET_CONTAINER
832             if (netif == group->netif_default) {
833                 (void)netif_set_default(NULL, group);
834 #else
835             if (netif == netif_default) {
836                 (void)netif_set_default(NULL);
837 #endif
838             }
839         }
840         return 0;
841     }
842 }
843 
844 static u8_t lwip_ioctl_internal_SIOCSIFHWADDR(struct ifreq *ifr)
845 {
846     struct netif *netif = NULL;
847     err_t ret;
848 
849 #if LWIP_ENABLE_NET_CAPABILITY
850     if (!IsCapPermit(CAP_NET_ADMIN)) {
851         return EPERM;
852     }
853 #endif
854 
855     /* set netif hw addr */
856     netif = netif_find(ifr->ifr_name);
857     if (netif == NULL) {
858         return ENODEV;
859     }
860 #if LWIP_HAVE_LOOPIF
861     else if (netif->link_layer_type == LOOPBACK_IF) {
862         return EPERM;
863     }
864 #endif
865     else {
866         /* bring netif down to clear all Neighbor Cache Entry */
867         (void)netif_set_down(netif);
868 
869         ret = netif_set_hwaddr(netif, (const unsigned char *)ifr->ifr_hwaddr.sa_data, netif->hwaddr_len);
870         if (ret != ERR_OK) {
871             (void)netif_set_up(netif);
872             return err_to_errno(ret);
873         }
874 
875         /*
876          * bring netif up to try to send GARP/IGMP/NA/MLD/RS. GARP and NA would
877          * make the neighboring nodes update their Neighbor Cache immediately.
878          */
879         (void)netif_set_up(netif);
880         return 0;
881     }
882 }
883 
884 static u8_t lwip_ioctl_internal_SIOCGIFHWADDR(struct ifreq *ifr)
885 {
886     struct netif *netif = NULL;
887 
888     /* get netif hw addr */
889     netif = netif_find(ifr->ifr_name);
890     if (netif == NULL) {
891         return ENODEV;
892     }
893 #if LWIP_HAVE_LOOPIF
894     else if (netif->link_layer_type == LOOPBACK_IF) {
895         return EPERM;
896     }
897 #endif /* LWIP_HAVE_LOOPIF */
898     else {
899         if (memcpy_s((void *)ifr->ifr_hwaddr.sa_data, sizeof(ifr->ifr_hwaddr.sa_data),
900                      (void *)netif->hwaddr, netif->hwaddr_len) != EOK) {
901             return EINVAL;
902         }
903         return 0;
904     }
905 }
906 
907 static u8_t lwip_ioctl_internal_SIOCSIFFLAGS(struct ifreq *ifr)
908 {
909     struct netif *netif = NULL;
910 
911 #if LWIP_ENABLE_NET_CAPABILITY
912     if (!IsCapPermit(CAP_NET_ADMIN)) {
913         return EPERM;
914     }
915 #endif
916 
917     /* set netif hw addr */
918     netif = netif_find(ifr->ifr_name);
919     if (netif == NULL) {
920         return ENODEV;
921     }
922 #if LWIP_HAVE_LOOPIF
923     else if (netif->link_layer_type == LOOPBACK_IF) {
924         return EPERM;
925     }
926 #endif /* LWIP_HAVE_LOOPIF */
927     else {
928         if (((unsigned short)ifr->ifr_flags & IFF_UP) && !(netif->flags & NETIF_FLAG_UP)) {
929             (void)netif_set_up(netif);
930         } else if (!((unsigned short)ifr->ifr_flags & IFF_UP) && (netif->flags & NETIF_FLAG_UP)) {
931             (void)netif_set_down(netif);
932         }
933         if (((unsigned short)ifr->ifr_flags & IFF_RUNNING) && !(netif->flags & NETIF_FLAG_LINK_UP)) {
934             (void)netif_set_link_up(netif);
935         } else if (!((unsigned short)ifr->ifr_flags & IFF_RUNNING) && (netif->flags & NETIF_FLAG_LINK_UP)) {
936             (void)netif_set_link_down(netif);
937         }
938 
939         if ((unsigned short)ifr->ifr_flags & IFF_BROADCAST) {
940             netif->flags |= NETIF_FLAG_BROADCAST;
941         } else {
942             netif->flags = netif->flags & (~NETIF_FLAG_BROADCAST);
943         }
944         if ((unsigned short)ifr->ifr_flags & IFF_NOARP) {
945             netif->flags = (netif->flags & (~NETIF_FLAG_ETHARP));
946         } else {
947             netif->flags |= NETIF_FLAG_ETHARP;
948         }
949 
950         if ((unsigned short)ifr->ifr_flags & IFF_MULTICAST) {
951 #if LWIP_IGMP
952             netif->flags |= NETIF_FLAG_IGMP;
953 #endif /* LWIP_IGMP */
954 #if LWIP_IPV6 && LWIP_IPV6_MLD
955             netif->flags |= NETIF_FLAG_MLD6;
956 #endif /* LWIP_IPV6_MLD */
957         } else {
958 #if LWIP_IGMP
959             netif->flags = (netif->flags & ~NETIF_FLAG_IGMP);
960 #endif /* LWIP_IGMP */
961 #if LWIP_IPV6 && LWIP_IPV6_MLD
962             netif->flags = (netif->flags & ~NETIF_FLAG_MLD6);
963 #endif /* LWIP_IPV6_MLD */
964         }
965 
966 #if LWIP_DHCP
967         if ((unsigned short)ifr->ifr_flags & IFF_DYNAMIC) {
968             (void)dhcp_start(netif);
969         } else {
970             dhcp_stop(netif);
971 #if !LWIP_DHCP_SUBSTITUTE
972             dhcp_cleanup(netif);
973 #endif
974         }
975 #endif
976 
977 #if LWIP_NETIF_PROMISC
978         if (((unsigned short)ifr->ifr_flags & IFF_PROMISC)) {
979             netif->flags |= NETIF_FLAG_PROMISC;
980         } else {
981             netif->flags &= ~NETIF_FLAG_PROMISC;
982         }
983         if (netif->drv_config) {
984             netif->drv_config(netif, IFF_PROMISC, !!((unsigned short)ifr->ifr_flags & IFF_PROMISC));
985         }
986 #endif /* LWIP_NETIF_PROMISC */
987         return 0;
988     }
989 }
990 
991 static u8_t lwip_ioctl_internal_SIOCGIFFLAGS(struct ifreq *ifr)
992 {
993     struct netif *netif = NULL;
994 
995     /* set netif hw addr */
996     netif = netif_find(ifr->ifr_name);
997     if (netif == NULL) {
998         return ENODEV;
999     } else {
1000         if (netif->flags & NETIF_FLAG_UP) {
1001             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_UP;
1002         } else {
1003             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_UP;
1004         }
1005         if (netif->flags & NETIF_FLAG_LINK_UP) {
1006             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_RUNNING;
1007         } else {
1008             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_RUNNING;
1009         }
1010         if (netif->flags & NETIF_FLAG_BROADCAST) {
1011             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_BROADCAST;
1012         } else {
1013             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_BROADCAST;
1014         }
1015         if (netif->flags & NETIF_FLAG_ETHARP) {
1016             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_NOARP;
1017         } else {
1018             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_NOARP;
1019         }
1020 
1021 #if LWIP_IGMP || LWIP_IPV6_MLD
1022         if (
1023 #if LWIP_IGMP
1024             (netif->flags & NETIF_FLAG_IGMP)
1025 #endif /* LWIP_IGMP */
1026 #if LWIP_IGMP && LWIP_IPV6_MLD
1027             ||
1028 #endif /* LWIP_IGMP && LWIP_IPV6_MLD */
1029 #if LWIP_IPV6_MLD
1030             (netif->flags & NETIF_FLAG_MLD6)
1031 #endif /* LWIP_IPV6_MLD */
1032                 ) {
1033             ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_MULTICAST);
1034         } else {
1035             ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_MULTICAST));
1036         }
1037 #endif /* LWIP_IGMP || LWIP_IPV6_MLD */
1038 
1039 #if LWIP_DHCP
1040         if (dhcp_supplied_address(netif)) {
1041             ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_DYNAMIC);
1042         } else {
1043             ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_DYNAMIC));
1044         }
1045 #endif
1046 
1047 #if LWIP_HAVE_LOOPIF
1048         if (netif->link_layer_type == LOOPBACK_IF) {
1049             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_LOOPBACK;
1050         }
1051 #endif
1052 
1053 #if LWIP_NETIF_PROMISC
1054         if (netif->flags & NETIF_FLAG_PROMISC) {
1055             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_PROMISC;
1056         } else {
1057             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_PROMISC;
1058         }
1059 #endif /* LWIP_NETIF_PROMISC */
1060 
1061         return 0;
1062     }
1063 }
1064 
1065 #ifdef LOSCFG_NET_CONTAINER
1066 static u8_t lwip_ioctl_internal_SIOCGIFNAME(struct ifreq *ifr, struct net_group *group)
1067 #else
1068 static u8_t lwip_ioctl_internal_SIOCGIFNAME(struct ifreq *ifr)
1069 #endif
1070 {
1071     struct netif *netif = NULL;
1072     int ret;
1073 #ifdef LOSCFG_NET_CONTAINER
1074     for (netif = group->netif_list; netif != NULL; netif = netif->next) {
1075 #else
1076     for (netif = netif_list; netif != NULL; netif = netif->next) {
1077 #endif
1078         if (ifr->ifr_ifindex == netif_get_index(netif)) {
1079             break;
1080         }
1081     }
1082 
1083     if (netif == NULL) {
1084         return ENODEV;
1085     } else {
1086         if (netif->link_layer_type == LOOPBACK_IF) {
1087             ret = snprintf_s(ifr->ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%.2s", netif->name);
1088             if ((ret <= 0) || (ret >= IFNAMSIZ)) {
1089                 return ENOBUFS;
1090             }
1091         } else {
1092             ret = snprintf_s(ifr->ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%s", netif_get_name(netif));
1093             if ((ret <= 0) || (ret >= IFNAMSIZ)) {
1094                 return ENOBUFS;
1095             }
1096         }
1097         return 0;
1098     }
1099 }
1100 
1101 static bool lwip_validate_ifname(const char *name, u8_t *let_pos)
1102 {
1103     unsigned short num_pos = 0;
1104     unsigned short letter_pos = 0;
1105     unsigned short pos = 0;
1106     bool have_num = 0;
1107 
1108     /* if the first position of variable name is not letter, such as '6eth2' */
1109     if (((*name >= 'a') && (*name <= 'z')) || ((*name >= 'A') && (*name <= 'Z'))) {
1110         return 0;
1111     }
1112 
1113     /* check if the position of letter is bigger than the the position of digital */
1114     while (*name != '\0') {
1115         if ((*name >= '0') && (*name <= '9')) {
1116             num_pos = pos;
1117             have_num = 1;
1118         } else if (((*name >= 'a') && (*name <= 'z')) || ((*name >= 'A') && (*name <= 'Z'))) {
1119             letter_pos = pos;
1120             if (have_num != 0) {
1121                 return 0;
1122             }
1123         } else {
1124             return 0;
1125         }
1126         pos++;
1127         name++;
1128     }
1129 
1130     /* for the speacil case as all position of variable name is letter, such as 'ethabc' */
1131     if (num_pos == 0) {
1132         return 0;
1133     }
1134 
1135     /* cheak if the digital in the variable name is bigger than 255, such as 'eth266' */
1136     if (atoi(name - (pos - letter_pos - 1)) > 255) {
1137         return 0;
1138     }
1139 
1140     *let_pos = (u8_t)letter_pos;
1141 
1142     return 1;
1143 }
1144 
1145 static u8_t lwip_ioctl_internal_SIOCSIFNAME(struct ifreq *ifr)
1146 {
1147     struct netif *netif = NULL;
1148     u8_t letter_pos = 0;
1149 
1150 #if LWIP_ENABLE_NET_CAPABILITY
1151     if (!IsCapPermit(CAP_NET_ADMIN)) {
1152         return EPERM;
1153     }
1154 #endif
1155 
1156     netif = netif_find(ifr->ifr_name);
1157     if (netif == NULL) {
1158         return ENODEV;
1159     } else if (netif->link_layer_type == LOOPBACK_IF) {
1160         return EPERM;
1161     } else if ((netif->flags & IFF_UP) != 0) {
1162         return EBUSY;
1163     } else {
1164         if (strncmp(ifr->ifr_name, ifr->ifr_newname, IFNAMSIZ) == 0) {
1165             /* not change */
1166             return 0;
1167         }
1168 
1169         ifr->ifr_newname[IFNAMSIZ - 1] = '\0';
1170         if ((lwip_validate_ifname(ifr->ifr_newname, &letter_pos) == 0) || (strlen(ifr->ifr_newname) > (IFNAMSIZ - 1))) {
1171             return EINVAL;
1172         }
1173 
1174         if (strncpy_s(netif->full_name, sizeof(netif->full_name), ifr->ifr_newname, strlen(ifr->ifr_newname)) != EOK) {
1175             return EINVAL;
1176         }
1177     }
1178 
1179     return 0;
1180 }
1181 
1182 static u8_t lwip_ioctl_internal_SIOCGIFINDEX(struct ifreq *ifr)
1183 {
1184     struct netif *netif = NULL;
1185 
1186     netif = netif_find(ifr->ifr_name);
1187     if (netif == NULL) {
1188         return ENODEV;
1189     } else {
1190         ifr->ifr_ifindex = netif_get_index(netif);
1191         return 0;
1192     }
1193 }
1194 
1195 static u8_t lwip_ioctl_internal_SIOCSIFMTU(struct ifreq *ifr)
1196 {
1197     struct netif *netif = NULL;
1198 
1199 #if LWIP_ENABLE_NET_CAPABILITY
1200     if (!IsCapPermit(CAP_NET_ADMIN)) {
1201         return EPERM;
1202     }
1203 #endif
1204 
1205     /* set netif hw addr */
1206     netif = netif_find(ifr->ifr_name);
1207     if (netif == NULL) {
1208         return ENODEV;
1209     }
1210 #if LWIP_HAVE_LOOPIF
1211         /* the mtu of loopif is not used. */
1212     else if (netif->link_layer_type == LOOPBACK_IF) {
1213         return EPERM;
1214     }
1215 #endif
1216     else {
1217         if (ERR_OK != netif_set_mtu(netif, (u16_t)ifr->ifr_mtu)) {
1218             return EINVAL;
1219         }
1220 
1221         return 0;
1222     }
1223 }
1224 
1225 static u8_t lwip_ioctl_internal_SIOCGIFMTU(struct ifreq *ifr)
1226 {
1227     struct netif *netif = NULL;
1228 
1229     /* get netif hw addr */
1230     netif = netif_find(ifr->ifr_name);
1231     if (netif == NULL) {
1232         return ENODEV;
1233     } else {
1234         ifr->ifr_mtu = netif->mtu;
1235         return 0;
1236     }
1237 }
1238 
1239 static u8_t lwip_ioctl_internal_SIOCGIFBRDADDR(struct ifreq *ifr)
1240 {
1241     struct netif *netif = NULL;
1242     struct sockaddr_in *sock_in = NULL;
1243 
1244     /* get netif subnet broadcast addr */
1245     netif = netif_find(ifr->ifr_name);
1246     if (netif == NULL) {
1247         return ENODEV;
1248     }
1249     if (ip4_addr_isany_val(*(ip_2_ip4(&netif->netmask)))) {
1250         return ENXIO;
1251     }
1252     sock_in = (struct sockaddr_in *)&ifr->ifr_addr;
1253     sock_in->sin_family = AF_INET;
1254     sock_in->sin_addr.s_addr = (ip_2_ip4(&((netif)->ip_addr))->addr | ~(ip_2_ip4(&netif->netmask)->addr));
1255     return 0;
1256 }
1257 
1258 #endif /* LWIP_IOCTL_IF */
1259 
1260 #if LWIP_NETIF_ETHTOOL
1261 
1262 static s32_t lwip_ioctl_internal_SIOCETHTOOL(struct ifreq *ifr)
1263 {
1264     struct netif *netif;
1265 
1266 #if LWIP_ENABLE_NET_CAPABILITY
1267     if (!IsCapPermit(CAP_NET_ADMIN)) {
1268         return EPERM;
1269     }
1270 #endif
1271 
1272     netif = netif_find(ifr->ifr_name);
1273     if (netif == NULL) {
1274         return ENODEV;
1275     } else {
1276         return dev_ethtool(netif, ifr);
1277     }
1278 }
1279 
1280 #endif
1281 
1282 #if LWIP_IPV6
1283 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS
1284 
1285 static u8_t lwip_ioctl_internal_SIOCSIPV6DAD(struct ifreq *ifr)
1286 {
1287 #if LWIP_ENABLE_NET_CAPABILITY
1288     if (!IsCapPermit(CAP_NET_ADMIN)) {
1289         return EPERM;
1290     }
1291 #endif
1292 
1293     struct netif *tmpnetif = netif_find(ifr->ifr_name);
1294     if (tmpnetif == NULL) {
1295         LWIP_DEBUGF(SOCKETS_DEBUG, ("Interface not found.\n"));
1296         return ENODEV;
1297     }
1298 
1299     if ((ifr->ifr_ifru.ifru_ivalue != 0) && (ifr->ifr_ifru.ifru_ivalue != 1)) {
1300         LWIP_DEBUGF(SOCKETS_DEBUG, ("Invalid ioctl argument(ifru_ivalue 0/1).\n"));
1301         return EBADRQC;
1302     }
1303 
1304     if (ifr->ifr_ifru.ifru_ivalue == 1) {
1305         tmpnetif->ipv6_flags = (tmpnetif->ipv6_flags | LWIP_IPV6_ND6_FLAG_DAD);
1306 
1307         LWIP_DEBUGF(SOCKETS_DEBUG, ("DAD turned on through ioctl for  %s iface index %u \n",
1308                 tmpnetif->name, tmpnetif->num));
1309     } else {
1310         tmpnetif->ipv6_flags = (tmpnetif->ipv6_flags & ((~LWIP_IPV6_ND6_FLAG_DAD) & 0xffU));
1311 
1312         LWIP_DEBUGF(SOCKETS_DEBUG, ("DAD turned off through ioctl for  %s iface index %u \n",
1313                 tmpnetif->name, tmpnetif->num));
1314     }
1315     return 0;
1316 }
1317 
1318 static u8_t lwip_ioctl_internal_SIOCGIPV6DAD(struct ifreq *ifr)
1319 {
1320     struct netif *tmpnetif = netif_find(ifr->ifr_name);
1321     if (tmpnetif == NULL) {
1322         LWIP_DEBUGF(SOCKETS_DEBUG, ("Interface not found.\n"));
1323         return ENODEV;
1324     }
1325     ifr->ifr_ifru.ifru_ivalue = (tmpnetif->ipv6_flags & LWIP_IPV6_ND6_FLAG_DAD) ? 1 : 0;
1326     return 0;
1327 }
1328 
1329 #endif
1330 
1331 #if LWIP_IOCTL_IPV6DPCTD
1332 
1333 static u8_t lwip_ioctl_internal_SIOCSIPV6DPCTD(struct ifreq *ifr)
1334 {
1335 #if LWIP_ENABLE_NET_CAPABILITY
1336     if (!IsCapPermit(CAP_NET_ADMIN)) {
1337         return EPERM;
1338     }
1339 #endif
1340 
1341     struct netif *tmpnetif = netif_find(ifr->ifr_name);
1342     if (tmpnetif == NULL) {
1343         LWIP_DEBUGF(SOCKETS_DEBUG, ("Interface not found.\n"));
1344         return ENODEV;
1345     }
1346     if ((ifr->ifr_ifru.ifru_ivalue != 0) && (ifr->ifr_ifru.ifru_ivalue != 1)) {
1347         LWIP_DEBUGF(SOCKETS_DEBUG, ("Invalid ioctl argument(ifru_ivalue 0/1).\n"));
1348         return EBADRQC;
1349     }
1350     if (ifr->ifr_ifru.ifru_ivalue == 1) {
1351         tmpnetif->ipv6_flags = (tmpnetif->ipv6_flags | LWIP_IPV6_ND6_FLAG_DEPRECATED);
1352         LWIP_DEBUGF(SOCKETS_DEBUG, ("Deprecation turned on through ioctl for  %s iface index %u \n",
1353                 tmpnetif->name, tmpnetif->num));
1354     } else {
1355         tmpnetif->ipv6_flags = (tmpnetif->ipv6_flags & ((~LWIP_IPV6_ND6_FLAG_DEPRECATED) & 0xffU));
1356         LWIP_DEBUGF(SOCKETS_DEBUG, ("Deprecation turned off through ioctl for  %s iface index %u \n",
1357                 tmpnetif->name, tmpnetif->num));
1358     }
1359     return 0;
1360 }
1361 
1362 static u8_t lwip_ioctl_internal_SIOCGIPV6DPCTD(struct ifreq *ifr)
1363 {
1364     struct netif *tmpnetif = netif_find(ifr->ifr_name);
1365     if (tmpnetif == NULL) {
1366         LWIP_DEBUGF(SOCKETS_DEBUG, ("Interface not found.\n"));
1367         return ENODEV;
1368     }
1369 
1370     ifr->ifr_ifru.ifru_ivalue = (tmpnetif->ipv6_flags & LWIP_IPV6_ND6_FLAG_DEPRECATED) ? 1 : 0;
1371     return 0;
1372 }
1373 
1374 #endif /* LWIP_IOCTL_IPV6DPCTD */
1375 #endif
1376 
1377 static u8_t lwip_ioctl_impl(const struct lwip_sock *sock, long cmd, void *argp)
1378 {
1379     u8_t err = 0;
1380 #if LWIP_NETIF_ETHTOOL
1381     s32_t ret;
1382 #endif
1383 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS || LWIP_IOCTL_IPV6DPCTD || LWIP_IOCTL_IF || LWIP_NETIF_ETHTOOL
1384     struct ifreq *ifr = (struct ifreq *)argp;
1385 #endif
1386 #if LWIP_IOCTL_ROUTE
1387     struct rtentry *rmten = (struct rtentry *)argp;
1388 #endif
1389 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS || LWIP_IOCTL_IPV6DPCTD || LWIP_IOCTL_ROUTE || LWIP_IOCTL_IF
1390     bool is_ipv6 = 0;
1391 
1392     /* allow it only on IPv6 sockets... */
1393     is_ipv6 = NETCONNTYPE_ISIPV6((unsigned int)(sock->conn->type));
1394 #endif
1395 #ifdef LOSCFG_NET_CONTAINER
1396     struct net_group *group = get_net_group_from_ippcb(sock->conn->pcb.ip);
1397 #endif
1398     switch ((u32_t)cmd) {
1399 #if LWIP_IPV6
1400 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS
1401         case SIOCSIPV6DAD:
1402             /* allow it only on IPv6 sockets... */
1403             if (is_ipv6 == 0) {
1404                 err = EINVAL;
1405             } else {
1406                 err = lwip_ioctl_internal_SIOCSIPV6DAD(ifr);
1407             }
1408             break;
1409         case SIOCGIPV6DAD:
1410             /* allow it only on IPv6 sockets... */
1411             if (is_ipv6 == 0) {
1412                 err = EINVAL;
1413             } else {
1414                 err = lwip_ioctl_internal_SIOCGIPV6DAD(ifr);
1415             }
1416             break;
1417 #endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */
1418 #if LWIP_IOCTL_IPV6DPCTD
1419         case SIOCSIPV6DPCTD:
1420             /* allow it only on IPv6 sockets... */
1421             if (is_ipv6 == 0) {
1422                 err = EINVAL;
1423             } else {
1424                 err = lwip_ioctl_internal_SIOCSIPV6DPCTD(ifr);
1425             }
1426             break;
1427         case SIOCGIPV6DPCTD:
1428             /* allow it only on IPv6 sockets... */
1429             if (is_ipv6 == 0) {
1430                 err = EINVAL;
1431             } else {
1432                 err = lwip_ioctl_internal_SIOCGIPV6DPCTD(ifr);
1433             }
1434             break;
1435 #endif
1436 #endif /* LWIP_IPV6 */
1437 #if LWIP_IOCTL_ROUTE
1438         case SIOCADDRT:
1439             /* Do not allow if socket is AF_INET6 */
1440             if (is_ipv6 != 0) {
1441                 err = EINVAL;
1442             } else {
1443 #ifdef LOSCFG_NET_CONTAINER
1444                 err = lwip_ioctl_internal_SIOCADDRT(rmten, group);
1445 #else
1446                 err = lwip_ioctl_internal_SIOCADDRT(rmten);
1447 #endif
1448             }
1449             break;
1450 #endif
1451 #if LWIP_IOCTL_IF
1452         case SIOCGIFCONF:
1453             /* Do not allow if socket is AF_INET6 */
1454             if (is_ipv6 != 0) {
1455                 err = EINVAL;
1456             } else {
1457 #ifdef LOSCFG_NET_CONTAINER
1458                 err = lwip_ioctl_internal_SIOCGIFCONF(ifr, group);
1459 #else
1460                 err = lwip_ioctl_internal_SIOCGIFCONF(ifr);
1461 #endif
1462             }
1463             break;
1464         case SIOCGIFADDR:
1465             if (is_ipv6 != 0) {
1466                 err = EINVAL;
1467             } else {
1468                 err = lwip_ioctl_internal_SIOCGIFADDR(ifr);
1469             }
1470             break;
1471         case SIOCSIFADDR:
1472             if (is_ipv6 != 0) {
1473                 err = lwip_ioctl_internal_SIOCSIFADDR_6(ifr);
1474             } else {
1475 #ifdef LOSCFG_NET_CONTAINER
1476                 err = lwip_ioctl_internal_SIOCSIFADDR(ifr, group);
1477 #else
1478                 err = lwip_ioctl_internal_SIOCSIFADDR(ifr);
1479 #endif
1480             }
1481             break;
1482         case SIOCDIFADDR:
1483             /* Delete interface address */
1484             if (is_ipv6 != 0) {
1485                 err = lwip_ioctl_internal_SIOCDIFADDR_6(ifr);
1486             } else {
1487 #ifdef LOSCFG_NET_CONTAINER
1488                 err = lwip_ioctl_internal_SIOCDIFADDR(ifr, group);
1489 #else
1490                 err = lwip_ioctl_internal_SIOCDIFADDR(ifr);
1491 #endif
1492             }
1493             break;
1494         case SIOCGIFNETMASK:
1495             if (is_ipv6 != 0) {
1496                 err = EINVAL;
1497             } else {
1498                 err = lwip_ioctl_internal_SIOCGIFNETMASK(ifr);
1499             }
1500             break;
1501         case SIOCSIFNETMASK:
1502             if (is_ipv6 != 0) {
1503                 err = EINVAL;
1504             } else {
1505 #ifdef LOSCFG_NET_CONTAINER
1506                 err = lwip_ioctl_internal_SIOCSIFNETMASK(ifr, group);
1507 #else
1508                 err = lwip_ioctl_internal_SIOCSIFNETMASK(ifr);
1509 #endif
1510             }
1511             break;
1512         case SIOCSIFHWADDR:
1513             err = lwip_ioctl_internal_SIOCSIFHWADDR(ifr);
1514             break;
1515         case SIOCGIFHWADDR:
1516             err = lwip_ioctl_internal_SIOCGIFHWADDR(ifr);
1517             break;
1518         case SIOCSIFFLAGS:
1519             err = lwip_ioctl_internal_SIOCSIFFLAGS(ifr);
1520             break;
1521         case SIOCGIFFLAGS:
1522             err = lwip_ioctl_internal_SIOCGIFFLAGS(ifr);
1523             break;
1524         case SIOCGIFNAME:
1525 #ifdef LOSCFG_NET_CONTAINER
1526             err = lwip_ioctl_internal_SIOCGIFNAME(ifr, group);
1527 #else
1528             err = lwip_ioctl_internal_SIOCGIFNAME(ifr);
1529 #endif
1530             break;
1531         case SIOCSIFNAME:
1532             err = lwip_ioctl_internal_SIOCSIFNAME(ifr);
1533             break;
1534             /* Need to support the get index through ioctl
1535              * As of now the options is restricted to PF_PACKET scenario , so removed the compiler flag Begin
1536              */
1537         case SIOCGIFINDEX:
1538             err = lwip_ioctl_internal_SIOCGIFINDEX(ifr);
1539             break;
1540         case SIOCGIFMTU:
1541             err = lwip_ioctl_internal_SIOCGIFMTU(ifr);
1542             break;
1543         case SIOCSIFMTU:
1544             err = lwip_ioctl_internal_SIOCSIFMTU(ifr);
1545             break;
1546         case SIOCGIFBRDADDR:
1547             if (is_ipv6 != 0) {
1548                 err = EINVAL;
1549             } else {
1550                 err = lwip_ioctl_internal_SIOCGIFBRDADDR(ifr);
1551             }
1552             break;
1553 #endif /* LWIP_IOCTL_IF */
1554 #if LWIP_NETIF_ETHTOOL
1555         case SIOCETHTOOL:
1556             ret = lwip_ioctl_internal_SIOCETHTOOL(ifr);
1557             if (ret != 0) {
1558                 /* an IO error happened */
1559                 err = EIO;
1560             }
1561             break;
1562 #endif
1563             /* START For cmd = -1 stack has to treat it as Invalid Input and return EINVAL */
1564         case 0xFFFFFFFF:
1565             err = EINVAL;
1566             LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl_impl(INVALID: 0x%lx)\n", cmd));
1567             break;
1568         default:
1569             err = ENOSYS;
1570             LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(UNIMPL: 0x%lx)\n", cmd));
1571             break;
1572     }
1573 
1574     return err;
1575 }
1576 
1577 static err_t lwip_do_ioctl_impl(struct tcpip_api_call_data *call)
1578 {
1579     struct lwip_ioctl_apimsg *msg = (struct lwip_ioctl_apimsg *)(void *)call;
1580     return lwip_ioctl_impl(msg->sock, msg->cmd, msg->argp);
1581 }
1582 
1583 #include "los_vm_map.h"
1584 #include "user_copy.h"
1585 static int do_ioctl_SIOCGIFCONF(int sockfd, long cmd, void *argp)
1586 {
1587     int nbytes;
1588     struct ifconf ifc;
1589     char *buf_bak = NULL;
1590     int ret;
1591 
1592     if (LOS_ArchCopyFromUser(&ifc, argp, sizeof(struct ifconf)) != 0) {
1593         set_errno(EFAULT);
1594         return -1;
1595     }
1596     nbytes = ifc.ifc_len;
1597     if (nbytes <= 0) {
1598         set_errno(EINVAL);
1599         return -1;
1600     }
1601     buf_bak = ifc.ifc_buf;
1602     if (!LOS_IsUserAddress((VADDR_T)(uintptr_t)buf_bak)) {
1603         set_errno(EFAULT);
1604         return -1;
1605     }
1606     ifc.ifc_buf = malloc(nbytes);
1607     if (ifc.ifc_buf == NULL) {
1608         set_errno(ENOMEM);
1609         return -1;
1610     }
1611     (void)memset_s(ifc.ifc_buf, nbytes, 0, nbytes);
1612 
1613     ret = lwip_ioctl(sockfd, cmd, &ifc);
1614     if (ret == 0) {
1615         if (LOS_ArchCopyToUser(buf_bak, ifc.ifc_buf, nbytes) != 0) {
1616             set_errno(EFAULT);
1617             ret = -1;
1618         }
1619     }
1620 
1621     free(ifc.ifc_buf);
1622     ifc.ifc_buf = buf_bak;
1623     if (LOS_ArchCopyToUser(argp, &ifc, sizeof(struct ifconf)) != 0) {
1624         set_errno(EFAULT);
1625         ret = -1;
1626     }
1627     return ret;
1628 }
1629 
1630 int socks_ioctl(int sockfd, long cmd, void *argp)
1631 {
1632     void *argpbak = argp;
1633     int ret;
1634     size_t nbytes = 0;
1635 
1636     if (LOS_IsUserAddress((VADDR_T)(uintptr_t)argp)) {
1637         switch (cmd) {
1638             case FIONREAD:
1639             case FIONBIO:
1640                 nbytes = sizeof(int);
1641                 break;
1642             case SIOCADDRT:
1643                 nbytes = sizeof(struct rtentry);
1644                 break;
1645             case SIOCGIFCONF:
1646                 return do_ioctl_SIOCGIFCONF(sockfd, cmd, argp);
1647             case SIOCSIPV6DAD:
1648             case SIOCGIPV6DAD:
1649             case SIOCSIPV6DPCTD:
1650             case SIOCGIPV6DPCTD:
1651             case SIOCGIFADDR:
1652             case SIOCSIFADDR:
1653             case SIOCDIFADDR:
1654             case SIOCGIFNETMASK:
1655             case SIOCSIFNETMASK:
1656             case SIOCSIFHWADDR:
1657             case SIOCGIFHWADDR:
1658             case SIOCSIFFLAGS:
1659             case SIOCGIFFLAGS:
1660             case SIOCGIFNAME:
1661             case SIOCSIFNAME:
1662             case SIOCGIFINDEX:
1663             case SIOCGIFMTU:
1664             case SIOCSIFMTU:
1665             case SIOCETHTOOL:
1666             case SIOCGIFBRDADDR:
1667                 nbytes = sizeof(struct ifreq);
1668                 break;
1669             default:
1670                 nbytes = 0;
1671         }
1672         if (argp != NULL && nbytes > 0) {
1673             argp = malloc(nbytes);
1674             if (argp == NULL) {
1675                 set_errno(ENOMEM);
1676                 return -1;
1677             }
1678             if (LOS_ArchCopyFromUser(argp, argpbak, nbytes) != 0) {
1679                 free(argp);
1680                 set_errno(EFAULT);
1681                 return -1;
1682             }
1683         }
1684     }
1685     ret = lwip_ioctl(sockfd, cmd, argp);
1686     if (ret == 0 && argp != argpbak) {
1687         if (LOS_ArchCopyToUser(argpbak, argp, nbytes) != 0) {
1688             /* how to rollback ioctl ? */
1689             set_errno(EFAULT);
1690             ret = -1;
1691         }
1692     }
1693     if (argp != argpbak) {
1694         free(argp);
1695     }
1696     return ret;
1697 }
1698 
1699 void socks_refer(int sockfd)
1700 {
1701     struct lwip_sock *sock = NULL;
1702     SYS_ARCH_DECL_PROTECT(lev);
1703 
1704     sock = get_socket(sockfd);
1705     if (!sock) {
1706         return;
1707     }
1708 
1709     SYS_ARCH_PROTECT(lev);
1710 
1711     sock->s_refcount++;
1712 
1713     SYS_ARCH_UNPROTECT(lev);
1714 
1715     done_socket(sock);
1716 }
1717 
1718 int socks_close(int sockfd)
1719 {
1720     struct lwip_sock *sock = NULL;
1721     SYS_ARCH_DECL_PROTECT(lev);
1722 
1723     sock = get_socket(sockfd);
1724     if (!sock) {
1725         return -1;
1726     }
1727 
1728     SYS_ARCH_PROTECT(lev);
1729 
1730     if (sock->s_refcount == 0) {
1731         SYS_ARCH_UNPROTECT(lev);
1732         done_socket(sock);
1733         return lwip_close(sockfd);
1734     }
1735 
1736     sock->s_refcount--;
1737 
1738     SYS_ARCH_UNPROTECT(lev);
1739     done_socket(sock);
1740     return 0;
1741 }
1742