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 #ifdef LWIP_SOCKET_IOCTL_FUNC
ioctl(int fd,int req,...)215 int ioctl(int fd, int req, ...)
216 {
217 UINTPTR arg = 0;
218 va_list ap;
219 va_start(ap, req);
220 arg = va_arg(ap, UINTPTR);
221 va_end(ap);
222 return lwip_ioctl(fd, (long)req, (void *)arg);
223 }
224 #endif
225
226 #ifdef LWIP_SOCKET_FCNTL_FUNC
fcntl(int fd,int cmd,...)227 int fcntl(int fd, int cmd, ...)
228 {
229 int val = 0;
230 va_list ap;
231 va_start(ap, cmd);
232 val = va_arg(ap, int);
233 va_end(ap);
234 return lwip_fcntl(fd, cmd, val);
235 }
236 #endif
237
238 #if LWIP_SOCKET_SELECT
239 #ifdef LWIP_SOCKET_SELECT_FUNC
select(int maxfdp1,fd_set * readset,fd_set * writeset,fd_set * exceptset,struct timeval * timeout)240 int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout)
241 {
242 return lwip_select(maxfdp1, readset, writeset, exceptset, timeout);
243 }
244 #endif
245 #endif
246
247 #if LWIP_SOCKET_POLL
248 #ifdef LWIP_SOCKET_POLL_FUNC
poll(struct pollfd * fds,nfds_t nfds,int timeout)249 int poll(struct pollfd *fds, nfds_t nfds, int timeout)
250 {
251 return lwip_poll(fds, nfds, timeout);
252 }
253 #endif
254 #endif
255
if_nametoindex(const char * ifname)256 unsigned int if_nametoindex(const char *ifname)
257 {
258 return lwip_if_nametoindex(ifname);
259 }
260
261 #endif
262 #endif /* !LWIP_COMPAT_SOCKETS */
263
264 #define IOCTL_CMD_CASE_HANDLER() do { \
265 err_t err; \
266 struct lwip_ioctl_apimsg msg; \
267 msg.sock = sock; \
268 msg.cmd = cmd; \
269 msg.argp = argp; \
270 \
271 err = tcpip_api_call(lwip_do_ioctl_impl, &msg.call); \
272 if (err != ENOSYS) { \
273 sock_set_errno(sock, err); \
274 done_socket(sock); \
275 return -(err != ERR_OK); \
276 } \
277 } while (0)
278
279 struct lwip_ioctl_apimsg {
280 struct tcpip_api_call_data call;
281 struct lwip_sock *sock;
282 long cmd;
283 void *argp;
284 };
285
286 static err_t lwip_do_ioctl_impl(struct tcpip_api_call_data *call);
287
288 #include "../api/sockets.c"
289
lwip_ioctl_internal_SIOCGIFCONF(struct ifreq * ifr)290 static u8_t lwip_ioctl_internal_SIOCGIFCONF(struct ifreq *ifr)
291 {
292 struct ifconf *ifc = NULL;
293 struct netif *netif = NULL;
294 struct ifreq ifreq;
295 struct sockaddr_in *sock_in = NULL;
296 int pos;
297 int len;
298 int ret;
299
300 /* Format the caller's buffer. */
301 ifc = (struct ifconf *)ifr;
302 len = ifc->ifc_len;
303
304 /* Loop over the interfaces, and write an info block for each. */
305 pos = 0;
306 for (netif = netif_list; netif != NULL; netif = netif->next) {
307 if (ifc->ifc_buf == NULL) {
308 pos = (pos + (int)sizeof(struct ifreq));
309 continue;
310 }
311
312 if (len < (int)sizeof(ifreq)) {
313 break;
314 }
315 (void)memset_s(&ifreq, sizeof(struct ifreq), 0, sizeof(struct ifreq));
316 if (netif->link_layer_type == LOOPBACK_IF) {
317 ret = snprintf_s(ifreq.ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%.2s", netif->name);
318 if ((ret <= 0) || (ret >= IFNAMSIZ)) {
319 LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed."));
320 return ENOBUFS;
321 }
322 } else {
323 ret = snprintf_s(ifreq.ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%s", netif_get_name(netif));
324 if ((ret <= 0) || (ret >= IFNAMSIZ)) {
325 LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed."));
326 return ENOBUFS;
327 }
328 }
329
330 sock_in = (struct sockaddr_in *)&ifreq.ifr_addr;
331 sock_in->sin_family = AF_INET;
332 sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr;
333 if (memcpy_s(ifc->ifc_buf + pos, sizeof(struct ifreq), &ifreq, sizeof(struct ifreq)) != EOK) {
334 return ENOBUFS;
335 }
336 pos = pos + (int)sizeof(struct ifreq);
337 len = len - (int)sizeof(struct ifreq);
338 }
339
340 ifc->ifc_len = pos;
341
342 return 0;
343 }
344
lwip_ioctl_internal_SIOCGIFADDR(struct ifreq * ifr)345 static u8_t lwip_ioctl_internal_SIOCGIFADDR(struct ifreq *ifr)
346 {
347 struct netif *netif = NULL;
348 struct sockaddr_in *sock_in = NULL;
349
350 /* get netif ipaddr */
351 netif = netif_find(ifr->ifr_name);
352 if (netif == NULL) {
353 return ENODEV;
354 } else {
355 sock_in = (struct sockaddr_in *)&ifr->ifr_addr;
356 sock_in->sin_family = AF_INET;
357 sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr;
358 return 0;
359 }
360 }
361
lwip_ioctl_internal_SIOCGIFNETMASK(struct ifreq * ifr)362 static u8_t lwip_ioctl_internal_SIOCGIFNETMASK(struct ifreq *ifr)
363 {
364 struct netif *netif = NULL;
365 struct sockaddr_in *sock_in = NULL;
366
367 /* get netif netmask */
368 netif = netif_find(ifr->ifr_name);
369 if (netif == NULL) {
370 return ENODEV;
371 } else {
372 sock_in = (struct sockaddr_in *)&ifr->ifr_netmask;
373 sock_in->sin_family = AF_INET;
374 sock_in->sin_addr.s_addr = ip_2_ip4(&netif->netmask)->addr;
375 return 0;
376 }
377 }
378
lwip_ioctl_internal_SIOCGIFHWADDR(struct ifreq * ifr)379 static u8_t lwip_ioctl_internal_SIOCGIFHWADDR(struct ifreq *ifr)
380 {
381 struct netif *netif = NULL;
382
383 /* get netif hw addr */
384 netif = netif_find(ifr->ifr_name);
385 if (netif == NULL) {
386 return ENODEV;
387 }
388 #if LWIP_HAVE_LOOPIF
389 else if (netif->link_layer_type == LOOPBACK_IF) {
390 return EPERM;
391 }
392 #endif /* LWIP_HAVE_LOOPIF */
393 else {
394 if (memcpy_s((void *)ifr->ifr_hwaddr.sa_data, sizeof(ifr->ifr_hwaddr.sa_data),
395 (void *)netif->hwaddr, netif->hwaddr_len) != EOK) {
396 return EINVAL;
397 }
398 return 0;
399 }
400 }
401
lwip_ioctl_internal_SIOCSIFFLAGS(struct ifreq * ifr)402 static u8_t lwip_ioctl_internal_SIOCSIFFLAGS(struct ifreq *ifr)
403 {
404 struct netif *netif = NULL;
405
406 /* set netif hw addr */
407 netif = netif_find(ifr->ifr_name);
408 if (netif == NULL) {
409 return ENODEV;
410 }
411 #if LWIP_HAVE_LOOPIF
412 else if (netif->link_layer_type == LOOPBACK_IF) {
413 return EPERM;
414 }
415 #endif /* LWIP_HAVE_LOOPIF */
416 else {
417 if (((unsigned short)ifr->ifr_flags & IFF_UP) && !(netif->flags & NETIF_FLAG_UP)) {
418 (void)netif_set_up(netif);
419 } else if (!((unsigned short)ifr->ifr_flags & IFF_UP) && (netif->flags & NETIF_FLAG_UP)) {
420 (void)netif_set_down(netif);
421 }
422 if (((unsigned short)ifr->ifr_flags & IFF_RUNNING) && !(netif->flags & NETIF_FLAG_LINK_UP)) {
423 (void)netif_set_link_up(netif);
424 } else if (!((unsigned short)ifr->ifr_flags & IFF_RUNNING) && (netif->flags & NETIF_FLAG_LINK_UP)) {
425 (void)netif_set_link_down(netif);
426 }
427
428 if ((unsigned short)ifr->ifr_flags & IFF_BROADCAST) {
429 netif->flags |= NETIF_FLAG_BROADCAST;
430 } else {
431 netif->flags = netif->flags & (~NETIF_FLAG_BROADCAST);
432 }
433 if ((unsigned short)ifr->ifr_flags & IFF_NOARP) {
434 netif->flags = (netif->flags & (~NETIF_FLAG_ETHARP));
435 } else {
436 netif->flags |= NETIF_FLAG_ETHARP;
437 }
438
439 if ((unsigned short)ifr->ifr_flags & IFF_MULTICAST) {
440 #if LWIP_IGMP
441 netif->flags |= NETIF_FLAG_IGMP;
442 #endif /* LWIP_IGMP */
443 #if LWIP_IPV6 && LWIP_IPV6_MLD
444 netif->flags |= NETIF_FLAG_MLD6;
445 #endif /* LWIP_IPV6_MLD */
446 } else {
447 #if LWIP_IGMP
448 netif->flags = (netif->flags & ~NETIF_FLAG_IGMP);
449 #endif /* LWIP_IGMP */
450 #if LWIP_IPV6 && LWIP_IPV6_MLD
451 netif->flags = (netif->flags & ~NETIF_FLAG_MLD6);
452 #endif /* LWIP_IPV6_MLD */
453 }
454
455 #if LWIP_DHCP
456 if ((unsigned short)ifr->ifr_flags & IFF_DYNAMIC) {
457 (void)dhcp_start(netif);
458 } else {
459 dhcp_stop(netif);
460 #if !LWIP_DHCP_SUBSTITUTE
461 dhcp_cleanup(netif);
462 #endif
463 }
464 #endif
465
466 #if LWIP_NETIF_PROMISC
467 if (((unsigned short)ifr->ifr_flags & IFF_PROMISC)) {
468 netif->flags |= NETIF_FLAG_PROMISC;
469 } else {
470 netif->flags &= ~NETIF_FLAG_PROMISC;
471 }
472 if (netif->drv_config) {
473 netif->drv_config(netif, IFF_PROMISC, !!((unsigned short)ifr->ifr_flags & IFF_PROMISC));
474 }
475 #endif /* LWIP_NETIF_PROMISC */
476 return 0;
477 }
478 }
479
lwip_ioctl_internal_SIOCGIFFLAGS(struct ifreq * ifr)480 static u8_t lwip_ioctl_internal_SIOCGIFFLAGS(struct ifreq *ifr)
481 {
482 struct netif *netif = NULL;
483
484 /* set netif hw addr */
485 netif = netif_find(ifr->ifr_name);
486 if (netif == NULL) {
487 return ENODEV;
488 } else {
489 if (netif->flags & NETIF_FLAG_UP) {
490 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_UP;
491 } else {
492 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_UP;
493 }
494 if (netif->flags & NETIF_FLAG_LINK_UP) {
495 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_RUNNING;
496 } else {
497 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_RUNNING;
498 }
499 if (netif->flags & NETIF_FLAG_BROADCAST) {
500 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_BROADCAST;
501 } else {
502 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_BROADCAST;
503 }
504 if (netif->flags & NETIF_FLAG_ETHARP) {
505 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_NOARP;
506 } else {
507 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_NOARP;
508 }
509
510 #if LWIP_IGMP || LWIP_IPV6_MLD
511 if (
512 #if LWIP_IGMP
513 (netif->flags & NETIF_FLAG_IGMP)
514 #endif /* LWIP_IGMP */
515 #if LWIP_IGMP && LWIP_IPV6_MLD
516 ||
517 #endif /* LWIP_IGMP && LWIP_IPV6_MLD */
518 #if LWIP_IPV6_MLD
519 (netif->flags & NETIF_FLAG_MLD6)
520 #endif /* LWIP_IPV6_MLD */
521 ) {
522 ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_MULTICAST);
523 } else {
524 ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_MULTICAST));
525 }
526 #endif /* LWIP_IGMP || LWIP_IPV6_MLD */
527
528 #if LWIP_DHCP
529 if (dhcp_supplied_address(netif)) {
530 ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_DYNAMIC);
531 } else {
532 ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_DYNAMIC));
533 }
534 #endif
535
536 #if LWIP_HAVE_LOOPIF
537 if (netif->link_layer_type == LOOPBACK_IF) {
538 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_LOOPBACK;
539 }
540 #endif
541
542 #if LWIP_NETIF_PROMISC
543 if (netif->flags & NETIF_FLAG_PROMISC) {
544 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) | IFF_PROMISC;
545 } else {
546 ifr->ifr_flags = ((unsigned short)(ifr->ifr_flags)) & ~IFF_PROMISC;
547 }
548 #endif /* LWIP_NETIF_PROMISC */
549
550 return 0;
551 }
552 }
553
lwip_ioctl_internal_SIOCGIFNAME(struct ifreq * ifr)554 static u8_t lwip_ioctl_internal_SIOCGIFNAME(struct ifreq *ifr)
555 {
556 struct netif *netif = NULL;
557 int ret;
558
559 for (netif = netif_list; netif != NULL; netif = netif->next) {
560 if (ifr->ifr_ifindex == netif_get_index(netif)) {
561 break;
562 }
563 }
564
565 if (netif == NULL) {
566 return ENODEV;
567 } else {
568 if (netif->link_layer_type == LOOPBACK_IF) {
569 ret = snprintf_s(ifr->ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%.2s", netif->name);
570 if ((ret <= 0) || (ret >= IFNAMSIZ)) {
571 return ENOBUFS;
572 }
573 } else {
574 ret = snprintf_s(ifr->ifr_name, IFNAMSIZ, (IFNAMSIZ - 1), "%s", netif_get_name(netif));
575 if ((ret <= 0) || (ret >= IFNAMSIZ)) {
576 return ENOBUFS;
577 }
578 }
579 return 0;
580 }
581 }
582
lwip_validate_ifname(const char * name,u8_t * let_pos)583 static u8_t lwip_validate_ifname(const char *name, u8_t *let_pos)
584 {
585 unsigned short num_pos = 0;
586 unsigned short letter_pos = 0;
587 unsigned short pos = 0;
588 u8_t have_num = 0;
589
590 /* if the first position of variable name is not letter, such as '6eth2' */
591 if (!((*name >= 'a' && *name <= 'z') || (*name >= 'A' && *name <= 'Z'))) {
592 return 0;
593 }
594
595 /* check if the position of letter is bigger than the the position of digital */
596 while (*name != '\0') {
597 if ((*name >= '0') && (*name <= '9')) {
598 num_pos = pos;
599 have_num = 1;
600 } else if (((*name >= 'a') && (*name <= 'z')) || ((*name >= 'A') && (*name <= 'Z'))) {
601 letter_pos = pos;
602 if (have_num != 0) {
603 return 0;
604 }
605 } else {
606 return 0;
607 }
608 pos++;
609 name++;
610 }
611
612 /* for the speacil case as all position of variable name is letter, such as 'ethabc' */
613 if (num_pos == 0) {
614 return 0;
615 }
616
617 /* cheak if the digital in the variable name is bigger than 255, such as 'eth266' */
618 if (atoi(name - (pos - letter_pos - 1)) > 255) {
619 return 0;
620 }
621
622 *let_pos = (u8_t)letter_pos;
623
624 return 1;
625 }
626
lwip_ioctl_internal_SIOCSIFNAME(struct ifreq * ifr)627 static u8_t lwip_ioctl_internal_SIOCSIFNAME(struct ifreq *ifr)
628 {
629 struct netif *netif = NULL;
630 u8_t letter_pos = 0;
631
632 netif = netif_find(ifr->ifr_name);
633 if (netif == NULL) {
634 return ENODEV;
635 } else if (netif->link_layer_type == LOOPBACK_IF) {
636 return EPERM;
637 } else if ((netif->flags & IFF_UP) != 0) {
638 return EBUSY;
639 } else {
640 if (strncmp(ifr->ifr_name, ifr->ifr_newname, IFNAMSIZ) == 0) {
641 /* not change */
642 return 0;
643 }
644
645 ifr->ifr_newname[IFNAMSIZ - 1] = '\0';
646 if ((lwip_validate_ifname(ifr->ifr_newname, &letter_pos) == 0) || (strlen(ifr->ifr_newname) > (IFNAMSIZ - 1))) {
647 return EINVAL;
648 }
649
650 if (strncpy_s(netif->full_name, sizeof(netif->full_name), ifr->ifr_newname, strlen(ifr->ifr_newname)) != EOK) {
651 return EINVAL;
652 }
653 }
654
655 return 0;
656 }
657
lwip_ioctl_internal_SIOCGIFINDEX(struct ifreq * ifr)658 static u8_t lwip_ioctl_internal_SIOCGIFINDEX(struct ifreq *ifr)
659 {
660 struct netif *netif = NULL;
661
662 netif = netif_find(ifr->ifr_name);
663 if (netif == NULL) {
664 return ENODEV;
665 } else {
666 ifr->ifr_ifindex = netif_get_index(netif);
667 return 0;
668 }
669 }
670
lwip_ioctl_internal_SIOCGIFMTU(struct ifreq * ifr)671 static u8_t lwip_ioctl_internal_SIOCGIFMTU(struct ifreq *ifr)
672 {
673 struct netif *netif = NULL;
674
675 /* get netif hw addr */
676 netif = netif_find(ifr->ifr_name);
677 if (netif == NULL) {
678 return ENODEV;
679 } else {
680 ifr->ifr_mtu = netif->mtu;
681 return 0;
682 }
683 }
684
lwip_ioctl_internal_SIOCGIFBRDADDR(struct ifreq * ifr)685 static u8_t lwip_ioctl_internal_SIOCGIFBRDADDR(struct ifreq *ifr)
686 {
687 struct netif *netif = NULL;
688 struct sockaddr_in *sock_in = NULL;
689
690 /* get netif subnet broadcast addr */
691 netif = netif_find(ifr->ifr_name);
692 if (netif == NULL) {
693 return ENODEV;
694 }
695 if (ip4_addr_isany_val(*(ip_2_ip4(&netif->netmask)))) {
696 return ENXIO;
697 }
698 sock_in = (struct sockaddr_in *)&ifr->ifr_addr;
699 sock_in->sin_family = AF_INET;
700 sock_in->sin_addr.s_addr = (ip_2_ip4(&((netif)->ip_addr))->addr | ~(ip_2_ip4(&netif->netmask)->addr));
701 return 0;
702 }
703
lwip_ioctl_impl(const struct lwip_sock * sock,long cmd,void * argp)704 static u8_t lwip_ioctl_impl(const struct lwip_sock *sock, long cmd, void *argp)
705 {
706 u8_t err = 0;
707 struct ifreq *ifr = (struct ifreq *)argp;
708 u8_t is_ipv6 = 0;
709
710 /* allow it only on IPv6 sockets... */
711 is_ipv6 = NETCONNTYPE_ISIPV6((unsigned int)(sock->conn->type));
712
713 switch ((u32_t)cmd) {
714 case SIOCGIFCONF:
715 if (is_ipv6 != 0) {
716 err = EINVAL;
717 } else {
718 err = lwip_ioctl_internal_SIOCGIFCONF(ifr);
719 }
720 break;
721 case SIOCGIFADDR:
722 if (is_ipv6 != 0) {
723 err = EINVAL;
724 } else {
725 err = lwip_ioctl_internal_SIOCGIFADDR(ifr);
726 }
727 break;
728 case SIOCGIFNETMASK:
729 if (is_ipv6 != 0) {
730 err = EINVAL;
731 } else {
732 err = lwip_ioctl_internal_SIOCGIFNETMASK(ifr);
733 }
734 break;
735 case SIOCGIFHWADDR:
736 err = lwip_ioctl_internal_SIOCGIFHWADDR(ifr);
737 break;
738 case SIOCSIFFLAGS:
739 err = lwip_ioctl_internal_SIOCSIFFLAGS(ifr);
740 break;
741 case SIOCGIFFLAGS:
742 err = lwip_ioctl_internal_SIOCGIFFLAGS(ifr);
743 break;
744 case SIOCGIFNAME:
745 err = lwip_ioctl_internal_SIOCGIFNAME(ifr);
746 break;
747 case SIOCSIFNAME:
748 err = lwip_ioctl_internal_SIOCSIFNAME(ifr);
749 break;
750 case SIOCGIFINDEX:
751 err = lwip_ioctl_internal_SIOCGIFINDEX(ifr);
752 break;
753 case SIOCGIFMTU:
754 err = lwip_ioctl_internal_SIOCGIFMTU(ifr);
755 break;
756 case SIOCGIFBRDADDR:
757 if (is_ipv6 != 0) {
758 err = EINVAL;
759 } else {
760 err = lwip_ioctl_internal_SIOCGIFBRDADDR(ifr);
761 }
762 break;
763 default:
764 err = ENOSYS;
765 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(UNIMPL: 0x%lx)\n", cmd));
766 break;
767 }
768
769 return err;
770 }
771
lwip_do_ioctl_impl(struct tcpip_api_call_data * call)772 static err_t lwip_do_ioctl_impl(struct tcpip_api_call_data *call)
773 {
774 struct lwip_ioctl_apimsg *msg = (struct lwip_ioctl_apimsg *)(void *)call;
775 return lwip_ioctl_impl(msg->sock, msg->cmd, msg->argp);
776 }