]> git.sesse.net Git - greproxy/blob - tunprotocol.cpp
Add a simple Makefile and .gitignore.
[greproxy] / tunprotocol.cpp
1 #include <string.h>
2 #include <fcntl.h>
3 #include <unistd.h>
4 #include <sys/ioctl.h>
5 #include <netinet/in.h>
6 #include <arpa/inet.h>
7 #include <linux/if.h>
8 #include <linux/if_tun.h>
9
10 #include "tunprotocol.h"
11
12 using namespace std;
13
14 namespace {
15
16 int tun_open(const char *name) {
17         struct ifreq ifr;
18
19         int fd = open("/dev/net/tun", O_RDWR);
20         if (fd == -1) {
21                 perror("/dev/net/tun");
22                 exit(1);
23         }
24
25         memset(&ifr, 0, sizeof(ifr));
26         ifr.ifr_flags = IFF_TUN;
27         strncpy(ifr.ifr_name, name, IFNAMSIZ);
28
29         int err = ioctl(fd, TUNSETIFF, &ifr);
30         if (err == -1) {
31                 perror("ioctl(TUNSETIFF)");
32                 exit(-1);
33         }
34
35         return fd;
36 }
37
38 }  // namespace
39
40 TUNProtocol::TUNProtocol(const char *devname)
41         : tunfd(tun_open(devname)) {
42 }
43
44 void TUNProtocol::send_packet(uint16_t proto, const string &data, int incoming_seq)
45 {
46         char buf[4096];
47
48         char *ptr = buf;
49         uint16_t flags = 0;
50         memcpy(ptr, &flags, sizeof(flags));
51         ptr += sizeof(flags);
52
53         proto = htons(proto);
54         memcpy(ptr, &proto, sizeof(proto));
55         ptr += sizeof(proto);
56
57         memcpy(ptr, data.data(), data.size());
58
59         int len = sizeof(flags) + sizeof(proto) + data.size();
60         if (write(tunfd, buf, len) != len) {
61                 perror("write");
62                 return;
63         }
64 }
65
66 int TUNProtocol::fd() const
67 {
68         return tunfd;
69 }
70
71 void TUNProtocol::read_packet(Protocol *sender)
72 {
73         char buf[4096];
74         int ret = read(tunfd, buf, sizeof(buf));
75         if (ret == -1) {
76                 perror("read");
77                 exit(1);
78         }
79         if (ret == 0) {
80                 fprintf(stderr, "tunfd EOF\n");
81                 exit(1);
82         }
83         
84         char *ptr = buf;
85         uint16_t flags = *(uint16_t *)ptr;
86         ptr += 2;
87         uint16_t proto = ntohs(*(uint16_t *)ptr);
88         ptr += 2;
89         //fprintf(stderr, "tun packet: flags=%x proto=%x len=%d\n",
90         //      flags, proto, ret - 4);
91         sender->send_packet(proto, string(ptr, buf + ret), -1);
92 }
93