1 /*
2 * Inspired by opendp/dpdk-nginx's ans_module.c.
3 * License of opendp:
4 *
5 BSD LICENSE
6 Copyright(c) 2015-2017 Ansyun [email protected]. All rights reserved.
7 All rights reserved.
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
10 are met:
11
12 Redistributions of source code must retain the above copyright
13 notice, this list of conditions and the following disclaimer.
14 Redistributions in binary form must reproduce the above copyright
15 notice, this list of conditions and the following disclaimer in
16 the documentation and/or other materials provided with the
17 distribution.
18 Neither the name of Ansyun [email protected] nor the names of its
19 contributors may be used to endorse or promote products derived
20 from this software without specific prior written permission.
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 Author: JiaKai ([email protected]) and Bluestar ([email protected])
33 */
34
35 /*
36 * Copyright (C) 2017-2021 THL A29 Limited, a Tencent company.
37 * All rights reserved.
38 *
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions are met:
41 *
42 * 1. Redistributions of source code must retain the above copyright notice, this
43 * list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright notice,
45 * this list of conditions and the following disclaimer in the documentation
46 * and/or other materials provided with the distribution.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
51 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
52 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
53 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
54 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
55 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
56 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
57 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58 *
59 */
60
61 #include <stdio.h>
62 #include <stdint.h>
63 #include <string.h>
64 #include <stdlib.h>
65 #include <stdarg.h>
66 #include <errno.h>
67 #include <netinet/in.h>
68 #include <assert.h>
69 #include <unistd.h>
70 #include <sys/types.h>
71 #include <sys/socket.h>
72 #include <arpa/inet.h>
73 #include <sys/time.h>
74 #include <sys/select.h>
75
76 typedef unsigned short u_short;
77 typedef unsigned int u_int;
78 #include "ff_api.h"
79
80 #define _GNU_SOURCE
81 #define __USE_GNU
82
83 #include <unistd.h>
84 //#include <sched.h>
85 #include <sys/types.h>
86 //#include <fcntl.h>
87 #include <sys/syscall.h>
88 #include <dlfcn.h>
89
90 #pragma GCC diagnostic push
91 #pragma GCC diagnostic ignored "-Wpedantic"
92
93 #ifndef likely
94 #define likely(x) __builtin_expect((x),1)
95 #endif
96
97 #ifndef unlikely
98 #define unlikely(x) __builtin_expect((x),0)
99 #endif
100
101 #define INIT_FUNCTION(func) \
102 real_##func = dlsym(RTLD_NEXT, #func); \
103 assert(real_##func)
104
105 static int inited = 0;
106
107 static int (*real_close)(int);
108 static int (*real_socket)(int, int, int);
109 static int (*real_bind)(int, const struct sockaddr*, socklen_t);
110 static int (*real_connect)(int, const struct sockaddr*, socklen_t);
111 static int (*real_listen)(int, int);
112 static int (*real_setsockopt)(int, int, int, const void *, socklen_t);
113
114 static int (*real_accept)(int, struct sockaddr *, socklen_t *);
115 static int (*real_accept4)(int, struct sockaddr *, socklen_t *, int);
116 static ssize_t (*real_recv)(int, void *, size_t, int);
117 static ssize_t (*real_send)(int, const void *, size_t, int);
118
119 static ssize_t (*real_writev)(int, const struct iovec *, int);
120 static ssize_t (*real_write)(int, const void *, size_t );
121 static ssize_t (*real_read)(int, void *, size_t );
122 static ssize_t (*real_readv)(int, const struct iovec *, int);
123
124 static int (*real_ioctl)(int, int, void *);
125 static int (*real_fcntl)(int, int, void *);
126
127 static int (*real_select) (int, fd_set *, fd_set *, fd_set *, struct timeval *);
128
129
ff_mod_init()130 void ff_mod_init() {
131 INIT_FUNCTION(socket);
132 INIT_FUNCTION(bind);
133 INIT_FUNCTION(connect);
134 INIT_FUNCTION(close);
135 INIT_FUNCTION(listen);
136 INIT_FUNCTION(setsockopt);
137 INIT_FUNCTION(accept);
138 INIT_FUNCTION(accept4);
139 INIT_FUNCTION(recv);
140 INIT_FUNCTION(send);
141 INIT_FUNCTION(writev);
142 INIT_FUNCTION(write);
143 INIT_FUNCTION(read);
144 INIT_FUNCTION(readv);
145
146 INIT_FUNCTION(ioctl);
147 INIT_FUNCTION(fcntl);
148 INIT_FUNCTION(select);
149
150 inited = 1;
151 }
152
153 int
socket(int domain,int type,int protocol)154 socket(int domain, int type, int protocol)
155 {
156 int rc;
157
158 if (unlikely(inited == 0)) {
159 INIT_FUNCTION(socket);
160 return real_socket(domain, type, protocol);
161 }
162
163 if ((AF_INET != domain) || (SOCK_STREAM != type && SOCK_DGRAM != type)) {
164 rc = real_socket(domain, type, protocol);
165 return rc;
166 }
167
168 rc = ff_socket(domain, type, protocol);
169
170 return rc;
171 }
172
173 int
bind(int sockfd,const struct sockaddr * addr,socklen_t addrlen)174 bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
175 {
176 if (unlikely(inited == 0)) {
177 INIT_FUNCTION(bind);
178 return real_bind(sockfd, addr, addrlen);
179 }
180
181 if (ff_fdisused(sockfd)) {
182 return ff_bind(sockfd, (struct linux_sockaddr *)addr, addrlen);
183 } else {
184 return real_bind(sockfd, addr, addrlen);
185 }
186 }
187
188 int
connect(int sockfd,const struct sockaddr * addr,socklen_t addrlen)189 connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
190 {
191 if (unlikely(inited == 0)) {
192 INIT_FUNCTION(connect);
193 return real_connect(sockfd, addr, addrlen);
194 }
195
196 if (ff_fdisused(sockfd)) {
197 return ff_connect(sockfd, (struct linux_sockaddr *)addr, addrlen);
198 } else {
199 return real_connect(sockfd, addr, addrlen);
200 }
201 }
202
203 ssize_t
send(int sockfd,const void * buf,size_t len,int flags)204 send(int sockfd, const void *buf, size_t len, int flags)
205 {
206 if (unlikely(inited == 0)) {
207 INIT_FUNCTION(send);
208 return real_send(sockfd, buf, len, flags);
209 }
210
211 if (ff_fdisused(sockfd)) {
212 return ff_send(sockfd, buf, len, flags);
213 } else {
214 return real_send(sockfd, buf, len, flags);
215 }
216 }
217
218 ssize_t
recv(int sockfd,void * buf,size_t len,int flags)219 recv(int sockfd, void *buf, size_t len, int flags)
220 {
221 if (unlikely(inited == 0)) {
222 INIT_FUNCTION(recv);
223 return real_recv(sockfd, buf, len, flags);
224 }
225
226 if (ff_fdisused(sockfd)) {
227 return ff_recv(sockfd, buf, len, flags);
228 } else {
229 return real_recv(sockfd, buf, len, flags);
230 }
231 }
232
233 int
listen(int sockfd,int backlog)234 listen(int sockfd, int backlog)
235 {
236 if (unlikely(inited == 0)) {
237 INIT_FUNCTION(listen);
238 return real_listen(sockfd, backlog);
239 }
240
241 if (ff_fdisused(sockfd)) {
242 return ff_listen(sockfd, backlog);
243 } else {
244 return real_listen(sockfd, backlog);
245 }
246 }
247
248 int
setsockopt(int sockfd,int level,int optname,const void * optval,socklen_t optlen)249 setsockopt (int sockfd, int level, int optname,
250 const void *optval, socklen_t optlen)
251 {
252 if (unlikely(inited == 0)) {
253 INIT_FUNCTION(setsockopt);
254 return real_setsockopt(sockfd, level, optname, optval, optlen);
255 }
256
257 if (ff_fdisused(sockfd)) {
258 return ff_setsockopt(sockfd, level, optname, optval, optlen);
259 } else {
260 return real_setsockopt(sockfd, level, optname, optval, optlen);
261 }
262 }
263
264 int
accept(int sockfd,struct sockaddr * addr,socklen_t * addrlen)265 accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
266 {
267 if (unlikely(inited == 0)) {
268 INIT_FUNCTION(accept);
269 return real_accept(sockfd, addr, addrlen);
270 }
271
272 if (ff_fdisused(sockfd)) {
273 return ff_accept(sockfd, (struct linux_sockaddr *)addr, addrlen);
274 } else {
275 return real_accept(sockfd, addr, addrlen);
276 }
277 }
278
279 int
accept4(int sockfd,struct sockaddr * addr,socklen_t * addrlen,int flags)280 accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
281 {
282 if (unlikely(inited == 0)) {
283 INIT_FUNCTION(accept4);
284 return real_accept4(sockfd, addr, addrlen, flags);
285 }
286
287 if (ff_fdisused(sockfd)) {
288 return ff_accept(sockfd, (struct linux_sockaddr *)addr, addrlen);
289 } else {
290 return real_accept4(sockfd, addr, addrlen, flags);
291 }
292 }
293
294 int
close(int sockfd)295 close(int sockfd)
296 {
297 if (unlikely(inited == 0)) {
298 INIT_FUNCTION(close);
299 return real_close(sockfd);
300 }
301
302 if (ff_fdisused(sockfd)) {
303 return ff_close(sockfd);
304 } else {
305 return real_close(sockfd);
306 }
307 }
308
write(int sockfd,const void * buf,size_t count)309 ssize_t write(int sockfd, const void *buf, size_t count)
310 {
311 if (unlikely(inited == 0)) {
312 INIT_FUNCTION(write);
313 return real_write(sockfd, buf, count);
314 }
315
316 if (ff_fdisused(sockfd)) {
317 return ff_write(sockfd, buf, count);
318 } else {
319 return real_write(sockfd, buf, count);
320 }
321 }
322
323 ssize_t
writev(int sockfd,const struct iovec * iov,int iovcnt)324 writev(int sockfd, const struct iovec *iov, int iovcnt)
325 {
326 if (unlikely(inited == 0)) {
327 INIT_FUNCTION(writev);
328 return real_writev(sockfd, iov, iovcnt);
329 }
330
331 if (ff_fdisused(sockfd)) {
332 return ff_writev(sockfd, iov, iovcnt);
333 } else {
334 return real_writev(sockfd, iov, iovcnt);
335 }
336 }
337
read(int sockfd,void * buf,size_t count)338 ssize_t read(int sockfd, void *buf, size_t count)
339 {
340 if (unlikely(inited == 0)) {
341 INIT_FUNCTION(read);
342 return real_read(sockfd, buf, count);
343 }
344
345 if (ff_fdisused(sockfd)) {
346 return ff_read(sockfd, buf, count);
347 } else {
348 return real_read(sockfd, buf, count);
349 }
350 }
351
352 ssize_t
readv(int sockfd,const struct iovec * iov,int iovcnt)353 readv(int sockfd, const struct iovec *iov, int iovcnt)
354 {
355 if (unlikely(inited == 0)) {
356 INIT_FUNCTION(readv);
357 return real_readv(sockfd, iov, iovcnt);
358 }
359
360 if (ff_fdisused(sockfd)) {
361 return ff_readv(sockfd, iov, iovcnt);
362 } else {
363 return real_readv(sockfd, iov, iovcnt);
364 }
365 }
366
367 int
ioctl(int sockfd,int request,void * p)368 ioctl(int sockfd, int request, void *p)
369 {
370 if (unlikely(inited == 0)) {
371 INIT_FUNCTION(ioctl);
372 return real_ioctl(sockfd, request, p);
373 }
374
375 if (ff_fdisused(sockfd)) {
376 return ff_ioctl(sockfd, request, p);
377 } else {
378 return real_ioctl(sockfd, request, p);
379 }
380 }
381
fcntl(int sockfd,int cmd,void * p)382 int fcntl(int sockfd, int cmd, void *p)
383 {
384 if (unlikely(inited == 0)) {
385 INIT_FUNCTION(fcntl);
386 return real_fcntl(sockfd, cmd, p);
387 }
388
389 if (ff_fdisused(sockfd)) {
390 return ff_fcntl(sockfd, cmd, p);
391 } else {
392 return real_fcntl(sockfd, cmd, p);
393 }
394 }
395
396 int
select(int nfds,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout)397 select(int nfds, fd_set *readfds, fd_set *writefds,
398 fd_set *exceptfds, struct timeval *timeout)
399 {
400 if (unlikely(inited == 0)) {
401 INIT_FUNCTION(select);
402 return real_select(nfds, readfds, writefds, exceptfds, timeout);
403 }
404
405 if (ff_fdisused(nfds)) {
406 struct timeval tv;
407 tv.tv_sec = 0;
408 tv.tv_usec = 0;
409 return ff_select(nfds, readfds, writefds, exceptfds, &tv);
410 } else {
411 return real_select(nfds, readfds, writefds, exceptfds, timeout);
412 }
413 }
414
415 #pragma GCC diagnostic pop
416
417