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