DNS - host name to IP address resolver.
#include "lwip/opt.h"
#include "lwip/udp.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/dns.h"
#include <string.h>
Data Structures | |
struct | dns_answer |
DNS answer message structure. More... | |
struct | dns_hdr |
DNS message header. More... | |
struct | dns_query |
DNS query message structure. More... | |
struct | dns_req_entry |
DNS request table entry: used when dns_gehostbyname cannot answer the request from the DNS table. More... | |
struct | dns_table_entry |
DNS table entry. More... | |
Macros | |
#define | DNS_FLAG1_AUTHORATIVE 0x04 |
#define | DNS_FLAG1_OPCODE_INVERSE 0x08 |
#define | DNS_FLAG1_OPCODE_STANDARD 0x00 |
#define | DNS_FLAG1_OPCODE_STATUS 0x10 |
#define | DNS_FLAG1_RD 0x01 |
#define | DNS_FLAG1_RESPONSE 0x80 |
#define | DNS_FLAG1_TRUNC 0x02 |
#define | DNS_FLAG2_ERR_MASK 0x0f |
#define | DNS_FLAG2_ERR_NAME 0x03 |
#define | DNS_FLAG2_ERR_NONE 0x00 |
#define | DNS_FLAG2_RA 0x80 |
#define | DNS_MAX_REQUESTS DNS_TABLE_SIZE |
#define | DNS_MAX_RETRIES 4 |
DNS maximum number of retries when asking for a name, before "timeout". More... | |
#define | DNS_MAX_SOURCE_PORTS DNS_MAX_REQUESTS |
#define | DNS_MAX_TTL 604800 |
DNS resource record max. More... | |
#define | DNS_PORT_ALLOWED(port) ((port) >= 1024) |
Limits the source port to be >= 1024 by default. More... | |
#define | DNS_RAND_TXID LWIP_RAND |
Random generator function to create random TXIDs and source ports for queries. More... | |
#define | DNS_SERVER_ADDRESS(ipaddr) (ip4_addr_set_u32(ipaddr, ipaddr_addr("208.67.222.222"))) /* resolver1.opendns.com */ |
DNS server IP address. More... | |
#define | DNS_SERVER_PORT 53 |
DNS server port address. More... | |
#define | DNS_STATE_ASKING 2 |
#define | DNS_STATE_DONE 3 |
#define | DNS_STATE_NEW 1 |
#define | DNS_STATE_UNUSED 0 |
#define | LWIP_DNS_SECURE (LWIP_DNS_SECURE_RAND_XID | LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT) |
Use all DNS security features by default. More... | |
#define | LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING 2 |
#define | LWIP_DNS_SECURE_RAND_SRC_PORT 4 |
#define | LWIP_DNS_SECURE_RAND_XID 1 |
This file implements a DNS host name to IP address resolver. More... | |
#define | LWIP_DNS_STRICMP(str1, str2) dns_stricmp(str1, str2) |
#define | SIZEOF_DNS_ANSWER 10 |
#define | SIZEOF_DNS_ANSWER_ASSERT 12 |
#define | SIZEOF_DNS_HDR 12 |
#define | SIZEOF_DNS_QUERY 4 |
Functions | |
static u8_t | dns_alloc_pcb (void) |
dns_alloc_pcb() - allocates a new pcb (or reuses an existing one) to be used for sending a request More... | |
static struct udp_pcb * | dns_alloc_random_port (void) |
static void | dns_call_found (u8_t idx, ip_addr_t *addr) |
dns_call_found() - call the found callback and check if there are duplicate entries for the given hostname. More... | |
static void | dns_check_entries (void) |
Call dns_check_entry for each entry in dns_table - check all entries. More... | |
static void | dns_check_entry (u8_t i) |
dns_check_entry() - see if entry has not yet been queried and, if so, sends out a query. More... | |
static u16_t | dns_compare_name (char *query, struct pbuf *p, u16_t start_offset) |
Compare the "dotted" name "query" with the encoded name "response" to make sure an answer from the DNS server matches the current dns_table entry (otherwise, answers might arrive late for hostname not on the list any more). More... | |
static u16_t | dns_create_txid (void) |
static err_t | dns_enqueue (const char *name, size_t hostnamelen, dns_found_callback found, void *callback_arg) |
Queues a new hostname to resolve and sends out a DNS query for that hostname. More... | |
err_t | dns_gethostbyname (const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg) |
Resolve a hostname (string) into an IP address. More... | |
ip_addr_t * | dns_getserver (u8_t numdns) |
Obtain one of the currently configured DNS server. More... | |
void | dns_init () |
Initialize the resolver: set up the UDP pcb and configure the default server (DNS_SERVER_ADDRESS). More... | |
static u32_t | dns_lookup (const char *name) |
Look up a hostname in the array of known hostnames. More... | |
static u16_t | dns_parse_name (struct pbuf *p, u16_t query_idx) |
Walk through a compact encoded DNS name and return the end of the name. More... | |
static void | dns_recv (void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) |
Receive input function for DNS response packets arriving for the dns UDP pcb. More... | |
static err_t | dns_send (struct dns_table_entry *entry) |
Send a DNS query packet. More... | |
void | dns_setserver (u8_t numdns, ip_addr_t *dnsserver) |
Initialize one of the DNS servers. More... | |
static int | dns_stricmp (const char *str1, const char *str2) |
A small but sufficient implementation for case insensitive strcmp. More... | |
void | dns_tmr (void) |
The DNS resolver client timer - handle retries and timeouts and should be called every DNS_TMR_INTERVAL milliseconds (every second by default). More... | |
Variables | |
static u8_t | dns_last_pcb_idx |
static struct udp_pcb * | dns_pcbs [DNS_MAX_SOURCE_PORTS] |
static struct dns_req_entry | dns_requests [DNS_MAX_REQUESTS] |
static u8_t | dns_seqno |
static ip_addr_t | dns_servers [DNS_MAX_SERVERS] |
static struct dns_table_entry | dns_table [DNS_TABLE_SIZE] |
PACK_STRUCT_BEGIN struct dns_hdr | PACK_STRUCT_STRUCT |
#define DNS_FLAG1_AUTHORATIVE 0x04 |
#define DNS_FLAG1_OPCODE_INVERSE 0x08 |
#define DNS_FLAG1_OPCODE_STANDARD 0x00 |
#define DNS_FLAG1_OPCODE_STATUS 0x10 |
#define DNS_FLAG1_RD 0x01 |
Referenced by dns_send().
#define DNS_FLAG1_RESPONSE 0x80 |
Referenced by dns_recv().
#define DNS_FLAG1_TRUNC 0x02 |
#define DNS_FLAG2_ERR_MASK 0x0f |
Referenced by dns_recv().
#define DNS_FLAG2_ERR_NAME 0x03 |
#define DNS_FLAG2_ERR_NONE 0x00 |
#define DNS_FLAG2_RA 0x80 |
#define DNS_MAX_REQUESTS DNS_TABLE_SIZE |
Referenced by dns_call_found(), and dns_enqueue().
#define DNS_MAX_RETRIES 4 |
DNS maximum number of retries when asking for a name, before "timeout".
Referenced by dns_check_entry().
#define DNS_MAX_SOURCE_PORTS DNS_MAX_REQUESTS |
Referenced by dns_alloc_pcb(), dns_call_found(), and dns_enqueue().
#define DNS_MAX_TTL 604800 |
#define DNS_PORT_ALLOWED | ( | port | ) | ((port) >= 1024) |
Limits the source port to be >= 1024 by default.
Referenced by dns_alloc_random_port().
#define DNS_RAND_TXID LWIP_RAND |
Random generator function to create random TXIDs and source ports for queries.
Referenced by dns_alloc_random_port(), and dns_create_txid().
#define DNS_SERVER_ADDRESS | ( | ipaddr | ) | (ip4_addr_set_u32(ipaddr, ipaddr_addr("208.67.222.222"))) /* resolver1.opendns.com */ |
DNS server IP address.
Referenced by dns_init().
#define DNS_SERVER_PORT 53 |
DNS server port address.
Referenced by dns_send().
#define DNS_STATE_ASKING 2 |
Referenced by dns_call_found(), dns_check_entry(), dns_create_txid(), dns_enqueue(), and dns_recv().
#define DNS_STATE_DONE 3 |
Referenced by dns_check_entry(), dns_enqueue(), dns_lookup(), and dns_recv().
#define DNS_STATE_NEW 1 |
Referenced by dns_check_entry(), and dns_enqueue().
#define DNS_STATE_UNUSED 0 |
Referenced by dns_check_entry(), dns_enqueue(), dns_init(), and dns_recv().
#define LWIP_DNS_SECURE (LWIP_DNS_SECURE_RAND_XID | LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT) |
Use all DNS security features by default.
This is overridable but should only be needed by very small targets or when using against non standard DNS servers.
#define LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING 2 |
#define LWIP_DNS_SECURE_RAND_SRC_PORT 4 |
#define LWIP_DNS_SECURE_RAND_XID 1 |
This file implements a DNS host name to IP address resolver.
Port to lwIP from uIP by Jim Pettinato April 2007
security fixes and more by Simon Goldschmidt
uIP version Copyright (c) 2002-2003, Adam Dunkels. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
DNS.C
The lwIP DNS resolver functions are used to lookup a host name and map it to a numerical IP address. It maintains a list of resolved hostnames that can be queried with the dns_lookup() function. New hostnames can be resolved using the dns_query() function.
The lwIP version of the resolver also adds a non-blocking version of gethostbyname() that will work with a raw API application. This function checks for an IP address string first and converts it if it is valid. gethostbyname() then does a dns_lookup() to see if the name is already in the table. If so, the IP is returned. If not, a query is issued and the function returns with a ERR_INPROGRESS status. The app using the dns client must then go into a waiting state.
Once a hostname has been resolved (or found to be non-existent), the resolver code calls a specified callback function (which must be implemented by the module that uses the resolver).
#define LWIP_DNS_STRICMP | ( | str1, | |
str2 | |||
) | dns_stricmp(str1, str2) |
Referenced by dns_enqueue(), and dns_lookup().
#define SIZEOF_DNS_ANSWER 10 |
Referenced by dns_recv().
#define SIZEOF_DNS_ANSWER_ASSERT 12 |
Referenced by dns_init().
#define SIZEOF_DNS_HDR 12 |
Referenced by dns_recv(), and dns_send().
#define SIZEOF_DNS_QUERY 4 |
Referenced by dns_init(), dns_recv(), and dns_send().
dns_alloc_pcb() - allocates a new pcb (or reuses an existing one) to be used for sending a request
References dns_alloc_random_port(), dns_last_pcb_idx, DNS_MAX_SOURCE_PORTS, and NULL.
Referenced by dns_enqueue().
References DNS_PORT_ALLOWED, DNS_RAND_TXID, dns_recv(), ERR_OK, ERR_USE, IP_ADDR_ANY, NULL, udp_bind(), udp_new(), udp_recv(), and udp_remove().
Referenced by dns_alloc_pcb().
dns_call_found() - call the found callback and check if there are duplicate entries for the given hostname.
If there are any, their found callback will be called and they will be removed.
idx | dns table index of the entry that is resolved or removed |
addr | IP address for the hostname (or NULL on error or memory shortage) |
References arg, DNS_MAX_REQUESTS, DNS_MAX_SOURCE_PORTS, dns_requests, DNS_STATE_ASKING, dns_table, dns_req_entry::found, NULL, dns_table_entry::pcb_idx, and udp_remove().
Referenced by dns_check_entry(), and dns_recv().
Call dns_check_entry for each entry in dns_table - check all entries.
References dns_check_entry().
Referenced by dns_tmr().
dns_check_entry() - see if entry has not yet been queried and, if so, sends out a query.
Check an entry in the dns_table:
i | index of the dns_table entry to check |
References dns_call_found(), dns_create_txid(), DNS_DEBUG, DNS_MAX_RETRIES, dns_send(), dns_servers, DNS_STATE_ASKING, DNS_STATE_DONE, DNS_STATE_NEW, DNS_STATE_UNUSED, dns_table, ERR_OK, ip_addr_isany, LWIP_ASSERT, LWIP_DBG_LEVEL_WARNING, LWIP_DEBUGF, lwip_strerr, dns_table_entry::name, NULL, dns_table_entry::retries, dns_table_entry::server_idx, dns_table_entry::state, dns_table_entry::tmr, dns_table_entry::ttl, and dns_table_entry::txid.
Referenced by dns_check_entries(), and dns_enqueue().
Compare the "dotted" name "query" with the encoded name "response" to make sure an answer from the DNS server matches the current dns_table entry (otherwise, answers might arrive late for hostname not on the list any more).
query | hostname (not encoded) from the dns_table |
p | pbuf containing the encoded hostname in the DNS response |
start_offset | offset into p where the name starts |
References pbuf_get_at().
Referenced by dns_recv().
References DNS_RAND_TXID, DNS_STATE_ASKING, and dns_table.
Referenced by dns_check_entry().
|
static |
Queues a new hostname to resolve and sends out a DNS query for that hostname.
name | the hostname that is to be queried |
hostnamelen | length of the hostname |
found | a callback function to be called on success, failure or timeout |
callback_arg | argument to pass to the callback function |
References dns_req_entry::arg, dns_alloc_pcb(), dns_check_entry(), DNS_DEBUG, DNS_MAX_REQUESTS, DNS_MAX_SOURCE_PORTS, dns_requests, dns_seqno, DNS_STATE_ASKING, DNS_STATE_DONE, DNS_STATE_NEW, DNS_STATE_UNUSED, dns_table, dns_req_entry::dns_table_idx, ERR_INPROGRESS, ERR_MEM, dns_req_entry::found, LWIP_DEBUGF, LWIP_DNS_STRICMP, LWIP_MIN, dns_table_entry::name, NULL, dns_table_entry::pcb_idx, dns_table_entry::seqno, dns_table_entry::state, and U16_F.
Referenced by dns_gethostbyname().
err_t dns_gethostbyname | ( | const char * | hostname, |
ip_addr_t * | addr, | ||
dns_found_callback | found, | ||
void * | callback_arg | ||
) |
Resolve a hostname (string) into an IP address.
NON-BLOCKING callback version for use with raw API!!!
Returns immediately with one of err_t return codes:
hostname | the hostname that is to be queried |
addr | pointer to a ip_addr_t where to store the address if it is already cached in the dns_table (only valid if ERR_OK is returned!) |
found | a callback function to be called on success, failure or timeout (only if ERR_INPROGRESS is returned!) |
callback_arg | argument to pass to the callback function |
References DNS_DEBUG, dns_enqueue(), dns_lookup(), ERR_ARG, ERR_OK, ip4_addr_set_u32, ip_addr_set_loopback, ipaddr_addr(), IPADDR_NONE, LWIP_DEBUGF, and NULL.
Referenced by lwip_netconn_do_gethostbyname(), and wifi_cb().
Obtain one of the currently configured DNS server.
numdns | the index of the DNS server |
References dns_servers, and IP_ADDR_ANY.
Initialize the resolver: set up the UDP pcb and configure the default server (DNS_SERVER_ADDRESS).
References DNS_DEBUG, dns_recv(), DNS_SERVER_ADDRESS, dns_setserver(), DNS_STATE_UNUSED, IP_ADDR_ANY, LWIP_ASSERT, LWIP_DEBUGF, NULL, SIZEOF_DNS_ANSWER_ASSERT, SIZEOF_DNS_QUERY, udp_bind(), udp_new(), and udp_recv().
Referenced by lwip_init().
|
static |
Look up a hostname in the array of known hostnames.
name | the hostname to look up |
References DNS_DEBUG, DNS_STATE_DONE, dns_table, ip4_addr_get_u32, ip_addr_debug_print, IPADDR_NONE, LWIP_DEBUGF, and LWIP_DNS_STRICMP.
Referenced by dns_gethostbyname().
Walk through a compact encoded DNS name and return the end of the name.
p | pbuf containing the name |
query_idx | start index into p pointing to encoded DNS name in the DNS server response |
References pbuf_get_at().
Referenced by dns_recv().
|
static |
Receive input function for DNS response packets arriving for the dns UDP pcb.
see udp.h
References dns_query::cls, dns_answer::cls, dns_call_found(), dns_compare_name(), DNS_DEBUG, DNS_FLAG1_RESPONSE, DNS_FLAG2_ERR_MASK, DNS_MAX_TTL, dns_parse_name(), DNS_RRCLASS_IN, DNS_RRTYPE_A, dns_servers, DNS_STATE_ASKING, DNS_STATE_DONE, DNS_STATE_UNUSED, dns_table, htons, ip_addr_cmp, ip_addr_debug_print, dns_table_entry::ipaddr, dns_answer::len, LWIP_DEBUGF, dns_table_entry::name, ntohl, NULL, pbuf_copy_partial(), pbuf_free(), PP_HTONS, dns_table_entry::server_idx, SIZEOF_DNS_ANSWER, SIZEOF_DNS_HDR, SIZEOF_DNS_QUERY, dns_table_entry::state, pbuf::tot_len, dns_answer::ttl, dns_table_entry::ttl, dns_table_entry::txid, dns_query::type, and dns_answer::type.
Referenced by dns_alloc_random_port(), and dns_init().
|
static |
Send a DNS query packet.
entry | the DNS table entry for which to send a request |
References dns_query::cls, DNS_DEBUG, DNS_FLAG1_RD, DNS_RRCLASS_IN, DNS_RRTYPE_A, DNS_SERVER_PORT, dns_servers, ERR_MEM, htons, ip_addr_isany, LWIP_ASSERT, LWIP_DEBUGF, dns_table_entry::name, NULL, pbuf_alloc(), pbuf_free(), pbuf_put_at(), PBUF_RAM, pbuf_take(), pbuf_take_at(), PBUF_TRANSPORT, dns_table_entry::pcb_idx, PP_HTONS, dns_table_entry::server_idx, SIZEOF_DNS_HDR, SIZEOF_DNS_QUERY, dns_table_entry::txid, dns_query::type, U16_F, and udp_sendto().
Referenced by dns_check_entry().
Initialize one of the DNS servers.
numdns | the index of the DNS server to set must be < DNS_MAX_SERVERS |
dnsserver | IP address of the DNS server to set |
References dns_servers, IP_ADDR_ANY, and NULL.
Referenced by dhcp_handle_ack(), and dns_init().
|
static |
A small but sufficient implementation for case insensitive strcmp.
This can be defined to e.g. stricmp for windows or strcasecmp for linux.
The DNS resolver client timer - handle retries and timeouts and should be called every DNS_TMR_INTERVAL milliseconds (every second by default).
References dns_check_entries(), DNS_DEBUG, and LWIP_DEBUGF.
Referenced by dns_timer().
|
static |
Referenced by dns_alloc_pcb().
|
static |
|
static |
Referenced by dns_call_found(), and dns_enqueue().
|
static |
Referenced by dns_enqueue().
|
static |
Referenced by dns_check_entry(), dns_getserver(), dns_recv(), dns_send(), and dns_setserver().
|
static |
Referenced by dns_call_found(), dns_check_entry(), dns_create_txid(), dns_enqueue(), dns_lookup(), and dns_recv().
PACK_STRUCT_BEGIN struct dns_hdr PACK_STRUCT_STRUCT |