task #12243: DNS/IPv6: added support for AAAA records

This commit is contained in:
goldsimon 2015-09-04 12:16:14 +02:00
parent c8cd67c989
commit dd3725a452
4 changed files with 205 additions and 48 deletions

View File

@ -6,6 +6,9 @@ HISTORY
++ New features:
2015-09-03: Simon Goldschmidt
* opt.h, dns.h/.c: DNS/IPv6: added support for AAAA records
2015-09-01: Simon Goldschmidt
* task #12178: hardware checksum capabilities can be configured per netif
(use NETIF_SET_CHECKSUM_CTRL() in your netif's init function)
@ -25,7 +28,7 @@ HISTORY
2015-04-24: Simon Goldschmidt
* dhcp.h/c, autoip.h/.c: added functions dhcp/autoip_supplied_address() to
check for the source of address assignemnt (replacement for NETIF_FLAG_DHCP)
check for the source of address assignment (replacement for NETIF_FLAG_DHCP)
2015-04-10: Simon Goldschmidt
* many files: task #13480: added LWIP_IPV4 define - IPv4 can be disabled,

View File

@ -161,6 +161,23 @@ static u16_t dns_txid;
#define DNS_MAX_SOURCE_PORTS 1
#endif
#if LWIP_IPV4 && LWIP_IPV6
#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) (((t) == LWIP_DNS_ADDRTYPE_IPV6_IPV4) || ((t) == LWIP_DNS_ADDRTYPE_IPV6))
#define LWIP_DNS_ADDRTYPE_MATCH_IP(t, ip) (IP_IS_V6_VAL(ip) ? LWIP_DNS_ADDRTYPE_IS_IPV6(t) : (!LWIP_DNS_ADDRTYPE_IS_IPV6(t)))
#define LWIP_DNS_ADDRTYPE_ARG(x) , x
#define LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(x) x
#define LWIP_DNS_SET_ADDRTYPE(x, y) do { x = y; } while(0)
#else
#if LWIP_IPV6
#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) 1
#else
#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) 0
#endif
#define LWIP_DNS_ADDRTYPE_MATCH_IP(t, ip) 1
#define LWIP_DNS_ADDRTYPE_ARG(x)
#define LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(x) 0
#define LWIP_DNS_SET_ADDRTYPE(x, y)
#endif /* LWIP_IPV4 && LWIP_IPV6 */
/* DNS protocol flags */
#define DNS_FLAG1_RESPONSE 0x80
@ -239,6 +256,9 @@ struct dns_table_entry {
u8_t pcb_idx;
#endif
char name[DNS_MAX_NAME_LENGTH];
#if LWIP_IPV4 && LWIP_IPV6
u8_t reqaddrtype;
#endif /* LWIP_IPV4 && LWIP_IPV6 */
};
/** DNS request table entry: used when dns_gehostbyname cannot answer the
@ -251,6 +271,9 @@ struct dns_req_entry {
#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
u8_t dns_table_idx;
#endif
#if LWIP_IPV4 && LWIP_IPV6
u8_t reqaddrtype;
#endif /* LWIP_IPV4 && LWIP_IPV6 */
};
#if DNS_LOCAL_HOSTLIST
@ -459,12 +482,13 @@ dns_init_local(void)
* @return ERR_OK if found, ERR_ARG if not found
*/
static err_t
dns_lookup_local(const char *hostname, ip_addr_t *addr)
dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype))
{
#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
struct local_hostlist_entry *entry = local_hostlist_dynamic;
while(entry != NULL) {
if (LWIP_DNS_STRICMP(entry->name, hostname) == 0) {
if ((LWIP_DNS_STRICMP(entry->name, hostname) == 0) &&
LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, entry->addr)) {
if (addr) {
ip_addr_copy(*addr, entry->addr);
}
@ -475,7 +499,8 @@ dns_lookup_local(const char *hostname, ip_addr_t *addr)
#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
int i;
for (i = 0; i < sizeof(local_hostlist_static) / sizeof(struct local_hostlist_entry); i++) {
if (LWIP_DNS_STRICMP(local_hostlist_static[i].name, hostname) == 0) {
if ((LWIP_DNS_STRICMP(local_hostlist_static[i].name, hostname) == 0) &&
LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, local_hostlist_static[i].addr)) {
if (addr) {
ip_addr_copy(*addr, local_hostlist_static[i].addr);
}
@ -568,26 +593,27 @@ dns_local_addhost(const char *hostname, const ip_addr_t *addr)
* @return ERR_OK if found, ERR_ARG if not found
*/
static err_t
dns_lookup(const char *name, ip_addr_t *addr)
dns_lookup(const char *name, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype))
{
u8_t i;
#if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN)
#endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */
#if DNS_LOCAL_HOSTLIST
if (dns_lookup_local(name, addr) == ERR_OK) {
if (dns_lookup_local(name, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) {
return ERR_OK;
}
#endif /* DNS_LOCAL_HOSTLIST */
#ifdef DNS_LOOKUP_LOCAL_EXTERN
if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) != IPADDR_NONE) {
return addr;
if (DNS_LOOKUP_LOCAL_EXTERN(name, addr, LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(dns_addrtype))) {
return ERR_OK;
}
#endif /* DNS_LOOKUP_LOCAL_EXTERN */
/* Walk through name list, return entry if found. If not, return NULL. */
for (i = 0; i < DNS_TABLE_SIZE; ++i) {
if ((dns_table[i].state == DNS_STATE_DONE) &&
(LWIP_DNS_STRICMP(name, dns_table[i].name) == 0)) {
(LWIP_DNS_STRICMP(name, dns_table[i].name) == 0) &&
LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, dns_table[i].ipaddr)) {
LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name));
ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr));
LWIP_DEBUGF(DNS_DEBUG, ("\n"));
@ -698,7 +724,7 @@ dns_send(u8_t idx)
/* call specified callback function if provided */
dns_call_found(idx, NULL);
/* flush this entry */
entry->state = DNS_STATE_UNUSED;
entry->state = DNS_STATE_UNUSED;
return ERR_OK;
}
@ -732,7 +758,11 @@ dns_send(u8_t idx)
query_idx++;
/* fill dns query */
qry.type = PP_HTONS(DNS_RRTYPE_A);
if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) {
qry.type = PP_HTONS(DNS_RRTYPE_AAAA);
} else {
qry.type = PP_HTONS(DNS_RRTYPE_A);
}
qry.cls = PP_HTONS(DNS_RRCLASS_IN);
pbuf_take_at(p, &qry, SIZEOF_DNS_QUERY, query_idx);
@ -840,6 +870,19 @@ dns_call_found(u8_t idx, ip_addr_t* addr)
u8_t i;
#endif
#if LWIP_IPV4 && LWIP_IPV6
if (addr != NULL) {
/* check that address type matches the request and adapt the table entry */
if (IP_IS_V6_VAL(*addr)) {
LWIP_ASSERT("invalid response", LWIP_DNS_ADDRTYPE_IS_IPV6(dns_table[idx].reqaddrtype));
dns_table[idx].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV6;
} else {
LWIP_ASSERT("invalid response", !LWIP_DNS_ADDRTYPE_IS_IPV6(dns_table[idx].reqaddrtype));
dns_table[idx].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV4;
}
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
for (i = 0; i < DNS_MAX_REQUESTS; i++) {
if (dns_requests[i].found && (dns_requests[i].dns_table_idx == idx)) {
@ -1068,7 +1111,9 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
/* check if "question" part matches the request */
pbuf_copy_partial(p, &qry, SIZEOF_DNS_QUERY, res_idx);
if((qry.type != PP_HTONS(DNS_RRTYPE_A)) || (qry.cls != PP_HTONS(DNS_RRCLASS_IN))) {
if((qry.cls != PP_HTONS(DNS_RRCLASS_IN)) ||
(LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_AAAA))) ||
(!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_A)))) {
LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name));
/* call callback to indicate error, clean up memory and return */
goto responseerr;
@ -1082,39 +1127,94 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
/* Check for IP address type and Internet class. Others are discarded. */
pbuf_copy_partial(p, &ans, SIZEOF_DNS_ANSWER, res_idx);
if (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) {
#if LWIP_IPV4
if((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) &&
(ans.len == PP_HTONS(sizeof(ip4_addr_t))) ) {
res_idx += SIZEOF_DNS_ANSWER;
/* read the answer resource record's TTL, and maximize it if needed */
entry->ttl = ntohl(ans.ttl);
if (entry->ttl > DNS_MAX_TTL) {
entry->ttl = DNS_MAX_TTL;
if((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.len == PP_HTONS(sizeof(ip4_addr_t)))) {
#if LWIP_IPV4 && LWIP_IPV6
if (!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype))
#endif /* LWIP_IPV4 && LWIP_IPV6 */
{
ip4_addr_t ip4addr;
res_idx += SIZEOF_DNS_ANSWER;
/* read the answer resource record's TTL, and maximize it if needed */
entry->ttl = ntohl(ans.ttl);
if (entry->ttl > DNS_MAX_TTL) {
entry->ttl = DNS_MAX_TTL;
}
/* read the IP address after answer resource record's header */
pbuf_copy_partial(p, &ip4addr, sizeof(ip4_addr_t), res_idx);
ip_addr_copy_from_ip4(entry->ipaddr, ip4addr);
LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", entry->name));
ip_addr_debug_print(DNS_DEBUG, (&(entry->ipaddr)));
LWIP_DEBUGF(DNS_DEBUG, ("\n"));
/* call specified callback function if provided */
dns_call_found(entry_idx, &entry->ipaddr);
if (entry->ttl == 0) {
/* RFC 883, page 29: "Zero values are
interpreted to mean that the RR can only be used for the
transaction in progress, and should not be cached."
-> flush this entry now */
goto flushentry;
}
/* deallocate memory and return */
goto memerr;
}
}
/* read the IP address after answer resource record's header */
pbuf_copy_partial(p, &(entry->ipaddr), sizeof(entry->ipaddr), res_idx);
LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", entry->name));
ip_addr_debug_print(DNS_DEBUG, (&(entry->ipaddr)));
LWIP_DEBUGF(DNS_DEBUG, ("\n"));
/* call specified callback function if provided */
dns_call_found(entry_idx, &entry->ipaddr);
if (entry->ttl == 0) {
/* RFC 883, page 29: "Zero values are
interpreted to mean that the RR can only be used for the
transaction in progress, and should not be cached."
-> flush this entry now */
goto flushentry;
}
/* deallocate memory and return */
goto memerr;
} else
#endif /* LWIP_IPV4 */
{
/* @todo: parse IPv6 answers */
res_idx += SIZEOF_DNS_ANSWER + htons(ans.len);
#if LWIP_IPV6
if((ans.type == PP_HTONS(DNS_RRTYPE_AAAA)) && (ans.len == PP_HTONS(sizeof(ip6_addr_t)))) {
#if LWIP_IPV4 && LWIP_IPV6
if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype))
#endif /* LWIP_IPV4 && LWIP_IPV6 */
{
ip6_addr_t ip6addr;
res_idx += SIZEOF_DNS_ANSWER;
/* read the answer resource record's TTL, and maximize it if needed */
entry->ttl = ntohl(ans.ttl);
if (entry->ttl > DNS_MAX_TTL) {
entry->ttl = DNS_MAX_TTL;
}
/* read the IP address after answer resource record's header */
pbuf_copy_partial(p, &ip6addr, sizeof(ip6_addr_t), res_idx);
ip_addr_copy_from_ip6(entry->ipaddr, ip6addr);
LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", entry->name));
ip_addr_debug_print(DNS_DEBUG, (&(entry->ipaddr)));
LWIP_DEBUGF(DNS_DEBUG, (" AAAA\n"));
/* call specified callback function if provided */
dns_call_found(entry_idx, &entry->ipaddr);
if (entry->ttl == 0) {
/* RFC 883, page 29: "Zero values are
interpreted to mean that the RR can only be used for the
transaction in progress, and should not be cached."
-> flush this entry now */
goto flushentry;
}
/* deallocate memory and return */
goto memerr;
}
}
#endif /* LWIP_IPV6 */
}
/* skip this answer */
res_idx += SIZEOF_DNS_ANSWER + htons(ans.len);
--nanswers;
}
#if LWIP_IPV4 && LWIP_IPV6
if ((entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) ||
(entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV6_IPV4)) {
if (entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) {
/* IPv4 failed, try IPv6 */
entry->reqaddrtype = LWIP_DNS_ADDRTYPE_IPV6;
} else {
/* IPv6 failed, try IPv4 */
entry->reqaddrtype = LWIP_DNS_ADDRTYPE_IPV4;
}
pbuf_free(p);
entry->state = DNS_STATE_NEW;
dns_check_entry(entry_idx);
return;
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", entry->name));
/* call callback to indicate error, clean up memory and return */
goto responseerr;
@ -1128,9 +1228,7 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
responseerr:
/* ERROR: call specified callback function with NULL as name to indicate an error */
dns_call_found(entry_idx, NULL);
#if LWIP_IPV4
flushentry:
#endif /* LWIP_IPV4 */
/* flush this entry */
dns_table[entry_idx].state = DNS_STATE_UNUSED;
@ -1151,7 +1249,7 @@ memerr:
*/
static err_t
dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found,
void *callback_arg)
void *callback_arg LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype))
{
u8_t i;
u8_t lseq, lseqi;
@ -1165,12 +1263,21 @@ dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found,
for (i = 0; i < DNS_TABLE_SIZE; i++) {
if ((dns_table[i].state == DNS_STATE_ASKING) &&
(LWIP_DNS_STRICMP(name, dns_table[i].name) == 0)) {
#if LWIP_IPV4 && LWIP_IPV6
if (dns_table[i].reqaddrtype != dns_addrtype) {
/* requested address types don't match
this can lead to 2 concurrent requests, but mixing the address types
for the same host should not be that common */
continue;
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
/* this is a duplicate entry, find a free request entry */
for (r = 0; r < DNS_MAX_REQUESTS; r++) {
if (dns_requests[r].found == 0) {
dns_requests[r].found = found;
dns_requests[r].arg = callback_arg;
dns_requests[r].dns_table_idx = i;
LWIP_DNS_SET_ADDRTYPE(dns_requests[r].reqaddrtype, dns_addrtype);
LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": duplicate request\n", name));
return ERR_INPROGRESS;
}
@ -1237,6 +1344,8 @@ dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found,
/* fill the entry */
entry->state = DNS_STATE_NEW;
entry->seqno = dns_seqno;
LWIP_DNS_SET_ADDRTYPE(entry->reqaddrtype, dns_addrtype);
LWIP_DNS_SET_ADDRTYPE(req->reqaddrtype, dns_addrtype);
req->found = found;
req->arg = callback_arg;
namelen = LWIP_MIN(hostnamelen, DNS_MAX_NAME_LENGTH-1);
@ -1287,6 +1396,21 @@ err_t
dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found,
void *callback_arg)
{
#if LWIP_IPV4 && LWIP_IPV6
return dns_gethostbyname_addrtype(hostname, addr, found, callback_arg, LWIP_DNS_ADDRTYPE_IPV4_IPV6);
}
/** Like dns_gethostbyname, but returned address type can be controlled:
* @param dns_addrtype: - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 first, try IPv6 if IPv4 fails only
* - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 first, try IPv4 if IPv6 fails only
* - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only
* - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only
*/
err_t
dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_callback found,
void *callback_arg, u8_t dns_addrtype)
{
#endif /* LWIP_IPV4 && LWIP_IPV6 */
size_t hostnamelen;
/* not initialized or no valid server yet, or invalid addr pointer
* or invalid hostname or invalid hostname length */
@ -1308,8 +1432,7 @@ dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback foun
#if LWIP_HAVE_LOOPIF
if (strcmp(hostname, "localhost") == 0) {
/* @todo: IPv6 support... */
ip_addr_set_loopback(0, addr);
ip_addr_set_loopback(LWIP_DNS_ADDRTYPE_IS_IPV6(dns_addrtype), addr);
return ERR_OK;
}
#endif /* LWIP_HAVE_LOOPIF */
@ -1319,12 +1442,26 @@ dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback foun
return ERR_OK;
}
/* already have this address cached? */
if(dns_lookup(hostname, addr) == ERR_OK) {
if(dns_lookup(hostname, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) {
return ERR_OK;
}
#if LWIP_IPV4 && LWIP_IPV6
if ((dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) || (dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6)) {
/* fallback to 2nd IP type and try again to lookup */
u8_t fallback;
if (dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) {
fallback = LWIP_DNS_ADDRTYPE_IPV6;
} else {
fallback = LWIP_DNS_ADDRTYPE_IPV4;
}
if(dns_lookup(hostname, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) {
return ERR_OK;
}
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
/* queue query with specified callback */
return dns_enqueue(hostname, hostnamelen, found, callback_arg);
return dns_enqueue(hostname, hostnamelen, found, callback_arg LWIP_DNS_ADDRTYPE_ARG(dns_addrtype));
}
#endif /* LWIP_DNS */

View File

@ -62,6 +62,7 @@ extern "C" {
#define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information */
#define DNS_RRTYPE_MX 15 /* mail exchange */
#define DNS_RRTYPE_TXT 16 /* text strings */
#define DNS_RRTYPE_AAAA 28 /* IPv6 address */
/** DNS field CLASS used for "Resource Records" */
#define DNS_RRCLASS_IN 1 /* the Internet */
@ -70,6 +71,12 @@ extern "C" {
#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */
#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */
/* DNS resolve types: */
#define LWIP_DNS_ADDRTYPE_IPV4_IPV6 0 /* try to resolve IPv4 first, try IPv6 if IPv4 fails only */
#define LWIP_DNS_ADDRTYPE_IPV6_IPV4 0xFF /* try to resolve IPv6 first, try IPv4 if IPv6 fails only */
#define LWIP_DNS_ADDRTYPE_IPV4 DNS_RRTYPE_A
#define LWIP_DNS_ADDRTYPE_IPV6 DNS_RRTYPE_AAAA
#if DNS_LOCAL_HOSTLIST
/** struct used for local host-list */
struct local_hostlist_entry {
@ -102,6 +109,15 @@ void dns_setserver(u8_t numdns, ip_addr_t *dnsserver);
ip_addr_t dns_getserver(u8_t numdns);
err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr,
dns_found_callback found, void *callback_arg);
#if LWIP_IPV4 && LWIP_IPV6
err_t dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr,
dns_found_callback found, void *callback_arg,
u8_t dns_addrtype);
#else /* LWIP_IPV4 && LWIP_IPV6 */
#define dns_gethostbyname_addrtype(hostname, addr, found, callback_arg, dns_addrtype) \
dns_gethostbyname(hostname, addr, found, callback_arg)
#endif /* LWIP_IPV4 && LWIP_IPV6 */
#if DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC
int dns_local_removehost(const char *hostname, const ip_addr_t *addr);

View File

@ -1027,8 +1027,9 @@
* byte order).
*
* Instead, you can also use an external function:
* #define DNS_LOOKUP_LOCAL_EXTERN(x) extern u32_t my_lookup_function(const char *name)
* that returns the IP address or INADDR_NONE if not found.
* #define DNS_LOOKUP_LOCAL_EXTERN(x) extern int my_lookup_function(const char *name, ip_addr_t* result, u8_t reqtype)
* that provides the IP address, returns 1 if found or 0 if not found and gets
* the type of the requested address passed (see LWIP_DNS_ADDRTYPE_*)
*/
#ifndef DNS_LOCAL_HOSTLIST
#define DNS_LOCAL_HOSTLIST 0