#include #include #include #include #include #include #include "vtl.h" #include "vtl_harness.h" DEBUG_DECLARE(); /* Connection List Handling */ struct VTL_CON g_vtl_cons[MAX_VTL_CONS]; int g_first_vtl; int g_last_vtl; int g_num_vtl_cons; int add_vtl_con(RawEthernetPacket * pkt); int find_vtl_con(RawEthernetPacket * pkt); /* Packet Handlers */ int handle_local_tcp_pkt(RawEthernetPacket * pkt, iface_t * dev); int handle_remote_tcp_pkt(RawEthernetPacket * pkt); /* Packet functions */ int make_ack_pkt(RawEthernetPacket * pkt, int vcon_i); int init_ack_template(RawEthernetPacket * pkt); unsigned short ip_id_ctr = 1; int main(int argc, char ** argv) { RawEthernetPacket pkt; RawEthernetPacket ack_pkt; int i = 0; iface_t * dev; unsigned long src_addr; debug_init("./vtl.log"); JRLDBG("Starting VTP Daemon\n"); for (i = 0; i < MAX_VTL_CONS; i++) { g_vtl_cons[i].con_model.type = TCP_MODEL; g_vtl_cons[i].in_use = false; g_vtl_cons[i].next = -1; g_vtl_cons[i].prev = -1; } g_last_vtl = -1; g_first_vtl = -1; g_num_vtl_cons = 0; src_addr = ToIPAddress(argv[2]); dev = if_connect(argv[1]); while (if_read_pkt(dev, &pkt) != -1) { if (is_tcp_pkt(&pkt)) { if (GET_IP_SRC(pkt.data) == src_addr) { handle_local_tcp_pkt(&pkt, dev); } else if (GET_IP_DST(pkt.data) == src_addr) { if (GET_IP_ID(pkt.data) == ip_id_ctr -1) { continue; } handle_remote_tcp_pkt(&pkt); printf("Remote tcp packet\n"); } } } fclose(logfile); return(0); } int handle_local_tcp_pkt(RawEthernetPacket * pkt, iface_t * dev) { printf("local tcp pkt\n"); RawEthernetPacket ack_pkt; int index = find_vtl_con(pkt); if (index != -1) { // packet in the system sync_model(&(g_vtl_cons[index].con_model), pkt); // dbg_dump_model(&(g_vtl_cons[index].con_model)); if (GET_TCP_DATA_LEN(pkt->data) > 0) { create_empty_pkt(&(g_vtl_cons[index].con_model), &ack_pkt, INBOUND_PKT); dbg_print_pkt_info(&ack_pkt); if_write_pkt(dev, &ack_pkt); } } else { if (is_syn_pkt(pkt)) { int index = -1; index = add_vtl_con(pkt); printf("Connection added at %d\n", index); } } return 0; } int handle_remote_tcp_pkt(RawEthernetPacket * pkt) { int index; index = find_vtl_con(pkt); if (index != -1) { sync_model(&(g_vtl_cons[index].con_model), pkt); g_vtl_cons[index].con_model.model.ip_model.dst.ip_id = ip_id_ctr++; } return 0; } int find_vtl_con(RawEthernetPacket * pkt) { int index = -1; int i = 0; FOREACH_VTL_CON(i,g_vtl_cons) { if (is_model_pkt(&(g_vtl_cons[i].con_model), pkt)) { index = i; break; } } return index; } int add_vtl_con(RawEthernetPacket * pkt) { int i; for (i = 0; i < MAX_VTL_CONS; i++) { if (!(g_vtl_cons[i].in_use)) { JRLDBG("Adding connection in slot %d\n", i); initialize_model(&(g_vtl_cons[i].con_model), pkt); g_vtl_cons[i].in_use = true; dbg_dump_model(&(g_vtl_cons[i].con_model)); if (g_first_vtl == -1) g_first_vtl = i; g_vtl_cons[i].prev = g_last_vtl; g_vtl_cons[i].next = -1; if (g_last_vtl != -1) { g_vtl_cons[g_last_vtl].next = i; } g_last_vtl = i; g_num_vtl_cons++; return 0; } } return -1; } /* int handle_tcp_pkt(RawEthernetPacket *pkt) { unsigned short ip_pkt_len = 0; // unsigned char ip_hdr_len = (*(pkt->data + ETH_HDR_LEN) & 0x0f) << 2; unsigned char ip_hdr_len = IP_HDR_LEN(pkt->data); unsigned short * ip_pkt_len_ptr = (unsigned short *)(pkt->data + ETH_HDR_LEN + 2); ip_pkt_len = ntohs(*ip_pkt_len_ptr); JRLDBG("IP Header Length = %d(%x)\n", ip_hdr_len, *(pkt->data + ETH_HDR_LEN)); JRLDBG("IP Packet Length = %hu\n", ip_pkt_len); if (is_syn_pkt(pkt) == 0) { // we don't mess with connection establishment int vcon_i; unsigned long payload_len = 0; unsigned short tcp_hdr_len = 0; struct in_addr tmp; tcp_hdr_len = (*(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) & 0xf0) >> 2; payload_len = ip_pkt_len - (ip_hdr_len + tcp_hdr_len); if ((payload_len == 0) && (is_ack_pkt(pkt) == 1)) { // we just kill empty acks. //return 0; } vcon_i = find_remote_vtp_con(pkt); // Create ACK and send it. make_ack_pkt(pkt, vcon_i); g_vtl_cons[vcon_i].ack_template.VtpSerialize(vtp_in_fd, &tmp); } else { if(is_ack_pkt(pkt) == 1) { int vcon_i = find_remote_vtp_con(pkt); struct in_addr tmp; make_ack_pkt(pkt, vcon_i); g_vtl_cons[vcon_i].ack_template.VtpSerialize(vtp_in_fd, &tmp); } #ifdef DEBUG unsigned long * seq_num_ptr ; unsigned long seq_num = 0; unsigned long payload_len = 0; unsigned short tcp_hdr_len = 0; unsigned long ack = 0; JRLDBG("Packet is a Syn Packet\n"); seq_num_ptr = (unsigned long *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 4); seq_num = ntohl(*seq_num_ptr); JRLDBG("Sequence Number = %lu\n", seq_num); tcp_hdr_len = (*(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) & 0xf0) >> 2; payload_len = ip_pkt_len - (ip_hdr_len + tcp_hdr_len); JRLDBG("TCP Header Length = %hu\n", tcp_hdr_len); JRLDBG("Payload Length = %lu\n", payload_len); ack = (payload_len > 0) ? (seq_num + payload_len) : (seq_num + 1); JRLDBG("Ack Num = %lu\n", ack); #endif } return 0; } int handle_rem_tcp_pkt(RawEthernetPacket * pkt) { unsigned long * seq_num_ptr; unsigned long seq_num; unsigned char ip_hdr_len = IP_HDR_LEN(pkt->data); seq_num_ptr = (unsigned long *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 4); seq_num = ntohl(*seq_num_ptr); JRLDBG("Received Packet, SeqNum = %lu\n", seq_num); if (is_syn_pkt(pkt) == 1) { // syn packet seq_num++; add_vtp_con(pkt, seq_num); JRLDBG("Received Syn Packet, SeqNum = %lu\n", seq_num); } else { unsigned short ip_pkt_len = 0; unsigned short * ip_pkt_len_ptr = (unsigned short *)(pkt->data + ETH_HDR_LEN + 2); unsigned long payload_len = 0; unsigned short tcp_hdr_len = 0; int i_vcon = find_vtp_con(pkt); ip_pkt_len = ntohs(*ip_pkt_len_ptr); tcp_hdr_len = (*(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) & 0xf0) >> 2; if (tcp_hdr_len > 20) { unsigned long ts = get_tcp_timestamp(pkt->data + ETH_HDR_LEN + ip_hdr_len + 20, tcp_hdr_len - 20); JRLDBG("TCP Timestamp = %lu(%lu)\n", ts, (unsigned long)ntohl(ts)); g_vtl_cons[i_vcon].tcp_timestamp = ts; } payload_len = ip_pkt_len - (ip_hdr_len + tcp_hdr_len); seq_num += payload_len; JRLDBG("Received Data Packet, SeqNum = %lu\n", seq_num); g_vtl_cons[i_vcon].rem_seq_num = seq_num; JRLDBG("Remote Sequence Number (con: %d) = %lu\n", i_vcon, seq_num); #if 0 { int offset = 0; unsigned short tcp_cksum = 0; // Zero Ack Field *(unsigned long *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 8) = 0; // Zero Ack Flag offset = ETH_HDR_LEN + ip_hdr_len + 13; *(pkt->data + offset) &= 0xef; // Zero TCP chksum *(unsigned short *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 16) = 0; // Get TCP chksum tcp_cksum = get_tcp_checksum(pkt, ip_pkt_len - ip_hdr_len); // Set TCP chksum *(unsigned short *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 16) = tcp_cksum; } #endif } return 0; } int make_ack_pkt(RawEthernetPacket * pkt, int vcon_i) { unsigned long * seq_num_ptr ; unsigned long seq_num = 0; unsigned long rem_seq_num = 0; unsigned long payload_len = 0; unsigned short tcp_hdr_len = 0; unsigned long ack = 0; unsigned long local_ts = 0; unsigned short tcp_cksum = 0; unsigned char ip_hdr_len = IP_HDR_LEN(pkt->data); unsigned short ip_pkt_len = *(unsigned short *)(pkt->data + ETH_HDR_LEN + 2); RawEthernetPacket * ack_pkt = &(g_vtl_cons[vcon_i].ack_template); unsigned short ack_ip_pkt_len = *(unsigned short *)(ack_pkt->data + ETH_HDR_LEN + 2); unsigned char ack_ip_hdr_len = IP_HDR_LEN(ack_pkt->data); ip_pkt_len = ntohs(ip_pkt_len); ack_ip_pkt_len = ntohs(ack_ip_pkt_len); seq_num_ptr = (unsigned long *)(pkt->data + ETH_HDR_LEN + ip_hdr_len + 4); seq_num = ntohl(*seq_num_ptr); JRLDBG("Sequence Number = %lu\n", seq_num); tcp_hdr_len = (*(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) & 0xf0) >> 2; if (is_syn_pkt(pkt) == 1) { ack = seq_num + 1; } else { payload_len = ip_pkt_len - (ip_hdr_len + tcp_hdr_len); JRLDBG("TCP Header Length = %hu\n", tcp_hdr_len); JRLDBG("Payload Length = %lu\n", payload_len); ack = seq_num + payload_len; JRLDBG("Ack Num = %lu\n", ack); } // Set IP id g_vtl_cons[vcon_i].ip_id--; *(unsigned short *)(ack_pkt->data + ETH_HDR_LEN + 4) = htons(g_vtl_cons[vcon_i].ip_id); // Recompute IP checksum *(unsigned short *)(ack_pkt->data + ETH_HDR_LEN + 10) = 0; *(unsigned short *)(ack_pkt->data + ETH_HDR_LEN + 10) = get_ip_checksum(ack_pkt); //return 0; // Set Sequence Number rem_seq_num = htonl(g_vtl_cons[vcon_i].rem_seq_num); *(unsigned long *)(ack_pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 4) = rem_seq_num; // Set ACK Number ack = htonl(ack); *(unsigned long *)(ack_pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 8) = ack; // Set TCP Timestamp option local_ts = get_tcp_timestamp(pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 20, tcp_hdr_len - 20); // We use this for debugging: // If the TCPDump trace shows timestamps with the value of '5' then they are our packets // *(unsigned long *)(ack_pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 24) = g_vtl_cons[vcon_i].tcp_timestamp; // *(unsigned long *)(ack_pkt->data + ETH_HDR_LEN + ip_hdr_len + 24) = htonl(5); *(unsigned long *)(ack_pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 28) = local_ts; // Zero TCP chksum *(unsigned short *)(ack_pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 16) = 0; // Get TCP chksum tcp_cksum = get_tcp_checksum(ack_pkt, ack_ip_pkt_len - ack_ip_hdr_len); // Set TCP chksum *(unsigned short *)(ack_pkt->data + ETH_HDR_LEN + ack_ip_hdr_len + 16) = tcp_cksum; return 0; } // Connection List Handling // int init_ack_template(RawEthernetPacket * pkt) { // We assume here that the ethernet and ip headers are ok, except for ip pkt length // TCP is mostly right because its pulled off of a syn packet // we need to zero the data, and reset the syn flag. unsigned short IP_PACKET_LEN = 52; unsigned short TCP_HEADER_LEN = 32; unsigned char ip_hdr_len = IP_HDR_LEN(pkt->data); unsigned short ip_pkt_len = 0; unsigned short tcp_hdr_len = 0; unsigned short payload_len = 0; unsigned short * ip_pkt_len_ptr = (unsigned short *)(pkt->data + ETH_HDR_LEN + 2); unsigned int offset = 0; unsigned short ip_chksum = 0; JRLDBG("--> Initializing ACK Template <--\n"); ip_pkt_len = ntohs(*ip_pkt_len_ptr); JRLDBG("ip_pkt_len = %hu\n", ip_pkt_len); tcp_hdr_len = (*(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) & 0xf0) >> 2; payload_len = ip_pkt_len - (ip_hdr_len + tcp_hdr_len); JRLDBG("tcp_hdr_len = %hu\n", tcp_hdr_len); JRLDBG("payload_len = %hu\n", payload_len); // set only the ack flags offset = ETH_HDR_LEN + ip_hdr_len + 13; *(pkt->data + offset) |= 0x10; *(pkt->data + offset) &= 0xd0; // set up tcp options offset = ETH_HDR_LEN + ip_hdr_len + 20; *(pkt->data + offset) = 0x01; offset++; *(pkt->data + offset) = 0x01; offset++; *(pkt->data + offset) = 0x08; offset++; *(pkt->data + offset) = 0x0a; // Set Header Lengths // IP HEADER = 20 (same) // IP PACKET LEN = 52 // TCP Header len = 32 ip_pkt_len = htons(IP_PACKET_LEN); memcpy(pkt->data + ETH_HDR_LEN + 2, &ip_pkt_len, 2); tcp_hdr_len = (TCP_HEADER_LEN << 2); *(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) &= 0x0f; *(pkt->data + ETH_HDR_LEN + ip_hdr_len + 12) |= tcp_hdr_len; JRLDBG("Setting TEMPLATE TCPLEN = %2x\n", *(pkt->data + ETH_HDR_LEN +ip_hdr_len + 12)); // Set IP Header chksum *(unsigned short *)(pkt->data + ETH_HDR_LEN + 10) = 0; ip_chksum = get_ip_checksum(pkt); *(unsigned short *)(pkt->data + ETH_HDR_LEN + 10) = ip_chksum; // Set RawEthernetPacket size pkt->set_size(IP_PACKET_LEN + ETH_HDR_LEN); pkt->set_type("et"); JRLDBG("--> ACK Template Initialized <--\n"); return 0; } */