intmain(){ Stopwatch s; gLog.info("netd 1.0 starting"); ... // Make sure BPF programs are loaded before doing anything android::bpf::waitForProgsLoaded(); gLog.info("BPF programs are loaded"); ... // Set local DNS mode, to prevent bionic from proxying // back to this service, recursively. // TODO: Check if we could remove it since resolver cache no loger // checks this environment variable after aosp/838050. setenv("ANDROID_DNS_MODE", "local", 1); // Note that only call initDnsResolver after gCtls initializing. if (!initDnsResolver()) { ALOGE("Unable to init resolver"); exit(1); }
MDnsSdListener mdnsl; if (mdnsl.startListener()) { ALOGE("Unable to start MDnsSdListener (%s)", strerror(errno)); exit(1); }
FwmarkServer fwmarkServer(&gCtls->netCtrl, &gCtls->eventReporter, &gCtls->trafficCtrl); if (fwmarkServer.startListener()) { ALOGE("Unable to start FwmarkServer (%s)", strerror(errno)); exit(1); }
/* The implementation is always dual stack IPv6/IPv4 on android */ staticfinalInetAddressImplimpl=newInet6AddressImpl(); ... publicstatic InetAddress[] getAllByName(String host) throws UnknownHostException { // Android-changed: Resolves a hostname using Libcore.os. // Also, returns both the Inet4 and Inet6 loopback for null/empty host return impl.lookupAllHostAddr(host, NETID_UNSET).clone(); }
/** * Resolves a hostname to its IP addresses using a cache. */ privatestatic InetAddress[] lookupHostByName(String host, int netId) throws UnknownHostException { BlockGuard.getThreadPolicy().onNetwork(); // Do we have a result cached? ObjectcachedResult= addressCache.get(host, netId); if (cachedResult != null) { if (cachedResult instanceof InetAddress[]) { // A cached positive result. return (InetAddress[]) cachedResult; } else { // A cached negative result. thrownewUnknownHostException((String) cachedResult); } } try { StructAddrinfohints=newStructAddrinfo(); hints.ai_flags = AI_ADDRCONFIG; hints.ai_family = AF_UNSPEC; // If we don't specify a socket type, every address will appear twice, once // for SOCK_STREAM and one for SOCK_DGRAM. Since we do not return the family // anyway, just pick one. hints.ai_socktype = SOCK_STREAM; InetAddress[] addresses = Libcore.os.android_getaddrinfo(host, hints, netId); // TODO: should getaddrinfo set the hostname of the InetAddresses it returns? for (InetAddress address : addresses) { address.holder().hostName = host; address.holder().originalHostName = host; } addressCache.put(host, netId, addresses); return addresses; } catch (GaiException gaiException) { ... } }
// Count results so we know how to size the output array. int addressCount = 0; for (addrinfo* ai = addressList; ai != NULL; ai = ai->ai_next) { if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) { ++addressCount; } else { ALOGE("android_getaddrinfo unexpected ai_family %i", ai->ai_family); } } ... // Prepare output array. jobjectArray result = env->NewObjectArray(addressCount, JniConstants::GetInetAddressClass(env), NULL); if (result == NULL) { returnNULL; }
// Examine returned addresses one by one, save them in the output array. int index = 0; for (addrinfo* ai = addressList; ai != NULL; ai = ai->ai_next) { if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) { // Unknown address family. Skip this address. ALOGE("android_getaddrinfo unexpected ai_family %i", ai->ai_family); continue; }
// Convert each IP address into a Java byte array. sockaddr_storage& address = *reinterpret_cast<sockaddr_storage*>(ai->ai_addr); ScopedLocalRef<jobject> inetAddress(env, sockaddrToInetAddress(env, address, NULL)); if (inetAddress.get() == NULL) { returnNULL; } env->SetObjectArrayElement(result, index, inetAddress.get()); ++index; } return result; }
// Returns 0 on success, else returns on error. staticintandroid_getaddrinfo_proxy( constchar *hostname, constchar *servname, conststruct addrinfo *hints, struct addrinfo **res, unsigned netid) { int success = 0;
// Clear this at start, as we use its non-NULLness later (in the // error path) to decide if we have to free up any memory we // allocated in the process (before failing). *res = NULL; ...
// struct addrinfo { // int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */ // int ai_family; /* PF_xxx */ // int ai_socktype; /* SOCK_xxx */ // int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ // socklen_t ai_addrlen; /* length of ai_addr */ // char *ai_canonname; /* canonical name for hostname */ // struct sockaddr *ai_addr; /* binary address */ // struct addrinfo *ai_next; /* next structure in linked list */ // };
// Read the struct piece by piece because we might be a 32-bit process // talking to a 64-bit netd. int32_t addr_len; bool success = readBE32(proxy, &ai->ai_flags) && readBE32(proxy, &ai->ai_family) && readBE32(proxy, &ai->ai_socktype) && readBE32(proxy, &ai->ai_protocol) && readBE32(proxy, &addr_len); if (!success) { break; }
// Set ai_addrlen and read the ai_addr data. ai->ai_addrlen = addr_len; if (addr_len != 0) { if ((size_t) addr_len > sizeof(struct sockaddr_storage)) { // Bogus; too big. break; } if (fread(ai->ai_addr, addr_len, 1, proxy) != 1) { break; } } ... }
if (ai != NULL) { // Clean up partially-built addrinfo that we never ended up // attaching to the response. freeaddrinfo(ai); } ... }
// 更新DNS配置 updateDnses(newLp, oldLp, netId); // Make sure LinkProperties represents the latest private DNS status. // This does not need to be done before updateDnses because the // LinkProperties are not the source of the private DNS configuration. // updateDnses will fetch the private DNS configuration from DnsManager. mDnsManager.updatePrivateDnsStatus(netId, newLp);
if (isDefaultNetwork(networkAgent)) { handleApplyDefaultProxy(newLp.getHttpProxy()); } else { updateProxy(newLp, oldLp); }
updateWakeOnLan(newLp);
// Captive portal data is obtained from NetworkMonitor and stored in NetworkAgentInfo. // It is not always contained in the LinkProperties sent from NetworkAgents, and if it // does, it needs to be merged here. newLp.setCaptivePortalData(mergeCaptivePortalData(networkAgent.networkAgentPortalData, networkAgent.capportApiData)); ... }
/** * Flush DNS caches and events work before boot has completed. */ publicvoidflushVmDnsCache() { /* * Tell the VMs to toss their DNS caches */ finalIntentintent=newIntent(ConnectivityManager.ACTION_CLEAR_DNS_CACHE); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); /* * Connectivity events can happen before boot has completed ... */ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); finallongident= Binder.clearCallingIdentity(); try { mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } finally { Binder.restoreCallingIdentity(ident); } }
publicvoidclearDnsCache() { // a non-standard API to get this to libcore InetAddress.clearDnsCache(); // Allow libcore to perform the necessary actions as it sees fit upon a network // configuration change. NetworkEventDispatcher.getInstance().dispatchNetworkConfigurationChange(); }
privatevoiddestroyNetwork(NetworkAgentInfo nai) { if (nai.created) { // Tell netd to clean up the configuration for this network // (routing rules, DNS, etc). // This may be slow as it requires a lot of netd shelling out to ip and // ip[6]tables to flush routes and remove the incoming packet mark rule, so do it // after we've rematched networks with requests (which might change the default // network or service a new request from an app), so network traffic isn't interrupted // for an unnecessarily long time. destroyNativeNetwork(nai); mDnsManager.removeNetwork(nai.network); } mNetIdManager.releaseNetId(nai.network.getNetId()); nai.onNetworkDestroyed(); }