|
|
|
|
@ -24,6 +24,11 @@
|
|
|
|
|
* the resolver code calls a specified callback function (which |
|
|
|
|
* must be implemented by the module that uses the resolver). |
|
|
|
|
*
|
|
|
|
|
* Multicast DNS queries are supported for names ending on ".local". |
|
|
|
|
* However, only "One-Shot Multicast DNS Queries" are supported (RFC 6762 |
|
|
|
|
* chapter 5.1), this is not a fully compliant implementation of continuous |
|
|
|
|
* mDNS querying! |
|
|
|
|
* |
|
|
|
|
* All functions must be called from TCPIP thread. |
|
|
|
|
*
|
|
|
|
|
* @see @ref netconn_common for thread-safe access. |
|
|
|
|
@ -71,6 +76,7 @@
|
|
|
|
|
/** @todo: define good default values (rfc compliance) */ |
|
|
|
|
/** @todo: improve answer parsing, more checkings... */ |
|
|
|
|
/** @todo: check RFC1035 - 7.3. Processing responses */ |
|
|
|
|
/** @todo: one-shot mDNS: dual-stack fallback to another IP version */ |
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
|
|
|
* Includes |
|
|
|
|
@ -175,6 +181,12 @@ static u16_t dns_txid;
|
|
|
|
|
#define LWIP_DNS_SET_ADDRTYPE(x, y) |
|
|
|
|
#endif /* LWIP_IPV4 && LWIP_IPV6 */ |
|
|
|
|
|
|
|
|
|
#if LWIP_DNS_SUPPORT_MDNS_QUERIES |
|
|
|
|
#define LWIP_DNS_ISMDNS_ARG(x) , x |
|
|
|
|
#else |
|
|
|
|
#define LWIP_DNS_ISMDNS_ARG(x) |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/** DNS query message structure.
|
|
|
|
|
No packing needed: only used locally on the stack. */ |
|
|
|
|
struct dns_query { |
|
|
|
|
@ -224,6 +236,9 @@ struct dns_table_entry {
|
|
|
|
|
#if LWIP_IPV4 && LWIP_IPV6 |
|
|
|
|
u8_t reqaddrtype; |
|
|
|
|
#endif /* LWIP_IPV4 && LWIP_IPV6 */ |
|
|
|
|
#if LWIP_DNS_SUPPORT_MDNS_QUERIES |
|
|
|
|
u8_t is_mdns; |
|
|
|
|
#endif |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** DNS request table entry: used when dns_gehostbyname cannot answer the
|
|
|
|
|
@ -287,6 +302,13 @@ static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
|
|
|
|
|
static struct dns_req_entry dns_requests[DNS_MAX_REQUESTS]; |
|
|
|
|
static ip_addr_t dns_servers[DNS_MAX_SERVERS]; |
|
|
|
|
|
|
|
|
|
#if LWIP_IPV4 |
|
|
|
|
const ip_addr_t dns_mquery_v4group = DNS_MQUERY_IPV4_GROUP_INIT; |
|
|
|
|
#endif /* LWIP_IPV4 */ |
|
|
|
|
#if LWIP_IPV6 |
|
|
|
|
const ip_addr_t dns_mquery_v6group = DNS_MQUERY_IPV6_GROUP_INIT; |
|
|
|
|
#endif /* LWIP_IPV6 */ |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Initialize the resolver: set up the UDP pcb and configure the default server |
|
|
|
|
* (if DNS_SERVER_ADDRESS is set). |
|
|
|
|
@ -680,7 +702,11 @@ dns_send(u8_t idx)
|
|
|
|
|
LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n", |
|
|
|
|
(u16_t)(entry->server_idx), entry->name)); |
|
|
|
|
LWIP_ASSERT("dns server out of array", entry->server_idx < DNS_MAX_SERVERS); |
|
|
|
|
if (ip_addr_isany_val(dns_servers[entry->server_idx])) { |
|
|
|
|
if (ip_addr_isany_val(dns_servers[entry->server_idx]) |
|
|
|
|
#if LWIP_DNS_SUPPORT_MDNS_QUERIES |
|
|
|
|
&& !entry->is_mdns |
|
|
|
|
#endif |
|
|
|
|
) { |
|
|
|
|
/* DNS server not valid anymore, e.g. PPP netif has been shut down */ |
|
|
|
|
/* call specified callback function if provided */ |
|
|
|
|
dns_call_found(idx, NULL); |
|
|
|
|
@ -693,6 +719,8 @@ dns_send(u8_t idx)
|
|
|
|
|
p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(SIZEOF_DNS_HDR + strlen(entry->name) + 2 + |
|
|
|
|
SIZEOF_DNS_QUERY), PBUF_RAM); |
|
|
|
|
if (p != NULL) { |
|
|
|
|
const ip_addr_t* dst; |
|
|
|
|
u16_t dst_port; |
|
|
|
|
/* fill dns header */ |
|
|
|
|
memset(&hdr, 0, SIZEOF_DNS_HDR); |
|
|
|
|
hdr.id = lwip_htons(entry->txid); |
|
|
|
|
@ -735,7 +763,30 @@ dns_send(u8_t idx)
|
|
|
|
|
/* send dns packet */ |
|
|
|
|
LWIP_DEBUGF(DNS_DEBUG, ("sending DNS request ID %d for name \"%s\" to server %d\r\n", |
|
|
|
|
entry->txid, entry->name, entry->server_idx)); |
|
|
|
|
err = udp_sendto(dns_pcbs[pcb_idx], p, &dns_servers[entry->server_idx], DNS_SERVER_PORT); |
|
|
|
|
#if LWIP_DNS_SUPPORT_MDNS_QUERIES |
|
|
|
|
if (entry->is_mdns) { |
|
|
|
|
dst_port = DNS_MQUERY_PORT; |
|
|
|
|
#if LWIP_IPV6 |
|
|
|
|
if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) |
|
|
|
|
{ |
|
|
|
|
dst = &dns_mquery_v6group; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
#if LWIP_IPV4 && LWIP_IPV6 |
|
|
|
|
else |
|
|
|
|
#endif |
|
|
|
|
#if LWIP_IPV4 |
|
|
|
|
{ |
|
|
|
|
dst = &dns_mquery_v4group; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
} else |
|
|
|
|
#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */ |
|
|
|
|
{ |
|
|
|
|
dst_port = DNS_SERVER_PORT; |
|
|
|
|
dst = &dns_servers[entry->server_idx]; |
|
|
|
|
} |
|
|
|
|
err = udp_sendto(dns_pcbs[pcb_idx], p, dst, dst_port); |
|
|
|
|
|
|
|
|
|
/* free pbuf */ |
|
|
|
|
pbuf_free(p); |
|
|
|
|
@ -938,7 +989,11 @@ dns_check_entry(u8_t i)
|
|
|
|
|
case DNS_STATE_ASKING: |
|
|
|
|
if (--entry->tmr == 0) { |
|
|
|
|
if (++entry->retries == DNS_MAX_RETRIES) { |
|
|
|
|
if ((entry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany_val(dns_servers[entry->server_idx + 1])) { |
|
|
|
|
if ((entry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany_val(dns_servers[entry->server_idx + 1]) |
|
|
|
|
#if LWIP_DNS_SUPPORT_MDNS_QUERIES |
|
|
|
|
&& !entry->is_mdns |
|
|
|
|
#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */ |
|
|
|
|
) { |
|
|
|
|
/* change of server */ |
|
|
|
|
entry->server_idx++; |
|
|
|
|
entry->tmr = 1; |
|
|
|
|
@ -1075,10 +1130,15 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
|
|
|
|
|
goto memerr; /* ignore this packet */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Check whether response comes from the same network address to which the
|
|
|
|
|
question was sent. (RFC 5452) */ |
|
|
|
|
if (!ip_addr_cmp(addr, &dns_servers[entry->server_idx])) { |
|
|
|
|
goto memerr; /* ignore this packet */ |
|
|
|
|
#if LWIP_DNS_SUPPORT_MDNS_QUERIES |
|
|
|
|
if (!entry->is_mdns) |
|
|
|
|
#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */ |
|
|
|
|
{ |
|
|
|
|
/* Check whether response comes from the same network address to which the
|
|
|
|
|
question was sent. (RFC 5452) */ |
|
|
|
|
if (!ip_addr_cmp(addr, &dns_servers[entry->server_idx])) { |
|
|
|
|
goto memerr; /* ignore this packet */ |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Check if the name in the "question" part match with the name in the entry and
|
|
|
|
|
@ -1210,7 +1270,7 @@ memerr:
|
|
|
|
|
*/ |
|
|
|
|
static err_t |
|
|
|
|
dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, |
|
|
|
|
void *callback_arg LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)) |
|
|
|
|
void *callback_arg LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype) LWIP_DNS_ISMDNS_ARG(u8_t is_mdns)) |
|
|
|
|
{ |
|
|
|
|
u8_t i; |
|
|
|
|
u8_t lseq, lseqi; |
|
|
|
|
@ -1326,6 +1386,10 @@ dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found,
|
|
|
|
|
LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS pcb %"U16_F"\n", name, (u16_t)(entry->pcb_idx))); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#if LWIP_DNS_SUPPORT_MDNS_QUERIES |
|
|
|
|
entry->is_mdns = is_mdns; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
dns_seqno++; |
|
|
|
|
|
|
|
|
|
/* force to send query without waiting timer */ |
|
|
|
|
@ -1381,6 +1445,9 @@ dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_call
|
|
|
|
|
void *callback_arg, u8_t dns_addrtype) |
|
|
|
|
{ |
|
|
|
|
size_t hostnamelen; |
|
|
|
|
#if LWIP_DNS_SUPPORT_MDNS_QUERIES |
|
|
|
|
u8_t is_mdns; |
|
|
|
|
#endif |
|
|
|
|
/* not initialized or no valid server yet, or invalid addr pointer
|
|
|
|
|
* or invalid hostname or invalid hostname length */ |
|
|
|
|
if ((addr == NULL) || |
|
|
|
|
@ -1437,13 +1504,25 @@ dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_call
|
|
|
|
|
LWIP_UNUSED_ARG(dns_addrtype); |
|
|
|
|
#endif /* LWIP_IPV4 && LWIP_IPV6 */ |
|
|
|
|
|
|
|
|
|
/* prevent calling found callback if no server is set, return error instead */ |
|
|
|
|
if (ip_addr_isany_val(dns_servers[0])) { |
|
|
|
|
return ERR_VAL; |
|
|
|
|
#if LWIP_DNS_SUPPORT_MDNS_QUERIES |
|
|
|
|
if (strstr(hostname, ".local") == &hostname[hostnamelen] - 6) { |
|
|
|
|
is_mdns = 1; |
|
|
|
|
} else { |
|
|
|
|
is_mdns = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!is_mdns) |
|
|
|
|
#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */ |
|
|
|
|
{ |
|
|
|
|
/* prevent calling found callback if no server is set, return error instead */ |
|
|
|
|
if (ip_addr_isany_val(dns_servers[0])) { |
|
|
|
|
return ERR_VAL; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* queue query with specified callback */ |
|
|
|
|
return dns_enqueue(hostname, hostnamelen, found, callback_arg LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)); |
|
|
|
|
return dns_enqueue(hostname, hostnamelen, found, callback_arg LWIP_DNS_ADDRTYPE_ARG(dns_addrtype) |
|
|
|
|
LWIP_DNS_ISMDNS_ARG(is_mdns)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endif /* LWIP_DNS */ |
|
|
|
|
|