1 /*
2 VTun - Virtual Tunnel over TCP/IP network.
3
4 Copyright (C) 1998-2016 Maxim Krasnyansky <max_mk@yahoo.com>
5
6 VTun has been derived from VPPP package by Maxim Krasnyansky.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 */
18
19 /*
20 * $Id: tun_dev.c,v 1.4.2.2 2016/10/01 21:46:01 mtbishop Exp $
21 */
22
23 #include "config.h"
24
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <syslog.h>
31 #include <errno.h>
32
33 #include <sys/ioctl.h>
34 #include <sys/socket.h>
35 #include <linux/if.h>
36
37 #include "vtun.h"
38 #include "lib.h"
39
40 /*
41 * Allocate TUN device, returns opened fd.
42 * Stores dev name in the first arg(must be large enough).
43 */
tun_open_common0(char * dev,int istun)44 static int tun_open_common0(char *dev, int istun)
45 {
46 char tunname[14];
47 int i, fd, err;
48
49 if( *dev ) {
50 sprintf(tunname, "/dev/%s", dev);
51 return open(tunname, O_RDWR);
52 }
53
54 sprintf(tunname, "/dev/%s", istun ? "tun" : "tap");
55 err = 0;
56 for(i=0; i < 255; i++){
57 sprintf(tunname + 8, "%d", i);
58 /* Open device */
59 if( (fd=open(tunname, O_RDWR)) > 0 ) {
60 strcpy(dev, tunname + 5);
61 return fd;
62 }
63 else if (errno != ENOENT)
64 err = errno;
65 else if (i) /* don't try all 256 devices */
66 break;
67 }
68 if (err)
69 errno = err;
70 return -1;
71 }
72
73 #ifdef HAVE_LINUX_IF_TUN_H /* New driver support */
74 #include <linux/if_tun.h>
75
76 #ifndef OTUNSETNOCSUM
77 /* pre 2.4.6 compatibility */
78 #define OTUNSETNOCSUM (('T'<< 8) | 200)
79 #define OTUNSETDEBUG (('T'<< 8) | 201)
80 #define OTUNSETIFF (('T'<< 8) | 202)
81 #define OTUNSETPERSIST (('T'<< 8) | 203)
82 #define OTUNSETOWNER (('T'<< 8) | 204)
83 #endif
84
tun_open_common(char * dev,int istun)85 static int tun_open_common(char *dev, int istun)
86 {
87 struct ifreq ifr;
88 int fd;
89
90 if ((fd = open("/dev/net/tun", O_RDWR)) < 0)
91 return tun_open_common0(dev, istun);
92
93 memset(&ifr, 0, sizeof(ifr));
94 ifr.ifr_flags = (istun ? IFF_TUN : IFF_TAP) | IFF_NO_PI;
95 if (*dev)
96 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
97
98 if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
99 if (errno == EBADFD) {
100 /* Try old ioctl */
101 if (ioctl(fd, OTUNSETIFF, (void *) &ifr) < 0)
102 goto failed;
103 } else
104 goto failed;
105 }
106
107 strcpy(dev, ifr.ifr_name);
108 return fd;
109
110 failed:
111 close(fd);
112 return -1;
113 }
114
115 #else
116
117 # define tun_open_common(dev, type) tun_open_common0(dev, type)
118
119 #endif /* New driver support */
120
tun_open(char * dev)121 int tun_open(char *dev) { return tun_open_common(dev, 1); }
tap_open(char * dev)122 int tap_open(char *dev) { return tun_open_common(dev, 0); }
123
tun_close(int fd,char * dev)124 int tun_close(int fd, char *dev) { return close(fd); }
tap_close(int fd,char * dev)125 int tap_close(int fd, char *dev) { return close(fd); }
126
127 /* Read/write frames from TUN device */
tun_write(int fd,char * buf,int len)128 int tun_write(int fd, char *buf, int len) { return write(fd, buf, len); }
tap_write(int fd,char * buf,int len)129 int tap_write(int fd, char *buf, int len) { return write(fd, buf, len); }
130
tun_read(int fd,char * buf,int len)131 int tun_read(int fd, char *buf, int len) { return read(fd, buf, len); }
tap_read(int fd,char * buf,int len)132 int tap_read(int fd, char *buf, int len) { return read(fd, buf, len); }
133