completed pkcs7 parsing methods
[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 /** bridge this interface is attached to */
41 bridge_t *bridge;
42 /** mconsole for guest */
43 mconsole_t *mconsole;
44 };
45
46 /**
47 * Implementation of iface_t.get_guestif.
48 */
49 static char* get_guestif(private_iface_t *this)
50 {
51 return this->guestif;
52 }
53
54 /**
55 * Implementation of iface_t.get_hostif.
56 */
57 static char* get_hostif(private_iface_t *this)
58 {
59 return this->hostif;
60 }
61
62 /**
63 * Implementation of iface_t.set_bridge.
64 */
65 static void set_bridge(private_iface_t *this, bridge_t *bridge)
66 {
67 this->bridge = bridge;
68 }
69
70 /**
71 * destroy the tap device
72 */
73 static bool destroy_tap(private_iface_t *this)
74 {
75 struct ifreq ifr;
76 int tap;
77
78 memset(&ifr, 0, sizeof(ifr));
79 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
80 strncpy(ifr.ifr_name, this->hostif, sizeof(ifr.ifr_name) - 1);
81
82 tap = open(TAP_DEVICE, O_RDWR);
83 if (tap < 0)
84 {
85 DBG1("unable to open tap device %s: %m", TAP_DEVICE);
86 return FALSE;
87 }
88 if (ioctl(tap, TUNSETIFF, &ifr) < 0 ||
89 ioctl(tap, TUNSETPERSIST, 0) < 0)
90 {
91 DBG1("removing %s failed: %m", this->hostif);
92 close(tap);
93 return FALSE;
94 }
95 close(tap);
96 return TRUE;
97 }
98
99 /**
100 * create the tap device
101 */
102 static char* create_tap(private_iface_t *this, char *guest)
103 {
104 struct ifreq ifr;
105 int tap;
106
107 memset(&ifr, 0, sizeof(ifr));
108 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
109 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s-%s", guest, this->guestif);
110
111 tap = open(TAP_DEVICE, O_RDWR);
112 if (tap < 0)
113 {
114 DBG1("unable to open tap device %s: %m", TAP_DEVICE);
115 return NULL;
116 }
117 if (ioctl(tap, TUNSETIFF, &ifr) < 0 ||
118 ioctl(tap, TUNSETPERSIST, 1) < 0 ||
119 ioctl(tap, TUNSETOWNER, 0))
120 {
121 DBG1("creating new tap device failed: %m");
122 close(tap);
123 return NULL;
124 }
125 close(tap);
126 return strdup(ifr.ifr_name);
127 }
128
129 /**
130 * Implementation of iface_t.destroy.
131 */
132 static void destroy(private_iface_t *this)
133 {
134 if (this->bridge)
135 {
136 this->bridge->disconnect_iface(this->bridge, &this->public);
137 }
138 this->mconsole->del_iface(this->mconsole, this->guestif);
139 destroy_tap(this);
140 free(this->guestif);
141 free(this->hostif);
142 free(this);
143 }
144
145 /**
146 * create the iface instance
147 */
148 iface_t *iface_create(char *guest, char *guestif, mconsole_t *mconsole)
149 {
150 private_iface_t *this = malloc_thing(private_iface_t);
151
152 this->public.get_hostif = (char*(*)(iface_t*))get_hostif;
153 this->public.get_guestif = (char*(*)(iface_t*))get_guestif;
154 this->public.set_bridge = (void(*)(iface_t*, bridge_t*))set_bridge;
155 this->public.destroy = (void*)destroy;
156
157 this->mconsole = mconsole;
158 this->guestif = strdup(guestif);
159 this->hostif = create_tap(this, guest);
160 this->bridge = NULL;
161 if (this->hostif == NULL)
162 {
163 destroy_tap(this);
164 free(this->guestif);
165 free(this);
166 return NULL;
167 }
168 if (!this->mconsole->add_iface(this->mconsole, this->guestif, this->hostif))
169 {
170 DBG1("creating interface '%s' in guest failed", this->guestif);
171 destroy_tap(this);
172 free(this->guestif);
173 free(this->hostif);
174 free(this);
175 return NULL;
176 }
177 return &this->public;
178 }
179