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) {
61 static void plfree (struct pidlist
*el
) {
66 static int addpid(int pid
) {
68 if ((plp
=plmalloc ()) != NULL
) {
79 void libvdetap_init (void) __attribute((constructor
));
80 void libvdetap_init(void)
83 nativesym(ioctl
, "ioctl");
84 nativesym(open
, "open");
85 nativesym(open64
, "open64");
87 pidpool
[i
-1].next
= &(pidpool
[i
]);
91 void libvdetap_fini(void)
93 struct pidlist
*plp
=plh
;
95 kill(plp
->pid
,SIGTERM
);
100 int open(const char *path
, int flags
, ...)
102 static char buf
[PATH_MAX
];
107 data
= va_arg(ap
, mode_t
);
110 if (strcmp(path
,TUNTAPPATH
)==0 && tapfd
[0] == -1) {
111 if (socketpair(PF_UNIX
, SOCK_DGRAM
, 0,tapfd
) == 0) {
118 return native_open(path
, flags
, data
);
121 int open64(const char *path
, int flags
, ...)
123 static char buf
[PATH_MAX
];
128 data
= va_arg(ap
, mode_t
);
131 if (strcmp(path
,TUNTAPPATH
)==0 && tapfd
[0] == -1) {
132 if (socketpair(PF_UNIX
, SOCK_DGRAM
, 0,tapfd
) == 0) {
139 return native_open64(path
, flags
| O_LARGEFILE
, data
);
142 int ioctl(int fd
, unsigned long int command
, ...)
149 va_start(ap
, command
);
150 data
= va_arg(ap
, char *);
153 if (fd
== tapfd
[0]) {
154 if (command
== TUNSETIFF
) {
155 struct ifreq
*ifr
= (struct ifreq
*) data
;
159 ifr
->ifr_name
[IFNAMSIZ
-1] = '\0';
160 if (ifr
->ifr_name
[0] == 0) {
161 if (ifr
->ifr_flags
& IFF_TAP
)
162 sprintf(name
,"tap%d",tapcount
++);
164 sprintf(name
,"tun%d",tuncount
++);
165 strncpy(ifr
->ifr_name
,name
,IFNAMSIZ
);
167 else if (strchr(ifr
->ifr_name
, '%') != NULL
) {
168 sprintf(name
,ifr
->ifr_name
,tapcount
++);
169 strncpy(ifr
->ifr_name
,name
,IFNAMSIZ
);
171 if (ifr
->ifr_flags
& IFF_TAP
&&
172 ((vdesock
=getenv(ifr
->ifr_name
)) != NULL
)
173 ||(vdesock
=getenv(VDEALLTAP
)) != NULL
){
174 if ((pid
=fork()) < 0) {
178 } else if (pid
> 0) { /*father*/
179 if(pid
=addpid(pid
) < 0) {
190 sprintf(num
,"%d",tapfd
[1]);
191 execlp(VDETAPEXEC
,"-",num
,vdesock
,name
,(char *) 0);
194 else /*roll back to the native tuntap*/
200 if ((newfd
=native_open(TUNTAPPATH
, O_RDWR
, 0)) < 0) {
207 resultioctl
=native_ioctl(fd
, command
, data
);
208 if (resultioctl
< 0) {
214 dup2(newfd
,tapfd
[0]);
222 return (native_ioctl(fd
, command
, data
));