blob: f79254dc2e5a5c202deadead0d5f7cd7ea082dd3 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright 2008, The Android Open Source Project
3 *
Elliott Hughesdd66bcb2011-04-12 11:28:59 -07004 * 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007 *
Elliott Hughesdd66bcb2011-04-12 11:28:59 -07008 * http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009 *
Elliott Hughesdd66bcb2011-04-12 11:28:59 -070010 * 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014 * limitations under the License.
15 */
16
17#define LOG_TAG "NetUtils"
18
19#include "jni.h"
Chad Brubaker12324b42013-07-11 13:30:36 -070020#include "JNIHelp.h"
Paul Jensen38764952014-05-20 11:25:35 -040021#include "NetdClient.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022#include <utils/misc.h>
23#include <android_runtime/AndroidRuntime.h>
24#include <utils/Log.h>
25#include <arpa/inet.h>
Lorenzo Colitticbe4f7c2015-03-06 19:57:39 +090026#include <net/if.h>
27#include <linux/filter.h>
Paul Jensen578a76e2016-01-14 14:54:39 -050028#include <linux/if_arp.h>
Elliott Hughes7691b782016-05-11 15:18:13 -070029#include <netinet/ether.h>
Paul Jensen578a76e2016-01-14 14:54:39 -050030#include <netinet/icmp6.h>
Lorenzo Colitticbe4f7c2015-03-06 19:57:39 +090031#include <netinet/ip.h>
Paul Jensen578a76e2016-01-14 14:54:39 -050032#include <netinet/ip6.h>
Lorenzo Colitticbe4f7c2015-03-06 19:57:39 +090033#include <netinet/udp.h>
Robert Greenwalt0216e612011-01-14 16:29:58 -080034#include <cutils/properties.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035
Andreas Gampe987f79f2014-11-18 17:29:46 -080036#include "core_jni_helpers.h"
37
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038extern "C" {
Mike Lockwood0900f362009-07-10 17:24:07 -040039int ifc_enable(const char *ifname);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040int ifc_disable(const char *ifname);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041}
42
43#define NETUTILS_PKG_NAME "android/net/NetworkUtils"
44
45namespace android {
46
Lorenzo Colitticbe4f7c2015-03-06 19:57:39 +090047static const uint16_t kDhcpClientPort = 68;
48
Lorenzo Colitticbe4f7c2015-03-06 19:57:39 +090049static void android_net_utils_attachDhcpFilter(JNIEnv *env, jobject clazz, jobject javaFd)
50{
Lorenzo Colitticbe4f7c2015-03-06 19:57:39 +090051 uint32_t ip_offset = sizeof(ether_header);
52 uint32_t proto_offset = ip_offset + offsetof(iphdr, protocol);
Paul Jensen578a76e2016-01-14 14:54:39 -050053 uint32_t flags_offset = ip_offset + offsetof(iphdr, frag_off);
Lorenzo Colitticbe4f7c2015-03-06 19:57:39 +090054 uint32_t dport_indirect_offset = ip_offset + offsetof(udphdr, dest);
55 struct sock_filter filter_code[] = {
56 // Check the protocol is UDP.
57 BPF_STMT(BPF_LD | BPF_B | BPF_ABS, proto_offset),
58 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, IPPROTO_UDP, 0, 6),
59
60 // Check this is not a fragment.
61 BPF_STMT(BPF_LD | BPF_H | BPF_ABS, flags_offset),
62 BPF_JUMP(BPF_JMP | BPF_JSET | BPF_K, 0x1fff, 4, 0),
63
64 // Get the IP header length.
65 BPF_STMT(BPF_LDX | BPF_B | BPF_MSH, ip_offset),
66
67 // Check the destination port.
68 BPF_STMT(BPF_LD | BPF_H | BPF_IND, dport_indirect_offset),
69 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, kDhcpClientPort, 0, 1),
70
71 // Accept or reject.
72 BPF_STMT(BPF_RET | BPF_K, 0xffff),
73 BPF_STMT(BPF_RET | BPF_K, 0)
74 };
75 struct sock_fprog filter = {
76 sizeof(filter_code) / sizeof(filter_code[0]),
77 filter_code,
78 };
79
Paul Jensen578a76e2016-01-14 14:54:39 -050080 int fd = jniGetFDFromFileDescriptor(env, javaFd);
81 if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) != 0) {
82 jniThrowExceptionFmt(env, "java/net/SocketException",
83 "setsockopt(SO_ATTACH_FILTER): %s", strerror(errno));
84 }
85}
86
87static void android_net_utils_attachRaFilter(JNIEnv *env, jobject clazz, jobject javaFd,
88 jint hardwareAddressType)
89{
90 if (hardwareAddressType != ARPHRD_ETHER) {
91 jniThrowExceptionFmt(env, "java/net/SocketException",
92 "attachRaFilter only supports ARPHRD_ETHER");
93 return;
94 }
95
96 uint32_t ipv6_offset = sizeof(ether_header);
97 uint32_t ipv6_next_header_offset = ipv6_offset + offsetof(ip6_hdr, ip6_nxt);
98 uint32_t icmp6_offset = ipv6_offset + sizeof(ip6_hdr);
99 uint32_t icmp6_type_offset = icmp6_offset + offsetof(icmp6_hdr, icmp6_type);
100 struct sock_filter filter_code[] = {
101 // Check IPv6 Next Header is ICMPv6.
102 BPF_STMT(BPF_LD | BPF_B | BPF_ABS, ipv6_next_header_offset),
103 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, IPPROTO_ICMPV6, 0, 3),
104
105 // Check ICMPv6 type is Router Advertisement.
106 BPF_STMT(BPF_LD | BPF_B | BPF_ABS, icmp6_type_offset),
107 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ND_ROUTER_ADVERT, 0, 1),
108
109 // Accept or reject.
110 BPF_STMT(BPF_RET | BPF_K, 0xffff),
111 BPF_STMT(BPF_RET | BPF_K, 0)
112 };
113 struct sock_fprog filter = {
114 sizeof(filter_code) / sizeof(filter_code[0]),
115 filter_code,
116 };
117
118 int fd = jniGetFDFromFileDescriptor(env, javaFd);
Lorenzo Colitticbe4f7c2015-03-06 19:57:39 +0900119 if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) != 0) {
120 jniThrowExceptionFmt(env, "java/net/SocketException",
121 "setsockopt(SO_ATTACH_FILTER): %s", strerror(errno));
122 }
123}
124
Paul Jensen32a58f02014-06-20 13:58:14 -0400125static jboolean android_net_utils_bindProcessToNetwork(JNIEnv *env, jobject thiz, jint netId)
Paul Jensen38764952014-05-20 11:25:35 -0400126{
Paul Jensen32a58f02014-06-20 13:58:14 -0400127 return (jboolean) !setNetworkForProcess(netId);
Paul Jensen38764952014-05-20 11:25:35 -0400128}
129
Paul Jensen72db88e2015-03-10 10:54:12 -0400130static jint android_net_utils_getBoundNetworkForProcess(JNIEnv *env, jobject thiz)
Paul Jensen38764952014-05-20 11:25:35 -0400131{
132 return getNetworkForProcess();
133}
134
Paul Jensen32a58f02014-06-20 13:58:14 -0400135static jboolean android_net_utils_bindProcessToNetworkForHostResolution(JNIEnv *env, jobject thiz,
136 jint netId)
Paul Jensen38764952014-05-20 11:25:35 -0400137{
Paul Jensen32a58f02014-06-20 13:58:14 -0400138 return (jboolean) !setNetworkForResolv(netId);
Paul Jensen38764952014-05-20 11:25:35 -0400139}
140
Lorenzo Colitti9f1274b2014-08-21 11:45:54 -0700141static jint android_net_utils_bindSocketToNetwork(JNIEnv *env, jobject thiz, jint socket,
Paul Jensen32a58f02014-06-20 13:58:14 -0400142 jint netId)
Paul Jensen38764952014-05-20 11:25:35 -0400143{
Lorenzo Colitti9f1274b2014-08-21 11:45:54 -0700144 return setNetworkForSocket(netId, socket);
Paul Jensen38764952014-05-20 11:25:35 -0400145}
146
Paul Jensen6bc2c2c2014-05-07 15:27:40 -0400147static jboolean android_net_utils_protectFromVpn(JNIEnv *env, jobject thiz, jint socket)
148{
149 return (jboolean) !protectFromVpn(socket);
150}
151
Paul Jensencee9b512015-05-06 07:32:40 -0400152static jboolean android_net_utils_queryUserAccess(JNIEnv *env, jobject thiz, jint uid, jint netId)
153{
154 return (jboolean) !queryUserAccess(uid, netId);
155}
156
Lorenzo Colitticbe4f7c2015-03-06 19:57:39 +0900157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158// ----------------------------------------------------------------------------
159
160/*
161 * JNI registration.
162 */
Daniel Micay76f6a862015-09-19 17:31:01 -0400163static const JNINativeMethod gNetworkUtilMethods[] = {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 /* name, signature, funcPtr */
Paul Jensen32a58f02014-06-20 13:58:14 -0400165 { "bindProcessToNetwork", "(I)Z", (void*) android_net_utils_bindProcessToNetwork },
Paul Jensen72db88e2015-03-10 10:54:12 -0400166 { "getBoundNetworkForProcess", "()I", (void*) android_net_utils_getBoundNetworkForProcess },
Paul Jensen32a58f02014-06-20 13:58:14 -0400167 { "bindProcessToNetworkForHostResolution", "(I)Z", (void*) android_net_utils_bindProcessToNetworkForHostResolution },
Lorenzo Colitti9f1274b2014-08-21 11:45:54 -0700168 { "bindSocketToNetwork", "(II)I", (void*) android_net_utils_bindSocketToNetwork },
Paul Jensen6bc2c2c2014-05-07 15:27:40 -0400169 { "protectFromVpn", "(I)Z", (void*)android_net_utils_protectFromVpn },
Paul Jensencee9b512015-05-06 07:32:40 -0400170 { "queryUserAccess", "(II)Z", (void*)android_net_utils_queryUserAccess },
Lorenzo Colitticbe4f7c2015-03-06 19:57:39 +0900171 { "attachDhcpFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDhcpFilter },
Paul Jensen578a76e2016-01-14 14:54:39 -0500172 { "attachRaFilter", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_attachRaFilter },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173};
174
175int register_android_net_NetworkUtils(JNIEnv* env)
176{
Andreas Gampe987f79f2014-11-18 17:29:46 -0800177 return RegisterMethodsOrDie(env, NETUTILS_PKG_NAME, gNetworkUtilMethods,
178 NELEM(gNetworkUtilMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179}
180
181}; // namespace android