Create a TUN device via VpnService.Builder once the CHILD_SA is established
[strongswan.git] / src / frontends / android / jni / libandroidbridge / backend / android_service.c
1 /*
2 * Copyright (C) 2010-2012 Tobias Brunner
3 * Copyright (C) 2012 Giuliano Grassi
4 * Copyright (C) 2012 Ralf Sager
5 * Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include "android_service.h"
19 #include "../charonservice.h"
20 #include "../vpnservice_builder.h"
21
22 #include <daemon.h>
23 #include <library.h>
24 #include <processing/jobs/callback_job.h>
25 #include <threading/rwlock.h>
26
27 typedef struct private_android_service_t private_android_service_t;
28
29 #define TUN_DEFAULT_MTU 1400
30
31 /**
32 * private data of Android service
33 */
34 struct private_android_service_t {
35
36 /**
37 * public interface
38 */
39 android_service_t public;
40
41 /**
42 * current IKE_SA
43 */
44 ike_sa_t *ike_sa;
45
46 /**
47 * local ipv4 address
48 */
49 char *local_address;
50
51 /**
52 * gateway
53 */
54 char *gateway;
55
56 /**
57 * username
58 */
59 char *username;
60
61 /**
62 * lock to safely access the TUN device fd
63 */
64 rwlock_t *lock;
65
66 /**
67 * TUN device file descriptor
68 */
69 int tunfd;
70
71 };
72
73 /**
74 * Setup a new TUN device for the supplied SAs.
75 * Additional information such as DNS servers are gathered in appropriate
76 * listeners asynchronously. To be sure every required bit of information is
77 * available this should be called after the CHILD_SA has been established.
78 */
79 static bool setup_tun_device(private_android_service_t *this,
80 ike_sa_t *ike_sa, child_sa_t *child_sa)
81 {
82 vpnservice_builder_t *builder;
83 int tunfd;
84
85 DBG1(DBG_DMN, "setting up TUN device for CHILD_SA %s{%u}",
86 child_sa->get_name(child_sa), child_sa->get_reqid(child_sa));
87
88 builder = charonservice->get_vpnservice_builder(charonservice);
89 if (!builder->set_mtu(builder, TUN_DEFAULT_MTU))
90 {
91 return FALSE;
92 }
93
94 tunfd = builder->establish(builder);
95 if (tunfd == -1)
96 {
97 return FALSE;
98 }
99
100 this->lock->write_lock(this->lock);
101 this->tunfd = tunfd;
102 this->lock->unlock(this->lock);
103
104 DBG1(DBG_DMN, "successfully created TUN device");
105 return TRUE;
106 }
107
108 /**
109 * Close the current tun device
110 */
111 static void close_tun_device(private_android_service_t *this)
112 {
113 int tunfd;
114
115 this->lock->write_lock(this->lock);
116 if (this->tunfd < 0)
117 { /* already closed (or never created) */
118 this->lock->unlock(this->lock);
119 return;
120 }
121 tunfd = this->tunfd;
122 this->tunfd = -1;
123 this->lock->unlock(this->lock);
124 close(tunfd);
125 }
126
127 METHOD(listener_t, child_updown, bool,
128 private_android_service_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
129 bool up)
130 {
131 if (this->ike_sa == ike_sa)
132 {
133 if (up)
134 {
135 /* disable the hooks registered to catch initiation failures */
136 this->public.listener.ike_updown = NULL;
137 this->public.listener.ike_state_change = NULL;
138 if (!setup_tun_device(this, ike_sa, child_sa))
139 {
140 DBG1(DBG_DMN, "failed to setup TUN device");
141 charonservice->update_status(charonservice,
142 CHARONSERVICE_GENERIC_ERROR);
143 return FALSE;
144
145 }
146 charonservice->update_status(charonservice,
147 CHARONSERVICE_CHILD_STATE_UP);
148 }
149 else
150 {
151 close_tun_device(this);
152 charonservice->update_status(charonservice,
153 CHARONSERVICE_CHILD_STATE_DOWN);
154 return FALSE;
155 }
156 }
157 return TRUE;
158 }
159
160 METHOD(listener_t, ike_updown, bool,
161 private_android_service_t *this, ike_sa_t *ike_sa, bool up)
162 {
163 /* this callback is only registered during initiation, so if the IKE_SA
164 * goes down we assume an authentication error */
165 if (this->ike_sa == ike_sa && !up)
166 {
167 charonservice->update_status(charonservice,
168 CHARONSERVICE_AUTH_ERROR);
169 return FALSE;
170 }
171 return TRUE;
172 }
173
174 METHOD(listener_t, ike_state_change, bool,
175 private_android_service_t *this, ike_sa_t *ike_sa, ike_sa_state_t state)
176 {
177 /* this call back is only registered during initiation */
178 if (this->ike_sa == ike_sa && state == IKE_DESTROYING)
179 {
180 charonservice->update_status(charonservice,
181 CHARONSERVICE_UNREACHABLE_ERROR);
182 return FALSE;
183 }
184 return TRUE;
185 }
186
187 METHOD(listener_t, alert, bool,
188 private_android_service_t *this, ike_sa_t *ike_sa, alert_t alert,
189 va_list args)
190 {
191 if (this->ike_sa == ike_sa)
192 {
193 switch (alert)
194 {
195 case ALERT_PEER_ADDR_FAILED:
196 charonservice->update_status(charonservice,
197 CHARONSERVICE_LOOKUP_ERROR);
198 break;
199 case ALERT_PEER_AUTH_FAILED:
200 charonservice->update_status(charonservice,
201 CHARONSERVICE_PEER_AUTH_ERROR);
202 break;
203 default:
204 break;
205 }
206 }
207 return TRUE;
208 }
209
210 METHOD(listener_t, ike_rekey, bool,
211 private_android_service_t *this, ike_sa_t *old, ike_sa_t *new)
212 {
213 if (this->ike_sa == old)
214 {
215 this->ike_sa = new;
216 }
217 return TRUE;
218 }
219
220 static job_requeue_t initiate(private_android_service_t *this)
221 {
222 identification_t *gateway, *user;
223 ike_cfg_t *ike_cfg;
224 peer_cfg_t *peer_cfg;
225 child_cfg_t *child_cfg;
226 traffic_selector_t *ts;
227 ike_sa_t *ike_sa;
228 auth_cfg_t *auth;
229 lifetime_cfg_t lifetime = {
230 .time = {
231 .life = 10800, /* 3h */
232 .rekey = 10200, /* 2h50min */
233 .jitter = 300 /* 5min */
234 }
235 };
236
237 ike_cfg = ike_cfg_create(TRUE, TRUE, this->local_address, FALSE,
238 charon->socket->get_port(charon->socket, FALSE),
239 this->gateway, FALSE, IKEV2_UDP_PORT);
240 ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
241
242 peer_cfg = peer_cfg_create("android", IKEV2, ike_cfg, CERT_SEND_IF_ASKED,
243 UNIQUE_REPLACE, 1, /* keyingtries */
244 36000, 0, /* rekey 10h, reauth none */
245 600, 600, /* jitter, over 10min */
246 TRUE, FALSE, /* mobike, aggressive */
247 0, 0, /* DPD delay, timeout */
248 host_create_from_string("0.0.0.0", 0) /* virt */,
249 NULL, FALSE, NULL, NULL); /* pool, mediation */
250
251
252 auth = auth_cfg_create();
253 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
254 user = identification_create_from_string(this->username);
255 auth->add(auth, AUTH_RULE_IDENTITY, user);
256 peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
257 auth = auth_cfg_create();
258 auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
259 gateway = identification_create_from_string(this->gateway);
260 auth->add(auth, AUTH_RULE_IDENTITY, gateway);
261 peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
262
263 child_cfg = child_cfg_create("android", &lifetime, NULL, TRUE, MODE_TUNNEL,
264 ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
265 0, 0, NULL, NULL, 0);
266 child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
267 ts = traffic_selector_create_dynamic(0, 0, 65535);
268 child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
269 ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE, "0.0.0.0",
270 0, "255.255.255.255", 65535);
271 child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
272 peer_cfg->add_child_cfg(peer_cfg, child_cfg);
273
274 /* get us an IKE_SA */
275 ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
276 peer_cfg);
277 if (!ike_sa)
278 {
279 peer_cfg->destroy(peer_cfg);
280 charonservice->update_status(charonservice,
281 CHARONSERVICE_GENERIC_ERROR);
282 return JOB_REQUEUE_NONE;
283 }
284 if (!ike_sa->get_peer_cfg(ike_sa))
285 {
286 ike_sa->set_peer_cfg(ike_sa, peer_cfg);
287 }
288 peer_cfg->destroy(peer_cfg);
289
290 /* store the IKE_SA so we can track its progress */
291 this->ike_sa = ike_sa;
292
293 /* get an additional reference because initiate consumes one */
294 child_cfg->get_ref(child_cfg);
295 if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS)
296 {
297 DBG1(DBG_CFG, "failed to initiate tunnel");
298 charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
299 ike_sa);
300 return JOB_REQUEUE_NONE;
301 }
302 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
303 return JOB_REQUEUE_NONE;
304 }
305
306 METHOD(android_service_t, destroy, void,
307 private_android_service_t *this)
308 {
309 charon->bus->remove_listener(charon->bus, &this->public.listener);
310 /* make sure the tun device is actually closed */
311 close_tun_device(this);
312 this->lock->destroy(this->lock);
313 free(this->local_address);
314 free(this->username);
315 free(this->gateway);
316 free(this);
317 }
318
319 /**
320 * See header
321 */
322 android_service_t *android_service_create(char *local_address, char *gateway,
323 char *username)
324 {
325 private_android_service_t *this;
326
327 INIT(this,
328 .public = {
329 .listener = {
330 .ike_rekey = _ike_rekey,
331 .ike_updown = _ike_updown,
332 .ike_state_change = _ike_state_change,
333 .child_updown = _child_updown,
334 .alert = _alert,
335 },
336 .destroy = _destroy,
337 },
338 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
339 .local_address = local_address,
340 .username = username,
341 .gateway = gateway,
342 .tunfd = -1,
343 );
344
345 charon->bus->add_listener(charon->bus, &this->public.listener);
346
347 lib->processor->queue_job(lib->processor,
348 (job_t*)callback_job_create((callback_job_cb_t)initiate, this,
349 NULL, NULL));
350 return &this->public;
351 }