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 */ 23 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <stdint.h> 27 #include <unistd.h> 28 #include <errno.h> 29 #include <assert.h> 30 #include <sys/types.h> 31 #include <sys/stat.h> 32 #include <stdarg.h> 33 34 #include "micro_thread.h" 35 #include "mt_sys_hook.h" 36 #include "ff_hook.h" 37 38 using namespace NS_MICRO_THREAD; 39 40 41 #define MT_HOOK_MAX_FD 65535*2 42 #define MT_FD_FLG_INUSE 0x1 43 #define MT_FD_FLG_UNBLOCK 0x2 44 45 typedef struct socket_hook_info 46 { 47 int sock_flag; 48 int read_timeout; 49 int write_timeout; 50 }MtHookFd; 51 52 MtSyscallFuncTab g_mt_syscall_tab; 53 int g_mt_hook_flag; 54 int g_ff_hook_flag; 55 static MtHookFd g_mt_hook_fd_tab[MT_HOOK_MAX_FD]; 56 57 MtHookFd* mt_hook_find_fd(int fd) 58 { 59 if ((fd < 0) || (fd >= MT_HOOK_MAX_FD)) { 60 return NULL; 61 } 62 63 MtHookFd* fd_info = &g_mt_hook_fd_tab[fd]; 64 if (!(fd_info->sock_flag & MT_FD_FLG_INUSE)) { 65 return NULL; 66 } else { 67 return fd_info; 68 } 69 } 70 71 void mt_hook_new_fd(int fd) 72 { 73 if ((fd < 0) || (fd >= MT_HOOK_MAX_FD)) { 74 return; 75 } 76 77 MtHookFd* fd_info = &g_mt_hook_fd_tab[fd]; 78 fd_info->sock_flag = MT_FD_FLG_INUSE; 79 fd_info->read_timeout = 500; 80 fd_info->write_timeout = 500; 81 } 82 83 void mt_hook_free_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 = 0; 91 fd_info->read_timeout = 0; 92 fd_info->write_timeout = 0; 93 } 94 95 #ifdef __cplusplus 96 extern "C" { 97 #endif 98 int ioctl(int fd, unsigned long cmd, ...) 99 { 100 va_list ap; 101 va_start(ap, cmd); 102 void* arg = va_arg(ap, void *); 103 va_end(ap); 104 105 mt_hook_syscall(ioctl); 106 MtHookFd* hook_fd = mt_hook_find_fd(fd); 107 if (!mt_hook_active() || !hook_fd || !ff_hook_active()) 108 { 109 return ff_hook_ioctl(fd, cmd, arg); 110 } 111 112 if (cmd == FIONBIO) 113 { 114 int flags = (arg != NULL) ? *((int*)arg) : 0; 115 if (flags != 0) { 116 hook_fd->sock_flag |= MT_FD_FLG_UNBLOCK; 117 } 118 } 119 120 return ff_hook_ioctl(fd, cmd, arg); 121 } 122 123 int socket(int domain, int type, int protocol) 124 { 125 mt_hook_syscall(socket); 126 127 if (!ff_hook_active()) 128 { 129 return mt_real_func(socket)(domain, type, protocol); 130 } 131 132 int fd = ff_hook_socket(domain, type, protocol); 133 if (fd < 0) 134 { 135 return fd; 136 } 137 138 mt_hook_new_fd(fd); 139 140 mt_hook_syscall(ioctl); 141 int nb = 1; 142 ff_hook_ioctl(fd, FIONBIO, &nb); 143 144 return fd; 145 } 146 147 int close(int fd) 148 { 149 mt_hook_syscall(close); 150 if (!ff_hook_active()) 151 { 152 return mt_real_func(close)(fd); 153 } 154 155 mt_hook_free_fd(fd); 156 return ff_hook_close(fd); 157 } 158 159 int connect(int fd, const struct sockaddr *address, socklen_t address_len) 160 { 161 mt_hook_syscall(connect); 162 MtHookFd* hook_fd = mt_hook_find_fd(fd); 163 if (!mt_hook_active() || !hook_fd || !ff_hook_active()) 164 { 165 return mt_real_func(connect)(fd, address, address_len); 166 } 167 168 if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK) 169 { 170 return ff_hook_connect(fd, address, address_len); 171 } 172 173 return MtFrame::connect(fd, address, (int)address_len, hook_fd->write_timeout); 174 } 175 176 ssize_t read(int fd, void *buf, size_t nbyte) 177 { 178 mt_hook_syscall(read); 179 MtHookFd* hook_fd = mt_hook_find_fd(fd); 180 if (!mt_hook_active() || !hook_fd || !ff_hook_active()) 181 { 182 return mt_real_func(read)(fd, buf, nbyte); 183 } 184 185 if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK) 186 { 187 return ff_hook_read(fd, buf, nbyte); 188 } 189 190 return MtFrame::read(fd, buf, nbyte, hook_fd->read_timeout); 191 } 192 193 ssize_t write(int fd, const void *buf, size_t nbyte) 194 { 195 mt_hook_syscall(write); 196 MtHookFd* hook_fd = mt_hook_find_fd(fd); 197 if (!mt_hook_active() || !hook_fd || !ff_hook_active()) 198 { 199 return mt_real_func(write)(fd, buf, nbyte); 200 } 201 202 if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK) 203 { 204 return ff_hook_write(fd, buf, nbyte); 205 } 206 207 return MtFrame::write(fd, buf, nbyte, hook_fd->write_timeout); 208 } 209 210 ssize_t sendto(int fd, const void *message, size_t length, int flags, 211 const struct sockaddr *dest_addr, socklen_t dest_len) 212 { 213 mt_hook_syscall(sendto); 214 MtHookFd* hook_fd = mt_hook_find_fd(fd); 215 if (!mt_hook_active() || !hook_fd || !ff_hook_active()) 216 { 217 return mt_real_func(sendto)(fd, message, length, flags, dest_addr, dest_len); 218 } 219 220 if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK) 221 { 222 return ff_hook_sendto(fd, message, length, flags, dest_addr, dest_len); 223 } 224 225 return MtFrame::sendto(fd, message, (int)length, flags, 226 dest_addr, dest_len, hook_fd->write_timeout); 227 } 228 229 ssize_t recvfrom(int fd, void *buffer, size_t length, int flags, 230 struct sockaddr *address, socklen_t *address_len) 231 { 232 mt_hook_syscall(recvfrom); 233 MtHookFd* hook_fd = mt_hook_find_fd(fd); 234 if (!mt_hook_active() || !hook_fd || !ff_hook_active()) 235 { 236 return mt_real_func(recvfrom)(fd, buffer, length, flags, address, address_len); 237 } 238 239 if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK) 240 { 241 return ff_hook_recvfrom(fd, buffer, length, flags, address, address_len); 242 } 243 244 return MtFrame::recvfrom(fd, buffer, length, flags, address, address_len, hook_fd->read_timeout); 245 246 } 247 248 ssize_t recv(int fd, void *buffer, size_t length, int flags) 249 { 250 mt_hook_syscall(recv); 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(recv)(fd, buffer, length, flags); 255 } 256 257 if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK) 258 { 259 return ff_hook_recv(fd, buffer, length, flags); 260 } 261 262 return MtFrame::recv(fd, buffer, length, flags, hook_fd->read_timeout); 263 } 264 265 ssize_t send(int fd, const void *buf, size_t nbyte, int flags) 266 { 267 mt_hook_syscall(send); 268 MtHookFd* hook_fd = mt_hook_find_fd(fd); 269 if (!mt_hook_active() || !hook_fd || !ff_hook_active()) 270 { 271 return mt_real_func(send)(fd, buf, nbyte, flags); 272 } 273 274 if (hook_fd->sock_flag & MT_FD_FLG_UNBLOCK) 275 { 276 return ff_hook_send(fd, buf, nbyte, flags); 277 } 278 279 return MtFrame::send(fd, buf, nbyte, flags, hook_fd->write_timeout); 280 } 281 282 int setsockopt(int fd, int level, int option_name, const void *option_value, socklen_t option_len) 283 { 284 mt_hook_syscall(setsockopt); 285 MtHookFd* hook_fd = mt_hook_find_fd(fd); 286 if (!mt_hook_active() || !hook_fd || !ff_hook_active()) 287 { 288 return mt_real_func(setsockopt)(fd, level, option_name, option_value, option_len); 289 } 290 291 if (SOL_SOCKET == level) 292 { 293 struct timeval *val = (struct timeval*)option_value; 294 if (SO_RCVTIMEO == option_name) 295 { 296 hook_fd->read_timeout = val->tv_sec * 1000 + val->tv_usec / 1000; 297 } 298 else if (SO_SNDTIMEO == option_name) 299 { 300 hook_fd->write_timeout = val->tv_sec * 1000 + val->tv_usec / 1000; 301 } 302 } 303 304 return ff_hook_setsockopt(fd, level, option_name, option_value, option_len); 305 } 306 307 int fcntl(int fd, int cmd, ...) 308 { 309 va_list ap; 310 va_start(ap, cmd); 311 void* arg = va_arg(ap, void *); 312 va_end(ap); 313 314 mt_hook_syscall(fcntl); 315 MtHookFd* hook_fd = mt_hook_find_fd(fd); 316 if (!mt_hook_active() || !hook_fd || !ff_hook_active()) 317 { 318 return mt_real_func(fcntl)(fd, cmd, arg); 319 } 320 321 if (cmd == F_SETFL) 322 { 323 va_start(ap, cmd); 324 int flags = va_arg(ap, int); 325 va_end(ap); 326 327 if (flags & O_NONBLOCK) 328 { 329 hook_fd->sock_flag |= MT_FD_FLG_UNBLOCK; 330 } 331 } 332 333 return ff_hook_fcntl(fd, cmd, arg); 334 } 335 336 int listen(int sockfd, int backlog) 337 { 338 mt_hook_syscall(listen); 339 if (!ff_hook_active()) 340 { 341 return mt_real_func(listen)(sockfd, backlog); 342 } 343 344 return ff_hook_listen(sockfd, backlog); 345 } 346 347 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) 348 { 349 mt_hook_syscall(bind); 350 if (!ff_hook_active()) 351 { 352 return mt_real_func(bind)(sockfd, addr, addrlen); 353 } 354 355 return ff_hook_bind(sockfd, addr, addrlen); 356 } 357 358 int accept(int fd, struct sockaddr *addr, socklen_t *addrlen) 359 { 360 mt_hook_syscall(accept); 361 if (!ff_hook_active()) 362 { 363 return mt_real_func(accept)(fd, addr, addrlen); 364 } 365 366 return ff_hook_accept(fd, addr, addrlen); 367 } 368 369 #ifdef __cplusplus 370 } 371 #endif 372