void tc_intercept_release_tunnel(int fd, tc_event_t *rev) { if (!srv_settings.tunnel[fd].fd_valid) { tc_log_info(LOG_WARN, 0, "already released, fd:%d", fd); return; } tc_log_info(LOG_NOTICE, 0, "release tunnel related resources, fd:%d", fd); tc_socket_close(fd); srv_settings.tunnel[fd].fd_valid = 0; #if (INTERCEPT_COMBINED) if (srv_settings.tunnel[fd].combined != NULL) { free(srv_settings.tunnel[fd].combined); srv_settings.tunnel[fd].combined = NULL; } else { tc_log_info(LOG_NOTICE, 0, "crazy here, combined is null, fd:%d", fd); } #endif if (rev == NULL) { if (srv_settings.tunnel[fd].ev == NULL) { tc_log_info(LOG_NOTICE, 0, "crazy here, ev is null, fd:%d", fd); } else { tc_event_del(srv_settings.tunnel[fd].ev->loop, srv_settings.tunnel[fd].ev, TC_EVENT_READ); tc_event_destroy(srv_settings.tunnel[fd].ev, 1); srv_settings.tunnel[fd].ev = NULL; } } else { tc_event_del(rev->loop, rev, TC_EVENT_READ); } }
static int tc_msg_event_process(tc_event_t *rev) { msg_client_t msg; if (tc_socket_recv(rev->fd, (char *) &msg, MSG_CLIENT_SIZE) == TC_ERROR) { tc_socket_close(rev->fd); tc_log_info(LOG_NOTICE, 0, "close sock:%d", rev->fd); tc_event_del(rev->loop, rev, TC_EVENT_READ); return TC_ERROR; } switch (msg.type) { case CLIENT_ADD: tc_log_debug1(LOG_DEBUG, 0, "add client router:%u", ntohs(msg.client_port)); router_add(msg.client_ip, msg.client_port, rev->fd); break; case CLIENT_DEL: tc_log_debug1(LOG_DEBUG, 0, "del client router:%u", ntohs(msg.client_port)); router_del(msg.client_ip, msg.client_port); break; } return TC_OK; }
int tc_socket_connect(int fd, uint32_t ip, uint16_t port) { socklen_t len; struct sockaddr_in remote_addr; tc_memzero(&remote_addr, sizeof(remote_addr)); remote_addr.sin_family = AF_INET; remote_addr.sin_addr.s_addr = ip; remote_addr.sin_port = htons(port); len = (socklen_t) (sizeof(remote_addr)); if (connect(fd, (struct sockaddr *) &remote_addr, len) == -1) { tc_log_info(LOG_ERR, errno, "Can not connect to remote server(%s:%d)", inet_ntoa(remote_addr.sin_addr), port); tc_socket_close(fd); return TC_ERROR; } else { tc_log_info(LOG_INFO, 0, "connect to remote server(%s:%d)", inet_ntoa(remote_addr.sin_addr), port); return TC_OK; } }
static int tc_msg_event_accept(tc_event_t *rev) { tc_event_t *ev; register int fd; tunnel_basic_t *tunnel; if ((fd = tc_socket_accept(rev->fd)) == TC_INVALID_SOCK) { tc_log_info(LOG_ERR, 0, "msg accept failed, from listen:%d", rev->fd); return TC_ERR; } tc_log_info(LOG_NOTICE, 0, "it adds fd:%d", fd); if (tc_socket_set_nodelay(fd) == TC_ERR) { tc_log_info(LOG_ERR, 0, "Set no delay to socket(%d) failed.", rev->fd); tc_log_info(LOG_NOTICE, 0, "it close socket:%d", fd); tc_socket_close(fd); return TC_ERR; } #if (TC_SINGLE) if (!tc_intercept_check_tunnel_for_single(fd)) { tc_log_info(LOG_WARN, 0, "sth tries to connect to server."); tc_log_info(LOG_NOTICE, 0, "it close socket:%d", fd); tc_socket_close(fd); return TC_ERR; } #endif ev = tc_event_create(rev->loop->pool, fd, tc_msg_event_proc, NULL); if (ev == NULL) { tc_log_info(LOG_ERR, 0, "Msg event create failed."); return TC_ERR; } if (tc_event_add(rev->loop, ev, TC_EVENT_READ) == TC_EVENT_ERROR) { return TC_ERR; } tunnel = srv_settings.tunnel; tunnel[fd].ev = ev; tunnel[fd].first_in = 1; tunnel[fd].fd_valid = 1; return TC_OK; }
static int connect_to_server(tc_event_loop_t *ev_lp) { int i, j, fd; uint32_t target_ip; conns_t *conns; uint16_t target_port; for (i = 0; i < clt_settings.real_servers.num; i++) { conns = &(clt_settings.real_servers.conns[i]); target_ip = conns[i].ip; target_port = conns[i].port; if (target_port == 0) { target_port = clt_settings.srv_port; } if (conns[i].active != 0) { continue; } for (j = 0; j < conns->num; j++) { fd = conns->fds[j]; if (fd > 0) { tc_log_info(LOG_NOTICE, 0, "it close socket:%d", fd); tc_socket_close(fd); tc_event_del(clt_settings.ev[fd]->loop, clt_settings.ev[fd], TC_EVENT_READ); tc_event_destroy(clt_settings.ev[fd], 0); conns->fds[j] = -1; } } clt_settings.real_servers.conns[i].num = 0; clt_settings.real_servers.conns[i].remained_num = 0; for (j = 0; j < clt_settings.par_conns; j++) { fd = tc_message_init(ev_lp, target_ip, target_port); if (fd == TC_INVALID_SOCK) { return TC_ERR; } if (!send_version(fd)) { return TC_ERR; } if (j == 0) { clt_settings.real_servers.active_num++; conns[i].active = 1; } clt_settings.real_servers.conns[i].fds[j] = fd; clt_settings.real_servers.conns[i].num++; clt_settings.real_servers.conns[i].remained_num++; } } return TC_OK; }
void tcp_copy_release_resources(void) { #if (TC_PCAP) int i; #endif tc_log_info(LOG_WARN, 0, "sig %d received", tc_over); tc_output_stat(); tc_dest_sess_table(); check_resource_usage(NULL); #if (TC_PLUGIN) if (clt_settings.plugin && clt_settings.plugin->exit_module) { clt_settings.plugin->exit_module(&clt_settings); } #endif tc_event_loop_finish(&event_loop); tc_log_info(LOG_NOTICE, 0, "tc_event_loop_finish over"); #if (TC_DIGEST) tc_destroy_sha1(); tc_destroy_digests(); #endif #if (TC_PCAP) for (i = 0; i < clt_settings.devices.device_num; i++) { if (clt_settings.devices.device[i].pcap != NULL) { pcap_close(clt_settings.devices.device[i].pcap); clt_settings.devices.device[i].pcap = NULL; } } #endif #if (TC_OFFLINE) if (clt_settings.pcap != NULL) { pcap_close(clt_settings.pcap); clt_settings.pcap = NULL; } #endif if (tc_raw_socket_out > 0) { tc_socket_close(tc_raw_socket_out); tc_raw_socket_out = TC_INVALID_SOCK; } #if (TC_PCAP_SND) tc_pcap_over(); #endif tc_destroy_pool(clt_settings.pool); tc_log_end(); }
int tc_raw_socket_send(int fd, void *buf, size_t len, uint32_t ip) { ssize_t send_len, offset = 0, num_bytes; const char *ptr; struct sockaddr_in dst_addr; if (fd > 0) { memset(&dst_addr, 0, sizeof(struct sockaddr_in)); dst_addr.sin_family = AF_INET; dst_addr.sin_addr.s_addr = ip; ptr = buf; /* * The output packet will take a special path of IP layer * (raw_sendmsg->raw_send_hdrinc->NF_INET_LOCAL_OUT->...). * No IP fragmentation will take place if needed. * This means that a raw packet larger than the MTU of the * interface will probably be discarded. Instead ip_local_error(), * which does general sk_buff cleaning, is called and an * error EMSGSIZE is returned. */ do { num_bytes = len - offset; send_len = sendto(fd, ptr + offset, num_bytes, 0, (struct sockaddr *) &dst_addr, sizeof(dst_addr)); if (send_len == -1) { if (errno == EINTR) { tc_log_info(LOG_NOTICE, errno, "raw fd:%d EINTR", fd); } else if (errno == EAGAIN) { tc_log_info(LOG_NOTICE, errno, "raw fd:%d EAGAIN", fd); } else { tc_log_info(LOG_ERR, errno, "raw fd:%d", fd); tc_socket_close(fd); return TC_ERROR; } } else { offset += send_len; } } while (offset < len); } return TC_OK; }
static void address_release() { int i, j, fd; hash_node *hn; link_list *list; p_link_node ln, tmp_ln; connections_t *connections; if (addr_table == NULL) { return; } for (i = 0; i < addr_table->size; i++) { list = addr_table->lists[i]; ln = link_list_first(list); while (ln) { tmp_ln = link_list_get_next(list, ln); hn = (hash_node *) ln->data; if (hn->data != NULL) { connections = (connections_t *) hn->data; hn->data = NULL; for (j = 0; j < connections->num; j++) { fd = connections->fds[j]; if (fd > 0) { tc_log_info(LOG_NOTICE, 0, "it close socket:%d", fd); connections->fds[j] = -1; tc_socket_close(fd); } } free(connections); } ln = tmp_ln; } } tc_log_info(LOG_NOTICE, 0, "destroy addr table"); hash_destroy(addr_table); free(addr_table); addr_table = NULL; }
static int tc_process_server_msg(tc_event_t *rev) { #if (TCPCOPY_DR) int i; #endif msg_server_t msg; if (tc_socket_recv(rev->fd, (char *) &msg, MSG_SERVER_SIZE) == TC_ERROR) { tc_log_info(LOG_ERR, 0, "Recv socket(%d)error, server may be closed", rev->fd); #if (TCPCOPY_DR) for (i = 0; i < clt_settings.real_servers.num; i++) { if (clt_settings.real_servers.fds[i] == rev->fd) { if (clt_settings.real_servers.active[i]) { clt_settings.real_servers.active[i] = 0; clt_settings.real_servers.active_num--; } tc_socket_close(rev->fd); tc_log_info(LOG_NOTICE, 0, "close sock:%d", rev->fd); tc_event_del(rev->loop, rev, TC_EVENT_READ); break; } } if (clt_settings.real_servers.active_num == 0) { return TC_ERR_EXIT; } else { return TC_OK; } #else return TC_ERR_EXIT; #endif } process((char *) &msg, REMOTE); return TC_OK; }
int tc_socket_send(int fd, char *buffer, int len) { ssize_t send_len, offset = 0, num_bytes; const char *ptr; if (len <= 0) { return TC_OK; } ptr = buffer; num_bytes = len - offset; do { send_len = send(fd, ptr + offset, num_bytes, 0); if (send_len == -1) { if (errno == EINTR) { tc_log_info(LOG_NOTICE, errno, "fd:%d EINTR", fd); } else if (errno == EAGAIN) { tc_log_info(LOG_NOTICE, errno, "fd:%d EAGAIN", fd); } else { tc_log_info(LOG_ERR, errno, "fd:%d", fd); tc_socket_close(fd); return TC_ERROR; } } else { if (send_len != num_bytes) { tc_log_info(LOG_WARN, 0, "fd:%d, slen:%ld, bsize:%ld", fd, send_len, num_bytes); } offset += send_len; } } while (offset < len); return TC_OK; }
int tc_select_destroy(tc_event_loop_t *loop) { int i; tc_event_t *event; tc_select_multiplex_io_t *io; io = loop->io; for (i = 0; i < io->last; i++) { event = io->evs[i]; if (event->fd > 0) { tc_socket_close(event->fd); } event->fd = -1; free(event); } free(io->evs); free(loop->io); return TC_EVENT_OK; }
int tc_epoll_destroy(tc_event_loop_t *loop) { int i; tc_event_t *event; tc_epoll_multiplex_io_t *io; io = loop->io; for (i = 0; i <= io->max_fd; i++) { event = io->evs[i]; if (event != NULL) { if (event->fd > 0) { tc_log_info(LOG_NOTICE, 0, "tc_epoll_destroy, close fd:%d", event->fd); tc_socket_close(event->fd); event->fd = -1; tc_pfree(loop->pool, event); } else { tc_log_info(LOG_WARN, 0, "tc_epoll_destroy, fd < 0:%d", event->fd); tc_pfree(loop->pool, event); } } } if (io->efd) { close(io->efd); io->efd = -1; } io->max_fd = -1; tc_pfree(loop->pool, io->events); tc_pfree(loop->pool, io->evs); tc_pfree(loop->pool, loop->io); return TC_EVENT_OK; }
int tc_select_destroy(tc_event_loop_t *loop) { int i; tc_event_t *event; tc_select_multiplex_io_t *io; io = loop->io; for (i = 0; i < io->last; i++) { event = io->evs[i]; if (event->fd > 0) { tc_log_info(LOG_NOTICE, 0, "tc_select_destroy, close fd:%d", event->fd); tc_socket_close(event->fd); } event->fd = -1; tc_pfree(loop->pool, event); } tc_pfree(loop->pool, io->evs); tc_pfree(loop->pool, loop->io); return TC_EVENT_OK; }
static int tc_process_server_msg(tc_event_t *rev) { #if (TCPCOPY_DR) int i, j; connections_t *connections; #endif #if (!TCPCOPY_COMBINED) int len; msg_server_t msg; #else int num, k; unsigned char *p, aggr_resp[COMB_LENGTH + sizeof(uint16_t)]; #endif #if (!TCPCOPY_COMBINED) len = MSG_SERVER_SIZE; #endif #if (!TCPCOPY_COMBINED) if (tc_socket_recv(rev->fd, (char *) &msg, len) == TC_ERROR) #else if (tc_socket_cmb_recv(rev->fd, &num, (char *) aggr_resp) == TC_ERROR) #endif { tc_log_info(LOG_ERR, 0, "Recv socket(%d)error", rev->fd); tc_log_info(LOG_ERR, 0, "server may be closed or"); tc_log_info(LOG_ERR, 0, "backend TCP/IP kernel memeory is too low or"); tc_log_info(LOG_ERR, 0, "the version of intercept may not be equal to the version of tcpcopy"); #if (TCPCOPY_DR) for (i = 0; i < clt_settings.real_servers.num; i++) { connections = &(clt_settings.real_servers.connections[i]); for (j = 0; j < connections->num; j++) { if (connections->fds[j] == rev->fd) { tc_socket_close(rev->fd); tc_log_info(LOG_NOTICE, 0, "close sock:%d", rev->fd); tc_event_del(rev->loop, rev, TC_EVENT_READ); connections->num--; if (connections->num == 0 && clt_settings.real_servers.active[i]) { clt_settings.real_servers.active[i] = 0; clt_settings.real_servers.active_num--; } break; } } } if (clt_settings.real_servers.active_num == 0) { return TC_ERR_EXIT; } else { return TC_OK; } #else return TC_ERR_EXIT; #endif } #if (!TCPCOPY_COMBINED) process_out((unsigned char *) &msg); #else tc_log_debug1(LOG_DEBUG, 0, "resp packets:%d", num); p = aggr_resp + sizeof(uint16_t); for (k = 0; k < num; k++) { process_out(p); p = p + MSG_SERVER_SIZE; } #endif return TC_OK; }
void tcp_copy_release_resources() { int i; tc_log_info(LOG_WARN, 0, "sig %d received", tc_over); output_stat(); tc_time_remove_timer(); tc_log_info(LOG_NOTICE, 0, "remove timer over"); destroy_for_sessions(); tc_event_loop_finish(&event_loop); tc_log_info(LOG_NOTICE, 0, "tc_event_loop_finish over"); #if (TCPCOPY_DIGEST) tc_destroy_sha1(); tc_destroy_digests(); #endif #if (!TCPCOPY_DR) address_release(); #endif tc_log_end(); #ifdef TCPCOPY_MYSQL_ADVANCED release_mysql_user_pwd_info(); #endif #if (TCPCOPY_PCAP) for (i = 0; i < clt_settings.devices.device_num; i++) { if (clt_settings.devices.device[i].pcap != NULL) { pcap_close(clt_settings.devices.device[i].pcap); clt_settings.devices.device[i].pcap = NULL; } } #endif #if (TCPCOPY_OFFLINE) if (clt_settings.pcap != NULL) { pcap_close(clt_settings.pcap); clt_settings.pcap = NULL; } #endif if (tc_raw_socket_out > 0) { tc_socket_close(tc_raw_socket_out); tc_raw_socket_out = TC_INVALID_SOCKET; } #if (TCPCOPY_PCAP_SEND) tc_pcap_over(); #endif if (clt_settings.transfer.mappings != NULL) { for (i = 0; i < clt_settings.transfer.num; i++) { free(clt_settings.transfer.mappings[i]); } free(clt_settings.transfer.mappings); clt_settings.transfer.mappings = NULL; } }
static int connect_to_server(tc_event_loop_t *event_loop) { int i, j, fd; uint32_t target_ip; uint16_t target_port; connections_t *connections; /* * add connections to the real servers for sending router info * and receiving response packet */ for (i = 0; i < clt_settings.real_servers.num; i++) { target_ip = clt_settings.real_servers.ips[i]; target_port = clt_settings.real_servers.ports[i]; if (target_port == 0) { target_port = clt_settings.srv_port; } if (clt_settings.real_servers.active[i] != 0) { continue; } connections = &(clt_settings.real_servers.connections[i]); for (j = 0; j < connections->num; j++) { fd = connections->fds[j]; if (fd > 0) { tc_log_info(LOG_NOTICE, 0, "it close socket:%d", fd); tc_socket_close(fd); tc_event_del(clt_settings.ev[fd]->loop, clt_settings.ev[fd], TC_EVENT_READ); tc_event_destroy(clt_settings.ev[fd]); connections->fds[j] = -1; } } clt_settings.real_servers.connections[i].num = 0; clt_settings.real_servers.connections[i].remained_num = 0; for (j = 0; j < clt_settings.par_connections; j++) { fd = tc_message_init(event_loop, target_ip, target_port); if (fd == TC_INVALID_SOCKET) { return TC_ERROR; } if (!send_version(fd)) { return TC_ERROR; } if (j == 0) { clt_settings.real_servers.active_num++; clt_settings.real_servers.active[i] = 1; } clt_settings.real_servers.connections[i].fds[j] = fd; clt_settings.real_servers.connections[i].num++; clt_settings.real_servers.connections[i].remained_num++; } tc_log_info(LOG_NOTICE, 0, "add dr tunnels for exchanging info:%u:%u", target_ip, target_port); } return TC_OK; }