faketcp.cc revision bcb7e916
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 12bcb7e916SShuo Chenint sethostaddr(const char* dev) 13bcb7e916SShuo Chen{ 14bcb7e916SShuo Chen struct ifreq ifr; 15bcb7e916SShuo Chen bzero(&ifr, sizeof(ifr)); 16bcb7e916SShuo Chen strcpy(ifr.ifr_name, dev); 17bcb7e916SShuo Chen struct sockaddr_in addr; 18bcb7e916SShuo Chen bzero(&addr, sizeof addr); 19bcb7e916SShuo Chen addr.sin_family = AF_INET; 20bcb7e916SShuo Chen inet_pton(AF_INET, "192.168.0.1", &addr.sin_addr); 21bcb7e916SShuo Chen //addr.sin_addr.s_addr = htonl(0xc0a80001); 22bcb7e916SShuo Chen bcopy(&addr, &ifr.ifr_addr, sizeof addr); 23bcb7e916SShuo Chen int sockfd = socket(AF_INET, SOCK_DGRAM, 0); 24bcb7e916SShuo Chen if (sockfd < 0) 25bcb7e916SShuo Chen return sockfd; 26bcb7e916SShuo Chen int err = 0; 27bcb7e916SShuo Chen // ifconfig tun0 192.168.0.1 28bcb7e916SShuo Chen if ((err = ioctl(sockfd, SIOCSIFADDR, (void *) &ifr)) < 0) 29bcb7e916SShuo Chen { 30bcb7e916SShuo Chen perror("ioctl SIOCSIFADDR"); 31bcb7e916SShuo Chen goto done; 32bcb7e916SShuo Chen } 33bcb7e916SShuo Chen // ifup tun0 34bcb7e916SShuo Chen if ((err = ioctl(sockfd, SIOCGIFFLAGS, (void *) &ifr)) < 0) 35bcb7e916SShuo Chen { 36bcb7e916SShuo Chen perror("ioctl SIOCGIFFLAGS"); 37bcb7e916SShuo Chen goto done; 38bcb7e916SShuo Chen } 39bcb7e916SShuo Chen ifr.ifr_flags |= IFF_UP; 40bcb7e916SShuo Chen if ((err = ioctl(sockfd, SIOCSIFFLAGS, (void *) &ifr)) < 0) 41bcb7e916SShuo Chen { 42bcb7e916SShuo Chen perror("ioctl SIOCSIFFLAGS"); 43bcb7e916SShuo Chen goto done; 44bcb7e916SShuo Chen } 45bcb7e916SShuo Chen // ifconfig tun0 192.168.0.1/24 46bcb7e916SShuo Chen inet_pton(AF_INET, "255.255.255.0", &addr.sin_addr); 47bcb7e916SShuo Chen bcopy(&addr, &ifr.ifr_netmask, sizeof addr); 48bcb7e916SShuo Chen if ((err = ioctl(sockfd, SIOCSIFNETMASK, (void *) &ifr)) < 0) 49bcb7e916SShuo Chen { 50bcb7e916SShuo Chen perror("ioctl SIOCSIFNETMASK"); 51bcb7e916SShuo Chen goto done; 52bcb7e916SShuo Chen } 53bcb7e916SShuo Chendone: 54bcb7e916SShuo Chen close(sockfd); 55bcb7e916SShuo Chen return err; 56bcb7e916SShuo Chen} 57bcb7e916SShuo Chen 58bcb7e916SShuo Chen 59bcb7e916SShuo Chenint tun_alloc(char dev[IFNAMSIZ]) 60cc808594SShuo Chen{ 61cc808594SShuo Chen struct ifreq ifr; 62cc808594SShuo Chen int fd, err; 63cc808594SShuo Chen 64cc808594SShuo Chen if ((fd = open("/dev/net/tun", O_RDWR)) < 0) 65cc808594SShuo Chen { 66cc808594SShuo Chen perror("open"); 67cc808594SShuo Chen return -1; 68cc808594SShuo Chen } 69cc808594SShuo Chen 70bcb7e916SShuo Chen bzero(&ifr, sizeof(ifr)); 71cc808594SShuo Chen ifr.ifr_flags = IFF_TUN | IFF_NO_PI; 72cc808594SShuo Chen 73cc808594SShuo Chen if (*dev) 74cc808594SShuo Chen { 75cc808594SShuo Chen strncpy(ifr.ifr_name, dev, IFNAMSIZ); 76cc808594SShuo Chen } 77cc808594SShuo Chen 78cc808594SShuo Chen if ((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0) 79cc808594SShuo Chen { 80bcb7e916SShuo Chen perror("ioctl TUNSETIFF"); 81cc808594SShuo Chen close(fd); 82cc808594SShuo Chen return err; 83cc808594SShuo Chen } 84cc808594SShuo Chen strcpy(dev, ifr.ifr_name); 85bcb7e916SShuo Chen if ((err = sethostaddr(dev)) < 0) 86bcb7e916SShuo Chen return err; 87cc808594SShuo Chen 88cc808594SShuo Chen return fd; 89cc808594SShuo Chen} 90cc808594SShuo Chen 91cc808594SShuo Chenuint16_t in_checksum(const void* buf, int len) 92cc808594SShuo Chen{ 93cc808594SShuo Chen assert(len % 2 == 0); 94cc808594SShuo Chen const uint16_t* data = static_cast<const uint16_t*>(buf); 95cc808594SShuo Chen int sum = 0; 96cc808594SShuo Chen for (int i = 0; i < len; i+=2) 97cc808594SShuo Chen { 98cc808594SShuo Chen sum += *data++; 99cc808594SShuo Chen } 100a4bafd74SShuo Chen while (sum >> 16) 101a4bafd74SShuo Chen sum = (sum & 0xFFFF) + (sum >> 16); 102cc808594SShuo Chen assert(sum <= 0xFFFF); 103cc808594SShuo Chen return ~sum; 104cc808594SShuo Chen} 105cc808594SShuo Chen 106cc808594SShuo Chenvoid icmp_input(int fd, const void* input, const void* payload, int len) 107cc808594SShuo Chen{ 108cc808594SShuo Chen const struct iphdr* iphdr = static_cast<const struct iphdr*>(input); 109cc808594SShuo Chen const struct icmphdr* icmphdr = static_cast<const struct icmphdr*>(payload); 110cc808594SShuo Chen // const int icmphdr_size = sizeof(*icmphdr); 111cc808594SShuo Chen const int iphdr_len = iphdr->ihl*4; 112cc808594SShuo Chen 113cc808594SShuo Chen if (icmphdr->type == ICMP_ECHO) 114cc808594SShuo Chen { 115cc808594SShuo Chen char source[INET_ADDRSTRLEN]; 116cc808594SShuo Chen char dest[INET_ADDRSTRLEN]; 117cc808594SShuo Chen inet_ntop(AF_INET, &iphdr->saddr, source, INET_ADDRSTRLEN); 118cc808594SShuo Chen inet_ntop(AF_INET, &iphdr->daddr, dest, INET_ADDRSTRLEN); 119cc808594SShuo Chen printf("%s > %s: ", source, dest); 120cc808594SShuo Chen printf("ICMP echo request, id %d, seq %d, length %d\n", 121cc808594SShuo Chen ntohs(icmphdr->un.echo.id), 122cc808594SShuo Chen ntohs(icmphdr->un.echo.sequence), 123cc808594SShuo Chen len - iphdr_len); 124cc808594SShuo Chen 125cc808594SShuo Chen union 126cc808594SShuo Chen { 127cc808594SShuo Chen unsigned char output[ETH_FRAME_LEN]; 128cc808594SShuo Chen struct 129cc808594SShuo Chen { 130cc808594SShuo Chen struct iphdr iphdr; 131cc808594SShuo Chen struct icmphdr icmphdr; 132cc808594SShuo Chen } out; 133cc808594SShuo Chen }; 134cc808594SShuo Chen 135cc808594SShuo Chen memcpy(output, input, len); 136cc808594SShuo Chen out.icmphdr.type = ICMP_ECHOREPLY; 137cc808594SShuo Chen out.icmphdr.checksum += ICMP_ECHO; // FIXME: not portable 138cc808594SShuo Chen std::swap(out.iphdr.saddr, out.iphdr.daddr); 139cc808594SShuo Chen write(fd, output, len); 140cc808594SShuo Chen } 141cc808594SShuo Chen} 142cc808594SShuo Chen 143