4.12.1.17 DNS Functions

Most DNS-related functions cache their results in the database ‘dns’, so no matter how many times you use a particular function in your startup program, it will result in at most one actual DNS lookup. See DNS Cache Management, for the description of the database and its management.

The functions are implemented in two layers: primitive built-in functions which raise exceptions if the lookup fails, and library calls that are warranted to always return meaningful value without throwing exceptions.

The built-in layer is always available. The library calls become available after requesting ‘dns.mf’ module (see section Modules):

 
require dns
Built-in Function: string dns_getaddr (string domain)

Returns a whitespace-separated list of IP addresses (A records) for domain. At most 64 addresses are returned.

This function does not use the DNS cache.

Built-in Function: string dns_getname (string ipstr)

Returns a whitespace-separated list of domain names (PTR records) for the IPv4 address ipstr. At most 64 names are returned.

This function does not use the DNS cache.

Built-in Function: string getmx (string domain   [, number ip])

Returns a whitespace-separated list of ‘MX’ names (if ip is not given or if it is 0) or ‘MXIP addresses (if ip!=0)) for domain. Within the returned string, items are sorted in order of increasing ‘MX’ priority. If domain has no ‘MX’ records, an empty string is returned. If the DNS query fails, getmx raises an appropriate exception.

Examples:

 
getmx("mafra.cz") ⇒ "smtp1.mafra.cz smtp2.mafra.cz relay.iol.cz"
getmx("idnes.cz") ⇒ "smtp1.mafra.cz smtp2.mafra.cz relay.iol.cz"
getmx("gnu.org")  ⇒ "mx10.gnu.org mx20.gnu.org"
getmx("org.pl") ⇒ ""

Notes:

  1. The getmx function returns at most 32 MX names or IP addresses.
  2. The number of items returned by getmx(domain) can differ from that obtained from getmx(domain, 1), e.g.:
     
    getmx("aol.com")
      ⇒ mailin-01.mx.aol.com mailin-02.mx.aol.com
                mailin-03.mx.aol.com mailin-04.mx.aol.com
    getmx("aol.com", 1)
      ⇒ 64.12.137.89 64.12.137.168 64.12.137.184
                64.12.137.249 64.12.138.57 64.12.138.88
                64.12.138.120 64.12.138.185 205.188.155.89
                205.188.156.185 205.188.156.249 205.188.157.25
                205.188.157.217 205.188.158.121 205.188.159.57
                205.188.159.217
    
  3. This interface will change in future releases, when array data types are implemented.

Built-in Function: boolean primitive_hasmx (string domain)

Returns true if the domain name given by its argument has any ‘MX’ records.

If the DNS query fails, this function throws failure or temp_failure.

Library Function: boolean hasmx (string domain)

Returns true if the domain name given by its argument has any ‘MX’ records.

Otherwise, if domain has no ‘MX’s or if the DNS query fails, hasmx returns false.

Built-in Function: string primitive_hostname (string ip)

The ip argument should be a string representing an IP address in dotted-quad notation. The function returns the canonical name of the host with this IP address obtained from DNS lookup. For example

 
primitive_hostname (${client_addr})

returns the fully qualified domain name of the host represented by Sendmail variable ‘client_addr’.

If there is no ‘PTR’ record for ip, primitive_hostname raises the exception e_not_found.

If DNS query fails, the function raises failure or temp_failure, depending on the character of the failure.

Library Function: string hostname (string ip)

The ip argument should be a string representing an IP address in dotted-quad notation. The function returns the canonical name of the host with this IP address obtained from DNS lookup.

If there is no ‘PTR’ record for ip, or if the lookup fails, the function returns ip unchanged.

The previous mailfromd versions used the following paradigm to check if an IP address resolves:

 
  if hostname(%ip) != %ip
    ...

Built-in Function: boolean primitive_ismx (string domain,   string host)

The domain argument is any valid domain name, the host is a host name or IP address.

