static int dispose_packet(char *recv_buf, int recv_len, int *p_valid_flag) { int replica_num, i, last, packet_num, max_payload, index, payload_len; char *packet, tmp_buf[RECV_BUF_SIZE]; bool packet_valid = false; uint16_t id, size_ip, size_tcp, tot_len, cont_len, pack_len = 0, head_len; uint32_t seq; tc_ip_header_t *ip_header; tc_tcp_header_t *tcp_header; packet = recv_buf; if (is_packet_needed((const char *) packet)) { replica_num = clt_settings.replica_num; packet_num = 1; ip_header = (tc_ip_header_t *)packet; if (localhost == ip_header->saddr) { if (clt_settings.lo_tf_ip != 0) { ip_header->saddr = clt_settings.lo_tf_ip; } } /* * If the packet length is larger than MTU, we split it. * This is to solve the ip fragmentation problem */ if (recv_len > clt_settings.mtu) { /* calculate number of packets */ size_ip = ip_header->ihl << 2; tot_len = ntohs(ip_header -> tot_len); if (tot_len != recv_len) { tc_log_info(LOG_WARN, 0, "packet len:%u, recv len:%u", tot_len, recv_len); return TC_ERROR; } tcp_header = (tc_tcp_header_t *) ((char *) ip_header + size_ip); size_tcp = tcp_header->doff << 2; cont_len = tot_len - size_tcp - size_ip; head_len = size_ip + size_tcp; max_payload = clt_settings.mtu - head_len; packet_num = (cont_len + max_payload - 1)/max_payload; seq = ntohl(tcp_header->seq); last = packet_num - 1; id = ip_header->id; #if (TCPCOPY_DEBUG) tc_log_trace(LOG_NOTICE, 0, CLIENT_FLAG, ip_header, tcp_header); #endif tc_log_debug1(LOG_DEBUG, 0, "recv:%d, more than MTU", recv_len); index = head_len; for (i = 0 ; i < packet_num; i++) { tcp_header->seq = htonl(seq + i * max_payload); if (i != last) { pack_len = clt_settings.mtu; } else { pack_len += (cont_len - packet_num * max_payload); } payload_len = pack_len - head_len; ip_header->tot_len = htons(pack_len); ip_header->id = id++; /* copy header here */ memcpy(tmp_buf, recv_buf, head_len); /* copy payload here */ memcpy(tmp_buf + head_len, recv_buf + index, payload_len); index = index + payload_len; if (replica_num > 1) { packet_valid = process_packet(true, tmp_buf, pack_len); replicate_packs(tmp_buf, pack_len, replica_num); } else { packet_valid = process_packet(false, tmp_buf, pack_len); } } } else { if (replica_num > 1) { packet_valid = process_packet(true, packet, recv_len); replicate_packs(packet, recv_len, replica_num); } else { packet_valid = process_packet(false, packet, recv_len); } } } if (p_valid_flag) { *p_valid_flag = (packet_valid == true ? 1 : 0); } return TC_OK; }
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 }
static bool process_packet(tc_user_t *u, unsigned char *frame) { bool result; uint16_t size_ip, size_tcp, tot_len, cont_len; uint32_t h_ack, h_last_ack; tc_ip_header_t *ip_header; tc_tcp_header_t *tcp_header; ip_port_pair_mapping_t *test; ip_header = (tc_ip_header_t *) (frame + ETHERNET_HDR_LEN); 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); cont_len = tot_len - size_tcp - size_ip; if (u->dst_port == 0) { test = get_test_pair(&(clt_settings.transfer), ip_header->daddr, tcp_header->dest); if (test == NULL) { tc_log_info(LOG_NOTICE, 0, " test null:%u", ntohs(tcp_header->dest)); tc_log_trace(LOG_WARN, 0, TO_BAKEND_FLAG, ip_header, tcp_header); return false; } u->dst_addr = test->target_ip; u->dst_port = test->target_port; #if (GRYPHON_PCAP_SEND) u->src_mac = test->src_mac; u->dst_mac = test->dst_mac; #endif } if (u->state.last_ack_recorded) { if (u->state.status < SEND_REQ && (u->state.status & SYN_CONFIRM)) { h_ack = ntohl(tcp_header->ack_seq); h_last_ack = ntohl(u->history_last_ack_seq); if (after(h_ack, h_last_ack)) { tc_log_debug1(LOG_DEBUG, 0, "server resp first, wait, p:%u", ntohs(u->src_port)); u->state.resp_waiting = 1; return false; } } } ip_header->saddr = u->src_addr; tcp_header->source = u->src_port; u->history_last_ack_seq = tcp_header->ack_seq; u->state.last_ack_recorded = 1; tcp_header->ack_seq = u->exp_ack_seq; ip_header->daddr = u->dst_addr; tcp_header->dest = u->dst_port; tc_log_debug2(LOG_DEBUG, 0, "set ack seq:%u, p:%u", ntohl(u->exp_ack_seq), ntohs(u->src_port)); packs_sent_cnt++; if (tcp_header->syn) { syn_sent_cnt++; #if (!GRYPHON_SINGLE) if (!send_router_info(u, CLIENT_ADD)) { return false; } #endif u->state.last_ack_recorded = 0; u->state.status |= SYN_SENT; } else if (tcp_header->fin) { fin_sent_cnt++; u->state.status |= CLIENT_FIN; } else if (tcp_header->rst) { rst_sent_cnt++; u->state.status |= CLIENT_FIN; tc_log_debug1(LOG_DEBUG, 0, "a reset packet to back:%u", ntohs(u->src_port)); } if (cont_len > 0) { cont_sent_cnt++; u->state.status |= SEND_REQ; } if (u->state.timestamped) { update_timestamp(u, tcp_header); } tcp_header->check = 0; tcp_header->check = tcpcsum((unsigned char *) ip_header, (unsigned short *) tcp_header, (int) (tot_len - size_ip)); #if (GRYPHON_PCAP_SEND) ip_header->check = 0; ip_header->check = csum((unsigned short *) ip_header,size_ip); #endif tc_log_debug_trace(LOG_DEBUG, 0, TO_BAKEND_FLAG, ip_header, tcp_header); #if (!GRYPHON_PCAP_SEND) result = tc_raw_socket_send(tc_raw_socket_out, ip_header, tot_len, ip_header->daddr); #else fill_frame((struct ethernet_hdr *) frame, u->src_mac, u->dst_mac); result = tc_pcap_send(frame, tot_len + ETHERNET_HDR_LEN); #endif if (result == TC_OK) { u->last_sent_time = tc_time(); return true; } else { tc_log_info(LOG_ERR, 0, "send to back error,tot_len is:%d,cont_len:%d", tot_len,cont_len); #if (!TCPCOPY_PCAP_SEND) tc_raw_socket_out = TC_INVALID_SOCKET; #endif tc_over = SIGRTMAX; return false; } }
static int dispose_packet(unsigned char *frame, int frame_len, int ip_recv_len, int *p_valid_flag) { int replica_num, i, last, packet_num, max_payload, index, payload_len; char *p, buf[ETHERNET_HDR_LEN + IP_RECV_BUF_SIZE]; bool packet_valid = false; uint16_t id, size_ip, size_tcp, tot_len, cont_len, pack_len = 0, head_len; uint32_t seq; unsigned char *packet; tc_ip_header_t *ip_header; tc_tcp_header_t *tcp_header; packet = frame + ETHERNET_HDR_LEN; if (is_packet_needed(packet)) { replica_num = clt_settings.replica_num; ip_header = (tc_ip_header_t *) packet; if (clt_settings.clt_tf_ip != 0) { ip_header->saddr = clt_settings.clt_tf_ip; } /* * If the packet length is larger than MTU, we split it. */ if (ip_recv_len > clt_settings.mtu) { /* calculate number of packets */ size_ip = ip_header->ihl << 2; tot_len = ntohs(ip_header -> tot_len); if (tot_len != ip_recv_len) { tc_log_info(LOG_WARN, 0, "packet len:%u, recv len:%u", tot_len, ip_recv_len); return TC_ERROR; } tcp_header = (tc_tcp_header_t *) ((char *) ip_header + size_ip); size_tcp = tcp_header->doff << 2; cont_len = tot_len - size_tcp - size_ip; head_len = size_ip + size_tcp; max_payload = clt_settings.mtu - head_len; packet_num = (cont_len + max_payload - 1)/max_payload; seq = ntohl(tcp_header->seq); last = packet_num - 1; id = ip_header->id; #if (TCPCOPY_DEBUG) tc_log_trace(LOG_NOTICE, 0, CLIENT_FLAG, ip_header, tcp_header); #endif tc_log_debug1(LOG_DEBUG, 0, "recv:%d, more than MTU", ip_recv_len); index = head_len; for (i = 0 ; i < packet_num; i++) { tcp_header->seq = htonl(seq + i * max_payload); if (i != last) { pack_len = clt_settings.mtu; } else { pack_len += (cont_len - packet_num * max_payload); } payload_len = pack_len - head_len; ip_header->tot_len = htons(pack_len); ip_header->id = id++; p = buf + ETHERNET_HDR_LEN; /* copy header here */ memcpy(p, (char *) packet, head_len); p += head_len; /* copy payload here */ memcpy(p, (char *) (packet + index), payload_len); index = index + payload_len; if (replica_num > 1) { packet_valid = process_packet(true, (unsigned char *) buf, ETHERNET_HDR_LEN + pack_len); replicate_packs((unsigned char *) buf, ETHERNET_HDR_LEN + pack_len, replica_num); } else { packet_valid = process_packet(false, (unsigned char *) buf, ETHERNET_HDR_LEN + pack_len); } } } else { if (replica_num > 1) { packet_valid = process_packet(true, frame, frame_len); replicate_packs(frame, frame_len, replica_num); } else { packet_valid = process_packet(false, frame, frame_len); } } } if (p_valid_flag) { *p_valid_flag = (packet_valid == true ? 1 : 0); } return TC_OK; }
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 }