summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Schleifer <js@heap.zone>2019-10-03 23:43:07 +0200
committerJonathan Schleifer <js@heap.zone>2019-10-03 23:43:07 +0200
commit4b220e04d918c504ea33452ef001a0b8e1845be9 (patch)
tree837a74fa719597ae25a30c39ec42cc3b2ea54b0c
parent6b1978714587a94219ae134404d9086b4dd11b8c (diff)
OFDNSResolver: Split out settings
This makes it easier to attach them to a query.
-rw-r--r--src/Makefile3
-rw-r--r--src/OFDNSResolver.h12
-rw-r--r--src/OFDNSResolver.m662
-rw-r--r--src/OFDNSResolverSettings.h45
-rw-r--r--src/OFDNSResolverSettings.m545
5 files changed, 681 insertions, 586 deletions
diff --git a/src/Makefile b/src/Makefile
index 4d98df1c..591f2bb0 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -214,7 +214,8 @@ SRCS += OFAdjacentArray.m \
${LIBBASES_M}
SRCS_FILES += OFFileURLHandler.m \
OFINIFileSettings.m
-SRCS_SOCKETS += OFHTTPURLHandler.m \
+SRCS_SOCKETS += OFDNSResolverSettings.m \
+ OFHTTPURLHandler.m \
OFKernelEventObserver.m \
${OFEPOLLKERNELEVENTOBSERVER_M} \
${OFKQUEUEKERNELEVENTOBSERVER_M} \
diff --git a/src/OFDNSResolver.h b/src/OFDNSResolver.h
index 89155600..6ae94352 100644
--- a/src/OFDNSResolver.h
+++ b/src/OFDNSResolver.h
@@ -29,6 +29,7 @@ OF_ASSUME_NONNULL_BEGIN
@class OFArray OF_GENERIC(ObjectType);
@class OFDNSResolver;
@class OFDNSResolverQuery;
+@class OFDNSResolverSettings;
@class OFDate;
@class OFDictionary OF_GENERIC(KeyType, ObjectType);
@class OFMutableDictionary OF_GENERIC(KeyType, ObjectType);
@@ -116,16 +117,7 @@ typedef enum of_dns_resolver_error_t {
OF_SUBCLASSING_RESTRICTED
@interface OFDNSResolver: OFObject
{
- OFDictionary OF_GENERIC(OFString *, OFArray OF_GENERIC(OFString *) *)
- *_staticHosts;
- OFArray OF_GENERIC(OFString *) *_nameServers;
- OFString *_Nullable _localDomain;
- OFArray OF_GENERIC(OFString *) *_searchDomains;
- of_time_interval_t _timeout;
- unsigned int _maxAttempts, _minNumberOfDotsInAbsoluteName;
- bool _usesTCP;
- of_time_interval_t _configReloadInterval;
- OFDate *_lastConfigReload;
+ OFDNSResolverSettings *_settings;
OFUDPSocket *_IPv4Socket;
#ifdef OF_HAVE_IPV6
OFUDPSocket *_IPv6Socket;
diff --git a/src/OFDNSResolver.m b/src/OFDNSResolver.m
index 660d6b00..8acfe2de 100644
--- a/src/OFDNSResolver.m
+++ b/src/OFDNSResolver.m
@@ -17,52 +17,31 @@
#include "config.h"
-#include <errno.h>
#include <string.h>
-#include "unistd_wrapper.h"
#import "OFDNSResolver.h"
#import "OFArray.h"
-#import "OFCharacterSet.h"
#import "OFDNSRequest.h"
+#import "OFDNSResolverSettings.h"
#import "OFDNSResponse.h"
#import "OFData.h"
#import "OFDate.h"
#import "OFDictionary.h"
-#import "OFFile.h"
-#import "OFLocale.h"
#import "OFNumber.h"
#import "OFPair.h"
#import "OFString.h"
#import "OFTimer.h"
#import "OFUDPSocket.h"
#import "OFUDPSocket+Private.h"
-#ifdef OF_WINDOWS
-# import "OFWindowsRegistryKey.h"
-#endif
#import "OFDNSRequestFailedException.h"
#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFInvalidServerReplyException.h"
-#import "OFOpenItemFailedException.h"
-#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"
#import "OFTruncatedDataException.h"
-#ifdef OF_WINDOWS
-# define interface struct
-# include <iphlpapi.h>
-# undef interface
-#endif
-
-#import "socket_helpers.h"
-
-#ifdef OF_NINTENDO_3DS
-# include <3ds.h>
-#endif
-
#ifndef SOCK_DNS
# define SOCK_DNS 0
#endif
@@ -79,22 +58,6 @@
#define CNAME_RECURSION 3
-#if defined(OF_HAIKU)
-# define HOSTS_PATH @"/system/settings/network/hosts"
-# define RESOLV_CONF_PATH @"/system/settings/network/resolv.conf"
-#elif defined(OF_MORPHOS)
-# define HOSTS_PATH @"ENV:sys/net/hosts"
-# define RESOLV_CONF_PATH @"ENV:sys/net/resolv.conf"
-#elif defined(OF_AMIGAOS4)
-# define HOSTS_PATH @"DEVS:Internet/hosts"
-#elif defined(OF_AMIGAOS)
-# define HOSTS_PATH @"AmiTCP:db/hosts"
-# define RESOLV_CONF_PATH @"AmiTCP:db/resolv.conf"
-#else
-# define HOSTS_PATH @"/etc/hosts"
-# define RESOLV_CONF_PATH @"/etc/resolv.conf"
-#endif
-
/*
* TODO:
*
@@ -104,22 +67,6 @@
static const of_run_loop_mode_t resolveRunLoopMode =
@"of_dns_resolver_resolve_mode";
-@interface OFDNSResolverSettings: OFObject
-{
-@public
- OFArray OF_GENERIC(OFString *) *_nameServers, *_searchDomains;
- of_time_interval_t _timeout;
- unsigned int _maxAttempts, _minNumberOfDotsInAbsoluteName;
-}
-
-- (instancetype)
- initWithNameServers: (OFArray *)nameServers
- searchDomains: (OFArray *)searchDomains
- timeout: (of_time_interval_t)timeout
- maxAttempts: (unsigned int)maxAttempts
- minNumberOfDotsInAbsoluteName: (unsigned int)minNumberOfDotsInAbsoluteName;
-@end
-
@interface OFDNSResolverQuery: OFObject
{
@public
@@ -195,25 +142,6 @@ static const of_run_loop_mode_t resolveRunLoopMode =
@end
@interface OFDNSResolver () <OFUDPSocketDelegate>
-- (void)of_setDefaults;
-- (void)of_obtainSystemConfig;
-#if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_3DS)
-- (void)of_parseHosts: (OFString *)path;
-# if !defined(OF_WINDOWS) && !defined(OF_AMIGAOS4)
-- (void)of_parseResolvConf: (OFString *)path;
-- (void)of_parseResolvConfOption: (OFString *)option;
-# endif
-#endif
-#ifdef OF_WINDOWS
-- (void)of_obtainWindowsSystemConfig;
-#endif
-#ifdef OF_AMIGAOS4
-- (void)of_obtainAmigaOS4SystemConfig;
-#endif
-#ifdef OF_NINTENDO_3DS
-- (void)of_obtainNintendo3DSSytemConfig;
-#endif
-- (void)of_reloadSystemConfig;
- (void)of_asyncPerformRequest: (OFDNSRequest *)request
settings: (OFDNSResolverSettings *)settings
nameServersIndex: (size_t)nameServersIndex
@@ -222,50 +150,11 @@ static const of_run_loop_mode_t resolveRunLoopMode =
target: (id)target
selector: (SEL)selector
context: (id)context;
-- (void)of_asyncPerformRequest: (OFDNSRequest *)request
- runLoopMode: (of_run_loop_mode_t)runLoopMode
- target: (id)target
- selector: (SEL)selector
- context: (id)context;
- (void)of_sendQuery: (OFDNSResolverQuery *)query
runLoopMode: (of_run_loop_mode_t)runLoopMode;
- (void)of_queryWithIDTimedOut: (OFDNSResolverQuery *)query;
@end
-#ifndef OF_WII
-static OFString *
-domainFromHostname(void)
-{
- char hostname[256];
- OFString *domain;
-
- if (gethostname(hostname, 256) != 0)
- return nil;
-
- domain = [OFString stringWithCString: hostname
- encoding: [OFLocale encoding]];
-
- @try {
- of_socket_address_parse_ip(domain, 0);
-
- /*
- * If we are still here, the host name is a valid IP address.
- * We can't use that as local domain.
- */
- return nil;
- } @catch (OFInvalidFormatException *e) {
- /* Not an IP address -> we can use it if it contains a dot. */
- size_t pos = [domain rangeOfString: @"."].location;
-
- if (pos == OF_NOT_FOUND)
- return nil;
-
- return [domain substringWithRange:
- of_range(pos + 1, domain.length - pos - 1)];
- }
-}
-#endif
-
static bool
isFQDN(OFString *host, OFDNSResolverSettings *settings)
{
@@ -660,38 +549,6 @@ callback(id target, SEL selector, OFDNSResolver *resolver, OFString *domainName,
exception);
}
-@implementation OFDNSResolverSettings
-- (instancetype)initWithNameServers: (OFArray *)nameServers
- searchDomains: (OFArray *)searchDomains
- timeout: (of_time_interval_t)timeout
- maxAttempts: (unsigned int)maxAttempts
- minNumberOfDotsInAbsoluteName: (unsigned int)minNumberOfDotsInAbsoluteName
-{
- self = [super init];
-
- @try {
- _nameServers = [nameServers copy];
- _searchDomains = [searchDomains copy];
- _timeout = timeout;
- _maxAttempts = maxAttempts;
- _minNumberOfDotsInAbsoluteName = minNumberOfDotsInAbsoluteName;
- } @catch (id e) {
- [self release];
- @throw e;
- }
-
- return self;
-}
-
-- (void)dealloc
-{
- [_nameServers release];
- [_searchDomains release];
-
- [super dealloc];
-}
-@end
-
@implementation OFDNSResolverQuery
- (instancetype)initWithRequest: (OFDNSRequest *)request
domainName: (OFString *)domainName
@@ -713,7 +570,7 @@ callback(id target, SEL selector, OFDNSResolver *resolver, OFString *domainName,
_request = [request copy];
_domainName = [domainName copy];
_ID = [ID retain];
- _settings = [settings retain];
+ _settings = [settings copy];
_nameServersIndex = nameServersIndex;
_searchDomainsIndex = searchDomainsIndex;
_target = [target retain];
@@ -899,6 +756,9 @@ callback(id target, SEL selector, OFDNSResolver *resolver, OFString *domainName,
recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN
recordType: recordType];
[_resolver of_asyncPerformRequest: request
+ settings: nil
+ nameServersIndex: 0
+ searchDomainsIndex: 0
runLoopMode: runLoopMode
target: self
selector: @selector(resolver:
@@ -1088,12 +948,6 @@ callback(id target, SEL selector, OFDNSResolver *resolver, OFString *domainName,
@end
@implementation OFDNSResolver
-@synthesize staticHosts = _staticHosts, nameServers = _nameServers;
-@synthesize localDomain = _localDomain, searchDomains = _searchDomains;
-@synthesize timeout = _timeout, maxAttempts = _maxAttempts;
-@synthesize minNumberOfDotsInAbsoluteName = _minNumberOfDotsInAbsoluteName;
-@synthesize usesTCP = _usesTCP, configReloadInterval = _configReloadInterval;
-
#ifdef OF_AMIGAOS
+ (void)initialize
{
@@ -1116,9 +970,10 @@ callback(id target, SEL selector, OFDNSResolver *resolver, OFString *domainName,
self = [super init];
@try {
+ _settings = [[OFDNSResolverSettings alloc] init];
_queries = [[OFMutableDictionary alloc] init];
- [self of_obtainSystemConfig];
+ [_settings reload];
} @catch (id e) {
[self release];
@throw e;
@@ -1127,99 +982,11 @@ callback(id target, SEL selector, OFDNSResolver *resolver, OFString *domainName,
return self;
}
-- (void)of_setDefaults
-{
- _timeout = 2;
- _maxAttempts = 3;
- _minNumberOfDotsInAbsoluteName = 1;
- _usesTCP = false;
-#ifndef OF_NINTENDO_3DS
- _configReloadInterval = 2;
-#else
- _configReloadInterval = 0;
-#endif
-}
-
-- (void)of_obtainSystemConfig
-{
- void *pool = objc_autoreleasePoolPush();
-#ifdef OF_WINDOWS
- OFString *path;
-#endif
-
- [self of_setDefaults];
-
-#if defined(OF_WINDOWS)
-# ifdef OF_HAVE_FILES
- path = [[OFWindowsRegistryKey localMachineKey]
- stringForValue: @"DataBasePath"
- subkeyPath: @"SYSTEM\\CurrentControlSet\\Services\\"
- @"Tcpip\\Parameters"];
- path = [path stringByAppendingPathComponent: @"hosts"];
-
- if (path != nil)
- [self of_parseHosts: path];
-# endif
-
- [self of_obtainWindowsSystemConfig];
-#elif defined(OF_AMIGAOS4)
- [self of_parseHosts: HOSTS_PATH];
- [self of_obtainAmigaOS4SystemConfig];
-#elif defined(OF_NINTENDO_3DS)
- [self of_obtainNintendo3DSSytemConfig];
-#elif defined(OF_HAVE_FILES)
- [self of_parseHosts: HOSTS_PATH];
- [self of_parseResolvConf: RESOLV_CONF_PATH];
-#endif
-
- if (_staticHosts == nil) {
- OFArray *localhost =
-#ifdef OF_HAVE_IPV6
- [OFArray arrayWithObjects: @"::1", @"127.0.0.1", nil];
-#else
- [OFArray arrayWithObject: @"127.0.0.1"];
-#endif
-
- _staticHosts = [[OFDictionary alloc]
- initWithObject: localhost
- forKey: @"localhost"];
- }
-
- if (_nameServers == nil)
-#ifdef OF_HAVE_IPV6
- _nameServers = [[OFArray alloc]
- initWithObjects: @"127.0.0.1", @"::1", nil];
-#else
- _nameServers = [[OFArray alloc] initWithObject: @"127.0.0.1"];
-#endif
-
-#ifndef OF_WII
- if (_localDomain == nil)
- _localDomain = [domainFromHostname() copy];
-#endif
-
- if (_searchDomains == nil) {
- if (_localDomain != nil)
- _searchDomains = [[OFArray alloc]
- initWithObject: _localDomain];
- else
- _searchDomains = [[OFArray alloc] init];
- }
-
- _lastConfigReload = [[OFDate alloc] init];
-
- objc_autoreleasePoolPop(pool);
-}
-
- (void)dealloc
{
[self close];
- [_staticHosts release];
- [_nameServers release];
- [_localDomain release];
- [_searchDomains release];
- [_lastConfigReload release];
+ [_settings release];
[_IPv4Socket cancelAsyncRequests];
[_IPv4Socket release];
#ifdef OF_HAVE_IPV6
@@ -1231,340 +998,97 @@ callback(id target, SEL selector, OFDNSResolver *resolver, OFString *domainName,
[super dealloc];
}
-#if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_3DS)
-- (void)of_parseHosts: (OFString *)path
+- (OFDictionary *)staticHosts
{
- void *pool = objc_autoreleasePoolPush();
- OFCharacterSet *whitespaceCharacterSet =
- [OFCharacterSet whitespaceCharacterSet];
- OFMutableDictionary *staticHosts;
- OFFile *file;
- OFString *line;
- OFEnumerator *enumerator;
- OFMutableArray *addresses;
-
- @try {
- file = [OFFile fileWithPath: path
- mode: @"r"];
- } @catch (OFOpenItemFailedException *e) {
- objc_autoreleasePoolPop(pool);
- return;
- }
-
- staticHosts = [OFMutableDictionary dictionary];
-
- while ((line = [file readLine]) != nil) {
- void *pool2 = objc_autoreleasePoolPush();
- OFArray *components, *hosts;
- size_t pos;
- OFString *address;
-
- pos = [line rangeOfString: @"#"].location;
- if (pos != OF_NOT_FOUND)
- line = [line substringWithRange: of_range(0, pos)];
-
- components = [line
- componentsSeparatedByCharactersInSet: whitespaceCharacterSet
- options: OF_STRING_SKIP_EMPTY];
-
- if (components.count < 2) {
- objc_autoreleasePoolPop(pool2);
- continue;
- }
-
- address = components.firstObject;
- hosts = [components objectsInRange:
- of_range(1, components.count - 1)];
-
- for (OFString *host in hosts) {
- addresses = [staticHosts objectForKey: host];
-
- if (addresses == nil) {
- addresses = [OFMutableArray array];
- [staticHosts setObject: addresses
- forKey: host];
- }
-
- [addresses addObject: address];
- }
-
- objc_autoreleasePoolPop(pool2);
- }
-
- enumerator = [staticHosts objectEnumerator];
- while ((addresses = [enumerator nextObject]) != nil)
- [addresses makeImmutable];
-
- [staticHosts makeImmutable];
-
- [_staticHosts release];
- _staticHosts = [staticHosts copy];
-
- objc_autoreleasePoolPop(pool);
+ return _settings->_staticHosts;
}
-# if !defined(OF_WINDOWS) && !defined(OF_AMIGAOS4)
-- (void)of_parseResolvConf: (OFString *)path
+- (void)setStaticHosts: (OFDictionary *)staticHosts
{
- void *pool = objc_autoreleasePoolPush();
- OFCharacterSet *whitespaceCharacterSet =
- [OFCharacterSet whitespaceCharacterSet];
- OFCharacterSet *commentCharacters = [OFCharacterSet
- characterSetWithCharactersInString: @"#;"];
- OFMutableArray *nameServers = [[_nameServers mutableCopy] autorelease];
- OFFile *file;
- OFString *line;
-
- @try {
- file = [OFFile fileWithPath: path
- mode: @"r"];
- } @catch (OFOpenItemFailedException *e) {
- objc_autoreleasePoolPop(pool);
- return;
- }
-
- if (nameServers == nil)
- nameServers = [OFMutableArray array];
-
- while ((line = [file readLine]) != nil) {
- void *pool2 = objc_autoreleasePoolPush();
- size_t pos;
- OFArray *components, *arguments;
- OFString *option;
-
- pos = [line indexOfCharacterFromSet: commentCharacters];
- if (pos != OF_NOT_FOUND)
- line = [line substringWithRange: of_range(0, pos)];
-
- components = [line
- componentsSeparatedByCharactersInSet: whitespaceCharacterSet
- options: OF_STRING_SKIP_EMPTY];
-
- if (components.count < 2) {
- objc_autoreleasePoolPop(pool2);
- continue;
- }
-
- option = components.firstObject;
- arguments = [components objectsInRange:
- of_range(1, components.count - 1)];
-
- if ([option isEqual: @"nameserver"]) {
- if (arguments.count != 1) {
- objc_autoreleasePoolPop(pool2);
- continue;
- }
-
- [nameServers addObject: [arguments firstObject]];
- } else if ([option isEqual: @"domain"]) {
- if (arguments.count != 1) {
- objc_autoreleasePoolPop(pool2);
- continue;
- }
-
- [_localDomain release];
- _localDomain = [arguments.firstObject copy];
- } else if ([option isEqual: @"search"]) {
- [_searchDomains release];
- _searchDomains = [arguments copy];
- } else if ([option isEqual: @"options"])
- for (OFString *argument in arguments)
- [self of_parseResolvConfOption: argument];
-
- objc_autoreleasePoolPop(pool2);
- }
-
- [nameServers makeImmutable];
-
- [_nameServers release];
- _nameServers = [nameServers copy];
-
- objc_autoreleasePoolPop(pool);
+ OFDictionary *old = _settings->_staticHosts;
+ _settings->_staticHosts = [staticHosts copy];
+ [old release];
}
-- (void)of_parseResolvConfOption: (OFString *)option
+- (OFArray *)nameServers
{
- @try {
- if ([option hasPrefix: @"ndots:"]) {
- option = [option substringWithRange:
- of_range(6, option.length - 6)];
-
- _minNumberOfDotsInAbsoluteName =
- (unsigned int)option.decimalValue;
- } else if ([option hasPrefix: @"timeout:"]) {
- option = [option substringWithRange:
- of_range(8, option.length - 8)];
-
- _timeout = option.decimalValue;
- } else if ([option hasPrefix: @"attempts:"]) {
- option = [option substringWithRange:
- of_range(9, option.length - 9)];
-
- _maxAttempts = (unsigned int)option.decimalValue;
- } else if ([option hasPrefix: @"reload-period:"]) {
- option = [option substringWithRange:
- of_range(14, option.length - 14)];
-
- _configReloadInterval = option.decimalValue;
- } else if ([option isEqual: @"tcp"])
- _usesTCP = true;
- } @catch (OFInvalidFormatException *e) {
- }
+ return _settings->_nameServers;
}
-# endif
-#endif
-#ifdef OF_WINDOWS
-- (void)of_obtainWindowsSystemConfig
+- (void)setNameServers: (OFArray *)nameServers
{
- of_string_encoding_t encoding = [OFLocale encoding];
- OFMutableArray *nameServers;
- /*
- * We need more space than FIXED_INFO in case we have more than one
- * name server, but we also want it to be properly aligned, meaning we
- * can't just get a buffer of bytes. Thus, we just get space for 8.
- */
- FIXED_INFO fixedInfo[8];
- ULONG length = sizeof(fixedInfo);
- PIP_ADDR_STRING iter;
-
- if (GetNetworkParams(fixedInfo, &length) != ERROR_SUCCESS)
- return;
-
- nameServers = [OFMutableArray array];
-
- for (iter = &fixedInfo->DnsServerList; iter != NULL; iter = iter->Next)
- [nameServers addObject:
- [OFString stringWithCString: iter->IpAddress.String
- encoding: encoding]];
-
- if (nameServers.count > 0) {
- [nameServers makeImmutable];
- _nameServers = [nameServers copy];
- }
-
- if (fixedInfo->DomainName[0] != '\0')
- _localDomain = [[OFString alloc]
- initWithCString: fixedInfo->DomainName
- encoding: encoding];
+ OFArray *old = _settings->_nameServers;
+ _settings->_nameServers = [nameServers copy];
+ [old release];
}
-#endif
-#ifdef OF_AMIGAOS4
-- (void)of_obtainAmigaOS4SystemConfig
+- (OFString *)localDomain
{
- OFMutableArray *nameServers = [OFMutableArray array];
- of_string_encoding_t encoding = [OFLocale encoding];
- struct List *nameServerList = ObtainDomainNameServerList();
- char buffer[MAXHOSTNAMELEN];
-
- if (nameServerList == NULL)
- @throw [OFOutOfMemoryException exception];
-
- @try {
- struct DomainNameServerNode *iter =
- (struct DomainNameServerNode *)&nameServerList->lh_Head;
-
- while (iter->dnsn_MinNode.mln_Succ != NULL) {
- if (iter->dnsn_UseCount != 0 &&
- iter->dnsn_Address != NULL) {
- OFString *address = [OFString
- stringWithCString: iter->dnsn_Address
- encoding: encoding];
-
- [nameServers addObject: address];
- }
-
- iter = (struct DomainNameServerNode *)
- iter->dnsn_MinNode.mln_Succ;
- }
- } @finally {
- ReleaseDomainNameServerList(nameServerList);
- }
-
- if (nameServers.count > 0) {
- [nameServers makeImmutable];
- _nameServers = [nameServers copy];
- }
-
- if (GetDefaultDomainName(buffer, sizeof(buffer)))
- _localDomain = [[OFString alloc] initWithCString: buffer
- encoding: encoding];
+ return _settings->_localDomain;
}
-#endif
-#ifdef OF_NINTENDO_3DS
-- (void)of_obtainNintendo3DSSytemConfig
+- (OFArray *)searchDomains
{
- OFMutableArray *nameServers = [OFMutableArray array];
- union {
- /*
- * For some unknown reason, this needs a 336 bytes buffer and
- * always returns 336 bytes.
- */
- char bytes[336];
- SOCU_DNSTableEntry entries[2];
- } buffer;
- socklen_t optLen = sizeof(buffer);
-
- if (SOCU_GetNetworkOpt(SOL_CONFIG, NETOPT_DNS_TABLE,
- &buffer, &optLen) != 0)
- return;
-
- /*
- * We're fine if this gets smaller in a future release (unlikely), as
- * long as two entries still fit.
- */
- if (optLen < sizeof(buffer.entries))
- return;
-
- for (uint_fast8_t i = 0; i < 2; i++) {
- uint32_t ip = OF_BSWAP32_IF_LE(buffer.entries[i].ip.s_addr);
-
- if (ip == 0)
- continue;
+ return _settings->_searchDomains;
+}
- [nameServers addObject: [OFString stringWithFormat:
- @"%u.%u.%u.%u", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
- (ip >> 8) & 0xFF, ip & 0xFF]];
- }
+- (void)setSearchDomains: (OFArray *)searchDomains
+{
+ OFArray *old = _settings->_searchDomains;
+ _settings->_searchDomains = [searchDomains copy];
+ [old release];
+}
- if (nameServers.count > 0) {
- [nameServers makeImmutable];
- _nameServers = [nameServers copy];
- }
+- (of_time_interval_t)timeout
+{
+ return _settings->_timeout;
}
-#endif
-- (void)of_reloadSystemConfig
+- (void)setTimeout: (of_time_interval_t)timeout
{
- /*
- * TODO: Rather than reparsing every time, check what actually changed
- * (mtime) and only reset those.
- */
+ _settings->_timeout = timeout;
+}
- if (_lastConfigReload != nil && _configReloadInterval > 0 &&
- _lastConfigReload.timeIntervalSinceNow < _configReloadInterval)
- return;
+- (unsigned int)maxAttempts
+{
+ return _settings->_maxAttempts;
+}
- [_staticHosts release];
- _staticHosts = nil;
+- (void)setMaxAttempts: (unsigned int)maxAttempts
+{
+ _settings->_maxAttempts = maxAttempts;
+}
- [_nameServers release];
- _nameServers = nil;
+- (unsigned int)minNumberOfDotsInAbsoluteName
+{
+ return _settings->_minNumberOfDotsInAbsoluteName;
+}
- [_localDomain release];
- _localDomain = nil;
+- (void)setMinNumberOfDotsInAbsoluteName:
+ (unsigned int)minNumberOfDotsInAbsoluteName
+{
+ _settings->_minNumberOfDotsInAbsoluteName =
+ minNumberOfDotsInAbsoluteName;
+}
- [_searchDomains release];
- _searchDomains = nil;
+- (bool)usesTCP
+{
+ return _settings->_usesTCP;
+}
- [self of_setDefaults];
+- (void)setUsesTCP: (bool)usesTCP
+{
+ _settings->_usesTCP = usesTCP;
+}
- [_lastConfigReload release];
- _lastConfigReload = nil;
+- (of_time_interval_t)configReloadInterval
+{
+ return _settings->_configReloadInterval;
+}
- [self of_obtainSystemConfig];
+- (void)setConfigReloadInterval: (of_time_interval_t)configReloadInterval
+{
+ _settings->_configReloadInterval = configReloadInterval;
}
- (void)of_asyncPerformRequest: (OFDNSRequest *)request
@@ -1581,7 +1105,10 @@ callback(id target, SEL selector, OFDNSResolver *resolver, OFString *domainName,
OFString *host, *domainName;
OFDNSResolverQuery *query;
- [self of_reloadSystemConfig];
+ if (settings == nil) {
+ [_settings reload];
+ settings = _settings;
+ }
/* Random, unused ID */
do {
@@ -1642,6 +1169,9 @@ callback(id target, SEL selector, OFDNSResolver *resolver, OFString *domainName,
delegate: (id <OFDNSResolverDelegate>)delegate
{
[self of_asyncPerformRequest: request
+ settings: nil
+ nameServersIndex: 0
+ searchDomainsIndex: 0
runLoopMode: of_run_loop_mode_default
target: self
selector: @selector(of_resolver:
@@ -1655,6 +1185,9 @@ callback(id target, SEL selector, OFDNSResolver *resolver, OFString *domainName,
delegate: (id <OFDNSResolverDelegate>)delegate
{
[self of_asyncPerformRequest: request
+ settings: nil
+ nameServersIndex: 0
+ searchDomainsIndex: 0
runLoopMode: runLoopMode
target: self
selector: @selector(of_resolver:
@@ -1663,33 +1196,6 @@ callback(id target, SEL selector, OFDNSResolver *resolver, OFString *domainName,
context: delegate];
}
-- (void)of_asyncPerformRequest: (OFDNSRequest *)request
- runLoopMode: (of_run_loop_mode_t)runLoopMode
- target: (id)target
- selector: (SEL)selector
- context: (id)context
-{
- void *pool = objc_autoreleasePoolPush();
- OFDNSResolverSettings *settings = [[[OFDNSResolverSettings alloc]
- initWithNameServers: _nameServers
- searchDomains: _searchDomains
- timeout: _timeout
- maxAttempts: _maxAttempts
- minNumberOfDotsInAbsoluteName: _minNumberOfDotsInAbsoluteName]
- autorelease];
-
- [self of_asyncPerformRequest: request
- settings: settings
- nameServersIndex: 0
- searchDomainsIndex: 0
- runLoopMode: runLoopMode
- target: target
- selector: selector
- context: context];
-
- objc_autoreleasePoolPop(pool);
-}
-
- (void)of_sendQuery: (OFDNSResolverQuery *)query
runLoopMode: (of_run_loop_mode_t)runLoopMode
{
@@ -2024,7 +1530,7 @@ callback(id target, SEL selector, OFDNSResolver *resolver, OFString *domainName,
} @catch (OFInvalidFormatException *e) {
}
- if ((aliases = [_staticHosts objectForKey: host]) != nil) {
+ if ((aliases = [_settings->_staticHosts objectForKey: host]) != nil) {
OFMutableData *addresses = [OFMutableData
dataWithItemSize: sizeof(of_socket_address_t)];
id exception = nil;
@@ -2140,6 +1646,9 @@ callback(id target, SEL selector, OFDNSResolver *resolver, OFString *domainName,
[OFNumber numberWithInt: OF_DNS_RESOURCE_RECORD_TYPE_AAAA];
[self of_asyncPerformRequest: request
+ settings: nil
+ nameServersIndex: 0
+ searchDomainsIndex: 0
runLoopMode: runLoopMode
target: context
selector: @selector(resolver:
@@ -2159,6 +1668,9 @@ callback(id target, SEL selector, OFDNSResolver *resolver, OFString *domainName,
[OFNumber numberWithInt: OF_DNS_RESOURCE_RECORD_TYPE_A];
[self of_asyncPerformRequest: request
+ settings: nil
+ nameServersIndex: 0
+ searchDomainsIndex: 0
runLoopMode: runLoopMode
target: context
selector: @selector(resolver:
diff --git a/src/OFDNSResolverSettings.h b/src/OFDNSResolverSettings.h
new file mode 100644
index 00000000..25fc8578
--- /dev/null
+++ b/src/OFDNSResolverSettings.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
+ * 2018, 2019
+ * Jonathan Schleifer <js@heap.zone>
+ *
+ * All rights reserved.
+ *
+ * This file is part of ObjFW. It may be distributed under the terms of the
+ * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
+ * the packaging of this file.
+ *
+ * Alternatively, it may be distributed under the terms of the GNU General
+ * Public License, either version 2 or 3, which can be found in the file
+ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
+ * file.
+ */
+
+#import "OFObject.h"
+
+OF_ASSUME_NONNULL_BEGIN
+
+@class OFArray OF_GENERIC(ObjectType);
+@class OFDate;
+@class OFDictionary OF_GENERIC(KeyType, ObjectType);
+
+@interface OFDNSResolverSettings: OFObject <OFCopying>
+{
+@public
+ OFDictionary OF_GENERIC(OFString *, OFArray OF_GENERIC(OFString *) *)
+ *_staticHosts;
+ OFArray OF_GENERIC(OFString *) *_nameServers;
+ OFString *_Nullable _localDomain;
+ OFArray OF_GENERIC(OFString *) *_searchDomains;
+ of_time_interval_t _timeout;
+ unsigned int _maxAttempts, _minNumberOfDotsInAbsoluteName;
+ bool _usesTCP;
+ of_time_interval_t _configReloadInterval;
+@protected
+ OFDate *_lastConfigReload;
+}
+
+- (void)reload;
+@end
+
+OF_ASSUME_NONNULL_END
diff --git a/src/OFDNSResolverSettings.m b/src/OFDNSResolverSettings.m
new file mode 100644
index 00000000..ed5daf8a
--- /dev/null
+++ b/src/OFDNSResolverSettings.m
@@ -0,0 +1,545 @@
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
+ * 2018, 2019
+ * Jonathan Schleifer <js@heap.zone>
+ *
+ * All rights reserved.
+ *
+ * This file is part of ObjFW. It may be distributed under the terms of the
+ * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
+ * the packaging of this file.
+ *
+ * Alternatively, it may be distributed under the terms of the GNU General
+ * Public License, either version 2 or 3, which can be found in the file
+ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
+ * file.
+ */
+
+#include "config.h"
+
+#include "unistd_wrapper.h"
+
+#import "OFDNSResolverSettings.h"
+#import "OFArray.h"
+#import "OFCharacterSet.h"
+#import "OFDate.h"
+#import "OFDictionary.h"
+#import "OFFile.h"
+#import "OFLocale.h"
+#import "OFString.h"
+#ifdef OF_WINDOWS
+# import "OFWindowsRegistryKey.h"
+#endif
+
+#import "OFInvalidFormatException.h"
+#import "OFOpenItemFailedException.h"
+#import "OFOutOfMemoryException.h"
+
+#ifdef OF_WINDOWS
+# define interface struct
+# include <iphlpapi.h>
+# undef interface
+#endif
+
+#ifdef OF_NINTENDO_3DS
+# include <3ds.h>
+#endif
+
+#import "socket_helpers.h"
+
+#if defined(OF_HAIKU)
+# define HOSTS_PATH @"/system/settings/network/hosts"
+# define RESOLV_CONF_PATH @"/system/settings/network/resolv.conf"
+#elif defined(OF_MORPHOS)
+# define HOSTS_PATH @"ENV:sys/net/hosts"
+# define RESOLV_CONF_PATH @"ENV:sys/net/resolv.conf"
+#elif defined(OF_AMIGAOS4)
+# define HOSTS_PATH @"DEVS:Internet/hosts"
+#elif defined(OF_AMIGAOS)
+# define HOSTS_PATH @"AmiTCP:db/hosts"
+# define RESOLV_CONF_PATH @"AmiTCP:db/resolv.conf"
+#else
+# define HOSTS_PATH @"/etc/hosts"
+# define RESOLV_CONF_PATH @"/etc/resolv.conf"
+#endif
+
+#ifndef OF_WII
+static OFString *
+domainFromHostname(void)
+{
+ char hostname[256];
+ OFString *domain;
+
+ if (gethostname(hostname, 256) != 0)
+ return nil;
+
+ domain = [OFString stringWithCString: hostname
+ encoding: [OFLocale encoding]];
+
+ @try {
+ of_socket_address_parse_ip(domain, 0);
+
+ /*
+ * If we are still here, the host name is a valid IP address.
+ * We can't use that as local domain.
+ */
+ return nil;
+ } @catch (OFInvalidFormatException *e) {
+ /* Not an IP address -> we can use it if it contains a dot. */
+ size_t pos = [domain rangeOfString: @"."].location;
+
+ if (pos == OF_NOT_FOUND)
+ return nil;
+
+ return [domain substringWithRange:
+ of_range(pos + 1, domain.length - pos - 1)];
+ }
+}
+#endif
+
+@implementation OFDNSResolverSettings
+- (void)dealloc
+{
+ [_staticHosts release];
+ [_nameServers release];
+ [_localDomain release];
+ [_searchDomains release];
+ [_lastConfigReload release];
+
+ [super dealloc];
+}
+
+- (id)copy
+{
+ OFDNSResolverSettings *copy = [[OFDNSResolverSettings alloc] init];
+
+ @try {
+ copy->_staticHosts = [_staticHosts copy];
+ copy->_nameServers = [_nameServers copy];
+ copy->_localDomain = [_localDomain copy];
+ copy->_searchDomains = [_searchDomains copy];
+ copy->_timeout = _timeout;
+ copy->_maxAttempts = _maxAttempts;
+ copy->_minNumberOfDotsInAbsoluteName =
+ _minNumberOfDotsInAbsoluteName;
+ copy->_usesTCP = _usesTCP;
+ copy->_configReloadInterval = _configReloadInterval;
+ copy->_lastConfigReload = [_lastConfigReload copy];
+ } @catch (id e) {
+ [copy release];
+ @throw e;
+ }
+
+ return copy;
+}
+
+- (void)setDefaults
+{
+ [_staticHosts release];
+ _staticHosts = nil;
+
+ [_nameServers release];
+ _nameServers = nil;
+
+ [_localDomain release];
+ _localDomain = nil;
+
+ [_searchDomains release];
+ _searchDomains = nil;
+
+ _timeout = 2;
+ _maxAttempts = 3;
+ _minNumberOfDotsInAbsoluteName = 1;
+ _usesTCP = false;
+#ifndef OF_NINTENDO_3DS
+ _configReloadInterval = 2;
+#else
+ _configReloadInterval = 0;
+#endif
+}
+
+#if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_3DS)
+- (void)parseHosts: (OFString *)path
+{
+ void *pool = objc_autoreleasePoolPush();
+ OFCharacterSet *whitespaceCharacterSet =
+ [OFCharacterSet whitespaceCharacterSet];
+ OFMutableDictionary *staticHosts;
+ OFFile *file;
+ OFString *line;
+ OFEnumerator *enumerator;
+ OFMutableArray *addresses;
+
+ @try {
+ file = [OFFile fileWithPath: path
+ mode: @"r"];
+ } @catch (OFOpenItemFailedException *e) {
+ objc_autoreleasePoolPop(pool);
+ return;
+ }
+
+ staticHosts = [OFMutableDictionary dictionary];
+
+ while ((line = [file readLine]) != nil) {
+ void *pool2 = objc_autoreleasePoolPush();
+ OFArray *components, *hosts;
+ size_t pos;
+ OFString *address;
+
+ pos = [line rangeOfString: @"#"].location;
+ if (pos != OF_NOT_FOUND)
+ line = [line substringWithRange: of_range(0, pos)];
+
+ components = [line
+ componentsSeparatedByCharactersInSet: whitespaceCharacterSet
+ options: OF_STRING_SKIP_EMPTY];
+
+ if (components.count < 2) {
+ objc_autoreleasePoolPop(pool2);
+ continue;
+ }
+
+ address = components.firstObject;
+ hosts = [components objectsInRange:
+ of_range(1, components.count - 1)];
+
+ for (OFString *host in hosts) {
+ addresses = [staticHosts objectForKey: host];
+
+ if (addresses == nil) {
+ addresses = [OFMutableArray array];
+ [staticHosts setObject: addresses
+ forKey: host];
+ }
+
+ [addresses addObject: address];
+ }
+
+ objc_autoreleasePoolPop(pool2);
+ }
+
+ enumerator = [staticHosts objectEnumerator];
+ while ((addresses = [enumerator nextObject]) != nil)
+ [addresses makeImmutable];
+
+ [staticHosts makeImmutable];
+
+ [_staticHosts release];
+ _staticHosts = [staticHosts copy];
+
+ objc_autoreleasePoolPop(pool);
+}
+
+# if !defined(OF_WINDOWS) && !defined(OF_AMIGAOS4)
+- (void)parseResolvConfOption: (OFString *)option
+{
+ @try {
+ if ([option hasPrefix: @"ndots:"]) {
+ option = [option substringWithRange:
+ of_range(6, option.length - 6)];
+
+ _minNumberOfDotsInAbsoluteName =
+ (unsigned int)option.decimalValue;
+ } else if ([option hasPrefix: @"timeout:"]) {
+ option = [option substringWithRange:
+ of_range(8, option.length - 8)];
+
+ _timeout = option.decimalValue;
+ } else if ([option hasPrefix: @"attempts:"]) {
+ option = [option substringWithRange:
+ of_range(9, option.length - 9)];
+
+ _maxAttempts = (unsigned int)option.decimalValue;
+ } else if ([option hasPrefix: @"reload-period:"]) {
+ option = [option substringWithRange:
+ of_range(14, option.length - 14)];
+
+ _configReloadInterval = option.decimalValue;
+ } else if ([option isEqual: @"tcp"])
+ _usesTCP = true;
+ } @catch (OFInvalidFormatException *e) {
+ }
+}
+
+- (void)parseResolvConf: (OFString *)path
+{
+ void *pool = objc_autoreleasePoolPush();
+ OFCharacterSet *whitespaceCharacterSet =
+ [OFCharacterSet whitespaceCharacterSet];
+ OFCharacterSet *commentCharacters = [OFCharacterSet
+ characterSetWithCharactersInString: @"#;"];
+ OFMutableArray *nameServers = [[_nameServers mutableCopy] autorelease];
+ OFFile *file;
+ OFString *line;
+
+ @try {
+ file = [OFFile fileWithPath: path
+ mode: @"r"];
+ } @catch (OFOpenItemFailedException *e) {
+ objc_autoreleasePoolPop(pool);
+ return;
+ }
+
+ if (nameServers == nil)
+ nameServers = [OFMutableArray array];
+
+ while ((line = [file readLine]) != nil) {
+ void *pool2 = objc_autoreleasePoolPush();
+ size_t pos;
+ OFArray *components, *arguments;
+ OFString *option;
+
+ pos = [line indexOfCharacterFromSet: commentCharacters];
+ if (pos != OF_NOT_FOUND)
+ line = [line substringWithRange: of_range(0, pos)];
+
+ components = [line
+ componentsSeparatedByCharactersInSet: whitespaceCharacterSet
+ options: OF_STRING_SKIP_EMPTY];
+
+ if (components.count < 2) {
+ objc_autoreleasePoolPop(pool2);
+ continue;
+ }
+
+ option = components.firstObject;
+ arguments = [components objectsInRange:
+ of_range(1, components.count - 1)];
+
+ if ([option isEqual: @"nameserver"]) {
+ if (arguments.count != 1) {
+ objc_autoreleasePoolPop(pool2);
+ continue;
+ }
+
+ [nameServers addObject: [arguments firstObject]];
+ } else if ([option isEqual: @"domain"]) {
+ if (arguments.count != 1) {
+ objc_autoreleasePoolPop(pool2);
+ continue;
+ }
+
+ [_localDomain release];
+ _localDomain = [arguments.firstObject copy];
+ } else if ([option isEqual: @"search"]) {
+ [_searchDomains release];
+ _searchDomains = [arguments copy];
+ } else if ([option isEqual: @"options"])
+ for (OFString *argument in arguments)
+ [self parseResolvConfOption: argument];
+
+ objc_autoreleasePoolPop(pool2);
+ }
+
+ [nameServers makeImmutable];
+
+ [_nameServers release];
+ _nameServers = [nameServers copy];
+
+ objc_autoreleasePoolPop(pool);
+}
+# endif
+#endif
+
+#ifdef OF_WINDOWS
+- (void)obtainWindowsSystemConfig
+{
+ of_string_encoding_t encoding = [OFLocale encoding];
+ OFMutableArray *nameServers;
+ /*
+ * We need more space than FIXED_INFO in case we have more than one
+ * name server, but we also want it to be properly aligned, meaning we
+ * can't just get a buffer of bytes. Thus, we just get space for 8.
+ */
+ FIXED_INFO fixedInfo[8];
+ ULONG length = sizeof(fixedInfo);
+ PIP_ADDR_STRING iter;
+
+ if (GetNetworkParams(fixedInfo, &length) != ERROR_SUCCESS)
+ return;
+
+ nameServers = [OFMutableArray array];
+
+ for (iter = &fixedInfo->DnsServerList; iter != NULL; iter = iter->Next)
+ [nameServers addObject:
+ [OFString stringWithCString: iter->IpAddress.String
+ encoding: encoding]];
+
+ if (nameServers.count > 0) {
+ [nameServers makeImmutable];
+ _nameServers = [nameServers copy];
+ }
+
+ if (fixedInfo->DomainName[0] != '\0')
+ _localDomain = [[OFString alloc]
+ initWithCString: fixedInfo->DomainName
+ encoding: encoding];
+}
+#endif
+
+#ifdef OF_AMIGAOS4
+- (void)obtainAmigaOS4SystemConfig
+{
+ OFMutableArray *nameServers = [OFMutableArray array];
+ of_string_encoding_t encoding = [OFLocale encoding];
+ struct List *nameServerList = ObtainDomainNameServerList();
+ char buffer[MAXHOSTNAMELEN];
+
+ if (nameServerList == NULL)
+ @throw [OFOutOfMemoryException exception];
+
+ @try {
+ struct DomainNameServerNode *iter =
+ (struct DomainNameServerNode *)&nameServerList->lh_Head;
+
+ while (iter->dnsn_MinNode.mln_Succ != NULL) {
+ if (iter->dnsn_UseCount != 0 &&
+ iter->dnsn_Address != NULL) {
+ OFString *address = [OFString
+ stringWithCString: iter->dnsn_Address
+ encoding: encoding];
+
+ [nameServers addObject: address];
+ }
+
+ iter = (struct DomainNameServerNode *)
+ iter->dnsn_MinNode.mln_Succ;
+ }
+ } @finally {
+ ReleaseDomainNameServerList(nameServerList);
+ }
+
+ if (nameServers.count > 0) {
+ [nameServers makeImmutable];
+ _nameServers = [nameServers copy];
+ }
+
+ if (GetDefaultDomainName(buffer, sizeof(buffer)))
+ _localDomain = [[OFString alloc] initWithCString: buffer
+ encoding: encoding];
+}
+#endif
+
+#ifdef OF_NINTENDO_3DS
+- (void)obtainNintendo3DSSytemConfig
+{
+ OFMutableArray *nameServers = [OFMutableArray array];
+ union {
+ /*
+ * For some unknown reason, this needs a 336 bytes buffer and
+ * always returns 336 bytes.
+ */
+ char bytes[336];
+ SOCU_DNSTableEntry entries[2];
+ } buffer;
+ socklen_t optLen = sizeof(buffer);
+
+ if (SOCU_GetNetworkOpt(SOL_CONFIG, NETOPT_DNS_TABLE,
+ &buffer, &optLen) != 0)
+ return;
+
+ /*
+ * We're fine if this gets smaller in a future release (unlikely), as
+ * long as two entries still fit.
+ */
+ if (optLen < sizeof(buffer.entries))
+ return;
+
+ for (uint_fast8_t i = 0; i < 2; i++) {
+ uint32_t ip = OF_BSWAP32_IF_LE(buffer.entries[i].ip.s_addr);
+
+ if (ip == 0)
+ continue;
+
+ [nameServers addObject: [OFString stringWithFormat:
+ @"%u.%u.%u.%u", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
+ (ip >> 8) & 0xFF, ip & 0xFF]];
+ }
+
+ if (nameServers.count > 0) {
+ [nameServers makeImmutable];
+ _nameServers = [nameServers copy];
+ }
+}
+#endif
+
+- (void)reload
+{
+ void *pool;
+#ifdef OF_WINDOWS
+ OFString *path;
+#endif
+
+ /*
+ * TODO: Rather than reparsing every time, check what actually changed
+ * (mtime) and only reset those.
+ */
+
+ if (_lastConfigReload != nil && _configReloadInterval > 0 &&
+ _lastConfigReload.timeIntervalSinceNow < _configReloadInterval)
+ return;
+
+ pool = objc_autoreleasePoolPush();
+
+ [self setDefaults];
+
+#if defined(OF_WINDOWS)
+# ifdef OF_HAVE_FILES
+ path = [[OFWindowsRegistryKey localMachineKey]
+ stringForValue: @"DataBasePath"
+ subkeyPath: @"SYSTEM\\CurrentControlSet\\Services\\"
+ @"Tcpip\\Parameters"];
+ path = [path stringByAppendingPathComponent: @"hosts"];
+
+ if (path != nil)
+ [self parseHosts: path];
+# endif
+
+ [self obtainWindowsSystemConfig];
+#elif defined(OF_AMIGAOS4)
+ [self parseHosts: HOSTS_PATH];
+ [self obtainAmigaOS4SystemConfig];
+#elif defined(OF_NINTENDO_3DS)
+ [self obtainNintendo3DSSytemConfig];
+#elif defined(OF_HAVE_FILES)
+ [self parseHosts: HOSTS_PATH];
+ [self parseResolvConf: RESOLV_CONF_PATH];
+#endif
+
+ if (_staticHosts == nil) {
+ OFArray *localhost =
+#ifdef OF_HAVE_IPV6
+ [OFArray arrayWithObjects: @"::1", @"127.0.0.1", nil];
+#else
+ [OFArray arrayWithObject: @"127.0.0.1"];
+#endif
+
+ _staticHosts = [[OFDictionary alloc]
+ initWithObject: localhost
+ forKey: @"localhost"];
+ }
+
+ if (_nameServers == nil)
+#ifdef OF_HAVE_IPV6
+ _nameServers = [[OFArray alloc]
+ initWithObjects: @"127.0.0.1", @"::1", nil];
+#else
+ _nameServers = [[OFArray alloc] initWithObject: @"127.0.0.1"];
+#endif
+
+#ifndef OF_WII
+ if (_localDomain == nil)
+ _localDomain = [domainFromHostname() copy];
+#endif
+
+ if (_searchDomains == nil) {
+ if (_localDomain != nil)
+ _searchDomains = [[OFArray alloc]
+ initWithObject: _localDomain];
+ else
+ _searchDomains = [[OFArray alloc] init];
+ }
+
+ objc_autoreleasePoolPop(pool);
+}
+@end