The function returns true if host is one of the ‘MX’ records for the domain.

If domain has no ‘MX’ records, primitive_ismx raises exception e_not_found.

If DNS query fails, the function raises failure or temp_failure, depending on the character of the failure.

Library Function: boolean ismx (string domain,   string host)

The domain argument is any valid domain name, the host is a host name or IP address.

The function returns true if host is one of the ‘MX’ records for the domain. Otherwise it returns false.

If domain has no ‘MX’ records, or if the DNS query fails, the function returns false.

Built-in Function: string primitive_resolve (string host,   [string domain])

Reverse of primitive_hostname. The primitive_resolve function returns the IP address for the host name specified by host argument. If host has no A records, the function raises the exception e_not_found.

If DNS lookup fails, the function raises failure or temp_failure, depending on the character of the failure.

If the optional domain argument is given, it will be appended to host (with an intermediate dot), before querying the DNS. For example, the following two expressions will return the same value:

 
primitive_resolve("puszcza.gnu.org.ua")
primitive_resolve("puszcza", "gnu.org.ua")

There is a considerable internal difference between one-argument and two-argument forms of primitive_resolve: the former queries DNS for an ‘A’ record, whereas the latter queries it for any record matching host in the domain domain and then selects the most appropriate one. For example, the following two calls are equivalent:

 
primitive_hostname("213.130.0.22")
primitive_resolve("22.0.130.213", "in-addr.arpa")

This makes it possible to use primitive_resolve for querying DNS black listing domains. See match_dnsbl, for a working example of this approach. See also match_rhsbl, for another practical example of the use of the two-argument form.

Library Function: string resolve (string host,   [string domain])

Reverse of hostname. The resolve function returns IP address for the host name specified by host argument. If the host name cannot be resolved, or a DNS failure occurs, the function returns ‘"0"’.

This function is entirely equivalent to primitive_resolve (see above), except that it never raises exceptions.

All the functions above use DNS cache database for caching DNS answers. The database is normally named ‘statedir/dns.db’ (See Local state directory, for the description of statedir), but its actual name and location can be set at the run time using database dns configuration file statement (see section Database Configuration). Each record in the database consists of expiration time in seconds since the Epoch and the actual answer, which depends on the type of the query (see below).

When called, any DNS function first looks if the corresponding query is in the ‘dns’ database. It does so by building a lookup key, which consists of query type and query argument separated by a single whitespace. The query type is:

A for resolve
PTR for hostname
MX for hasmx and ismx

If the lookup key is present in the database and its expiration time is not yet reached, the corresponding answer from the database is returned. Otherwise, the function performs actual DNS lookup, stores the obtained data in the database and returns it.

The expiration date for each new record is obtained by increasing the current system timestamp by the value of TTL obtained from the DNS reply. If the latter carried several TTLs (e.g. if it was an ‘MX’ request), the smallest of them is used.

If the DNS lookup failed, the result is stored in the database as well. In this case, the value part of the record consists only of the expiration time (negative caching). It is computed by adding to the current timestamp the negative expiration period, which defaults to 3600 seconds. The negative expiration period can be configured using the negative-expire-interval configuration file statement (see section negative-expire-interval).

Thus, there are two statements in the configuration file that control the settings of the DNS databases. The following example illustrates them:

 
database dns {
  file "/var/run/mailfromd/dns.db";
  negative-expire-interval 7200;
}  

The contents of the DNS database can be listed using the following command:

 
$ mailfromd --list --format=dns
# or:
$ mailfromd --list -Hdns

You can look up a particular entry as well. For example:

 
$ mailfromd --list -Hdns "A mx10.gnu.org"
A mx10.gnu.org: Sun Dec  3 10:56:12 2006 199.232.76.166

The above example shows that the IP address of ‘mx10.gnu.org’ and that it expires on Sunday, December 3d, at 10:56:12.

Of course, the rest of database management options are also valid for DNS database. See section Database Maintenance, for more information on these.