discardall.cc revision b2fec1ea
1bf7dd643SShuo Chen#include "faketcp.h" 2bf7dd643SShuo Chen 3bf7dd643SShuo Chen#include <stdio.h> 4bf7dd643SShuo Chen#include <stdlib.h> 5bf7dd643SShuo Chen#include <string.h> 6bf7dd643SShuo Chen#include <unistd.h> 7bf7dd643SShuo Chen#include <netinet/ip.h> 8bf7dd643SShuo Chen#include <netinet/tcp.h> 9bf7dd643SShuo Chen#include <linux/if_ether.h> 10bf7dd643SShuo Chen 11bf7dd643SShuo Chenvoid tcp_input(int fd, const void* input, const void* payload, int tot_len) 12bf7dd643SShuo Chen{ 13bf7dd643SShuo Chen const struct iphdr* iphdr = static_cast<const struct iphdr*>(input); 14bf7dd643SShuo Chen const struct tcphdr* tcphdr = static_cast<const struct tcphdr*>(payload); 15bf7dd643SShuo Chen const int iphdr_len = iphdr->ihl*4; 16bf7dd643SShuo Chen const int tcp_seg_len = tot_len - iphdr_len; 17bf7dd643SShuo Chen const int tcphdr_size = sizeof(*tcphdr); 18bf7dd643SShuo Chen if (tcp_seg_len >= tcphdr_size 19bf7dd643SShuo Chen && tcp_seg_len >= tcphdr->doff*4) 20bf7dd643SShuo Chen { 21bf7dd643SShuo Chen const int tcphdr_len = tcphdr->doff*4; 22bf7dd643SShuo Chen const int payload_len = tot_len - iphdr_len - tcphdr_len; 23bf7dd643SShuo Chen 24bf7dd643SShuo Chen char source[INET_ADDRSTRLEN]; 25bf7dd643SShuo Chen char dest[INET_ADDRSTRLEN]; 26bf7dd643SShuo Chen inet_ntop(AF_INET, &iphdr->saddr, source, INET_ADDRSTRLEN); 27bf7dd643SShuo Chen inet_ntop(AF_INET, &iphdr->daddr, dest, INET_ADDRSTRLEN); 28bf7dd643SShuo Chen printf("IP %s.%d > %s.%d: ", 29bf7dd643SShuo Chen source, ntohs(tcphdr->source), dest, ntohs(tcphdr->dest)); 30bf7dd643SShuo Chen printf("Flags [%c], seq %u, win %d, length %d\n", 31bf7dd643SShuo Chen tcphdr->syn ? 'S' : (tcphdr->fin ? 'F' : '.'), 32bf7dd643SShuo Chen ntohl(tcphdr->seq), 33bf7dd643SShuo Chen ntohs(tcphdr->window), 34bf7dd643SShuo Chen payload_len); 35bf7dd643SShuo Chen 36bf7dd643SShuo Chen union 37bf7dd643SShuo Chen { 38bf7dd643SShuo Chen unsigned char output[ETH_FRAME_LEN]; 39bf7dd643SShuo Chen struct 40bf7dd643SShuo Chen { 41bf7dd643SShuo Chen struct iphdr iphdr; 42bf7dd643SShuo Chen struct tcphdr tcphdr; 43bf7dd643SShuo Chen } out; 44bf7dd643SShuo Chen }; 45bf7dd643SShuo Chen 46bf7dd643SShuo Chen assert(sizeof(out) == sizeof(struct iphdr) + sizeof(struct tcphdr)); 47bf7dd643SShuo Chen int output_len = sizeof(out); 48bf7dd643SShuo Chen bzero(&out, output_len + 4); 49bf7dd643SShuo Chen memcpy(output, input, sizeof(struct iphdr)); 50bf7dd643SShuo Chen 51bf7dd643SShuo Chen out.iphdr.tot_len = htons(output_len); 52bf7dd643SShuo Chen std::swap(out.iphdr.saddr, out.iphdr.daddr); 53bf7dd643SShuo Chen out.iphdr.check = 0; 54bf7dd643SShuo Chen out.iphdr.check = in_checksum(output, sizeof(struct iphdr)); 55bf7dd643SShuo Chen 56bf7dd643SShuo Chen out.tcphdr.source = tcphdr->dest; 57bf7dd643SShuo Chen out.tcphdr.dest = tcphdr->source; 58bf7dd643SShuo Chen out.tcphdr.doff = sizeof(struct tcphdr) / 4; 59bf7dd643SShuo Chen out.tcphdr.window = htons(5000); 60bf7dd643SShuo Chen 61bf7dd643SShuo Chen bool response = false; 62bf7dd643SShuo Chen if (tcphdr->syn) 63bf7dd643SShuo Chen { 64bf7dd643SShuo Chen out.tcphdr.seq = htonl(123456); 65bf7dd643SShuo Chen out.tcphdr.ack_seq = htonl(ntohl(tcphdr->seq)+1); 66bf7dd643SShuo Chen out.tcphdr.syn = 1; 67bf7dd643SShuo Chen out.tcphdr.ack = 1; 68bf7dd643SShuo Chen response = true; 69bf7dd643SShuo Chen } 70bf7dd643SShuo Chen else if (tcphdr->fin) 71bf7dd643SShuo Chen { 72bf7dd643SShuo Chen out.tcphdr.seq = htonl(123457); 73bf7dd643SShuo Chen out.tcphdr.ack_seq = htonl(ntohl(tcphdr->seq)+1); 74bf7dd643SShuo Chen out.tcphdr.fin = 1; 75bf7dd643SShuo Chen out.tcphdr.ack = 1; 76bf7dd643SShuo Chen response = true; 77bf7dd643SShuo Chen } 78bf7dd643SShuo Chen else if (payload_len > 0) 79bf7dd643SShuo Chen { 80bf7dd643SShuo Chen out.tcphdr.seq = htonl(123457); 81bf7dd643SShuo Chen out.tcphdr.ack_seq = htonl(ntohl(tcphdr->seq)+payload_len); 82bf7dd643SShuo Chen out.tcphdr.ack = 1; 83bf7dd643SShuo Chen response = true; 84bf7dd643SShuo Chen } 85bf7dd643SShuo Chen 86bf7dd643SShuo Chen unsigned char* pseudo = output + output_len; 87bf7dd643SShuo Chen pseudo[0] = 0; 88bf7dd643SShuo Chen pseudo[1] = IPPROTO_TCP; 89bf7dd643SShuo Chen pseudo[2] = 0; 90bf7dd643SShuo Chen pseudo[3] = sizeof(struct tcphdr); 91bf7dd643SShuo Chen out.tcphdr.check = in_checksum(&out.iphdr.saddr, sizeof(struct tcphdr)+12); 92bf7dd643SShuo Chen if (response) 93bf7dd643SShuo Chen { 94bf7dd643SShuo Chen write(fd, output, output_len); 95bf7dd643SShuo Chen } 96bf7dd643SShuo Chen } 97bf7dd643SShuo Chen} 98bf7dd643SShuo Chen 99bf7dd643SShuo Chenint main() 100bf7dd643SShuo Chen{ 101bf7dd643SShuo Chen char ifname[IFNAMSIZ] = "tun%d"; 102bf7dd643SShuo Chen int fd = tun_alloc(ifname); 103bf7dd643SShuo Chen 104bf7dd643SShuo Chen if (fd < 0) 105bf7dd643SShuo Chen { 106bf7dd643SShuo Chen fprintf(stderr, "tunnel interface allocation failed\n"); 107bf7dd643SShuo Chen exit(1); 108bf7dd643SShuo Chen } 109bf7dd643SShuo Chen 110bf7dd643SShuo Chen printf("allocted tunnel interface %s\n", ifname); 111bf7dd643SShuo Chen sleep(1); 112bf7dd643SShuo Chen 113bf7dd643SShuo Chen for (;;) 114bf7dd643SShuo Chen { 115b2fec1eaSShuo Chen union 116b2fec1eaSShuo Chen { 117b2fec1eaSShuo Chen unsigned char buf[ETH_FRAME_LEN]; 118b2fec1eaSShuo Chen struct iphdr iphdr; 119b2fec1eaSShuo Chen }; 120b2fec1eaSShuo Chen 121b2fec1eaSShuo Chen const int iphdr_size = sizeof iphdr; 122b2fec1eaSShuo Chen 123bf7dd643SShuo Chen int nread = read(fd, buf, sizeof(buf)); 124bf7dd643SShuo Chen if (nread < 0) 125bf7dd643SShuo Chen { 126bf7dd643SShuo Chen perror("read"); 127bf7dd643SShuo Chen close(fd); 128bf7dd643SShuo Chen exit(1); 129bf7dd643SShuo Chen } 130bf7dd643SShuo Chen printf("read %d bytes from tunnel interface %s.\n", nread, ifname); 131bf7dd643SShuo Chen 132b2fec1eaSShuo Chen const int iphdr_len = iphdr.ihl*4; 133bf7dd643SShuo Chen if (nread >= iphdr_size 134bf7dd643SShuo Chen && iphdr.version == 4 135b2fec1eaSShuo Chen && iphdr_len >= iphdr_size 136b2fec1eaSShuo Chen && iphdr_len <= nread 137bf7dd643SShuo Chen && iphdr.tot_len == htons(nread) 138b2fec1eaSShuo Chen && in_checksum(buf, iphdr_len) == 0) 139bf7dd643SShuo Chen { 140b2fec1eaSShuo Chen const void* payload = buf + iphdr_len; 141bf7dd643SShuo Chen if (iphdr.protocol == IPPROTO_ICMP) 142bf7dd643SShuo Chen { 143bf7dd643SShuo Chen icmp_input(fd, buf, payload, nread); 144bf7dd643SShuo Chen } 145bf7dd643SShuo Chen else if (iphdr.protocol == IPPROTO_TCP) 146bf7dd643SShuo Chen { 147bf7dd643SShuo Chen tcp_input(fd, buf, payload, nread); 148bf7dd643SShuo Chen } 149bf7dd643SShuo Chen } 150bf7dd643SShuo Chen else 151bf7dd643SShuo Chen { 152bf7dd643SShuo Chen printf("bad packet\n"); 153bf7dd643SShuo Chen for (int i = 0; i < nread; ++i) 154bf7dd643SShuo Chen { 155bf7dd643SShuo Chen if (i % 4 == 0) printf("\n"); 156bf7dd643SShuo Chen printf("%02x ", buf[i]); 157bf7dd643SShuo Chen } 158bf7dd643SShuo Chen printf("\n"); 159bf7dd643SShuo Chen } 160bf7dd643SShuo Chen } 161bf7dd643SShuo Chen 162bf7dd643SShuo Chen return 0; 163bf7dd643SShuo Chen} 164