• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 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 
lwip_ioctl_internal_SIOCADDRT(struct rtentry * rmten)407 static u8_t lwip_ioctl_internal_SIOCADDRT(struct rtentry *rmten)
408 {
409     struct netif *netif = NULL;
410     ip_addr_t rtgw_addr;
411     u16_t rtgw_port;
412 
413 #if LWIP_ENABLE_NET_CAPABILITY
414     if (!IsCapPermit(CAP_NET_ADMIN)) {
415         return EPERM;
416     }
417 #endif
418 
419     SOCKADDR_TO_IPADDR_PORT(&rmten->rt_gateway, &rtgw_addr, rtgw_port);
420 
421     if (!IP_IS_V4_VAL(rtgw_addr)) {
422         return EINVAL;
423     }
424 
425     /* check if multicast/0/loopback */
426     if (ip_addr_ismulticast(&rtgw_addr) || ip_addr_isany(&rtgw_addr) ||
427         ip_addr_isloopback(&rtgw_addr)) {
428         return EINVAL;
429     }
430 
431     /* check if reachable */
432     for (netif = netif_list; netif != NULL; netif = netif->next) {
433         if (ip_addr_netcmp(&rtgw_addr, &netif->ip_addr, ip_2_ip4(&netif->netmask))) {
434             break;
435         }
436     }
437 
438     if (netif == NULL) {
439         return EHOSTUNREACH;
440     }
441 
442     /* check if broadcast */
443     if (ip_addr_isbroadcast(&rtgw_addr, netif) != 0) {
444         return EINVAL;
445     }
446 
447     /* Check flags */
448     if ((rmten->rt_flags & RTF_GATEWAY) == 0) {
449         return EINVAL;
450     }
451 
452     /* Add validation */
453     if ((netif_default != NULL) && (netif_default != netif)) {
454         ip_addr_set_zero(&netif_default->gw);
455         (void)netif_set_default(netif);
456     }
457     netif_set_gw(netif, ip_2_ip4(&rtgw_addr));
458 
459     return 0;
460 }
461 
462 #endif
463 
464 #if LWIP_IOCTL_IF
465 
lwip_ioctl_internal_SIOCGIFCONF(struct ifreq * ifr)466 static u8_t lwip_ioctl_internal_SIOCGIFCONF(struct ifreq *ifr)
467 {
468     struct ifconf *ifc = NULL;
469     struct netif *netif = NULL;
470     struct ifreq ifreq;
471     struct sockaddr_in *sock_in = NULL;
472     int pos;
473     int len;
474     int ret;
475 
476     /* Format the caller's buffer. */
477     ifc = (struct ifconf *)ifr;
478     len = ifc->ifc_len;
479 
480     /* Loop over the interfaces, and write an info block for each. */
481     pos = 0;
482     for (netif = netif_list; netif != NULL; netif = netif->next) {
483         if (ifc->ifc_buf == NULL) {
484             pos = (pos + (int)sizeof(struct ifreq));
485             continue;
486         }
487 
488         if (len < (int)sizeof(ifreq)) {
489             break;
490         }
491         (void)memset_s(&ifreq, sizeof(struct ifreq), 0, sizeof(struct ifreq));
492         if (netif->link_layer_type == LOOPBACK_IF) {
493             ret = snprintf_s(ifreq.ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%.2s", netif->name);
494             if ((ret <= 0) || (ret >= IFNAMSIZ)) {
495                 LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed."));
496                 return ENOBUFS;
497             }
498         } else {
499             ret = snprintf_s(ifreq.ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%s", netif_get_name(netif));
500             if ((ret <= 0) || (ret >= IFNAMSIZ)) {
501                 LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed."));
502                 return ENOBUFS;
503             }
504         }
505 
506         sock_in = (struct sockaddr_in *)&ifreq.ifr_addr;
507         sock_in->sin_family = AF_INET;
508         sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr;
509         if (memcpy_s(ifc->ifc_buf + pos, sizeof(struct ifreq), &ifreq, sizeof(struct ifreq)) != EOK) {
510             return ENOBUFS;
511         }
512         pos = pos + (int)sizeof(struct ifreq);
513         len = len - (int)sizeof(struct ifreq);
514     }
515 
516     ifc->ifc_len = pos;
517 
518     return 0;
519 }
520 
lwip_ioctl_internal_SIOCGIFADDR(struct ifreq * ifr)521 static u8_t lwip_ioctl_internal_SIOCGIFADDR(struct ifreq *ifr)
522 {
523     struct netif *netif = NULL;
524     struct sockaddr_in *sock_in = NULL;
525 
526     /* get netif ipaddr */
527     netif = netif_find(ifr->ifr_name);
528     if (netif == NULL) {
529         return ENODEV;
530     } else {
531         sock_in = (struct sockaddr_in *)&ifr->ifr_addr;
532         sock_in->sin_family = AF_INET;
533         sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr;
534         return 0;
535     }
536 }
537 
538 #ifndef LWIP_IPV6_PREFIX_LEN
539 #define LWIP_IPV6_PREFIX_LEN 64
540 #endif
541 
542 #ifndef LWIP_NETIF_IFINDEX_MAX_EX
543 #define LWIP_NETIF_IFINDEX_MAX_EX 255
544 #endif
545 
546 #include "lwip/dhcp.h"
547 #include "lwip/dhcp6.h"
548 #include "lwip/prot/dhcp.h"
549 #include "lwip/prot/dhcp6.h"
550 
lwip_ioctl_internal_SIOCSIFADDR_6(struct ifreq * ifr)551 static u8_t lwip_ioctl_internal_SIOCSIFADDR_6(struct ifreq *ifr)
552 {
553     (void)ifr;
554     return ENOSYS;
555 }
556 
lwip_ioctl_internal_SIOCSIFADDR(struct ifreq * ifr)557 static u8_t lwip_ioctl_internal_SIOCSIFADDR(struct ifreq *ifr)
558 {
559     struct netif *netif = NULL;
560 
561     struct netif *loc_netif = NULL;
562     ip_addr_t taget_addr;
563     u16_t taget_port;
564     SOCKADDR_TO_IPADDR_PORT(&ifr->ifr_addr, &taget_addr, taget_port);
565 
566 #if LWIP_ENABLE_NET_CAPABILITY
567     if (!IsCapPermit(CAP_NET_ADMIN)) {
568         return EPERM;
569     }
570 #endif
571 
572     /* set netif ipaddr */
573     netif = netif_find(ifr->ifr_name);
574     if (netif == NULL) {
575         return ENODEV;
576     }
577 #if LWIP_HAVE_LOOPIF
578     else if (netif->link_layer_type == LOOPBACK_IF) {
579         return EPERM;
580     }
581 #endif
582     else {
583         /* check the address is not multicast/broadcast/0/loopback */
584         if (!IP_IS_V4(&taget_addr) || ip_addr_ismulticast(&taget_addr) ||
585             ip_addr_isbroadcast(&taget_addr, netif) ||
586             ip_addr_isany(&taget_addr) ||
587             ip_addr_isloopback(&taget_addr)) {
588             return EINVAL;
589         }
590 
591         /* reset gateway if new and previous ipaddr not in same net */
592         if (ip_addr_netcmp(&taget_addr, &netif->ip_addr, ip_2_ip4(&netif->netmask)) == 0) {
593             ip_addr_set_zero(&netif->gw);
594             if (netif == netif_default) {
595                 (void)netif_set_default(NULL);
596             }
597         }
598 
599         /* lwip disallow two netif sit in same net at the same time */
600         loc_netif = netif_list;
601         while (loc_netif != NULL) {
602             if (loc_netif == netif) {
603                 loc_netif = loc_netif->next;
604                 continue;
605             }
606             if (ip_addr_cmp(&netif->netmask, &loc_netif->netmask) &&
607                 ip_addr_netcmp(&loc_netif->ip_addr, &taget_addr,
608                                ip_2_ip4(&netif->netmask))) {
609                 return EINVAL;
610             }
611             loc_netif = loc_netif->next;
612         }
613 
614 #if LWIP_DHCP
615         if ((netif_dhcp_data(netif) != NULL) &&
616             (netif_dhcp_data(netif)->state != DHCP_STATE_OFF)) {
617             (void)netif_dhcp_off(netif);
618         }
619 #endif
620 
621 #if LWIP_ARP
622         /* clear ARP cache when IP address changed */
623         if ((netif->flags & NETIF_FLAG_ETHARP) != 0) {
624             etharp_cleanup_netif(netif);
625         }
626 #endif /* LWIP_ARP */
627 
628         netif_set_ipaddr(netif, ip_2_ip4(&taget_addr));
629 
630         return 0;
631     }
632 }
633 
lwip_ioctl_internal_SIOCDIFADDR_6(struct ifreq * ifr)634 static u8_t lwip_ioctl_internal_SIOCDIFADDR_6(struct ifreq *ifr)
635 {
636     (void)ifr;
637     return ENOSYS;
638 }
639 
lwip_ioctl_internal_SIOCDIFADDR(struct ifreq * ifr)640 static u8_t lwip_ioctl_internal_SIOCDIFADDR(struct ifreq *ifr)
641 {
642     struct netif *netif = NULL;
643 
644     ip_addr_t target_addr;
645     u16_t target_port;
646 
647     SOCKADDR_TO_IPADDR_PORT(&ifr->ifr_addr, &target_addr, target_port);
648 
649 #if LWIP_ENABLE_NET_CAPABILITY
650     if (!IsCapPermit(CAP_NET_ADMIN)) {
651         return EPERM;
652     }
653 #endif
654 
655     /* set netif ipaddr */
656     netif = netif_find(ifr->ifr_name);
657     if (netif == NULL) {
658         return ENODEV;
659     }
660 #if LWIP_HAVE_LOOPIF
661     else if (netif->link_layer_type == LOOPBACK_IF) {
662         return EPERM;
663     }
664 #endif
665 
666     /* check the address is not loopback */
667     if (!IP_IS_V4(&target_addr) || ip_addr_isloopback(&target_addr)) {
668         return EINVAL;
669     }
670 
671 #if LWIP_DHCP
672     if ((netif_dhcp_data(netif) != NULL) &&
673         (netif_dhcp_data(netif)->state != DHCP_STATE_OFF)) {
674         (void)netif_dhcp_off(netif);
675     }
676 #endif
677 
678     ip_addr_set_zero(&netif->gw);
679     ip_addr_set_zero(&netif->ip_addr);
680     ip_addr_set_zero(&netif->netmask);
681     if (netif == netif_default) {
682         (void)netif_set_default(NULL);
683     }
684 
685 #if LWIP_IPV4 && LWIP_ARP
686     if ((netif->flags & NETIF_FLAG_ETHARP) != 0) {
687         etharp_cleanup_netif(netif);
688     }
689 #endif /* LWIP_IPV4 && LWIP_ARP */
690 
691     return ERR_OK;
692 }
693 
lwip_ioctl_internal_SIOCGIFNETMASK(struct ifreq * ifr)694 static u8_t lwip_ioctl_internal_SIOCGIFNETMASK(struct ifreq *ifr)
695 {
696     struct netif *netif = NULL;
697     struct sockaddr_in *sock_in = NULL;
698 
699     /* get netif netmask */
700     netif = netif_find(ifr->ifr_name);
701     if (netif == NULL) {
702         return ENODEV;
703     } else {
704         sock_in = (struct sockaddr_in *)&ifr->ifr_netmask;
705         sock_in->sin_family = AF_INET;
706         sock_in->sin_addr.s_addr = ip_2_ip4(&netif->netmask)->addr;
707         return 0;
708     }
709 }
710 
lwip_ioctl_internal_SIOCSIFNETMASK(struct ifreq * ifr)711 static u8_t lwip_ioctl_internal_SIOCSIFNETMASK(struct ifreq *ifr)
712 {
713     struct netif *netif = NULL;
714 
715     struct netif *loc_netif = NULL;
716     ip_addr_t taget_addr;
717     u16_t taget_port;
718     SOCKADDR_TO_IPADDR_PORT(&ifr->ifr_addr, &taget_addr, taget_port);
719 
720 #if LWIP_ENABLE_NET_CAPABILITY
721     if (!IsCapPermit(CAP_NET_ADMIN)) {
722         return EPERM;
723     }
724 #endif
725 
726     if (!IP_IS_V4(&taget_addr)) {
727         return EINVAL;
728     }
729 
730     /* set netif netmask */
731     netif = netif_find(ifr->ifr_name);
732     if (netif == NULL) {
733         return ENODEV;
734     }
735 #if LWIP_HAVE_LOOPIF
736     else if (netif->link_layer_type == LOOPBACK_IF) {
737         return EPERM;
738     }
739 #endif
740     else {
741         if (ip_addr_cmp(&netif->netmask, &taget_addr)) {
742             return 0;
743         }
744         /* check data valid */
745         if (ip_addr_netmask_valid(ip_2_ip4(&taget_addr)) != 0) {
746             return EINVAL;
747         }
748 
749         /* lwip disallow two netif sit in same net at the same time */
750         loc_netif = netif_list;
751         while (loc_netif != NULL) {
752             if (loc_netif == netif) {
753                 loc_netif = loc_netif->next;
754                 continue;
755             }
756             if (ip_addr_cmp(&loc_netif->netmask, &taget_addr) &&
757                 ip_addr_netcmp(&loc_netif->ip_addr,
758                                &netif->ip_addr, ip_2_ip4(&loc_netif->netmask))) {
759                 return EINVAL;
760             }
761             loc_netif = loc_netif->next;
762         }
763 
764 #if LWIP_DHCP
765         if ((netif_dhcp_data(netif) != NULL) &&
766             (netif_dhcp_data(netif)->state != DHCP_STATE_OFF)) {
767             (void)netif_dhcp_off(netif);
768         }
769 #endif
770 
771         netif_set_netmask(netif, ip_2_ip4(&taget_addr));
772 
773         /* check if gateway still reachable */
774         if (!ip_addr_netcmp(&netif->gw, &netif->ip_addr, ip_2_ip4(&taget_addr))) {
775             ip_addr_set_zero(&(netif->gw));
776             if (netif == netif_default) {
777                 (void)netif_set_default(NULL);
778             }
779         }
780         return 0;
781     }
782 }
783 
lwip_ioctl_internal_SIOCSIFHWADDR(struct ifreq * ifr)784 static u8_t lwip_ioctl_internal_SIOCSIFHWADDR(struct ifreq *ifr)
785 {
786     struct netif *netif = NULL;
787     err_t ret;
788 
789 #if LWIP_ENABLE_NET_CAPABILITY
790     if (!IsCapPermit(CAP_NET_ADMIN)) {
791         return EPERM;
792     }
793 #endif
794 
795     /* set netif hw addr */
796     netif = netif_find(ifr->ifr_name);
797     if (netif == NULL) {
798         return ENODEV;
799     }
800 #if LWIP_HAVE_LOOPIF
801     else if (netif->link_layer_type == LOOPBACK_IF) {
802         return EPERM;
803     }
804 #endif
805     else {
806 
807         /* bring netif down to clear all Neighbor Cache Entry */
808         (void)netif_set_down(netif);
809 
810         ret = netif_set_hwaddr(netif, (const unsigned char *)ifr->ifr_hwaddr.sa_data, netif->hwaddr_len);
811 
812         if (ret != ERR_OK) {
813             (void)netif_set_up(netif);
814             return err_to_errno(ret);
815         }
816 
817         /*
818          * bring netif up to try to send GARP/IGMP/NA/MLD/RS. GARP and NA would
819          * make the neighboring nodes update their Neighbor Cache immediately.
820          */
821         (void)netif_set_up(netif);
822         return 0;
823     }
824 }
825 
lwip_ioctl_internal_SIOCGIFHWADDR(struct ifreq * ifr)826 static u8_t lwip_ioctl_internal_SIOCGIFHWADDR(struct ifreq *ifr)
827 {
828     struct netif *netif = NULL;
829 
830     /* get netif hw addr */
831     netif = netif_find(ifr->ifr_name);
832     if (netif == NULL) {
833         return ENODEV;
834     }
835 #if LWIP_HAVE_LOOPIF
836     else if (netif->link_layer_type == LOOPBACK_IF) {
837         return EPERM;
838     }
839 #endif /* LWIP_HAVE_LOOPIF */
840     else {
841         if (memcpy_s((void *)ifr->ifr_hwaddr.sa_data, sizeof(ifr->ifr_hwaddr.sa_data),
842                      (void *)netif->hwaddr, netif->hwaddr_len) != EOK) {
843             return EINVAL;
844         }
845         return 0;
846     }
847 }
848 
lwip_ioctl_internal_SIOCSIFFLAGS(struct ifreq * ifr)849 static u8_t lwip_ioctl_internal_SIOCSIFFLAGS(struct ifreq *ifr)
850 {
851     struct netif *netif = NULL;
852 
853 #if LWIP_ENABLE_NET_CAPABILITY
854     if (!IsCapPermit(CAP_NET_ADMIN)) {
855         return EPERM;
856     }
857 #endif
858 
859     /* set netif hw addr */
860     netif = netif_find(ifr->ifr_name);
861     if (netif == NULL) {
862         return ENODEV;
863     }
864 #if LWIP_HAVE_LOOPIF
865     else if (netif->link_layer_type == LOOPBACK_IF) {
866         return EPERM;
867     }
868 #endif /* LWIP_HAVE_LOOPIF */
869     else {
870         if (((unsigned short)ifr->ifr_flags & IFF_UP) && !(netif->flags & NETIF_FLAG_UP)) {
871             (void)netif_set_up(netif);
872         } else if (!((unsigned short)ifr->ifr_flags & IFF_UP) && (netif->flags & NETIF_FLAG_UP)) {
873             (void)netif_set_down(netif);
874         }
875         if (((unsigned short)ifr->ifr_flags & IFF_RUNNING) && !(netif->flags & NETIF_FLAG_LINK_UP)) {
876             (void)netif_set_link_up(netif);
877         } else if (!((unsigned short)ifr->ifr_flags & IFF_RUNNING) && (netif->flags & NETIF_FLAG_LINK_UP)) {
878             (void)netif_set_link_down(netif);
879         }
880 
881         if ((unsigned short)ifr->ifr_flags & IFF_BROADCAST) {
882             netif->flags |= NETIF_FLAG_BROADCAST;
883         } else {
884             netif->flags = netif->flags & (~NETIF_FLAG_BROADCAST);
885         }
886         if ((unsigned short)ifr->ifr_flags & IFF_NOARP) {
887             netif->flags = (netif->flags & (~NETIF_FLAG_ETHARP));
888         } else {
889             netif->flags |= NETIF_FLAG_ETHARP;
890         }
891 
892         if ((unsigned short)ifr->ifr_flags & IFF_MULTICAST) {
893 #if LWIP_IGMP
894             netif->flags |= NETIF_FLAG_IGMP;
895 #endif /* LWIP_IGMP */
896 #if LWIP_IPV6 && LWIP_IPV6_MLD
897             netif->flags |= NETIF_FLAG_MLD6;
898 #endif /* LWIP_IPV6_MLD */
899         } else {
900 #if LWIP_IGMP
901             netif->flags = (netif->flags & ~NETIF_FLAG_IGMP);
902 #endif /* LWIP_IGMP */
903 #if LWIP_IPV6 && LWIP_IPV6_MLD
904             netif->flags = (netif->flags & ~NETIF_FLAG_MLD6);
905 #endif /* LWIP_IPV6_MLD */
906         }
907 
908 #if LWIP_DHCP
909         if ((unsigned short)ifr->ifr_flags & IFF_DYNAMIC) {
910             (void)dhcp_start(netif);
911         } else {
912             dhcp_stop(netif);
913 #if !LWIP_DHCP_SUBSTITUTE
914             dhcp_cleanup(netif);
915 #endif
916         }
917 #endif
918 
919 #if LWIP_NETIF_PROMISC
920         if (((unsigned short)ifr->ifr_flags & IFF_PROMISC)) {
921             netif->flags |= NETIF_FLAG_PROMISC;
922         } else {
923             netif->flags &= ~NETIF_FLAG_PROMISC;
924         }
925         if (netif->drv_config) {
926             netif->drv_config(netif, IFF_PROMISC, !!((unsigned short)ifr->ifr_flags & IFF_PROMISC));
927         }
928 #endif /* LWIP_NETIF_PROMISC */
929         return 0;
930     }
931 }
932 
lwip_ioctl_internal_SIOCGIFFLAGS(struct ifreq * ifr)933 static u8_t lwip_ioctl_internal_SIOCGIFFLAGS(struct ifreq *ifr)
934 {
935     struct netif *netif = NULL;
936 
937     /* set netif hw addr */
938     netif = netif_find(ifr->ifr_name);
939     if (netif == NULL) {
940         return ENODEV;
941     } else {
942         if (netif->flags & NETIF_FLAG_UP) {
943             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_UP;
944         } else {
945             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_UP;
946         }
947         if (netif->flags & NETIF_FLAG_LINK_UP) {
948             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_RUNNING;
949         } else {
950             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_RUNNING;
951         }
952         if (netif->flags & NETIF_FLAG_BROADCAST) {
953             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_BROADCAST;
954         } else {
955             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_BROADCAST;
956         }
957         if (netif->flags & NETIF_FLAG_ETHARP) {
958             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_NOARP;
959         } else {
960             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_NOARP;
961         }
962 
963 #if LWIP_IGMP || LWIP_IPV6_MLD
964         if (
965 #if LWIP_IGMP
966             (netif->flags & NETIF_FLAG_IGMP)
967 #endif /* LWIP_IGMP */
968 #if LWIP_IGMP && LWIP_IPV6_MLD
969             ||
970 #endif /* LWIP_IGMP && LWIP_IPV6_MLD */
971 #if LWIP_IPV6_MLD
972             (netif->flags & NETIF_FLAG_MLD6)
973 #endif /* LWIP_IPV6_MLD */
974                 ) {
975             ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_MULTICAST);
976         } else {
977             ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_MULTICAST));
978         }
979 #endif /* LWIP_IGMP || LWIP_IPV6_MLD */
980 
981 #if LWIP_DHCP
982         //if ((netif->flags & NETIF_FLAG_DHCP) != 0) {
983         if (dhcp_supplied_address(netif)) {
984             ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_DYNAMIC);
985         } else {
986             ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_DYNAMIC));
987         }
988 #endif
989 
990 #if LWIP_HAVE_LOOPIF
991         if (netif->link_layer_type == LOOPBACK_IF) {
992             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_LOOPBACK;
993         }
994 #endif
995 
996 #if LWIP_NETIF_PROMISC
997         if (netif->flags & NETIF_FLAG_PROMISC) {
998             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_PROMISC;
999         } else {
1000             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_PROMISC;
1001         }
1002 #endif /* LWIP_NETIF_PROMISC */
1003 
1004         return 0;
1005     }
1006 }
1007 
lwip_ioctl_internal_SIOCGIFNAME(struct ifreq * ifr)1008 static u8_t lwip_ioctl_internal_SIOCGIFNAME(struct ifreq *ifr)
1009 {
1010     struct netif *netif = NULL;
1011     int ret;
1012 
1013     for (netif = netif_list; netif != NULL; netif = netif->next) {
1014         if (ifr->ifr_ifindex == netif_get_index(netif)) {
1015             break;
1016         }
1017     }
1018 
1019     if (netif == NULL) {
1020         return ENODEV;
1021     } else {
1022         if (netif->link_layer_type == LOOPBACK_IF) {
1023             ret = snprintf_s(ifr->ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%.2s", netif->name);
1024             if ((ret <= 0) || (ret >= IFNAMSIZ)) {
1025                 return ENOBUFS;
1026             }
1027         } else {
1028             ret = snprintf_s(ifr->ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%s", netif_get_name(netif));
1029             if ((ret <= 0) || (ret >= IFNAMSIZ)) {
1030                 return ENOBUFS;
1031             }
1032         }
1033         return 0;
1034     }
1035 }
1036 
lwip_validate_ifname(const char * name,u8_t * let_pos)1037 static bool lwip_validate_ifname(const char *name, u8_t *let_pos)
1038 {
1039     unsigned short num_pos = 0;
1040     unsigned short letter_pos = 0;
1041     unsigned short pos = 0;
1042     bool have_num = 0;
1043 
1044     /* if the first position of variable name is not letter, such as '6eth2' */
1045     if (((*name >= 'a') && (*name <= 'z')) || ((*name >= 'A') && (*name <= 'Z'))) {
1046         return 0;
1047     }
1048 
1049     /* check if the position of letter is bigger than the the position of digital */
1050     while (*name != '\0') {
1051         if ((*name >= '0') && (*name <= '9')) {
1052             num_pos = pos;
1053             have_num = 1;
1054         } else if (((*name >= 'a') && (*name <= 'z')) || ((*name >= 'A') && (*name <= 'Z'))) {
1055             letter_pos = pos;
1056             if (have_num != 0) {
1057                 return 0;
1058             }
1059         } else {
1060             return 0;
1061         }
1062         pos++;
1063         name++;
1064     }
1065 
1066     /* for the speacil case as all position of variable name is letter, such as 'ethabc' */
1067     if (num_pos == 0) {
1068         return 0;
1069     }
1070 
1071     /* cheak if the digital in the variable name is bigger than 255, such as 'eth266' */
1072     if (atoi(name - (pos - letter_pos - 1)) > 255) {
1073         return 0;
1074     }
1075 
1076     *let_pos = (u8_t)letter_pos;
1077 
1078     return 1;
1079 }
1080 
lwip_ioctl_internal_SIOCSIFNAME(struct ifreq * ifr)1081 static u8_t lwip_ioctl_internal_SIOCSIFNAME(struct ifreq *ifr)
1082 {
1083     struct netif *netif = NULL;
1084     u8_t letter_pos = 0;
1085 
1086 #if LWIP_ENABLE_NET_CAPABILITY
1087     if (!IsCapPermit(CAP_NET_ADMIN)) {
1088         return EPERM;
1089     }
1090 #endif
1091 
1092     netif = netif_find(ifr->ifr_name);
1093 
1094     if (netif == NULL) {
1095         return ENODEV;
1096     } else if (netif->link_layer_type == LOOPBACK_IF) {
1097         return EPERM;
1098     } else if ((netif->flags & IFF_UP) != 0) {
1099         return EBUSY;
1100     } else {
1101         if (strncmp(ifr->ifr_name, ifr->ifr_newname, IFNAMSIZ) == 0) {
1102             /* not change */
1103             return 0;
1104         }
1105 
1106         ifr->ifr_newname[IFNAMSIZ - 1] = '\0';
1107         if ((lwip_validate_ifname(ifr->ifr_newname, &letter_pos) == 0) || (strlen(ifr->ifr_newname) > (IFNAMSIZ - 1))) {
1108             return EINVAL;
1109         }
1110 
1111         if (strncpy_s(netif->full_name, sizeof(netif->full_name), ifr->ifr_newname, strlen(ifr->ifr_newname)) != EOK) {
1112             return EINVAL;
1113         }
1114     }
1115 
1116     return 0;
1117 }
1118 
lwip_ioctl_internal_SIOCGIFINDEX(struct ifreq * ifr)1119 static u8_t lwip_ioctl_internal_SIOCGIFINDEX(struct ifreq *ifr)
1120 {
1121     struct netif *netif = NULL;
1122 
1123     netif = netif_find(ifr->ifr_name);
1124     if (netif == NULL) {
1125         return ENODEV;
1126     } else {
1127         ifr->ifr_ifindex = netif_get_index(netif);
1128         return 0;
1129     }
1130 }
1131 
lwip_ioctl_internal_SIOCSIFMTU(struct ifreq * ifr)1132 static u8_t lwip_ioctl_internal_SIOCSIFMTU(struct ifreq *ifr)
1133 {
1134     struct netif *netif = NULL;
1135 
1136 #if LWIP_ENABLE_NET_CAPABILITY
1137     if (!IsCapPermit(CAP_NET_ADMIN)) {
1138         return EPERM;
1139     }
1140 #endif
1141 
1142     /* set netif hw addr */
1143     netif = netif_find(ifr->ifr_name);
1144     if (netif == NULL) {
1145         return ENODEV;
1146     }
1147 #if LWIP_HAVE_LOOPIF
1148         /* the mtu of loopif is not used. */
1149     else if (netif->link_layer_type == LOOPBACK_IF) {
1150         return EPERM;
1151     }
1152 #endif
1153     else {
1154         if (ERR_OK != netif_set_mtu(netif, (u16_t)ifr->ifr_mtu)) {
1155             return EINVAL;
1156         }
1157 
1158         return 0;
1159     }
1160 }
1161 
lwip_ioctl_internal_SIOCGIFMTU(struct ifreq * ifr)1162 static u8_t lwip_ioctl_internal_SIOCGIFMTU(struct ifreq *ifr)
1163 {
1164     struct netif *netif = NULL;
1165 
1166     /* get netif hw addr */
1167     netif = netif_find(ifr->ifr_name);
1168 
1169     if (netif == NULL) {
1170         return ENODEV;
1171     } else {
1172         ifr->ifr_mtu = netif->mtu;
1173         return 0;
1174     }
1175 }
1176 
lwip_ioctl_internal_SIOCGIFBRDADDR(struct ifreq * ifr)1177 static u8_t lwip_ioctl_internal_SIOCGIFBRDADDR(struct ifreq *ifr)
1178 {
1179     struct netif *netif = NULL;
1180     struct sockaddr_in *sock_in = NULL;
1181 
1182     /* get netif subnet broadcast addr */
1183     netif = netif_find(ifr->ifr_name);
1184     if (netif == NULL) {
1185         return ENODEV;
1186     }
1187     if (ip4_addr_isany_val(*(ip_2_ip4(&netif->netmask)))) {
1188         return ENXIO;
1189     }
1190     sock_in = (struct sockaddr_in *)&ifr->ifr_addr;
1191     sock_in->sin_family = AF_INET;
1192     sock_in->sin_addr.s_addr = (ip_2_ip4(&((netif)->ip_addr))->addr | ~(ip_2_ip4(&netif->netmask)->addr));
1193     return 0;
1194 }
1195 
1196 #endif /* LWIP_IOCTL_IF */
1197 
1198 #if LWIP_NETIF_ETHTOOL
1199 
lwip_ioctl_internal_SIOCETHTOOL(struct ifreq * ifr)1200 static s32_t lwip_ioctl_internal_SIOCETHTOOL(struct ifreq *ifr)
1201 {
1202     struct netif *netif;
1203 
1204 #if LWIP_ENABLE_NET_CAPABILITY
1205     if (!IsCapPermit(CAP_NET_ADMIN)) {
1206         return EPERM;
1207     }
1208 #endif
1209 
1210     netif = netif_find(ifr->ifr_name);
1211     if (netif == NULL) {
1212         return ENODEV;
1213     } else {
1214         return dev_ethtool(netif, ifr);
1215     }
1216 }
1217 
1218 #endif
1219 
1220 #if LWIP_IPV6
1221 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS
1222 
lwip_ioctl_internal_SIOCSIPV6DAD(struct ifreq * ifr)1223 static u8_t lwip_ioctl_internal_SIOCSIPV6DAD(struct ifreq *ifr)
1224 {
1225 #if LWIP_ENABLE_NET_CAPABILITY
1226     if (!IsCapPermit(CAP_NET_ADMIN)) {
1227         return EPERM;
1228     }
1229 #endif
1230 
1231     struct netif *tmpnetif = netif_find(ifr->ifr_name);
1232     if (tmpnetif == NULL) {
1233         LWIP_DEBUGF(SOCKETS_DEBUG, ("Interface not found.\n"));
1234         return ENODEV;
1235     }
1236 
1237     if ((ifr->ifr_ifru.ifru_ivalue != 0) && (ifr->ifr_ifru.ifru_ivalue != 1)) {
1238         LWIP_DEBUGF(SOCKETS_DEBUG, ("Invalid ioctl argument(ifru_ivalue 0/1).\n"));
1239         return EBADRQC;
1240     }
1241 
1242     if (ifr->ifr_ifru.ifru_ivalue == 1) {
1243         tmpnetif->ipv6_flags = (tmpnetif->ipv6_flags | LWIP_IPV6_ND6_FLAG_DAD);
1244 
1245         LWIP_DEBUGF(SOCKETS_DEBUG, ("DAD turned on through ioctl for  %s iface index %u \n",
1246                 tmpnetif->name, tmpnetif->num));
1247     } else {
1248         tmpnetif->ipv6_flags = (tmpnetif->ipv6_flags & ((~LWIP_IPV6_ND6_FLAG_DAD) & 0xffU));
1249 
1250         LWIP_DEBUGF(SOCKETS_DEBUG, ("DAD turned off through ioctl for  %s iface index %u \n",
1251                 tmpnetif->name, tmpnetif->num));
1252     }
1253     return 0;
1254 }
1255 
lwip_ioctl_internal_SIOCGIPV6DAD(struct ifreq * ifr)1256 static u8_t lwip_ioctl_internal_SIOCGIPV6DAD(struct ifreq *ifr)
1257 {
1258     struct netif *tmpnetif = netif_find(ifr->ifr_name);
1259     if (tmpnetif == NULL) {
1260         LWIP_DEBUGF(SOCKETS_DEBUG, ("Interface not found.\n"));
1261         return ENODEV;
1262     }
1263     ifr->ifr_ifru.ifru_ivalue = (tmpnetif->ipv6_flags & LWIP_IPV6_ND6_FLAG_DAD) ? 1 : 0;
1264     return 0;
1265 }
1266 
1267 #endif
1268 
1269 #if LWIP_IOCTL_IPV6DPCTD
1270 
lwip_ioctl_internal_SIOCSIPV6DPCTD(struct ifreq * ifr)1271 static u8_t lwip_ioctl_internal_SIOCSIPV6DPCTD(struct ifreq *ifr)
1272 {
1273 #if LWIP_ENABLE_NET_CAPABILITY
1274     if (!IsCapPermit(CAP_NET_ADMIN)) {
1275         return EPERM;
1276     }
1277 #endif
1278 
1279     struct netif *tmpnetif = netif_find(ifr->ifr_name);
1280     if (tmpnetif == NULL) {
1281         LWIP_DEBUGF(SOCKETS_DEBUG, ("Interface not found.\n"));
1282         return ENODEV;
1283     }
1284     if ((ifr->ifr_ifru.ifru_ivalue != 0) && (ifr->ifr_ifru.ifru_ivalue != 1)) {
1285         LWIP_DEBUGF(SOCKETS_DEBUG, ("Invalid ioctl argument(ifru_ivalue 0/1).\n"));
1286         return EBADRQC;
1287     }
1288     if (ifr->ifr_ifru.ifru_ivalue == 1) {
1289         tmpnetif->ipv6_flags = (tmpnetif->ipv6_flags | LWIP_IPV6_ND6_FLAG_DEPRECATED);
1290         LWIP_DEBUGF(SOCKETS_DEBUG, ("Deprecation turned on through ioctl for  %s iface index %u \n",
1291                 tmpnetif->name, tmpnetif->num));
1292     } else {
1293         tmpnetif->ipv6_flags = (tmpnetif->ipv6_flags & ((~LWIP_IPV6_ND6_FLAG_DEPRECATED) & 0xffU));
1294         LWIP_DEBUGF(SOCKETS_DEBUG, ("Deprecation turned off through ioctl for  %s iface index %u \n",
1295                 tmpnetif->name, tmpnetif->num));
1296     }
1297     return 0;
1298 }
1299 
lwip_ioctl_internal_SIOCGIPV6DPCTD(struct ifreq * ifr)1300 static u8_t lwip_ioctl_internal_SIOCGIPV6DPCTD(struct ifreq *ifr)
1301 {
1302     struct netif *tmpnetif = netif_find(ifr->ifr_name);
1303     if (tmpnetif == NULL) {
1304         LWIP_DEBUGF(SOCKETS_DEBUG, ("Interface not found.\n"));
1305         return ENODEV;
1306     }
1307 
1308     ifr->ifr_ifru.ifru_ivalue = (tmpnetif->ipv6_flags & LWIP_IPV6_ND6_FLAG_DEPRECATED) ? 1 : 0;
1309     return 0;
1310 }
1311 
1312 #endif /* LWIP_IOCTL_IPV6DPCTD */
1313 #endif
1314 
lwip_ioctl_impl(const struct lwip_sock * sock,long cmd,void * argp)1315 static u8_t lwip_ioctl_impl(const struct lwip_sock *sock, long cmd, void *argp)
1316 {
1317     u8_t err = 0;
1318 #if LWIP_NETIF_ETHTOOL
1319     s32_t ret;
1320 #endif
1321 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS || LWIP_IOCTL_IPV6DPCTD || LWIP_IOCTL_IF || LWIP_NETIF_ETHTOOL
1322     struct ifreq *ifr = (struct ifreq *)argp;
1323 #endif
1324 #if LWIP_IOCTL_ROUTE
1325     struct rtentry *rmten = (struct rtentry *)argp;
1326 #endif
1327 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS || LWIP_IOCTL_IPV6DPCTD || LWIP_IOCTL_ROUTE || LWIP_IOCTL_IF
1328     bool is_ipv6 = 0;
1329 
1330     /* allow it only on IPv6 sockets... */
1331     is_ipv6 = NETCONNTYPE_ISIPV6((unsigned int)(sock->conn->type));
1332 #endif
1333 
1334     switch ((u32_t)cmd) {
1335 #if LWIP_IPV6
1336 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS
1337         case SIOCSIPV6DAD:
1338             /* allow it only on IPv6 sockets... */
1339             if (is_ipv6 == 0) {
1340                 err = EINVAL;
1341             } else {
1342                 err = lwip_ioctl_internal_SIOCSIPV6DAD(ifr);
1343             }
1344             break;
1345         case SIOCGIPV6DAD:
1346             /* allow it only on IPv6 sockets... */
1347             if (is_ipv6 == 0) {
1348                 err = EINVAL;
1349             } else {
1350                 err = lwip_ioctl_internal_SIOCGIPV6DAD(ifr);
1351             }
1352             break;
1353 #endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */
1354 #if LWIP_IOCTL_IPV6DPCTD
1355         case SIOCSIPV6DPCTD:
1356             /* allow it only on IPv6 sockets... */
1357             if (is_ipv6 == 0) {
1358                 err = EINVAL;
1359             } else {
1360                 err = lwip_ioctl_internal_SIOCSIPV6DPCTD(ifr);
1361             }
1362             break;
1363         case SIOCGIPV6DPCTD:
1364             /* allow it only on IPv6 sockets... */
1365             if (is_ipv6 == 0) {
1366                 err = EINVAL;
1367             } else {
1368                 err = lwip_ioctl_internal_SIOCGIPV6DPCTD(ifr);
1369             }
1370             break;
1371 #endif
1372 #endif /* LWIP_IPV6 */
1373 #if LWIP_IOCTL_ROUTE
1374         case SIOCADDRT:
1375             /* Do not allow if socket is AF_INET6 */
1376             if (is_ipv6 != 0) {
1377                 err = EINVAL;
1378             } else {
1379                 err = lwip_ioctl_internal_SIOCADDRT(rmten);
1380             }
1381             break;
1382 #endif
1383 #if LWIP_IOCTL_IF
1384         case SIOCGIFCONF:
1385             /* Do not allow if socket is AF_INET6 */
1386             if (is_ipv6 != 0) {
1387                 err = EINVAL;
1388             } else {
1389                 err = lwip_ioctl_internal_SIOCGIFCONF(ifr);
1390             }
1391             break;
1392         case SIOCGIFADDR:
1393             if (is_ipv6 != 0) {
1394                 err = EINVAL;
1395             } else {
1396                 err = lwip_ioctl_internal_SIOCGIFADDR(ifr);
1397             }
1398             break;
1399         case SIOCSIFADDR:
1400             if (is_ipv6 != 0) {
1401                 err = lwip_ioctl_internal_SIOCSIFADDR_6(ifr);
1402             } else {
1403                 err = lwip_ioctl_internal_SIOCSIFADDR(ifr);
1404             }
1405             break;
1406         case SIOCDIFADDR:
1407             /* Delete interface address */
1408             if (is_ipv6 != 0) {
1409                 err = lwip_ioctl_internal_SIOCDIFADDR_6(ifr);
1410             } else {
1411                 err = lwip_ioctl_internal_SIOCDIFADDR(ifr);
1412             }
1413             break;
1414         case SIOCGIFNETMASK:
1415             if (is_ipv6 != 0) {
1416                 err = EINVAL;
1417             } else {
1418                 err = lwip_ioctl_internal_SIOCGIFNETMASK(ifr);
1419             }
1420             break;
1421         case SIOCSIFNETMASK:
1422             if (is_ipv6 != 0) {
1423                 err = EINVAL;
1424             } else {
1425                 err = lwip_ioctl_internal_SIOCSIFNETMASK(ifr);
1426             }
1427             break;
1428         case SIOCSIFHWADDR:
1429             err = lwip_ioctl_internal_SIOCSIFHWADDR(ifr);
1430             break;
1431         case SIOCGIFHWADDR:
1432             err = lwip_ioctl_internal_SIOCGIFHWADDR(ifr);
1433             break;
1434         case SIOCSIFFLAGS:
1435             err = lwip_ioctl_internal_SIOCSIFFLAGS(ifr);
1436             break;
1437         case SIOCGIFFLAGS:
1438             err = lwip_ioctl_internal_SIOCGIFFLAGS(ifr);
1439             break;
1440         case SIOCGIFNAME:
1441             err = lwip_ioctl_internal_SIOCGIFNAME(ifr);
1442             break;
1443         case SIOCSIFNAME:
1444             err = lwip_ioctl_internal_SIOCSIFNAME(ifr);
1445             break;
1446             /* Need to support the get index through ioctl
1447              * As of now the options is restricted to PF_PACKET scenario , so removed the compiler flag Begin
1448              */
1449         case SIOCGIFINDEX:
1450             err = lwip_ioctl_internal_SIOCGIFINDEX(ifr);
1451             break;
1452         case SIOCGIFMTU:
1453             err = lwip_ioctl_internal_SIOCGIFMTU(ifr);
1454             break;
1455         case SIOCSIFMTU:
1456             err = lwip_ioctl_internal_SIOCSIFMTU(ifr);
1457             break;
1458         case SIOCGIFBRDADDR:
1459             if (is_ipv6 != 0) {
1460                 err = EINVAL;
1461             } else {
1462                 err = lwip_ioctl_internal_SIOCGIFBRDADDR(ifr);
1463             }
1464             break;
1465 #endif /* LWIP_IOCTL_IF */
1466 #if LWIP_NETIF_ETHTOOL
1467         case SIOCETHTOOL:
1468             ret = lwip_ioctl_internal_SIOCETHTOOL(ifr);
1469             if (ret != 0) {
1470                 /* an IO error happened */
1471                 err = EIO;
1472             }
1473             break;
1474 #endif
1475             /* START For cmd = -1 stack has to treat it as Invalid Input and return EINVAL */
1476         case 0xFFFFFFFF:
1477             err = EINVAL;
1478             LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl_impl(INVALID: 0x%lx)\n", cmd));
1479             break;
1480         default:
1481             err = ENOSYS;
1482             LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(UNIMPL: 0x%lx)\n", cmd));
1483             break;
1484     }
1485 
1486     return err;
1487 }
1488 
lwip_do_ioctl_impl(struct tcpip_api_call_data * call)1489 static err_t lwip_do_ioctl_impl(struct tcpip_api_call_data *call)
1490 {
1491     struct lwip_ioctl_apimsg *msg = (struct lwip_ioctl_apimsg *)(void *)call;
1492     return lwip_ioctl_impl(msg->sock, msg->cmd, msg->argp);
1493 }
1494 
1495 #include "los_vm_map.h"
1496 #include "user_copy.h"
do_ioctl_SIOCGIFCONF(int sockfd,long cmd,void * argp)1497 static int do_ioctl_SIOCGIFCONF(int sockfd, long cmd, void *argp)
1498 {
1499     int nbytes;
1500     struct ifconf ifc;
1501     char *buf_bak = NULL;
1502     int ret;
1503 
1504     if (LOS_ArchCopyFromUser(&ifc, argp, sizeof(struct ifconf)) != 0) {
1505         set_errno(EFAULT);
1506         return -1;
1507     }
1508     nbytes = ifc.ifc_len;
1509     if (nbytes <= 0) {
1510         set_errno(EINVAL);
1511         return -1;
1512     }
1513     buf_bak = ifc.ifc_buf;
1514     if (!LOS_IsUserAddress((VADDR_T)(uintptr_t)buf_bak)) {
1515         set_errno(EFAULT);
1516         return -1;
1517     }
1518     ifc.ifc_buf = malloc(nbytes);
1519     if (ifc.ifc_buf == NULL) {
1520         set_errno(ENOMEM);
1521         return -1;
1522     }
1523     (void)memset_s(ifc.ifc_buf, nbytes, 0, nbytes);
1524 
1525     ret = lwip_ioctl(sockfd, cmd, &ifc);
1526     if (ret == 0) {
1527         if (LOS_ArchCopyToUser(buf_bak, ifc.ifc_buf, nbytes) != 0) {
1528             set_errno(EFAULT);
1529             ret = -1;
1530         }
1531     }
1532 
1533     free(ifc.ifc_buf);
1534     ifc.ifc_buf = buf_bak;
1535     if (LOS_ArchCopyToUser(argp, &ifc, sizeof(struct ifconf)) != 0) {
1536         set_errno(EFAULT);
1537         ret = -1;
1538     }
1539     return ret;
1540 }
1541 
socks_ioctl(int sockfd,long cmd,void * argp)1542 int socks_ioctl(int sockfd, long cmd, void *argp)
1543 {
1544     void *argpbak = argp;
1545     int ret;
1546     size_t nbytes = 0;
1547 
1548     if (LOS_IsUserAddress((VADDR_T)(uintptr_t)argp)) {
1549         switch (cmd) {
1550             case FIONREAD:
1551             case FIONBIO:
1552                 nbytes = sizeof(int);
1553                 break;
1554             case SIOCADDRT:
1555                 nbytes = sizeof(struct rtentry);
1556                 break;
1557             case SIOCGIFCONF:
1558                 return do_ioctl_SIOCGIFCONF(sockfd, cmd, argp);
1559             case SIOCSIPV6DAD:
1560             case SIOCGIPV6DAD:
1561             case SIOCSIPV6DPCTD:
1562             case SIOCGIPV6DPCTD:
1563             case SIOCGIFADDR:
1564             case SIOCSIFADDR:
1565             case SIOCDIFADDR:
1566             case SIOCGIFNETMASK:
1567             case SIOCSIFNETMASK:
1568             case SIOCSIFHWADDR:
1569             case SIOCGIFHWADDR:
1570             case SIOCSIFFLAGS:
1571             case SIOCGIFFLAGS:
1572             case SIOCGIFNAME:
1573             case SIOCSIFNAME:
1574             case SIOCGIFINDEX:
1575             case SIOCGIFMTU:
1576             case SIOCSIFMTU:
1577             case SIOCETHTOOL:
1578             case SIOCGIFBRDADDR:
1579                 nbytes = sizeof(struct ifreq);
1580                 break;
1581             default:
1582                 nbytes = 0;
1583         }
1584         if (argp != NULL && nbytes > 0) {
1585             argp = malloc(nbytes);
1586             if (argp == NULL) {
1587                 set_errno(ENOMEM);
1588                 return -1;
1589             }
1590             if (LOS_ArchCopyFromUser(argp, argpbak, nbytes) != 0) {
1591                 free(argp);
1592                 set_errno(EFAULT);
1593                 return -1;
1594             }
1595         }
1596     }
1597     ret = lwip_ioctl(sockfd, cmd, argp);
1598     if (ret == 0 && argp != argpbak) {
1599         if (LOS_ArchCopyToUser(argpbak, argp, nbytes) != 0) {
1600             /* how to rollback ioctl ? */
1601             set_errno(EFAULT);
1602             ret = -1;
1603         }
1604     }
1605     if (argp != argpbak) {
1606         free(argp);
1607     }
1608     return ret;
1609 }
1610 
socks_refer(int sockfd)1611 void socks_refer(int sockfd)
1612 {
1613     struct lwip_sock *sock = NULL;
1614     SYS_ARCH_DECL_PROTECT(lev);
1615 
1616     sock = get_socket(sockfd);
1617     if (!sock) {
1618         return;
1619     }
1620 
1621     SYS_ARCH_PROTECT(lev);
1622 
1623     sock->s_refcount++;
1624 
1625     SYS_ARCH_UNPROTECT(lev);
1626 
1627     done_socket(sock);
1628 }
1629 
socks_close(int sockfd)1630 int socks_close(int sockfd)
1631 {
1632     struct lwip_sock *sock = NULL;
1633     SYS_ARCH_DECL_PROTECT(lev);
1634 
1635     sock = get_socket(sockfd);
1636     if (!sock) {
1637         return -1;
1638     }
1639 
1640     SYS_ARCH_PROTECT(lev);
1641 
1642     if (sock->s_refcount == 0) {
1643         SYS_ARCH_UNPROTECT(lev);
1644         done_socket(sock);
1645         return lwip_close(sockfd);
1646     }
1647 
1648     sock->s_refcount--;
1649 
1650     SYS_ARCH_UNPROTECT(lev);
1651     done_socket(sock);
1652     return 0;
1653 }
1654