xref: /f-stack/tools/compat/ioctl.c (revision 2317ada5)
1df6ad731Slogwang /*
2*2317ada5Sfengbojiang  * Copyright (C) 2017-2021 THL A29 Limited, a Tencent company.
3df6ad731Slogwang  * All rights reserved.
4df6ad731Slogwang  *
5df6ad731Slogwang  * Redistribution and use in source and binary forms, with or without
6df6ad731Slogwang  * modification, are permitted provided that the following conditions are met:
7df6ad731Slogwang  *
8df6ad731Slogwang  * 1. Redistributions of source code must retain the above copyright notice, this
9df6ad731Slogwang  *   list of conditions and the following disclaimer.
10df6ad731Slogwang  * 2. Redistributions in binary form must reproduce the above copyright notice,
11df6ad731Slogwang  *   this list of conditions and the following disclaimer in the documentation
12df6ad731Slogwang  *   and/or other materials provided with the distribution.
13df6ad731Slogwang  *
14df6ad731Slogwang  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15df6ad731Slogwang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16df6ad731Slogwang  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17df6ad731Slogwang  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18df6ad731Slogwang  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19df6ad731Slogwang  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20df6ad731Slogwang  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21df6ad731Slogwang  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22df6ad731Slogwang  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23df6ad731Slogwang  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24df6ad731Slogwang  *
25df6ad731Slogwang  */
26df6ad731Slogwang 
27df6ad731Slogwang #include <string.h>
28df6ad731Slogwang #include <stdarg.h>
29127dd473Swhl739 #include <sys/socket.h>
30127dd473Swhl739 #include <sys/ioctl.h>
31df6ad731Slogwang #include "ff_ipc.h"
32df6ad731Slogwang 
33df6ad731Slogwang /*
34df6ad731Slogwang  * In general, we always call like this: ioctl(fd, com, data),
35df6ad731Slogwang  * but if there is a pointer in the data and the pointer points to
36df6ad731Slogwang  * a memory area, for example, data is struct ifreq, and it uses
37df6ad731Slogwang  * ifreq.ifr_ifru.ifru_data, we must copy the memory to msg->buf_addr,
38df6ad731Slogwang  * after this, it can be used to communicate with F-Stack process.
39df6ad731Slogwang  * Otherwise, an unknown error will occur.
40df6ad731Slogwang  *
41df6ad731Slogwang  * Two cases:
42df6ad731Slogwang  * 1.Normal, there is no need to copy memory: ioctl_va(fd, com, data, 0).
43df6ad731Slogwang  * 2.There is a memory need to be copied: ioctl_va(fd, com, data, 3, offset, cpy_mem, clen).
44df6ad731Slogwang  *     offset: the offset of cpy_mem relative to data struct.
45df6ad731Slogwang  *     cpy_mem: the memory address that need to be copied.
46df6ad731Slogwang  *     clen: the size of memory that the cpy_mem pointed to.
47df6ad731Slogwang  *
48df6ad731Slogwang  */
49df6ad731Slogwang int
ioctl_va(int fd,unsigned long com,void * data,int argc,...)50df6ad731Slogwang ioctl_va(int fd, unsigned long com, void *data, int argc, ...)
51df6ad731Slogwang {
52df6ad731Slogwang     struct ff_msg *msg, *retmsg = NULL;
53df6ad731Slogwang     unsigned size;
54df6ad731Slogwang     void *cpy_mem;
55df6ad731Slogwang     size_t offset, clen;
56cd4d3a58Sroot     int af = AF_INET;
57df6ad731Slogwang 
58143d7be7Sfengbojiang(姜凤波)     if (argc != 0 && argc != 3 && argc != 1) {
59df6ad731Slogwang         errno = EINVAL;
60df6ad731Slogwang         return -1;
61df6ad731Slogwang     }
62df6ad731Slogwang 
63df6ad731Slogwang     if (argc == 3) {
64df6ad731Slogwang         va_list ap;
65df6ad731Slogwang         va_start(ap, argc);
66df6ad731Slogwang         offset = va_arg(ap, size_t);
67df6ad731Slogwang         cpy_mem = va_arg(ap, void *);
68df6ad731Slogwang         clen = va_arg(ap, size_t);
69df6ad731Slogwang         va_end(ap);
70143d7be7Sfengbojiang(姜凤波)     } else if (argc == 1) {
71143d7be7Sfengbojiang(姜凤波)         va_list ap;
72143d7be7Sfengbojiang(姜凤波)         va_start(ap, argc);
73143d7be7Sfengbojiang(姜凤波)         af = va_arg(ap, int);
74143d7be7Sfengbojiang(姜凤波)         va_end(ap);
75df6ad731Slogwang     }
76df6ad731Slogwang 
77df6ad731Slogwang     if (com > 0xffffffff) {
78df6ad731Slogwang         printf("WARNING: ioctl sign-extension ioctl %lx\n", com);
79df6ad731Slogwang         com &= 0xffffffff;
80df6ad731Slogwang     }
81df6ad731Slogwang 
82df6ad731Slogwang     size = IOCPARM_LEN(com);
83df6ad731Slogwang     if ((size > IOCPARM_MAX) ||
84df6ad731Slogwang         ((com & (IOC_IN | IOC_OUT)) == 0) ||
85df6ad731Slogwang         (size == 0) ||
86df6ad731Slogwang         (com & IOC_VOID))
87df6ad731Slogwang         return (ENOTTY);
88df6ad731Slogwang 
89df6ad731Slogwang     msg = ff_ipc_msg_alloc();
90df6ad731Slogwang     if (msg == NULL) {
91df6ad731Slogwang         errno = ENOMEM;
92df6ad731Slogwang         return -1;
93df6ad731Slogwang     }
94df6ad731Slogwang 
95df6ad731Slogwang     if (size > msg->buf_len) {
961eaf0ac3Slogwang         errno = ENOMEM;
97df6ad731Slogwang         ff_ipc_msg_free(msg);
98df6ad731Slogwang         return -1;
99df6ad731Slogwang     }
100df6ad731Slogwang 
101143d7be7Sfengbojiang(姜凤波) #ifdef INET6
102143d7be7Sfengbojiang(姜凤波)     if (af == AF_INET6) {
103143d7be7Sfengbojiang(姜凤波)         msg->msg_type = FF_IOCTL6;
104143d7be7Sfengbojiang(姜凤波)     } else
105143d7be7Sfengbojiang(姜凤波) #endif
106143d7be7Sfengbojiang(姜凤波)     if (af == AF_INET)
107df6ad731Slogwang         msg->msg_type = FF_IOCTL;
108143d7be7Sfengbojiang(姜凤波)     else {
109143d7be7Sfengbojiang(姜凤波)         errno = EINVAL;
110cd4d3a58Sroot         ff_ipc_msg_free(msg);
111143d7be7Sfengbojiang(姜凤波)         return -1;
112143d7be7Sfengbojiang(姜凤波)     }
113143d7be7Sfengbojiang(姜凤波) 
114df6ad731Slogwang     msg->ioctl.cmd = com;
115df6ad731Slogwang     msg->ioctl.data = msg->buf_addr;
116df6ad731Slogwang     memcpy(msg->ioctl.data, data, size);
117df6ad731Slogwang     msg->buf_addr += size;
118df6ad731Slogwang 
119df6ad731Slogwang     if (argc == 3) {
120df6ad731Slogwang         if (size + clen > msg->buf_len) {
1211eaf0ac3Slogwang             errno = ENOMEM;
122df6ad731Slogwang             ff_ipc_msg_free(msg);
123df6ad731Slogwang             return -1;
124df6ad731Slogwang         }
125df6ad731Slogwang         char *ptr = (char *)(msg->ioctl.data) + offset;
126df6ad731Slogwang         char *buf_addr = msg->buf_addr;
127df6ad731Slogwang         memcpy(ptr, &buf_addr, sizeof(char *));
128df6ad731Slogwang         memcpy(buf_addr, cpy_mem, clen);
129df6ad731Slogwang     }
130df6ad731Slogwang 
131df6ad731Slogwang     int ret = ff_ipc_send(msg);
132df6ad731Slogwang     if (ret < 0) {
133df6ad731Slogwang         errno = EPIPE;
134df6ad731Slogwang         ff_ipc_msg_free(msg);
135df6ad731Slogwang         return -1;
136df6ad731Slogwang     }
137df6ad731Slogwang 
138df6ad731Slogwang     do {
139df6ad731Slogwang         if (retmsg != NULL) {
140df6ad731Slogwang             ff_ipc_msg_free(retmsg);
141df6ad731Slogwang         }
1426194fcd2Sfengbojiang(姜凤波)         ret = ff_ipc_recv(&retmsg, msg->msg_type);
143df6ad731Slogwang         if (ret < 0) {
144df6ad731Slogwang             errno = EPIPE;
145df6ad731Slogwang             return -1;
146df6ad731Slogwang         }
147df6ad731Slogwang     } while (msg != retmsg);
148df6ad731Slogwang 
149df6ad731Slogwang     if (retmsg->result == 0) {
150df6ad731Slogwang         ret = 0;
151df6ad731Slogwang 
152df6ad731Slogwang         if (com & IOC_OUT) {
153df6ad731Slogwang             memcpy(data, retmsg->ioctl.data, size);
154df6ad731Slogwang             if (argc == 3) {
155df6ad731Slogwang                 memcpy(cpy_mem, retmsg->buf_addr, clen);
156df6ad731Slogwang                 char *ptr = (char *)data + offset;
157df6ad731Slogwang                 memcpy(ptr, &cpy_mem, sizeof(void *));
158df6ad731Slogwang             }
159df6ad731Slogwang         }
160df6ad731Slogwang     } else {
161df6ad731Slogwang         ret = -1;
162df6ad731Slogwang         errno = retmsg->result;
163df6ad731Slogwang     }
164df6ad731Slogwang 
165df6ad731Slogwang     ff_ipc_msg_free(msg);
166df6ad731Slogwang 
167df6ad731Slogwang     return ret;
168df6ad731Slogwang }
169fa74a859Slogwang 
170