|
NetBurner 3.5.8
PDF Version |
Topics | |
| DNS Record Types | |
| DNS Return Codes | |
Functions | |
| bool | IsNameIPAddress (const char *name) |
| Determine if the name is a valid IP Address and does not need to be looked up. | |
| int | fd_dns_part1 (const char *name, const IPADDR &dns_server, uint16_t TYPE=DNS_A, uint16_t TYPE2=extra_dns_t, int ifn=-1) |
| Open a UDP socket and initiate a DNS lookup. | |
| bool | fd_dns_processresult (int fd, const char *name, IPADDR &addr_out, uint16_t TYPE=DNS_A, uint16_t TYPE2=DNS_AAAA, uint32_t *ttl=0) |
| Process any responses on the UDP socket opened for DNS. | |
| int | fd_outstanding_Responses (int fd) |
| Check to see if there are any outstanding DNS requests. | |
| bool | AnyDNSInterFaceActive () |
| Determine if we have an active DNS route; DNS server is set for an active interface. | |
| int | GetHostByName (const char *name, IPADDR *pIpaddr, const IPADDR &dns_server, const TickTimeout tout, uint16_t TYPE1=DNS_A, uint16_t TYPE2=extra_dns_t, uint32_t *ttl=NULL) |
| Get the IP address associated with the specified domain name. | |
| int | GetHostByNameViaIfNum (const char *name, IPADDR *pIpaddr, const IPADDR &dns_server, int ifn, const TickTimeout &tout, uint16_t TYPE1=DNS_A, uint16_t TYPE2=extra_dns_t, uint32_t *ttl=NULL) |
| Get the IP address associated with the specified domain name on a specific interface. | |
| bool | CheckDnsCache (const char *name, IPADDR &ia, uint32_t *ttl, uint16_t rtype) |
| Check the DNS cache for a stored response. | |
#include< dns.h>
DNS turns a name such as www.netburner.com into an IP address your application can connect to.
The current DNS system is agnostic about the use of IPADDR, IPADDR6 or IPADDR4. The capability of C++ is such that you pass in any of those types and the compiler will select the correct function for that type. This is a change from tools versions 3.4.0 and earlier in which explicit IPv4 and IPv6 functions were used.
See IPv4/IPv6 Dual Stack Guide for how IPADDR selects the correct function for the address type you pass.
There are two ways to resolve a name.
GetHostByName() blocks the calling task until it has an answer or the timeout expires. Use this unless your task already runs a select() loop and cannot afford to block.
fd_dns_part1() with fd_dns_processresult() is the non-blocking pair. The first call sends the query and returns a file descriptor you add to your own fd_set; the second parses whatever arrives. See Non-blocking Lookups below.
By default a lookup asks for both an IPv4 address and an IPv6 address, and returns whichever the host publishes. On an IPv4 only build it asks for IPv4 alone. This suits most applications, which simply want a usable address, so the record types are normally left off the call entirely:
The TYPE and TYPE2 parameters narrow the request when you need to. Pass the same type twice to ask for one record type:
Pass DNS_AAAA as both types to ask for IPv6 alone. The available record types are listed under DNS Record Types.
The same two parameters apply to fd_dns_part1(), and the types passed there must match the types passed to fd_dns_processresult().
The timeout you pass is a total timeout for the whole lookup, not a per-query value. Within it the resolver retransmits an outstanding query on a backoff, so a query lost in transit is re-sent rather than costing the entire timeout.
Retransmissions currently go out at 1 s, then 3 s, then 7 s, doubling from a one second interval and capped at four seconds thereafter. Treat this as current behaviour rather than a guarantee.
Size the timeout for the round trip you expect plus room for at least one retry. Ten seconds is reasonable for a public resolver, less for one on the LAN.
A lookup that returns at roughly one of those backoff boundaries was answered on a retransmission rather than on the first query. That points at queries being lost on the way out, not at a slow server.
| Code | Meaning |
|---|---|
| DNS_OK | A usable address was returned. |
| DNS_NOSUCHNAME | The server answered, and the name has no record of the requested type. |
| DNS_TIMEOUT | No usable answer arrived within the timeout. The server may be unreachable, or the name unresolvable. |
| DNS_ERR | The request could not be made, for example a null name. |
The distinction between DNS_NOSUCHNAME and DNS_TIMEOUT is worth reading carefully when diagnosing a failure. DNS_NOSUCHNAME means something replied. DNS_TIMEOUT means the timeout expired.
DNS needs more than a link. The interface needs an active link and a DNS server address. It needs a gateway address as well only when the DNS server is on another subnet, because the gateway is what carries the query off the local network. A DNS server on the same subnet is reached directly and needs no gateway.
WaitForActiveNetwork() waits for link only. An application that resolves a name immediately after startup should check the rest:
Pass IPADDR::NullIP() to use the DNS server the interface already has, whether it came from DHCP or static configuration. This is what most applications want.
GetHostByNameViaIfNum() restricts the query to one interface on a multi-homed device.
Successful lookups are cached, so a repeated lookup of the same name returns immediately without network traffic. Entries expire according to the TTL supplied by the DNS server.
A name resolved a moment ago costs nothing to resolve again, so applications are free to call GetHostByName() at the point of use rather than caching the address themselves.
An IP address written as text needs no lookup at all. GetHostByName("10.1.1.50", ...) returns that address directly, so a setting that accepts either a name or an address can be passed straight through.
The cache is enabled by DNS_CACHE in predef.h, and its size is set by NUM_DNS_CACHE in constants.h.
A name ending in .local is not sent to your DNS server. It is resolved by multicast DNS: the query goes to the multicast group 224.0.0.251 on port 5353, and any host on the local network that owns the name answers.
This means .local lookups work with no DNS server configured at all, and equally that a correctly configured DNS server has no effect on them. Only IPv4 .local lookups are supported.
fd_dns_part1() sends the query and returns a file descriptor to add to your fd_set. When select() reports the descriptor readable, fd_dns_processresult() parses whatever arrived and returns true once it has an address.
Three responsibilities move to you with this interface:
| bool AnyDNSInterFaceActive | ( | ) |
#include <dns.h>
Determine if we have an active DNS route; DNS server is set for an active interface.
| bool CheckDnsCache | ( | const char * | name, |
| IPADDR & | ia, | ||
| uint32_t * | ttl, | ||
| uint16_t | rtype ) |
#include <dns.h>
Check the DNS cache for a stored response.
| *name | Pointer to domain name to resolve |
| ia | Variable of type IPADDR to store resultant IP address |
| ttl | Optional pointer to return variable for TimeToLive value for DNS record |
| rtype | Request type: DNS Record Types |
| int fd_dns_part1 | ( | const char * | name, |
| const IPADDR & | dns_server, | ||
| uint16_t | TYPE = DNS_A, | ||
| uint16_t | TYPE2 = extra_dns_t, | ||
| int | ifn = -1 ) |
#include <dns.h>
Open a UDP socket and initiate a DNS lookup.
This socket can be put in a select and used for asynchronous DNS lookups. Opens a UDP receive FD and sends DNS queries.
| name | Pointer to domain name to resolve |
| dns_server | Reference to the DNS server to use. Pass INADDR_ANY to use the DNS server associated with the interface. |
| TYPE | Optional DNS record type. If no type is specified the default is IPv4 DNS_A |
| TYPE2 | Optional 2nd DNS record type. Defaults to DNS_AAAA on a dual stack build and to DNS_A on an IPv4 only build, matching GetHostByName(). Pass the same types to fd_dns_processresult(). |
| ifn | Which interface to use -1 uses the default active DNS interface |
| bool fd_dns_processresult | ( | int | fd, |
| const char * | name, | ||
| IPADDR & | addr_out, | ||
| uint16_t | TYPE = DNS_A, | ||
| uint16_t | TYPE2 = DNS_AAAA, | ||
| uint32_t * | ttl = 0 ) |
#include <dns.h>
Process any responses on the UDP socket opened for DNS.
This should only be called when the socket has data, otherwise it will block.
| fd | The file descriptor opened with fd_dns_part1 |
| name | Pointer to domain name to resolve |
| addr_out | Reference to IPADDR variable to hold the result |
| TYPE | DNS record type. If no type is specified the default is IPv4 DNS_A |
| TYPE2 | 2nd DNS record type. If no type is specified the default is no look up |
| ttl | Optional pointer to return variable for TimeToLive value for DNS record |
| int fd_outstanding_Responses | ( | int | fd | ) |
#include <dns.h>
Check to see if there are any outstanding DNS requests.
If this returns 0 then all DNS responses have been processed and one can assume ther eis no such name.
| fd | The file descriptor opened with fd_dns_part1 |
|
inline |
#include <dns.h>
Get the IP address associated with the specified domain name.
Calling GetHostByName() in dual stack mode will automatically call the correct IPv4 or IPv6 function.
The function will attempt to retrieve record type 1 first. If successful the function returns. If if the attempt using type 1 fails, the function will attempt to get a record using the type 2 parameter. For example, lets say you wish your code to use IPv6, but its OK to fall back to IPv4. You can set type 1 to DNS_AAAA and type2 to DNS_A.
| *name | Pointer to domain name to resolve |
| *pIpaddr | Pointer to variable of type IPADDR (or IPADDR4) to store resultant IP address. |
| &dns_server | Specified the DNS server to use. Pass INADDR_ANY to use the DNS server associated with the interface. |
| tout | Number of time ticks to wait of type TickTimeout |
| TYPE1 | Optional record type. If not specified will default to IPv4 DNS_A |
| TYPE2 | Optional record type. If not specified will default to IPv6 DNS_AAAA |
| ttl | Optional pointer to return variable for TimeToLive value for DNS record |
|
inline |
#include <dns.h>
Get the IP address associated with the specified domain name on a specific interface.
Calling GetHostByName() in dual stack mode will automatically call the correct IPv4 or IPv6 function.
The function will attempt to retrieve record type 1 first. If successful the function returns. If if the attempt using type 1 fails, the function will attempt to get a record using the type 2 parameter. For example, lets say you wish your code to use IPv6, but its OK to fall back to IPv4. You can set type 1 to DNS_AAAA and type2 to DNS_A.
| *name | Pointer to domain name to resolve |
| *pIpaddr | Pointer to variable of type IPADDR to store resultant IP address |
| &dns_server | Specified the DNS server to use. Pass INADDR_ANY to use the DNS server associated with the interface. |
| tout | A reference to the number of time ticks to wait of type TickTimeout |
| TYPE1 | Optional record type. If not specified will default to IPv4 DNS_A |
| TYPE2 | Optional record type. If not specified will default to IPv6 DNS_AAAA |
| ifn | Interface number |
| ttl | Optional pointer to return variable for TimeToLive value for DNS record |
| bool IsNameIPAddress | ( | const char * | name | ) |
#include <dns.h>
Determine if the name is a valid IP Address and does not need to be looked up.
| *name | Pointer to domain name to check |