Chapter 177. DNS
Table of Contents
177.1. DNS API
The DNS client uses the normal BSD API for performing lookups:
gethostbyname(),
gethostbyaddr()
,
getaddrinfo()
,
getnameinfo()
.
There are a few restrictions:
-
If the DNS server returns multiple authoritive records
for a host name to
gethostbyname
, the hostent will only contain a record for the first entry. If multiple records are desired, usegetaddrinfo
, which will return multiple results. -
The code has been made thread safe. ie multiple threads
may call
gethostbyname()
without causing problems to the hostent structure returned. What is not safe is one thread using bothgethostbyname()
andgethostbyaddr()
. A call to one will destroy the results from the previous call to the other function.getaddrinfo()
andgetnameinfo()
are thread safe and so these are the preferred interfaces. They are also address family independent so making it easier to port code to IPv6. - The DNS client will only return IPv4 addresses to RedBoot. At the moment this is not really a limitation, since RedBoot only supports IPv4 and not IPv6.
To initialise the DNS client the following function must be called:
#include <network.h> int cyg_dns_res_start(char * dns_server)
Where dns_server is the address of the DNS server. The address must be in numeric form and can be either an IPv4 or an IPv6 address.
There also exists a deprecated function to start the DNS client:
int cyg_dns_res_init(struct in_addr *dns_server)
where dns_server is the address of the DNS server the client should query. The address should be in network order and can only be an IPv4 address.
On error both this function returns -1, otherwise 0 for success. If lookups are attemped before this function has been called, they will fail and return NULL, unless numeric host addresses are passed. In this cause, the address will be converted and returned without the need for a lookup.
A default, hard coded, server may be specified in the CDL option
CYGDAT_NS_DNS_DEFAULT_SERVER
. The use of this is
controlled by CYGPKG_NS_DNS_DEFAULT
. If this is
enabled, init_all_network_interfaces()
will
initialize the resolver with the hard coded address. The DHCP client
or user code my override this address by calling
cyg_dns_res_init
again.
The DNS client understands the concepts of the target being in a domain. By default no domain will be used. Host name lookups should be for fully qualified names. The domain name can be set and retrieved using the functions:
int getdomainname(
char *name, size_t len)
;
int setdomainname(
const char *name, size_t len)
;
Alternatively, a hard coded domain name can be set using CDL.
The boolean CYGPKG_NS_DNS_DOMAINNAME
enables this
and the domain name is taken from
CYGPKG_NS_DNS_DOMAINNAME_NAME
.
Once set, the DNS client will use some simple heuristics when deciding how to use the domainname. If the name given to the client ends with a "." it is assumed to be a FQDN and the domain name will not be used. If the name contains a "." somewhere within it, first a lookup will be performed without the domainname. If that fails the domainname will be appended and looked up. If the name does not contain a ".", the domainname is appended and used for the first query. If that fails, the unadorned name is lookup.
The getaddrinfo
will return both IPv4 and
IPv6 addresses for a given host name, when IPv6 is enabled in
the eCos configuration. The CDL option
CYGOPT_NS_DNS_FIRST_FAMILY
controls the order
IPv6 and IPv4 addresses are returned in the linked list of
addrinfo
structures. If the value
AF_INET
is used, the IPv4 addresses will be
first. If the value AF_INET6
, which is the
default, is used, IPv6 address will be first. This ordering will
control how clients attempt to connect to servers, ie using IPv6
or IPv4 first.
177.2. DNS Client Testing
The DNS client has a test program, dns1.c, which tests many of
the features of the DNS client and the functions
gethostbyname(),
gethostbyaddr()
,
getaddrinfo()
,
getnameinfo()
.
In order for this test to work, a DNS server must be configured with a number of names and addresses. The following is an example forward address resolution database for bind v9, which explains the requirements.
@ 1D IN SOA @ hostmaster.ecoscentric.com. ( 2017022501 ; serial 3H ; refresh 2H ; retry 2W ; expiry 1D ) ; minimum 1D IN NS ns0 1D IN NS ns1 1D IN NS dns1.zoneedit.com. 1D IN NS dns2.zoneedit.com. albus 1D IN A 212.13.207.200 barn 1D IN A 87.127.120.188 farm 1D IN A 88.97.17.238 fawkes 1D IN A 212.13.207.202 www 1D IN CNAME albus www2 1D IN CNAME fawkes
The actual names and addresses do not matter, since they are configurable in the test. What is important is the relationship between the names and the addresses and there family. ie hostnamev4 should map to one IPv4 address. hostnamev46 should map to both an IPv4 and an IPv6 address. cnamev4 should be a CNAME record for hostname4. Reverse lookup information is also needed by the test.
The information placed into the DNS server is also need in the test case. A structure is defined to hold this information:
struct test_info_s { char * dns_server_v4; char * dns_server_v6; char * domain_name; char * hostname_v4; char * cname_v4; char * ip_addr_v4; char * hostname_v6; char * cname_v6; char * ip_addr_v6; char * hostname_v46; char * cname_v46; char * ip_addr_v46_v4; char * ip_addr_v46_v6; };
The test program may hold a number of such structures for different DNS server. The test will use each structure in turn to perform the tests. If IPv6 is not enabled in the eCos configuration, the entries which use IPv6 may be assigned to NULL.
2024-03-18 | Open Publication License |