fixed mconsole when using multiple 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 ioctl(this->tap, TUNSETOWNER, 0))
94 {
95 DBG1("creating new tap device failed: %m");
96 return NULL;
97 }
98 return strdup(ifr.ifr_name);
99 }
100
101 /**
102 * Implementation of iface_t.destroy.
103 */
104 static void destroy(private_iface_t *this)
105 {
106 this->mconsole->del_iface(this->mconsole, this->guest);
107 destroy_tap(this);
108 close(this->tap);
109 free(this->guest);
110 free(this->host);
111 free(this);
112 }
113
114 /**
115 * create the iface instance
116 */
117 iface_t *iface_create(char *guest, mconsole_t *mconsole)
118 {
119 private_iface_t *this = malloc_thing(private_iface_t);
120
121 this->public.get_host = (char*(*)(iface_t*))get_host;
122 this->public.get_guest = (char*(*)(iface_t*))get_guest;
123 this->public.destroy = (void*)destroy;
124
125 this->mconsole = mconsole;
126 this->tap = open(TAP_DEVICE, O_RDWR);
127 if (this->tap < 0)
128 {
129 DBG1("unable to open tap device %s: %m", TAP_DEVICE);
130 free(this);
131 return NULL;
132 }
133 this->guest = strdup(guest);
134 this->host = create_tap(this);
135 if (this->host == NULL)
136 {
137 destroy_tap(this);
138 close(this->tap);
139 free(this->guest);
140 free(this);
141 return NULL;
142 }
143 if (!this->mconsole->add_iface(this->mconsole, this->guest, this->host))
144 {
145 DBG1("creating interface '%s' in guest failed", this->guest);
146 destroy_tap(this);
147 close(this->tap);
148 free(this->guest);
149 free(this->host);
150 free(this);
151 return NULL;
152 }
153 return &this->public;
154 }
155