added dynamic interface manipulation for guests
[strongswan.git] / src / dumm / iface.c
1 /*
2 * Copyright (C) 2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 * Copyright (C) 2002 Jeff Dike
5 *
6 * Based on the "tunctl" utlity from Jeff Dike.
7 *
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>.
12 *
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
16 * for more details.
17 */
18
19 #include <sys/types.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <net/if.h>
23 #include <sys/ioctl.h>
24 #include <linux/if_tun.h>
25
26 #include <debug.h>
27
28 #include "iface.h"
29
30 typedef struct private_iface_t private_iface_t;
31
32 struct private_iface_t {
33 /** public interface */
34 iface_t public;
35 /** device name in guest (eth0) */
36 char *guest;
37 /** device name at host (tap0) */
38 char *host;
39 /** tap device handle to manage taps */
40 int tap;
41 /** mconsole for guest */
42 mconsole_t *mconsole;
43 };
44
45 /**
46 * Implementation of iface_t.get_guest.
47 */
48 static char* get_guest(private_iface_t *this)
49 {
50 return this->guest;
51 }
52
53 /**
54 * Implementation of iface_t.get_host.
55 */
56 static char* get_host(private_iface_t *this)
57 {
58 return this->host;
59 }
60
61 /**
62 * destroy the tap device
63 */
64 static bool destroy_tap(private_iface_t *this)
65 {
66 struct ifreq ifr;
67
68 memset(&ifr, 0, sizeof(ifr));
69 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
70 strncpy(ifr.ifr_name, this->host, sizeof(ifr.ifr_name) - 1);
71
72 if (ioctl(this->tap, TUNSETIFF, &ifr) < 0 ||
73 ioctl(this->tap, TUNSETPERSIST, 0) < 0)
74 {
75 DBG1("removing %s failed: %m", this->host);
76 return FALSE;
77 }
78 return TRUE;
79 }
80
81 /**
82 * create the tap device
83 */
84 static char* create_tap(private_iface_t *this)
85 {
86 struct ifreq ifr;
87
88 memset(&ifr, 0, sizeof(ifr));
89 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
90
91 if (ioctl(this->tap, TUNSETIFF, &ifr) < 0 ||
92 ioctl(this->tap, TUNSETPERSIST, 1) < 0)
93 {
94 DBG1("creating new tap device failed: %m");
95 return NULL;
96 }
97 return strdup(ifr.ifr_name);
98 }
99
100 /**
101 * Implementation of iface_t.destroy.
102 */
103 static void destroy(private_iface_t *this)
104 {
105 this->mconsole->del_iface(this->mconsole, this->guest);
106 destroy_tap(this);
107 close(this->tap);
108 free(this->guest);
109 free(this->host);
110 free(this);
111 }
112
113 /**
114 * create the iface instance
115 */
116 iface_t *iface_create(char *guest, mconsole_t *mconsole)
117 {
118 private_iface_t *this = malloc_thing(private_iface_t);
119
120 this->public.get_host = (char*(*)(iface_t*))get_host;
121 this->public.get_guest = (char*(*)(iface_t*))get_guest;
122 this->public.destroy = (void*)destroy;
123
124 this->mconsole = mconsole;
125 this->tap = open(TAP_DEVICE, O_RDWR);
126 if (this->tap < 0)
127 {
128 DBG1("unable to open tap device %s: %m", TAP_DEVICE);
129 free(this);
130 return NULL;
131 }
132 this->guest = strdup(guest);
133 this->host = create_tap(this);
134 if (this->host == NULL)
135 {
136 destroy_tap(this);
137 close(this->tap);
138 free(this->guest);
139 free(this);
140 return NULL;
141 }
142 if (!this->mconsole->add_iface(this->mconsole, this->guest, this->host))
143 {
144 DBG1("creating interface '%s' in guest failed", this->guest);
145 destroy_tap(this);
146 close(this->tap);
147 free(this->guest);
148 free(this->host);
149 free(this);
150 return NULL;
151 }
152 return &this->public;
153 }
154