12c431f66SShuo Chen#include "faketcp.h" 22c431f66SShuo Chen 32c431f66SShuo Chen#include <map> 42c431f66SShuo Chen 52c431f66SShuo Chen#include <stdio.h> 62c431f66SShuo Chen#include <stdlib.h> 7a4bafd74SShuo Chen#include <sys/time.h> 82c431f66SShuo Chen#include <unistd.h> 92c431f66SShuo Chen#include <netinet/ip.h> 102c431f66SShuo Chen#include <netinet/tcp.h> 112c431f66SShuo Chen#include <linux/if_ether.h> 122c431f66SShuo Chen 132c431f66SShuo Chenstruct TcpState 142c431f66SShuo Chen{ 152c431f66SShuo Chen uint32_t rcv_nxt; 162c431f66SShuo Chen uint32_t snd_una; 172c431f66SShuo Chen}; 182c431f66SShuo Chen 192c431f66SShuo Chenstd::map<SocketAddr, TcpState> expectedSeqs; 202c431f66SShuo Chen 212c431f66SShuo Chenvoid tcp_input(int fd, const void* input, const void* ippayload, int tot_len) 222c431f66SShuo Chen{ 232c431f66SShuo Chen const struct iphdr* iphdr = static_cast<const struct iphdr*>(input); 242c431f66SShuo Chen const struct tcphdr* tcphdr = static_cast<const struct tcphdr*>(ippayload); 252c431f66SShuo Chen const int iphdr_len = iphdr->ihl*4; 262c431f66SShuo Chen const int tcp_seg_len = tot_len - iphdr_len; 272c431f66SShuo Chen const int tcphdr_size = sizeof(*tcphdr); 282c431f66SShuo Chen if (tcp_seg_len >= tcphdr_size 292c431f66SShuo Chen && tcp_seg_len >= tcphdr->doff*4) 302c431f66SShuo Chen { 312c431f66SShuo Chen const int tcphdr_len = tcphdr->doff*4; 322c431f66SShuo Chen const void* payload = ippayload + tcphdr_len; 332c431f66SShuo Chen const int payload_len = tot_len - iphdr_len - tcphdr_len; 342c431f66SShuo Chen 352c431f66SShuo Chen char source[INET_ADDRSTRLEN]; 362c431f66SShuo Chen char dest[INET_ADDRSTRLEN]; 372c431f66SShuo Chen inet_ntop(AF_INET, &iphdr->saddr, source, INET_ADDRSTRLEN); 382c431f66SShuo Chen inet_ntop(AF_INET, &iphdr->daddr, dest, INET_ADDRSTRLEN); 392c431f66SShuo Chen printf("IP %s.%d > %s.%d: ", 402c431f66SShuo Chen source, ntohs(tcphdr->source), dest, ntohs(tcphdr->dest)); 412c431f66SShuo Chen printf("Flags [%c], seq %u, win %d, length %d\n", 422c431f66SShuo Chen tcphdr->syn ? 'S' : (tcphdr->fin ? 'F' : '.'), 432c431f66SShuo Chen ntohl(tcphdr->seq), 442c431f66SShuo Chen ntohs(tcphdr->window), 452c431f66SShuo Chen payload_len); 462c431f66SShuo Chen 472c431f66SShuo Chen union 482c431f66SShuo Chen { 492c431f66SShuo Chen unsigned char output[ETH_FRAME_LEN]; 502c431f66SShuo Chen struct 512c431f66SShuo Chen { 522c431f66SShuo Chen struct iphdr iphdr; 532c431f66SShuo Chen struct tcphdr tcphdr; 542c431f66SShuo Chen } out; 552c431f66SShuo Chen }; 562c431f66SShuo Chen 572c431f66SShuo Chen assert(sizeof(out) == sizeof(struct iphdr) + sizeof(struct tcphdr)); 582c431f66SShuo Chen int output_len = sizeof(out); 592c431f66SShuo Chen bzero(&out, output_len + 4); 602c431f66SShuo Chen memcpy(output, input, sizeof(struct iphdr)); 612c431f66SShuo Chen 622c431f66SShuo Chen std::swap(out.iphdr.saddr, out.iphdr.daddr); 632c431f66SShuo Chen out.iphdr.check = 0; 642c431f66SShuo Chen 652c431f66SShuo Chen out.tcphdr.source = tcphdr->dest; 662c431f66SShuo Chen out.tcphdr.dest = tcphdr->source; 672c431f66SShuo Chen out.tcphdr.doff = sizeof(struct tcphdr) / 4; 682c431f66SShuo Chen out.tcphdr.window = htons(5000); 692c431f66SShuo Chen 702c431f66SShuo Chen SocketAddr addr = { out.iphdr.saddr, out.iphdr.daddr, out.tcphdr.source, out.tcphdr.dest }; 712c431f66SShuo Chen bool response = false; 722c431f66SShuo Chen const uint32_t seq = ntohl(tcphdr->seq); 732c431f66SShuo Chen if (tcphdr->syn) 742c431f66SShuo Chen { 752c431f66SShuo Chen out.tcphdr.seq = htonl(seq); 762c431f66SShuo Chen out.tcphdr.ack_seq = htonl(seq+1); 772c431f66SShuo Chen out.tcphdr.syn = 1; 782c431f66SShuo Chen out.tcphdr.ack = 1; 792c431f66SShuo Chen TcpState s = { seq + 1, seq + 1 }; 802c431f66SShuo Chen expectedSeqs[addr] = s; 812c431f66SShuo Chen response = true; 822c431f66SShuo Chen } 832c431f66SShuo Chen else if (tcphdr->fin) 842c431f66SShuo Chen { 852c431f66SShuo Chen out.tcphdr.seq = htonl(seq); 862c431f66SShuo Chen out.tcphdr.ack_seq = htonl(seq+1); 872c431f66SShuo Chen out.tcphdr.fin = 1; 882c431f66SShuo Chen out.tcphdr.ack = 1; 892c431f66SShuo Chen expectedSeqs.erase(addr); 902c431f66SShuo Chen response = true; 912c431f66SShuo Chen } 922c431f66SShuo Chen else 932c431f66SShuo Chen { 942c431f66SShuo Chen out.tcphdr.seq = htonl(seq); 952c431f66SShuo Chen out.tcphdr.ack_seq = htonl(seq+payload_len); 962c431f66SShuo Chen out.tcphdr.psh = 1; 972c431f66SShuo Chen out.tcphdr.ack = 1; 982c431f66SShuo Chen assert(output + output_len + payload_len < output + sizeof(output)); 992c431f66SShuo Chen memcpy(output + output_len, payload, payload_len); 1002c431f66SShuo Chen output_len += payload_len; 1012c431f66SShuo Chen auto it = expectedSeqs.find(addr); 1022c431f66SShuo Chen if (it != expectedSeqs.end()) 1032c431f66SShuo Chen { 1042c431f66SShuo Chen const uint32_t ack = ntohl(tcphdr->ack_seq); 1052c431f66SShuo Chen printf("seq = %u, ack = %u\n", seq, ack); 1062c431f66SShuo Chen printf("rcv_nxt = %u, snd_una = %u\n", it->second.rcv_nxt, it->second.snd_una); 107a4bafd74SShuo Chen if (tcphdr->ack && ack == it->second.snd_una) 108a4bafd74SShuo Chen { 109a4bafd74SShuo Chen it->second.rcv_nxt = ack; 110a4bafd74SShuo Chen } 1112c431f66SShuo Chen if (payload_len > 0 && it->second.rcv_nxt == seq) 1122c431f66SShuo Chen { 1132c431f66SShuo Chen it->second.snd_una = seq+payload_len; 1142c431f66SShuo Chen response = true; 1152c431f66SShuo Chen } 1162c431f66SShuo Chen printf("rcv_nxt = %u, snd_una = %u\n", it->second.rcv_nxt, it->second.snd_una); 1172c431f66SShuo Chen } 1182c431f66SShuo Chen else 1192c431f66SShuo Chen { 1202c431f66SShuo Chen // RST 1212c431f66SShuo Chen } 1222c431f66SShuo Chen } 1232c431f66SShuo Chen 1242c431f66SShuo Chen out.iphdr.tot_len = htons(output_len); 1252c431f66SShuo Chen out.iphdr.check = in_checksum(output, sizeof(struct iphdr)); 1262c431f66SShuo Chen 1272c431f66SShuo Chen unsigned char* pseudo = output + output_len; 1282c431f66SShuo Chen if (payload_len % 2 == 1) 1292c431f66SShuo Chen { 1302c431f66SShuo Chen *pseudo = 0; 1312c431f66SShuo Chen ++pseudo; 1322c431f66SShuo Chen } 1332c431f66SShuo Chen unsigned int len = sizeof(struct tcphdr)+payload_len; 1342c431f66SShuo Chen pseudo[0] = 0; 1352c431f66SShuo Chen pseudo[1] = IPPROTO_TCP; 1362c431f66SShuo Chen pseudo[2] = len / 256; 1372c431f66SShuo Chen pseudo[3] = len % 256; 1382c431f66SShuo Chen out.tcphdr.check = in_checksum(&out.iphdr.saddr, len + 12 + (payload_len % 2)); 1392c431f66SShuo Chen if (response) 1402c431f66SShuo Chen { 1412c431f66SShuo Chen write(fd, output, output_len); 1422c431f66SShuo Chen } 1432c431f66SShuo Chen } 1442c431f66SShuo Chen} 1452c431f66SShuo Chen 1462c431f66SShuo Chenint main() 1472c431f66SShuo Chen{ 1482c431f66SShuo Chen char ifname[IFNAMSIZ] = "tun%d"; 1492c431f66SShuo Chen int fd = tun_alloc(ifname); 1502c431f66SShuo Chen 1512c431f66SShuo Chen if (fd < 0) 1522c431f66SShuo Chen { 1532c431f66SShuo Chen fprintf(stderr, "tunnel interface allocation failed\n"); 1542c431f66SShuo Chen exit(1); 1552c431f66SShuo Chen } 1562c431f66SShuo Chen 1572c431f66SShuo Chen printf("allocted tunnel interface %s\n", ifname); 1582c431f66SShuo Chen sleep(1); 1592c431f66SShuo Chen 1602c431f66SShuo Chen for (;;) 1612c431f66SShuo Chen { 1622c431f66SShuo Chen union 1632c431f66SShuo Chen { 1642c431f66SShuo Chen unsigned char buf[ETH_FRAME_LEN]; 1652c431f66SShuo Chen struct iphdr iphdr; 1662c431f66SShuo Chen }; 1672c431f66SShuo Chen 1682c431f66SShuo Chen const int iphdr_size = sizeof iphdr; 1692c431f66SShuo Chen 1702c431f66SShuo Chen int nread = read(fd, buf, sizeof(buf)); 1712c431f66SShuo Chen if (nread < 0) 1722c431f66SShuo Chen { 1732c431f66SShuo Chen perror("read"); 1742c431f66SShuo Chen close(fd); 1752c431f66SShuo Chen exit(1); 1762c431f66SShuo Chen } 177a4bafd74SShuo Chen struct timeval tv; 178a4bafd74SShuo Chen gettimeofday(&tv, NULL); 179a4bafd74SShuo Chen printf("%ld.%06ld read %d bytes %s.\n", tv.tv_sec, tv.tv_usec, nread, ifname); 1802c431f66SShuo Chen 1812c431f66SShuo Chen const int iphdr_len = iphdr.ihl*4; 1822c431f66SShuo Chen if (nread >= iphdr_size 1832c431f66SShuo Chen && iphdr.version == 4 1842c431f66SShuo Chen && iphdr_len >= iphdr_size 1852c431f66SShuo Chen && iphdr_len <= nread 1862c431f66SShuo Chen && iphdr.tot_len == htons(nread) 1872c431f66SShuo Chen && in_checksum(buf, iphdr_len) == 0) 1882c431f66SShuo Chen { 1892c431f66SShuo Chen const void* payload = buf + iphdr_len; 1902c431f66SShuo Chen if (iphdr.protocol == IPPROTO_ICMP) 1912c431f66SShuo Chen { 1922c431f66SShuo Chen icmp_input(fd, buf, payload, nread); 1932c431f66SShuo Chen } 1942c431f66SShuo Chen else if (iphdr.protocol == IPPROTO_TCP) 1952c431f66SShuo Chen { 1962c431f66SShuo Chen tcp_input(fd, buf, payload, nread); 1972c431f66SShuo Chen } 1982c431f66SShuo Chen } 1992c431f66SShuo Chen else 2002c431f66SShuo Chen { 2012c431f66SShuo Chen printf("bad packet\n"); 2022c431f66SShuo Chen for (int i = 0; i < nread; ++i) 2032c431f66SShuo Chen { 2042c431f66SShuo Chen if (i % 4 == 0) printf("\n"); 2052c431f66SShuo Chen printf("%02x ", buf[i]); 2062c431f66SShuo Chen } 2072c431f66SShuo Chen printf("\n"); 2082c431f66SShuo Chen } 2092c431f66SShuo Chen } 2102c431f66SShuo Chen 2112c431f66SShuo Chen return 0; 2122c431f66SShuo Chen} 213