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