Chapter 13

DNS Client Library

Used files:
dns.scm
Name of the package:
dns

13.1  Overview

The dns structure contains a library for querying DNS servers. The library contains sophisticated replacements for scsh's interface to the gethostbyname and gethostbyaddr and many extensions to these functions.

The main features of the libraray include:

13.2  Conditions

The library defines a set of conditions raised by the procedures of the library. The supertype of these conditions is dns-error.

(dns-error? thing)     --->     boolean         (procedure) 
The predicate for dns-error conditions.

(dns-error->string dns-error-condition)     --->     string         (procedure) 
Returns a string with the description of the condition.

parse-error         condition 
unexpected-eof-from-server         condition 
bad-address         condition 
no-nameservers         condition 
bad-nameserver         condition 
not-a-hostname         condition 
not-a-ip         condition 

dns-format-error         condition 
dns-server-failure         condition 
dns-name-error         condition 
dns-not-implemented         condition 
dns-refused         condition 
These conditons correspond to errors returned by the DNS server. They are all subtypes of the dns-server-error condition which in turn is a subtype of dns-error.

(dns-server-error? thing)     --->     boolean         (procedure) 
The predicate for dns-server-error conditions.

(parse-error? thing)     --->     boolean         (procedure) 
(unexpected-eof-from-server? thing)     --->     boolean         (procedure) 
(bad-address? thing)     --->     boolean         (procedure) 
(no-nameservers? thing)     --->     boolean         (procedure) 
(bad-nameserver? thing)     --->     boolean         (procedure) 
(not-a-hostname? thing)     --->     boolean         (procedure) 
(not-a-ip? thing)     --->     boolean         (procedure) 
(dns-format-error? thing)     --->     boolean         (procedure) 
(dns-server-failure? thing)     --->     boolean         (procedure) 
(dns-name-error? thing)     --->     boolean         (procedure) 
(dns-not-implemented? thing)     --->     boolean         (procedure) 
(dns-refused? thing)     --->     boolean         (procedure) 
The type predicates for the conditions above.

13.3  High-level Interface

The library uses an internal store to cache data obtained from DNS servers. All procedures take a boolean flag use-cache? that indicates whether the cache should be used or not. use-cache? defaults to true.

(dns-clear-cache!)     --->     undefined         (procedure) 
This procedure erases all information stored in the internal cache.

The library is further capable of parsing the contents of /etc/resolv.conf (see Section 13.5). The nameservers listed there are the default value for the optional argument nameserver list which many procedures of the library accept. Nameserver is either a IP-address or a dotted IP string.

(dns-lookup-name FQDN [nameserver list][use-cache?])     --->     IP-address         (procedure) 
Given the FQDN of a host, dns-lookup-ip returns the IP address. The optional argument specifes the name servers to query, it defaults to the ones found in /etc/resolv.conf.

(dns-lookup-ip IP-string/IP-address [nameserver list][use-cache?])     --->     FQDN         (procedure) 
Looks up the FQDN for the given IP address. The optional argument specifes the name servers to query, it defaults to the ones found in /etc/resolv.conf.

(dns-lookup-nameserver IP-string/IP-address [nameserver list][use-cache?])     --->     IP-address list         (procedure) 
Looks up an authoritative name server for a hostname, returns a list of name servers.

(dns-lookup-mail-exchanger IP-string/IP-address [nameserver list][use-cache?])     --->     FQDN list         (procedure) 
Looks up mail-exchangers for a hostname und returns them in a list sorted by preference.

(socket-address->fqdn socket-address [nameserver list][use-cache?])     --->     FQDN         (procedure) 
Returns the FQDN for of the address bound to argument. The argument cache? indicates whether the internal cache may be queried to obtain the information.

(maybe-dns-lookup-name FQDN [nameserver list][use-cache?])     --->     IP-address or #f         (procedure) 
(maybe-dns-lookup-ip IP-string/IP-address [nameserver list][use-cache?])     --->     FQDN or #f         (procedure) 
These procedures provide the same functionality as dns-lookup-name and dns-lookup-ip but return #f in case of an dns-error.

(host-fqdn name/socket-address [nameserver list][use-cache?])     --->     FQDN         (procedure) 
(system-fqdn [nameserver list][use-cache?])     --->     FQDN         (procedure) 
host-fqdn returns the fully qualified domain name (FQDN) for its argument which can be either a unqualified host name or a socket address. The procedure system-fqdn returns the FQDN of the local host. These procedures use a list of domain names obtained from /etc/resolv.conf to the generate FQDNs and try to resolve these FQDNs.

13.4  Low-level Interface

This section describes a set of data structures and procedures which directly correspond to the data flow of the DNS protocol. The central entity is a message, the abstraction of the packet sent to the server or received from the server (The DNS protocol uses the same data format for both directions). A dns-message encapsulates the query message sent to the server, the response message received from the server, and some additional information the library gathered while generating the dns-message.

