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

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:

  • SWI 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.
  • SWI 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:

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:

OffsetNameContents
0h_namePointer to host name
4h_aliasesPointer to 0 terminated list of pointers to aliases for this host
8h_addrtypeAddress type (usually AF_INET)
12h_lengthAddress length (4 for AF_INET)
16h_addr_listPointer to 0 terminated list of addresses

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.

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 SWI 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 DNS servers to query

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

Local host name, without any period.

Inet$LocalDomain
Local domain name

Local domain name. When applied to Inet$Hostname provides the Fully Qualified Domain Name of this host.

Inet$SearchDomains
Domains to search for unqualified addresses

Space separated list of IP domain names to search for unqualified addresses.

Inet$ResolverRetries
Number of retries to perform when lookups fail

Number of retries to perform when lookups fail.

Inet$ResolverDelay
Delay between retries when lookups fail

Delay in seconds between retry attempts when lookups fail.

Inet$ResolverServer
Whether the Resolver acts as a simple DNS server

Set if the Resolver module should act as a simple DNS server to other machines. Unset if it should not.

Inet$ResolverFreewayHosts
Whether the Resolver uses the names provided by Freeway

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
Whether the Resolver uses the names provided by LanManFS

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
Whether the Resolver reorders the servers by response time

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.

SWI Calls

Resolver_GetHostByNameSWI &46000
Resolve a host name, waiting for the result
R1=Pointer to host name string, 0 terminated
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
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI is provided primarily for backwards compatibility since new network applications can use the more flexible SWI Resolver_GetHost SWI as described below.

The main use of this SWI is by the simple ports of unix applications using the gethostbyname() function call.

Interrupt status is undefined. Fast interrupts are enabled. Processor is in SVC mode. The SWI is not reentrant, except where preempted with UpCall 6.

Resolver_GetHostSWI &46001
Resolve a host name in the background
R1=Pointer to host name string, 0 terminated
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
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This SWI provides a DNS resolution facility that runs in the background (unlike SWI Resolver_GetHostByName) 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.

Interrupt status is undefined. Fast interrupts are enabled. Processor is in SVC mode. The SWI is not reentrant.

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

Resolver_GetCacheSWI &46002
Internal call
None
None
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

This call is for internal use only; you must not use it in your own code.

Resolver_CacheControlSWI &46003
Control the Resolver cache
R0=Reason code:
ReasonMeaning
0Flush cache of failed lookups
1Flush cache of all items
2Flush cache of hosts file items
3Re-read configuration
8Disable caching of failed lookups
9Enable caching of failed lookups
Other reason codes are reserved
R0 - R1preserved
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
SWI is not re-entrant

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.

All registers are preserved. Interrupt status is undefined. Fast interrupts are enabled. Processor is in SVC mode. The SWI is not reentrant.

Events

Vector EventV 102Internet_DNSResolveCompleteVector &10
A DNS resolution has completed
R0=19 (Event_Internet)
R1=&102 (Event_Internet_DNSResolveComplete, 258)
R2=Pointer to name being resolved
R3=IP address requested in Network Byte Order, if a numeric request failed:
ValueMeaning
&00000000A numeric request was not made
&FFFFFFFFA 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
R0 - R5preserved
Interrupts are undefined
Fast interrupts are enabled
Processor is in SVC mode
Vector is not re-entrant

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.

Interrupt status is undefined. Fast interrupts are enabled. Processor is in SVC mode.