implemented mconsole notification to check if guest came up
[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" utility 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 <stdio.h>
23 #include <net/if.h>
24 #include <sys/ioctl.h>
25 #include <linux/if_tun.h>
26
27 #include <debug.h>
28
29 #include "iface.h"
30
31 typedef struct private_iface_t private_iface_t;
32
33 struct private_iface_t {
34 /** public interface */
35 iface_t public;
36 /** device name in guest (eth0) */
37 char *guestif;
38 /** device name at host (tap0) */
39 char *hostif;
40 /** mconsole for guest */
41 mconsole_t *mconsole;
42 };
43
44 /**
45 * Implementation of iface_t.get_guestif.
46 */
47 static char* get_guestif(private_iface_t *this)
48 {
49 return this->guestif;
50 }
51
52 /**
53 * Implementation of iface_t.get_hostif.
54 */
55 static char* get_hostif(private_iface_t *this)
56 {
57 return this->hostif;
58 }
59
60 /**
61 * destroy the tap device
62 */
63 static bool destroy_tap(private_iface_t *this)
64 {
65 struct ifreq ifr;
66 int tap;
67
68 memset(&ifr, 0, sizeof(ifr));
69 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
70 strncpy(ifr.ifr_name, this->hostif, sizeof(ifr.ifr_name) - 1);
71
72 tap = open(TAP_DEVICE, O_RDWR);
73 if (tap < 0)
74 {
75 DBG1("unable to open tap device %s: %m", TAP_DEVICE);
76 return FALSE;
77 }
78 if (ioctl(tap, TUNSETIFF, &ifr) < 0 ||
79 ioctl(tap, TUNSETPERSIST, 0) < 0)
80 {
81 DBG1("removing %s failed: %m", this->hostif);
82 close(tap);
83 return FALSE;
84 }
85 close(tap);
86 return TRUE;
87 }
88
89 /**
90 * create the tap device
91 */
92 static char* create_tap(private_iface_t *this, char *guest)
93 {
94 struct ifreq ifr;
95 int tap;
96
97 memset(&ifr, 0, sizeof(ifr));
98 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
99 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s-%s", guest, this->guestif);
100
101 tap = open(TAP_DEVICE, O_RDWR);
102 if (tap < 0)
103 {
104 DBG1("unable to open tap device %s: %m", TAP_DEVICE);
105 return NULL;
106 }
107 if (ioctl(tap, TUNSETIFF, &ifr) < 0 ||
108 ioctl(tap, TUNSETPERSIST, 1) < 0 ||
109 ioctl(tap, TUNSETOWNER, 0))
110 {
111 DBG1("creating new tap device failed: %m");
112 close(tap);
113 return NULL;
114 }
115 close(tap);
116 return strdup(ifr.ifr_name);
117 }
118
119 /**
120 * Implementation of iface_t.destroy.
121 */
122 static void destroy(private_iface_t *this)
123 {
124 this->mconsole->del_iface(this->mconsole, this->guestif);
125 destroy_tap(this);
126 free(this->guestif);
127 free(this->hostif);
128 free(this);
129 }
130
131 /**
132 * create the iface instance
133 */
134 iface_t *iface_create(char *guest, char *guestif, mconsole_t *mconsole)
135 {
136 private_iface_t *this = malloc_thing(private_iface_t);
137
138 this->public.get_hostif = (char*(*)(iface_t*))get_hostif;
139 this->public.get_guestif = (char*(*)(iface_t*))get_guestif;
140 this->public.destroy = (void*)destroy;
141
142 this->mconsole = mconsole;
143 this->guestif = strdup(guestif);
144 this->hostif = create_tap(this, guest);
145 if (this->hostif == NULL)
146 {
147 destroy_tap(this);
148 free(this->guestif);
149 free(this);
150 return NULL;
151 }
152 if (!this->mconsole->add_iface(this->mconsole, this->guestif, this->hostif))
153 {
154 DBG1("creating interface '%s' in guest failed", this->guestif);
155 destroy_tap(this);
156 free(this->guestif);
157 free(this->hostif);
158 free(this);
159 return NULL;
160 }
161 return &this->public;
162 }
163