xref: /f-stack/app/micro_thread/mt_sys_hook.cpp (revision e7741141)
1 
2 /**
3  * Tencent is pleased to support the open source community by making MSEC available.
4  *
5  * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
6  *
7  * Licensed under the GNU General Public License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License. You may
9  * obtain a copy of the License at
10  *
11  *     https://opensource.org/licenses/GPL-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software distributed under the
14  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
15  * either express or implied. See the License for the specific language governing permissions
16  * and limitations under the License.
17  */
18 
19 
20 /**
21  *  @filename mt_sys_hook.cpp
22  *  @info  ΢�߳�hookϵͳapi, �Բ��ö�����������, תͬ��Ϊ�첽��
23  *         ֻhook socket��ص�API, HOOK ����, �ο�pth��libcoʵ��
24  */
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <stdint.h>
29 #include <unistd.h>
30 #include <errno.h>
31 #include <assert.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <stdarg.h>
35 
36 #include "micro_thread.h"
37 #include "mt_sys_hook.h"
38 #include "ff_hook.h"
39 
40 using namespace NS_MICRO_THREAD;
41 
42 
43 #define MT_HOOK_MAX_FD      65535*2
44 #define MT_FD_FLG_INUSE     0x1
45 #define MT_FD_FLG_UNBLOCK   0x2
46 
47 
48 /**
49  * @brief ÿsockt����һ������ṹ, ����Ƿ���ҪHOOK, ��ʱʱ���
50  */
51 typedef struct socket_hook_info
52 {
53     int     sock_flag;      // �Ƿ�ʹ��HOOK, �Ƿ��û�����UNBLOCK
54     int     read_timeout;   // socket��ȡ��ʱʱ��, ms��λ
55     int     write_timeout;  // socketд�볬ʱʱ��, ms��λ
56 }MtHookFd;
57 
58 MtSyscallFuncTab       g_mt_syscall_tab;            // ȫ�ַ��ű�
59 int                    g_mt_hook_flag;              // ȫ�ֿ��Ʊ��
60 int                    g_ff_hook_flag;              // ȫ�ֿ��Ʊ��
61 static MtHookFd        g_mt_hook_fd_tab[MT_HOOK_MAX_FD];   // ȫ��fd����
62 
63 /**
64  * @brief �ڲ��ӿ�, ��ȡhook fd��ص���Ϣ, socket Ĭ��hook, open Ĭ��no hook
65  */
66 MtHookFd* mt_hook_find_fd(int fd)
67 {
68     if ((fd < 0) || (fd >= MT_HOOK_MAX_FD)) {
69         return NULL;
70     }
71 
72     MtHookFd* fd_info =  &g_mt_hook_fd_tab[fd];
73     if (!(fd_info->sock_flag & MT_FD_FLG_INUSE)) {
74         return NULL;
75     } else {
76         return fd_info;
77     }
78 }
79 
80 /**
81  * @brief �ڲ��ӿ�, ����socket����hook, ֻ����socket, �������ļ�IO
82  */
83 void mt_hook_new_fd(int fd)
84 {
85     if ((fd < 0) || (fd >= MT_HOOK_MAX_FD)) {
86         return;
87     }
88 
89     MtHookFd* fd_info       = &g_mt_hook_fd_tab[fd];
90     fd_info->sock_flag      = MT_FD_FLG_INUSE;
91     fd_info->read_timeout   = 500;
92     fd_info->write_timeout  = 500;
93 }
94 
95 /**
96  * @brief �ڲ��ӿ�, �ر�hook socket
97  */
98 void mt_hook_free_fd(int fd)
99 {
100     if ((fd < 0) || (fd >= MT_HOOK_MAX_FD)) {
101         return;
102     }
103 
104     MtHookFd* fd_info       = &g_mt_hook_fd_tab[fd];
105     fd_info->sock_flag      = 0;
106     fd_info->read_timeout   = 0;
107     fd_info->write_timeout  = 0;
108 }
109 
110 /**
111  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi, �ػ��û����õķ��������
112  */
113 #ifdef __cplusplus
114 extern "C" {
115 #endif
116 int ioctl(int fd, unsigned long cmd, ...)
117 {
118     va_list ap;
119     va_start(ap, cmd);
120     void* arg = va_arg(ap, void *);
121     va_end(ap);
122 
123     mt_hook_syscall(ioctl);
124     MtHookFd* hook_fd = mt_hook_find_fd(fd);
125     if (!mt_hook_active() || !hook_fd || !ff_hook_active())
126     {
127         return ff_hook_ioctl(fd, cmd, arg);
128     }
129 
130     if (cmd == FIONBIO)
131     {
132         int flags =  (arg != NULL) ? *((int*)arg) : 0;
133         if (flags != 0) {
134             hook_fd->sock_flag |= MT_FD_FLG_UNBLOCK;
135         }
136     }
137 
138 	return ff_hook_ioctl(fd, cmd, arg);
139 }
140 
141 /**
142  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi, Ĭ������unblock
143  */
144 int socket(int domain, int type, int protocol)
145 {
146     mt_hook_syscall(socket);
147 
148     if (!ff_hook_active())
149     {
150         return mt_real_func(socket)(domain, type, protocol);
151     }
152 
153     int fd = ff_hook_socket(domain, type, protocol);
154     if (fd < 0)
155     {
156         return fd;
157     }
158 
159     mt_hook_new_fd(fd);
160 
161     mt_hook_syscall(ioctl);
162 	int nb = 1;
163 	ff_hook_ioctl(fd, FIONBIO, &nb);
164 
165     return fd;
166 }
167 
168 /**
169  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi
170  */
171 int close(int fd)
172 {
173     mt_hook_syscall(close);
174     if (!ff_hook_active())
175     {
176         return mt_real_func(close)(fd);
177     }
178 
179     mt_hook_free_fd(fd);
180 	return ff_hook_close(fd);
181 }
182 
183 
184 /**
185  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi
186  */
187 int connect(int fd, const struct sockaddr *address, socklen_t address_len)
188 {
189     mt_hook_syscall(connect);
190     MtHookFd* hook_fd = mt_hook_find_fd(fd);
191     if (!mt_hook_active() || !hook_fd || !ff_hook_active())
192     {
193         return mt_real_func(connect)(fd, address, address_len);
194     }
195 
196     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
197     {
198         return ff_hook_connect(fd, address, address_len);
199     }
200 
201     return MtFrame::connect(fd, address, (int)address_len, hook_fd->write_timeout);
202 }
203 
204 /**
205  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi, �û��Ѿ�����unblock, ����
206  */
207 ssize_t read(int fd, void *buf, size_t nbyte)
208 {
209     mt_hook_syscall(read);
210     MtHookFd* hook_fd = mt_hook_find_fd(fd);
211     if (!mt_hook_active() || !hook_fd || !ff_hook_active())
212     {
213         return mt_real_func(read)(fd, buf, nbyte);
214     }
215 
216     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
217     {
218         return ff_hook_read(fd, buf, nbyte);
219     }
220 
221     return MtFrame::read(fd, buf, nbyte, hook_fd->read_timeout);
222 }
223 
224 /**
225  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi, �û��Ѿ�����unblock, ����
226  */
227 ssize_t write(int fd, const void *buf, size_t nbyte)
228 {
229     mt_hook_syscall(write);
230     MtHookFd* hook_fd = mt_hook_find_fd(fd);
231     if (!mt_hook_active() || !hook_fd || !ff_hook_active())
232     {
233         return mt_real_func(write)(fd, buf, nbyte);
234     }
235 
236     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
237     {
238         return ff_hook_write(fd, buf, nbyte);
239     }
240 
241     return MtFrame::write(fd, buf, nbyte, hook_fd->write_timeout);
242 }
243 
244 /**
245  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi, �û��Ѿ�����unblock, ����
246  */
247 ssize_t sendto(int fd, const void *message, size_t length, int flags,
248                const struct sockaddr *dest_addr, socklen_t dest_len)
249 {
250     mt_hook_syscall(sendto);
251     MtHookFd* hook_fd = mt_hook_find_fd(fd);
252     if (!mt_hook_active() || !hook_fd || !ff_hook_active())
253     {
254         return mt_real_func(sendto)(fd, message, length, flags, dest_addr, dest_len);
255     }
256 
257     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
258     {
259         return ff_hook_sendto(fd, message, length, flags, dest_addr, dest_len);
260     }
261 
262     return MtFrame::sendto(fd, message, (int)length, flags,
263                            dest_addr, dest_len, hook_fd->write_timeout);
264 }
265 
266 /**
267  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi, �û��Ѿ�����unblock, ����
268  */
269 ssize_t recvfrom(int fd, void *buffer, size_t length, int flags,
270                   struct sockaddr *address, socklen_t *address_len)
271 {
272     mt_hook_syscall(recvfrom);
273     MtHookFd* hook_fd = mt_hook_find_fd(fd);
274     if (!mt_hook_active() || !hook_fd || !ff_hook_active())
275     {
276         return mt_real_func(recvfrom)(fd, buffer, length, flags, address, address_len);
277     }
278 
279     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
280     {
281         return ff_hook_recvfrom(fd, buffer, length, flags, address, address_len);
282     }
283 
284     return MtFrame::recvfrom(fd, buffer, length, flags, address, address_len, hook_fd->read_timeout);
285 
286 }
287 
288 /**
289  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi, �û��Ѿ�����unblock, ����
290  */
291 ssize_t recv(int fd, void *buffer, size_t length, int flags)
292 {
293     mt_hook_syscall(recv);
294     MtHookFd* hook_fd = mt_hook_find_fd(fd);
295     if (!mt_hook_active() || !hook_fd || !ff_hook_active())
296     {
297         return mt_real_func(recv)(fd, buffer, length, flags);
298     }
299 
300     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
301     {
302         return ff_hook_recv(fd, buffer, length, flags);
303     }
304 
305     return MtFrame::recv(fd, buffer, length, flags, hook_fd->read_timeout);
306 }
307 
308 /**
309  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi, �û��Ѿ�����unblock, ����
310  */
311 ssize_t send(int fd, const void *buf, size_t nbyte, int flags)
312 {
313     mt_hook_syscall(send);
314     MtHookFd* hook_fd = mt_hook_find_fd(fd);
315     if (!mt_hook_active() || !hook_fd || !ff_hook_active())
316     {
317         return mt_real_func(send)(fd, buf, nbyte, flags);
318     }
319 
320     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
321     {
322         return ff_hook_send(fd, buf, nbyte, flags);
323     }
324 
325     return MtFrame::send(fd, buf, nbyte, flags, hook_fd->write_timeout);
326 }
327 
328 
329 /**
330  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi, �ػ��û����õij�ʱʱ����Ϣ
331  */
332 int setsockopt(int fd, int level, int option_name, const void *option_value, socklen_t option_len)
333 {
334     mt_hook_syscall(setsockopt);
335     MtHookFd* hook_fd = mt_hook_find_fd(fd);
336     if (!mt_hook_active() || !hook_fd || !ff_hook_active())
337     {
338         return mt_real_func(setsockopt)(fd, level, option_name, option_value, option_len);
339     }
340 
341     if (SOL_SOCKET == level)
342     {
343         struct timeval *val = (struct timeval*)option_value;
344         if (SO_RCVTIMEO == option_name)
345         {
346             hook_fd->read_timeout = val->tv_sec * 1000 + val->tv_usec / 1000;
347         }
348         else if (SO_SNDTIMEO == option_name)
349         {
350             hook_fd->write_timeout = val->tv_sec * 1000 + val->tv_usec / 1000;
351         }
352     }
353 
354 	return ff_hook_setsockopt(fd, level, option_name, option_value, option_len);
355 }
356 
357 
358 
359 /**
360  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi, �ػ��û����õķ��������
361  */
362 int fcntl(int fd, int cmd, ...)
363 {
364     va_list ap;
365     va_start(ap, cmd);
366     void* arg = va_arg(ap, void *);
367     va_end(ap);
368 
369     mt_hook_syscall(fcntl);
370     MtHookFd* hook_fd = mt_hook_find_fd(fd);
371     if (!mt_hook_active() || !hook_fd || !ff_hook_active())
372     {
373         return mt_real_func(fcntl)(fd, cmd, arg);
374     }
375 
376     if (cmd == F_SETFL)
377     {
378         va_start(ap, cmd);
379         int flags = va_arg(ap, int);
380         va_end(ap);
381 
382         if (flags & O_NONBLOCK)
383         {
384             hook_fd->sock_flag |= MT_FD_FLG_UNBLOCK;
385         }
386     }
387 
388     return ff_hook_fcntl(fd, cmd, arg);
389 }
390 
391 
392 int listen(int sockfd, int backlog)
393 {
394     mt_hook_syscall(listen);
395     if (!ff_hook_active())
396     {
397         return mt_real_func(listen)(sockfd, backlog);
398     }
399 
400 	return ff_hook_listen(sockfd, backlog);
401 }
402 
403 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
404 {
405     mt_hook_syscall(bind);
406     if (!ff_hook_active())
407     {
408         return mt_real_func(bind)(sockfd, addr, addrlen);
409     }
410 
411 	return ff_hook_bind(sockfd, addr, addrlen);
412 }
413 
414 int accept(int fd, struct sockaddr *addr, socklen_t *addrlen)
415 {
416     mt_hook_syscall(accept);
417     if (!ff_hook_active())
418     {
419         return mt_real_func(accept)(fd, addr, addrlen);
420     }
421 
422 	return ff_hook_accept(fd, addr, addrlen);
423 }
424 
425 #ifdef __cplusplus
426 }
427 #endif
428