1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "net/android/network_library.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <dlfcn.h>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include <string>
10*6777b538SAndroid Build Coastguard Worker #include <string_view>
11*6777b538SAndroid Build Coastguard Worker #include <vector>
12*6777b538SAndroid Build Coastguard Worker
13*6777b538SAndroid Build Coastguard Worker #include "base/android/build_info.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/android/jni_android.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/android/jni_array.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/android/jni_string.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/android/scoped_java_ref.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/native_library.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_split.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/threading/scoped_blocking_call.h"
23*6777b538SAndroid Build Coastguard Worker #include "net/base/net_errors.h"
24*6777b538SAndroid Build Coastguard Worker #include "net/dns/public/dns_protocol.h"
25*6777b538SAndroid Build Coastguard Worker #include "net/net_jni_headers/AndroidNetworkLibrary_jni.h"
26*6777b538SAndroid Build Coastguard Worker #include "net/net_jni_headers/DnsStatus_jni.h"
27*6777b538SAndroid Build Coastguard Worker
28*6777b538SAndroid Build Coastguard Worker using base::android::AttachCurrentThread;
29*6777b538SAndroid Build Coastguard Worker using base::android::ConvertJavaStringToUTF8;
30*6777b538SAndroid Build Coastguard Worker using base::android::ConvertUTF8ToJavaString;
31*6777b538SAndroid Build Coastguard Worker using base::android::JavaArrayOfByteArrayToStringVector;
32*6777b538SAndroid Build Coastguard Worker using base::android::ScopedJavaLocalRef;
33*6777b538SAndroid Build Coastguard Worker using base::android::ToJavaArrayOfByteArray;
34*6777b538SAndroid Build Coastguard Worker using base::android::ToJavaByteArray;
35*6777b538SAndroid Build Coastguard Worker
36*6777b538SAndroid Build Coastguard Worker namespace net::android {
37*6777b538SAndroid Build Coastguard Worker
GetUserAddedRoots()38*6777b538SAndroid Build Coastguard Worker std::vector<std::string> GetUserAddedRoots() {
39*6777b538SAndroid Build Coastguard Worker std::vector<std::string> roots;
40*6777b538SAndroid Build Coastguard Worker JNIEnv* env = AttachCurrentThread();
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker ScopedJavaLocalRef<jobjectArray> roots_byte_array =
43*6777b538SAndroid Build Coastguard Worker Java_AndroidNetworkLibrary_getUserAddedRoots(env);
44*6777b538SAndroid Build Coastguard Worker JavaArrayOfByteArrayToStringVector(env, roots_byte_array, &roots);
45*6777b538SAndroid Build Coastguard Worker return roots;
46*6777b538SAndroid Build Coastguard Worker }
47*6777b538SAndroid Build Coastguard Worker
VerifyX509CertChain(const std::vector<std::string> & cert_chain,std::string_view auth_type,std::string_view host,CertVerifyStatusAndroid * status,bool * is_issued_by_known_root,std::vector<std::string> * verified_chain)48*6777b538SAndroid Build Coastguard Worker void VerifyX509CertChain(const std::vector<std::string>& cert_chain,
49*6777b538SAndroid Build Coastguard Worker std::string_view auth_type,
50*6777b538SAndroid Build Coastguard Worker std::string_view host,
51*6777b538SAndroid Build Coastguard Worker CertVerifyStatusAndroid* status,
52*6777b538SAndroid Build Coastguard Worker bool* is_issued_by_known_root,
53*6777b538SAndroid Build Coastguard Worker std::vector<std::string>* verified_chain) {
54*6777b538SAndroid Build Coastguard Worker JNIEnv* env = AttachCurrentThread();
55*6777b538SAndroid Build Coastguard Worker
56*6777b538SAndroid Build Coastguard Worker ScopedJavaLocalRef<jobjectArray> chain_byte_array =
57*6777b538SAndroid Build Coastguard Worker ToJavaArrayOfByteArray(env, cert_chain);
58*6777b538SAndroid Build Coastguard Worker DCHECK(!chain_byte_array.is_null());
59*6777b538SAndroid Build Coastguard Worker
60*6777b538SAndroid Build Coastguard Worker ScopedJavaLocalRef<jstring> auth_string =
61*6777b538SAndroid Build Coastguard Worker ConvertUTF8ToJavaString(env, auth_type);
62*6777b538SAndroid Build Coastguard Worker DCHECK(!auth_string.is_null());
63*6777b538SAndroid Build Coastguard Worker
64*6777b538SAndroid Build Coastguard Worker ScopedJavaLocalRef<jstring> host_string =
65*6777b538SAndroid Build Coastguard Worker ConvertUTF8ToJavaString(env, host);
66*6777b538SAndroid Build Coastguard Worker DCHECK(!host_string.is_null());
67*6777b538SAndroid Build Coastguard Worker
68*6777b538SAndroid Build Coastguard Worker ScopedJavaLocalRef<jobject> result =
69*6777b538SAndroid Build Coastguard Worker Java_AndroidNetworkLibrary_verifyServerCertificates(
70*6777b538SAndroid Build Coastguard Worker env, chain_byte_array, auth_string, host_string);
71*6777b538SAndroid Build Coastguard Worker
72*6777b538SAndroid Build Coastguard Worker ExtractCertVerifyResult(result, status, is_issued_by_known_root,
73*6777b538SAndroid Build Coastguard Worker verified_chain);
74*6777b538SAndroid Build Coastguard Worker }
75*6777b538SAndroid Build Coastguard Worker
AddTestRootCertificate(const uint8_t * cert,size_t len)76*6777b538SAndroid Build Coastguard Worker void AddTestRootCertificate(const uint8_t* cert, size_t len) {
77*6777b538SAndroid Build Coastguard Worker JNIEnv* env = AttachCurrentThread();
78*6777b538SAndroid Build Coastguard Worker ScopedJavaLocalRef<jbyteArray> cert_array = ToJavaByteArray(env, cert, len);
79*6777b538SAndroid Build Coastguard Worker DCHECK(!cert_array.is_null());
80*6777b538SAndroid Build Coastguard Worker Java_AndroidNetworkLibrary_addTestRootCertificate(env, cert_array);
81*6777b538SAndroid Build Coastguard Worker }
82*6777b538SAndroid Build Coastguard Worker
ClearTestRootCertificates()83*6777b538SAndroid Build Coastguard Worker void ClearTestRootCertificates() {
84*6777b538SAndroid Build Coastguard Worker JNIEnv* env = AttachCurrentThread();
85*6777b538SAndroid Build Coastguard Worker Java_AndroidNetworkLibrary_clearTestRootCertificates(env);
86*6777b538SAndroid Build Coastguard Worker }
87*6777b538SAndroid Build Coastguard Worker
IsCleartextPermitted(std::string_view host)88*6777b538SAndroid Build Coastguard Worker bool IsCleartextPermitted(std::string_view host) {
89*6777b538SAndroid Build Coastguard Worker JNIEnv* env = AttachCurrentThread();
90*6777b538SAndroid Build Coastguard Worker ScopedJavaLocalRef<jstring> host_string = ConvertUTF8ToJavaString(env, host);
91*6777b538SAndroid Build Coastguard Worker return Java_AndroidNetworkLibrary_isCleartextPermitted(env, host_string);
92*6777b538SAndroid Build Coastguard Worker }
93*6777b538SAndroid Build Coastguard Worker
HaveOnlyLoopbackAddresses()94*6777b538SAndroid Build Coastguard Worker bool HaveOnlyLoopbackAddresses() {
95*6777b538SAndroid Build Coastguard Worker base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
96*6777b538SAndroid Build Coastguard Worker base::BlockingType::MAY_BLOCK);
97*6777b538SAndroid Build Coastguard Worker JNIEnv* env = AttachCurrentThread();
98*6777b538SAndroid Build Coastguard Worker return Java_AndroidNetworkLibrary_haveOnlyLoopbackAddresses(env);
99*6777b538SAndroid Build Coastguard Worker }
100*6777b538SAndroid Build Coastguard Worker
GetMimeTypeFromExtension(std::string_view extension,std::string * result)101*6777b538SAndroid Build Coastguard Worker bool GetMimeTypeFromExtension(std::string_view extension, std::string* result) {
102*6777b538SAndroid Build Coastguard Worker JNIEnv* env = AttachCurrentThread();
103*6777b538SAndroid Build Coastguard Worker
104*6777b538SAndroid Build Coastguard Worker ScopedJavaLocalRef<jstring> extension_string =
105*6777b538SAndroid Build Coastguard Worker ConvertUTF8ToJavaString(env, extension);
106*6777b538SAndroid Build Coastguard Worker ScopedJavaLocalRef<jstring> ret =
107*6777b538SAndroid Build Coastguard Worker Java_AndroidNetworkLibrary_getMimeTypeFromExtension(env,
108*6777b538SAndroid Build Coastguard Worker extension_string);
109*6777b538SAndroid Build Coastguard Worker
110*6777b538SAndroid Build Coastguard Worker if (!ret.obj())
111*6777b538SAndroid Build Coastguard Worker return false;
112*6777b538SAndroid Build Coastguard Worker *result = ConvertJavaStringToUTF8(ret);
113*6777b538SAndroid Build Coastguard Worker return true;
114*6777b538SAndroid Build Coastguard Worker }
115*6777b538SAndroid Build Coastguard Worker
GetTelephonyNetworkOperator()116*6777b538SAndroid Build Coastguard Worker std::string GetTelephonyNetworkOperator() {
117*6777b538SAndroid Build Coastguard Worker return base::android::ConvertJavaStringToUTF8(
118*6777b538SAndroid Build Coastguard Worker Java_AndroidNetworkLibrary_getNetworkOperator(
119*6777b538SAndroid Build Coastguard Worker base::android::AttachCurrentThread()));
120*6777b538SAndroid Build Coastguard Worker }
121*6777b538SAndroid Build Coastguard Worker
GetIsRoaming()122*6777b538SAndroid Build Coastguard Worker bool GetIsRoaming() {
123*6777b538SAndroid Build Coastguard Worker return Java_AndroidNetworkLibrary_getIsRoaming(
124*6777b538SAndroid Build Coastguard Worker base::android::AttachCurrentThread());
125*6777b538SAndroid Build Coastguard Worker }
126*6777b538SAndroid Build Coastguard Worker
GetIsCaptivePortal()127*6777b538SAndroid Build Coastguard Worker bool GetIsCaptivePortal() {
128*6777b538SAndroid Build Coastguard Worker return Java_AndroidNetworkLibrary_getIsCaptivePortal(
129*6777b538SAndroid Build Coastguard Worker base::android::AttachCurrentThread());
130*6777b538SAndroid Build Coastguard Worker }
131*6777b538SAndroid Build Coastguard Worker
GetWifiSSID()132*6777b538SAndroid Build Coastguard Worker std::string GetWifiSSID() {
133*6777b538SAndroid Build Coastguard Worker return base::android::ConvertJavaStringToUTF8(
134*6777b538SAndroid Build Coastguard Worker Java_AndroidNetworkLibrary_getWifiSSID(
135*6777b538SAndroid Build Coastguard Worker base::android::AttachCurrentThread()));
136*6777b538SAndroid Build Coastguard Worker }
137*6777b538SAndroid Build Coastguard Worker
SetWifiEnabledForTesting(bool enabled)138*6777b538SAndroid Build Coastguard Worker void SetWifiEnabledForTesting(bool enabled) {
139*6777b538SAndroid Build Coastguard Worker Java_AndroidNetworkLibrary_setWifiEnabledForTesting(
140*6777b538SAndroid Build Coastguard Worker base::android::AttachCurrentThread(), enabled);
141*6777b538SAndroid Build Coastguard Worker }
142*6777b538SAndroid Build Coastguard Worker
GetWifiSignalLevel()143*6777b538SAndroid Build Coastguard Worker std::optional<int32_t> GetWifiSignalLevel() {
144*6777b538SAndroid Build Coastguard Worker const int count_buckets = 5;
145*6777b538SAndroid Build Coastguard Worker int signal_strength = Java_AndroidNetworkLibrary_getWifiSignalLevel(
146*6777b538SAndroid Build Coastguard Worker base::android::AttachCurrentThread(), count_buckets);
147*6777b538SAndroid Build Coastguard Worker if (signal_strength < 0)
148*6777b538SAndroid Build Coastguard Worker return std::nullopt;
149*6777b538SAndroid Build Coastguard Worker DCHECK_LE(0, signal_strength);
150*6777b538SAndroid Build Coastguard Worker DCHECK_GE(count_buckets - 1, signal_strength);
151*6777b538SAndroid Build Coastguard Worker
152*6777b538SAndroid Build Coastguard Worker return signal_strength;
153*6777b538SAndroid Build Coastguard Worker }
154*6777b538SAndroid Build Coastguard Worker
155*6777b538SAndroid Build Coastguard Worker namespace {
156*6777b538SAndroid Build Coastguard Worker
GetDnsServersInternal(JNIEnv * env,const base::android::JavaRef<jobject> & dns_status,std::vector<IPEndPoint> * dns_servers,bool * dns_over_tls_active,std::string * dns_over_tls_hostname,std::vector<std::string> * search_suffixes)157*6777b538SAndroid Build Coastguard Worker bool GetDnsServersInternal(JNIEnv* env,
158*6777b538SAndroid Build Coastguard Worker const base::android::JavaRef<jobject>& dns_status,
159*6777b538SAndroid Build Coastguard Worker std::vector<IPEndPoint>* dns_servers,
160*6777b538SAndroid Build Coastguard Worker bool* dns_over_tls_active,
161*6777b538SAndroid Build Coastguard Worker std::string* dns_over_tls_hostname,
162*6777b538SAndroid Build Coastguard Worker std::vector<std::string>* search_suffixes) {
163*6777b538SAndroid Build Coastguard Worker // Parse the DNS servers.
164*6777b538SAndroid Build Coastguard Worker std::vector<std::vector<uint8_t>> dns_servers_data;
165*6777b538SAndroid Build Coastguard Worker base::android::JavaArrayOfByteArrayToBytesVector(
166*6777b538SAndroid Build Coastguard Worker env, Java_DnsStatus_getDnsServers(env, dns_status), &dns_servers_data);
167*6777b538SAndroid Build Coastguard Worker for (const std::vector<uint8_t>& dns_address_data : dns_servers_data) {
168*6777b538SAndroid Build Coastguard Worker IPAddress dns_address(dns_address_data);
169*6777b538SAndroid Build Coastguard Worker IPEndPoint dns_server(dns_address, dns_protocol::kDefaultPort);
170*6777b538SAndroid Build Coastguard Worker dns_servers->push_back(dns_server);
171*6777b538SAndroid Build Coastguard Worker }
172*6777b538SAndroid Build Coastguard Worker
173*6777b538SAndroid Build Coastguard Worker *dns_over_tls_active = Java_DnsStatus_getPrivateDnsActive(env, dns_status);
174*6777b538SAndroid Build Coastguard Worker *dns_over_tls_hostname = base::android::ConvertJavaStringToUTF8(
175*6777b538SAndroid Build Coastguard Worker Java_DnsStatus_getPrivateDnsServerName(env, dns_status));
176*6777b538SAndroid Build Coastguard Worker
177*6777b538SAndroid Build Coastguard Worker std::string search_suffixes_str = base::android::ConvertJavaStringToUTF8(
178*6777b538SAndroid Build Coastguard Worker Java_DnsStatus_getSearchDomains(env, dns_status));
179*6777b538SAndroid Build Coastguard Worker *search_suffixes =
180*6777b538SAndroid Build Coastguard Worker base::SplitString(search_suffixes_str, ",", base::TRIM_WHITESPACE,
181*6777b538SAndroid Build Coastguard Worker base::SPLIT_WANT_NONEMPTY);
182*6777b538SAndroid Build Coastguard Worker
183*6777b538SAndroid Build Coastguard Worker return !dns_servers->empty();
184*6777b538SAndroid Build Coastguard Worker }
185*6777b538SAndroid Build Coastguard Worker
186*6777b538SAndroid Build Coastguard Worker } // namespace
187*6777b538SAndroid Build Coastguard Worker
GetCurrentDnsServers(std::vector<IPEndPoint> * dns_servers,bool * dns_over_tls_active,std::string * dns_over_tls_hostname,std::vector<std::string> * search_suffixes)188*6777b538SAndroid Build Coastguard Worker bool GetCurrentDnsServers(std::vector<IPEndPoint>* dns_servers,
189*6777b538SAndroid Build Coastguard Worker bool* dns_over_tls_active,
190*6777b538SAndroid Build Coastguard Worker std::string* dns_over_tls_hostname,
191*6777b538SAndroid Build Coastguard Worker std::vector<std::string>* search_suffixes) {
192*6777b538SAndroid Build Coastguard Worker DCHECK_GE(base::android::BuildInfo::GetInstance()->sdk_int(),
193*6777b538SAndroid Build Coastguard Worker base::android::SDK_VERSION_MARSHMALLOW);
194*6777b538SAndroid Build Coastguard Worker
195*6777b538SAndroid Build Coastguard Worker JNIEnv* env = AttachCurrentThread();
196*6777b538SAndroid Build Coastguard Worker // Get the DNS status for the current default network.
197*6777b538SAndroid Build Coastguard Worker ScopedJavaLocalRef<jobject> result =
198*6777b538SAndroid Build Coastguard Worker Java_AndroidNetworkLibrary_getCurrentDnsStatus(env);
199*6777b538SAndroid Build Coastguard Worker if (result.is_null())
200*6777b538SAndroid Build Coastguard Worker return false;
201*6777b538SAndroid Build Coastguard Worker return GetDnsServersInternal(env, result, dns_servers, dns_over_tls_active,
202*6777b538SAndroid Build Coastguard Worker dns_over_tls_hostname, search_suffixes);
203*6777b538SAndroid Build Coastguard Worker }
204*6777b538SAndroid Build Coastguard Worker
GetDnsServersForNetwork(std::vector<IPEndPoint> * dns_servers,bool * dns_over_tls_active,std::string * dns_over_tls_hostname,std::vector<std::string> * search_suffixes,handles::NetworkHandle network)205*6777b538SAndroid Build Coastguard Worker bool GetDnsServersForNetwork(std::vector<IPEndPoint>* dns_servers,
206*6777b538SAndroid Build Coastguard Worker bool* dns_over_tls_active,
207*6777b538SAndroid Build Coastguard Worker std::string* dns_over_tls_hostname,
208*6777b538SAndroid Build Coastguard Worker std::vector<std::string>* search_suffixes,
209*6777b538SAndroid Build Coastguard Worker handles::NetworkHandle network) {
210*6777b538SAndroid Build Coastguard Worker DCHECK_GE(base::android::BuildInfo::GetInstance()->sdk_int(),
211*6777b538SAndroid Build Coastguard Worker base::android::SDK_VERSION_P);
212*6777b538SAndroid Build Coastguard Worker
213*6777b538SAndroid Build Coastguard Worker JNIEnv* env = AttachCurrentThread();
214*6777b538SAndroid Build Coastguard Worker ScopedJavaLocalRef<jobject> result =
215*6777b538SAndroid Build Coastguard Worker Java_AndroidNetworkLibrary_getDnsStatusForNetwork(env, network);
216*6777b538SAndroid Build Coastguard Worker if (result.is_null())
217*6777b538SAndroid Build Coastguard Worker return false;
218*6777b538SAndroid Build Coastguard Worker return GetDnsServersInternal(env, result, dns_servers, dns_over_tls_active,
219*6777b538SAndroid Build Coastguard Worker dns_over_tls_hostname, search_suffixes);
220*6777b538SAndroid Build Coastguard Worker }
221*6777b538SAndroid Build Coastguard Worker
ReportBadDefaultNetwork()222*6777b538SAndroid Build Coastguard Worker bool ReportBadDefaultNetwork() {
223*6777b538SAndroid Build Coastguard Worker return Java_AndroidNetworkLibrary_reportBadDefaultNetwork(
224*6777b538SAndroid Build Coastguard Worker AttachCurrentThread());
225*6777b538SAndroid Build Coastguard Worker }
226*6777b538SAndroid Build Coastguard Worker
TagSocket(SocketDescriptor socket,uid_t uid,int32_t tag)227*6777b538SAndroid Build Coastguard Worker void TagSocket(SocketDescriptor socket, uid_t uid, int32_t tag) {
228*6777b538SAndroid Build Coastguard Worker Java_AndroidNetworkLibrary_tagSocket(AttachCurrentThread(), socket, uid, tag);
229*6777b538SAndroid Build Coastguard Worker }
230*6777b538SAndroid Build Coastguard Worker
231*6777b538SAndroid Build Coastguard Worker namespace {
232*6777b538SAndroid Build Coastguard Worker
233*6777b538SAndroid Build Coastguard Worker using LollipopSetNetworkForSocket = int (*)(unsigned net_id, int socket_fd);
234*6777b538SAndroid Build Coastguard Worker using MarshmallowSetNetworkForSocket = int (*)(int64_t net_id, int socket_fd);
235*6777b538SAndroid Build Coastguard Worker
GetMarshmallowSetNetworkForSocket()236*6777b538SAndroid Build Coastguard Worker MarshmallowSetNetworkForSocket GetMarshmallowSetNetworkForSocket() {
237*6777b538SAndroid Build Coastguard Worker // On Android M and newer releases use supported NDK API.
238*6777b538SAndroid Build Coastguard Worker base::FilePath file(base::GetNativeLibraryName("android"));
239*6777b538SAndroid Build Coastguard Worker // See declaration of android_setsocknetwork() here:
240*6777b538SAndroid Build Coastguard Worker // http://androidxref.com/6.0.0_r1/xref/development/ndk/platforms/android-M/include/android/multinetwork.h#65
241*6777b538SAndroid Build Coastguard Worker // Function cannot be called directly as it will cause app to fail to load on
242*6777b538SAndroid Build Coastguard Worker // pre-marshmallow devices.
243*6777b538SAndroid Build Coastguard Worker void* dl = dlopen(file.value().c_str(), RTLD_NOW);
244*6777b538SAndroid Build Coastguard Worker return reinterpret_cast<MarshmallowSetNetworkForSocket>(
245*6777b538SAndroid Build Coastguard Worker dlsym(dl, "android_setsocknetwork"));
246*6777b538SAndroid Build Coastguard Worker }
247*6777b538SAndroid Build Coastguard Worker
GetLollipopSetNetworkForSocket()248*6777b538SAndroid Build Coastguard Worker LollipopSetNetworkForSocket GetLollipopSetNetworkForSocket() {
249*6777b538SAndroid Build Coastguard Worker // On Android L use setNetworkForSocket from libnetd_client.so. Android's netd
250*6777b538SAndroid Build Coastguard Worker // client library should always be loaded in our address space as it shims
251*6777b538SAndroid Build Coastguard Worker // socket().
252*6777b538SAndroid Build Coastguard Worker base::FilePath file(base::GetNativeLibraryName("netd_client"));
253*6777b538SAndroid Build Coastguard Worker // Use RTLD_NOW to match Android's prior loading of the library:
254*6777b538SAndroid Build Coastguard Worker // http://androidxref.com/6.0.0_r5/xref/bionic/libc/bionic/NetdClient.cpp#37
255*6777b538SAndroid Build Coastguard Worker // Use RTLD_NOLOAD to assert that the library is already loaded and avoid
256*6777b538SAndroid Build Coastguard Worker // doing any disk IO.
257*6777b538SAndroid Build Coastguard Worker void* dl = dlopen(file.value().c_str(), RTLD_NOW | RTLD_NOLOAD);
258*6777b538SAndroid Build Coastguard Worker return reinterpret_cast<LollipopSetNetworkForSocket>(
259*6777b538SAndroid Build Coastguard Worker dlsym(dl, "setNetworkForSocket"));
260*6777b538SAndroid Build Coastguard Worker }
261*6777b538SAndroid Build Coastguard Worker
262*6777b538SAndroid Build Coastguard Worker } // namespace
263*6777b538SAndroid Build Coastguard Worker
BindToNetwork(SocketDescriptor socket,handles::NetworkHandle network)264*6777b538SAndroid Build Coastguard Worker int BindToNetwork(SocketDescriptor socket, handles::NetworkHandle network) {
265*6777b538SAndroid Build Coastguard Worker DCHECK_NE(socket, kInvalidSocket);
266*6777b538SAndroid Build Coastguard Worker if (network == handles::kInvalidNetworkHandle)
267*6777b538SAndroid Build Coastguard Worker return ERR_INVALID_ARGUMENT;
268*6777b538SAndroid Build Coastguard Worker
269*6777b538SAndroid Build Coastguard Worker // Android prior to Lollipop didn't have support for binding sockets to
270*6777b538SAndroid Build Coastguard Worker // networks.
271*6777b538SAndroid Build Coastguard Worker if (base::android::BuildInfo::GetInstance()->sdk_int() <
272*6777b538SAndroid Build Coastguard Worker base::android::SDK_VERSION_LOLLIPOP)
273*6777b538SAndroid Build Coastguard Worker return ERR_NOT_IMPLEMENTED;
274*6777b538SAndroid Build Coastguard Worker
275*6777b538SAndroid Build Coastguard Worker int rv;
276*6777b538SAndroid Build Coastguard Worker if (base::android::BuildInfo::GetInstance()->sdk_int() >=
277*6777b538SAndroid Build Coastguard Worker base::android::SDK_VERSION_MARSHMALLOW) {
278*6777b538SAndroid Build Coastguard Worker static MarshmallowSetNetworkForSocket marshmallow_set_network_for_socket =
279*6777b538SAndroid Build Coastguard Worker GetMarshmallowSetNetworkForSocket();
280*6777b538SAndroid Build Coastguard Worker if (!marshmallow_set_network_for_socket)
281*6777b538SAndroid Build Coastguard Worker return ERR_NOT_IMPLEMENTED;
282*6777b538SAndroid Build Coastguard Worker rv = marshmallow_set_network_for_socket(network, socket);
283*6777b538SAndroid Build Coastguard Worker if (rv)
284*6777b538SAndroid Build Coastguard Worker rv = errno;
285*6777b538SAndroid Build Coastguard Worker } else {
286*6777b538SAndroid Build Coastguard Worker static LollipopSetNetworkForSocket lollipop_set_network_for_socket =
287*6777b538SAndroid Build Coastguard Worker GetLollipopSetNetworkForSocket();
288*6777b538SAndroid Build Coastguard Worker if (!lollipop_set_network_for_socket)
289*6777b538SAndroid Build Coastguard Worker return ERR_NOT_IMPLEMENTED;
290*6777b538SAndroid Build Coastguard Worker rv = -lollipop_set_network_for_socket(network, socket);
291*6777b538SAndroid Build Coastguard Worker }
292*6777b538SAndroid Build Coastguard Worker // If |network| has since disconnected, |rv| will be ENONET. Surface this as
293*6777b538SAndroid Build Coastguard Worker // ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back
294*6777b538SAndroid Build Coastguard Worker // the less descriptive ERR_FAILED.
295*6777b538SAndroid Build Coastguard Worker if (rv == ENONET)
296*6777b538SAndroid Build Coastguard Worker return ERR_NETWORK_CHANGED;
297*6777b538SAndroid Build Coastguard Worker return MapSystemError(rv);
298*6777b538SAndroid Build Coastguard Worker }
299*6777b538SAndroid Build Coastguard Worker
300*6777b538SAndroid Build Coastguard Worker namespace {
301*6777b538SAndroid Build Coastguard Worker
302*6777b538SAndroid Build Coastguard Worker using MarshmallowGetAddrInfoForNetwork = int (*)(int64_t network,
303*6777b538SAndroid Build Coastguard Worker const char* node,
304*6777b538SAndroid Build Coastguard Worker const char* service,
305*6777b538SAndroid Build Coastguard Worker const struct addrinfo* hints,
306*6777b538SAndroid Build Coastguard Worker struct addrinfo** res);
307*6777b538SAndroid Build Coastguard Worker
GetMarshmallowGetAddrInfoForNetwork()308*6777b538SAndroid Build Coastguard Worker MarshmallowGetAddrInfoForNetwork GetMarshmallowGetAddrInfoForNetwork() {
309*6777b538SAndroid Build Coastguard Worker // On Android M and newer releases use supported NDK API.
310*6777b538SAndroid Build Coastguard Worker base::FilePath file(base::GetNativeLibraryName("android"));
311*6777b538SAndroid Build Coastguard Worker // See declaration of android_getaddrinfofornetwork() here:
312*6777b538SAndroid Build Coastguard Worker // https://developer.android.com/ndk/reference/group/networking#android_getaddrinfofornetwork
313*6777b538SAndroid Build Coastguard Worker // Function cannot be called directly as it will cause app to fail to load on
314*6777b538SAndroid Build Coastguard Worker // pre-marshmallow devices.
315*6777b538SAndroid Build Coastguard Worker void* dl = dlopen(file.value().c_str(), RTLD_NOW);
316*6777b538SAndroid Build Coastguard Worker return reinterpret_cast<MarshmallowGetAddrInfoForNetwork>(
317*6777b538SAndroid Build Coastguard Worker dlsym(dl, "android_getaddrinfofornetwork"));
318*6777b538SAndroid Build Coastguard Worker }
319*6777b538SAndroid Build Coastguard Worker
320*6777b538SAndroid Build Coastguard Worker } // namespace
321*6777b538SAndroid Build Coastguard Worker
GetAddrInfoForNetwork(handles::NetworkHandle network,const char * node,const char * service,const struct addrinfo * hints,struct addrinfo ** res)322*6777b538SAndroid Build Coastguard Worker NET_EXPORT_PRIVATE int GetAddrInfoForNetwork(handles::NetworkHandle network,
323*6777b538SAndroid Build Coastguard Worker const char* node,
324*6777b538SAndroid Build Coastguard Worker const char* service,
325*6777b538SAndroid Build Coastguard Worker const struct addrinfo* hints,
326*6777b538SAndroid Build Coastguard Worker struct addrinfo** res) {
327*6777b538SAndroid Build Coastguard Worker if (network == handles::kInvalidNetworkHandle) {
328*6777b538SAndroid Build Coastguard Worker errno = EINVAL;
329*6777b538SAndroid Build Coastguard Worker return EAI_SYSTEM;
330*6777b538SAndroid Build Coastguard Worker }
331*6777b538SAndroid Build Coastguard Worker if (base::android::BuildInfo::GetInstance()->sdk_int() <
332*6777b538SAndroid Build Coastguard Worker base::android::SDK_VERSION_MARSHMALLOW) {
333*6777b538SAndroid Build Coastguard Worker errno = ENOSYS;
334*6777b538SAndroid Build Coastguard Worker return EAI_SYSTEM;
335*6777b538SAndroid Build Coastguard Worker }
336*6777b538SAndroid Build Coastguard Worker
337*6777b538SAndroid Build Coastguard Worker static MarshmallowGetAddrInfoForNetwork get_addrinfo_for_network =
338*6777b538SAndroid Build Coastguard Worker GetMarshmallowGetAddrInfoForNetwork();
339*6777b538SAndroid Build Coastguard Worker if (!get_addrinfo_for_network) {
340*6777b538SAndroid Build Coastguard Worker errno = ENOSYS;
341*6777b538SAndroid Build Coastguard Worker return EAI_SYSTEM;
342*6777b538SAndroid Build Coastguard Worker }
343*6777b538SAndroid Build Coastguard Worker
344*6777b538SAndroid Build Coastguard Worker return get_addrinfo_for_network(network, node, service, hints, res);
345*6777b538SAndroid Build Coastguard Worker }
346*6777b538SAndroid Build Coastguard Worker
347*6777b538SAndroid Build Coastguard Worker } // namespace net::android
348