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