5232bc4829988ff80a7602eaaa461da65886f18e
[strongswan.git] / src / frontends / android / jni / libandroidbridge / vpnservice_builder.c
1 /*
2 * Copyright (C) 2012-2013 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 "vpnservice_builder.h"
19 #include "android_jni.h"
20
21 #include <utils/debug.h>
22 #include <library.h>
23
24 typedef struct private_vpnservice_builder_t private_vpnservice_builder_t;
25
26 /**
27 * private data of vpnservice_builder
28 */
29 struct private_vpnservice_builder_t {
30
31 /**
32 * public interface
33 */
34 vpnservice_builder_t public;
35
36 /**
37 * Java object
38 */
39 jobject builder;
40 };
41
42 METHOD(vpnservice_builder_t, add_address, bool,
43 private_vpnservice_builder_t *this, host_t *addr)
44 {
45 JNIEnv *env;
46 jmethodID method_id;
47 jstring str;
48 char buf[INET6_ADDRSTRLEN];
49 int prefix;
50
51 androidjni_attach_thread(&env);
52
53 DBG2(DBG_LIB, "builder: adding interface address %H", addr);
54
55 prefix = addr->get_family(addr) == AF_INET ? 32 : 128;
56 if (snprintf(buf, sizeof(buf), "%H", addr) >= sizeof(buf))
57 {
58 goto failed;
59 }
60
61 method_id = (*env)->GetMethodID(env, android_charonvpnservice_builder_class,
62 "addAddress", "(Ljava/lang/String;I)Z");
63 if (!method_id)
64 {
65 goto failed;
66 }
67 str = (*env)->NewStringUTF(env, buf);
68 if (!str)
69 {
70 goto failed;
71 }
72 if (!(*env)->CallBooleanMethod(env, this->builder, method_id, str, prefix))
73 {
74 goto failed;
75 }
76 androidjni_detach_thread();
77 return TRUE;
78
79 failed:
80 DBG1(DBG_LIB, "builder: failed to add address");
81 androidjni_exception_occurred(env);
82 androidjni_detach_thread();
83 return FALSE;
84 }
85
86 METHOD(vpnservice_builder_t, set_mtu, bool,
87 private_vpnservice_builder_t *this, int mtu)
88 {
89 JNIEnv *env;
90 jmethodID method_id;
91
92 androidjni_attach_thread(&env);
93
94 DBG2(DBG_LIB, "builder: setting MTU to %d", mtu);
95
96 method_id = (*env)->GetMethodID(env, android_charonvpnservice_builder_class,
97 "setMtu", "(I)Z");
98 if (!method_id)
99 {
100 goto failed;
101 }
102 if (!(*env)->CallBooleanMethod(env, this->builder, method_id, mtu))
103 {
104 goto failed;
105 }
106 androidjni_detach_thread();
107 return TRUE;
108
109 failed:
110 DBG1(DBG_LIB, "builder: failed to set MTU");
111 androidjni_exception_occurred(env);
112 androidjni_detach_thread();
113 return FALSE;
114 }
115
116 METHOD(vpnservice_builder_t, add_route, bool,
117 private_vpnservice_builder_t *this, host_t *net, int prefix)
118 {
119 JNIEnv *env;
120 jmethodID method_id;
121 jstring str;
122 char buf[INET6_ADDRSTRLEN];
123
124 androidjni_attach_thread(&env);
125
126 DBG2(DBG_LIB, "builder: adding route %+H/%d", net, prefix);
127
128 if (snprintf(buf, sizeof(buf), "%+H", net) >= sizeof(buf))
129 {
130 goto failed;
131 }
132
133 method_id = (*env)->GetMethodID(env, android_charonvpnservice_builder_class,
134 "addRoute", "(Ljava/lang/String;I)Z");
135 if (!method_id)
136 {
137 goto failed;
138 }
139 str = (*env)->NewStringUTF(env, buf);
140 if (!str)
141 {
142 goto failed;
143 }
144 if (!(*env)->CallBooleanMethod(env, this->builder, method_id, str, prefix))
145 {
146 goto failed;
147 }
148 androidjni_detach_thread();
149 return TRUE;
150
151 failed:
152 DBG1(DBG_LIB, "builder: failed to add route");
153 androidjni_exception_occurred(env);
154 androidjni_detach_thread();
155 return FALSE;
156 }
157
158 METHOD(vpnservice_builder_t, add_dns, bool,
159 private_vpnservice_builder_t *this, host_t *dns)
160 {
161 JNIEnv *env;
162 jmethodID method_id;
163 jstring str;
164 char buf[INET_ADDRSTRLEN];
165
166 androidjni_attach_thread(&env);
167
168 DBG2(DBG_LIB, "builder: adding DNS server %H", dns);
169
170 if (dns->get_family(dns) != AF_INET)
171 {
172 goto failed;
173 }
174 if (snprintf(buf, sizeof(buf), "%H", dns) >= sizeof(buf))
175 {
176 goto failed;
177 }
178
179 method_id = (*env)->GetMethodID(env, android_charonvpnservice_builder_class,
180 "addDnsServer", "(Ljava/lang/String;)Z");
181 if (!method_id)
182 {
183 goto failed;
184 }
185 str = (*env)->NewStringUTF(env, buf);
186 if (!str)
187 {
188 goto failed;
189 }
190 if (!(*env)->CallBooleanMethod(env, this->builder, method_id, str))
191 {
192 goto failed;
193 }
194 androidjni_detach_thread();
195 return TRUE;
196
197 failed:
198 DBG1(DBG_LIB, "builder: failed to add DNS server");
199 androidjni_exception_occurred(env);
200 androidjni_detach_thread();
201 return FALSE;
202 }
203
204 METHOD(vpnservice_builder_t, establish, int,
205 private_vpnservice_builder_t *this)
206 {
207 JNIEnv *env;
208 jmethodID method_id;
209 int fd;
210
211 androidjni_attach_thread(&env);
212
213 DBG2(DBG_LIB, "builder: building TUN device");
214
215 method_id = (*env)->GetMethodID(env, android_charonvpnservice_builder_class,
216 "establish", "()I");
217 if (!method_id)
218 {
219 goto failed;
220 }
221 fd = (*env)->CallIntMethod(env, this->builder, method_id);
222 if (fd == -1)
223 {
224 goto failed;
225 }
226 androidjni_detach_thread();
227 return fd;
228
229 failed:
230 DBG1(DBG_LIB, "builder: failed to build TUN device");
231 androidjni_exception_occurred(env);
232 androidjni_detach_thread();
233 return -1;
234 }
235
236 METHOD(vpnservice_builder_t, destroy, void,
237 private_vpnservice_builder_t *this)
238 {
239 JNIEnv *env;
240
241 androidjni_attach_thread(&env);
242 (*env)->DeleteGlobalRef(env, this->builder);
243 androidjni_detach_thread();
244 free(this);
245 }
246
247 vpnservice_builder_t *vpnservice_builder_create(jobject builder)
248 {
249 JNIEnv *env;
250 private_vpnservice_builder_t *this;
251
252 INIT(this,
253 .public = {
254 .add_address = _add_address,
255 .add_route = _add_route,
256 .add_dns = _add_dns,
257 .set_mtu = _set_mtu,
258 .establish = _establish,
259 .destroy = _destroy,
260 },
261 );
262
263 androidjni_attach_thread(&env);
264 this->builder = (*env)->NewGlobalRef(env, builder);
265 androidjni_detach_thread();
266
267 return &this->public;
268 }