1b2fec1eaSShuo Chen#include "faketcp.h" 2b2fec1eaSShuo Chen 3b2fec1eaSShuo Chen#include <stdio.h> 4b2fec1eaSShuo Chen#include <stdlib.h> 5b2fec1eaSShuo Chen#include <string.h> 6b2fec1eaSShuo Chen#include <unistd.h> 7b2fec1eaSShuo Chen#include <netinet/ip.h> 8b2fec1eaSShuo Chen#include <netinet/tcp.h> 9b2fec1eaSShuo Chen#include <linux/if_ether.h> 10b2fec1eaSShuo Chen 11b2fec1eaSShuo Chenvoid tcp_input(int fd, const void* input, const void* payload, int tot_len, bool passive) 12b2fec1eaSShuo Chen{ 13b2fec1eaSShuo Chen const struct iphdr* iphdr = static_cast<const struct iphdr*>(input); 14b2fec1eaSShuo Chen const struct tcphdr* tcphdr = static_cast<const struct tcphdr*>(payload); 15b2fec1eaSShuo Chen const int iphdr_len = iphdr->ihl*4; 16b2fec1eaSShuo Chen const int tcp_seg_len = tot_len - iphdr_len; 17b2fec1eaSShuo Chen const int tcphdr_size = sizeof(*tcphdr); 18b2fec1eaSShuo Chen if (tcp_seg_len >= tcphdr_size 19b2fec1eaSShuo Chen && tcp_seg_len >= tcphdr->doff*4) 20b2fec1eaSShuo Chen { 21b2fec1eaSShuo Chen const int tcphdr_len = tcphdr->doff*4; 22b2fec1eaSShuo Chen const int payload_len = tot_len - iphdr_len - tcphdr_len; 23b2fec1eaSShuo Chen 24b2fec1eaSShuo Chen char source[INET_ADDRSTRLEN]; 25b2fec1eaSShuo Chen char dest[INET_ADDRSTRLEN]; 26b2fec1eaSShuo Chen inet_ntop(AF_INET, &iphdr->saddr, source, INET_ADDRSTRLEN); 27b2fec1eaSShuo Chen inet_ntop(AF_INET, &iphdr->daddr, dest, INET_ADDRSTRLEN); 28b2fec1eaSShuo Chen printf("IP %s.%d > %s.%d: ", 29b2fec1eaSShuo Chen source, ntohs(tcphdr->source), dest, ntohs(tcphdr->dest)); 30b2fec1eaSShuo Chen printf("Flags [%c], seq %u, win %d, length %d\n", 31b2fec1eaSShuo Chen tcphdr->syn ? 'S' : (tcphdr->fin ? 'F' : '.'), 32b2fec1eaSShuo Chen ntohl(tcphdr->seq), 33b2fec1eaSShuo Chen ntohs(tcphdr->window), 34b2fec1eaSShuo Chen payload_len); 35b2fec1eaSShuo Chen 36b2fec1eaSShuo Chen union 37b2fec1eaSShuo Chen { 38b2fec1eaSShuo Chen unsigned char output[ETH_FRAME_LEN]; 39b2fec1eaSShuo Chen struct 40b2fec1eaSShuo Chen { 41b2fec1eaSShuo Chen struct iphdr iphdr; 42b2fec1eaSShuo Chen struct tcphdr tcphdr; 43b2fec1eaSShuo Chen } out; 44b2fec1eaSShuo Chen }; 45b2fec1eaSShuo Chen 46b2fec1eaSShuo Chen assert(sizeof(out) == sizeof(struct iphdr) + sizeof(struct tcphdr)); 47b2fec1eaSShuo Chen int output_len = sizeof(out); 48b2fec1eaSShuo Chen bzero(&out, output_len + 4); 49b2fec1eaSShuo Chen memcpy(output, input, sizeof(struct iphdr)); 50b2fec1eaSShuo Chen 51b2fec1eaSShuo Chen out.iphdr.tot_len = htons(output_len); 52b2fec1eaSShuo Chen std::swap(out.iphdr.saddr, out.iphdr.daddr); 53b2fec1eaSShuo Chen out.iphdr.check = 0; 54b2fec1eaSShuo Chen out.iphdr.check = in_checksum(output, sizeof(struct iphdr)); 55b2fec1eaSShuo Chen 56b2fec1eaSShuo Chen out.tcphdr.source = tcphdr->dest; 57b2fec1eaSShuo Chen out.tcphdr.dest = tcphdr->source; 58b2fec1eaSShuo Chen out.tcphdr.doff = sizeof(struct tcphdr) / 4; 59b2fec1eaSShuo Chen out.tcphdr.window = htons(5000); 60b2fec1eaSShuo Chen 61b2fec1eaSShuo Chen bool response = false; 62b2fec1eaSShuo Chen if (tcphdr->syn) 63b2fec1eaSShuo Chen { 64b2fec1eaSShuo Chen out.tcphdr.seq = htonl(passive ? 123456 : 123457); 65b2fec1eaSShuo Chen out.tcphdr.ack_seq = htonl(ntohl(tcphdr->seq)+1); 66b2fec1eaSShuo Chen if (passive) 67b2fec1eaSShuo Chen { 68b2fec1eaSShuo Chen out.tcphdr.syn = 1; 69b2fec1eaSShuo Chen } 70b2fec1eaSShuo Chen out.tcphdr.ack = 1; 71b2fec1eaSShuo Chen response = true; 72b2fec1eaSShuo Chen } 73b2fec1eaSShuo Chen else if (tcphdr->fin) 74b2fec1eaSShuo Chen { 75b2fec1eaSShuo Chen out.tcphdr.seq = htonl(123457); 76b2fec1eaSShuo Chen out.tcphdr.ack_seq = htonl(ntohl(tcphdr->seq)+1); 77b2fec1eaSShuo Chen out.tcphdr.fin = 1; 78b2fec1eaSShuo Chen out.tcphdr.ack = 1; 79b2fec1eaSShuo Chen response = true; 80b2fec1eaSShuo Chen } 81b2fec1eaSShuo Chen else if (payload_len > 0) 82b2fec1eaSShuo Chen { 83b2fec1eaSShuo Chen out.tcphdr.seq = htonl(123457); 84b2fec1eaSShuo Chen out.tcphdr.ack_seq = htonl(ntohl(tcphdr->seq)+payload_len); 85b2fec1eaSShuo Chen out.tcphdr.ack = 1; 86b2fec1eaSShuo Chen response = true; 87b2fec1eaSShuo Chen } 88b2fec1eaSShuo Chen 89b2fec1eaSShuo Chen unsigned char* pseudo = output + output_len; 90b2fec1eaSShuo Chen pseudo[0] = 0; 91b2fec1eaSShuo Chen pseudo[1] = IPPROTO_TCP; 92b2fec1eaSShuo Chen pseudo[2] = 0; 93b2fec1eaSShuo Chen pseudo[3] = sizeof(struct tcphdr); 94b2fec1eaSShuo Chen out.tcphdr.check = in_checksum(&out.iphdr.saddr, sizeof(struct tcphdr)+12); 95b2fec1eaSShuo Chen if (response) 96b2fec1eaSShuo Chen { 97b2fec1eaSShuo Chen write(fd, output, output_len); 98b2fec1eaSShuo Chen } 99b2fec1eaSShuo Chen } 100b2fec1eaSShuo Chen} 101b2fec1eaSShuo Chen 102b2fec1eaSShuo Chen 103b2fec1eaSShuo Chenbool connect_one(int fd, uint32_t daddr, int dport, uint32_t saddr, int sport) 104b2fec1eaSShuo Chen{ 105b2fec1eaSShuo Chen { 106b2fec1eaSShuo Chen union 107b2fec1eaSShuo Chen { 108b2fec1eaSShuo Chen unsigned char output[ETH_FRAME_LEN]; 109b2fec1eaSShuo Chen struct 110b2fec1eaSShuo Chen { 111b2fec1eaSShuo Chen struct iphdr iphdr; 112b2fec1eaSShuo Chen struct tcphdr tcphdr; 113b2fec1eaSShuo Chen } out; 114b2fec1eaSShuo Chen }; 115b2fec1eaSShuo Chen 116b2fec1eaSShuo Chen bzero(&out, (sizeof out)+4); 117b2fec1eaSShuo Chen 118b2fec1eaSShuo Chen out.iphdr.version = IPVERSION; 119b2fec1eaSShuo Chen out.iphdr.ihl = sizeof(out.iphdr)/4; 120b2fec1eaSShuo Chen out.iphdr.tos = 0; 121b2fec1eaSShuo Chen out.iphdr.tot_len = htons(sizeof(out)); 122b2fec1eaSShuo Chen out.iphdr.id = 55564; 123b2fec1eaSShuo Chen out.iphdr.frag_off |= htons(IP_DF); 124b2fec1eaSShuo Chen out.iphdr.ttl = IPDEFTTL; 125b2fec1eaSShuo Chen out.iphdr.protocol = IPPROTO_TCP; 126b2fec1eaSShuo Chen out.iphdr.saddr = saddr; 127b2fec1eaSShuo Chen out.iphdr.daddr = daddr; 128b2fec1eaSShuo Chen out.iphdr.check = in_checksum(output, sizeof(struct iphdr)); 129b2fec1eaSShuo Chen 130b2fec1eaSShuo Chen out.tcphdr.source = sport; 131b2fec1eaSShuo Chen out.tcphdr.dest = dport; 132b2fec1eaSShuo Chen out.tcphdr.seq = htonl(123456); 133b2fec1eaSShuo Chen out.tcphdr.ack_seq = 0; 134b2fec1eaSShuo Chen out.tcphdr.doff = sizeof(out.tcphdr)/4; 135b2fec1eaSShuo Chen out.tcphdr.syn = 1; 136b2fec1eaSShuo Chen out.tcphdr.window = htons(4096); 137b2fec1eaSShuo Chen 138b2fec1eaSShuo Chen unsigned char* pseudo = output + sizeof out; 139b2fec1eaSShuo Chen pseudo[0] = 0; 140b2fec1eaSShuo Chen pseudo[1] = IPPROTO_TCP; 141b2fec1eaSShuo Chen pseudo[2] = 0; 142b2fec1eaSShuo Chen pseudo[3] = sizeof(struct tcphdr); 143b2fec1eaSShuo Chen out.tcphdr.check = in_checksum(&out.iphdr.saddr, sizeof(struct tcphdr)+12); 144b2fec1eaSShuo Chen 145b2fec1eaSShuo Chen write(fd, output, sizeof out); 146b2fec1eaSShuo Chen } 147b2fec1eaSShuo Chen 148b2fec1eaSShuo Chen union 149b2fec1eaSShuo Chen { 150b2fec1eaSShuo Chen unsigned char buf[ETH_FRAME_LEN]; 151b2fec1eaSShuo Chen struct iphdr iphdr; 152b2fec1eaSShuo Chen }; 153b2fec1eaSShuo Chen 154b2fec1eaSShuo Chen const int iphdr_size = sizeof iphdr; 155b2fec1eaSShuo Chen 156b2fec1eaSShuo Chen int nread = read(fd, buf, sizeof(buf)); 157b2fec1eaSShuo Chen if (nread < 0) 158b2fec1eaSShuo Chen { 159b2fec1eaSShuo Chen perror("read"); 160b2fec1eaSShuo Chen close(fd); 161b2fec1eaSShuo Chen exit(1); 162b2fec1eaSShuo Chen } 163b2fec1eaSShuo Chen // printf("read %d bytes from tunnel interface %s.\n", nread, ifname); 164b2fec1eaSShuo Chen 165b2fec1eaSShuo Chen if (nread >= iphdr_size 166b2fec1eaSShuo Chen && iphdr.version == 4 167b2fec1eaSShuo Chen && iphdr.ihl*4 >= iphdr_size 168b2fec1eaSShuo Chen && iphdr.ihl*4 <= nread 169b2fec1eaSShuo Chen && iphdr.tot_len == htons(nread) 170b2fec1eaSShuo Chen && in_checksum(buf, iphdr.ihl*4) == 0) 171b2fec1eaSShuo Chen { 172b2fec1eaSShuo Chen const void* payload = buf + iphdr.ihl*4; 173b2fec1eaSShuo Chen if (iphdr.protocol == IPPROTO_ICMP) 174b2fec1eaSShuo Chen { 175b2fec1eaSShuo Chen icmp_input(fd, buf, payload, nread); 176b2fec1eaSShuo Chen } 177b2fec1eaSShuo Chen else if (iphdr.protocol == IPPROTO_TCP) 178b2fec1eaSShuo Chen { 179b2fec1eaSShuo Chen tcp_input(fd, buf, payload, nread, false); 180b2fec1eaSShuo Chen } 181b2fec1eaSShuo Chen } 182b2fec1eaSShuo Chen 183b2fec1eaSShuo Chen return true; 184b2fec1eaSShuo Chen} 185b2fec1eaSShuo Chen 186b2fec1eaSShuo Chenvoid connect_many(int fd, const char* ipstr, int port, int count) 187b2fec1eaSShuo Chen{ 188b2fec1eaSShuo Chen uint32_t destip; 189b2fec1eaSShuo Chen inet_pton(AF_INET, ipstr, &destip); 190b2fec1eaSShuo Chen 191b2fec1eaSShuo Chen uint32_t srcip = ntohl(destip)+1; 192b2fec1eaSShuo Chen int srcport = 1024; 193b2fec1eaSShuo Chen 194b2fec1eaSShuo Chen for (int i = 0; i < count; ++i) 195b2fec1eaSShuo Chen { 196b2fec1eaSShuo Chen connect_one(fd, destip, htons(port), htonl(srcip), htons(srcport)); 197b2fec1eaSShuo Chen srcport++; 198b2fec1eaSShuo Chen if (srcport > 0xFFFF) 199b2fec1eaSShuo Chen { 200b2fec1eaSShuo Chen srcport = 1024; 201b2fec1eaSShuo Chen srcip++; 202b2fec1eaSShuo Chen } 203b2fec1eaSShuo Chen } 204b2fec1eaSShuo Chen} 205b2fec1eaSShuo Chen 206b2fec1eaSShuo Chenvoid usage() 207b2fec1eaSShuo Chen{ 208b2fec1eaSShuo Chen} 209b2fec1eaSShuo Chen 210b2fec1eaSShuo Chenint main(int argc, char* argv[]) 211b2fec1eaSShuo Chen{ 212b2fec1eaSShuo Chen if (argc < 4) 213b2fec1eaSShuo Chen { 214b2fec1eaSShuo Chen usage(); 215b2fec1eaSShuo Chen return 0; 216b2fec1eaSShuo Chen } 217b2fec1eaSShuo Chen 218b2fec1eaSShuo Chen char ifname[IFNAMSIZ] = "tun%d"; 219b2fec1eaSShuo Chen int fd = tun_alloc(ifname); 220b2fec1eaSShuo Chen 221b2fec1eaSShuo Chen if (fd < 0) 222b2fec1eaSShuo Chen { 223b2fec1eaSShuo Chen fprintf(stderr, "tunnel interface allocation failed\n"); 224b2fec1eaSShuo Chen exit(1); 225b2fec1eaSShuo Chen } 226b2fec1eaSShuo Chen 227b2fec1eaSShuo Chen const char* ip = argv[1]; 228b2fec1eaSShuo Chen int port = atoi(argv[2]); 229b2fec1eaSShuo Chen int count = atoi(argv[3]); 230b2fec1eaSShuo Chen printf("allocted tunnel interface %s\n", ifname); 231b2fec1eaSShuo Chen printf("press enter key to start connecting %s:%d\n", ip, port); 232b2fec1eaSShuo Chen getchar(); 233b2fec1eaSShuo Chen 234b2fec1eaSShuo Chen connect_many(fd, ip, port, count); 235b2fec1eaSShuo Chen 236b2fec1eaSShuo Chen for (;;) 237b2fec1eaSShuo Chen { 238b2fec1eaSShuo Chen union 239b2fec1eaSShuo Chen { 240b2fec1eaSShuo Chen unsigned char buf[ETH_FRAME_LEN]; 241b2fec1eaSShuo Chen struct iphdr iphdr; 242b2fec1eaSShuo Chen }; 243b2fec1eaSShuo Chen 244b2fec1eaSShuo Chen const int iphdr_size = sizeof iphdr; 245b2fec1eaSShuo Chen 246b2fec1eaSShuo Chen int nread = read(fd, buf, sizeof(buf)); 247b2fec1eaSShuo Chen if (nread < 0) 248b2fec1eaSShuo Chen { 249b2fec1eaSShuo Chen perror("read"); 250b2fec1eaSShuo Chen close(fd); 251b2fec1eaSShuo Chen exit(1); 252b2fec1eaSShuo Chen } 253b2fec1eaSShuo Chen printf("read %d bytes from tunnel interface %s.\n", nread, ifname); 254b2fec1eaSShuo Chen 255b2fec1eaSShuo Chen const int iphdr_len = iphdr.ihl*4; 256b2fec1eaSShuo Chen if (nread >= iphdr_size 257b2fec1eaSShuo Chen && iphdr.version == 4 258b2fec1eaSShuo Chen && iphdr_len >= iphdr_size 259b2fec1eaSShuo Chen && iphdr_len <= nread 260b2fec1eaSShuo Chen && iphdr.tot_len == htons(nread) 261b2fec1eaSShuo Chen && in_checksum(buf, iphdr_len) == 0) 262b2fec1eaSShuo Chen { 263b2fec1eaSShuo Chen const void* payload = buf + iphdr_len; 264b2fec1eaSShuo Chen if (iphdr.protocol == IPPROTO_ICMP) 265b2fec1eaSShuo Chen { 266b2fec1eaSShuo Chen icmp_input(fd, buf, payload, nread); 267b2fec1eaSShuo Chen } 268b2fec1eaSShuo Chen else if (iphdr.protocol == IPPROTO_TCP) 269b2fec1eaSShuo Chen { 270b2fec1eaSShuo Chen tcp_input(fd, buf, payload, nread, true); 271b2fec1eaSShuo Chen } 272b2fec1eaSShuo Chen } 273b2fec1eaSShuo Chen else 274b2fec1eaSShuo Chen { 275b2fec1eaSShuo Chen printf("bad packet\n"); 276b2fec1eaSShuo Chen for (int i = 0; i < nread; ++i) 277b2fec1eaSShuo Chen { 278b2fec1eaSShuo Chen if (i % 4 == 0) printf("\n"); 279b2fec1eaSShuo Chen printf("%02x ", buf[i]); 280b2fec1eaSShuo Chen } 281b2fec1eaSShuo Chen printf("\n"); 282b2fec1eaSShuo Chen } 283b2fec1eaSShuo Chen } 284b2fec1eaSShuo Chen 285b2fec1eaSShuo Chen return 0; 286b2fec1eaSShuo Chen} 287