• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "lwip/sockets.h"
33 #include "lwip/priv/tcpip_priv.h"
34 #include "lwip/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 }