Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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