~ubuntu-branches/ubuntu/lucid/vde2/lucid-proposed

« back to all changes in this revision

Viewing changes to vdetaplib/libvdetap.c

  • Committer: Bazaar Package Importer
  • Author(s): Filippo Giunchedi
  • Date: 2008-06-17 15:36:32 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20080617153632-5318x7iv0zwmu3zu
Tags: 2.2.1-1
* New upstream release
  - fix vlan commands on amd64 (Closes: #484295)
  - fix mac addresses switch between ports (Closes: #469098)
* Suggest: qemu and kvm as requested in #461514
* Expand and spell-check README.Debian, add manual method example
  (Closes: #466363)
* Do not assume MAKEDEV presence in postinst
* Remove /usr/bin/daemon usage from ifupdown scripts (and Recommends)
* Add manpage for vde_tunctl
* Upgrade to S-V 3.8.0 (add Homepage field) 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright 2004 Renzo Davoli
2
 
 * Reseased under the GPLv2 */
3
 
 
4
 
#define _GNU_SOURCE
5
 
#include <config.h>
6
 
#include <dlfcn.h>
7
 
#include <stdio.h>
8
 
#include <sys/types.h>
9
 
#include <sys/socket.h>
10
 
#include <sys/syscall.h>
11
 
#include <sys/stat.h>
12
 
#include <stdarg.h>
13
 
#include <string.h>
14
 
#include <unistd.h>
15
 
#include <stdlib.h>
16
 
#include <fcntl.h>
17
 
#include <errno.h>
18
 
#include <stdio.h>
19
 
#include <signal.h>
20
 
#include <linux/ioctl.h>
21
 
#include <linux/if.h>
22
 
#include <linux/if_tun.h>
23
 
 
24
 
#define TUNTAPPATH "/dev/net/tun"
25
 
#define VDETAPEXEC LIBEXECDIR "/vdetap"
26
 
#define VDEALLTAP "VDEALLTAP"
27
 
#define MAX 10
28
 
 
29
 
#define nativesym(function, name) \
30
 
    { \
31
 
        const char *msg; \
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); \
36
 
            } \
37
 
        } \
38
 
    }
39
 
 
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;
43
 
 
44
 
int tapfd[2] = {-1,-1};
45
 
static int tapcount=0;
46
 
static int tuncount=0;
47
 
 
48
 
static struct pidlist {
49
 
        pid_t pid;
50
 
        struct pidlist *next;
51
 
} *plh = NULL, *flh=NULL, pidpool[MAX];
52
 
 
53
 
static struct pidlist *plmalloc(void) {
54
 
        struct pidlist *rv;
55
 
        rv=flh;
56
 
        if (rv != NULL) 
57
 
                flh=flh->next;
58
 
        return rv;
59
 
}
60
 
 
61
 
/* not used? 
62
 
static void plfree (struct pidlist *el) {
63
 
        el->next=flh;
64
 
        flh=el;
65
 
}
66
 
*/
67
 
 
68
 
static int addpid(int pid) {
69
 
        struct pidlist *plp;
70
 
        if ((plp=plmalloc ()) != NULL) {
71
 
                plp->next=plh;
72
 
                plh=plp;
73
 
                plp->pid=pid;
74
 
                return pid;
75
 
        } else {
76
 
                kill(pid,SIGTERM);
77
 
                return -1;
78
 
        }
79
 
}
80
 
 
81
 
void libvdetap_init (void) __attribute((constructor));
82
 
void libvdetap_init(void)
83
 
{
84
 
        register int i;
85
 
        nativesym(ioctl, "ioctl");
86
 
        nativesym(open, "open");
87
 
        nativesym(open64, "open64");
88
 
        for (i=1;i<MAX;i++) 
89
 
                pidpool[i-1].next= &(pidpool[i]);
90
 
        flh=pidpool;
91
 
}
92
 
 
93
 
void libvdetap_fini(void)
94
 
{
95
 
        struct pidlist *plp=plh;
96
 
        while (plp != NULL) {
97
 
                kill(plp->pid,SIGTERM);
98
 
                plp = plp->next;
99
 
        }
100
 
}
101
 
 
102
 
int open(const char *path, int flags, ...)
103
 
