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