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/priv/sockets_priv.h"
35 #include "lwip/prot/dhcp.h"
36 #include "lwip/dhcp.h"
37 #include "lwip/if_api.h"
38
39 #if !LWIP_COMPAT_SOCKETS
40 #if LWIP_SOCKET
41
42 #define CHECK_NULL_PTR(ptr) do { if ((ptr) == NULL) { set_errno(EFAULT); return -1; } } while (0)
43
accept(int s,struct sockaddr * addr,socklen_t * addrlen)44 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
45 {
46 return lwip_accept(s, addr, addrlen);
47 }
48
bind(int s,const struct sockaddr * name,socklen_t namelen)49 int bind(int s, const struct sockaddr *name, socklen_t namelen)
50 {
51 CHECK_NULL_PTR(name);
52 if (namelen < sizeof(*name)) {
53 set_errno(EINVAL);
54 return -1;
55 }
56 return lwip_bind(s, name, namelen);
57 }
58
shutdown(int s,int how)59 int shutdown(int s, int how)
60 {
61 return lwip_shutdown(s, how);
62 }
63
getpeername(int s,struct sockaddr * name,socklen_t * namelen)64 int getpeername(int s, struct sockaddr *name, socklen_t *namelen)
65 {
66 CHECK_NULL_PTR(name);
67 CHECK_NULL_PTR(namelen);
68 return lwip_getpeername(s, name, namelen);
69 }
70
getsockname(int s,struct sockaddr * name,socklen_t * namelen)71 int getsockname(int s, struct sockaddr *name, socklen_t *namelen)
72 {
73 CHECK_NULL_PTR(name);
74 CHECK_NULL_PTR(namelen);
75 return lwip_getsockname(s, name, namelen);
76 }
77
getsockopt(int s,int level,int optname,void * optval,socklen_t * optlen)78 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
79 {
80 return lwip_getsockopt(s, level, optname, optval, optlen);
81 }
82
setsockopt(int s,int level,int optname,const void * optval,socklen_t optlen)83 int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
84 {
85 return lwip_setsockopt(s, level, optname, optval, optlen);
86 }
87
closesocket(int s)88 int closesocket(int s)
89 {
90 return lwip_close(s);
91 }
92
connect(int s,const struct sockaddr * name,socklen_t namelen)93 int connect(int s, const struct sockaddr *name, socklen_t namelen)
94 {
95 CHECK_NULL_PTR(name);
96 if (namelen < sizeof(*name)) {
97 set_errno(EINVAL);
98 return -1;
99 }
100 return lwip_connect(s, name, namelen);
101 }
102
listen(int s,int backlog)103 int listen(int s, int backlog)
104 {
105 return lwip_listen(s, backlog);
106 }
107
recv(int s,void * mem,size_t len,int flags)108 ssize_t recv(int s, void *mem, size_t len, int flags)
109 {
110 CHECK_NULL_PTR(mem);
111 return lwip_recv(s, mem, len, flags);
112 }
113
recvfrom(int s,void * mem,size_t len,int flags,struct sockaddr * from,socklen_t * fromlen)114 ssize_t recvfrom(int s, void *mem, size_t len, int flags,
115 struct sockaddr *from, socklen_t *fromlen)
116 {
117 CHECK_NULL_PTR(mem);
118 return lwip_recvfrom(s, mem, len, flags, from, fromlen);
119 }
120
recvmsg(int s,struct msghdr * message,int flags)121 ssize_t recvmsg(int s, struct msghdr *message, int flags)
122 {
123 CHECK_NULL_PTR(message);
124 if (message->msg_iovlen) {
125 CHECK_NULL_PTR(message->msg_iov);
126 }
127 return lwip_recvmsg(s, message, flags);
128 }
129
send(int s,const void * dataptr,size_t size,int flags)130 ssize_t send(int s, const void *dataptr, size_t size, int flags)
131 {
132 CHECK_NULL_PTR(dataptr);
133 return lwip_send(s, dataptr, size, flags);
134 }
135
sendmsg(int s,const struct msghdr * message,int flags)136 ssize_t sendmsg(int s, const struct msghdr *message, int flags)
137 {
138 return lwip_sendmsg(s, message, flags);
139 }
140
sendto(int s,const void * dataptr,size_t size,int flags,const struct sockaddr * to,socklen_t tolen)141 ssize_t sendto(int s, const void *dataptr, size_t size, int flags,
142 const struct sockaddr *to, socklen_t tolen)
143 {
144 CHECK_NULL_PTR(dataptr);
145 if (to && tolen < sizeof(*to)) {
146 set_errno(EINVAL);
147 return -1;
148 }
149 return lwip_sendto(s, dataptr, size, flags, to, tolen);
150 }
151
socket(int domain,int type,int protocol)152 int socket(int domain, int type, int protocol)
153 {
154 return lwip_socket(domain, type, protocol);
155 }
156
inet_ntop(int af,const void * src,char * dst,socklen_t size)157 const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)
158 {
159 return lwip_inet_ntop(af, src, dst, size);
160 }
161
inet_pton(int af,const char * src,void * dst)162 int inet_pton(int af, const char *src, void *dst)
163 {
164 return lwip_inet_pton(af, src, dst);
165 }
166
167 #ifndef LWIP_INET_ADDR_FUNC
inet_addr(const char * cp)168 in_addr_t inet_addr(const char *cp)
169 {
170 return ipaddr_addr(cp);
171 }
172 #endif
173
174 #ifndef LWIP_INET_NTOA_FUNC
inet_ntoa(struct in_addr addr)175 char *inet_ntoa(struct in_addr addr)
176 {
177 return ip4addr_ntoa((const ip4_addr_t*)&(addr));
178 }
179 #endif
180
181 #ifndef LWIP_INET_ATON_FUNC
inet_aton(const char * cp,struct in_addr * addr)182 int inet_aton(const char *cp, struct in_addr *addr)
183 {
184 return ip4addr_aton(cp, (ip4_addr_t*)addr);
185 }
186 #endif
187
ioctlsocket(int s,long cmd,void * argp)188 int ioctlsocket(int s, long cmd, void *argp)
189 {
190 return lwip_ioctl(s, cmd, argp);
191 }
192
193 #ifdef LWIP_SOCKET_READ_FUNC
read(int fd,void * buf,size_t len)194 ssize_t read(int fd, void *buf, size_t len)
195 {
196 return lwip_read(fd, buf, len);
197 }
198 #endif
199
200 #ifdef LWIP_SOCKET_WRITE_FUNC
write(int fd,const void * buf,size_t len)201 ssize_t write(int fd, const void *buf, size_t len)
202 {
203 return lwip_write(fd, buf, len);
204 }
205 #endif
206
207 #ifdef LWIP_SOCKET_CLOSE_FUNC
close(int fd)208 int close(int fd)
209 {
210 return lwip_close(fd);
211 }
212 #endif
213
214 #if LWIP_SOCKET_IOCTL
215 #ifdef LWIP_SOCKET_IOCTL_FUNC
ioctl(int fd,int req,...)216 int ioctl(int fd, int req, ...)
217 {
218 UINTPTR arg = 0;
219 va_list ap;
220 va_start(ap, req);
221 arg = va_arg(ap, UINTPTR);
222 va_end(ap);
223 return lwip_ioctl(fd, (long)req, (void *)arg);
224 }
225 #endif
226 #endif
227
228 #if LWIP_SOCKET_FCNTL
229 #ifdef LWIP_SOCKET_FCNTL_FUNC
fcntl(int fd,int cmd,...)230 int fcntl(int fd, int cmd, ...)
231 {
232 int val = 0;
233 va_list ap;
234 va_start(ap, cmd);
235 val = va_arg(ap, int);
236 va_end(ap);
237 return lwip_fcntl(fd, cmd, val);
238 }
239 #endif
240 #endif
241
242 #if LWIP_SOCKET_SELECT
243 #ifdef LWIP_SOCKET_SELECT_FUNC
select(int maxfdp1,fd_set * readset,fd_set * writeset,fd_set * exceptset,struct timeval * timeout)244 int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout)
245 {
246 return lwip_select(maxfdp1, readset, writeset, exceptset, timeout);
247 }
248 #endif
249 #endif
250
251 #if LWIP_SOCKET_POLL
252 #ifdef LWIP_SOCKET_POLL_FUNC
poll(struct pollfd * fds,nfds_t nfds,int timeout)253 int poll(struct pollfd *fds, nfds_t nfds, int timeout)
254 {
255 return lwip_poll(fds, nfds, timeout);
256 }
257 #endif
258 #endif
259
if_nametoindex(const char * ifname)260 unsigned int if_nametoindex(const char *ifname)
261 {
262 return lwip_if_nametoindex(ifname);
263 }
264
265 #endif
266 #endif /* !LWIP_COMPAT_SOCKETS */
267
268 #define IOCTL_CMD_CASE_HANDLER() do { \
269 err_t err; \
270 struct lwip_ioctl_apimsg msg; \
271 msg.sock = sock; \
272 msg.cmd = cmd; \
273 msg.argp = argp; \
274 \
275 err = tcpip_api_call(lwip_do_ioctl_impl, &msg.call); \
276 if (err != ENOSYS) { \
277 sock_set_errno(sock, err); \
278 done_socket(sock); \
279 return -(err != ERR_OK); \
280 } \
281 } while (0)
282
283 struct lwip_ioctl_apimsg {
284 struct tcpip_api_call_data call;
285 struct lwip_sock *sock;
286 long cmd;
287 void *argp;
288 };
289
290 static err_t lwip_do_ioctl_impl(struct tcpip_api_call_data *call);
291
292 #include "../api/sockets.c"
293
lwip_ioctl_internal_SIOCGIFCONF(struct ifreq * ifr)294 static u8_t lwip_ioctl_internal_SIOCGIFCONF(struct ifreq *ifr)
295 {
296 struct ifconf *ifc = NULL;
297 struct netif *netif = NULL;
298 struct ifreq ifreq;
299 struct sockaddr_in *sock_in = NULL;
300 int pos;
301 int len;
302 int ret;
303
304 /* Format the caller's buffer. */
305 ifc = (struct ifconf *)ifr;
306 len = ifc->ifc_len;
307
308 /* Loop over the interfaces, and write an info block for each. */
309 pos = 0;
310 for (netif = netif_list; netif != NULL; netif = netif->next) {
311 if (ifc->ifc_buf == NULL) {
312 pos = (pos + (int)sizeof(struct ifreq));
313 continue;
314 }
315
316 if (len < (int)sizeof(ifreq)) {
317 break;
318 }
319 (void)memset_s(&ifreq, sizeof(struct ifreq), 0, sizeof(struct ifreq));
320 if (netif->link_layer_type == LOOPBACK_IF) {
321 ret = snprintf_s(ifreq.ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%.2s", netif->name);
322 if ((ret <= 0) || (ret >= IFNAMSIZ)) {
323 LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed."));
324 return ENOBUFS;
325 }
326 } else {
327 ret = snprintf_s(ifreq.ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%s", netif_get_name(netif));
328 if ((ret <= 0) || (ret >= IFNAMSIZ)) {
329 LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed."));
330 return ENOBUFS;
331 }
332 }
333
334 sock_in = (struct sockaddr_in *)&ifreq.ifr_addr;
335 sock_in->sin_family = AF_INET;
336 sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr;
337 if (memcpy_s(ifc->ifc_buf + pos, sizeof(struct ifreq), &ifreq, sizeof(struct ifreq)) != EOK) {
338 return ENOBUFS;
339 }
340 pos = pos + (int)sizeof(struct ifreq);
341 len = len - (int)sizeof(struct ifreq);
342 }
343
344 ifc->ifc_len = pos;
345
346 return 0;
347 }
348
lwip_ioctl_internal_SIOCGIFADDR(struct ifreq * ifr)349 static u8_t lwip_ioctl_internal_SIOCGIFADDR(struct ifreq *ifr)
350 {
351 struct netif *netif = NULL;
352 struct sockaddr_in *sock_in = NULL;
353
354 /* get netif ipaddr */
355 netif = netif_find(ifr->ifr_name);
356 if (netif == NULL) {
357 return ENODEV;
358 } else {
359 sock_in = (struct sockaddr_in *)&ifr->ifr_addr;
360 sock_in->sin_family = AF_INET;
361 sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr;
362 return 0;
363 }
364 }
365
lwip_ioctl_internal_SIOCGIFNETMASK(struct ifreq * ifr)366 static u8_t lwip_ioctl_internal_SIOCGIFNETMASK(struct ifreq *ifr)
367 {
368 struct netif *netif = NULL;
369 struct sockaddr_in *sock_in = NULL;
370
371 /* get netif netmask */
372 netif = netif_find(ifr->ifr_name);
373 if (netif == NULL) {
374 return ENODEV;
375 } else {
376 sock_in = (struct sockaddr_in *)&ifr->ifr_netmask;
377 sock_in->sin_family = AF_INET;
378 sock_in->sin_addr.s_addr = ip_2_ip4(&netif->netmask)->addr;
379 return 0;
380 }
381 }
382
lwip_ioctl_internal_SIOCGIFHWADDR(struct ifreq * ifr)383 static u8_t lwip_ioctl_internal_SIOCGIFHWADDR(struct ifreq *ifr)
384 {
385 struct netif *netif = NULL;
386
387 /* get netif hw addr */
388 netif = netif_find(ifr->ifr_name);
389 if (netif == NULL) {
390 return ENODEV;
391 }
392 #if LWIP_HAVE_LOOPIF
393 else if (netif->link_layer_type == LOOPBACK_IF) {
394 return EPERM;
395 }
396 #endif /* LWIP_HAVE_LOOPIF */
397 else {
398 if (memcpy_s((void *)ifr->ifr_hwaddr.sa_data, sizeof(ifr->ifr_hwaddr.sa_data),
399 (void *)netif->hwaddr, netif->hwaddr_len) != EOK) {
400 return EINVAL;
401 }
402 return 0;
403 }
404 }
405
lwip_ioctl_internal_SIOCSIFFLAGS(struct ifreq * ifr)406 static u8_t lwip_ioctl_internal_SIOCSIFFLAGS(struct ifreq *ifr)
407 {
408 struct netif *netif = NULL;
409
410 /* set netif hw addr */
411 netif = netif_find(ifr->ifr_name);
412 if (netif == NULL) {
413 return ENODEV;
414 }
415 #if LWIP_HAVE_LOOPIF
416 else if (netif->link_layer_type == LOOPBACK_IF) {
417 return EPERM;
418 }
419 #endif /* LWIP_HAVE_LOOPIF */
420 else {
421 if (((unsigned short)ifr->ifr_flags & IFF_UP) && !(netif->flags & NETIF_FLAG_UP)) {
422 (void)netif_set_up(netif);
423 } else if (!((unsigned short)ifr->ifr_flags & IFF_UP) && (netif->flags & NETIF_FLAG_UP)) {
424 (void)netif_set_down(netif);
425 }
426 if (((unsigned short)ifr->ifr_flags & IFF_RUNNING) && !(netif->flags & NETIF_FLAG_LINK_UP)) {
427 (void)netif_set_link_up(netif);
428 } else if (!((unsigned short)ifr->ifr_flags & IFF_RUNNING) && (netif->flags & NETIF_FLAG_LINK_UP)) {
429 (void)netif_set_link_down(netif);
430 }
431
432 if ((unsigned short)ifr->ifr_flags & IFF_BROADCAST) {
433 netif->flags |= NETIF_FLAG_BROADCAST;
434 } else {
435 netif->flags = netif->flags & (~NETIF_FLAG_BROADCAST);
436 }
437 if ((unsigned short)ifr->ifr_flags & IFF_NOARP) {
438 netif->flags = (netif->flags & (~NETIF_FLAG_ETHARP));
439 } else {
440 netif->flags |= NETIF_FLAG_ETHARP;
441 }
442
443 if ((unsigned short)ifr->ifr_flags & IFF_MULTICAST) {
444 #if LWIP_IGMP
445 netif->flags |= NETIF_FLAG_IGMP;
446 #endif /* LWIP_IGMP */
447 #if LWIP_IPV6 && LWIP_IPV6_MLD
448 netif->flags |= NETIF_FLAG_MLD6;
449 #endif /* LWIP_IPV6_MLD */
450 } else {
451 #if LWIP_IGMP
452 netif->flags = (netif->flags & ~NETIF_FLAG_IGMP);
453 #endif /* LWIP_IGMP */
454 #if LWIP_IPV6 && LWIP_IPV6_MLD
455 netif->flags = (netif->flags & ~NETIF_FLAG_MLD6);
456 #endif /* LWIP_IPV6_MLD */
457 }
458
459 #if LWIP_DHCP
460 if ((unsigned short)ifr->ifr_flags & IFF_DYNAMIC) {
461 (void)dhcp_start(netif);
462 } else {
463 dhcp_stop(netif);
464 #if !LWIP_DHCP_SUBSTITUTE
465 dhcp_cleanup(netif);
466 #endif
467 }
468 #endif
469
470 #if LWIP_NETIF_PROMISC
471 if (((unsigned short)ifr->ifr_flags & IFF_PROMISC)) {
472 netif->flags |= NETIF_FLAG_PROMISC;
473 } else {
474 netif->flags &= ~NETIF_FLAG_PROMISC;
475 }
476 if (netif->drv_config) {
477 netif->drv_config(netif, IFF_PROMISC, !!((unsigned short)ifr->ifr_flags & IFF_PROMISC));
478 }
479 #endif /* LWIP_NETIF_PROMISC */
480 return 0;
481 }
482 }
483
lwip_ioctl_internal_SIOCGIFFLAGS(struct ifreq * ifr)484 static u8_t lwip_ioctl_internal_SIOCGIFFLAGS(struct ifreq *ifr)
485 {
486 struct netif *netif = NULL;
487
488 /* set netif hw addr */
489 netif = netif_find(ifr->ifr_name);
490 if (netif == NULL) {
491 return ENODEV;
492 } else {
493 if (netif->flags & NETIF_FLAG_UP) {
494 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_UP;
495 } else {
496 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_UP;
497 }
498 if (netif->flags & NETIF_FLAG_LINK_UP) {
499 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_RUNNING;
500 } else {
501 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_RUNNING;
502 }
503 if (netif->flags & NETIF_FLAG_BROADCAST) {
504 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_BROADCAST;
505 } else {
506 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_BROADCAST;
507 }
508 if (netif->flags & NETIF_FLAG_ETHARP) {
509 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_NOARP;
510 } else {
511 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_NOARP;
512 }
513
514 #if LWIP_IGMP || LWIP_IPV6_MLD
515 if (
516 #if LWIP_IGMP
517 (netif->flags & NETIF_FLAG_IGMP)
518 #endif /* LWIP_IGMP */
519 #if LWIP_IGMP && LWIP_IPV6_MLD
520 ||
521 #endif /* LWIP_IGMP && LWIP_IPV6_MLD */
522 #if LWIP_IPV6_MLD
523 (netif->flags & NETIF_FLAG_MLD6)
524 #endif /* LWIP_IPV6_MLD */
525 ) {
526 ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_MULTICAST);
527 } else {
528 ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_MULTICAST));
529 }
530 #endif /* LWIP_IGMP || LWIP_IPV6_MLD */
531
532 #if LWIP_DHCP
533 if (dhcp_supplied_address(netif)) {
534 ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_DYNAMIC);
535 } else {
536 ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_DYNAMIC));
537 }
538 #endif
539
540 #if LWIP_HAVE_LOOPIF
541 if (netif->link_layer_type == LOOPBACK_IF) {
542 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_LOOPBACK;
543 }
544 #endif
545
546 #if LWIP_NETIF_PROMISC
547 if (netif->flags & NETIF_FLAG_PROMISC) {
548 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_PROMISC;
549 } else {
550 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_PROMISC;
551 }
552 #endif /* LWIP_NETIF_PROMISC */
553
554 return 0;
555 }
556 }
557
lwip_ioctl_internal_SIOCGIFNAME(struct ifreq * ifr)558 static u8_t lwip_ioctl_internal_SIOCGIFNAME(struct ifreq *ifr)
559 {
560 struct netif *netif = NULL;
561 int ret;
562
563 for (netif = netif_list; netif != NULL; netif = netif->next) {
564 if (ifr->ifr_ifindex == netif_get_index(netif)) {
565 break;
566 }
567 }
568
569 if (netif == NULL) {
570 return ENODEV;
571 } else {
572 if (netif->link_layer_type == LOOPBACK_IF) {
573 ret = snprintf_s(ifr->ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%.2s", netif->name);
574 if ((ret <= 0) || (ret >= IFNAMSIZ)) {
575 return ENOBUFS;
576 }
577 } else {
578 ret = snprintf_s(ifr->ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%s", netif_get_name(netif));
579 if ((ret <= 0) || (ret >= IFNAMSIZ)) {
580 return ENOBUFS;
581 }
582 }
583 return 0;
584 }
585 }
586
lwip_validate_ifname(const char * name,u8_t * let_pos)587 static u8_t lwip_validate_ifname(const char *name, u8_t *let_pos)
588 {
589 unsigned short num_pos = 0;
590 unsigned short letter_pos = 0;
591 unsigned short pos = 0;
592 u8_t have_num = 0;
593
594 /* if the first position of variable name is not letter, such as '6eth2' */
595 if (!((*name >= 'a' && *name <= 'z') || (*name >= 'A' && *name <= 'Z'))) {
596 return 0;
597 }
598
599 /* check if the position of letter is bigger than the the position of digital */
600 while (*name != '\0') {
601 if ((*name >= '0') && (*name <= '9')) {
602 num_pos = pos;
603 have_num = 1;
604 } else if (((*name >= 'a') && (*name <= 'z')) || ((*name >= 'A') && (*name <= 'Z'))) {
605 letter_pos = pos;
606 if (have_num != 0) {
607 return 0;
608 }
609 } else {
610 return 0;
611 }
612 pos++;
613 name++;
614 }
615
616 /* for the speacil case as all position of variable name is letter, such as 'ethabc' */
617 if (num_pos == 0) {
618 return 0;
619 }
620
621 /* cheak if the digital in the variable name is bigger than 255, such as 'eth266' */
622 if (atoi(name - (pos - letter_pos - 1)) > 255) {
623 return 0;
624 }
625
626 *let_pos = (u8_t)letter_pos;
627
628 return 1;
629 }
630
lwip_ioctl_internal_SIOCSIFNAME(struct ifreq * ifr)631 static u8_t lwip_ioctl_internal_SIOCSIFNAME(struct ifreq *ifr)
632 {
633 struct netif *netif = NULL;
634 u8_t letter_pos = 0;
635
636 netif = netif_find(ifr->ifr_name);
637 if (netif == NULL) {
638 return ENODEV;
639 } else if (netif->link_layer_type == LOOPBACK_IF) {
640 return EPERM;
641 } else if ((netif->flags & IFF_UP) != 0) {
642 return EBUSY;
643 } else {
644 if (strncmp(ifr->ifr_name, ifr->ifr_newname, IFNAMSIZ) == 0) {
645 /* not change */
646 return 0;
647 }
648
649 ifr->ifr_newname[IFNAMSIZ - 1] = '\0';
650 if ((lwip_validate_ifname(ifr->ifr_newname, &letter_pos) == 0) || (strlen(ifr->ifr_newname) > (IFNAMSIZ - 1))) {
651 return EINVAL;
652 }
653
654 if (strncpy_s(netif->full_name, sizeof(netif->full_name), ifr->ifr_newname, strlen(ifr->ifr_newname)) != EOK) {
655 return EINVAL;
656 }
657 }
658
659 return 0;
660 }
661
lwip_ioctl_internal_SIOCGIFINDEX(struct ifreq * ifr)662 static u8_t lwip_ioctl_internal_SIOCGIFINDEX(struct ifreq *ifr)
663 {
664 struct netif *netif = NULL;
665
666 netif = netif_find(ifr->ifr_name);
667 if (netif == NULL) {
668 return ENODEV;
669 } else {
670 ifr->ifr_ifindex = netif_get_index(netif);
671 return 0;
672 }
673 }
674
lwip_ioctl_internal_SIOCGIFMTU(struct ifreq * ifr)675 static u8_t lwip_ioctl_internal_SIOCGIFMTU(struct ifreq *ifr)
676 {
677 struct netif *netif = NULL;
678
679 /* get netif hw addr */
680 netif = netif_find(ifr->ifr_name);
681 if (netif == NULL) {
682 return ENODEV;
683 } else {
684 ifr->ifr_mtu = netif->mtu;
685 return 0;
686 }
687 }
688
lwip_ioctl_internal_SIOCGIFBRDADDR(struct ifreq * ifr)689 static u8_t lwip_ioctl_internal_SIOCGIFBRDADDR(struct ifreq *ifr)
690 {
691 struct netif *netif = NULL;
692 struct sockaddr_in *sock_in = NULL;
693
694 /* get netif subnet broadcast addr */
695 netif = netif_find(ifr->ifr_name);
696 if (netif == NULL) {
697 return ENODEV;
698 }
699 if (ip4_addr_isany_val(*(ip_2_ip4(&netif->netmask)))) {
700 return ENXIO;
701 }
702 sock_in = (struct sockaddr_in *)&ifr->ifr_addr;
703 sock_in->sin_family = AF_INET;
704 sock_in->sin_addr.s_addr = (ip_2_ip4(&((netif)->ip_addr))->addr | ~(ip_2_ip4(&netif->netmask)->addr));
705 return 0;
706 }
707
lwip_ioctl_impl(const struct lwip_sock * sock,long cmd,void * argp)708 static u8_t lwip_ioctl_impl(const struct lwip_sock *sock, long cmd, void *argp)
709 {
710 u8_t err = 0;
711 struct ifreq *ifr = (struct ifreq *)argp;
712 u8_t is_ipv6 = 0;
713
714 /* allow it only on IPv6 sockets... */
715 is_ipv6 = NETCONNTYPE_ISIPV6((unsigned int)(sock->conn->type));
716
717 switch ((u32_t)cmd) {
718 case SIOCGIFCONF:
719 if (is_ipv6 != 0) {
720 err = EINVAL;
721 } else {
722 err = lwip_ioctl_internal_SIOCGIFCONF(ifr);
723 }
724 break;
725 case SIOCGIFADDR:
726 if (is_ipv6 != 0) {
727 err = EINVAL;
728 } else {
729 err = lwip_ioctl_internal_SIOCGIFADDR(ifr);
730 }
731 break;
732 case SIOCGIFNETMASK:
733 if (is_ipv6 != 0) {
734 err = EINVAL;
735 } else {
736 err = lwip_ioctl_internal_SIOCGIFNETMASK(ifr);
737 }
738 break;
739 case SIOCGIFHWADDR:
740 err = lwip_ioctl_internal_SIOCGIFHWADDR(ifr);
741 break;
742 case SIOCSIFFLAGS:
743 err = lwip_ioctl_internal_SIOCSIFFLAGS(ifr);
744 break;
745 case SIOCGIFFLAGS:
746 err = lwip_ioctl_internal_SIOCGIFFLAGS(ifr);
747 break;
748 case SIOCGIFNAME:
749 err = lwip_ioctl_internal_SIOCGIFNAME(ifr);
750 break;
751 case SIOCSIFNAME:
752 err = lwip_ioctl_internal_SIOCSIFNAME(ifr);
753 break;
754 case SIOCGIFINDEX:
755 err = lwip_ioctl_internal_SIOCGIFINDEX(ifr);
756 break;
757 case SIOCGIFMTU:
758 err = lwip_ioctl_internal_SIOCGIFMTU(ifr);
759 break;
760 case SIOCGIFBRDADDR:
761 if (is_ipv6 != 0) {
762 err = EINVAL;
763 } else {
764 err = lwip_ioctl_internal_SIOCGIFBRDADDR(ifr);
765 }
766 break;
767 default:
768 err = ENOSYS;
769 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(UNIMPL: 0x%lx)\n", cmd));
770 break;
771 }
772
773 return err;
774 }
775
lwip_do_ioctl_impl(struct tcpip_api_call_data * call)776 static err_t lwip_do_ioctl_impl(struct tcpip_api_call_data *call)
777 {
778 struct lwip_ioctl_apimsg *msg = (struct lwip_ioctl_apimsg *)(void *)call;
779 return lwip_ioctl_impl(msg->sock, msg->cmd, msg->argp);
780 }