xref: /f-stack/tools/libnetgraph/compat.c (revision 9bd490e8)
1 /*
2  * Copyright (C) 2017 THL A29 Limited, a Tencent company.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this
9  *   list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  *   this list of conditions and the following disclaimer in the documentation
12  *   and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  *
26  */
27 
28 
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <sys/sysproto.h>
32 #include <string.h>
33 
34 #include "ff_api.h"
35 #include "ff_ipc.h"
36 #include "netgraph.h"
37 
38 static int
39 ngctl(int cmd, void *data, size_t len)
40 {
41     struct ff_msg *msg, *retmsg = NULL;
42 
43     msg = ff_ipc_msg_alloc();
44     if (msg == NULL) {
45         errno = ENOMEM;
46         return -1;
47     }
48 
49     if (len > msg->buf_len) {
50         errno = EINVAL;
51         ff_ipc_msg_free(msg);
52         return -1;
53     }
54 
55     msg->msg_type = FF_NGCTL;
56     msg->ngctl.cmd = cmd;
57     msg->ngctl.data = msg->buf_addr;
58 
59     switch (cmd) {
60         case NGCTL_SOCKET:
61         case NGCTL_CLOSE:
62             memcpy(msg->ngctl.data, data, len);
63             break;
64         case NGCTL_BIND:
65         case NGCTL_CONNECT:
66         {
67             struct bind_args *src = (struct bind_args *)data;
68             struct bind_args *dst = (struct bind_args *)(msg->ngctl.data);
69             dst->s = src->s;
70             dst->name = (char *)msg->buf_addr + sizeof(struct bind_args);
71             dst->namelen = src->namelen;
72             memcpy(dst->name, src->name, src->namelen);
73             break;
74         }
75         case NGCTL_SEND:
76         {
77             struct sendto_args *src = (struct sendto_args *)data;
78             struct sendto_args *dst = (struct sendto_args *)(msg->ngctl.data);
79             dst->s = src->s;
80             dst->buf = (char *)msg->buf_addr + sizeof(struct sendto_args);
81             dst->len = src->len;
82             dst->flags = src->flags;
83             dst->to = dst->buf + src->len;
84             dst->tolen = src->tolen;
85             memcpy(dst->buf, src->buf, src->len);
86             memcpy(dst->to, src->to, src->tolen);
87             break;
88         }
89         case NGCTL_RECV:
90         {
91             struct recvfrom_args *src = (struct recvfrom_args *)data;
92             struct recvfrom_args *dst = (struct recvfrom_args *)(msg->ngctl.data);
93             dst->s = src->s;
94             dst->buf = msg->buf_addr + sizeof(struct recvfrom_args);
95             dst->len = src->len;
96             dst->flags = src->flags;
97             dst->from = (struct sockaddr *)dst->buf + src->len;
98             dst->fromlenaddr = (socklen_t *)dst->buf + src->len + *(src->fromlenaddr);
99             memcpy(dst->buf, src->buf, src->len);
100             memcpy(dst->from, src->from, *(src->fromlenaddr));
101             memcpy(dst->fromlenaddr, src->fromlenaddr, sizeof(socklen_t));
102             break;
103         }
104         default:
105             errno = EINVAL;
106             ff_ipc_msg_free(msg);
107             return -1;
108     }
109 
110     int ret = ff_ipc_send(msg);
111     if (ret < 0) {
112         errno = EPIPE;
113         ff_ipc_msg_free(msg);
114         return -1;
115     }
116 
117     do {
118         if (retmsg != NULL) {
119             ff_ipc_msg_free(retmsg);
120         }
121         ret = ff_ipc_recv(&retmsg);
122         if (ret < 0) {
123             errno = EPIPE;
124             ff_ipc_msg_free(msg);
125             return -1;
126         }
127     } while (msg != retmsg);
128 
129     if (retmsg->result != 0) {
130         ret = -1;
131         errno = retmsg->result;
132     } else {
133         ret = msg->ngctl.ret;
134 
135         if (cmd == NGCTL_RECV) {
136             struct recvfrom_args *dst = (struct recvfrom_args *)data;
137             struct recvfrom_args *src = (struct recvfrom_args *)(msg->ngctl.data);
138             memcpy(dst->buf, src->buf, src->len);
139             memcpy(dst->from, src->from, *(src->fromlenaddr));
140             memcpy(dst->fromlenaddr, src->fromlenaddr, sizeof(socklen_t));
141         }
142     }
143 
144     ff_ipc_msg_free(msg);
145 
146     return ret;
147 }
148 
149 int
150 ng_socket(int domain, int type, int protocol)
151 {
152     struct socket_args sa;
153     sa.domain = domain;
154     sa.type = type;
155     sa.protocol = protocol;
156 
157     return ngctl(NGCTL_SOCKET, (void *)&sa, sizeof(sa));
158 }
159 
160 int
161 ng_bind(int sockfd, const struct sockaddr *addr,
162     socklen_t addrlen)
163 {
164     size_t len;
165     struct bind_args ba;
166 
167     ba.s = sockfd;
168     ba.name = (char *)addr;
169     ba.namelen = addrlen;
170 
171     len = sizeof(ba) + addrlen;
172 
173     return ngctl(NGCTL_BIND, (void *)&ba, len);
174 }
175 
176 int
177 ng_connect(int sockfd, const struct sockaddr *addr,
178     socklen_t addrlen)
179 {
180     size_t len;
181     struct connect_args ca;
182 
183     ca.s = sockfd;
184     ca.name = (char *)addr;
185     ca.namelen = addrlen;
186 
187     len = sizeof(ca) + addrlen;
188 
189     return ngctl(NGCTL_CONNECT, (void *)&ca, len);
190 }
191 
192 ssize_t
193 ng_sendto(int sockfd, const void *buf, size_t len, int flags,
194     const struct sockaddr *dest_addr, socklen_t addrlen)
195 {
196     size_t datalen;
197 
198     struct sendto_args sa;
199     sa.s = sockfd;
200     sa.buf = (void *)buf;
201     sa.len = len;
202     sa.flags = flags;
203     sa.to = (char *)dest_addr;
204     sa.tolen = addrlen;
205 
206     datalen = sizeof(sa) + len + addrlen;
207     return ngctl(NGCTL_SEND, (void *)&sa, datalen);
208 }
209 
210 ssize_t
211 ng_recvfrom(int sockfd, void *buf, size_t len, int flags,
212     struct sockaddr *src_addr, socklen_t *addrlen)
213 {
214     size_t datalen;
215 
216     struct recvfrom_args ra;
217     ra.s = sockfd;
218     ra.buf = buf;
219     ra.len = len;
220     ra.flags = flags;
221     ra.from = src_addr;
222     ra.fromlenaddr = addrlen;
223 
224     datalen = sizeof(ra) + len + (*addrlen) + sizeof(socklen_t);
225     return ngctl(NGCTL_RECV, (void *)&ra, datalen);
226 }
227 
228 int
229 ng_close(int fd)
230 {
231     struct close_args ca;
232     ca.fd = fd;
233 
234     return ngctl(NGCTL_CLOSE, (void *)&ca, sizeof(ca));
235 }
236 
237