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; }
static void interception_process(int fd) { int diff, new_fd, i, pass_through_flag = 0; time_t now; unsigned long packet_id; struct iphdr *ip_header; struct msg_client_s *c_msg; if(fd == msg_listen_sock){ new_fd = accept(msg_listen_sock, NULL, NULL); set_sock_no_delay(new_fd); if(new_fd != -1){ select_server_add(new_fd); } }else if(fd == firewall_sock){ packet_id = 0; ip_header = nl_firewall_recv(firewall_sock, &packet_id); if(ip_header != NULL){ /* Check if it is the valid user to pass through firewall */ for(i = 0; i < srv_settings.passed_ips.num; i++){ if(srv_settings.passed_ips.ips[i] == ip_header->daddr){ pass_through_flag = 1; break; } } if(pass_through_flag){ /* Pass through the firewall */ dispose_netlink_packet(NF_ACCEPT, packet_id); }else{ router_update(ip_header); now = time(0); diff = now - last_clean_time; if(diff > CHECK_INTERVAL){ route_delete_obsolete(now); delay_table_delete_obsolete(now); last_clean_time = now; } /* Drop the packet */ dispose_netlink_packet(NF_DROP, packet_id); } } }else{ c_msg = msg_server_recv(fd); if(c_msg){ if(c_msg->type == CLIENT_ADD){ tc_log_debug1(LOG_NOTICE, "add client router:%u", ntohs(c_msg->client_port)); router_add(c_msg->client_ip, c_msg->client_port, fd); }else if(c_msg->type == CLIENT_DEL){ tc_log_debug1(LOG_NOTICE, "del client router:%u", ntohs(c_msg->client_port)); router_del(c_msg->client_ip, c_msg->client_port); } }else{ close(fd); select_server_del(fd); log_info(LOG_NOTICE, "close sock:%d", fd); } } }
int tc_socket_cmb_recv(int fd, int *num, char *buffer) { int read_num = 0; size_t last; ssize_t n, len; last = 0; len = sizeof(uint16_t); for ( ;; ) { n = recv(fd, buffer + last, len, 0); if (n == -1) { if (errno == EAGAIN || errno == EINTR) { continue; } else { tc_log_info(LOG_NOTICE, errno, "return -1,fd:%d", fd); return TC_ERROR; } } if (n == 0) { tc_log_info(LOG_NOTICE, 0, "recv length 0,fd:%d", fd); return TC_ERROR; } last += n; tc_log_debug1(LOG_DEBUG, 0, "current len:%d", len); if ((!read_num) && last >= sizeof(uint16_t)) { *num = (int) ntohs(*(uint16_t *) buffer); if (*num > COMB_MAX_NUM) { tc_log_info(LOG_WARN, 0, "num:%d larger than threshold", *num); return TC_ERROR; } read_num = 1; len = ((*num) * MSG_SERVER_SIZE) + len; tc_log_debug2(LOG_DEBUG, 0, "all bytes needed reading:%d,num:%d", len, *num); } tc_log_debug1(LOG_DEBUG, 0, "this time reading:%d", n); if ((len -= n) == 0) { tc_log_debug1(LOG_DEBUG, 0, "remain readed:%d", len); break; } if (len < 0) { tc_log_info(LOG_WARN, 0, "read:%d,num packs:%d, remain:%d", n, *num, len); break; } tc_log_debug1(LOG_DEBUG, 0, "remain readed:%d", len); } return TC_OK; }
/* replicate packets for multiple-copying */ static void replicate_packs(char *packet, int length, int replica_num) { int i; uint16_t orig_port, addition, dest_port, rand_port; uint32_t size_ip; tc_tcp_header_t *tcp_header; tc_ip_header_t *ip_header; ip_header = (tc_ip_header_t *) packet; size_ip = ip_header->ihl << 2; tcp_header = (tc_tcp_header_t *) ((char *) ip_header + size_ip); rand_port = clt_settings.rand_port_shifted; orig_port = ntohs(tcp_header->source); tc_log_debug1(LOG_DEBUG, 0, "orig port:%u", orig_port); for (i = 1; i < replica_num; i++) { addition = (((i << 1) - 1) << 5) + rand_port; dest_port = get_appropriate_port(orig_port, addition); tcp_header->source = htons(dest_port); process_packet(true, packet, length); tc_log_debug2(LOG_DEBUG, 0, "new port:%u,add:%u", dest_port, addition); } }
static void replicate_packs(unsigned char *frame, int frame_len, int replica_num) { int i; uint32_t size_ip; uint16_t orig_port, addition, dest_port, rand_port; unsigned char *packet; tc_ip_header_t *ip_header; tc_udp_header_t *udp_header; packet = frame + ETHERNET_HDR_LEN; ip_header = (tc_ip_header_t *) packet; size_ip = ip_header->ihl << 2; udp_header = (tc_udp_header_t *) ((char *) ip_header + size_ip); orig_port = ntohs(udp_header->source); tc_log_debug1(LOG_DEBUG, 0, "orig port:%u", orig_port); rand_port = clt_settings.rand_port_shifted; for (i = 1; i < replica_num; i++) { addition = (((i << 1) - 1) << 5) + rand_port; dest_port = get_appropriate_port(orig_port, addition); tc_log_debug2(LOG_DEBUG, 0, "new port:%u,add:%u", dest_port, addition); udp_header->source = htons(dest_port); process_packet(true, frame, frame_len); } }
static bool check_pack_needed_for_recons(tc_sess_t *s, tc_iph_t *ip, tc_tcph_t *tcp) { uint16_t size_tcp; p_link_node ln; unsigned char *payload, command, *pkt; mysql_table_item_t *item; if (s->cur_pack.cont_len > 0) { size_tcp = tcp->doff << 2; payload = (unsigned char *) ((char *) tcp + size_tcp); /* skip packet length */ payload = payload + 3; /* skip packet number */ payload = payload + 1; command = payload[0]; if (command != COM_STMT_PREPARE) { return false; } item = hash_find(ctx.table, s->hash_key); if (!item) { item = tc_pcalloc(ctx.pool, sizeof(mysql_table_item_t)); if (item != NULL) { item->list = link_list_create(ctx.pool); if (item->list != NULL) { hash_add(ctx.table, ctx.pool, s->hash_key, item); if (ctx.table->total > MAX_TABLE_ITEM_NUM) { tc_log_info(LOG_INFO, 0, "too many items in ctx.table"); } } else { tc_log_info(LOG_ERR, 0, "list create err"); return false; } } else { tc_log_info(LOG_ERR, 0, "mysql item create err"); return false; } } if (item->list->size > MAX_SP_SIZE) { tc_log_info(LOG_INFO, 0, "too many prepared stmts for a session"); return false; } tc_log_debug1(LOG_INFO, 0, "push packet:%u", ntohs(s->src_port)); pkt = (unsigned char *) cp_fr_ip_pack(ctx.pool, ip); ln = link_node_malloc(ctx.pool, pkt); ln->key = ntohl(tcp->seq); link_list_append_by_order(item->list, ln); item->tot_cont_len += s->cur_pack.cont_len; return true; } return false; }
static void update_ack_packets(tc_user_t *u, uint32_t cur_ack_seq) { frame_t *unack_frame, *next; unack_frame = u->orig_unack_frame; if (unack_frame == NULL) { return; } next = unack_frame->next; while (true) { if (unack_frame == u->orig_frame) { break; } if (next != NULL) { if (next->seq == cur_ack_seq) { u->orig_unack_frame = unack_frame->next; break; } else if (before(cur_ack_seq, next->seq) && before(unack_frame->seq, cur_ack_seq)) { tc_log_debug1(LOG_DEBUG, 0, "partially acked:%u", ntohs(u->src_port)); break; } else { tc_log_debug1(LOG_DEBUG, 0, "skipped:%u", ntohs(u->src_port)); unack_frame = next; next = unack_frame->next; if (unack_frame == u->orig_session->last_frame) { break; } } } else { if (before(unack_frame->seq, cur_ack_seq)) { unack_frame = unack_frame->next; } u->orig_unack_frame = unack_frame; break; } } }
static void update_timestamp(tc_user_t *u, tc_tcp_header_t *tcp_header) { uint32_t ts; unsigned int opt, opt_len; unsigned char *p, *end; p = ((unsigned char *) tcp_header) + TCP_HEADER_MIN_LEN; end = ((unsigned char *) tcp_header) + (tcp_header->doff << 2); while (p < end) { opt = p[0]; switch (opt) { case TCPOPT_TIMESTAMP: if ((p + 1) >= end) { return; } opt_len = p[1]; if ((p + opt_len) <= end) { ts = htonl(u->ts_ec_r); tc_log_debug2(LOG_DEBUG, 0, "set ts reply:%u,p:%u", u->ts_ec_r, ntohs(u->src_port)); bcopy((void *) &ts, (void *) (p + 6), sizeof(ts)); ts = EXTRACT_32BITS(p + 2); if (ts < u->ts_value) { tc_log_debug1(LOG_DEBUG, 0, "ts < history,p:%u", ntohs(u->src_port)); ts = htonl(u->ts_value); bcopy((void *) &ts, (void *) (p + 2), sizeof(ts)); } else { u->ts_value = ts; } } return; case TCPOPT_NOP: p = p + 1; break; case TCPOPT_EOL: return; default: if ((p + 1) >= end) { return; } opt_len = p[1]; if (opt_len < 2) { tc_log_info(LOG_WARN, 0, "opt len:%d", opt_len); return; } p += opt_len; break; } } return; }
static void process_user_packet(tc_user_t *u) { unsigned char frame[MAX_FRAME_LENGTH]; if (send_stop(u)) { return; } while (true) { if (u->orig_frame->frame_len > MAX_FRAME_LENGTH) { tc_log_info(LOG_NOTICE, 0, " frame length may be damaged"); } memcpy(frame, u->orig_frame->frame_data, u->orig_frame->frame_len); process_packet(u, frame); u->total_packets_sent++; u->orig_frame = u->orig_frame->next; if (send_stop(u)) { break; } tc_log_debug1(LOG_DEBUG, 0, "check resp waiting:%u", ntohs(u->src_port)); if (!u->orig_frame->belong_to_the_same_req) { tc_log_debug2(LOG_DEBUG, 0, "user state:%d,port:%u", u->state.status, ntohs(u->src_port)); if (u->state.status & SYN_CONFIRM) { tc_log_debug1(LOG_DEBUG, 0, "set resp waiting:%u", ntohs(u->src_port)); u->state.resp_waiting = 1; } break; } else { tc_log_debug1(LOG_DEBUG, 0, "the same req:%u", ntohs(u->src_port)); } } }
static void fast_retransmit(tc_user_t *u, uint32_t cur_ack_seq) { frame_t *unack_frame, *next; unack_frame = u->orig_unack_frame; if (unack_frame == NULL) { return; } next = unack_frame->next; while (true) { if (unack_frame == u->orig_frame) { break; } if (unack_frame->seq == cur_ack_seq) { tc_log_debug1(LOG_DEBUG, 0, "packets retransmitted:%u", ntohs(u->src_port)); process_packet(u, unack_frame->frame_data); break; } else if (before(unack_frame->seq, cur_ack_seq) && next != NULL && before(cur_ack_seq, next->seq)) { process_packet(u, unack_frame->frame_data); break; } else if (before(unack_frame->seq, cur_ack_seq)) { unack_frame = next; if (unack_frame == NULL) { break; } next = unack_frame->next; } else { tc_log_debug1(LOG_DEBUG, 0, "packets retransmitted not match:%u", ntohs(u->src_port)); break; } } }
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_debug1(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; }
int tc_socket_send(int fd, char *buffer, int len) { int cnt = 0; 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 (cnt > MAX_RW_TRIES) { tc_log_info(LOG_ERR, 0, "send timeout,fd:%d", fd); return TC_ERROR; } if (errno == EINTR) { tc_log_info(LOG_NOTICE, errno, "fd:%d EINTR", fd); cnt++; } else if (errno == EAGAIN) { tc_log_debug1(LOG_NOTICE, errno, "fd:%d EAGAIN", fd); cnt++; } else { tc_log_info(LOG_ERR, errno, "fd:%d", 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; num_bytes -= send_len; } } while (offset < len); return TC_OK; }
void tc_event_expire_timers(void) { tc_event_timer_t *ev; tc_rbtree_node_t *node, *root, *sentinel; sentinel = tc_event_timer_rbtree.sentinel; for ( ;; ) { root = tc_event_timer_rbtree.root; if (root == sentinel) { return; } node = tc_rbtree_min(root, sentinel); /* node->key <= tc_current_time */ if ((tc_msec_int_t) (node->key - tc_current_time_msec) <= 0) { ev = (tc_event_timer_t *) ((char *) node - offsetof(tc_event_timer_t, timer)); #if (TC_DEBUG) tc_log_debug1(LOG_DEBUG, 0, "del timer:%llu", ev); #endif tc_rbtree_delete(&tc_event_timer_rbtree, &ev->timer); ev->timer_set = 0; ev->handler(ev); continue; } break; } }
tc_event_timer_t* tc_event_add_timer(tc_pool_t *pool, tc_msec_t timer, void *data, tc_event_timer_handler_pt handler) { tc_msec_t key; tc_event_timer_t *ev; ev = (tc_event_timer_t *) tc_palloc(pool, sizeof(tc_event_timer_t)); if (ev != NULL) { ev->pool = pool; ev->handler = handler; ev->data = data; key = ((tc_msec_t) tc_current_time_msec) + timer; ev->timer.key = key; tc_rbtree_insert(&tc_event_timer_rbtree, &ev->timer); tc_log_debug1(LOG_DEBUG, 0, "add timer:%llu", ev); ev->timer_set = 1; } return ev; }
static bool check_renew_session(tc_iph_t *ip, tc_tcph_t *tcp) { uint16_t size_ip, size_tcp, tot_len, cont_len; unsigned char *payload, command, pack_number; if (ctx.fir_auth_pack == NULL) { tc_log_debug0(LOG_DEBUG, 0, "fir auth packet is null"); return false; } size_ip = ip->ihl << 2; size_tcp = tcp->doff << 2; tot_len = ntohs(ip->tot_len); cont_len = tot_len - size_tcp - size_ip; if (cont_len > 0) { payload = (unsigned char *) ((char *) tcp + size_tcp); /* skip packet length */ payload = payload + 3; /* retrieve packet number */ pack_number = payload[0]; /* if it is the second authenticate_user, skip it */ if (pack_number != 0) { return false; } /* skip packet number */ payload = payload + 1; command = payload[0]; tc_log_debug1(LOG_DEBUG, 0, "mysql command:%u", command); if (command == COM_QUERY || command == COM_STMT_EXECUTE) { return true; } } return false; }
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; }
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; }
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; }
static bool send_stop(tc_user_t *u) { int send_diff; long app_resp_diff; uint32_t srv_sk_buf_s; if (u->orig_frame == NULL) { tc_log_debug1(LOG_DEBUG, 0, "orig frame is null :%d", ntohs(u->src_port)); return true; } if (u->state.status & SYN_SENT) { if (!(u->state.status & SYN_CONFIRM)) { tc_log_debug1(LOG_DEBUG, 0, "client wait server handshake:%d", ntohs(u->src_port)); return true; } } if (u->state.status & CLIENT_FIN) { if (!(u->state.status & SERVER_FIN)) { tc_log_debug1(LOG_DEBUG, 0, "client wait server fin:%d", ntohs(u->src_port)); return true; } } send_diff = tc_time() - u->last_sent_time; if (send_diff >= 3) { tc_log_debug1(LOG_DEBUG, 0, "timeout, need to send more packet:%d", ntohs(u->src_port)); u->state.resp_waiting = 0; return false; } if (u->state.resp_waiting) { tc_log_debug1(LOG_DEBUG, 0, "client wait server resp:%d", ntohs(u->src_port)); return true; } if (u->state.status & SEND_REQ) { if (u->orig_frame->next != NULL) { srv_sk_buf_s = u->orig_frame->next->seq - u->orig_frame->seq; srv_sk_buf_s = srv_sk_buf_s + u->orig_frame->seq - u->last_ack_seq; if (srv_sk_buf_s > u->srv_window) { tc_log_debug3(LOG_DEBUG, 0, "wait,srv_sk_buf_s:%u,win:%u,p:%u", srv_sk_buf_s, u->srv_window, ntohs(u->src_port)); return true; } } } app_resp_diff = tc_milliscond_time() - u->last_recv_resp_cont_time; if (app_resp_diff <= 10) { tc_log_debug1(LOG_DEBUG, 0, "need to wait resp complete:%d", ntohs(u->src_port)); return true; } tc_log_debug1(LOG_DEBUG, 0, "last resort, set stop false:%d", ntohs(u->src_port)); return false; }
void process_outgress(unsigned char *packet) { uint16_t size_ip, size_tcp, tot_len, cont_len; uint32_t seq, ack_seq; uint64_t key; tc_user_t *u; tc_ip_header_t *ip_header; tc_tcp_header_t *tcp_header; last_resp_time = tc_time(); resp_cnt++; ip_header = (tc_ip_header_t *) packet; size_ip = ip_header->ihl << 2; tcp_header = (tc_tcp_header_t *) ((char *) ip_header + size_ip); key = tc_get_key(ip_header->daddr, tcp_header->dest); tc_log_debug1(LOG_DEBUG, 0, "key from bak:%llu", key); u = tc_retrieve_user(key); if (u != NULL) { tc_log_debug_trace(LOG_DEBUG, 0, BACKEND_FLAG, ip_header, tcp_header); u->srv_window = ntohs(tcp_header->window); if (u->wscale) { u->srv_window = u->srv_window << (u->wscale); tc_log_debug1(LOG_DEBUG, 0, "window size:%u", u->srv_window); } if (u->state.timestamped) { retrieve_options(u, REMOTE, tcp_header); } size_tcp = tcp_header->doff << 2; tot_len = ntohs(ip_header->tot_len); cont_len = tot_len - size_tcp - size_ip; if (ip_header->daddr != u->src_addr || tcp_header->dest!= u->src_port) { tc_log_info(LOG_NOTICE, 0, " key conflict"); } seq = ntohl(tcp_header->seq); u->exp_seq = tcp_header->ack_seq; ack_seq = ntohl(tcp_header->ack_seq); if (u->last_seq == seq && u->last_ack_seq == ack_seq) { u->fast_retransmit_cnt++; if (u->fast_retransmit_cnt == 3) { fast_retransmit(u, ack_seq); return; } } else { update_ack_packets(u, ack_seq); u->fast_retransmit_cnt = 0; } u->last_ack_seq = ack_seq; u->last_seq = seq; if (cont_len > 0) { u->last_recv_resp_cont_time = tc_milliscond_time(); resp_cont_cnt++; u->state.resp_waiting = 0; u->exp_ack_seq = htonl(seq + cont_len); send_faked_ack(u); } else { u->exp_ack_seq = tcp_header->seq; } if (tcp_header->syn) { tc_log_debug1(LOG_DEBUG, 0, "recv syn from back:%u", ntohs(u->src_port)); u->exp_ack_seq = htonl(ntohl(u->exp_ack_seq) + 1); if (!u->state.resp_syn_received) { conn_cnt++; active_conn_cnt++; u->state.resp_syn_received = 1; u->state.status |= SYN_CONFIRM; tc_log_debug2(LOG_DEBUG, 0, "exp ack seq:%u, p:%u", ntohl(u->exp_ack_seq), ntohs(u->src_port)); if (size_tcp > TCP_HEADER_MIN_LEN) { retrieve_options(u, REMOTE, tcp_header); if (u->wscale > 0) { tc_log_debug2(LOG_DEBUG, 0, "wscale:%u, p:%u", u->wscale, ntohs(u->src_port)); } } process_user_packet(u); } else { tc_log_debug1(LOG_DEBUG, 0, "syn, but already syn received:%u", ntohs(u->src_port)); } } else if (tcp_header->fin) { tc_log_debug1(LOG_DEBUG, 0, "recv fin from back:%u", ntohs(u->src_port)); u->exp_ack_seq = htonl(ntohl(u->exp_ack_seq) + 1); u->state.status |= SERVER_FIN; send_faked_ack(u); process_user_packet(u); fin_recv_cnt++; } else if (tcp_header->rst) { tc_log_info(LOG_NOTICE, 0, "recv rst from back:%u", ntohs(u->src_port)); rst_recv_cnt++; if (u->state.status == SYN_SENT) { if (!u->state.over) { conn_reject_cnt++; } } u->state.over = 1; u->state.status |= SERVER_FIN; } } else { tc_log_debug_trace(LOG_DEBUG, 0, BACKEND_FLAG, ip_header, tcp_header); tc_log_debug0(LOG_DEBUG, 0, "no active session for me"); } }
static int tc_msg_event_proc(tc_event_t *rev) { msg_clt_t msg; register int fd, version; tunnel_basic_t *tunnel; fd = rev->fd; tunnel = srv_settings.tunnel; if (!tunnel[fd].first_in) { if (tc_socket_rcv(fd, (char *) &msg, tunnel[fd].clt_msg_size) == TC_ERR) { tc_intercept_release_tunnel(fd, rev); return TC_ERR; } } else { if (tc_socket_rcv(fd, (char *) &msg, MSG_CLT_MIN_SIZE) != TC_ERR) { tunnel[fd].first_in = 0; version = ntohs(msg.type); if (msg.clt_ip != 0 || msg.clt_port != 0) { tc_log_info(LOG_ERR, 0, "client too old for intercept"); return TC_ERR; } else { if (version != INTERNAL_VERSION) { tc_log_info(LOG_WARN, 0, "not compatible,client:%d,intercept:%d", msg.type, INTERNAL_VERSION); } tunnel[fd].clt_msg_size = MSG_CLT_SIZE; if (tc_socket_rcv(fd, ((char *) &msg + MSG_CLT_MIN_SIZE), MSG_CLT_SIZE - MSG_CLT_MIN_SIZE) == TC_ERR) { tc_intercept_release_tunnel(fd, rev); return TC_ERR; } return TC_OK; } } else { tc_intercept_release_tunnel(fd, rev); return TC_ERR; } } msg.clt_ip = msg.clt_ip; msg.clt_port = msg.clt_port; msg.type = ntohs(msg.type); msg.target_ip = msg.target_ip; msg.target_port = msg.target_port; switch (msg.type) { case CLIENT_ADD: #if (!TC_SINGLE) tot_router_items++; tc_log_debug1(LOG_DEBUG, 0, "add client router:%u", ntohs(msg.clt_port)); router_add(msg.clt_ip, msg.clt_port, msg.target_ip, msg.target_port, rev->fd); #endif break; case CLIENT_DEL: tc_log_debug1(LOG_DEBUG, 0, "del client router:%u", ntohs(msg.clt_port)); break; default: tc_log_info(LOG_WARN, 0, "unknown msg type:%u", msg.type); } return TC_OK; }
static int tc_msg_event_process(tc_event_t *rev) { int fd, version; msg_client_t msg; fd = rev->fd; memset(&msg, 0, sizeof(msg_client_t)); if (tunnel[fd].first_in) { if (tc_socket_recv(fd, (char *) &msg, MSG_CLIENT_MIN_SIZE) == TC_ERROR) { tc_intercept_close_fd(fd, rev); return TC_ERROR; } version = ntohs(msg.type); tunnel[fd].first_in = 0; if (msg.client_ip != 0 || msg.client_port != 0) { tunnel[fd].clt_msg_size = MSG_CLIENT_MIN_SIZE; tc_log_info(LOG_WARN, 0, "too old tcpcopy for intercept"); srv_settings.old = 1; } else { if (version != INTERNAL_VERSION) { tc_log_info(LOG_WARN, 0, "not compatible,tcpcopy:%d,intercept:%d", msg.type, INTERNAL_VERSION); } tunnel[fd].clt_msg_size = MSG_CLIENT_SIZE; if (tc_socket_recv(fd, ((char *) &msg + MSG_CLIENT_MIN_SIZE), MSG_CLIENT_SIZE - MSG_CLIENT_MIN_SIZE) == TC_ERROR) { tc_intercept_close_fd(fd, rev); return TC_ERROR; } return TC_OK; } } else { if (tc_socket_recv(fd, (char *) &msg, tunnel[fd].clt_msg_size) == TC_ERROR) { tc_intercept_close_fd(fd, rev); return TC_ERROR; } } msg.client_ip = msg.client_ip; msg.client_port = msg.client_port; msg.type = ntohs(msg.type); msg.target_ip = msg.target_ip; msg.target_port = msg.target_port; switch (msg.type) { case CLIENT_ADD: #if (!TCPCOPY_SINGLE) tot_router_items++; tc_log_debug1(LOG_DEBUG, 0, "add client router:%u", ntohs(msg.client_port)); router_add(srv_settings.old, msg.client_ip, msg.client_port, msg.target_ip, msg.target_port, fd); #endif break; case CLIENT_DEL: tc_log_debug1(LOG_DEBUG, 0, "del client router:%u", ntohs(msg.client_port)); break; default: tc_log_info(LOG_WARN, 0, "unknown msg type:%u", msg.type); } return TC_OK; }
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 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); } } }
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 void retrieve_options(tc_user_t *u, int direction, tc_tcp_header_t *tcp_header) { uint32_t ts_value; unsigned int opt, opt_len; unsigned char *p, *end; p = ((unsigned char *) tcp_header) + TCP_HEADER_MIN_LEN; end = ((unsigned char *) tcp_header) + (tcp_header->doff << 2); while (p < end) { opt = p[0]; switch (opt) { case TCPOPT_WSCALE: if ((p + 1) >= end) { return; } opt_len = p[1]; if ((p + opt_len) > end) { return; } u->wscale = (uint16_t) p[2]; p += opt_len; case TCPOPT_TIMESTAMP: if ((p + 1) >= end) { return; } opt_len = p[1]; if ((p + opt_len) > end) { return; } if (direction == LOCAL) { ts_value = EXTRACT_32BITS(p + 2); } else { u->ts_ec_r = EXTRACT_32BITS(p + 2); ts_value = EXTRACT_32BITS(p + 6); if (tcp_header->syn) { u->state.timestamped = 1; tc_log_debug1(LOG_DEBUG, 0, "timestamped,p=%u", ntohs(u->src_port)); } tc_log_debug3(LOG_DEBUG, 0, "get ts(client viewpoint):%u,%u,p:%u", u->ts_value, u->ts_ec_r, ntohs(u->src_port)); } if (ts_value > u->ts_value) { tc_log_debug1(LOG_DEBUG, 0, "ts > history,p:%u", ntohs(u->src_port)); u->ts_value = ts_value; } p += opt_len; case TCPOPT_NOP: p = p + 1; break; case TCPOPT_EOL: return; default: if ((p + 1) >= end) { return; } opt_len = p[1]; p += opt_len; break; } } return; }
static int retrieve_clt_tf_ips() { int count = 0, len, i; char *split, *p, tmp_ip[32], *q; uint32_t ip; p = clt_settings.raw_clt_tf_ip; while (true) { split = strchr(p, ','); if (split != NULL) { *split = '\0'; } len = strlen(p); if (len == 0) { tc_log_info(LOG_WARN, 0, "ip is empty"); break; } if (p[len - 1] == 'x') { strncpy(tmp_ip, p, len -1); q = tmp_ip + len - 1; for (i = 1; i < 255; i++) { sprintf(q, "%d", i); ip = inet_addr(tmp_ip); tc_log_debug1(LOG_DEBUG, 0, "clt ip addr:%s", tmp_ip); if (check_client_ip_valid(ip)) { clt_settings.clt_tf_ip[count++] = ip; if (count == M_IP_NUM) { tc_log_info(LOG_WARN, 0, "reach limit for clt ips"); break; } } } } else if (p[len - 1] == '*') { tc_log_info(LOG_ERR, 0, "%s not valid, use x instead of *", p); fprintf(stderr, "%s not valid, use x instead of *\n", p); } else { ip = inet_addr(p); if (check_client_ip_valid(ip)) { clt_settings.clt_tf_ip[count++] = ip; if (count == M_IP_NUM) { tc_log_info(LOG_WARN, 0, "reach limit for clt ips"); break; } } } if (split != NULL) { *split = ','; } if (count == M_IP_NUM) { tc_log_info(LOG_WARN, 0, "reach the limit for clt_tf_ip"); break; } if (split == NULL) { break; } else { p = split + 1; } } clt_settings.clt_tf_ip_num = count; return 1; }
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_udp, tot_len, cont_len, pack_len, head_len; struct udphdr *udp_header; struct iphdr *ip_header; packet = recv_buf; if (is_packet_needed((const char *)packet)){ replica_num = clt_settings.replica_num; packet_num = 1; ip_header = (struct iphdr*)packet; if (localhost == ip_header->saddr){ if (0 != clt_settings.lo_tf_ip){ ip_header->saddr = clt_settings.lo_tf_ip; } } /* * If packet length larger than MTU, then 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){ log_info(LOG_WARN, "packet len:%u, recv len:%u", tot_len, recv_len); return FAILURE; } udp_header = (struct udphdr*)((char *)ip_header + size_ip); size_udp = ntohs(udp_header->len); cont_len = size_udp - sizeof(struct udphdr); head_len = size_ip + sizeof(struct udphdr); max_payload = clt_settings.mtu - head_len; packet_num = (cont_len + max_payload - 1)/max_payload; last = packet_num - 1; id = ip_header->id; tc_log_debug1(LOG_INFO, "recv:%d, more than MTU", recv_len); index = head_len; for (i = 0 ; i < packet_num; i++){ if (i != last){ pack_len = clt_settings.mtu; }else{ pack_len += (cont_len - packet_num * max_payload); } payload_len = pack_len - head_len; udp_header->len = htons(pack_len - size_ip); 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 (packet_valid){ *p_valid_flag = 1; } else { *p_valid_flag = 0; } return SUCCESS; }
/* 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 }