2 * Copyright (C) 2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 * Copyright (C) 2002 Jeff Dike
6 * Based on the "tunctl" utility from Jeff Dike.
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 #include <sys/types.h>
24 #include <sys/ioctl.h>
25 #include <linux/if_tun.h>
31 typedef struct private_iface_t private_iface_t
;
33 struct private_iface_t
{
34 /** public interface */
36 /** device name in guest (eth0) */
38 /** device name at host (tap0) */
40 /** bridge this interface is attached to */
42 /** mconsole for guest */
47 * bring an interface up or down
49 bool iface_control(char *name
, bool up
)
55 memset(&ifr
, 0, sizeof(struct ifreq
));
56 strncpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
58 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
63 if (ioctl(s
, SIOCGIFFLAGS
, &ifr
) == 0)
67 ifr
.ifr_flags
|= IFF_UP
;
71 ifr
.ifr_flags
&= ~IFF_UP
;
73 if (ioctl(s
, SIOCSIFFLAGS
, &ifr
) == 0)
83 * Implementation of iface_t.get_guestif.
85 static char* get_guestif(private_iface_t
*this)
91 * Implementation of iface_t.get_hostif.
93 static char* get_hostif(private_iface_t
*this)
99 * Implementation of iface_t.set_bridge.
101 static void set_bridge(private_iface_t
*this, bridge_t
*bridge
)
103 this->bridge
= bridge
;
107 * destroy the tap device
109 static bool destroy_tap(private_iface_t
*this)
114 if (!iface_control(this->hostif
, FALSE
))
116 DBG1("bringing iface down failed: %m");
118 memset(&ifr
, 0, sizeof(ifr
));
119 ifr
.ifr_flags
= IFF_TAP
| IFF_NO_PI
;
120 strncpy(ifr
.ifr_name
, this->hostif
, sizeof(ifr
.ifr_name
) - 1);
122 tap
= open(TAP_DEVICE
, O_RDWR
);
125 DBG1("unable to open tap device %s: %m", TAP_DEVICE
);
128 if (ioctl(tap
, TUNSETIFF
, &ifr
) < 0 ||
129 ioctl(tap
, TUNSETPERSIST
, 0) < 0)
131 DBG1("removing %s failed: %m", this->hostif
);
140 * create the tap device
142 static char* create_tap(private_iface_t
*this, char *guest
)
147 memset(&ifr
, 0, sizeof(ifr
));
148 ifr
.ifr_flags
= IFF_TAP
| IFF_NO_PI
;
149 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s-%s", guest
, this->guestif
);
151 tap
= open(TAP_DEVICE
, O_RDWR
);
154 DBG1("unable to open tap device %s: %m", TAP_DEVICE
);
157 if (ioctl(tap
, TUNSETIFF
, &ifr
) < 0 ||
158 ioctl(tap
, TUNSETPERSIST
, 1) < 0 ||
159 ioctl(tap
, TUNSETOWNER
, 0))
161 DBG1("creating new tap device failed: %m");
166 return strdup(ifr
.ifr_name
);
170 * Implementation of iface_t.destroy.
172 static void destroy(private_iface_t
*this)
176 this->bridge
->disconnect_iface(this->bridge
, &this->public);
178 this->mconsole
->del_iface(this->mconsole
, this->guestif
);
186 * create the iface instance
188 iface_t
*iface_create(char *guest
, char *guestif
, mconsole_t
*mconsole
)
190 private_iface_t
*this = malloc_thing(private_iface_t
);
192 this->public.get_hostif
= (char*(*)(iface_t
*))get_hostif
;
193 this->public.get_guestif
= (char*(*)(iface_t
*))get_guestif
;
194 this->public.set_bridge
= (void(*)(iface_t
*, bridge_t
*))set_bridge
;
195 this->public.destroy
= (void*)destroy
;
197 this->mconsole
= mconsole
;
198 this->guestif
= strdup(guestif
);
199 this->hostif
= create_tap(this, guest
);
201 if (this->hostif
== NULL
)
208 if (!iface_control(this->hostif
, TRUE
))
210 DBG1("bringing iface '%s' up failed: %m", this->hostif
);
212 if (!this->mconsole
->add_iface(this->mconsole
, this->guestif
, this->hostif
))
214 DBG1("creating interface '%s' in guest failed", this->guestif
);
221 return &this->public;