Resolver
Introduction
Internet based applications are required to connect to other hosts throughout the world. Location of these hosts is via numeric addresses which are determined by human readable names. The process of converting from names to addresses is performed by 'Domain Name Servers' (DNS).
Under RISC OS, communication with DNS is performed by the Resolver module.
This chapter describes how the Resolver module is configured to use DNS, and how applications should interact with it.
Terminology used
- The Resolver module provides shared Internet IP address resolution facilities to the system.
- The Hosts file is the file InetDBase:Hosts. It is used to initialise the local DNS cache with entries.
- DNS servers are queried by the Resolver and the results are cached.
Application is used within this chapter as a description of the Resolver querist, but this may also apply to Modules.
Technical details
How the Resolver works
The Resolver works as follows :
- The user configures the resolver through serial variables. Usually this is performed on machine start up from pre-set values.
- When an address is requested the application requests a lookup from the Resolver.
- The Resolver module checks its cached entries and if one exists that matches the request it is returned immediately. Otherwise a request is sent to the configured DNS servers.
- The application continues to request a lookup from the Resolver. The Resolver continues to try to look up the request until it times out.
- If the request to the DNS servers is satisfied or a failure is returned the result is returned to the application.
- If the request is not responded to within a period a failure is returned to the application.
SWIs used
The module provides two interfaces for resolving addresses :
- Resolver_GetHostByName to provide an equivalent operation to that expected by unix applications. This SWI will not return until a result or failure has been determined.
- Resolver_GetHost to provide a multi-tasking version of GetHostByName. This SWI returns a notification that the resolve is 'in progress' and should be polled until a result has been received.
In addition, there is a means for controlling the cache :
- Resolver_CacheControl can be used to perform various operations on the cache.
Host entries
All results are returned in the form of NetBSD standard 'hostent' structures. These structures should be considered to be read only by the application.
A hostent has the following structure :
Offset Data
0 Pointer to host name
4 Pointer to 0 terminated list of pointers to aliases for this host
8 Address type (usually AF_INET)
12 Address length (4 for AF_INET)
16 Pointer to 0 terminated list of addresses
System variables
The Resolver module uses a number of system variables for its configuration. These determine how and where it resolves Internet addresses from. In general, these variables are initialised during machine startup. They may be modified by the user once the Internet stack has started. They will be read when the re-configure call is made to the Resolver, either via the Resolver_CacheControl SWI or by the *ResolverConfig command. In addition, they will be re-read whenever the InetDBaseChanged service is issued.
Inet$Resolvers
Space separated list of dotted IP addresses of DNS servers to query. Up to three addresses may be supplied. The word 'auto' may be appended to the name in order to perform automatic resolver detection.
Inet$Hostname
Local host name, without any period.
Inet$LocalDomain
Local domain name. When applied to Inet$Hostname provides the Fully Qualified Domain Name of this host.
Inet$SearchDomains
Space separated list of IP domain names to search for unqualified addresses.
Inet$ResolverRetries
Number of retries to perform when lookups fail.
Inet$ResolverDelay
Delay in seconds between retry attempts when lookups fail.
Inet$ResolverServer
Set if the Resolver module should act as a simple DNS server to other machines. Unset if it should not.
Inet$ResolverFreewayHosts
Set to 1 if the Resolver module should use the names provided by Freeway in order to provide its resolutions. If unset it is treated as enabled. Set to 0 to disable.
Inet$ResolverNetBIOSHosts
Set to 1 if the Resolver module should use the names provided by LanManFS in order to provide its resolutions. If unset it is treated as enabled. Set to 0 to disable.
Inet$ResolverReorder
Set to 1 if the Resolver module should attempt to reorder the servers based on their response times. If unset or set to 0, it is treated as disabled.
Automatic resolver detection
The Resolver module can automatically detect the local systems which are acting as DNS servers. If the word 'auto' is appended to the list of resolvers the automatic search will be triggered. The method employed uses a broadcast request for a name resolution and a broadcast 'ping' of the local network. The systems responding to the broadcast 'ping' are directly queried for DNS services. As this option is only intended to be used on small networks, the traffic this incurs should be minimal. Larger networks should not use the automatic detection. Any host which responds is added to the list of servers, up to the maximum of 3. The automatic detection will be forced every hour, or when the *ResolverConfig command is issued.
Resolver reordering
The Resolver module can reorder the list of servers which it queries periodically if the 'Inet$ResolverReorder' variable is set to 1. This means that if the primary server is responding slowly it will be moved lower down the list, giving the secondary (or tertiary) servers an opportunity to respond faster. As response times can change greatly based on the local and global network activity this can have both a detrimental as well as beneficial effect. The main benefit from this behaviour is to move a non-responsive server to the end of the list dynamically whilst in use. If a number of servers are known to be available but their availability is variable the automatic reordering of the servers may help. Similarly, if the system is moving between networks with different DNS servers the system can recover more quickly despite having not changed the servers which it uses.
Because the option for reordering servers can have unexpected results, it is disabled by default.
SWI calls
Resolver_GetHostByName (SWI &46000)
On entry
R1 = pointer to host name string, 0 terminated
On exit
R0 = errno integer value if V flag is clear, or error block pointer if V flag is set
R1 = pointer to completed 'hostent' struct if successful, or 0 if failed
Interrupt status is undefined Fast interrupts are enabled
Processor is in SVC mode
SWI is not reentrant, except where preempted with UpCall 6
This SWI is provided primarily for backwards compatibility since new network applications can use the more flexible _GetHost SWI as described below.
The main use of this SWI is by the simple ports of unix applications using the gethostbyname() function call.
Related SWIs - Resolver_GetHost
Resolver_GetHost (SWI &46001)
On entry
R1 = pointer to host name string, 0 terminated
On exit
R0 = errno integer value if V flag is clear or error block pointer if V flag is set
R1 = pointer to completed 'hostent' struct if successful, or 0 if failed
Interrupt status is undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not reentrant
This SWI provides a DNS resolution facility that runs in the background (unlike Resolver_GetGostByName) above. Applications must poll the Resolver module for the state of the resolution. Sample code for this is given below.
If the hostname is a valid cache item or present in the hosts file on disc it is returned immediately in R1, with R0 set to 0.
If the hostname is a cache item, marked as failed, then R1 is set to 0 and R0 is either -1 (host not found), or -2 (remote failure. eg. configured resolver didn't respond).
If the hostname is a cache item, marked as pending, then R1 is set to 0 and R0 is EINPROGRESS (36 decimal). Items are marked as pending when a remote resolver lookup is in progress. The calling program is expected to periodically call Resolver_GetHost until a valid hostent is returned, or an error condition occurs.
Because name lookups can take anything up to 20 seconds or so it is important to be able to give feedback to the user on the status of the lookup, as well as giving the foreground application time to perform other tasks.
Cache sweeps occur periodically - pending items are marked as failed (remote failure) after a short period, failed items are removed after a longer period, and valid items are removed after their designated TTL has expired and remain valid for a further 90 seconds.
Previous documents have stated that cache entries remain valid for 24 hours, however this is not the case. Until version 0.94 entries would expire only when queried and only then after the server-declared TTL had expired. This effectively meant that the hostent structures were of variable lifetime. From 0.94 onward the cache will be checked regularly and entries expired only after TTL+90 seconds has expired - this means that you are guaranteed that the hostent structure will exist for 90 seconds after the SWI call, no matter what the returned TTL value was or when the original cache entry was read,
If there is a configuration error (such as Inet$Resolvers not being set) then a RISC OS error block pointer is returned in R0, and the V flag is set on exit.
Example
The calling program should run something like;
REM 'EINPROGRESS' error number is 36 decimal
REPEAT
SYS "Resolver_GetHost","host.net" TO status,hostent;flags
error = (flags AND 1) == 1
REM Perhaps inform user of the state of this lookup
UNTIL (error) OR (status != EINPROGRESS)
REM hostent is a valid pointer, or 0
Related SWIs - Resolver_GetHostByName
Resolver_GetCache (SWI &46002)
This call is for internal use only; you must not use it in your own code.
Resolver_CacheControl (SWI &46003)
On entry
R0 = reason code :
0 = Flush cache of failed lookups
1 = Flush cache of all items
2 = Flush cache of hosts file items
3 = Re-read configuration
8 = Disable caching of failed lookups
9 = Enable caching of failed lookups
Other reason codes are reserved
On exit
All registers preserved
Interrupt status is undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not reentrant
This SWI is provided to allow a calling application to control the Resolver cache in a limited way. Currently, the only reason codes supported are to force flushes of certain cache entries, and enabling or disabling of the caching of lookups that fail.
Caching of lookup failures is disabled by default. You might wish to enable the caching of lookup failures if you are sure that any failures are genuine bad host errors and not due to packet loss, remote server timeouts, etc.
Related SWIs - Resolver_GetHostByName
Events
Event_Internet (19)
Event_Internet_DNSResolveComplete (258)
On entry
R0 = Event_Internet (19)
R1 = Event_Internet_DNSResolveComplete (258)
R2 = pointer to name being resolved
R3 = IP address requested in Network Byte Order, if a numeric request failed
&00000000 if a numeric request was not made
&FFFFFFFF if a numeric request was made and has been satisfied by this result
R4 = error code (as returned by Resolver_GetHost)
R5 = pointer to a 'hostent' structure, or NULL if failed
On exit
R0-R5 preserved
Interrupt status is undefined
Fast interrupts are enabled
Processor is in SVC mode
This event is raised by the Resolver module when a resolution request completes, either successfully or by timing out.
This event should not be claimed by any module. Other modules may be interested in the resolution and a claim would prevent them from seeing the resolution results. Modules should take care when using the information provided within this event not to assume that the non-match of the string in R2 means that the resolution was for another address. For example, resolution requests will be converted to lower case by the module before being processed, numeric lookups may be converted to their canonical form, and the results may be returned for a different cache entry in cases where the address returned is an alias. In general, most clients will merely re-issue the Resolver_GetHost request to obtain the state of the resolution, using this event as an indication that some resolution has completed.
|