(dns-get-information message protocol answer-okay? [nameserver list][use-cache?])     --->     dns-message         (procedure) 
Most general way to submit a DNS query. The message is sent to the name servers via protocol which can be either (network-procotcol tcp) or (network-protocol udp), both members of of the enumerated type network-protocol. After receiving the reply, dns-get-information applies the predicate answer-okay? to the message. If it returns #f and the answer is not authoritative additional name servers sent with the reply are checked until an authoritative answer is found. If the predicate returns #f but the answer is authoritative a bad-address condition is signalled.

(network-protocol protocol-name)     --->     network-protocol         (syntax) 
(network-protocol? thing)     --->     boolean         (procedure) 
Constructor and predicate for the enumerated type network-protocol with the possible protocol names tcp and udp.

(dns-lookup IP-string/IP-address type [nameserver list][use-cache?])     --->     dns-message         (procedure) 
Convenient shortcut to submit a DNS query. The return value is a dns-message structure:

(dns-message? thing)     --->     boolean         (procedure) 
(dns-message-query dns-message)     --->     message         (procedure) 
(dns-message-reply dns-message)     --->     message         (procedure) 
(dns-message-cache? dns-message)     --->     boolean         (procedure) 
(dns-message-protocol dns-message)     --->     protocol         (procedure) 
(dns-message-tried-nameservers dns-message)     --->              (procedure) 
A dns-message records the query sent to the server and the reply from the server. It also contains information whether the library took the reply from the cache, which protocol was used and to which nameservers the query was sent.

(pretty-print-dns-message dns-message [output-port])     --->     undefined         (procedure) 
Pretty prints a DNS message to out-port which defaults to the current output port.

(message? thing)     --->     boolean         (procedure) 
(message-header message)     --->     header         (procedure) 
(message-questions message)     --->     question list         (procedure) 
(message-answers message)     --->     resource-record list         (procedure) 
(message-nameservers message)     --->     resource-record list         (procedure) 
(message-additionals message)     --->     resource-record list         (procedure) 
(message-source message)     --->     char list         (procedure) 
A message represents the data sent to the DNS server or received from the DNS server. The DNS protocol uses the same message format for queries and replies. In queries only the header and the questions is present, a reply may contain answers, name servers and and additional informations as resource records. Message-source returns the actual data sent over the network.

(make-query-message header header question [questions])     --->     message         (procedure) 
The procedure generates a message the supplied questions, header, and the standard message values for queries.

(make-simple-query-message name type class)     --->     message         (procedure) 
This simplified constructor generates a message with one question which is built from the parameters, and the standard header flags for queries and the standard message values for queries.

(header? thing)     --->     boolean         (procedure) 
(header-id header)     --->     number         (procedure) 
(header-flags header)     --->     flags         (procedure) 
(header-question-count header)     --->     number         (procedure) 
(header-answer-count header)     --->     number         (procedure) 
(header-nameserver-count header)     --->     number         (procedure) 
(header-additional-count header)     --->     number         (procedure) 
Every DNS message contains a header which stores information about the data present in the message and contains flags for the query.

(flags? thing)     --->     boolean         (procedure) 
(flags-query-type flags)     --->     'query or 'response         (procedure) 
(flags-opcode flags)     --->     number         (procedure) 
(flags-authoritative? flags)     --->     boolean         (procedure) 
(flags-truncated? flags)     --->     boolean         (procedure) 
(flags-recursion-desired? flags)     --->     boolean         (procedure) 
(flags-recursion-available? flags)     --->     boolean         (procedure) 
(flags-z flags)     --->     0         (procedure) 
(flags-response-code flags)     --->     number         (procedure) 
Flags occur within the header of a DNS message. The boolean value returned from flags-authoritative indicates whether the message was sent from a authoritative server, flags-truncated? should always be #fas the library automatically uses the TCP protocol is the UDP message size is not sufficied.

(question? thing)     --->     boolean         (procedure) 
(question-name question)     --->     string         (procedure) 
(question-type question)     --->     message-type         (procedure) 
(question-class question)     --->     message-class         (procedure) 
A question sent to the DNS server.
The type and class of the question and answer are elements of enumerated types:

(message-class class-name)     --->     message-class         (syntax) 
(message-class? thing)     --->     boolean         (procedure) 
(message-class-name message-class)     --->     symbol         (procedure) 
(message-class-number message-class)     --->     number         (procedure) 
message-class constructs a member of the enumerated type, message-class? is the type predicate, message-class-name returns the symbol and message-class-number the number used for the class in the DNS protocol.
The possible names for the classes are:
in
The Internet
cs
obsolete
ch
the CHAOS class
hs
Hesoid

(message-type type-name)     --->     message-type         (syntax) 
(message-type? thing)     --->     boolean         (procedure) 
(message-type-name message-type)     --->     symbol         (procedure) 
(message-type-index message-type)     --->     number         (procedure) 
message-type constructs a member of the enumeration from name <.type-name.> listed in Table 2. message-type? is the type predicate, message-type-name returns the name, and message-type-number the number used for the class the DNS protocol.


