faketcp.cc revision a4bafd74
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 } 51a4bafd74SShuo Chen while (sum >> 16) 52a4bafd74SShuo 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