1cc808594SShuo Chen#include "faketcp.h" 2cc808594SShuo Chen 3cc808594SShuo Chen#include <stdio.h> 4cc808594SShuo Chen#include <stdlib.h> 5cc808594SShuo Chen#include <string.h> 6cc808594SShuo Chen#include <unistd.h> 7cc808594SShuo Chen#include <netinet/ip.h> 8cc808594SShuo Chen#include <netinet/tcp.h> 9cc808594SShuo Chen#include <linux/if_ether.h> 10cc808594SShuo Chen 11cc808594SShuo Chenvoid tcp_input(int fd, const void* input, const void* payload, int tot_len) 12cc808594SShuo Chen{ 13cc808594SShuo Chen const struct iphdr* iphdr = static_cast<const struct iphdr*>(input); 14cc808594SShuo Chen const struct tcphdr* tcphdr = static_cast<const struct tcphdr*>(payload); 1584d8a3dfSShuo Chen const int iphdr_len = iphdr->ihl*4; 1684d8a3dfSShuo Chen const int tcp_seg_len = tot_len - iphdr_len; 1784d8a3dfSShuo Chen const int tcphdr_size = sizeof(*tcphdr); 1884d8a3dfSShuo Chen if (tcp_seg_len >= tcphdr_size 1984d8a3dfSShuo Chen && tcp_seg_len >= tcphdr->doff*4) 2084d8a3dfSShuo Chen { 2184d8a3dfSShuo Chen const int tcphdr_len = tcphdr->doff*4; 2284d8a3dfSShuo Chen 2384d8a3dfSShuo Chen char source[INET_ADDRSTRLEN]; 2484d8a3dfSShuo Chen char dest[INET_ADDRSTRLEN]; 2584d8a3dfSShuo Chen inet_ntop(AF_INET, &iphdr->saddr, source, INET_ADDRSTRLEN); 2684d8a3dfSShuo Chen inet_ntop(AF_INET, &iphdr->daddr, dest, INET_ADDRSTRLEN); 2784d8a3dfSShuo Chen printf("IP %s.%d > %s.%d: ", 2884d8a3dfSShuo Chen source, ntohs(tcphdr->source), dest, ntohs(tcphdr->dest)); 2984d8a3dfSShuo Chen printf("Flags [%c], seq %u, win %d, length %d\n", 3084d8a3dfSShuo Chen tcphdr->syn ? 'S' : (tcphdr->fin ? 'F' : '.'), 3184d8a3dfSShuo Chen ntohl(tcphdr->seq), 3284d8a3dfSShuo Chen ntohs(tcphdr->window), 3384d8a3dfSShuo Chen tot_len - iphdr_len - tcphdr_len); 3484d8a3dfSShuo Chen 3584d8a3dfSShuo Chen union 3684d8a3dfSShuo Chen { 3784d8a3dfSShuo Chen unsigned char output[ETH_FRAME_LEN]; 3884d8a3dfSShuo Chen struct 3984d8a3dfSShuo Chen { 4084d8a3dfSShuo Chen struct iphdr iphdr; 4184d8a3dfSShuo Chen struct tcphdr tcphdr; 4284d8a3dfSShuo Chen } out; 4384d8a3dfSShuo Chen }; 4484d8a3dfSShuo Chen 4584d8a3dfSShuo Chen assert(sizeof(out) == sizeof(struct iphdr) + sizeof(struct tcphdr)); 4684d8a3dfSShuo Chen int output_len = sizeof(out); 4784d8a3dfSShuo Chen bzero(&out, output_len + 4); 4884d8a3dfSShuo Chen memcpy(output, input, sizeof(struct iphdr)); 4984d8a3dfSShuo Chen 5084d8a3dfSShuo Chen out.iphdr.tot_len = htons(output_len); 5184d8a3dfSShuo Chen std::swap(out.iphdr.saddr, out.iphdr.daddr); 5284d8a3dfSShuo Chen out.iphdr.check = 0; 5384d8a3dfSShuo Chen out.iphdr.check = in_checksum(output, sizeof(struct iphdr)); 5484d8a3dfSShuo Chen 5584d8a3dfSShuo Chen out.tcphdr.source = tcphdr->dest; 5684d8a3dfSShuo Chen out.tcphdr.dest = tcphdr->source; 5784d8a3dfSShuo Chen out.tcphdr.ack_seq = htonl(ntohl(tcphdr->seq)+1); 5884d8a3dfSShuo Chen out.tcphdr.doff = sizeof(struct tcphdr) / 4; 5984d8a3dfSShuo Chen out.tcphdr.window = htons(5000); 6084d8a3dfSShuo Chen 6184d8a3dfSShuo Chen bool response = false; 6284d8a3dfSShuo Chen if (tcphdr->syn) 6384d8a3dfSShuo Chen { 6484d8a3dfSShuo Chen out.tcphdr.seq = htonl(123456); 6584d8a3dfSShuo Chen out.tcphdr.syn = 1; 6684d8a3dfSShuo Chen out.tcphdr.ack = 1; 6784d8a3dfSShuo Chen response = true; 6884d8a3dfSShuo Chen } 6984d8a3dfSShuo Chen else if (tcphdr->fin) 7084d8a3dfSShuo Chen { 7184d8a3dfSShuo Chen out.tcphdr.seq = htonl(123457); 7284d8a3dfSShuo Chen out.tcphdr.fin = 1; 7384d8a3dfSShuo Chen out.tcphdr.ack = 1; 7484d8a3dfSShuo Chen response = true; 7584d8a3dfSShuo Chen } 76cc808594SShuo Chen 7784d8a3dfSShuo Chen unsigned char* pseudo = output + output_len; 7884d8a3dfSShuo Chen pseudo[0] = 0; 7984d8a3dfSShuo Chen pseudo[1] = IPPROTO_TCP; 8084d8a3dfSShuo Chen pseudo[2] = 0; 8184d8a3dfSShuo Chen pseudo[3] = sizeof(struct tcphdr); 8284d8a3dfSShuo Chen out.tcphdr.check = in_checksum(&out.iphdr.saddr, sizeof(struct tcphdr)+12); 8384d8a3dfSShuo Chen if (response) 8484d8a3dfSShuo Chen { 8584d8a3dfSShuo Chen write(fd, output, output_len); 8684d8a3dfSShuo Chen } 8784d8a3dfSShuo Chen } 88cc808594SShuo Chen} 89cc808594SShuo Chen 90cc808594SShuo Chenint main() 91cc808594SShuo Chen{ 92cc808594SShuo Chen char ifname[IFNAMSIZ] = "tun%d"; 93cc808594SShuo Chen int fd = tun_alloc(ifname); 94cc808594SShuo Chen 95cc808594SShuo Chen if (fd < 0) 96cc808594SShuo Chen { 97cc808594SShuo Chen fprintf(stderr, "tunnel interface allocation failed\n"); 98cc808594SShuo Chen exit(1); 99cc808594SShuo Chen } 100cc808594SShuo Chen 101cc808594SShuo Chen printf("allocted tunnel interface %s\n", ifname); 102cc808594SShuo Chen sleep(1); 103cc808594SShuo Chen 104cc808594SShuo Chen for (;;) 105cc808594SShuo Chen { 106b2fec1eaSShuo Chen union 107b2fec1eaSShuo Chen { 108b2fec1eaSShuo Chen unsigned char buf[ETH_FRAME_LEN]; 109b2fec1eaSShuo Chen struct iphdr iphdr; 110b2fec1eaSShuo Chen }; 111b2fec1eaSShuo Chen 112b2fec1eaSShuo Chen const int iphdr_size = sizeof iphdr; 113b2fec1eaSShuo Chen 114cc808594SShuo Chen int nread = read(fd, buf, sizeof(buf)); 115cc808594SShuo Chen if (nread < 0) 116cc808594SShuo Chen { 117cc808594SShuo Chen perror("read"); 118cc808594SShuo Chen close(fd); 119cc808594SShuo Chen exit(1); 120cc808594SShuo Chen } 121cc808594SShuo Chen printf("read %d bytes from tunnel interface %s.\n", nread, ifname); 122cc808594SShuo Chen 123b2fec1eaSShuo Chen const int iphdr_len = iphdr.ihl*4; 124cc808594SShuo Chen if (nread >= iphdr_size 125cc808594SShuo Chen && iphdr.version == 4 126b2fec1eaSShuo Chen && iphdr_len >= iphdr_size 127b2fec1eaSShuo Chen && iphdr_len <= nread 128cc808594SShuo Chen && iphdr.tot_len == htons(nread) 129b2fec1eaSShuo Chen && in_checksum(buf, iphdr_len) == 0) 130cc808594SShuo Chen { 131b2fec1eaSShuo Chen const void* payload = buf + iphdr_len; 132cc808594SShuo Chen if (iphdr.protocol == IPPROTO_ICMP) 133cc808594SShuo Chen { 134cc808594SShuo Chen icmp_input(fd, buf, payload, nread); 135cc808594SShuo Chen } 136cc808594SShuo Chen else if (iphdr.protocol == IPPROTO_TCP) 137cc808594SShuo Chen { 138cc808594SShuo Chen tcp_input(fd, buf, payload, nread); 139cc808594SShuo Chen } 140cc808594SShuo Chen } 141cc808594SShuo Chen else 142cc808594SShuo Chen { 143cc808594SShuo Chen printf("bad packet\n"); 144cc808594SShuo Chen for (int i = 0; i < nread; ++i) 145cc808594SShuo Chen { 146cc808594SShuo Chen if (i % 4 == 0) printf("\n"); 147cc808594SShuo Chen printf("%02x ", buf[i]); 148cc808594SShuo Chen } 149cc808594SShuo Chen printf("\n"); 150cc808594SShuo Chen } 151cc808594SShuo Chen } 152cc808594SShuo Chen 153cc808594SShuo Chen return 0; 154cc808594SShuo Chen} 155