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