android: Request and install an IPv6 DNS server
[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[INET6_ADDRSTRLEN];
165
166 androidjni_attach_thread(&env);
167
168 DBG2(DBG_LIB, "builder: adding DNS server %H", dns);
169
170 if (snprintf(buf, sizeof(buf), "%H", dns) >= sizeof(buf))
171 {
172 goto failed;
173 }
174
175 method_id = (*env)->GetMethodID(env, android_charonvpnservice_builder_class,
176 "addDnsServer", "(Ljava/lang/String;)Z");
177 if (!method_id)
178 {
179 goto failed;
180 }
181 str = (*env)->NewStringUTF(env, buf);
182 if (!str)
183 {
184 goto failed;
185 }
186 if (!(*env)->CallBooleanMethod(env, this->builder, method_id, str))
187 {
188 goto failed;
189 }
190 androidjni_detach_thread();
191 return TRUE;
192
193 failed:
194 DBG1(DBG_LIB, "builder: failed to add DNS server");
195 androidjni_exception_occurred(env);
196 androidjni_detach_thread();
197 return FALSE;
198 }
199
200 METHOD(vpnservice_builder_t, establish, int,
201 private_vpnservice_builder_t *this)
202 {
203 JNIEnv *env;
204 jmethodID method_id;
205 int fd;
206
207 androidjni_attach_thread(&env);
208
209 DBG2(DBG_LIB, "builder: building TUN device");
210
211 method_id = (*env)->GetMethodID(env, android_charonvpnservice_builder_class,
212 "establish", "()I");
213 if (!method_id)
214 {
215 goto failed;
216 }
217 fd = (*env)->CallIntMethod(env, this->builder, method_id);
218 if (fd == -1)
219 {
220 goto failed;
221 }
222 androidjni_detach_thread();
223 return fd;
224
225 failed:
226 DBG1(DBG_LIB, "builder: failed to build TUN device");
227 androidjni_exception_occurred(env);
228 androidjni_detach_thread();
229 return -1;
230 }
231
232 METHOD(vpnservice_builder_t, destroy, void,
233 private_vpnservice_builder_t *this)
234 {
235 JNIEnv *env;
236
237 androidjni_attach_thread(&env);
238 (*env)->DeleteGlobalRef(env, this->builder);
239 androidjni_detach_thread();
240 free(this);
241 }
242
243 vpnservice_builder_t *vpnservice_builder_create(jobject builder)
244 {
245 JNIEnv *env;
246 private_vpnservice_builder_t *this;
247
248 INIT(this,
249 .public = {
250 .add_address = _add_address,
251 .add_route = _add_route,
252 .add_dns = _add_dns,
253 .set_mtu = _set_mtu,
254 .establish = _establish,
255 .destroy = _destroy,
256 },
257 );
258
259 androidjni_attach_thread(&env);
260 this->builder = (*env)->NewGlobalRef(env, builder);
261 androidjni_detach_thread();
262
263 return &this->public;
264 }