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