xref: /f-stack/app/micro_thread/mt_sys_hook.cpp (revision 144c6bcd)
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)
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 (!mt_hook_active())
149     {
150        return ff_hook_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 
162     mt_hook_syscall(ioctl);
163 	int nb = 1;
164 	ff_hook_ioctl(fd, FIONBIO, &nb);
165 
166     return fd;
167 }
168 
169 /**
170  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi
171  */
172 int close(int fd)
173 {
174     mt_hook_syscall(close);
175     if (!mt_hook_active())
176     {
177         return ff_hook_close(fd);
178     }
179 
180     mt_hook_free_fd(fd);
181 	return ff_hook_close(fd);
182 }
183 
184 
185 /**
186  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi
187  */
188 int connect(int fd, const struct sockaddr *address, socklen_t address_len)
189 {
190     mt_hook_syscall(connect);
191     MtHookFd* hook_fd = mt_hook_find_fd(fd);
192     if (!mt_hook_active() || !hook_fd)
193     {
194         return ff_hook_connect(fd, address, address_len);
195     }
196 
197     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
198     {
199         return ff_hook_connect(fd, address, address_len);
200     }
201 
202     return MtFrame::connect(fd, address, (int)address_len, hook_fd->write_timeout);
203 }
204 
205 /**
206  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi, �û��Ѿ�����unblock, ����
207  */
208 ssize_t read(int fd, void *buf, size_t nbyte)
209 {
210     mt_hook_syscall(read);
211     MtHookFd* hook_fd = mt_hook_find_fd(fd);
212     if (!mt_hook_active() || !hook_fd)
213     {
214         return ff_hook_read(fd, buf, nbyte);
215     }
216 
217     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
218     {
219         return ff_hook_read(fd, buf, nbyte);
220     }
221 
222     return MtFrame::read(fd, buf, nbyte, hook_fd->read_timeout);
223 }
224 
225 /**
226  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi, �û��Ѿ�����unblock, ����
227  */
228 ssize_t write(int fd, const void *buf, size_t nbyte)
229 {
230     mt_hook_syscall(write);
231     MtHookFd* hook_fd = mt_hook_find_fd(fd);
232     if (!mt_hook_active() || !hook_fd)
233     {
234         return ff_hook_write(fd, buf, nbyte);
235     }
236 
237     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
238     {
239         return ff_hook_write(fd, buf, nbyte);
240     }
241 
242     return MtFrame::write(fd, buf, nbyte, hook_fd->write_timeout);
243 }
244 
245 /**
246  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi, �û��Ѿ�����unblock, ����
247  */
248 ssize_t sendto(int fd, const void *message, size_t length, int flags,
249                const struct sockaddr *dest_addr, socklen_t dest_len)
250 {
251     mt_hook_syscall(sendto);
252     MtHookFd* hook_fd = mt_hook_find_fd(fd);
253     if (!mt_hook_active() || !hook_fd)
254     {
255         return ff_hook_sendto(fd, message, length, flags, dest_addr, dest_len);
256     }
257 
258     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
259     {
260         return ff_hook_sendto(fd, message, length, flags, dest_addr, dest_len);
261     }
262 
263     return MtFrame::sendto(fd, message, (int)length, flags,
264                            dest_addr, dest_len, hook_fd->write_timeout);
265 }
266 
267 /**
268  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi, �û��Ѿ�����unblock, ����
269  */
270 ssize_t recvfrom(int fd, void *buffer, size_t length, int flags,
271                   struct sockaddr *address, socklen_t *address_len)
272 {
273     mt_hook_syscall(recvfrom);
274     MtHookFd* hook_fd = mt_hook_find_fd(fd);
275     if (!mt_hook_active() || !hook_fd)
276     {
277         return ff_hook_recvfrom(fd, buffer, length, flags, address, address_len);
278     }
279 
280     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
281     {
282         return ff_hook_recvfrom(fd, buffer, length, flags, address, address_len);
283     }
284 
285     return MtFrame::recvfrom(fd, buffer, length, flags, address, address_len, hook_fd->read_timeout);
286 
287 }
288 
289 /**
290  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi, �û��Ѿ�����unblock, ����
291  */
292 ssize_t recv(int fd, void *buffer, size_t length, int flags)
293 {
294     mt_hook_syscall(recv);
295     MtHookFd* hook_fd = mt_hook_find_fd(fd);
296     if (!mt_hook_active() || !hook_fd)
297     {
298         return ff_hook_recv(fd, buffer, length, flags);
299     }
300 
301     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
302     {
303         return ff_hook_recv(fd, buffer, length, flags);
304     }
305 
306     return MtFrame::recv(fd, buffer, length, flags, hook_fd->read_timeout);
307 }
308 
309 /**
310  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi, �û��Ѿ�����unblock, ����
311  */
312 ssize_t send(int fd, const void *buf, size_t nbyte, int flags)
313 {
314     mt_hook_syscall(send);
315     MtHookFd* hook_fd = mt_hook_find_fd(fd);
316     if (!mt_hook_active() || !hook_fd)
317     {
318         return ff_hook_send(fd, buf, nbyte, flags);
319     }
320 
321     if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK)
322     {
323         return ff_hook_send(fd, buf, nbyte, flags);
324     }
325 
326     return MtFrame::send(fd, buf, nbyte, flags, hook_fd->write_timeout);
327 }
328 
329 
330 /**
331  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi, �ػ��û����õij�ʱʱ����Ϣ
332  */
333 int setsockopt(int fd, int level, int option_name, const void *option_value, socklen_t option_len)
334 {
335     mt_hook_syscall(setsockopt);
336     MtHookFd* hook_fd = mt_hook_find_fd(fd);
337     if (!mt_hook_active() || !hook_fd)
338     {
339         return ff_hook_setsockopt(fd, level, option_name, option_value, option_len);
340     }
341 
342     if (SOL_SOCKET == level)
343     {
344         struct timeval *val = (struct timeval*)option_value;
345         if (SO_RCVTIMEO == option_name)
346         {
347             hook_fd->read_timeout = val->tv_sec * 1000 + val->tv_usec / 1000;
348         }
349         else if (SO_SNDTIMEO == option_name)
350         {
351             hook_fd->write_timeout = val->tv_sec * 1000 + val->tv_usec / 1000;
352         }
353     }
354 
355 	return ff_hook_setsockopt(fd, level, option_name, option_value, option_len);
356 }
357 
358 
359 
360 /**
361  * @brief HOOK�ӿ�, ��ʼ��mt���, �ӹ�ϵͳapi, �ػ��û����õķ��������
362  */
363 int fcntl(int fd, int cmd, ...)
364 {
365     va_list ap;
366     va_start(ap, cmd);
367     void* arg = va_arg(ap, void *);
368     va_end(ap);
369 
370     mt_hook_syscall(fcntl);
371     MtHookFd* hook_fd = mt_hook_find_fd(fd);
372     if (!mt_hook_active() || !hook_fd)
373     {
374         return ff_hook_fcntl(fd, cmd, arg);
375     }
376 
377     if (cmd == F_SETFL)
378     {
379         va_start(ap, cmd);
380         int flags = va_arg(ap, int);
381         va_end(ap);
382 
383         if (flags & O_NONBLOCK)
384         {
385             hook_fd->sock_flag |= MT_FD_FLG_UNBLOCK;
386         }
387     }
388 
389     return ff_hook_fcntl(fd, cmd, arg);
390 }
391 
392 
393 int listen(int sockfd, int backlog)
394 {
395     mt_hook_syscall(listen);
396 	return ff_hook_listen(sockfd, backlog);
397 }
398 
399 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
400 {
401     mt_hook_syscall(bind);
402 	return ff_hook_bind(sockfd, addr, addrlen);
403 }
404 
405 int accept(int fd, struct sockaddr *addr, socklen_t *addrlen)
406 {
407     mt_hook_syscall(accept);
408 	return ff_hook_accept(fd, addr, addrlen);
409 }
410 
411 #ifdef __cplusplus
412 }
413 #endif
414