1 /* Copyright 2004 Renzo Davoli
2 * Reseased under the GPLv2 */
8 #include <sys/socket.h>
9 #include <sys/syscall.h>
19 #include <linux/ioctl.h>
21 #include <linux/if_tun.h>
25 #include <vdecommon.h>
27 #define TUNTAPPATH "/dev/net/tun"
28 #define VDETAPEXEC LIBEXECDIR "/vdetap"
29 #define VDEALLTAP "VDEALLTAP"
32 #define nativesym(function, name) \
35 if (native_##function == NULL) { \
36 *(void **)(&native_##function) = dlsym(RTLD_NEXT, name); \
37 if ((msg = dlerror()) != NULL) { \
38 fprintf (stderr, "%s: dlsym(%s): %s\n", PACKAGE, name, msg); \
43 static int (*native_ioctl
) (int d
, int request
, ...) = NULL
;
44 static int (*native_open
) (const char *pathname
, int flags
, ...) = NULL
;
45 static int (*native_open64
) (const char *pathname
, int flags
, ...) = NULL
;
47 int tapfd
[2] = {-1,-1};
48 static int tapcount
=0;
49 static int tuncount
=0;
51 static struct pidlist
{
54 } *plh
= NULL
, *flh
=NULL
, pidpool
[MAX
];
56 static struct pidlist
*plmalloc(void) {
65 static void plfree (struct pidlist *el) {
71 static int addpid(int pid
) {
73 if ((plp
=plmalloc ()) != NULL
) {
84 void libvdetap_init (void) __attribute((constructor
));
85 void libvdetap_init(void)
88 nativesym(ioctl
, "ioctl");
89 nativesym(open
, "open");
90 nativesym(open64
, "open64");
92 pidpool
[i
-1].next
= &(pidpool
[i
]);
96 void libvdetap_fini(void)
98 struct pidlist
*plp
=plh
;
100 kill(plp
->pid
,SIGTERM
);
105 int open(const char *path
, int flags
, ...)
111 data
= va_arg(ap
, int);
114 if (strcmp(path
,TUNTAPPATH
)==0 && tapfd
[0] == -1) {
115 if (socketpair(PF_UNIX
, SOCK_DGRAM
, 0,tapfd
) == 0)
121 return native_open(path
, flags
, data
);
124 int open64(const char *path
, int flags
, ...)
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)
140 return native_open64(path
, flags
| O_LARGEFILE
, data
);
143 static char *getvdeopt(struct ifreq
*ifr
,char *suffix
)
147 snprintf(buf
,16,"%s_%s",ifr
->ifr_name
,suffix
);
148 if ((rv
=getenv(buf
)) != NULL
)
150 snprintf(buf
,16,"VDEALLTAP_%s",suffix
);
151 if ((rv
=getenv(buf
)) != NULL
)
158 int ioctl(int fd
, int command
, ...)
160 int ioctl(int fd
, unsigned long int command
, ...)
167 int callerpid
=getpid();
169 va_start(ap
, command
);
170 data
= va_arg(ap
, char *);
173 if (fd
== tapfd
[0]) {
174 if (command
== TUNSETIFF
) {
175 struct ifreq
*ifr
= (struct ifreq
*) data
;
180 ifr
->ifr_name
[IFNAMSIZ
-1] = '\0';
181 if (ifr
->ifr_name
[0] == 0) {
182 if (ifr
->ifr_flags
& IFF_TAP
)
183 sprintf(name
,"tap%d",tapcount
++);
185 sprintf(name
,"tun%d",tuncount
++);
186 strncpy(ifr
->ifr_name
,name
,IFNAMSIZ
);
188 else if (strchr(ifr
->ifr_name
, '%') != NULL
) {
189 sprintf(name
,ifr
->ifr_name
,tapcount
++);
190 strncpy(ifr
->ifr_name
,name
,IFNAMSIZ
);
192 if ((ifr
->ifr_flags
& IFF_TAP
) && (
193 /* from env: single interface or VDEALLTAP */
194 ((vdesock
=getenv(ifr
->ifr_name
)) != NULL
) ||
195 (vdesock
=getenv(VDEALLTAP
)) != NULL
)
197 if ((pid
=fork()) < 0) {
201 } else if (pid
> 0) { /*father*/
202 if((pid
=addpid(pid
)) < 0) {
213 sprintf(num
,"%d",tapfd
[1]);
214 sprintf(scallerpid
,"%d",callerpid
);
215 return execlp(VDETAPEXEC
,"-",num
,vdesock
,ifr
->ifr_name
,
217 getvdeopt(ifr
,"port"),
218 getvdeopt(ifr
,"group"),
219 getvdeopt(ifr
,"mode"),
223 else /*roll back to the native tuntap*/
229 if ((newfd
=native_open(TUNTAPPATH
, O_RDWR
, 0)) < 0) {
236 resultioctl
=native_ioctl(fd
, command
, data
);
237 if (resultioctl
< 0) {
243 dup2(newfd
,tapfd
[0]);
251 return (native_ioctl(fd
, command
, data
));