1
/* Copyright 2004 Renzo Davoli
2
* Reseased under the GPLv2 */
9
#include <sys/socket.h>
10
#include <sys/syscall.h>
20
#include <linux/ioctl.h>
22
#include <linux/if_tun.h>
24
#define TUNTAPPATH "/dev/net/tun"
25
#define VDETAPEXEC LIBEXECDIR "/vdetap"
26
#define VDEALLTAP "VDEALLTAP"
29
#define nativesym(function, name) \
32
if (native_##function == NULL) { \
33
*(void **)(&native_##function) = dlsym(RTLD_NEXT, name); \
34
if ((msg = dlerror()) != NULL) { \
35
fprintf (stderr, "%s: dlsym(%s): %s\n", PACKAGE, name, msg); \
40
static int (*native_ioctl) (int d, int request, ...) = NULL;
41
static int (*native_open) (const char *pathname, int flags, ...) = NULL;
42
static int (*native_open64) (const char *pathname, int flags, ...) = NULL;
44
int tapfd[2] = {-1,-1};
45
static int tapcount=0;
46
static int tuncount=0;
48
static struct pidlist {
51
} *plh = NULL, *flh=NULL, pidpool[MAX];
53
static struct pidlist *plmalloc(void) {
62
static void plfree (struct pidlist *el) {
68
static int addpid(int pid) {
70
if ((plp=plmalloc ()) != NULL) {
81
void libvdetap_init (void) __attribute((constructor));
82
void libvdetap_init(void)
85
nativesym(ioctl, "ioctl");
86
nativesym(open, "open");
87
nativesym(open64, "open64");
89
pidpool[i-1].next= &(pidpool[i]);
93
void libvdetap_fini(void)
95
struct pidlist *plp=plh;
97
kill(plp->pid,SIGTERM);
102
int open(const char *path, int flags, ...)
104
/* static char buf[PATH_MAX]; */
109
data = va_arg(ap, int);
112
if (strcmp(path,TUNTAPPATH)==0 && tapfd[0] == -1) {
113
if (socketpair(PF_UNIX, SOCK_DGRAM, 0,tapfd) == 0) {
120
return native_open(path, flags, data);
123
int open64(const char *path, int flags, ...)
125
/* static char buf[PATH_MAX]; */
130
data = va_arg(ap, int);
133
if (strcmp(path,TUNTAPPATH)==0 && tapfd[0] == -1) {
134
if (socketpair(PF_UNIX, SOCK_DGRAM, 0,tapfd) == 0) {
141
return native_open64(path, flags | O_LARGEFILE, data);
144
int ioctl(int fd, unsigned long int command, ...)
151
va_start(ap, command);
152
data = va_arg(ap, char *);
155
if (fd == tapfd[0]) {
156
if (command == TUNSETIFF) {
157
struct ifreq *ifr = (struct ifreq *) data;
161
ifr->ifr_name[IFNAMSIZ-1] = '\0';
162
if (ifr->ifr_name[0] == 0) {
163
if (ifr->ifr_flags & IFF_TAP)
164
sprintf(name,"tap%d",tapcount++);
166
sprintf(name,"tun%d",tuncount++);
167
strncpy(ifr->ifr_name,name,IFNAMSIZ);
169
else if (strchr(ifr->ifr_name, '%') != NULL) {
170
sprintf(name,ifr->ifr_name,tapcount++);
171
strncpy(ifr->ifr_name,name,IFNAMSIZ);
173
if ((ifr->ifr_flags & IFF_TAP) && (
174
/* from env: single interface or VDEALLTAP */
175
((vdesock=getenv(ifr->ifr_name)) != NULL) ||
176
(vdesock=getenv(VDEALLTAP)) != NULL)
178
if ((pid=fork()) < 0) {
182
} else if (pid > 0) { /*father*/
183
if((pid=addpid(pid)) < 0) {
194
sprintf(num,"%d",tapfd[1]);
195
return execlp(VDETAPEXEC,"-",num,vdesock,name,(char *) 0);
198
else /*roll back to the native tuntap*/
204
if ((newfd=native_open(TUNTAPPATH, O_RDWR, 0)) < 0) {
211
resultioctl=native_ioctl(fd, command, data);
212
if (resultioctl < 0) {
218
dup2(newfd,tapfd[0]);
226
return (native_ioctl(fd, command, data));