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