NetworkUtils/src/dorkbox/netUtil/Dns.kt

123 lines
4.1 KiB
Kotlin

/*
* Copyright 2020 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
import dorkbox.executor.Executor
import dorkbox.netUtil.dnsUtils.DefaultHostsFileResolver
import dorkbox.netUtil.dnsUtils.ResolveConf
import dorkbox.netUtil.dnsUtils.ResolvedAddressTypes
import java.io.BufferedWriter
import java.io.File
import java.io.FileWriter
import java.io.IOException
import java.net.Inet4Address
import java.net.Inet6Address
import java.net.InetAddress
import java.net.InetSocketAddress
object Dns {
/**
* Gets the version number.
*/
const val version = Common.version
const val DEFAULT_SEARCH_DOMAIN = ""
/**
* @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")
if (!dnsFile.canRead()) {
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")
dnsServers.forEach { dns ->
it.write("nameserver $dns\n")
}
it.flush();
}
Executor().command("resolvconf", "-u").startBlocking()
} else {
throw RuntimeException("NOT IMPL.")
}
}
/**
* Resolve the address of a hostname against the entries in a hosts file, depending on some address types.
*
* @param inetHost the hostname to resolve
* @param resolvedAddressTypes the address types to resolve
*
* @return the first matching address or null
*/
fun resolveFromHosts(inetHost: String, resolvedAddressTypes: ResolvedAddressTypes = ResolvedAddressTypes.IPV4_PREFERRED): InetAddress? {
return DefaultHostsFileResolver.address(inetHost, resolvedAddressTypes)
}
/** Returns all name servers, including the default ones. */
val nameServers: Map<String, List<InetSocketAddress>> by lazy {
ResolveConf.getUnsortedNameServers()
}
/** Returns all default name servers. */
val defaultNameServers: List<InetSocketAddress> by lazy {
val defaultServers = nameServers[DEFAULT_SEARCH_DOMAIN]!!
if (IPv6.isPreferred) {
// prefer IPv6: return IPv6 first, then IPv4 (each in the order added)
defaultServers.filter { it.address is Inet6Address } + defaultServers.filter { it.address is Inet4Address }
} else if (IPv4.isPreferred) {
// skip IPv6 addresses
defaultServers.filter { it.address is Inet4Address }
} else {
// neither is specified, return in the order added
defaultServers
}
}
/**
* 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 = ResolveConf.tryParseResolvConfNDots("/etc/resolv.conf")
if (!tryParse.first) {
// then fallback to netware
tryParse = ResolveConf.tryParseResolvConfNDots("sys:/etc/resolv.cfg")
}
tryParse.second
}
}
}
//TODO add domain TLD, etc util tools