{
104
 
        /* static char buf[PATH_MAX]; */
105
 
        va_list ap;
106
 
        int data;
107
 
 
108
 
        va_start(ap, flags);
109
 
        data = va_arg(ap, int);
110
 
        va_end(ap);
111
 
 
112
 
        if (strcmp(path,TUNTAPPATH)==0 && tapfd[0] == -1) {
113
 
                if (socketpair(PF_UNIX, SOCK_DGRAM, 0,tapfd) == 0) {
114
 
                        return tapfd[0];
115
 
                }
116
 
                else
117
 
                        return -1;
118
 
 
119
 
        } else
120
 
                return native_open(path, flags, data);
121
 
}
122
 
 
123
 
int open64(const char *path, int flags, ...)
124
 
{
125
 
        /* static char buf[PATH_MAX]; */
126
 
        va_list ap;
127
 
        int data;
128
 
 
129
 
        va_start(ap, flags);
130
 
        data = va_arg(ap, int);
131
 
        va_end(ap);
132
 
 
133
 
        if (strcmp(path,TUNTAPPATH)==0 && tapfd[0] == -1) {
134
 
                if (socketpair(PF_UNIX, SOCK_DGRAM, 0,tapfd) == 0) {
135
 
                        return tapfd[0];
136
 
                }
137
 
                else
138
 
                        return -1;
139
 
 
140
 
        } else
141
 
                return native_open64(path, flags | O_LARGEFILE, data);
142
 
}
143
 
 
144
 
int ioctl(int fd, unsigned long int command, ...)
145
 
{
146
 
        va_list ap;
147
 
        char *data;
148
 
        char *vdesock;
149
 
        int pid;
150
 
 
151
 
        va_start(ap, command);
152
 
        data = va_arg(ap, char *);
153
 
        va_end(ap);
154
 
 
155
 
        if (fd == tapfd[0]) {
156
 
                if (command == TUNSETIFF) {
157
 
                        struct ifreq *ifr = (struct ifreq *) data;
158
 
                        char num[5];
159
 
                        char name[10];
160
 
 
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++);
165
 
                                else
166
 
                                        sprintf(name,"tun%d",tuncount++);
167
 
                                strncpy(ifr->ifr_name,name,IFNAMSIZ);
168
 
                        }
169
 
                        else if (strchr(ifr->ifr_name, '%') != NULL) {
170
 
                                sprintf(name,ifr->ifr_name,tapcount++);
171
 
                                strncpy(ifr->ifr_name,name,IFNAMSIZ);
172
 
                        }
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)
177
 
                                ){
178
 
                                if ((pid=fork()) < 0) { 
179
 
                                        close(tapfd[1]);
180
 
                                        errno=EINVAL;
181
 
                                        return -1;
182
 
                                } else if (pid > 0) { /*father*/
183
 
                                        if((pid=addpid(pid)) < 0) {
184
 
                                                close(tapfd[0]);
185
 
                                                close(tapfd[1]);
186
 
                                                return -1;
187
 
                                        } else {
188
 
                                                close(tapfd[1]);
189
 
                                                return 0;
190
 
                                        }
191
 
                                } else { /*son*/
192
 
                                        plh=NULL;
193
 
                                        close(tapfd[0]);
194
 
                                        sprintf(num,"%d",tapfd[1]);
195
 
                                        return execlp(VDETAPEXEC,"-",num,vdesock,name,(char *) 0);
196
 
                                }
197
 
                        }
198
 
                        else /*roll back to the native tuntap*/
199
 
                        {
200
 
                                int newfd;
201
 
                                int saverrno;
202
 
                                int resultioctl;
203
 
                                close(tapfd[1]);
204
 
                                if ((newfd=native_open(TUNTAPPATH,  O_RDWR, 0)) < 0) {
205
 
                                        saverrno=errno;
206
 
                                        close(tapfd[0]);
207
 
                                        errno=saverrno;
208
 
                                        return -1;
209
 
                                } else
210
 
                                {
211
 
                                        resultioctl=native_ioctl(fd, command, data);
212
 
                                        if (resultioctl < 0) {
213
 
                                                saverrno=errno;
214
 
                                                close(tapfd[0]);
215
 
                                                errno=saverrno;
216
 
                                                return -1;
217
 
                                        } else {
218
 
                                                dup2(newfd,tapfd[0]);
219
 
                                                return resultioctl;
220
 
                                        }
221
 
                                }
222
 
                        }
223
 
                } else  
224
 
                        return 0;
225
 
        } else 
226
 
                return (native_ioctl(fd, command, data));
227
 
}
228