Mercurial > hg > quicktun-tcp
comparison tunnel.c @ 0:17cb7cdbb8be draft default tip
Working prototype
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Fri, 07 Feb 2014 23:28:39 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:17cb7cdbb8be |
---|---|
1 /* Copyright 2014 Ivo Smits <Ivo@UCIS.nl>. All rights reserved. | |
2 Redistribution and use in source and binary forms, with or without modification, are | |
3 permitted provided that the following conditions are met: | |
4 | |
5 1. Redistributions of source code must retain the above copyright notice, this list of | |
6 conditions and the following disclaimer. | |
7 | |
8 2. Redistributions in binary form must reproduce the above copyright notice, this list | |
9 of conditions and the following disclaimer in the documentation and/or other materials | |
10 provided with the distribution. | |
11 | |
12 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
13 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
14 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR | |
15 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
16 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
17 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |
18 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
19 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
20 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
21 | |
22 The views and conclusions contained in the software and documentation are those of the | |
23 authors and should not be interpreted as representing official policies, either expressed | |
24 or implied, of Ivo Smits.*/ | |
25 | |
26 #include <stdio.h> | |
27 #include <stdbool.h> | |
28 #include <stdlib.h> | |
29 #include <unistd.h> | |
30 #include <sys/types.h> | |
31 #include <sys/uio.h> | |
32 #include <string.h> | |
33 #include <fcntl.h> | |
34 #include <sys/ioctl.h> | |
35 #include <net/if.h> | |
36 #ifdef linux | |
37 #include <linux/if_tun.h> | |
38 #include <linux/if_ether.h> | |
39 #else | |
40 #define ETH_FRAME_LEN 1514 | |
41 #include <net/if_tun.h> | |
42 #ifdef SOLARIS | |
43 #include <sys/stropts.h> | |
44 #include <sys/sockio.h> | |
45 #endif | |
46 #endif | |
47 #include "include.h" | |
48 | |
49 static unsigned char readbuffer[2000]; | |
50 | |
51 bool tunnel_write_data(tunnel_context* context, unsigned char* buffer, int len) { | |
52 if (context->fake_pi) { | |
53 if (len == 0) return true; | |
54 int ipver = (*buffer >> 4) & 0xf; | |
55 int pihdr = 0; | |
56 #if defined linux | |
57 if (ipver == 4) pihdr = 0x0000 | (0x0008 << 16); //little endian: flags and protocol are swapped | |
58 else if (ipver == 6) pihdr = 0x0000 | (0xdd86 << 16); | |
59 #else | |
60 if (ipver == 4) pihdr = htonl(AF_INET); | |
61 else if (ipver == 6) pihdr = htonl(AF_INET6); | |
62 #endif | |
63 struct iovec iov[2]; | |
64 iov[0].iov_base = &pihdr; | |
65 iov[0].iov_len = sizeof(pihdr); | |
66 iov[1].iov_base = buffer; | |
67 iov[1].iov_len = len; | |
68 writev(context->fd, iov, 2); | |
69 } else { | |
70 write(context->fd, buffer, len); | |
71 } | |
72 return true; | |
73 } | |
74 | |
75 bool tunnel_read(tunnel_context* context) { | |
76 int len = read(context->fd, readbuffer, sizeof(readbuffer)); | |
77 if (len < 0) return errorexitp("read failure on tap device"); | |
78 if (!context->connection) return true; | |
79 if (context->fake_pi) { | |
80 if (len < 4) return errorexit("short packet received from tap device"); | |
81 connection_write_data(context->connection, readbuffer + 4, len - 4); | |
82 } else { | |
83 connection_write_data(context->connection, readbuffer, len); | |
84 } | |
85 return true; | |
86 } | |
87 | |
88 bool tunnel_init(tunnel_context* context) { | |
89 memset(context, 0, sizeof(tunnel_context)); | |
90 char* envval; | |
91 fprintf(stderr, "Initializing tun/tap device...\n"); | |
92 int ttfd; //Tap device file descriptor | |
93 int tunmode = 0; | |
94 if ((envval = getconf("TUN_MODE"))) tunmode = atoi(envval); | |
95 #if defined(__linux__) | |
96 struct ifreq ifr; //required for tun/tap setup | |
97 memset(&ifr, 0, sizeof(ifr)); | |
98 if ((ttfd = open("/dev/net/tun", O_RDWR)) < 0) return errorexitp("Could not open tun/tap device file"); | |
99 if ((envval = getconf("INTERFACE"))) strcpy(ifr.ifr_name, envval); | |
100 ifr.ifr_flags = tunmode ? IFF_TUN : IFF_TAP; | |
101 ifr.ifr_flags |= IFF_NO_PI; | |
102 if (ioctl(ttfd, TUNSETIFF, (void *)&ifr) < 0) return errorexitp("TUNSETIFF ioctl failed"); | |
103 #elif defined SOLARIS | |
104 int ip_fd = -1, if_fd = -1, ppa = 0; | |
105 if ((ttfd = open("/dev/tun", O_RDWR)) < 0) return errorexitp("Could not open tun device file"); | |
106 if ((ip_fd = open("/dev/ip", O_RDWR, 0)) < 0) return errorexitp("Could not open /dev/ip"); | |
107 if ((envval = getconf("INTERFACE"))) { | |
108 while (*envval && !isdigit((int)*envval)) envval++; | |
109 ppa = atoi(envval); | |
110 } | |
111 if ((ppa = ioctl(ttfd, TUNNEWPPA, ppa)) < 0) return errorexitp("Could not assign new PPA"); | |
112 if ((if_fd = open("/dev/tun", O_RDWR, 0)) < 0) return errorexitp("Could not open tun device file again"); | |
113 if (ioctl(if_fd, I_PUSH, "ip") < 0) return errorexitp("Could not push IP module"); | |
114 if (ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0) return errorexitp("Could not set PPA"); | |
115 if (ioctl(ip_fd, I_LINK, if_fd) < 0) return errorexitp("Could not link TUN device to IP"); | |
116 #else | |
117 if (!(envval = getconf("INTERFACE"))) envval = "/dev/tun0"; | |
118 if ((ttfd = open(envval, O_RDWR)) < 0) return errorexitp("Could not open tun device file"); | |
119 if (tunmode) { | |
120 int i = IFF_POINTOPOINT | IFF_MULTICAST; | |
121 ioctl(ttfd, TUNSIFMODE, &i); | |
122 #if defined(__OpenBSD__) | |
123 context->fake_pi = true; | |
124 #else | |
125 i = 1; | |
126 ioctl(ttfd, TUNSIFHEAD, &i); | |
127 #endif | |
128 } | |
129 #endif | |
130 if ((envval = getconf("TUN_UP_SCRIPT"))) system(envval); | |
131 context->fd = ttfd; | |
132 return true; | |
133 } | |
134 |