Path: blob/master/src/java.base/windows/native/libnet/ResolverConfigurationImpl.c
41119 views
/*1* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <stdlib.h>26#include <stdio.h>27#include <stddef.h>28#include <time.h>29#include <assert.h>3031#include "net_util.h"32#include "jni_util.h"3334#define MAX_STR_LEN 10243536#define STS_NO_CONFIG 0x0 /* no configuration found */37#define STS_SL_FOUND 0x1 /* search list found */38#define STS_NS_FOUND 0x2 /* name servers found */39#define STS_ERROR -1 /* error return lodConfig failed memory allccation failure*/4041#define IS_SL_FOUND(sts) (sts & STS_SL_FOUND)42#define IS_NS_FOUND(sts) (sts & STS_NS_FOUND)4344/* JNI ids */45static jfieldID searchlistID;46static jfieldID nameserversID;4748extern int getAdapters(JNIEnv *env, int flags, IP_ADAPTER_ADDRESSES **adapters);4950/*51* Utility routine to append s2 to s1 with a comma delimiter.52* strappend(s1="abc", "def") => "abc,def"53* strappend(s1="", "def") => "def54*/55void strappend(char *s1, char *s2) {56size_t len;5758if (s2[0] == '\0') /* nothing to append */59return;6061len = strlen(s1)+1;62if (s1[0] != 0) /* needs comma character */63len++;64if (len + strlen(s2) > MAX_STR_LEN) /* insufficient space */65return;6667if (s1[0] != 0) {68strcat(s1, ",");69}70strcat(s1, s2);71}7273/*74* Use DNS server addresses returned by GetAdaptersAddresses for currently75* active interfaces.76*/77static int loadConfig(JNIEnv *env, char *sl, char *ns) {78IP_ADAPTER_ADDRESSES *adapters, *adapter;79IP_ADAPTER_DNS_SERVER_ADDRESS *dnsServer;80WCHAR *suffix;81DWORD ret, flags;82DWORD dwLen;83ULONG ulType;84char result[MAX_STR_LEN];85HANDLE hKey;86SOCKADDR *sockAddr;87struct sockaddr_in6 *sockAddrIpv6;8889/*90* First see if there is a global suffix list specified.91*/92ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,93"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",940,95KEY_READ,96(PHKEY)&hKey);97if (ret == ERROR_SUCCESS) {98dwLen = sizeof(result);99ret = RegQueryValueEx(hKey, "SearchList", NULL, &ulType,100(LPBYTE)&result, &dwLen);101if (ret == ERROR_SUCCESS) {102assert(ulType == REG_SZ);103if (strlen(result) > 0) {104strappend(sl, result);105}106}107RegCloseKey(hKey);108}109110111// We only need DNS server addresses so skip everything else.112flags = GAA_FLAG_SKIP_UNICAST;113flags |= GAA_FLAG_SKIP_ANYCAST;114flags |= GAA_FLAG_SKIP_MULTICAST;115flags |= GAA_FLAG_SKIP_FRIENDLY_NAME;116ret = getAdapters(env, flags, &adapters);117118if (ret != ERROR_SUCCESS) {119return STS_ERROR;120}121122adapter = adapters;123while (adapter != NULL) {124// Only load config from enabled adapters.125if (adapter->OperStatus == IfOperStatusUp) {126dnsServer = adapter->FirstDnsServerAddress;127while (dnsServer != NULL) {128sockAddr = dnsServer->Address.lpSockaddr;129if (sockAddr->sa_family == AF_INET6) {130sockAddrIpv6 = (struct sockaddr_in6 *)sockAddr;131if (sockAddrIpv6->sin6_scope_id != 0) {132// An address with a scope is either link-local or133// site-local, which aren't valid for DNS queries so134// we can skip them.135dnsServer = dnsServer->Next;136continue;137}138}139140dwLen = sizeof(result);141ret = WSAAddressToStringA(sockAddr,142dnsServer->Address.iSockaddrLength, NULL,143result, &dwLen);144if (ret == 0) {145strappend(ns, result);146}147148dnsServer = dnsServer->Next;149}150151// Add connection-specific search domains in addition to global one.152suffix = adapter->DnsSuffix;153if (suffix != NULL) {154ret = WideCharToMultiByte(CP_UTF8, 0, suffix, -1,155result, sizeof(result), NULL, NULL);156if (ret != 0) {157strappend(sl, result);158}159}160}161162adapter = adapter->Next;163}164165free(adapters);166167return STS_SL_FOUND & STS_NS_FOUND;168}169170171/*172* Initialize JNI field IDs and classes.173*/174JNIEXPORT void JNICALL175Java_sun_net_dns_ResolverConfigurationImpl_init0(JNIEnv *env, jclass cls)176{177searchlistID = (*env)->GetStaticFieldID(env, cls, "os_searchlist",178"Ljava/lang/String;");179CHECK_NULL(searchlistID);180nameserversID = (*env)->GetStaticFieldID(env, cls, "os_nameservers",181"Ljava/lang/String;");182}183184/*185* Class: sun_net_dns_ResolverConfgurationImpl186* Method: loadConfig0187* Signature: ()V188*/189JNIEXPORT void JNICALL190Java_sun_net_dns_ResolverConfigurationImpl_loadDNSconfig0(JNIEnv *env, jclass cls)191{192char searchlist[MAX_STR_LEN];193char nameservers[MAX_STR_LEN];194jstring obj;195196searchlist[0] = '\0';197nameservers[0] = '\0';198199if (loadConfig(env, searchlist, nameservers) != STS_ERROR) {200201/*202* Populate static fields in sun.net.DefaultResolverConfiguration203*/204obj = (*env)->NewStringUTF(env, searchlist);205CHECK_NULL(obj);206(*env)->SetStaticObjectField(env, cls, searchlistID, obj);207208obj = (*env)->NewStringUTF(env, nameservers);209CHECK_NULL(obj);210(*env)->SetStaticObjectField(env, cls, nameserversID, obj);211}212}213214215/*216* Class: sun_net_dns_ResolverConfgurationImpl217* Method: notifyAddrChange0218* Signature: ()I219*/220JNIEXPORT jint JNICALL221Java_sun_net_dns_ResolverConfigurationImpl_notifyAddrChange0(JNIEnv *env, jclass cls)222{223OVERLAPPED ol;224HANDLE h;225DWORD rc, xfer;226227ol.hEvent = (HANDLE)0;228rc = NotifyAddrChange(&h, &ol);229if (rc == ERROR_IO_PENDING) {230rc = GetOverlappedResult(h, &ol, &xfer, TRUE);231if (rc != 0) {232return 0; /* address changed */233}234}235236/* error */237return -1;238}239240241