aa host address
nsan authoritative name server
md(obsolete)
mf(obsolete)
cnamethe canonical name for an alias
soamarks the start of a zone of authority
mb(experimental)
mg(experimental)
mr(experimental)
null(experimental)
wksa well known service description
ptra domain name pointer
hinfohost information
minfo(experimental)
mxmail exchange
txttext strings
Table 2:  Message types


(resource-record? thing)     --->     boolean         (procedure) 
(resource-record-name resource-record)     --->     string         (procedure) 
(resource-record-type resource-record)     --->     message-type         (procedure) 
(resource-record-class resource-record)     --->     message-class         (procedure) 
(resource-record-ttl resource-record)     --->     number         (procedure) 
(resource-record-data resource-record)     --->     resource-record-data-...         (procedure) 
A resource record as returned from the DNS server. The actual data of the record is stored in the resource-record-data field. It is one of the record types for resource record data described below.

(resource-record-data-a? thing)     --->     boolean         (procedure) 
(resource-record-data-a-ip resource-record-data-a)     --->     IP-address         (procedure) 
An address resource record which holds an internet address.

(resource-record-data-ns? thing)     --->     boolean         (procedure) 
(resource-record-data-ns-name resource-record-data-ns)     --->     FQDN         (procedure) 
A name server resource record containing the FQDN of the name server.

(resource-record-data-cname? thing)     --->     boolean         (procedure) 
(resource-record-data-cname resource-record-data-cname)     --->     FQDN         (procedure) 
A canonical name resource record which contains the canonical or primary name of the owner.

(resource-record-data-mx? thing)     --->     boolean         (procedure) 
(resource-record-data-mx-preference resource-record-data-mx)     --->     number         (procedure) 
(resource-record-data-mx-exchanger resource-record-data-mx)     --->     FQDN         (procedure) 
A mail exchange resource record with the preference and the FQDN of a host willing to act as a mail exchange.

(resource-record-data-ptr? thing)     --->     boolean         (procedure) 
(resource-record-data-ptr-name resource-record-data-ptr)     --->     string         (procedure) 
A pointer resource record which points to some other domain name.

(resource-record-data-soa? thing)     --->     boolean         (procedure) 
(resource-record-data-soa-mname resource-record-data-soa)     --->     FQDN         (procedure) 
(resource-record-data-soa-rname resource-record-data-soa)     --->     FQDN         (procedure) 
(resource-record-data-soa-serial resource-record-data-soa)     --->     number         (procedure) 
(resource-record-data-soa-refresh resource-record-data-soa)     --->     number         (procedure) 
(resource-record-data-soa-retry resource-record-data-soa)     --->     number         (procedure) 
(resource-record-data-soa-expire resource-record-data-soa)     --->     number         (procedure) 
(resource-record-data-soa-minimum resource-record-data-soa)     --->     number         (procedure) 
A start of a zone of authority resource record.
The protocol specifies other possible values for the resource-record-data field but we where no able to find test cases for them.

(cache? thing)     --->     boolean         (procedure) 
(cache-answer cache)     --->     dns-message         (procedure) 
(cache-ttl cache)     --->     number         (procedure) 
(cache-time cache)     --->     number         (procedure) 
A cache data structure corresponds to a saved answer to a previous query. cache-answer returns the saved message, cache-ttl returns the time when the cache entry expires and cache-time returns the time the entry was created.

13.5  Parsing /etc/resolv.conf

resolv.conf-parse-error         condition 

(resolv.conf-parse-error? thing)     --->     boolean         (procedure) 
The code signals the condition resolv.conf-parse-error if a parse error occurs while scanning /etc/resolv.conf. It is a subtype of the dns-error condition. resolv.conf-parse-error? is the type predicate for this condition.

(resolv.conf)     --->     symbol-->string alist         (procedure) 
Returns the contents of /etc/resolv.conv as an alist with the possible keys nameserver, domain, search, sortlist and options.

Note that the library caches the contents of /etc/resolv.conv and resolv.conf only really opens the file if its modification time is more recent than the modification time of the cache.

(parse-resolv.conf!)     --->     undefined         (procedure) 
Parses the contents of /etc/resolv.conv and updates the internal cache of the library.

(dns-find-nameserver-list)     --->     FQDN list         (procedure) 
Returns a list of name servers from /etc/resolv.conf

(dns-find-nameserver)     --->     FQDN         (procedure) 
Returns the first name servers found in /etc/resolv.conf. dns-find-nameserver raises no-nameservers if /etc/resolv.conf does not contain a nameserver entry.

(domains-for-search)     --->     string list         (procedure) 
Parses /etc/resolv.conf and extracts the domains specified by the search keyword.

13.6  IP Addresses as Dotted Strings

Used files:
ip.scm
Name of the package:
ips

The structure ips provides a small set of procedures for turning the human-readable form of IP addresses (``dotted strings'') into 32 bits numbers.

(address32->ip-string IP-address )     --->     ip-string         (procedure) 

(ip-string->address32 ip-string)     --->     IP-address         (procedure) 

(ip-string? string)     --->     boolean         (procedure) 
Tests whether string is a valid dotted string for an IP address.