mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-11-04 14:29:39 +00:00
dns: added one-shot multicast DNS queries
This commit is contained in:
parent
85817e7611
commit
5774fdfe75
@ -6,6 +6,9 @@ HISTORY
|
||||
|
||||
++ New features:
|
||||
|
||||
2016-12-09: Simon Goldschmidt
|
||||
* dns.c: added one-shot multicast DNS queries
|
||||
|
||||
2016-11-24: Ambroz Bizjak, David van Moolenbroek
|
||||
* tcp_out.c: Optimize passing contiguous nocopy buffers to tcp_write (bug #46290)
|
||||
|
||||
|
103
src/core/dns.c
103
src/core/dns.c
@ -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 */
|
||||
|
@ -84,6 +84,13 @@ struct local_hostlist_entry {
|
||||
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
||||
#endif /* DNS_LOCAL_HOSTLIST */
|
||||
|
||||
#if LWIP_IPV4
|
||||
extern const ip_addr_t dns_mquery_v4group;
|
||||
#endif /* LWIP_IPV4 */
|
||||
#if LWIP_IPV6
|
||||
extern const ip_addr_t dns_mquery_v6group;
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
/** Callback which is invoked when a hostname is found.
|
||||
* A function of this type must be implemented by the application using the DNS resolver.
|
||||
* @param name pointer to the name that was looked up.
|
||||
|
@ -1057,6 +1057,12 @@
|
||||
#if !defined DNS_LOCAL_HOSTLIST_IS_DYNAMIC || defined __DOXYGEN__
|
||||
#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0
|
||||
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
||||
|
||||
/** Set this to 1 to enable querying ".local" names via mDNS
|
||||
* using a One-Shot Multicast DNS Query */
|
||||
#if !defined LWIP_DNS_SUPPORT_MDNS_QUERIES || defined __DOXYGEN__
|
||||
#define LWIP_DNS_SUPPORT_MDNS_QUERIES 0
|
||||
#endif
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
@ -115,6 +115,24 @@ PACK_STRUCT_END
|
||||
#endif
|
||||
#define SIZEOF_DNS_HDR 12
|
||||
|
||||
|
||||
/* Multicast DNS definitions */
|
||||
|
||||
/** UDP port for multicast DNS queries */
|
||||
#ifndef DNS_MQUERY_PORT
|
||||
#define DNS_MQUERY_PORT 5353
|
||||
#endif
|
||||
|
||||
/* IPv4 group for multicast DNS queries: 224.0.0.251 */
|
||||
#ifndef DNS_MQUERY_IPV4_GROUP_INIT
|
||||
#define DNS_MQUERY_IPV4_GROUP_INIT IPADDR4_INIT_BYTES(224,0,0,251)
|
||||
#endif
|
||||
|
||||
/* IPv6 group for multicast DNS queries: FF02::FB */
|
||||
#ifndef DNS_MQUERY_IPV6_GROUP_INIT
|
||||
#define DNS_MQUERY_IPV6_GROUP_INIT IPADDR6_INIT_HOST(0xFF020000,0,0,0xFB)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user