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); 15cc808594SShuo Chen const int iphdr_len = iphdr->ihl*4; 16cc808594SShuo Chen const int tcp_seg_len = tot_len - iphdr_len; 17cc808594SShuo Chen const int tcphdr_size = sizeof(*tcphdr); 18cc808594SShuo Chen if (tcp_seg_len >= tcphdr_size 19cc808594SShuo Chen && tcp_seg_len >= tcphdr->doff*4) 20cc808594SShuo Chen { 21cc808594SShuo Chen const int tcphdr_len = tcphdr->doff*4; 22cc808594SShuo Chen 23cc808594SShuo Chen if (tcphdr->syn) 24cc808594SShuo Chen { 25cc808594SShuo Chen char source[INET_ADDRSTRLEN]; 26cc808594SShuo Chen char dest[INET_ADDRSTRLEN]; 27cc808594SShuo Chen inet_ntop(AF_INET, &iphdr->saddr, source, INET_ADDRSTRLEN); 28cc808594SShuo Chen inet_ntop(AF_INET, &iphdr->daddr, dest, INET_ADDRSTRLEN); 29cc808594SShuo Chen printf("IP %s.%d > %s.%d: ", 30cc808594SShuo Chen source, ntohs(tcphdr->source), dest, ntohs(tcphdr->dest)); 31cc808594SShuo Chen printf("Flags [S], seq %u, win %d, length %d\n", 32cc808594SShuo Chen ntohl(tcphdr->seq), 33cc808594SShuo Chen ntohs(tcphdr->window), 34cc808594SShuo Chen tot_len - iphdr_len - tcphdr_len); 35cc808594SShuo Chen 36cc808594SShuo Chen union 37cc808594SShuo Chen { 38cc808594SShuo Chen unsigned char output[ETH_FRAME_LEN]; 39cc808594SShuo Chen struct 40cc808594SShuo Chen { 41cc808594SShuo Chen struct iphdr iphdr; 42cc808594SShuo Chen struct tcphdr tcphdr; 43cc808594SShuo Chen } out; 44cc808594SShuo Chen }; 45cc808594SShuo Chen 46cc808594SShuo Chen assert(sizeof(out) == sizeof(struct iphdr) + sizeof(struct tcphdr)); 47cc808594SShuo Chen int output_len = sizeof(out); 48cc808594SShuo Chen bzero(&out, output_len + 4); 49cc808594SShuo Chen memcpy(output, input, sizeof(struct iphdr)); 50cc808594SShuo Chen 51cc808594SShuo Chen out.iphdr.tot_len = htons(output_len); 52cc808594SShuo Chen std::swap(out.iphdr.saddr, out.iphdr.daddr); 53cc808594SShuo Chen out.iphdr.check = 0; 54cc808594SShuo Chen out.iphdr.check = in_checksum(output, sizeof(struct iphdr)); 55cc808594SShuo Chen out.tcphdr.source = tcphdr->dest; 56cc808594SShuo Chen out.tcphdr.dest = tcphdr->source; 57cc808594SShuo Chen out.tcphdr.seq = 0; 58cc808594SShuo Chen out.tcphdr.ack_seq = htonl(ntohl(tcphdr->seq)+1); 59cc808594SShuo Chen out.tcphdr.doff = sizeof(struct tcphdr) / 4; 60cc808594SShuo Chen out.tcphdr.ack = 1; 61cc808594SShuo Chen out.tcphdr.rst = 1; 62cc808594SShuo Chen out.tcphdr.window = 0; 63cc808594SShuo Chen unsigned char* pseudo = output + output_len; 64cc808594SShuo Chen pseudo[0] = 0; 65cc808594SShuo Chen pseudo[1] = IPPROTO_TCP; 66cc808594SShuo Chen pseudo[2] = 0; 67cc808594SShuo Chen pseudo[3] = sizeof(struct tcphdr); 68cc808594SShuo Chen out.tcphdr.check = in_checksum(&out.iphdr.saddr, sizeof(struct tcphdr)+12); 69cc808594SShuo Chen write(fd, output, output_len); 70cc808594SShuo Chen } 71cc808594SShuo Chen } 72cc808594SShuo Chen} 73cc808594SShuo Chen 74cc808594SShuo Chenint main() 75cc808594SShuo Chen{ 76cc808594SShuo Chen char ifname[IFNAMSIZ] = "tun%d"; 77cc808594SShuo Chen int fd = tun_alloc(ifname); 78cc808594SShuo Chen 79cc808594SShuo Chen if (fd < 0) 80cc808594SShuo Chen { 81cc808594SShuo Chen fprintf(stderr, "tunnel interface allocation failed\n"); 82cc808594SShuo Chen exit(1); 83cc808594SShuo Chen } 84cc808594SShuo Chen 85cc808594SShuo Chen printf("allocted tunnel interface %s\n", ifname); 86cc808594SShuo Chen sleep(1); 87cc808594SShuo Chen 88cc808594SShuo Chen for (;;) 89cc808594SShuo Chen { 90b2fec1eaSShuo Chen union 91b2fec1eaSShuo Chen { 92b2fec1eaSShuo Chen unsigned char buf[ETH_FRAME_LEN]; 93b2fec1eaSShuo Chen struct iphdr iphdr; 94b2fec1eaSShuo Chen }; 95b2fec1eaSShuo Chen 96b2fec1eaSShuo Chen const int iphdr_size = sizeof iphdr; 97b2fec1eaSShuo Chen 98cc808594SShuo Chen int nread = read(fd, buf, sizeof(buf)); 99cc808594SShuo Chen if (nread < 0) 100cc808594SShuo Chen { 101cc808594SShuo Chen perror("read"); 102cc808594SShuo Chen close(fd); 103cc808594SShuo Chen exit(1); 104cc808594SShuo Chen } 105cc808594SShuo Chen printf("read %d bytes from tunnel interface %s.\n", nread, ifname); 106cc808594SShuo Chen 107b2fec1eaSShuo Chen const int iphdr_len = iphdr.ihl*4; 108cc808594SShuo Chen if (nread >= iphdr_size 109cc808594SShuo Chen && iphdr.version == 4 110b2fec1eaSShuo Chen && iphdr_len >= iphdr_size 111b2fec1eaSShuo Chen && iphdr_len <= nread 112cc808594SShuo Chen && iphdr.tot_len == htons(nread) 113b2fec1eaSShuo Chen && in_checksum(buf, iphdr_len) == 0) 114cc808594SShuo Chen { 115b2fec1eaSShuo Chen const void* payload = buf + iphdr_len; 116cc808594SShuo Chen if (iphdr.protocol == IPPROTO_ICMP) 117cc808594SShuo Chen { 118cc808594SShuo Chen icmp_input(fd, buf, payload, nread); 119cc808594SShuo Chen } 120cc808594SShuo Chen else if (iphdr.protocol == IPPROTO_TCP) 121cc808594SShuo Chen { 122cc808594SShuo Chen tcp_input(fd, buf, payload, nread); 123cc808594SShuo Chen } 124cc808594SShuo Chen } 125cc808594SShuo Chen else 126cc808594SShuo Chen { 127cc808594SShuo Chen printf("bad packet\n"); 128cc808594SShuo Chen for (int i = 0; i < nread; ++i) 129cc808594SShuo Chen { 130cc808594SShuo Chen if (i % 4 == 0) printf("\n"); 131cc808594SShuo Chen printf("%02x ", buf[i]); 132cc808594SShuo Chen } 133cc808594SShuo Chen printf("\n"); 134cc808594SShuo Chen } 135cc808594SShuo Chen } 136cc808594SShuo Chen 137cc808594SShuo Chen return 0; 138cc808594SShuo Chen} 139