1 /*
2 VTun - Virtual Tunnel over TCP/IP network.
3
4 Copyright (C) 1998-2000 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 * tun_dev.c,v 1.2.2.2.2.1 2006/11/16 04:05:18 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 <ctype.h>
31 #include <stdarg.h>
32 #include <sys/time.h>
33 #include <sys/wait.h>
34 #include <syslog.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/sockio.h>
38 #include <sys/ioctl.h>
39 #include <errno.h>
40 #include <signal.h>
41 #include <stropts.h>
42 #include <net/if.h>
43 #include <net/if_tun.h>
44
45 #ifdef HAVE_NETINET_IN_H
46 #include <netinet/in.h>
47 #endif
48
49 #ifdef HAVE_NETINET_IN_SYSTM_H
50 #include <netinet/in_systm.h>
51 #endif
52
53 #ifdef HAVE_NETINET_IP_H
54 #include <netinet/ip.h>
55 #endif
56
57 #ifdef HAVE_NETINET_TCP_H
58 #include <netinet/tcp.h>
59 #endif
60
61 /* #include "vtun.h"
62 #include "lib.h" */
63
64 static int ip_fd = -1;
65
66 /*
67 * Allocate TUN device, returns opened fd.
68 * Stores dev name in the first arg(must be large enough).
69 */
tun_open(char * dev)70 int tun_open(char *dev)
71 {
72 int tun_fd, if_fd, muxid, ppa = -1;
73 struct ifreq ifr;
74 char *ptr;
75
76 if( *dev ){
77 ptr = dev;
78 while( *ptr && !isdigit((int)*ptr) ) ptr++;
79 ppa = atoi(ptr);
80 }
81
82 if( (ip_fd = open("/dev/udp", O_RDWR, 0)) < 0){
83 syslog(LOG_ERR, "Can't open /dev/ip");
84 return -1;
85 }
86
87 if( (tun_fd = open("/dev/tun", O_RDWR, 0)) < 0){
88 syslog(LOG_ERR, "Can't open /dev/tun");
89 return -1;
90 }
91
92 /* Assign a new PPA and get its unit number. */
93 if( (ppa = ioctl(tun_fd, TUNNEWPPA, ppa)) < 0){
94 syslog(LOG_ERR, "Can't assign new interface");
95 return -1;
96 }
97
98 if( (if_fd = open("/dev/tun", O_RDWR, 0)) < 0){
99 syslog(LOG_ERR, "Can't open /dev/tun (2)");
100 return -1;
101 }
102 if(ioctl(if_fd, I_PUSH, "ip") < 0){
103 syslog(LOG_ERR, "Can't push IP module");
104 return -1;
105 }
106
107 /* Assign ppa according to the unit number returned by tun device */
108 if(ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0){
109 syslog(LOG_ERR, "Can't set PPA %d", ppa);
110 return -1;
111 }
112 if( (muxid = ioctl(ip_fd, I_PLINK, if_fd)) < 0){
113 syslog(LOG_ERR, "Can't link TUN device to IP");
114 return -1;
115 }
116 close(if_fd);
117
118 sprintf(dev, "tun%d", ppa);
119
120 memset(&ifr, 0, sizeof(ifr));
121 strcpy(ifr.ifr_name, dev);
122 ifr.ifr_ip_muxid = muxid;
123
124 if( ioctl(ip_fd, SIOCSIFMUXID, &ifr) < 0 ){
125 ioctl(ip_fd, I_PUNLINK, muxid);
126 syslog(LOG_ERR, "Can't set multiplexor id");
127 return -1;
128 }
129
130 return tun_fd;
131 }
132
133 /*
134 * Close TUN device.
135 */
tun_close(int fd,char * dev)136 int tun_close(int fd, char *dev)
137 {
138 struct ifreq ifr;
139
140 memset(&ifr, 0, sizeof(ifr));
141 strcpy(ifr.ifr_name, dev);
142 if( ioctl(ip_fd, SIOCGIFFLAGS, &ifr) < 0 ){
143 syslog(LOG_ERR, "Can't get iface flags");
144 return 0;
145 }
146
147 if( ioctl(ip_fd, SIOCGIFMUXID, &ifr) < 0 ){
148 syslog(LOG_ERR, "Can't get multiplexor id");
149 return 0;
150 }
151
152 if( ioctl(ip_fd, I_PUNLINK, ifr.ifr_ip_muxid) < 0 ){
153 syslog(LOG_ERR, "Can't unlink interface");
154 return 0;
155 }
156
157 close(ip_fd); close(fd);
158 return 0;
159 }
160
tun_write(int fd,char * buf,int len)161 int tun_write(int fd, char *buf, int len)
162 {
163 struct strbuf sbuf;
164 sbuf.len = len;
165 sbuf.buf = buf;
166 return putmsg(fd, NULL, &sbuf, 0) >=0 ? sbuf.len : -1;
167 }
168
tun_read(int fd,char * buf,int len)169 int tun_read(int fd, char *buf, int len)
170 {
171 struct strbuf sbuf;
172 int f = 0;
173
174 sbuf.maxlen = len;
175 sbuf.buf = buf;
176 return getmsg(fd, NULL, &sbuf, &f) >=0 ? sbuf.len : -1;
177 }
178
tun_last_error()179 const char *tun_last_error()
180 {
181 return strerror(errno);
182 }
183