/* Update router table */ void router_update(tc_ip_header_t *ip_header, int len) { void *fd; uint32_t size_ip; uint64_t key; msg_server_t msg; struct tcphdr *tcp_header; size_ip = ip_header->ihl << 2; tcp_header = (struct tcphdr*)((char *)ip_header + size_ip); memcpy(&msg, ip_header, len); key = get_key(ip_header->daddr, tcp_header->dest); pthread_mutex_lock(&mutex); fd = hash_find(table, key); if ( NULL == fd ) { tc_log((LOG_DEBUG), 0, "fd is null"); delay_table_add(key, &msg); pthread_mutex_unlock(&mutex); return ; } pthread_mutex_unlock(&mutex); tc_socket_send((int) (long) fd, (char *) &msg, MSG_SERVER_SIZE); }
/* send delayed message according to the key */ void delay_table_send(uint64_t key, int fd) { link_list *msg_list; p_link_node first; msg_server_t *msg ; msg_list = (link_list *) hash_find(table, key); if (msg_list == NULL) { return; } while (!link_list_is_empty(msg_list)) { first = link_list_pop_first(msg_list); msg = (first->data); #if (INTERCEPT_COMBINED) buffer_and_send(fd, fd, msg); #else tc_socket_send(fd, (char *) msg, MSG_SERVER_SIZE); #endif msg_delay_sent_cnt++; msg_item_free_cnt++; link_node_internal_free(first); free(first); } }
/* Update router table */ void router_update(struct iphdr *ip_header) { void *fd; uint32_t size_ip; uint64_t key; msg_server_t msg; struct tcphdr *tcp_header; #if (TCPCOPY_MYSQL_ADVANCED) uint32_t size_tcp, cont_len, tot_len; unsigned char *payload; #endif if (ip_header->protocol != IPPROTO_TCP) { tc_log_info(LOG_INFO, 0, "this is not a tcp packet"); return; } size_ip = ip_header->ihl << 2; tcp_header = (struct tcphdr*)((char *)ip_header + size_ip); memset(&msg, 0, sizeof(struct msg_server_s)); memcpy((void *) &(msg.ip_header), ip_header, sizeof(struct iphdr)); memcpy((void *) &(msg.tcp_header), tcp_header, sizeof(struct tcphdr)); #if (TCPCOPY_MYSQL_ADVANCED) tot_len = ntohs(ip_header->tot_len); size_tcp = tcp_header->doff << 2; cont_len = tot_len - size_ip - size_tcp; if (cont_len > 0) { payload = (unsigned char*)((char*)tcp_header + size_tcp); if (cont_len <= MAX_PAYLOAD_LEN) { /* * Only transfer payload if content length is less * than MAX_PAYLOAD_LEN */ memcpy((void *) &(msg.payload), payload, cont_len); } } #endif key = get_key(ip_header->daddr, tcp_header->dest); fd = hash_find(table, key); if ( NULL == fd ) { tc_log_debug0(LOG_DEBUG, 0, "fd is null"); delay_table_add(key, &msg); return ; } tc_socket_send((int) (long) fd, (char *) &msg, MSG_SERVER_SIZE); }
static bool send_version(int fd) { msg_client_t msg; memset(&msg, 0, sizeof(msg_client_t)); msg.client_ip = htonl(0); msg.client_port = htons(0); msg.type = htons(INTERNAL_VERSION); if (tc_socket_send(fd, (char *) &msg, MSG_CLIENT_SIZE) == TC_ERROR) { tc_log_info(LOG_ERR, 0, "send version error:%d", fd); return false; } return true; }
static bool send_router_info(tc_user_t *u, uint16_t type) { int i, fd; bool result = false; msg_client_t msg; connections_t *connections; memset(&msg, 0, sizeof(msg_client_t)); msg.client_ip = u->src_addr; msg.client_port = u->src_port; msg.type = htons(type); msg.target_ip = u->dst_addr; msg.target_port = u->dst_port; for (i = 0; i < clt_settings.real_servers.num; i++) { if (!clt_settings.real_servers.active[i]) { continue; } connections = &(clt_settings.real_servers.connections[i]); fd = connections->fds[connections->index]; connections->index = (connections->index + 1) % connections->num; if (fd == -1) { tc_log_info(LOG_WARN, 0, "sock invalid"); continue; } if (tc_socket_send(fd, (char *) &msg, MSG_CLIENT_SIZE) == TC_ERROR) { tc_log_info(LOG_ERR, 0, "fd:%d, msg client send error", fd); if (clt_settings.real_servers.active[i] != 0) { clt_settings.real_servers.active[i] = 0; clt_settings.real_servers.active_num--; } continue; } result = true; } return result; }
void buffer_and_send(int fd, msg_server_t *msg) { int ret = TC_OK, is_send = 0, bytes; unsigned char *p; aggregation_t *aggr; if (fd > srv_settings.max_fd) { srv_settings.max_fd = fd; } if (srv_settings.max_fd > MAX_FD_VALUE) { tc_log_info(LOG_WARN, 0, "fd is too large:%d", srv_settings.max_fd); srv_settings.max_fd = MAX_FD_VALUE; return; } if (!srv_settings.tunnel[fd].fd_valid) { tc_log_debug1(LOG_DEBUG, 0, "fd is not valid:%d", fd); return; } aggr = srv_settings.tunnel[fd].combined; if (!aggr) { aggr = (aggregation_t *) malloc(sizeof(aggregation_t)); if (aggr == NULL) { tc_log_info(LOG_ERR, errno, "can't malloc memory"); } else { tc_log_info(LOG_INFO, 0, "malloc memory for fd:%d", fd); memset(aggr, 0, sizeof(aggregation_t)); aggr->cur_write = aggr->aggr_resp; srv_settings.tunnel[fd].combined = aggr; } } if (aggr) { if (msg != NULL) { p = aggr->cur_write; memcpy((char *) p, (char *) msg, MSG_SERVER_SIZE); aggr->cur_write = p + MSG_SERVER_SIZE; aggr->num = aggr->num + 1; } else { if (aggr->num == 0) { return; } } if (aggr->num == COMB_MAX_NUM) { is_send = 1; } else if (aggr->access_time < tc_current_time_sec) { is_send = 1; } else if (aggr->access_time == tc_current_time_sec) { if (aggr->access_msec != tc_current_time_msec) { is_send = 1; } } if (is_send) { tc_log_debug1(LOG_DEBUG, 0, "combined send:%d", aggr->num); aggr->num = htons(aggr->num); p = (unsigned char *) (&(aggr->num)); bytes = aggr->cur_write - aggr->aggr_resp + sizeof(aggr->num); tc_log_debug1(LOG_DEBUG, 0, "send bytes:%d", bytes); ret = tc_socket_send(fd, (char *) p, bytes); aggr->num = 0; aggr->cur_write = aggr->aggr_resp; } aggr->access_time = tc_current_time_sec; aggr->access_msec = tc_current_time_msec; if (ret == TC_ERROR) { tc_intercept_release_tunnel(fd, NULL); } } }
void buffer_and_send(int mfd, int fd, msg_server_t *msg) { int ret = TC_OK, is_send = 0, bytes; unsigned char *p; aggregation_t *aggr; #if (TCPCOPY_SINGLE) if (mfd == 0) { return; } #endif if (fd > max_fd) { max_fd = fd; } if (max_fd > MAX_FD_VALUE) { tc_log_info(LOG_WARN, 0, "fd is too large:%d", max_fd); max_fd = MAX_FD_VALUE; return; } if (!fd_valid[fd]) { tc_log_debug1(LOG_DEBUG, 0, "fd is not valid:%d", fd); return; } aggr = combined[fd]; if (!aggr) { aggr = (aggregation_t *) malloc(sizeof(aggregation_t)); if (aggr == NULL) { tc_log_info(LOG_ERR, errno, "can't malloc memory"); } else { tc_log_info(LOG_INFO, 0, "malloc memory for fd:%d", fd); memset(aggr, 0, sizeof(aggregation_t)); aggr->cur_write = aggr->aggr_resp; combined[fd] = aggr; } } if (aggr) { if (msg != NULL) { p = aggr->cur_write; memcpy((char *) p, (char *) msg, MSG_SERVER_SIZE); aggr->cur_write = p + MSG_SERVER_SIZE; aggr->num = aggr->num + 1; } else { if (aggr->num == 0) { tc_log_debug0(LOG_DEBUG, 0, "combined num is zero"); return; } } if (aggr->num == COMB_MAX_NUM) { is_send = 1; } else if (aggr->access_time < tc_current_time_sec) { is_send = 1; } else if (aggr->access_time == tc_current_time_sec) { if (aggr->access_msec != tc_current_time_msec) { is_send = 1; } } if (is_send) { tc_log_debug1(LOG_DEBUG, 0, "combined send:%d", aggr->num); aggr->num = htons(aggr->num); p = (unsigned char *) (&(aggr->num)); bytes = aggr->cur_write - aggr->aggr_resp + sizeof(aggr->num); tc_log_debug1(LOG_DEBUG, 0, "send bytes:%d", bytes); #if (!TCPCOPY_SINGLE) ret = tc_socket_send(fd, (char *) p, bytes); #else ret = tc_socket_send(mfd, (char *) p, bytes); #endif aggr->num = 0; aggr->cur_write = aggr->aggr_resp; } aggr->access_time = tc_current_time_sec; aggr->access_msec = tc_current_time_msec; if (ret == TC_ERROR) { fd_valid[fd] = false; free(combined[fd]); combined[fd] = NULL; } } }
void router_update(int main_router_fd, tc_ip_header_t *ip_header) { #if (!TCPCOPY_SINGLE) void *fd; uint64_t key; #endif uint32_t size_ip, size_tcp, new_size_tcp; msg_server_t msg; tc_tcp_header_t *tcp_header; #if (TCPCOPY_MYSQL_ADVANCED) uint32_t cont_len, tot_len, new_tot_len; unsigned char *payload, *p; #endif #if (TCPCOPY_SINGLE) if (main_router_fd == 0) { return; } #endif if (ip_header->protocol != IPPROTO_TCP) { tc_log_info(LOG_INFO, 0, "this is not a tcp packet"); return; } size_ip = ip_header->ihl << 2; tcp_header = (tc_tcp_header_t *) ((char *) ip_header + size_ip); size_tcp = tcp_header->doff << 2; #if (TCPCOPY_MYSQL_ADVANCED) tot_len = ntohs(ip_header->tot_len); #endif memset(&msg, 0, sizeof(struct msg_server_s)); new_size_tcp = size_tcp; if (size_tcp > TCP_HEADER_MIN_LEN) { set_wscale(tcp_header); new_size_tcp = tcp_header->doff << 2; #if (TCPCOPY_MYSQL_ADVANCED) new_tot_len = tot_len - (size_tcp - new_size_tcp); ip_header->tot_len = htons(new_tot_len); #endif } memcpy((void *) &(msg.ip_header), ip_header, sizeof(tc_ip_header_t)); memcpy((void *) &(msg.tcp_header), tcp_header, new_size_tcp); #if (TCPCOPY_MYSQL_ADVANCED) cont_len = tot_len - size_ip - size_tcp; if (cont_len > 0) { payload = (unsigned char *) ((char *) tcp_header + size_tcp); if (cont_len <= MAX_PAYLOAD_LEN) { p = ((unsigned char *) &(msg.tcp_header)) + new_size_tcp; /* * only transfer payload if content length is less * than MAX_PAYLOAD_LEN */ memcpy((void *) p, payload, cont_len); } } #endif #if (!TCPCOPY_SINGLE) key = get_key(ip_header->daddr, tcp_header->dest); fd = hash_find(table, key); if (fd == NULL) { if (!tcp_header->syn) { tc_log_info(LOG_NOTICE, 0, "fd is null after session is created"); tc_log_trace(LOG_NOTICE, 0, BACKEND_FLAG, ip_header, tcp_header); } tc_log_debug0(LOG_DEBUG, 0, "fd is null"); fd_null_cnt++; delay_table_add(key, &msg); return ; } #endif tc_log_debug_trace(LOG_NOTICE, 0, BACKEND_FLAG, ip_header, tcp_header); #if (INTERCEPT_COMBINED) #if (!TCPCOPY_SINGLE) buffer_and_send(main_router_fd, (int) (long) fd, &msg); #else buffer_and_send(main_router_fd, main_router_fd, &msg); #endif #else #if (!TCPCOPY_SINGLE) tc_socket_send((int) (long) fd, (char *) &msg, MSG_SERVER_SIZE); #else tc_socket_send(main_router_fd, (char *) &msg, MSG_SERVER_SIZE); #endif #endif }
/* update router table */ void router_update(int main_router_fd, tc_ip_header_t *ip_header, int len) { #if (!TCPCOPY_SINGLE) void *fd; uint64_t key; #endif uint32_t size_ip; msg_server_t msg; tc_tcp_header_t *tcp_header; #if (TCPCOPY_SINGLE) if (main_router_fd == 0) { return; } #endif if (ip_header->protocol != IPPROTO_TCP) { tc_log_info(LOG_INFO, 0, "this is not a tcp packet"); return; } size_ip = ip_header->ihl << 2; tcp_header = (tc_tcp_header_t *) ((char *) ip_header + size_ip); tc_log_debug1(LOG_DEBUG, 0, "router update:%u", ntohs(tcp_header->source)); memcpy(&msg, ip_header, len); #if (!TCPCOPY_SINGLE) key = get_key(ip_header->daddr, tcp_header->dest); pthread_mutex_lock(&mutex); fd = hash_find(table, key); if (fd == NULL) { if (!tcp_header->syn) { tc_log_info(LOG_NOTICE, 0, "fd is null after session is created"); tc_log_trace(LOG_NOTICE, 0, BACKEND_FLAG, ip_header, tcp_header); } tc_log_debug0(LOG_DEBUG, 0, "fd is null"); fd_null_cnt++; delay_table_add(key, &msg); pthread_mutex_unlock(&mutex); return ; } pthread_mutex_unlock(&mutex); #endif tc_log_debug_trace(LOG_NOTICE, 0, BACKEND_FLAG, ip_header, tcp_header); #if (INTERCEPT_COMBINED) #if (!TCPCOPY_SINGLE) buffer_and_send(main_router_fd, (int) (long) fd, &msg); #else buffer_and_send(main_router_fd, main_router_fd, &msg); #endif #else #if (!TCPCOPY_SINGLE) tc_socket_send((int) (long) fd, (char *) &msg, MSG_SERVER_SIZE); #else tc_socket_send(main_router_fd, (char *) &msg, MSG_SERVER_SIZE); #endif #endif }
void router_update(int old, int main_router_fd, tc_ip_header_t *ip_header) { #if (!TCPCOPY_SINGLE) int fd; uint32_t key; #endif uint32_t size_ip, size_tcp, tot_len; msg_server_t msg; tc_tcp_header_t *tcp_header; #if (TCPCOPY_MYSQL_ADVANCED) uint32_t cont_len; unsigned char *payload, *p; #endif #if (TCPCOPY_SINGLE) if (main_router_fd == 0) { return; } #endif if (ip_header->protocol != IPPROTO_TCP) { tc_log_info(LOG_INFO, 0, "this is not a tcp packet"); return; } size_ip = ip_header->ihl << 2; tcp_header = (tc_tcp_header_t *) ((char *) ip_header + size_ip); size_tcp = tcp_header->doff << 2; tot_len = ntohs(ip_header->tot_len); memset(&msg, 0, sizeof(struct msg_server_s)); memcpy((void *) &(msg.ip_header), ip_header, sizeof(tc_ip_header_t)); memcpy((void *) &(msg.tcp_header), tcp_header, size_tcp); #if (TCPCOPY_MYSQL_ADVANCED) cont_len = tot_len - size_ip - size_tcp; if (cont_len > 0) { payload = (unsigned char *) ((char *) tcp_header + size_tcp); if (cont_len <= MAX_PAYLOAD_LEN) { p = ((unsigned char *) &(msg.tcp_header)) + size_tcp; memcpy((void *) p, payload, cont_len); } } #endif #if (!TCPCOPY_SINGLE) key = get_route_key(old, ip_header->daddr, tcp_header->dest, ip_header->saddr, tcp_header->source); fd = router_get(key); if (fd <= 0) { if (tcp_header->syn || tcp_header->rst) { if (tcp_header->rst) { tc_log_info(LOG_NOTICE, 0, "reset from tcp"); } tc_log_debug0(LOG_DEBUG, 0, "fd is null"); delay_table_add(key, &msg); return ; } else { tc_log_info(LOG_NOTICE, 0, "fd is null after session is created"); tc_log_trace(LOG_NOTICE, 0, BACKEND_FLAG, ip_header, tcp_header); return; } } #endif tc_log_debug_trace(LOG_NOTICE, 0, BACKEND_FLAG, ip_header, tcp_header); #if (INTERCEPT_COMBINED) #if (!TCPCOPY_SINGLE) buffer_and_send(main_router_fd, (int) (long) fd, &msg); #else buffer_and_send(main_router_fd, main_router_fd, &msg); #endif #else #if (!TCPCOPY_SINGLE) tc_socket_send((int) (long) fd, (char *) &msg, MSG_SERVER_SIZE); #else tc_socket_send(main_router_fd, (char *) &msg, MSG_SERVER_SIZE); #endif #endif }