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);
1584d8a3dfSShuo Chen  const int iphdr_len = iphdr->ihl*4;
1684d8a3dfSShuo Chen  const int tcp_seg_len = tot_len - iphdr_len;
1784d8a3dfSShuo Chen  const int tcphdr_size = sizeof(*tcphdr);
1884d8a3dfSShuo Chen  if (tcp_seg_len >= tcphdr_size
1984d8a3dfSShuo Chen      && tcp_seg_len >= tcphdr->doff*4)
2084d8a3dfSShuo Chen  {
2184d8a3dfSShuo Chen    const int tcphdr_len = tcphdr->doff*4;
2284d8a3dfSShuo Chen
2384d8a3dfSShuo Chen    char source[INET_ADDRSTRLEN];
2484d8a3dfSShuo Chen    char dest[INET_ADDRSTRLEN];
2584d8a3dfSShuo Chen    inet_ntop(AF_INET, &iphdr->saddr, source, INET_ADDRSTRLEN);
2684d8a3dfSShuo Chen    inet_ntop(AF_INET, &iphdr->daddr, dest, INET_ADDRSTRLEN);
2784d8a3dfSShuo Chen    printf("IP %s.%d > %s.%d: ",
2884d8a3dfSShuo Chen           source, ntohs(tcphdr->source), dest, ntohs(tcphdr->dest));
2984d8a3dfSShuo Chen    printf("Flags [%c], seq %u, win %d, length %d\n",
3084d8a3dfSShuo Chen           tcphdr->syn ? 'S' : (tcphdr->fin ? 'F' : '.'),
3184d8a3dfSShuo Chen           ntohl(tcphdr->seq),
3284d8a3dfSShuo Chen           ntohs(tcphdr->window),
3384d8a3dfSShuo Chen           tot_len - iphdr_len - tcphdr_len);
3484d8a3dfSShuo Chen
3584d8a3dfSShuo Chen    union
3684d8a3dfSShuo Chen    {
3784d8a3dfSShuo Chen      unsigned char output[ETH_FRAME_LEN];
3884d8a3dfSShuo Chen      struct
3984d8a3dfSShuo Chen      {
4084d8a3dfSShuo Chen        struct iphdr iphdr;
4184d8a3dfSShuo Chen        struct tcphdr tcphdr;
4284d8a3dfSShuo Chen      } out;
4384d8a3dfSShuo Chen    };
4484d8a3dfSShuo Chen
4584d8a3dfSShuo Chen    assert(sizeof(out) == sizeof(struct iphdr) + sizeof(struct tcphdr));
4684d8a3dfSShuo Chen    int output_len = sizeof(out);
4784d8a3dfSShuo Chen    bzero(&out, output_len + 4);
4884d8a3dfSShuo Chen    memcpy(output, input, sizeof(struct iphdr));
4984d8a3dfSShuo Chen
5084d8a3dfSShuo Chen    out.iphdr.tot_len = htons(output_len);
5184d8a3dfSShuo Chen    std::swap(out.iphdr.saddr, out.iphdr.daddr);
5284d8a3dfSShuo Chen    out.iphdr.check = 0;
5384d8a3dfSShuo Chen    out.iphdr.check = in_checksum(output, sizeof(struct iphdr));
5484d8a3dfSShuo Chen
5584d8a3dfSShuo Chen    out.tcphdr.source = tcphdr->dest;
5684d8a3dfSShuo Chen    out.tcphdr.dest = tcphdr->source;
5784d8a3dfSShuo Chen    out.tcphdr.ack_seq = htonl(ntohl(tcphdr->seq)+1);
5884d8a3dfSShuo Chen    out.tcphdr.doff = sizeof(struct tcphdr) / 4;
5984d8a3dfSShuo Chen    out.tcphdr.window = htons(5000);
6084d8a3dfSShuo Chen
6184d8a3dfSShuo Chen    bool response = false;
6284d8a3dfSShuo Chen    if (tcphdr->syn)
6384d8a3dfSShuo Chen    {
6484d8a3dfSShuo Chen      out.tcphdr.seq = htonl(123456);
6584d8a3dfSShuo Chen      out.tcphdr.syn = 1;
6684d8a3dfSShuo Chen      out.tcphdr.ack = 1;
6784d8a3dfSShuo Chen      response = true;
6884d8a3dfSShuo Chen    }
6984d8a3dfSShuo Chen    else if (tcphdr->fin)
7084d8a3dfSShuo Chen    {
7184d8a3dfSShuo Chen      out.tcphdr.seq = htonl(123457);
7284d8a3dfSShuo Chen      out.tcphdr.fin = 1;
7384d8a3dfSShuo Chen      out.tcphdr.ack = 1;
7484d8a3dfSShuo Chen      response = true;
7584d8a3dfSShuo Chen    }
76cc808594SShuo Chen
7784d8a3dfSShuo Chen    unsigned char* pseudo = output + output_len;
7884d8a3dfSShuo Chen    pseudo[0] = 0;
7984d8a3dfSShuo Chen    pseudo[1] = IPPROTO_TCP;
8084d8a3dfSShuo Chen    pseudo[2] = 0;
8184d8a3dfSShuo Chen    pseudo[3] = sizeof(struct tcphdr);
8284d8a3dfSShuo Chen    out.tcphdr.check = in_checksum(&out.iphdr.saddr, sizeof(struct tcphdr)+12);
8384d8a3dfSShuo Chen    if (response)
8484d8a3dfSShuo Chen    {
8584d8a3dfSShuo Chen      write(fd, output, output_len);
8684d8a3dfSShuo Chen    }
8784d8a3dfSShuo Chen  }
88cc808594SShuo Chen}
89cc808594SShuo Chen
90cc808594SShuo Chenint main()
91cc808594SShuo Chen{
92cc808594SShuo Chen  char ifname[IFNAMSIZ] = "tun%d";
93cc808594SShuo Chen  int fd = tun_alloc(ifname);
94cc808594SShuo Chen
95cc808594SShuo Chen  if (fd < 0)
96cc808594SShuo Chen  {
97cc808594SShuo Chen    fprintf(stderr, "tunnel interface allocation failed\n");
98cc808594SShuo Chen    exit(1);
99cc808594SShuo Chen  }
100cc808594SShuo Chen
101cc808594SShuo Chen  printf("allocted tunnel interface %s\n", ifname);
102cc808594SShuo Chen  sleep(1);
103cc808594SShuo Chen
104cc808594SShuo Chen  for (;;)
105cc808594SShuo Chen  {
106b2fec1eaSShuo Chen    union
107b2fec1eaSShuo Chen    {
108b2fec1eaSShuo Chen      unsigned char buf[ETH_FRAME_LEN];
109b2fec1eaSShuo Chen      struct iphdr iphdr;
110b2fec1eaSShuo Chen    };
111b2fec1eaSShuo Chen
112b2fec1eaSShuo Chen    const int iphdr_size = sizeof iphdr;
113b2fec1eaSShuo Chen
114cc808594SShuo Chen    int nread = read(fd, buf, sizeof(buf));
115cc808594SShuo Chen    if (nread < 0)
116cc808594SShuo Chen    {
117cc808594SShuo Chen      perror("read");
118cc808594SShuo Chen      close(fd);
119cc808594SShuo Chen      exit(1);
120cc808594SShuo Chen    }
121cc808594SShuo Chen    printf("read %d bytes from tunnel interface %s.\n", nread, ifname);
122cc808594SShuo Chen
123b2fec1eaSShuo Chen    const int iphdr_len = iphdr.ihl*4;
124cc808594SShuo Chen    if (nread >= iphdr_size
125cc808594SShuo Chen        && iphdr.version == 4
126b2fec1eaSShuo Chen        && iphdr_len >= iphdr_size
127b2fec1eaSShuo Chen        && iphdr_len <= nread
128cc808594SShuo Chen        && iphdr.tot_len == htons(nread)
129b2fec1eaSShuo Chen        && in_checksum(buf, iphdr_len) == 0)
130cc808594SShuo Chen    {
131b2fec1eaSShuo Chen      const void* payload = buf + iphdr_len;
132cc808594SShuo Chen      if (iphdr.protocol == IPPROTO_ICMP)
133cc808594SShuo Chen      {
134cc808594SShuo Chen        icmp_input(fd, buf, payload, nread);
135cc808594SShuo Chen      }
136cc808594SShuo Chen      else if (iphdr.protocol == IPPROTO_TCP)
137cc808594SShuo Chen      {
138cc808594SShuo Chen        tcp_input(fd, buf, payload, nread);
139cc808594SShuo Chen      }
140cc808594SShuo Chen    }
141cc808594SShuo Chen    else
142cc808594SShuo Chen    {
143cc808594SShuo Chen      printf("bad packet\n");
144cc808594SShuo Chen      for (int i = 0; i < nread; ++i)
145cc808594SShuo Chen      {
146cc808594SShuo Chen        if (i % 4 == 0) printf("\n");
147cc808594SShuo Chen        printf("%02x ", buf[i]);
148cc808594SShuo Chen      }
149cc808594SShuo Chen      printf("\n");
150cc808594SShuo Chen    }
151cc808594SShuo Chen  }
152cc808594SShuo Chen
153cc808594SShuo Chen  return 0;
154cc808594SShuo Chen}
155