com_android_server_connectivity_Vpn.cpp revision 84bf7390ea6b9a82bbd036b64c41d7c120b7f159
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_NDEBUG 0 18 19#define LOG_TAG "VpnJni" 20#include <cutils/log.h> 21#include <cutils/properties.h> 22 23#include <stdio.h> 24#include <string.h> 25#include <sys/ioctl.h> 26#include <sys/types.h> 27#include <sys/stat.h> 28#include <sys/socket.h> 29#include <netinet/in.h> 30#include <arpa/inet.h> 31#include <errno.h> 32#include <fcntl.h> 33 34#include <linux/if.h> 35#include <linux/if_tun.h> 36#include <linux/route.h> 37#include <linux/ipv6_route.h> 38 39#include "jni.h" 40#include "JNIHelp.h" 41 42namespace android 43{ 44 45static inline in_addr_t *as_in_addr(sockaddr *sa) { 46 return &((sockaddr_in *)sa)->sin_addr.s_addr; 47} 48 49//------------------------------------------------------------------------------ 50 51#define SYSTEM_ERROR -1 52#define BAD_ARGUMENT -2 53 54static int create_interface(int mtu, char *name, int *index) 55{ 56 int tun = open("/dev/tun", O_RDWR); 57 int inet4 = socket(AF_INET, SOCK_DGRAM, 0); 58 int flags; 59 60 ifreq ifr4; 61 memset(&ifr4, 0, sizeof(ifr4)); 62 63 // Allocate interface. 64 ifr4.ifr_flags = IFF_TUN | IFF_NO_PI; 65 if (ioctl(tun, TUNSETIFF, &ifr4)) { 66 LOGE("Cannot allocate TUN: %s", strerror(errno)); 67 goto error; 68 } 69 70 // Activate interface. 71 ifr4.ifr_flags = IFF_UP; 72 if (ioctl(inet4, SIOCSIFFLAGS, &ifr4)) { 73 LOGE("Cannot activate %s: %s", ifr4.ifr_name, strerror(errno)); 74 goto error; 75 } 76 77 // Set MTU if it is specified. 78 ifr4.ifr_mtu = mtu; 79 if (mtu > 0 && ioctl(inet4, SIOCSIFMTU, &ifr4)) { 80 LOGE("Cannot set MTU on %s: %s", ifr4.ifr_name, strerror(errno)); 81 goto error; 82 } 83 84 // Get interface index. 85 if (ioctl(inet4, SIOGIFINDEX, &ifr4)) { 86 LOGE("Cannot get index of %s: %s", ifr4.ifr_name, strerror(errno)); 87 goto error; 88 } 89 90 // Make it non-blocking. 91 flags = fcntl(tun, F_GETFL, 0); 92 if (flags == -1 || fcntl(tun, F_SETFL, flags | O_NONBLOCK)) { 93 LOGE("Cannot set non-blocking on %s: %s", ifr4.ifr_name, strerror(errno)); 94 goto error; 95 } 96 97 strcpy(name, ifr4.ifr_name); 98 *index = ifr4.ifr_ifindex; 99 close(inet4); 100 return tun; 101 102error: 103 close(tun); 104 close(inet4); 105 return SYSTEM_ERROR; 106} 107 108static int set_addresses(const char *name, int index, const char *addresses) 109{ 110 int inet4 = socket(AF_INET, SOCK_DGRAM, 0); 111 int inet6 = socket(AF_INET6, SOCK_DGRAM, 0); 112 113 ifreq ifr4; 114 memset(&ifr4, 0, sizeof(ifr4)); 115 strcpy(ifr4.ifr_name, name); 116 ifr4.ifr_addr.sa_family = AF_INET; 117 118 in6_ifreq ifr6; 119 memset(&ifr6, 0, sizeof(ifr6)); 120 ifr6.ifr6_ifindex = index; 121 122 char address[65]; 123 int prefix; 124 125 int chars; 126 int count = 0; 127 128 while (sscanf(addresses, " %64[^/]/%d %n", address, &prefix, &chars) == 2) { 129 addresses += chars; 130 131 if (strchr(address, ':')) { 132 // Add an IPv6 address. 133 if (inet_pton(AF_INET6, address, &ifr6.ifr6_addr) != 1 || 134 prefix < 0 || prefix > 128) { 135 count = BAD_ARGUMENT; 136 break; 137 } 138 139 ifr6.ifr6_prefixlen = prefix; 140 if (ioctl(inet6, SIOCSIFADDR, &ifr6)) { 141 count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR; 142 break; 143 } 144 } else { 145 // Add an IPv4 address. 146 if (inet_pton(AF_INET, address, as_in_addr(&ifr4.ifr_addr)) != 1 || 147 prefix < 0 || prefix > 32) { 148 count = BAD_ARGUMENT; 149 break; 150 } 151 152 if (count) { 153 sprintf(ifr4.ifr_name, "%s:%d", name, count); 154 } 155 if (ioctl(inet4, SIOCSIFADDR, &ifr4)) { 156 count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR; 157 break; 158 } 159 160 in_addr_t mask = prefix ? (~0 << (32 - prefix)) : 0; 161 *as_in_addr(&ifr4.ifr_addr) = htonl(mask); 162 if (ioctl(inet4, SIOCSIFNETMASK, &ifr4)) { 163 count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR; 164 break; 165 } 166 } 167 LOGV("Address added on %s: %s/%d", name, address, prefix); 168 ++count; 169 } 170 171 if (count == BAD_ARGUMENT) { 172 LOGE("Invalid address: %s/%d", address, prefix); 173 } else if (count == SYSTEM_ERROR) { 174 LOGE("Cannot add address: %s/%d: %s", address, prefix, strerror(errno)); 175 } else if (*addresses) { 176 LOGE("Invalid address: %s", addresses); 177 count = BAD_ARGUMENT; 178 } 179 180 close(inet4); 181 close(inet6); 182 return count; 183} 184 185static int set_routes(const char *name, int index, const char *routes) 186{ 187 int inet4 = socket(AF_INET, SOCK_DGRAM, 0); 188 int inet6 = socket(AF_INET6, SOCK_DGRAM, 0); 189 190 rtentry rt4; 191 memset(&rt4, 0, sizeof(rt4)); 192 rt4.rt_dev = (char *)name; 193 rt4.rt_flags = RTF_UP; 194 rt4.rt_dst.sa_family = AF_INET; 195 rt4.rt_genmask.sa_family = AF_INET; 196 197 in6_rtmsg rt6; 198 memset(&rt6, 0, sizeof(rt6)); 199 rt6.rtmsg_ifindex = index; 200 rt6.rtmsg_flags = RTF_UP; 201 202 char address[65]; 203 int prefix; 204 205 int chars; 206 int count = 0; 207 208 while (sscanf(routes, " %64[^/]/%d %n", address, &prefix, &chars) == 2) { 209 routes += chars; 210 211 if (strchr(address, ':')) { 212 // Add an IPv6 route. 213 if (inet_pton(AF_INET6, address, &rt6.rtmsg_dst) != 1 || 214 prefix < 1 || prefix > 128) { 215 count = BAD_ARGUMENT; 216 break; 217 } 218 219 rt6.rtmsg_dst_len = prefix; 220 if (ioctl(inet6, SIOCADDRT, &rt6) && errno != EEXIST) { 221 count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR; 222 break; 223 } 224 } else { 225 // Add an IPv4 route. 226 if (inet_pton(AF_INET, address, as_in_addr(&rt4.rt_dst)) != 1 || 227 prefix < 1 || prefix > 32) { 228 count = BAD_ARGUMENT; 229 break; 230 } 231 232 in_addr_t mask = prefix ? (~0 << (32 - prefix)) : 0; 233 *as_in_addr(&rt4.rt_genmask) = htonl(mask); 234 if (ioctl(inet4, SIOCADDRT, &rt4) && errno != EEXIST) { 235 count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR; 236 break; 237 } 238 } 239 LOGV("Route added on %s: %s/%d", name, address, prefix); 240 ++count; 241 } 242 243 if (count == BAD_ARGUMENT) { 244 LOGE("Invalid route: %s/%d", address, prefix); 245 } else if (count == SYSTEM_ERROR) { 246 LOGE("Cannot add route: %s/%d: %s", 247 address, prefix, strerror(errno)); 248 } else if (*routes) { 249 LOGE("Invalid route: %s", routes); 250 count = BAD_ARGUMENT; 251 } 252 253 close(inet4); 254 close(inet6); 255 return count; 256} 257 258static int get_interface_name(char *name, int tun) 259{ 260 ifreq ifr4; 261 if (ioctl(tun, TUNGETIFF, &ifr4)) { 262 LOGE("Cannot get interface name: %s", strerror(errno)); 263 return SYSTEM_ERROR; 264 } 265 strcpy(name, ifr4.ifr_name); 266 return 0; 267} 268 269static int reset_interface(const char *name) 270{ 271 int inet4 = socket(AF_INET, SOCK_DGRAM, 0); 272 273 ifreq ifr4; 274 ifr4.ifr_flags = 0; 275 strncpy(ifr4.ifr_name, name, IFNAMSIZ); 276 277 if (ioctl(inet4, SIOCSIFFLAGS, &ifr4) && errno != ENODEV) { 278 LOGE("Cannot reset %s: %s", name, strerror(errno)); 279 close(inet4); 280 return SYSTEM_ERROR; 281 } 282 close(inet4); 283 return 0; 284} 285 286static int check_interface(const char *name) 287{ 288 int inet4 = socket(AF_INET, SOCK_DGRAM, 0); 289 290 ifreq ifr4; 291 strncpy(ifr4.ifr_name, name, IFNAMSIZ); 292 ifr4.ifr_flags = 0; 293 294 if (ioctl(inet4, SIOCGIFFLAGS, &ifr4) && errno != ENODEV) { 295 LOGE("Cannot check %s: %s", name, strerror(errno)); 296 } 297 close(inet4); 298 return ifr4.ifr_flags; 299} 300 301static int bind_to_interface(int fd, const char *name) 302{ 303 if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name))) { 304 LOGE("Cannot bind socket to %s: %s", name, strerror(errno)); 305 return SYSTEM_ERROR; 306 } 307 return 0; 308} 309 310//------------------------------------------------------------------------------ 311 312static void throwException(JNIEnv *env, int error, const char *message) 313{ 314 if (error == SYSTEM_ERROR) { 315 jniThrowException(env, "java/lang/IllegalStateException", message); 316 } else { 317 jniThrowException(env, "java/lang/IllegalArgumentException", message); 318 } 319} 320 321static jint establish(JNIEnv *env, jobject thiz, 322 jint mtu, jstring jAddresses, jstring jRoutes) 323{ 324 char name[IFNAMSIZ]; 325 int index; 326 int tun = create_interface(mtu, name, &index); 327 if (tun < 0) { 328 throwException(env, tun, "Cannot create interface"); 329 return -1; 330 } 331 LOGD("%s is created", name); 332 333 const char *addresses; 334 const char *routes; 335 int count; 336 337 // Addresses are required. 338 addresses = jAddresses ? env->GetStringUTFChars(jAddresses, NULL) : NULL; 339 if (!addresses) { 340 jniThrowNullPointerException(env, "address"); 341 goto error; 342 } 343 count = set_addresses(name, index, addresses); 344 env->ReleaseStringUTFChars(jAddresses, addresses); 345 if (count <= 0) { 346 throwException(env, count, "Cannot set address"); 347 goto error; 348 } 349 LOGD("Configured %d address(es) on %s", count, name); 350 351 // Routes are optional. 352 routes = jRoutes ? env->GetStringUTFChars(jRoutes, NULL) : NULL; 353 if (routes) { 354 count = set_routes(name, index, routes); 355 env->ReleaseStringUTFChars(jRoutes, routes); 356 if (count < 0) { 357 throwException(env, count, "Cannot set route"); 358 goto error; 359 } 360 LOGD("Configured %d route(s) on %s", count, name); 361 } 362 363 return tun; 364 365error: 366 close(tun); 367 LOGD("%s is destroyed", name); 368 return -1; 369} 370 371static jstring getName(JNIEnv *env, jobject thiz, jint fd) 372{ 373 char name[IFNAMSIZ]; 374 if (get_interface_name(name, fd) < 0) { 375 throwException(env, SYSTEM_ERROR, "Cannot get interface name"); 376 return NULL; 377 } 378 return env->NewStringUTF(name); 379} 380 381static void reset(JNIEnv *env, jobject thiz, jstring jName) 382{ 383 const char *name = jName ? 384 env->GetStringUTFChars(jName, NULL) : NULL; 385 if (!name) { 386 jniThrowNullPointerException(env, "name"); 387 return; 388 } 389 if (reset_interface(name) < 0) { 390 throwException(env, SYSTEM_ERROR, "Cannot reset interface"); 391 } else { 392 LOGD("%s is deactivated", name); 393 } 394 env->ReleaseStringUTFChars(jName, name); 395} 396 397static jint check(JNIEnv *env, jobject thiz, jstring jName) 398{ 399 const char *name = jName ? 400 env->GetStringUTFChars(jName, NULL) : NULL; 401 if (!name) { 402 jniThrowNullPointerException(env, "name"); 403 return 0; 404 } 405 int flags = check_interface(name); 406 env->ReleaseStringUTFChars(jName, name); 407 return flags; 408} 409 410static void protect(JNIEnv *env, jobject thiz, jint fd, jstring jName) 411{ 412 const char *name = jName ? 413 env->GetStringUTFChars(jName, NULL) : NULL; 414 if (!name) { 415 jniThrowNullPointerException(env, "name"); 416 return; 417 } 418 if (bind_to_interface(fd, name) < 0) { 419 throwException(env, SYSTEM_ERROR, "Cannot protect socket"); 420 } 421 env->ReleaseStringUTFChars(jName, name); 422} 423 424//------------------------------------------------------------------------------ 425 426static JNINativeMethod gMethods[] = { 427 {"nativeEstablish", "(ILjava/lang/String;Ljava/lang/String;)I", (void *)establish}, 428 {"nativeGetName", "(I)Ljava/lang/String;", (void *)getName}, 429 {"nativeReset", "(Ljava/lang/String;)V", (void *)reset}, 430 {"nativeCheck", "(Ljava/lang/String;)I", (void *)check}, 431 {"nativeProtect", "(ILjava/lang/String;)V", (void *)protect}, 432}; 433 434int register_android_server_connectivity_Vpn(JNIEnv *env) 435{ 436 return jniRegisterNativeMethods(env, "com/android/server/connectivity/Vpn", 437 gMethods, NELEM(gMethods)); 438} 439 440}; 441