Added JNA network utility, added getting DNS nameservers via JNA
parent
546ed90ec2
commit
d33cee3817
|
@ -1,33 +1,42 @@
|
|||
package dorkbox.netUtil
|
||||
|
||||
import com.sun.jna.Memory
|
||||
import com.sun.jna.Pointer.*
|
||||
import com.sun.jna.platform.win32.WinError
|
||||
import dorkbox.executor.Executor
|
||||
import java.io.BufferedWriter
|
||||
import java.io.File
|
||||
import java.io.FileWriter
|
||||
import java.io.IOException
|
||||
import dorkbox.netUtil.jna.windows.IPHlpAPI
|
||||
import dorkbox.netUtil.jna.windows.structs.IP_ADAPTER_ADDRESSES_LH
|
||||
import dorkbox.netUtil.jna.windows.structs.IP_ADAPTER_DNS_SERVER_ADDRESS_XP
|
||||
import java.io.*
|
||||
import java.net.*
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.util.*
|
||||
import javax.naming.Context
|
||||
import javax.naming.NamingException
|
||||
import javax.naming.directory.DirContext
|
||||
import javax.naming.directory.InitialDirContext
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
object Dns {
|
||||
/**
|
||||
* @throws IOException if the DNS resolve.conf file cannot be read
|
||||
*/
|
||||
fun setDNSServers(dnsServersString: String) {
|
||||
if (Common.OS_LINUX) {
|
||||
val dnsServers = dnsServersString.split(",");
|
||||
val dnsFile = File("/etc/resolvconf/resolv.conf.d/head");
|
||||
val dnsServers = dnsServersString.split(",")
|
||||
val dnsFile = File("/etc/resolvconf/resolv.conf.d/head")
|
||||
|
||||
if (!dnsFile.canRead()) {
|
||||
throw IOException("Unable to initialize dns server file. Something is SERIOUSLY wrong");
|
||||
throw IOException("Unable to initialize dns server file. Something is SERIOUSLY wrong")
|
||||
}
|
||||
|
||||
BufferedWriter(FileWriter(dnsFile)).use {
|
||||
it.write("# File location: /etc/resolvconf/resolv.conf.d/head\n");
|
||||
it.write("# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)\n");
|
||||
it.write("# File location: /etc/resolvconf/resolv.conf.d/head\n")
|
||||
it.write("# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)\n")
|
||||
|
||||
dnsServers.forEach { dns ->
|
||||
it.write("nameserver $dns\n");
|
||||
it.write("nameserver $dns\n")
|
||||
}
|
||||
|
||||
it.flush();
|
||||
|
@ -38,4 +47,331 @@ object Dns {
|
|||
throw RuntimeException("NOT IMPL.")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Returns all located name servers, which may be empty. */
|
||||
val defaultNameServers: List<InetSocketAddress> by lazy {
|
||||
val nameServers = getUnsortedDefaultNameServers()
|
||||
|
||||
if (IPv6.isPreferred) {
|
||||
// prefer IPv6: return IPv6 first, then IPv4 (each in the order added)
|
||||
nameServers.filter { it.address is Inet6Address } + nameServers.filter { it.address is Inet4Address }
|
||||
} else if (IPv4.isPreferred) {
|
||||
// skip IPv6 addresses
|
||||
nameServers.filter { it.address is Inet4Address }
|
||||
}
|
||||
|
||||
// neither is specified, return in the order added
|
||||
nameServers
|
||||
}
|
||||
|
||||
// largely from:
|
||||
// https://github.com/dnsjava/dnsjava/blob/fb4889ee7a73f391f43bf6dc78b019d87ae15f15/src/main/java/org/xbill/DNS/config/BaseResolverConfigProvider.java#L22
|
||||
private fun getUnsortedDefaultNameServers() : List<InetSocketAddress> {
|
||||
val defaultNameServers = mutableListOf<InetSocketAddress>()
|
||||
|
||||
// Using jndi-dns to obtain the default name servers.
|
||||
//
|
||||
// See:
|
||||
// - http://docs.oracle.com/javase/8/docs/technotes/guides/jndi/jndi-dns.html
|
||||
// - http://mail.openjdk.java.net/pipermail/net-dev/2017-March/010695.html
|
||||
|
||||
// Using jndi-dns to obtain the default name servers.
|
||||
//
|
||||
// See:
|
||||
// - http://docs.oracle.com/javase/8/docs/technotes/guides/jndi/jndi-dns.html
|
||||
// - http://mail.openjdk.java.net/pipermail/net-dev/2017-March/010695.html
|
||||
val env = Hashtable<String, String>()
|
||||
env[Context.INITIAL_CONTEXT_FACTORY] = "com.sun.jndi.dns.DnsContextFactory"
|
||||
env["java.naming.provider.url"] = "dns://"
|
||||
try {
|
||||
val ctx: DirContext = InitialDirContext(env)
|
||||
val dnsUrls = ctx.environment["java.naming.provider.url"] as String?
|
||||
val servers = dnsUrls!!.split(" ".toRegex()).toTypedArray()
|
||||
|
||||
for (server in servers) {
|
||||
try {
|
||||
defaultNameServers.add(Common.socketAddress(URI(server).host, 53))
|
||||
} catch (e: URISyntaxException) {
|
||||
Common.logger.debug("Skipping a malformed nameserver URI: {}", server, e)
|
||||
}
|
||||
}
|
||||
} catch (ignore: NamingException) {
|
||||
// Will also try JNA/etc if this fails.
|
||||
}
|
||||
|
||||
if (defaultNameServers.isNotEmpty()) {
|
||||
return defaultNameServers
|
||||
}
|
||||
|
||||
if (Common.OS_WINDOWS) {
|
||||
// have to use JNA to access the WINDOWS resolver info
|
||||
|
||||
// modified from: https://github.com/dnsjava/dnsjava/blob/master/src/main/java/org/xbill/DNS/config/WindowsResolverConfigProvider.java
|
||||
// The recommended method of calling the GetAdaptersAddresses function is to pre-allocate a 15KB working buffer
|
||||
var buffer: Memory? = Memory(15 * 1024)
|
||||
val size: com.sun.jna.ptr.IntByReference = com.sun.jna.ptr.IntByReference(0)
|
||||
|
||||
val flags: Int = IPHlpAPI.GAA_FLAG_SKIP_UNICAST or
|
||||
IPHlpAPI.GAA_FLAG_SKIP_ANYCAST or
|
||||
IPHlpAPI.GAA_FLAG_SKIP_MULTICAST or
|
||||
IPHlpAPI.GAA_FLAG_SKIP_FRIENDLY_NAME
|
||||
|
||||
var error: Int = IPHlpAPI.GetAdaptersAddresses(
|
||||
IPHlpAPI.AF_UNSPEC,
|
||||
flags,
|
||||
NULL,
|
||||
buffer,
|
||||
size
|
||||
)
|
||||
|
||||
if (error == WinError.ERROR_BUFFER_OVERFLOW) {
|
||||
buffer = Memory(size.value.toLong())
|
||||
error = IPHlpAPI.GetAdaptersAddresses(
|
||||
IPHlpAPI.AF_UNSPEC,
|
||||
flags,
|
||||
NULL,
|
||||
buffer,
|
||||
size
|
||||
)
|
||||
}
|
||||
|
||||
if (error == WinError.ERROR_SUCCESS) {
|
||||
var result: IP_ADAPTER_ADDRESSES_LH? = IP_ADAPTER_ADDRESSES_LH(buffer)
|
||||
while (result != null) {
|
||||
|
||||
// only interfaces with IfOperStatusUp
|
||||
if (result.OperStatus == 1) {
|
||||
var dns: IP_ADAPTER_DNS_SERVER_ADDRESS_XP? = result.FirstDnsServerAddress
|
||||
while (dns != null) {
|
||||
|
||||
var address: InetAddress
|
||||
try {
|
||||
address = dns.Address.toAddress()
|
||||
if (address is Inet4Address || !address.isSiteLocalAddress) {
|
||||
defaultNameServers.add(InetSocketAddress(address, 53))
|
||||
} else {
|
||||
Common.logger.debug("Skipped site-local IPv6 server address {} on adapter index {}", address, result.IfIndex)
|
||||
}
|
||||
} catch (e: UnknownHostException) {
|
||||
Common.logger.warn("Invalid nameserver address on adapter index {}", result.IfIndex, e)
|
||||
}
|
||||
dns = dns.Next
|
||||
}
|
||||
}
|
||||
|
||||
result = result.Next
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// try resolve.conf
|
||||
|
||||
// first try the default unix config path
|
||||
var tryParse = tryParseResolvConfNameservers("/etc/resolv.conf")
|
||||
if (!tryParse.first) {
|
||||
// then fallback to netware
|
||||
tryParse = tryParseResolvConfNameservers("sys:/etc/resolv.cfg")
|
||||
}
|
||||
|
||||
defaultNameServers.addAll(tryParse.second)
|
||||
}
|
||||
|
||||
return defaultNameServers
|
||||
}
|
||||
|
||||
private fun tryParseResolvConfNameservers(path: String): Pair<Boolean, MutableList<InetSocketAddress>> {
|
||||
val p = Paths.get(path)
|
||||
if (Files.exists(p)) {
|
||||
try {
|
||||
Files.newInputStream(p).use { `in` ->
|
||||
return Pair(true, parseResolvConfNameservers(`in`))
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return Pair(false, mutableListOf())
|
||||
}
|
||||
|
||||
private fun parseResolvConfNameservers(`in`: InputStream): MutableList<InetSocketAddress> {
|
||||
val defaultNameServers = mutableListOf<InetSocketAddress>()
|
||||
|
||||
InputStreamReader(`in`).use { isr ->
|
||||
BufferedReader(isr).use { br ->
|
||||
var line: String?
|
||||
while (br.readLine().also { line = it } != null) {
|
||||
val st = StringTokenizer(line)
|
||||
if (!st.hasMoreTokens()) {
|
||||
continue
|
||||
}
|
||||
when (st.nextToken()) {
|
||||
"nameserver" -> defaultNameServers.add(InetSocketAddress(st.nextToken(), 53))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return defaultNameServers
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the threshold for the number of dots which must appear in a name before it is considered
|
||||
* absolute. The default is 1.
|
||||
*/
|
||||
val numberDots: Int by lazy {
|
||||
if (Common.OS_WINDOWS) {
|
||||
1
|
||||
} else {
|
||||
// first try the default unix config path
|
||||
var tryParse = tryParseResolvConfNDots("/etc/resolv.conf")
|
||||
if (!tryParse.first) {
|
||||
// then fallback to netware
|
||||
tryParse = tryParseResolvConfNDots("sys:/etc/resolv.cfg")
|
||||
}
|
||||
tryParse.second
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryParseResolvConfNDots(path: String): Pair<Boolean, Int> {
|
||||
val p = Paths.get(path)
|
||||
if (Files.exists(p)) {
|
||||
try {
|
||||
Files.newInputStream(p).use { `in` ->
|
||||
return Pair(true, getNdots(`in`))
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return Pair(false, 1)
|
||||
}
|
||||
|
||||
|
||||
// @kotlin.jvm.Throws(IOException::class)
|
||||
// private fun parseResolvConf(`in`: InputStream) {
|
||||
// InputStreamReader(`in`).use { isr ->
|
||||
// BufferedReader(isr).use { br ->
|
||||
//
|
||||
// var line: String?
|
||||
// loop@ while (br.readLine().also { line = it } != null) {
|
||||
// val st = StringTokenizer(line)
|
||||
// if (!st.hasMoreTokens()) {
|
||||
// continue
|
||||
// }
|
||||
// when (st.nextToken()) {
|
||||
// "domain" -> {
|
||||
// // man resolv.conf:
|
||||
// // The domain and search keywords are mutually exclusive. If more than one instance of
|
||||
// // these keywords is present, the last instance wins.
|
||||
// searchlist.clear()
|
||||
// if (!st.hasMoreTokens()) {
|
||||
// continue@loop
|
||||
// }
|
||||
// addSearchPath(st.nextToken())
|
||||
// }
|
||||
// "search" -> {
|
||||
// // man resolv.conf:
|
||||
// // The domain and search keywords are mutually exclusive. If more than one instance of
|
||||
// // these keywords is present, the last instance wins.
|
||||
// searchlist.clear()
|
||||
// while (st.hasMoreTokens()) {
|
||||
// addSearchPath(st.nextToken())
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // man resolv.conf:
|
||||
// // The search keyword of a system's resolv.conf file can be overridden on a per-process basis by
|
||||
// // setting the environment variable LOCALDOMAIN to a space-separated list of search domains.
|
||||
// val localdomain = System.getenv("LOCALDOMAIN")
|
||||
// if (localdomain != null && !localdomain.isEmpty()) {
|
||||
// searchlist.clear()
|
||||
// parseSearchPathList(localdomain, " ")
|
||||
// }
|
||||
// }
|
||||
|
||||
// @kotlin.jvm.Throws(IOException::class)
|
||||
private fun getNdots(`in`: InputStream): Int {
|
||||
var ndots = 1
|
||||
|
||||
InputStreamReader(`in`).use { isr ->
|
||||
BufferedReader(isr).use { br ->
|
||||
var line: String?
|
||||
loop@ while (br.readLine().also { line = it } != null) {
|
||||
val st = StringTokenizer(line)
|
||||
if (!st.hasMoreTokens()) {
|
||||
continue
|
||||
}
|
||||
|
||||
when (st.nextToken()) {
|
||||
"domain" -> {
|
||||
// man resolv.conf:
|
||||
// The domain and search keywords are mutually exclusive. If more than one instance of
|
||||
// these keywords is present, the last instance wins.
|
||||
if (!st.hasMoreTokens()) {
|
||||
continue@loop
|
||||
}
|
||||
}
|
||||
"search" -> {
|
||||
// man resolv.conf:
|
||||
// The domain and search keywords are mutually exclusive. If more than one instance of
|
||||
// these keywords is present, the last instance wins.
|
||||
while (st.hasMoreTokens()) {
|
||||
val token = st.nextToken()
|
||||
if (token.startsWith("ndots:")) {
|
||||
ndots = parseNdots(token.substring(6))
|
||||
}
|
||||
}
|
||||
}
|
||||
"options" -> while (st.hasMoreTokens()) {
|
||||
val token = st.nextToken()
|
||||
if (token.startsWith("ndots:")) {
|
||||
ndots = parseNdots(token.substring(6))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// man resolv.conf:
|
||||
// The options keyword of a system's resolv.conf file can be amended on a per-process basis by
|
||||
// setting the environment variable RES_OPTIONS to a space-separated list of resolver options as
|
||||
// explained above under options.
|
||||
val resOptions = System.getenv("RES_OPTIONS")
|
||||
if (resOptions != null && !resOptions.isEmpty()) {
|
||||
val st = StringTokenizer(resOptions, " ")
|
||||
while (st.hasMoreTokens()) {
|
||||
val token = st.nextToken()
|
||||
if (token.startsWith("ndots:")) {
|
||||
ndots = parseNdots(token.substring(6))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ndots
|
||||
}
|
||||
|
||||
private fun parseNdots(token: String): Int {
|
||||
if (token.isNotEmpty()) {
|
||||
try {
|
||||
var ndots = token.toInt()
|
||||
if (ndots >= 0) {
|
||||
if (ndots > 15) {
|
||||
// man resolv.conf:
|
||||
// The value for this option is silently capped to 15
|
||||
ndots = 15
|
||||
}
|
||||
return ndots
|
||||
}
|
||||
} catch (e: NumberFormatException) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright 2016 dorkbox, llc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package dorkbox.netUtil.jna
|
||||
|
||||
import com.sun.jna.Library
|
||||
import com.sun.jna.Native
|
||||
import com.sun.jna.NativeLibrary
|
||||
import com.sun.jna.win32.W32APIOptions
|
||||
import dorkbox.netUtil.Common
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Helper method to get the library info from JNA when registering via direct map
|
||||
*/
|
||||
object JnaHelper {
|
||||
@kotlin.jvm.Throws(IllegalArgumentException::class)
|
||||
fun register(libraryName: String, clazz: Class<*>): NativeLibrary {
|
||||
val options: MutableMap<String, Any?> = HashMap()
|
||||
options[Library.OPTION_CLASSLOADER] = clazz.classLoader
|
||||
|
||||
if (Common.OS_WINDOWS) {
|
||||
val entries: Set<Map.Entry<String, Any?>> = W32APIOptions.DEFAULT_OPTIONS.entries
|
||||
for ((key, value) in entries) {
|
||||
options[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
val library = NativeLibrary.getInstance(libraryName, options)
|
||||
?: throw IllegalArgumentException("$libraryName doesn't exist or cannot be loaded.")
|
||||
|
||||
Native.register(clazz, library)
|
||||
return library
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package dorkbox.netUtil.jna.windows
|
||||
|
||||
import com.sun.jna.Pointer
|
||||
import com.sun.jna.ptr.IntByReference
|
||||
import dorkbox.netUtil.jna.JnaHelper.register
|
||||
|
||||
/**
|
||||
* https://docs.microsoft.com/en-us/windows/win32/api/iphlpapi/
|
||||
*/
|
||||
object IPHlpAPI {
|
||||
init {
|
||||
register("IPHlpAPI", IPHlpAPI::class.java)
|
||||
}
|
||||
|
||||
const val AF_UNSPEC = 0
|
||||
const val AF_INET = 2
|
||||
const val AF_INET6 = 23
|
||||
const val GAA_FLAG_SKIP_UNICAST = 0x0001
|
||||
const val GAA_FLAG_SKIP_ANYCAST = 0x0002
|
||||
const val GAA_FLAG_SKIP_MULTICAST = 0x0004
|
||||
const val GAA_FLAG_SKIP_DNS_SERVER = 0x0008
|
||||
const val GAA_FLAG_INCLUDE_PREFIX = 0x0010
|
||||
const val GAA_FLAG_SKIP_FRIENDLY_NAME = 0x0020
|
||||
const val GAA_FLAG_INCLUDE_WINS_INFO = 0x0040
|
||||
const val GAA_FLAG_INCLUDE_GATEWAYS = 0x0080
|
||||
const val GAA_FLAG_INCLUDE_ALL_INTERFACES = 0x0100
|
||||
const val GAA_FLAG_INCLUDE_ALL_COMPARTMENTS = 0x0200
|
||||
const val GAA_FLAG_INCLUDE_TUNNEL_BINDINGORDER = 0x0400
|
||||
|
||||
external fun GetAdaptersAddresses(
|
||||
family: Int,
|
||||
flags: Int,
|
||||
reserved: Pointer?,
|
||||
adapterAddresses: Pointer?,
|
||||
sizePointer: IntByReference?
|
||||
): Int
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
package dorkbox.netUtil.jna.windows.structs;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.Structure;
|
||||
import com.sun.jna.WString;
|
||||
import com.sun.jna.platform.win32.Guid;
|
||||
|
||||
public
|
||||
class IP_ADAPTER_ADDRESSES_LH extends Structure {
|
||||
public static
|
||||
class ByReference extends IP_ADAPTER_ADDRESSES_LH implements Structure.ByReference {}
|
||||
|
||||
|
||||
public int Length;
|
||||
public int IfIndex;
|
||||
|
||||
public IP_ADAPTER_ADDRESSES_LH.ByReference Next;
|
||||
public String AdapterName;
|
||||
|
||||
public IP_ADAPTER_UNICAST_ADDRESS_LH.ByReference FirstUnicastAddress;
|
||||
public IP_ADAPTER_ANYCAST_ADDRESS_XP.ByReference FirstAnycastAddress;
|
||||
public IP_ADAPTER_MULTICAST_ADDRESS_XP.ByReference FirstMulticastAddress;
|
||||
public IP_ADAPTER_DNS_SERVER_ADDRESS_XP.ByReference FirstDnsServerAddress;
|
||||
|
||||
public WString DnsSuffix;
|
||||
public WString Description;
|
||||
public WString FriendlyName;
|
||||
|
||||
public byte[] PhysicalAddress = new byte[8];
|
||||
public int PhysicalAddressLength;
|
||||
public int Flags;
|
||||
public int Mtu;
|
||||
public int IfType;
|
||||
public int OperStatus;
|
||||
public int Ipv6IfIndex;
|
||||
|
||||
public int[] ZoneIndices = new int[16];
|
||||
public Pointer FirstPrefix;
|
||||
|
||||
public long TransmitLinkSpeed;
|
||||
public long ReceiveLinkSpeed;
|
||||
|
||||
public Pointer FirstWinsServerAddress;
|
||||
public Pointer FirstGatewayAddress;
|
||||
|
||||
public int Ipv4Metric;
|
||||
public int Ipv6Metric;
|
||||
|
||||
public LUID Luid;
|
||||
public SOCKET_ADDRESS Dhcpv4Server;
|
||||
public int CompartmentId;
|
||||
public Guid.GUID NetworkGuid;
|
||||
|
||||
public int ConnectionType;
|
||||
public int TunnelType;
|
||||
public SOCKET_ADDRESS Dhcpv6Server;
|
||||
|
||||
public byte[] Dhcpv6ClientDuid = new byte[130];
|
||||
public int Dhcpv6ClientDuidLength;
|
||||
public int Dhcpv6Iaid;
|
||||
|
||||
public IP_ADAPTER_DNS_SUFFIX.ByReference FirstDnsSuffix;
|
||||
|
||||
public
|
||||
IP_ADAPTER_ADDRESSES_LH(Pointer p) {
|
||||
super(p);
|
||||
read();
|
||||
}
|
||||
|
||||
public
|
||||
IP_ADAPTER_ADDRESSES_LH() {}
|
||||
|
||||
@Override
|
||||
protected
|
||||
List<String> getFieldOrder() {
|
||||
return Arrays.asList("Length",
|
||||
"IfIndex",
|
||||
"Next",
|
||||
"AdapterName",
|
||||
"FirstUnicastAddress",
|
||||
"FirstAnycastAddress",
|
||||
"FirstMulticastAddress",
|
||||
"FirstDnsServerAddress",
|
||||
"DnsSuffix",
|
||||
"Description",
|
||||
"FriendlyName",
|
||||
"PhysicalAddress",
|
||||
"PhysicalAddressLength",
|
||||
"Flags",
|
||||
"Mtu",
|
||||
"IfType",
|
||||
"OperStatus",
|
||||
"Ipv6IfIndex",
|
||||
"ZoneIndices",
|
||||
"FirstPrefix",
|
||||
"TransmitLinkSpeed",
|
||||
"ReceiveLinkSpeed",
|
||||
"FirstWinsServerAddress",
|
||||
"FirstGatewayAddress",
|
||||
"Ipv4Metric",
|
||||
"Ipv6Metric",
|
||||
"Luid",
|
||||
"Dhcpv4Server",
|
||||
"CompartmentId",
|
||||
"NetworkGuid",
|
||||
"ConnectionType",
|
||||
"TunnelType",
|
||||
"Dhcpv6Server",
|
||||
"Dhcpv6ClientDuid",
|
||||
"Dhcpv6ClientDuidLength",
|
||||
"Dhcpv6Iaid",
|
||||
"FirstDnsSuffix");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package dorkbox.netUtil.jna.windows.structs;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.jna.Structure;
|
||||
|
||||
public
|
||||
class IP_ADAPTER_ANYCAST_ADDRESS_XP extends Structure {
|
||||
public static
|
||||
class ByReference extends IP_ADAPTER_ANYCAST_ADDRESS_XP implements Structure.ByReference {}
|
||||
|
||||
|
||||
public int Length;
|
||||
public int Reserved;
|
||||
|
||||
public IP_ADAPTER_DNS_SERVER_ADDRESS_XP.ByReference Next;
|
||||
public SOCKET_ADDRESS Address;
|
||||
|
||||
@Override
|
||||
protected
|
||||
List<String> getFieldOrder() {
|
||||
return Arrays.asList("Length", "Reserved", "Next", "Address");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package dorkbox.netUtil.jna.windows.structs;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.jna.Structure;
|
||||
|
||||
public
|
||||
class IP_ADAPTER_DNS_SERVER_ADDRESS_XP extends Structure {
|
||||
public static
|
||||
class ByReference extends IP_ADAPTER_DNS_SERVER_ADDRESS_XP implements Structure.ByReference {}
|
||||
|
||||
|
||||
public int Length;
|
||||
public int Reserved;
|
||||
|
||||
public IP_ADAPTER_DNS_SERVER_ADDRESS_XP.ByReference Next;
|
||||
public SOCKET_ADDRESS Address;
|
||||
|
||||
@Override
|
||||
protected
|
||||
List<String> getFieldOrder() {
|
||||
return Arrays.asList("Length", "Reserved", "Next", "Address");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package dorkbox.netUtil.jna.windows.structs;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.jna.Structure;
|
||||
|
||||
public
|
||||
class IP_ADAPTER_DNS_SUFFIX extends Structure {
|
||||
public static
|
||||
class ByReference extends IP_ADAPTER_DNS_SUFFIX implements Structure.ByReference {}
|
||||
|
||||
|
||||
public IP_ADAPTER_DNS_SUFFIX.ByReference Next;
|
||||
public char[] _String = new char[256];
|
||||
|
||||
@Override
|
||||
protected
|
||||
List<String> getFieldOrder() {
|
||||
return Arrays.asList("Next", "_String");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package dorkbox.netUtil.jna.windows.structs;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.jna.Structure;
|
||||
|
||||
public
|
||||
class IP_ADAPTER_MULTICAST_ADDRESS_XP extends Structure {
|
||||
public static
|
||||
class ByReference extends IP_ADAPTER_MULTICAST_ADDRESS_XP implements Structure.ByReference {}
|
||||
|
||||
|
||||
public int Length;
|
||||
public int Reserved;
|
||||
|
||||
public IP_ADAPTER_DNS_SERVER_ADDRESS_XP.ByReference Next;
|
||||
public SOCKET_ADDRESS Address;
|
||||
|
||||
@Override
|
||||
protected
|
||||
List<String> getFieldOrder() {
|
||||
return Arrays.asList("Length", "Reserved", "Next", "Address");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package dorkbox.netUtil.jna.windows.structs;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.jna.Structure;
|
||||
|
||||
public
|
||||
class IP_ADAPTER_UNICAST_ADDRESS_LH extends Structure {
|
||||
public static
|
||||
class ByReference extends IP_ADAPTER_UNICAST_ADDRESS_LH implements Structure.ByReference {}
|
||||
|
||||
|
||||
public int Length;
|
||||
public int IfIndex;
|
||||
|
||||
public IP_ADAPTER_UNICAST_ADDRESS_LH.ByReference Next;
|
||||
public SOCKET_ADDRESS Address;
|
||||
|
||||
public int PrefixOrigin;
|
||||
public int SuffixOrigin;
|
||||
public int DadState;
|
||||
|
||||
public int ValidLifetime;
|
||||
public int PreferredLifetime;
|
||||
public int LeaseLifetime;
|
||||
public byte OnLinkPrefixLength;
|
||||
|
||||
@Override
|
||||
protected
|
||||
List<String> getFieldOrder() {
|
||||
return Arrays.asList("Length",
|
||||
"IfIndex",
|
||||
"Next",
|
||||
"Address",
|
||||
"PrefixOrigin",
|
||||
"SuffixOrigin",
|
||||
"DadState",
|
||||
"ValidLifetime",
|
||||
"PreferredLifetime",
|
||||
"LeaseLifetime",
|
||||
"OnLinkPrefixLength");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package dorkbox.netUtil.jna.windows.structs;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.jna.Structure;
|
||||
|
||||
public
|
||||
class LUID extends Structure {
|
||||
public int LowPart;
|
||||
public int HighPart;
|
||||
|
||||
@Override
|
||||
protected
|
||||
List<String> getFieldOrder() {
|
||||
return Arrays.asList("LowPart", "HighPart");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package dorkbox.netUtil.jna.windows.structs;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.Structure;
|
||||
|
||||
public
|
||||
class SOCKADDR_IN extends Structure {
|
||||
public short sin_family;
|
||||
public short sin_port;
|
||||
public byte[] sin_addr = new byte[4];
|
||||
public byte[] sin_zero = new byte[8];
|
||||
|
||||
public
|
||||
SOCKADDR_IN(Pointer p) {
|
||||
super(p);
|
||||
read();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected
|
||||
List<String> getFieldOrder() {
|
||||
return Arrays.asList("sin_family", "sin_port", "sin_addr", "sin_zero");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package dorkbox.netUtil.jna.windows.structs;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.Structure;
|
||||
|
||||
public
|
||||
class SOCKADDR_IN6 extends Structure {
|
||||
public short sin6_family;
|
||||
public short sin6_port;
|
||||
public int sin6_flowinfo;
|
||||
|
||||
public byte[] sin6_addr = new byte[16];
|
||||
public int sin6_scope_id;
|
||||
|
||||
public
|
||||
SOCKADDR_IN6(Pointer p) {
|
||||
super(p);
|
||||
read();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected
|
||||
List<String> getFieldOrder() {
|
||||
return Arrays.asList("sin6_family", "sin6_port", "sin6_flowinfo", "sin6_addr", "sin6_scope_id");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package dorkbox.netUtil.jna.windows.structs;
|
||||
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.Structure;
|
||||
|
||||
public
|
||||
class SOCKET_ADDRESS extends Structure {
|
||||
public static final int AF_INET = 2;
|
||||
public static final int AF_INET6 = 23;
|
||||
|
||||
public Pointer lpSockaddr;
|
||||
public int iSockaddrLength;
|
||||
|
||||
public
|
||||
InetAddress toAddress() throws UnknownHostException {
|
||||
switch (((int) lpSockaddr.getShort(0))) {
|
||||
case AF_INET:
|
||||
SOCKADDR_IN in4 = new SOCKADDR_IN(lpSockaddr);
|
||||
return InetAddress.getByAddress(in4.sin_addr);
|
||||
case AF_INET6:
|
||||
SOCKADDR_IN6 in6 = new SOCKADDR_IN6(lpSockaddr);
|
||||
return Inet6Address.getByAddress("", in6.sin6_addr, in6.sin6_scope_id);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected
|
||||
List<String> getFieldOrder() {
|
||||
return Arrays.asList("lpSockaddr", "iSockaddrLength");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue