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