2 * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 #include <sys/types.h>
27 #include <arpa/inet.h>
28 #include <netinet/in.h>
32 #define TUN_MAX_TRY 50
38 #include <sys/ioctl.h>
40 #include <linux/if_tun.h>
43 open_tun(const char *tun_device)
48 char *tunnel = "/dev/net/tun";
50 if ((tun_fd = open(tunnel, O_RDWR)) < 0) {
51 warn("open_tun: %s: %s", tunnel, strerror(errno));
55 memset(&ifreq, 0, sizeof(ifreq));
57 ifreq.ifr_flags = IFF_TUN;
59 if (tun_device != NULL) {
60 strncpy(ifreq.ifr_name, tun_device, IFNAMSIZ);
61 ifreq.ifr_name[IFNAMSIZ-1] = '\0';
62 strncpy(if_name, tun_device, sizeof(if_name));
63 if_name[sizeof(if_name)-1] = '\0';
65 if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) {
66 printf("Opened %s\n", ifreq.ifr_name);
71 warn("open_tun: ioctl[TUNSETIFF]: %s", strerror(errno));
75 for (i = 0; i < TUN_MAX_TRY; i++) {
76 snprintf(ifreq.ifr_name, IFNAMSIZ, "dns%d", i);
78 if (ioctl(tun_fd, TUNSETIFF, (void *) &ifreq) != -1) {
79 printf("Opened %s\n", ifreq.ifr_name);
80 snprintf(if_name, sizeof(if_name), "dns%d", i);
85 warn("open_tun: ioctl[TUNSETIFF]: %s", strerror(errno));
90 warn("open_tun: Couldn't set interface name");
98 open_tun(const char *tun_device)
104 if (tun_device != NULL) {
105 snprintf(tun_name, sizeof(tun_name), "/dev/%s", tun_device);
106 strncpy(if_name, tun_device, sizeof(if_name));
107 if_name[sizeof(if_name)-1] = '\0';
109 if ((tun_fd = open(tun_name, O_RDWR)) < 0) {
110 warn("open_tun: %s: %s", tun_name, strerror(errno));
114 printf("Opened %s\n", tun_name);
117 for (i = 0; i < TUN_MAX_TRY; i++) {
118 snprintf(tun_name, sizeof(tun_name), "/dev/tun%d", i);
120 if ((tun_fd = open(tun_name, O_RDWR)) >= 0) {
121 printf("Opened %s\n", tun_name);
122 snprintf(if_name, sizeof(if_name), "tun%d", i);
130 warn("open_tun: Failed to open tunneling device");
139 close_tun(int tun_fd)
146 write_tun(int tun_fd, char *data, size_t len)
148 #if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD)
151 #else /* !FREEBSD/DARWIN */
165 if (write(tun_fd, data, len) != len) {
173 read_tun(int tun_fd, char *buf, size_t len)
175 #if defined (FREEBSD) || defined (DARWIN) || defined(NETBSD)
176 /* FreeBSD/Darwin/NetBSD has no header */
177 return read(tun_fd, buf + 4, len - 4) + 4;
179 return read(tun_fd, buf, len);
180 #endif /* !FREEBSD */
184 tun_setip(const char *ip, int netbits)
195 for (i = 0; i < netbits; i++) {
196 netmask = (netmask << 1) | 1;
198 netmask <<= (32 - netbits);
199 net.s_addr = htonl(netmask);
201 if (inet_addr(ip) != INADDR_NONE) {
202 snprintf(cmdline, sizeof(cmdline),
203 "/sbin/ifconfig %s %s %s netmask %s",
209 printf("Setting IP of %s to %s\n", if_name, ip);
215 snprintf(cmdline, sizeof(cmdline),
216 "/sbin/route add %s/%d %s",
219 printf("Adding route %s/%d to %s\n", ip, netbits, ip);
221 return system(cmdline);
223 printf("Invalid IP: %s!\n", ip);
230 tun_setmtu(const unsigned mtu)
234 if (mtu > 200 && mtu < 1500) {
235 snprintf(cmdline, sizeof(cmdline),
236 "/sbin/ifconfig %s mtu %u",
240 printf("Setting MTU of %s to %u\n", if_name, mtu);
241 return system(cmdline);
243 warn("MTU out of range: %u\n", mtu);