12c431f66SShuo Chen#include "faketcp.h"
22c431f66SShuo Chen
32c431f66SShuo Chen#include <map>
42c431f66SShuo Chen
52c431f66SShuo Chen#include <stdio.h>
62c431f66SShuo Chen#include <stdlib.h>
72c431f66SShuo Chen#include <unistd.h>
82c431f66SShuo Chen#include <netinet/ip.h>
92c431f66SShuo Chen#include <netinet/tcp.h>
102c431f66SShuo Chen#include <linux/if_ether.h>
112c431f66SShuo Chen
122c431f66SShuo Chenstruct TcpState
132c431f66SShuo Chen{
142c431f66SShuo Chen  uint32_t rcv_nxt;
152c431f66SShuo Chen//  uint32_t snd_una;
162c431f66SShuo Chen};
172c431f66SShuo Chen
182c431f66SShuo Chenstd::map<SocketAddr, TcpState> expectedSeqs;
192c431f66SShuo Chen
202c431f66SShuo Chenvoid tcp_input(int fd, const void* input, const void* payload, int tot_len)
212c431f66SShuo Chen{
222c431f66SShuo Chen  const struct iphdr* iphdr = static_cast<const struct iphdr*>(input);
232c431f66SShuo Chen  const struct tcphdr* tcphdr = static_cast<const struct tcphdr*>(payload);
242c431f66SShuo Chen  const int iphdr_len = iphdr->ihl*4;
252c431f66SShuo Chen  const int tcp_seg_len = tot_len - iphdr_len;
262c431f66SShuo Chen  const int tcphdr_size = sizeof(*tcphdr);
272c431f66SShuo Chen  if (tcp_seg_len >= tcphdr_size
282c431f66SShuo Chen      && tcp_seg_len >= tcphdr->doff*4)
292c431f66SShuo Chen  {
302c431f66SShuo Chen    const int tcphdr_len = tcphdr->doff*4;
312c431f66SShuo Chen    const int payload_len = tot_len - iphdr_len - tcphdr_len;
322c431f66SShuo Chen
332c431f66SShuo Chen    char source[INET_ADDRSTRLEN];
342c431f66SShuo Chen    char dest[INET_ADDRSTRLEN];
352c431f66SShuo Chen    inet_ntop(AF_INET, &iphdr->saddr, source, INET_ADDRSTRLEN);
362c431f66SShuo Chen    inet_ntop(AF_INET, &iphdr->daddr, dest, INET_ADDRSTRLEN);
372c431f66SShuo Chen    printf("IP %s.%d > %s.%d: ",
382c431f66SShuo Chen           source, ntohs(tcphdr->source), dest, ntohs(tcphdr->dest));
392c431f66SShuo Chen    printf("Flags [%c], seq %u, win %d, length %d\n",
402c431f66SShuo Chen           tcphdr->syn ? 'S' : (tcphdr->fin ? 'F' : '.'),
412c431f66SShuo Chen           ntohl(tcphdr->seq),
422c431f66SShuo Chen           ntohs(tcphdr->window),
432c431f66SShuo Chen           payload_len);
442c431f66SShuo Chen
452c431f66SShuo Chen    union
462c431f66SShuo Chen    {
472c431f66SShuo Chen      unsigned char output[ETH_FRAME_LEN];
482c431f66SShuo Chen      struct
492c431f66SShuo Chen      {
502c431f66SShuo Chen        struct iphdr iphdr;
512c431f66SShuo Chen        struct tcphdr tcphdr;
522c431f66SShuo Chen      } out;
532c431f66SShuo Chen    };
542c431f66SShuo Chen
5561cf49ddSShuo Chen    static_assert(sizeof(out) == sizeof(struct iphdr) + sizeof(struct tcphdr), "");
562c431f66SShuo Chen    int output_len = sizeof(out);
572c431f66SShuo Chen    bzero(&out, output_len + 4);
582c431f66SShuo Chen    memcpy(output, input, sizeof(struct iphdr));
592c431f66SShuo Chen
602c431f66SShuo Chen    out.iphdr.tot_len = htons(output_len);
612c431f66SShuo Chen    std::swap(out.iphdr.saddr, out.iphdr.daddr);
622c431f66SShuo Chen    out.iphdr.check = 0;
632c431f66SShuo Chen    out.iphdr.check = in_checksum(output, sizeof(struct iphdr));
642c431f66SShuo Chen
652c431f66SShuo Chen    out.tcphdr.source = tcphdr->dest;
662c431f66SShuo Chen    out.tcphdr.dest = tcphdr->source;
672c431f66SShuo Chen    out.tcphdr.doff = sizeof(struct tcphdr) / 4;
682c431f66SShuo Chen    out.tcphdr.window = htons(5000);
692c431f66SShuo Chen
702c431f66SShuo Chen    SocketAddr addr = { out.iphdr.saddr, out.iphdr.daddr, out.tcphdr.source, out.tcphdr.dest };
712c431f66SShuo Chen    bool response = false;
722c431f66SShuo Chen    const uint32_t seq = ntohl(tcphdr->seq);
732c431f66SShuo Chen    if (tcphdr->syn)
742c431f66SShuo Chen    {
752c431f66SShuo Chen      out.tcphdr.seq = htonl(123456);
762c431f66SShuo Chen      out.tcphdr.ack_seq = htonl(seq+1);
772c431f66SShuo Chen      out.tcphdr.syn = 1;
782c431f66SShuo Chen      out.tcphdr.ack = 1;
792c431f66SShuo Chen      TcpState s = { seq + 1 };
802c431f66SShuo Chen      expectedSeqs[addr] = s;
812c431f66SShuo Chen      response = true;
822c431f66SShuo Chen    }
832c431f66SShuo Chen    else if (tcphdr->fin)
842c431f66SShuo Chen    {
852c431f66SShuo Chen      out.tcphdr.seq = htonl(123457);
862c431f66SShuo Chen      out.tcphdr.ack_seq = htonl(seq+1);
872c431f66SShuo Chen      out.tcphdr.fin = 1;
882c431f66SShuo Chen      out.tcphdr.ack = 1;
892c431f66SShuo Chen      expectedSeqs.erase(addr);
902c431f66SShuo Chen      response = true;
912c431f66SShuo Chen    }
922c431f66SShuo Chen    else if (payload_len > 0)
932c431f66SShuo Chen    {
942c431f66SShuo Chen      out.tcphdr.seq = htonl(123457);
952c431f66SShuo Chen      out.tcphdr.ack_seq = htonl(seq+payload_len);
962c431f66SShuo Chen      out.tcphdr.ack = 1;
972c431f66SShuo Chen      auto it = expectedSeqs.find(addr);
982c431f66SShuo Chen      if (it != expectedSeqs.end())
992c431f66SShuo Chen      {
1001dfcf3a2SShuo Chen        if (it->second.rcv_nxt >= seq)  // FIXME: wrap!
1012c431f66SShuo Chen        {
1022c431f66SShuo Chen          if (it->second.rcv_nxt == seq)
1032c431f66SShuo Chen          {
1042c431f66SShuo Chen            printf("received, seq = %u:%u, len = %u\n", seq, seq+payload_len, payload_len);
1052c431f66SShuo Chen          }
1062c431f66SShuo Chen          else
1072c431f66SShuo Chen          {
1082c431f66SShuo Chen            printf("retransmit, rcv_nxt = %u, seq = %u\n", it->second.rcv_nxt, seq);
1092c431f66SShuo Chen          }
1102c431f66SShuo Chen
1112c431f66SShuo Chen          const uint32_t ack = ntohl(out.tcphdr.ack_seq);
1122c431f66SShuo Chen          it->second.rcv_nxt = ack;
1132c431f66SShuo Chen          response = true;
1142c431f66SShuo Chen        }
1152c431f66SShuo Chen        else
1162c431f66SShuo Chen        {
1172c431f66SShuo Chen          printf("packet loss, rcv_nxt = %u, seq = %u\n", it->second.rcv_nxt, seq);
1182c431f66SShuo Chen        }
1192c431f66SShuo Chen      }
1202c431f66SShuo Chen      else
1212c431f66SShuo Chen      {
1222c431f66SShuo Chen        // RST
1232c431f66SShuo Chen      }
1242c431f66SShuo Chen    }
1252c431f66SShuo Chen
1262c431f66SShuo Chen    unsigned char* pseudo = output + output_len;
1272c431f66SShuo Chen    pseudo[0] = 0;
1282c431f66SShuo Chen    pseudo[1] = IPPROTO_TCP;
1292c431f66SShuo Chen    pseudo[2] = 0;
1302c431f66SShuo Chen    pseudo[3] = sizeof(struct tcphdr);
1312c431f66SShuo Chen    out.tcphdr.check = in_checksum(&out.iphdr.saddr, sizeof(struct tcphdr)+12);
1322c431f66SShuo Chen    if (response)
1332c431f66SShuo Chen    {
1342c431f66SShuo Chen      write(fd, output, output_len);
1352c431f66SShuo Chen    }
1362c431f66SShuo Chen  }
1372c431f66SShuo Chen}
1382c431f66SShuo Chen
1392c431f66SShuo Chenint main()
1402c431f66SShuo Chen{
1412c431f66SShuo Chen  char ifname[IFNAMSIZ] = "tun%d";
1422c431f66SShuo Chen  int fd = tun_alloc(ifname);
1432c431f66SShuo Chen
1442c431f66SShuo Chen  if (fd < 0)
1452c431f66SShuo Chen  {
1462c431f66SShuo Chen    fprintf(stderr, "tunnel interface allocation failed\n");
1472c431f66SShuo Chen    exit(1);
1482c431f66SShuo Chen  }
1492c431f66SShuo Chen
1502c431f66SShuo Chen  printf("allocted tunnel interface %s\n", ifname);
1512c431f66SShuo Chen  sleep(1);
1522c431f66SShuo Chen
1532c431f66SShuo Chen  for (;;)
1542c431f66SShuo Chen  {
1552c431f66SShuo Chen    union
1562c431f66SShuo Chen    {
15761cf49ddSShuo Chen      unsigned char buf[IP_MAXPACKET];
1582c431f66SShuo Chen      struct iphdr iphdr;
1592c431f66SShuo Chen    };
1602c431f66SShuo Chen
1612c431f66SShuo Chen    const int iphdr_size = sizeof iphdr;
1622c431f66SShuo Chen
1632c431f66SShuo Chen    int nread = read(fd, buf, sizeof(buf));
1642c431f66SShuo Chen    if (nread < 0)
1652c431f66SShuo Chen    {
1662c431f66SShuo Chen      perror("read");
1672c431f66SShuo Chen      close(fd);
1682c431f66SShuo Chen      exit(1);
1692c431f66SShuo Chen    }
17061cf49ddSShuo Chen    else if (nread == sizeof(buf))
17161cf49ddSShuo Chen    {
17261cf49ddSShuo Chen      printf("possible message truncated.\n");
17361cf49ddSShuo Chen    }
1742c431f66SShuo Chen    printf("read %d bytes from tunnel interface %s.\n", nread, ifname);
1752c431f66SShuo Chen
17661cf49ddSShuo Chen    const int iphdr_len = iphdr.ihl*4;  // FIXME: check nread >= sizeof iphdr before accessing iphdr.ihl.
1772c431f66SShuo Chen    if (nread >= iphdr_size
1782c431f66SShuo Chen        && iphdr.version == 4
1792c431f66SShuo Chen        && iphdr_len >= iphdr_size
1802c431f66SShuo Chen        && iphdr_len <= nread
1812c431f66SShuo Chen        && iphdr.tot_len == htons(nread)
1822c431f66SShuo Chen        && in_checksum(buf, iphdr_len) == 0)
1832c431f66SShuo Chen    {
1842c431f66SShuo Chen      const void* payload = buf + iphdr_len;
1852c431f66SShuo Chen      if (iphdr.protocol == IPPROTO_ICMP)
1862c431f66SShuo Chen      {
1872c431f66SShuo Chen        icmp_input(fd, buf, payload, nread);
1882c431f66SShuo Chen      }
1892c431f66SShuo Chen      else if (iphdr.protocol == IPPROTO_TCP)
1902c431f66SShuo Chen      {
1912c431f66SShuo Chen        tcp_input(fd, buf, payload, nread);
1922c431f66SShuo Chen      }
1932c431f66SShuo Chen    }
19461cf49ddSShuo Chen    else if (iphdr.version == 4)
1952c431f66SShuo Chen    {
1962c431f66SShuo Chen      printf("bad packet\n");
1972c431f66SShuo Chen      for (int i = 0; i < nread; ++i)
1982c431f66SShuo Chen      {
1992c431f66SShuo Chen        if (i % 4 == 0) printf("\n");
2002c431f66SShuo Chen        printf("%02x ", buf[i]);
2012c431f66SShuo Chen      }
2022c431f66SShuo Chen      printf("\n");
2032c431f66SShuo Chen    }
2042c431f66SShuo Chen  }
2052c431f66SShuo Chen
2062c431f66SShuo Chen  return 0;
2072c431f66SShuo Chen}
208