• 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 
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         /* bring netif down to clear all Neighbor Cache Entry */
807         (void)netif_set_down(netif);
808 
809         ret = netif_set_hwaddr(netif, (const unsigned char *)ifr->ifr_hwaddr.sa_data, netif->hwaddr_len);
810         if (ret != ERR_OK) {
811             (void)netif_set_up(netif);
812             return err_to_errno(ret);
813         }
814 
815         /*
816          * bring netif up to try to send GARP/IGMP/NA/MLD/RS. GARP and NA would
817          * make the neighboring nodes update their Neighbor Cache immediately.
818          */
819         (void)netif_set_up(netif);
820         return 0;
821     }
822 }
823 
lwip_ioctl_internal_SIOCGIFHWADDR(struct ifreq * ifr)824 static u8_t lwip_ioctl_internal_SIOCGIFHWADDR(struct ifreq *ifr)
825 {
826     struct netif *netif = NULL;
827 
828     /* get netif hw addr */
829     netif = netif_find(ifr->ifr_name);
830     if (netif == NULL) {
831         return ENODEV;
832     }
833 #if LWIP_HAVE_LOOPIF
834     else if (netif->link_layer_type == LOOPBACK_IF) {
835         return EPERM;
836     }
837 #endif /* LWIP_HAVE_LOOPIF */
838     else {
839         if (memcpy_s((void *)ifr->ifr_hwaddr.sa_data, sizeof(ifr->ifr_hwaddr.sa_data),
840                      (void *)netif->hwaddr, netif->hwaddr_len) != EOK) {
841             return EINVAL;
842         }
843         return 0;
844     }
845 }
846 
lwip_ioctl_internal_SIOCSIFFLAGS(struct ifreq * ifr)847 static u8_t lwip_ioctl_internal_SIOCSIFFLAGS(struct ifreq *ifr)
848 {
849     struct netif *netif = NULL;
850 
851 #if LWIP_ENABLE_NET_CAPABILITY
852     if (!IsCapPermit(CAP_NET_ADMIN)) {
853         return EPERM;
854     }
855 #endif
856 
857     /* set netif hw addr */
858     netif = netif_find(ifr->ifr_name);
859     if (netif == NULL) {
860         return ENODEV;
861     }
862 #if LWIP_HAVE_LOOPIF
863     else if (netif->link_layer_type == LOOPBACK_IF) {
864         return EPERM;
865     }
866 #endif /* LWIP_HAVE_LOOPIF */
867     else {
868         if (((unsigned short)ifr->ifr_flags & IFF_UP) && !(netif->flags & NETIF_FLAG_UP)) {
869             (void)netif_set_up(netif);
870         } else if (!((unsigned short)ifr->ifr_flags & IFF_UP) && (netif->flags & NETIF_FLAG_UP)) {
871             (void)netif_set_down(netif);
872         }
873         if (((unsigned short)ifr->ifr_flags & IFF_RUNNING) && !(netif->flags & NETIF_FLAG_LINK_UP)) {
874             (void)netif_set_link_up(netif);
875         } else if (!((unsigned short)ifr->ifr_flags & IFF_RUNNING) && (netif->flags & NETIF_FLAG_LINK_UP)) {
876             (void)netif_set_link_down(netif);
877         }
878 
879         if ((unsigned short)ifr->ifr_flags & IFF_BROADCAST) {
880             netif->flags |= NETIF_FLAG_BROADCAST;
881         } else {
882             netif->flags = netif->flags & (~NETIF_FLAG_BROADCAST);
883         }
884         if ((unsigned short)ifr->ifr_flags & IFF_NOARP) {
885             netif->flags = (netif->flags & (~NETIF_FLAG_ETHARP));
886         } else {
887             netif->flags |= NETIF_FLAG_ETHARP;
888         }
889 
890         if ((unsigned short)ifr->ifr_flags & IFF_MULTICAST) {
891 #if LWIP_IGMP
892             netif->flags |= NETIF_FLAG_IGMP;
893 #endif /* LWIP_IGMP */
894 #if LWIP_IPV6 && LWIP_IPV6_MLD
895             netif->flags |= NETIF_FLAG_MLD6;
896 #endif /* LWIP_IPV6_MLD */
897         } else {
898 #if LWIP_IGMP
899             netif->flags = (netif->flags & ~NETIF_FLAG_IGMP);
900 #endif /* LWIP_IGMP */
901 #if LWIP_IPV6 && LWIP_IPV6_MLD
902             netif->flags = (netif->flags & ~NETIF_FLAG_MLD6);
903 #endif /* LWIP_IPV6_MLD */
904         }
905 
906 #if LWIP_DHCP
907         if ((unsigned short)ifr->ifr_flags & IFF_DYNAMIC) {
908             (void)dhcp_start(netif);
909         } else {
910             dhcp_stop(netif);
911 #if !LWIP_DHCP_SUBSTITUTE
912             dhcp_cleanup(netif);
913 #endif
914         }
915 #endif
916 
917 #if LWIP_NETIF_PROMISC
918         if (((unsigned short)ifr->ifr_flags & IFF_PROMISC)) {
919             netif->flags |= NETIF_FLAG_PROMISC;
920         } else {
921             netif->flags &= ~NETIF_FLAG_PROMISC;
922         }
923         if (netif->drv_config) {
924             netif->drv_config(netif, IFF_PROMISC, !!((unsigned short)ifr->ifr_flags & IFF_PROMISC));
925         }
926 #endif /* LWIP_NETIF_PROMISC */
927         return 0;
928     }
929 }
930 
lwip_ioctl_internal_SIOCGIFFLAGS(struct ifreq * ifr)931 static u8_t lwip_ioctl_internal_SIOCGIFFLAGS(struct ifreq *ifr)
932 {
933     struct netif *netif = NULL;
934 
935     /* set netif hw addr */
936     netif = netif_find(ifr->ifr_name);
937     if (netif == NULL) {
938         return ENODEV;
939     } else {
940         if (netif->flags & NETIF_FLAG_UP) {
941             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_UP;
942         } else {
943             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_UP;
944         }
945         if (netif->flags & NETIF_FLAG_LINK_UP) {
946             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_RUNNING;
947         } else {
948             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_RUNNING;
949         }
950         if (netif->flags & NETIF_FLAG_BROADCAST) {
951             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_BROADCAST;
952         } else {
953             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_BROADCAST;
954         }
955         if (netif->flags & NETIF_FLAG_ETHARP) {
956             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_NOARP;
957         } else {
958             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_NOARP;
959         }
960 
961 #if LWIP_IGMP || LWIP_IPV6_MLD
962         if (
963 #if LWIP_IGMP
964             (netif->flags & NETIF_FLAG_IGMP)
965 #endif /* LWIP_IGMP */
966 #if LWIP_IGMP && LWIP_IPV6_MLD
967             ||
968 #endif /* LWIP_IGMP && LWIP_IPV6_MLD */
969 #if LWIP_IPV6_MLD
970             (netif->flags & NETIF_FLAG_MLD6)
971 #endif /* LWIP_IPV6_MLD */
972                 ) {
973             ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_MULTICAST);
974         } else {
975             ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_MULTICAST));
976         }
977 #endif /* LWIP_IGMP || LWIP_IPV6_MLD */
978 
979 #if LWIP_DHCP
980         if (dhcp_supplied_address(netif)) {
981             ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_DYNAMIC);
982         } else {
983             ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_DYNAMIC));
984         }
985 #endif
986 
987 #if LWIP_HAVE_LOOPIF
988         if (netif->link_layer_type == LOOPBACK_IF) {
989             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_LOOPBACK;
990         }
991 #endif
992 
993 #if LWIP_NETIF_PROMISC
994         if (netif->flags & NETIF_FLAG_PROMISC) {
995             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_PROMISC;
996         } else {
997             ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_PROMISC;
998         }
999 #endif /* LWIP_NETIF_PROMISC */
1000 
1001         return 0;
1002     }
1003 }
1004 
lwip_ioctl_internal_SIOCGIFNAME(struct ifreq * ifr)1005 static u8_t lwip_ioctl_internal_SIOCGIFNAME(struct ifreq *ifr)
1006 {
1007     struct netif *netif = NULL;
1008     int ret;
1009 
1010     for (netif = netif_list; netif != NULL; netif = netif->next) {
1011         if (ifr->ifr_ifindex == netif_get_index(netif)) {
1012             break;
1013         }
1014     }
1015 
1016     if (netif == NULL) {
1017         return ENODEV;
1018     } else {
1019         if (netif->link_layer_type == LOOPBACK_IF) {
1020             ret = snprintf_s(ifr->ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%.2s", netif->name);
1021             if ((ret <= 0) || (ret >= IFNAMSIZ)) {
1022                 return ENOBUFS;
1023             }
1024         } else {
1025             ret = snprintf_s(ifr->ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%s", netif_get_name(netif));
1026             if ((ret <= 0) || (ret >= IFNAMSIZ)) {
1027                 return ENOBUFS;
1028             }
1029         }
1030         return 0;
1031     }
1032 }
1033 
lwip_validate_ifname(const char * name,u8_t * let_pos)1034 static bool lwip_validate_ifname(const char *name, u8_t *let_pos)
1035 {
1036     unsigned short num_pos = 0;
1037     unsigned short letter_pos = 0;
1038     unsigned short pos = 0;
1039     bool have_num = 0;
1040 
1041     /* if the first position of variable name is not letter, such as '6eth2' */
1042     if (((*name >= 'a') && (*name <= 'z')) || ((*name >= 'A') && (*name <= 'Z'))) {
1043         return 0;
1044     }
1045 
1046     /* check if the position of letter is bigger than the the position of digital */
1047     while (*name != '\0') {
1048         if ((*name >= '0') && (*name <= '9')) {
1049             num_pos = pos;
1050             have_num = 1;
1051         } else if (((*name >= 'a') && (*name <= 'z')) || ((*name >= 'A') && (*name <= 'Z'))) {
1052             letter_pos = pos;
1053             if (have_num != 0) {
1054                 return 0;
1055             }
1056         } else {
1057             return 0;
1058         }
1059         pos++;
1060         name++;
1061     }
1062 
1063     /* for the speacil case as all position of variable name is letter, such as 'ethabc' */
1064     if (num_pos == 0) {
1065         return 0;
1066     }
1067 
1068     /* cheak if the digital in the variable name is bigger than 255, such as 'eth266' */
1069     if (atoi(name - (pos - letter_pos - 1)) > 255) {
1070         return 0;
1071     }
1072 
1073     *let_pos = (u8_t)letter_pos;
1074 
1075     return 1;
1076 }
1077 
lwip_ioctl_internal_SIOCSIFNAME(struct ifreq * ifr)1078 static u8_t lwip_ioctl_internal_SIOCSIFNAME(struct ifreq *ifr)
1079 {
1080     struct netif *netif = NULL;
1081     u8_t letter_pos = 0;
1082 
1083 #if LWIP_ENABLE_NET_CAPABILITY
1084     if (!IsCapPermit(CAP_NET_ADMIN)) {
1085         return EPERM;
1086     }
1087 #endif
1088 
1089     netif = netif_find(ifr->ifr_name);
1090     if (netif == NULL) {
1091         return ENODEV;
1092     } else if (netif->link_layer_type == LOOPBACK_IF) {
1093         return EPERM;
1094     } else if ((netif->flags & IFF_UP) != 0) {
1095         return EBUSY;
1096     } else {
1097         if (strncmp(ifr->ifr_name, ifr->ifr_newname, IFNAMSIZ) == 0) {
1098             /* not change */
1099             return 0;
1100         }
1101 
1102         ifr->ifr_newname[IFNAMSIZ - 1] = '\0';
1103         if ((lwip_validate_ifname(ifr->ifr_newname, &letter_pos) == 0) || (strlen(ifr->ifr_newname) > (IFNAMSIZ - 1))) {
1104             return EINVAL;
1105         }
1106 
1107         if (strncpy_s(netif->full_name, sizeof(netif->full_name), ifr->ifr_newname, strlen(ifr->ifr_newname)) != EOK) {
1108             return EINVAL;
1109         }
1110     }
1111 
1112     return 0;
1113 }
1114 
lwip_ioctl_internal_SIOCGIFINDEX(struct ifreq * ifr)1115 static u8_t lwip_ioctl_internal_SIOCGIFINDEX(struct ifreq *ifr)
1116 {
1117     struct netif *netif = NULL;
1118 
1119     netif = netif_find(ifr->ifr_name);
1120     if (netif == NULL) {
1121         return ENODEV;
1122     } else {
1123         ifr->ifr_ifindex = netif_get_index(netif);
1124         return 0;
1125     }
1126 }
1127 
lwip_ioctl_internal_SIOCSIFMTU(struct ifreq * ifr)1128 static u8_t lwip_ioctl_internal_SIOCSIFMTU(struct ifreq *ifr)
1129 {
1130     struct netif *netif = NULL;
1131 
1132 #if LWIP_ENABLE_NET_CAPABILITY
1133     if (!IsCapPermit(CAP_NET_ADMIN)) {
1134         return EPERM;
1135     }
1136 #endif
1137 
1138     /* set netif hw addr */
1139     netif = netif_find(ifr->ifr_name);
1140     if (netif == NULL) {
1141         return ENODEV;
1142     }
1143 #if LWIP_HAVE_LOOPIF
1144         /* the mtu of loopif is not used. */
1145     else if (netif->link_layer_type == LOOPBACK_IF) {
1146         return EPERM;
1147     }
1148 #endif
1149     else {
1150         if (ERR_OK != netif_set_mtu(netif, (u16_t)ifr->ifr_mtu)) {
1151             return EINVAL;
1152         }
1153 
1154         return 0;
1155     }
1156 }
1157 
lwip_ioctl_internal_SIOCGIFMTU(struct ifreq * ifr)1158 static u8_t lwip_ioctl_internal_SIOCGIFMTU(struct ifreq *ifr)
1159 {
1160     struct netif *netif = NULL;
1161 
1162     /* get netif hw addr */
1163     netif = netif_find(ifr->ifr_name);
1164     if (netif == NULL) {
1165         return ENODEV;
1166     } else {
1167         ifr->ifr_mtu = netif->mtu;
1168         return 0;
1169     }
1170 }
1171 
lwip_ioctl_internal_SIOCGIFBRDADDR(struct ifreq * ifr)1172 static u8_t lwip_ioctl_internal_SIOCGIFBRDADDR(struct ifreq *ifr)
1173 {
1174     struct netif *netif = NULL;
1175     struct sockaddr_in *sock_in = NULL;
1176 
1177     /* get netif subnet broadcast addr */
1178     netif = netif_find(ifr->ifr_name);
1179     if (netif == NULL) {
1180         return ENODEV;
1181     }
1182     if (ip4_addr_isany_val(*(ip_2_ip4(&netif->netmask)))) {
1183         return ENXIO;
1184     }
1185     sock_in = (struct sockaddr_in *)&ifr->ifr_addr;
1186     sock_in->sin_family = AF_INET;
1187     sock_in->sin_addr.s_addr = (ip_2_ip4(&((netif)->ip_addr))->addr | ~(ip_2_ip4(&netif->netmask)->addr));
1188     return 0;
1189 }
1190 
1191 #endif /* LWIP_IOCTL_IF */
1192 
1193 #if LWIP_NETIF_ETHTOOL
1194 
lwip_ioctl_internal_SIOCETHTOOL(struct ifreq * ifr)1195 static s32_t lwip_ioctl_internal_SIOCETHTOOL(struct ifreq *ifr)
1196 {
1197     struct netif *netif;
1198 
1199 #if LWIP_ENABLE_NET_CAPABILITY
1200     if (!IsCapPermit(CAP_NET_ADMIN)) {
1201         return EPERM;
1202     }
1203 #endif
1204 
1205     netif = netif_find(ifr->ifr_name);
1206     if (netif == NULL) {
1207         return ENODEV;
1208     } else {
1209         return dev_ethtool(netif, ifr);
1210     }
1211 }
1212 
1213 #endif
1214 
1215 #if LWIP_IPV6
1216 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS
1217 
lwip_ioctl_internal_SIOCSIPV6DAD(struct ifreq * ifr)1218 static u8_t lwip_ioctl_internal_SIOCSIPV6DAD(struct ifreq *ifr)
1219 {
1220 #if LWIP_ENABLE_NET_CAPABILITY
1221     if (!IsCapPermit(CAP_NET_ADMIN)) {
1222         return EPERM;
1223     }
1224 #endif
1225 
1226     struct netif *tmpnetif = netif_find(ifr->ifr_name);
1227     if (tmpnetif == NULL) {
1228         LWIP_DEBUGF(SOCKETS_DEBUG, ("Interface not found.\n"));
1229         return ENODEV;
1230     }
1231 
1232     if ((ifr->ifr_ifru.ifru_ivalue != 0) && (ifr->ifr_ifru.ifru_ivalue != 1)) {
1233         LWIP_DEBUGF(SOCKETS_DEBUG, ("Invalid ioctl argument(ifru_ivalue 0/1).\n"));
1234         return EBADRQC;
1235     }
1236 
1237     if (ifr->ifr_ifru.ifru_ivalue == 1) {
1238         tmpnetif->ipv6_flags = (tmpnetif->ipv6_flags | LWIP_IPV6_ND6_FLAG_DAD);
1239 
1240         LWIP_DEBUGF(SOCKETS_DEBUG, ("DAD turned on through ioctl for  %s iface index %u \n",
1241                 tmpnetif->name, tmpnetif->num));
1242     } else {
1243         tmpnetif->ipv6_flags = (tmpnetif->ipv6_flags & ((~LWIP_IPV6_ND6_FLAG_DAD) & 0xffU));
1244 
1245         LWIP_DEBUGF(SOCKETS_DEBUG, ("DAD turned off through ioctl for  %s iface index %u \n",
1246                 tmpnetif->name, tmpnetif->num));
1247     }
1248     return 0;
1249 }
1250 
lwip_ioctl_internal_SIOCGIPV6DAD(struct ifreq * ifr)1251 static u8_t lwip_ioctl_internal_SIOCGIPV6DAD(struct ifreq *ifr)
1252 {
1253     struct netif *tmpnetif = netif_find(ifr->ifr_name);
1254     if (tmpnetif == NULL) {
1255         LWIP_DEBUGF(SOCKETS_DEBUG, ("Interface not found.\n"));
1256         return ENODEV;
1257     }
1258     ifr->ifr_ifru.ifru_ivalue = (tmpnetif->ipv6_flags & LWIP_IPV6_ND6_FLAG_DAD) ? 1 : 0;
1259     return 0;
1260 }
1261 
1262 #endif
1263 
1264 #if LWIP_IOCTL_IPV6DPCTD
1265 
lwip_ioctl_internal_SIOCSIPV6DPCTD(struct ifreq * ifr)1266 static u8_t lwip_ioctl_internal_SIOCSIPV6DPCTD(struct ifreq *ifr)
1267 {
1268 #if LWIP_ENABLE_NET_CAPABILITY
1269     if (!IsCapPermit(CAP_NET_ADMIN)) {
1270         return EPERM;
1271     }
1272 #endif
1273 
1274     struct netif *tmpnetif = netif_find(ifr->ifr_name);
1275     if (tmpnetif == NULL) {
1276         LWIP_DEBUGF(SOCKETS_DEBUG, ("Interface not found.\n"));
1277         return ENODEV;
1278     }
1279     if ((ifr->ifr_ifru.ifru_ivalue != 0) && (ifr->ifr_ifru.ifru_ivalue != 1)) {
1280         LWIP_DEBUGF(SOCKETS_DEBUG, ("Invalid ioctl argument(ifru_ivalue 0/1).\n"));
1281         return EBADRQC;
1282     }
1283     if (ifr->ifr_ifru.ifru_ivalue == 1) {
1284         tmpnetif->ipv6_flags = (tmpnetif->ipv6_flags | LWIP_IPV6_ND6_FLAG_DEPRECATED);
1285         LWIP_DEBUGF(SOCKETS_DEBUG, ("Deprecation turned on through ioctl for  %s iface index %u \n",
1286                 tmpnetif->name, tmpnetif->num));
1287     } else {
1288         tmpnetif->ipv6_flags = (tmpnetif->ipv6_flags & ((~LWIP_IPV6_ND6_FLAG_DEPRECATED) & 0xffU));
1289         LWIP_DEBUGF(SOCKETS_DEBUG, ("Deprecation turned off through ioctl for  %s iface index %u \n",
1290                 tmpnetif->name, tmpnetif->num));
1291     }
1292     return 0;
1293 }
1294 
lwip_ioctl_internal_SIOCGIPV6DPCTD(struct ifreq * ifr)1295 static u8_t lwip_ioctl_internal_SIOCGIPV6DPCTD(struct ifreq *ifr)
1296 {
1297     struct netif *tmpnetif = netif_find(ifr->ifr_name);
1298     if (tmpnetif == NULL) {
1299         LWIP_DEBUGF(SOCKETS_DEBUG, ("Interface not found.\n"));
1300         return ENODEV;
1301     }
1302 
1303     ifr->ifr_ifru.ifru_ivalue = (tmpnetif->ipv6_flags & LWIP_IPV6_ND6_FLAG_DEPRECATED) ? 1 : 0;
1304     return 0;
1305 }
1306 
1307 #endif /* LWIP_IOCTL_IPV6DPCTD */
1308 #endif
1309 
lwip_ioctl_impl(const struct lwip_sock * sock,long cmd,void * argp)1310 static u8_t lwip_ioctl_impl(const struct lwip_sock *sock, long cmd, void *argp)
1311 {
1312     u8_t err = 0;
1313 #if LWIP_NETIF_ETHTOOL
1314     s32_t ret;
1315 #endif
1316 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS || LWIP_IOCTL_IPV6DPCTD || LWIP_IOCTL_IF || LWIP_NETIF_ETHTOOL
1317     struct ifreq *ifr = (struct ifreq *)argp;
1318 #endif
1319 #if LWIP_IOCTL_ROUTE
1320     struct rtentry *rmten = (struct rtentry *)argp;
1321 #endif
1322 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS || LWIP_IOCTL_IPV6DPCTD || LWIP_IOCTL_ROUTE || LWIP_IOCTL_IF
1323     bool is_ipv6 = 0;
1324 
1325     /* allow it only on IPv6 sockets... */
1326     is_ipv6 = NETCONNTYPE_ISIPV6((unsigned int)(sock->conn->type));
1327 #endif
1328 
1329     switch ((u32_t)cmd) {
1330 #if LWIP_IPV6
1331 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS
1332         case SIOCSIPV6DAD:
1333             /* allow it only on IPv6 sockets... */
1334             if (is_ipv6 == 0) {
1335                 err = EINVAL;
1336             } else {
1337                 err = lwip_ioctl_internal_SIOCSIPV6DAD(ifr);
1338             }
1339             break;
1340         case SIOCGIPV6DAD:
1341             /* allow it only on IPv6 sockets... */
1342             if (is_ipv6 == 0) {
1343                 err = EINVAL;
1344             } else {
1345                 err = lwip_ioctl_internal_SIOCGIPV6DAD(ifr);
1346             }
1347             break;
1348 #endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */
1349 #if LWIP_IOCTL_IPV6DPCTD
1350         case SIOCSIPV6DPCTD:
1351             /* allow it only on IPv6 sockets... */
1352             if (is_ipv6 == 0) {
1353                 err = EINVAL;
1354             } else {
1355                 err = lwip_ioctl_internal_SIOCSIPV6DPCTD(ifr);
1356             }
1357             break;
1358         case SIOCGIPV6DPCTD:
1359             /* allow it only on IPv6 sockets... */
1360             if (is_ipv6 == 0) {
1361                 err = EINVAL;
1362             } else {
1363                 err = lwip_ioctl_internal_SIOCGIPV6DPCTD(ifr);
1364             }
1365             break;
1366 #endif
1367 #endif /* LWIP_IPV6 */
1368 #if LWIP_IOCTL_ROUTE
1369         case SIOCADDRT:
1370             /* Do not allow if socket is AF_INET6 */
1371             if (is_ipv6 != 0) {
1372                 err = EINVAL;
1373             } else {
1374                 err = lwip_ioctl_internal_SIOCADDRT(rmten);
1375             }
1376             break;
1377 #endif
1378 #if LWIP_IOCTL_IF
1379         case SIOCGIFCONF:
1380             /* Do not allow if socket is AF_INET6 */
1381             if (is_ipv6 != 0) {
1382                 err = EINVAL;
1383             } else {
1384                 err = lwip_ioctl_internal_SIOCGIFCONF(ifr);
1385             }
1386             break;
1387         case SIOCGIFADDR:
1388             if (is_ipv6 != 0) {
1389                 err = EINVAL;
1390             } else {
1391                 err = lwip_ioctl_internal_SIOCGIFADDR(ifr);
1392             }
1393             break;
1394         case SIOCSIFADDR:
1395             if (is_ipv6 != 0) {
1396                 err = lwip_ioctl_internal_SIOCSIFADDR_6(ifr);
1397             } else {
1398                 err = lwip_ioctl_internal_SIOCSIFADDR(ifr);
1399             }
1400             break;
1401         case SIOCDIFADDR:
1402             /* Delete interface address */
1403             if (is_ipv6 != 0) {
1404                 err = lwip_ioctl_internal_SIOCDIFADDR_6(ifr);
1405             } else {
1406                 err = lwip_ioctl_internal_SIOCDIFADDR(ifr);
1407             }
1408             break;
1409         case SIOCGIFNETMASK:
1410             if (is_ipv6 != 0) {
1411                 err = EINVAL;
1412             } else {
1413                 err = lwip_ioctl_internal_SIOCGIFNETMASK(ifr);
1414             }
1415             break;
1416         case SIOCSIFNETMASK:
1417             if (is_ipv6 != 0) {
1418                 err = EINVAL;
1419             } else {
1420                 err = lwip_ioctl_internal_SIOCSIFNETMASK(ifr);
1421             }
1422             break;
1423         case SIOCSIFHWADDR:
1424             err = lwip_ioctl_internal_SIOCSIFHWADDR(ifr);
1425             break;
1426         case SIOCGIFHWADDR:
1427             err = lwip_ioctl_internal_SIOCGIFHWADDR(ifr);
1428             break;
1429         case SIOCSIFFLAGS:
1430             err = lwip_ioctl_internal_SIOCSIFFLAGS(ifr);
1431             break;
1432         case SIOCGIFFLAGS:
1433             err = lwip_ioctl_internal_SIOCGIFFLAGS(ifr);
1434             break;
1435         case SIOCGIFNAME:
1436             err = lwip_ioctl_internal_SIOCGIFNAME(ifr);
1437             break;
1438         case SIOCSIFNAME:
1439             err = lwip_ioctl_internal_SIOCSIFNAME(ifr);
1440             break;
1441             /* Need to support the get index through ioctl
1442              * As of now the options is restricted to PF_PACKET scenario , so removed the compiler flag Begin
1443              */
1444         case SIOCGIFINDEX:
1445             err = lwip_ioctl_internal_SIOCGIFINDEX(ifr);
1446             break;
1447         case SIOCGIFMTU:
1448             err = lwip_ioctl_internal_SIOCGIFMTU(ifr);
1449             break;
1450         case SIOCSIFMTU:
1451             err = lwip_ioctl_internal_SIOCSIFMTU(ifr);
1452             break;
1453         case SIOCGIFBRDADDR:
1454             if (is_ipv6 != 0) {
1455                 err = EINVAL;
1456             } else {
1457                 err = lwip_ioctl_internal_SIOCGIFBRDADDR(ifr);
1458             }
1459             break;
1460 #endif /* LWIP_IOCTL_IF */
1461 #if LWIP_NETIF_ETHTOOL
1462         case SIOCETHTOOL:
1463             ret = lwip_ioctl_internal_SIOCETHTOOL(ifr);
1464             if (ret != 0) {
1465                 /* an IO error happened */
1466                 err = EIO;
1467             }
1468             break;
1469 #endif
1470             /* START For cmd = -1 stack has to treat it as Invalid Input and return EINVAL */
1471         case 0xFFFFFFFF:
1472             err = EINVAL;
1473             LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl_impl(INVALID: 0x%lx)\n", cmd));
1474             break;
1475         default:
1476             err = ENOSYS;
1477             LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(UNIMPL: 0x%lx)\n", cmd));
1478             break;
1479     }
1480 
1481     return err;
1482 }
1483 
lwip_do_ioctl_impl(struct tcpip_api_call_data * call)1484 static err_t lwip_do_ioctl_impl(struct tcpip_api_call_data *call)
1485 {
1486     struct lwip_ioctl_apimsg *msg = (struct lwip_ioctl_apimsg *)(void *)call;
1487     return lwip_ioctl_impl(msg->sock, msg->cmd, msg->argp);
1488 }
1489 
1490 #include "los_vm_map.h"
1491 #include "user_copy.h"
do_ioctl_SIOCGIFCONF(int sockfd,long cmd,void * argp)1492 static int do_ioctl_SIOCGIFCONF(int sockfd, long cmd, void *argp)
1493 {
1494     int nbytes;
1495     struct ifconf ifc;
1496     char *buf_bak = NULL;
1497     int ret;
1498 
1499     if (LOS_ArchCopyFromUser(&ifc, argp, sizeof(struct ifconf)) != 0) {
1500         set_errno(EFAULT);
1501         return -1;
1502     }
1503     nbytes = ifc.ifc_len;
1504     if (nbytes <= 0) {
1505         set_errno(EINVAL);
1506         return -1;
1507     }
1508     buf_bak = ifc.ifc_buf;
1509     if (!LOS_IsUserAddress((VADDR_T)(uintptr_t)buf_bak)) {
1510         set_errno(EFAULT);
1511         return -1;
1512     }
1513     ifc.ifc_buf = malloc(nbytes);
1514     if (ifc.ifc_buf == NULL) {
1515         set_errno(ENOMEM);
1516         return -1;
1517     }
1518     (void)memset_s(ifc.ifc_buf, nbytes, 0, nbytes);
1519 
1520     ret = lwip_ioctl(sockfd, cmd, &ifc);
1521     if (ret == 0) {
1522         if (LOS_ArchCopyToUser(buf_bak, ifc.ifc_buf, nbytes) != 0) {
1523             set_errno(EFAULT);
1524             ret = -1;
1525         }
1526     }
1527 
1528     free(ifc.ifc_buf);
1529     ifc.ifc_buf = buf_bak;
1530     if (LOS_ArchCopyToUser(argp, &ifc, sizeof(struct ifconf)) != 0) {
1531         set_errno(EFAULT);
1532         ret = -1;
1533     }
1534     return ret;
1535 }
1536 
socks_ioctl(int sockfd,long cmd,void * argp)1537 int socks_ioctl(int sockfd, long cmd, void *argp)
1538 {
1539     void *argpbak = argp;
1540     int ret;
1541     size_t nbytes = 0;
1542 
1543     if (LOS_IsUserAddress((VADDR_T)(uintptr_t)argp)) {
1544         switch (cmd) {
1545             case FIONREAD:
1546             case FIONBIO:
1547                 nbytes = sizeof(int);
1548                 break;
1549             case SIOCADDRT:
1550                 nbytes = sizeof(struct rtentry);
1551                 break;
1552             case SIOCGIFCONF:
1553                 return do_ioctl_SIOCGIFCONF(sockfd, cmd, argp);
1554             case SIOCSIPV6DAD:
1555             case SIOCGIPV6DAD:
1556             case SIOCSIPV6DPCTD:
1557             case SIOCGIPV6DPCTD:
1558             case SIOCGIFADDR:
1559             case SIOCSIFADDR:
1560             case SIOCDIFADDR:
1561             case SIOCGIFNETMASK:
1562             case SIOCSIFNETMASK:
1563             case SIOCSIFHWADDR:
1564             case SIOCGIFHWADDR:
1565             case SIOCSIFFLAGS:
1566             case SIOCGIFFLAGS:
1567             case SIOCGIFNAME:
1568             case SIOCSIFNAME:
1569             case SIOCGIFINDEX:
1570             case SIOCGIFMTU:
1571             case SIOCSIFMTU:
1572             case SIOCETHTOOL:
1573             case SIOCGIFBRDADDR:
1574                 nbytes = sizeof(struct ifreq);
1575                 break;
1576             default:
1577                 nbytes = 0;
1578         }
1579         if (argp != NULL && nbytes > 0) {
1580             argp = malloc(nbytes);
1581             if (argp == NULL) {
1582                 set_errno(ENOMEM);
1583                 return -1;
1584             }
1585             if (LOS_ArchCopyFromUser(argp, argpbak, nbytes) != 0) {
1586                 free(argp);
1587                 set_errno(EFAULT);
1588                 return -1;
1589             }
1590         }
1591     }
1592     ret = lwip_ioctl(sockfd, cmd, argp);
1593     if (ret == 0 && argp != argpbak) {
1594         if (LOS_ArchCopyToUser(argpbak, argp, nbytes) != 0) {
1595             /* how to rollback ioctl ? */
1596             set_errno(EFAULT);
1597             ret = -1;
1598         }
1599     }
1600     if (argp != argpbak) {
1601         free(argp);
1602     }
1603     return ret;
1604 }
1605 
socks_refer(int sockfd)1606 void socks_refer(int sockfd)
1607 {
1608     struct lwip_sock *sock = NULL;
1609     SYS_ARCH_DECL_PROTECT(lev);
1610 
1611     sock = get_socket(sockfd);
1612     if (!sock) {
1613         return;
1614     }
1615 
1616     SYS_ARCH_PROTECT(lev);
1617 
1618     sock->s_refcount++;
1619 
1620     SYS_ARCH_UNPROTECT(lev);
1621 
1622     done_socket(sock);
1623 }
1624 
socks_close(int sockfd)1625 int socks_close(int sockfd)
1626 {
1627     struct lwip_sock *sock = NULL;
1628     SYS_ARCH_DECL_PROTECT(lev);
1629 
1630     sock = get_socket(sockfd);
1631     if (!sock) {
1632         return -1;
1633     }
1634 
1635     SYS_ARCH_PROTECT(lev);
1636 
1637     if (sock->s_refcount == 0) {
1638         SYS_ARCH_UNPROTECT(lev);
1639         done_socket(sock);
1640         return lwip_close(sockfd);
1641     }
1642 
1643     sock->s_refcount--;
1644 
1645     SYS_ARCH_UNPROTECT(lev);
1646     done_socket(sock);
1647     return 0;
1648 }
1649