xref: /aosp_15_r20/external/cronet/net/android/network_library.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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