faketcp.cc revision cc808594
1cc808594SShuo Chen#include "faketcp.h"
2cc808594SShuo Chen
3cc808594SShuo Chen#include <fcntl.h>
4cc808594SShuo Chen#include <stdio.h>
5cc808594SShuo Chen#include <string.h>
6cc808594SShuo Chen#include <unistd.h>
7cc808594SShuo Chen#include <linux/if_tun.h>
8cc808594SShuo Chen#include <netinet/in.h>
9cc808594SShuo Chen#include <netinet/ip_icmp.h>
10cc808594SShuo Chen#include <sys/ioctl.h>
11cc808594SShuo Chen
12cc808594SShuo Chenint tun_alloc(char *dev)
13cc808594SShuo Chen{
14cc808594SShuo Chen  struct ifreq ifr;
15cc808594SShuo Chen  int fd, err;
16cc808594SShuo Chen
17cc808594SShuo Chen  if ((fd = open("/dev/net/tun", O_RDWR)) < 0)
18cc808594SShuo Chen  {
19cc808594SShuo Chen    perror("open");
20cc808594SShuo Chen    return -1;
21cc808594SShuo Chen  }
22cc808594SShuo Chen
23cc808594SShuo Chen  memset(&ifr, 0, sizeof(ifr));
24cc808594SShuo Chen  ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
25cc808594SShuo Chen
26cc808594SShuo Chen  if (*dev)
27cc808594SShuo Chen  {
28cc808594SShuo Chen    strncpy(ifr.ifr_name, dev, IFNAMSIZ);
29cc808594SShuo Chen  }
30cc808594SShuo Chen
31cc808594SShuo Chen  if ((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0)
32cc808594SShuo Chen  {
33cc808594SShuo Chen    perror("ioctl");
34cc808594SShuo Chen    close(fd);
35cc808594SShuo Chen    return err;
36cc808594SShuo Chen  }
37cc808594SShuo Chen  strcpy(dev, ifr.ifr_name);
38cc808594SShuo Chen
39cc808594SShuo Chen  return fd;
40cc808594SShuo Chen}
41cc808594SShuo Chen
42cc808594SShuo Chenuint16_t in_checksum(const void* buf, int len)
43cc808594SShuo Chen{
44cc808594SShuo Chen  assert(len % 2 == 0);
45cc808594SShuo Chen  const uint16_t* data = static_cast<const uint16_t*>(buf);
46cc808594SShuo Chen  int sum = 0;
47cc808594SShuo Chen  for (int i = 0; i < len; i+=2)
48cc808594SShuo Chen  {
49cc808594SShuo Chen    sum += *data++;
50cc808594SShuo Chen  }
51cc808594SShuo Chen  // while (sum >> 16)
52cc808594SShuo Chen  sum = (sum & 0xFFFF) + (sum >> 16);
53cc808594SShuo Chen  assert(sum <= 0xFFFF);
54cc808594SShuo Chen  return ~sum;
55cc808594SShuo Chen}
56cc808594SShuo Chen
57cc808594SShuo Chenvoid icmp_input(int fd, const void* input, const void* payload, int len)
58cc808594SShuo Chen{
59cc808594SShuo Chen  const struct iphdr* iphdr = static_cast<const struct iphdr*>(input);
60cc808594SShuo Chen  const struct icmphdr* icmphdr = static_cast<const struct icmphdr*>(payload);
61cc808594SShuo Chen  // const int icmphdr_size = sizeof(*icmphdr);
62cc808594SShuo Chen  const int iphdr_len = iphdr->ihl*4;
63cc808594SShuo Chen
64cc808594SShuo Chen  if (icmphdr->type == ICMP_ECHO)
65cc808594SShuo Chen  {
66cc808594SShuo Chen    char source[INET_ADDRSTRLEN];
67cc808594SShuo Chen    char dest[INET_ADDRSTRLEN];
68cc808594SShuo Chen    inet_ntop(AF_INET, &iphdr->saddr, source, INET_ADDRSTRLEN);
69cc808594SShuo Chen    inet_ntop(AF_INET, &iphdr->daddr, dest, INET_ADDRSTRLEN);
70cc808594SShuo Chen    printf("%s > %s: ", source, dest);
71cc808594SShuo Chen    printf("ICMP echo request, id %d, seq %d, length %d\n",
72cc808594SShuo Chen           ntohs(icmphdr->un.echo.id),
73cc808594SShuo Chen           ntohs(icmphdr->un.echo.sequence),
74cc808594SShuo Chen           len - iphdr_len);
75cc808594SShuo Chen
76cc808594SShuo Chen    union
77cc808594SShuo Chen    {
78cc808594SShuo Chen      unsigned char output[ETH_FRAME_LEN];
79cc808594SShuo Chen      struct
80cc808594SShuo Chen      {
81cc808594SShuo Chen        struct iphdr iphdr;
82cc808594SShuo Chen        struct icmphdr icmphdr;
83cc808594SShuo Chen      } out;
84cc808594SShuo Chen    };
85cc808594SShuo Chen
86cc808594SShuo Chen    memcpy(output, input, len);
87cc808594SShuo Chen    out.icmphdr.type = ICMP_ECHOREPLY;
88cc808594SShuo Chen    out.icmphdr.checksum += ICMP_ECHO; // FIXME: not portable
89cc808594SShuo Chen    std::swap(out.iphdr.saddr, out.iphdr.daddr);
90cc808594SShuo Chen    write(fd, output, len);
91cc808594SShuo Chen  }
92cc808594SShuo Chen}
93cc808594SShuo Chen
94