Official mbed lwIP library (version 1.4.0)

Dependents:   LwIPNetworking NetServicesMin EthernetInterface EthernetInterface_RSF ... more

Legacy Networking Libraries

This is an mbed 2 networking library. For mbed OS 5, lwip has been integrated with built-in networking interfaces. The networking libraries have been revised to better support additional network stacks and thread safety here.

This library is based on the code of lwIP v1.4.0

Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
All rights reserved. 

Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
   derived from this software without specific prior written permission. 

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.
Committer:
mbed_official
Date:
Mon Mar 14 16:15:36 2016 +0000
Revision:
20:08f08bfc3f3d
Parent:
0:51ac1d130fd4
Synchronized with git revision fec574a5ed6db26aca1b13992ff271bf527d4a0d

Full URL: https://github.com/mbedmicro/mbed/commit/fec574a5ed6db26aca1b13992ff271bf527d4a0d/

Increased allocated netbufs to handle DTLS handshakes

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 0:51ac1d130fd4 1 /**
mbed_official 0:51ac1d130fd4 2 * @file
mbed_official 0:51ac1d130fd4 3 * DNS - host name to IP address resolver.
mbed_official 0:51ac1d130fd4 4 *
mbed_official 0:51ac1d130fd4 5 */
mbed_official 0:51ac1d130fd4 6
mbed_official 0:51ac1d130fd4 7 /**
mbed_official 0:51ac1d130fd4 8
mbed_official 0:51ac1d130fd4 9 * This file implements a DNS host name to IP address resolver.
mbed_official 0:51ac1d130fd4 10
mbed_official 0:51ac1d130fd4 11 * Port to lwIP from uIP
mbed_official 0:51ac1d130fd4 12 * by Jim Pettinato April 2007
mbed_official 0:51ac1d130fd4 13
mbed_official 0:51ac1d130fd4 14 * uIP version Copyright (c) 2002-2003, Adam Dunkels.
mbed_official 0:51ac1d130fd4 15 * All rights reserved.
mbed_official 0:51ac1d130fd4 16 *
mbed_official 0:51ac1d130fd4 17 * Redistribution and use in source and binary forms, with or without
mbed_official 0:51ac1d130fd4 18 * modification, are permitted provided that the following conditions
mbed_official 0:51ac1d130fd4 19 * are met:
mbed_official 0:51ac1d130fd4 20 * 1. Redistributions of source code must retain the above copyright
mbed_official 0:51ac1d130fd4 21 * notice, this list of conditions and the following disclaimer.
mbed_official 0:51ac1d130fd4 22 * 2. Redistributions in binary form must reproduce the above copyright
mbed_official 0:51ac1d130fd4 23 * notice, this list of conditions and the following disclaimer in the
mbed_official 0:51ac1d130fd4 24 * documentation and/or other materials provided with the distribution.
mbed_official 0:51ac1d130fd4 25 * 3. The name of the author may not be used to endorse or promote
mbed_official 0:51ac1d130fd4 26 * products derived from this software without specific prior
mbed_official 0:51ac1d130fd4 27 * written permission.
mbed_official 0:51ac1d130fd4 28 *
mbed_official 0:51ac1d130fd4 29 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
mbed_official 0:51ac1d130fd4 30 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
mbed_official 0:51ac1d130fd4 31 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
mbed_official 0:51ac1d130fd4 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
mbed_official 0:51ac1d130fd4 33 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
mbed_official 0:51ac1d130fd4 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
mbed_official 0:51ac1d130fd4 35 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
mbed_official 0:51ac1d130fd4 36 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
mbed_official 0:51ac1d130fd4 37 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
mbed_official 0:51ac1d130fd4 38 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
mbed_official 0:51ac1d130fd4 39 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
mbed_official 0:51ac1d130fd4 40 *
mbed_official 0:51ac1d130fd4 41 *
mbed_official 0:51ac1d130fd4 42 * DNS.C
mbed_official 0:51ac1d130fd4 43 *
mbed_official 0:51ac1d130fd4 44 * The lwIP DNS resolver functions are used to lookup a host name and
mbed_official 0:51ac1d130fd4 45 * map it to a numerical IP address. It maintains a list of resolved
mbed_official 0:51ac1d130fd4 46 * hostnames that can be queried with the dns_lookup() function.
mbed_official 0:51ac1d130fd4 47 * New hostnames can be resolved using the dns_query() function.
mbed_official 0:51ac1d130fd4 48 *
mbed_official 0:51ac1d130fd4 49 * The lwIP version of the resolver also adds a non-blocking version of
mbed_official 0:51ac1d130fd4 50 * gethostbyname() that will work with a raw API application. This function
mbed_official 0:51ac1d130fd4 51 * checks for an IP address string first and converts it if it is valid.
mbed_official 0:51ac1d130fd4 52 * gethostbyname() then does a dns_lookup() to see if the name is
mbed_official 0:51ac1d130fd4 53 * already in the table. If so, the IP is returned. If not, a query is
mbed_official 0:51ac1d130fd4 54 * issued and the function returns with a ERR_INPROGRESS status. The app
mbed_official 0:51ac1d130fd4 55 * using the dns client must then go into a waiting state.
mbed_official 0:51ac1d130fd4 56 *
mbed_official 0:51ac1d130fd4 57 * Once a hostname has been resolved (or found to be non-existent),
mbed_official 0:51ac1d130fd4 58 * the resolver code calls a specified callback function (which
mbed_official 0:51ac1d130fd4 59 * must be implemented by the module that uses the resolver).
mbed_official 0:51ac1d130fd4 60 */
mbed_official 0:51ac1d130fd4 61
mbed_official 0:51ac1d130fd4 62 /*-----------------------------------------------------------------------------
mbed_official 0:51ac1d130fd4 63 * RFC 1035 - Domain names - implementation and specification
mbed_official 0:51ac1d130fd4 64 * RFC 2181 - Clarifications to the DNS Specification
mbed_official 0:51ac1d130fd4 65 *----------------------------------------------------------------------------*/
mbed_official 0:51ac1d130fd4 66
mbed_official 0:51ac1d130fd4 67 /** @todo: define good default values (rfc compliance) */
mbed_official 0:51ac1d130fd4 68 /** @todo: improve answer parsing, more checkings... */
mbed_official 0:51ac1d130fd4 69 /** @todo: check RFC1035 - 7.3. Processing responses */
mbed_official 0:51ac1d130fd4 70
mbed_official 0:51ac1d130fd4 71 /*-----------------------------------------------------------------------------
mbed_official 0:51ac1d130fd4 72 * Includes
mbed_official 0:51ac1d130fd4 73 *----------------------------------------------------------------------------*/
mbed_official 0:51ac1d130fd4 74
mbed_official 0:51ac1d130fd4 75 #include "lwip/opt.h"
mbed_official 0:51ac1d130fd4 76
mbed_official 0:51ac1d130fd4 77 #if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
mbed_official 0:51ac1d130fd4 78
mbed_official 0:51ac1d130fd4 79 #include "lwip/udp.h"
mbed_official 0:51ac1d130fd4 80 #include "lwip/mem.h"
mbed_official 0:51ac1d130fd4 81 #include "lwip/memp.h"
mbed_official 0:51ac1d130fd4 82 #include "lwip/dns.h"
mbed_official 0:51ac1d130fd4 83
mbed_official 0:51ac1d130fd4 84 #include <string.h>
mbed_official 0:51ac1d130fd4 85
mbed_official 0:51ac1d130fd4 86 /** DNS server IP address */
mbed_official 0:51ac1d130fd4 87 #ifndef DNS_SERVER_ADDRESS
mbed_official 0:51ac1d130fd4 88 #define DNS_SERVER_ADDRESS(ipaddr) (ip4_addr_set_u32(ipaddr, ipaddr_addr("208.67.222.222"))) /* resolver1.opendns.com */
mbed_official 0:51ac1d130fd4 89 #endif
mbed_official 0:51ac1d130fd4 90
mbed_official 0:51ac1d130fd4 91 /** DNS server port address */
mbed_official 0:51ac1d130fd4 92 #ifndef DNS_SERVER_PORT
mbed_official 0:51ac1d130fd4 93 #define DNS_SERVER_PORT 53
mbed_official 0:51ac1d130fd4 94 #endif
mbed_official 0:51ac1d130fd4 95
mbed_official 0:51ac1d130fd4 96 /** DNS maximum number of retries when asking for a name, before "timeout". */
mbed_official 0:51ac1d130fd4 97 #ifndef DNS_MAX_RETRIES
mbed_official 0:51ac1d130fd4 98 #define DNS_MAX_RETRIES 4
mbed_official 0:51ac1d130fd4 99 #endif
mbed_official 0:51ac1d130fd4 100
mbed_official 0:51ac1d130fd4 101 /** DNS resource record max. TTL (one week as default) */
mbed_official 0:51ac1d130fd4 102 #ifndef DNS_MAX_TTL
mbed_official 0:51ac1d130fd4 103 #define DNS_MAX_TTL 604800
mbed_official 0:51ac1d130fd4 104 #endif
mbed_official 0:51ac1d130fd4 105
mbed_official 0:51ac1d130fd4 106 /* DNS protocol flags */
mbed_official 0:51ac1d130fd4 107 #define DNS_FLAG1_RESPONSE 0x80
mbed_official 0:51ac1d130fd4 108 #define DNS_FLAG1_OPCODE_STATUS 0x10
mbed_official 0:51ac1d130fd4 109 #define DNS_FLAG1_OPCODE_INVERSE 0x08
mbed_official 0:51ac1d130fd4 110 #define DNS_FLAG1_OPCODE_STANDARD 0x00
mbed_official 0:51ac1d130fd4 111 #define DNS_FLAG1_AUTHORATIVE 0x04
mbed_official 0:51ac1d130fd4 112 #define DNS_FLAG1_TRUNC 0x02
mbed_official 0:51ac1d130fd4 113 #define DNS_FLAG1_RD 0x01
mbed_official 0:51ac1d130fd4 114 #define DNS_FLAG2_RA 0x80
mbed_official 0:51ac1d130fd4 115 #define DNS_FLAG2_ERR_MASK 0x0f
mbed_official 0:51ac1d130fd4 116 #define DNS_FLAG2_ERR_NONE 0x00
mbed_official 0:51ac1d130fd4 117 #define DNS_FLAG2_ERR_NAME 0x03
mbed_official 0:51ac1d130fd4 118
mbed_official 0:51ac1d130fd4 119 /* DNS protocol states */
mbed_official 0:51ac1d130fd4 120 #define DNS_STATE_UNUSED 0
mbed_official 0:51ac1d130fd4 121 #define DNS_STATE_NEW 1
mbed_official 0:51ac1d130fd4 122 #define DNS_STATE_ASKING 2
mbed_official 0:51ac1d130fd4 123 #define DNS_STATE_DONE 3
mbed_official 0:51ac1d130fd4 124
mbed_official 0:51ac1d130fd4 125 #ifdef PACK_STRUCT_USE_INCLUDES
mbed_official 0:51ac1d130fd4 126 # include "arch/bpstruct.h"
mbed_official 0:51ac1d130fd4 127 #endif
mbed_official 0:51ac1d130fd4 128 PACK_STRUCT_BEGIN
mbed_official 0:51ac1d130fd4 129 /** DNS message header */
mbed_official 0:51ac1d130fd4 130 struct dns_hdr {
mbed_official 0:51ac1d130fd4 131 PACK_STRUCT_FIELD(u16_t id);
mbed_official 0:51ac1d130fd4 132 PACK_STRUCT_FIELD(u8_t flags1);
mbed_official 0:51ac1d130fd4 133 PACK_STRUCT_FIELD(u8_t flags2);
mbed_official 0:51ac1d130fd4 134 PACK_STRUCT_FIELD(u16_t numquestions);
mbed_official 0:51ac1d130fd4 135 PACK_STRUCT_FIELD(u16_t numanswers);
mbed_official 0:51ac1d130fd4 136 PACK_STRUCT_FIELD(u16_t numauthrr);
mbed_official 0:51ac1d130fd4 137 PACK_STRUCT_FIELD(u16_t numextrarr);
mbed_official 0:51ac1d130fd4 138 } PACK_STRUCT_STRUCT;
mbed_official 0:51ac1d130fd4 139 PACK_STRUCT_END
mbed_official 0:51ac1d130fd4 140 #ifdef PACK_STRUCT_USE_INCLUDES
mbed_official 0:51ac1d130fd4 141 # include "arch/epstruct.h"
mbed_official 0:51ac1d130fd4 142 #endif
mbed_official 0:51ac1d130fd4 143 #define SIZEOF_DNS_HDR 12
mbed_official 0:51ac1d130fd4 144
mbed_official 0:51ac1d130fd4 145 /** DNS query message structure.
mbed_official 0:51ac1d130fd4 146 No packing needed: only used locally on the stack. */
mbed_official 0:51ac1d130fd4 147 struct dns_query {
mbed_official 0:51ac1d130fd4 148 /* DNS query record starts with either a domain name or a pointer
mbed_official 0:51ac1d130fd4 149 to a name already present somewhere in the packet. */
mbed_official 0:51ac1d130fd4 150 u16_t type;
mbed_official 0:51ac1d130fd4 151 u16_t cls;
mbed_official 0:51ac1d130fd4 152 };
mbed_official 0:51ac1d130fd4 153 #define SIZEOF_DNS_QUERY 4
mbed_official 0:51ac1d130fd4 154
mbed_official 0:51ac1d130fd4 155 /** DNS answer message structure.
mbed_official 0:51ac1d130fd4 156 No packing needed: only used locally on the stack. */
mbed_official 0:51ac1d130fd4 157 struct dns_answer {
mbed_official 0:51ac1d130fd4 158 /* DNS answer record starts with either a domain name or a pointer
mbed_official 0:51ac1d130fd4 159 to a name already present somewhere in the packet. */
mbed_official 0:51ac1d130fd4 160 u16_t type;
mbed_official 0:51ac1d130fd4 161 u16_t cls;
mbed_official 0:51ac1d130fd4 162 u32_t ttl;
mbed_official 0:51ac1d130fd4 163 u16_t len;
mbed_official 0:51ac1d130fd4 164 };
mbed_official 0:51ac1d130fd4 165 #define SIZEOF_DNS_ANSWER 10
mbed_official 0:51ac1d130fd4 166
mbed_official 0:51ac1d130fd4 167 /** DNS table entry */
mbed_official 0:51ac1d130fd4 168 struct dns_table_entry {
mbed_official 0:51ac1d130fd4 169 u8_t state;
mbed_official 0:51ac1d130fd4 170 u8_t numdns;
mbed_official 0:51ac1d130fd4 171 u8_t tmr;
mbed_official 0:51ac1d130fd4 172 u8_t retries;
mbed_official 0:51ac1d130fd4 173 u8_t seqno;
mbed_official 0:51ac1d130fd4 174 u8_t err;
mbed_official 0:51ac1d130fd4 175 u32_t ttl;
mbed_official 0:51ac1d130fd4 176 char name[DNS_MAX_NAME_LENGTH];
mbed_official 0:51ac1d130fd4 177 ip_addr_t ipaddr;
mbed_official 0:51ac1d130fd4 178 /* pointer to callback on DNS query done */
mbed_official 0:51ac1d130fd4 179 dns_found_callback found;
mbed_official 0:51ac1d130fd4 180 void *arg;
mbed_official 0:51ac1d130fd4 181 };
mbed_official 0:51ac1d130fd4 182
mbed_official 0:51ac1d130fd4 183 #if DNS_LOCAL_HOSTLIST
mbed_official 0:51ac1d130fd4 184
mbed_official 0:51ac1d130fd4 185 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
mbed_official 0:51ac1d130fd4 186 /** Local host-list. For hostnames in this list, no
mbed_official 0:51ac1d130fd4 187 * external name resolution is performed */
mbed_official 0:51ac1d130fd4 188 static struct local_hostlist_entry *local_hostlist_dynamic;
mbed_official 0:51ac1d130fd4 189 #else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
mbed_official 0:51ac1d130fd4 190
mbed_official 0:51ac1d130fd4 191 /** Defining this allows the local_hostlist_static to be placed in a different
mbed_official 0:51ac1d130fd4 192 * linker section (e.g. FLASH) */
mbed_official 0:51ac1d130fd4 193 #ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE
mbed_official 0:51ac1d130fd4 194 #define DNS_LOCAL_HOSTLIST_STORAGE_PRE static
mbed_official 0:51ac1d130fd4 195 #endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */
mbed_official 0:51ac1d130fd4 196 /** Defining this allows the local_hostlist_static to be placed in a different
mbed_official 0:51ac1d130fd4 197 * linker section (e.g. FLASH) */
mbed_official 0:51ac1d130fd4 198 #ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST
mbed_official 0:51ac1d130fd4 199 #define DNS_LOCAL_HOSTLIST_STORAGE_POST
mbed_official 0:51ac1d130fd4 200 #endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */
mbed_official 0:51ac1d130fd4 201 DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[]
mbed_official 0:51ac1d130fd4 202 DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT;
mbed_official 0:51ac1d130fd4 203
mbed_official 0:51ac1d130fd4 204 #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
mbed_official 0:51ac1d130fd4 205
mbed_official 0:51ac1d130fd4 206 static void dns_init_local();
mbed_official 0:51ac1d130fd4 207 #endif /* DNS_LOCAL_HOSTLIST */
mbed_official 0:51ac1d130fd4 208
mbed_official 0:51ac1d130fd4 209
mbed_official 0:51ac1d130fd4 210 /* forward declarations */
mbed_official 0:51ac1d130fd4 211 static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port);
mbed_official 0:51ac1d130fd4 212 static void dns_check_entries(void);
mbed_official 0:51ac1d130fd4 213
mbed_official 0:51ac1d130fd4 214 /*-----------------------------------------------------------------------------
mbed_official 0:51ac1d130fd4 215 * Globales
mbed_official 0:51ac1d130fd4 216 *----------------------------------------------------------------------------*/
mbed_official 0:51ac1d130fd4 217
mbed_official 0:51ac1d130fd4 218 /* DNS variables */
mbed_official 0:51ac1d130fd4 219 static struct udp_pcb *dns_pcb;
mbed_official 0:51ac1d130fd4 220 static u8_t dns_seqno;
mbed_official 0:51ac1d130fd4 221 static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
mbed_official 0:51ac1d130fd4 222 static ip_addr_t dns_servers[DNS_MAX_SERVERS];
mbed_official 0:51ac1d130fd4 223 /** Contiguous buffer for processing responses */
mbed_official 0:51ac1d130fd4 224 static u8_t dns_payload_buffer[LWIP_MEM_ALIGN_BUFFER(DNS_MSG_SIZE)];
mbed_official 0:51ac1d130fd4 225 static u8_t* dns_payload;
mbed_official 0:51ac1d130fd4 226
mbed_official 0:51ac1d130fd4 227 /**
mbed_official 0:51ac1d130fd4 228 * Initialize the resolver: set up the UDP pcb and configure the default server
mbed_official 0:51ac1d130fd4 229 * (DNS_SERVER_ADDRESS).
mbed_official 0:51ac1d130fd4 230 */
mbed_official 0:51ac1d130fd4 231 void
mbed_official 0:51ac1d130fd4 232 dns_init()
mbed_official 0:51ac1d130fd4 233 {
mbed_official 0:51ac1d130fd4 234 ip_addr_t dnsserver;
mbed_official 0:51ac1d130fd4 235
mbed_official 0:51ac1d130fd4 236 dns_payload = (u8_t *)LWIP_MEM_ALIGN(dns_payload_buffer);
mbed_official 0:51ac1d130fd4 237
mbed_official 0:51ac1d130fd4 238 /* initialize default DNS server address */
mbed_official 0:51ac1d130fd4 239 DNS_SERVER_ADDRESS(&dnsserver);
mbed_official 0:51ac1d130fd4 240
mbed_official 0:51ac1d130fd4 241 LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n"));
mbed_official 0:51ac1d130fd4 242
mbed_official 0:51ac1d130fd4 243 /* if dns client not yet initialized... */
mbed_official 0:51ac1d130fd4 244 if (dns_pcb == NULL) {
mbed_official 0:51ac1d130fd4 245 dns_pcb = udp_new();
mbed_official 0:51ac1d130fd4 246
mbed_official 0:51ac1d130fd4 247 if (dns_pcb != NULL) {
mbed_official 0:51ac1d130fd4 248 /* initialize DNS table not needed (initialized to zero since it is a
mbed_official 0:51ac1d130fd4 249 * global variable) */
mbed_official 0:51ac1d130fd4 250 LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0",
mbed_official 0:51ac1d130fd4 251 DNS_STATE_UNUSED == 0);
mbed_official 0:51ac1d130fd4 252
mbed_official 0:51ac1d130fd4 253 /* initialize DNS client */
mbed_official 0:51ac1d130fd4 254 udp_bind(dns_pcb, IP_ADDR_ANY, 0);
mbed_official 0:51ac1d130fd4 255 udp_recv(dns_pcb, dns_recv, NULL);
mbed_official 0:51ac1d130fd4 256
mbed_official 0:51ac1d130fd4 257 /* initialize default DNS primary server */
mbed_official 0:51ac1d130fd4 258 dns_setserver(0, &dnsserver);
mbed_official 0:51ac1d130fd4 259 }
mbed_official 0:51ac1d130fd4 260 }
mbed_official 0:51ac1d130fd4 261 #if DNS_LOCAL_HOSTLIST
mbed_official 0:51ac1d130fd4 262 dns_init_local();
mbed_official 0:51ac1d130fd4 263 #endif
mbed_official 0:51ac1d130fd4 264 }
mbed_official 0:51ac1d130fd4 265
mbed_official 0:51ac1d130fd4 266 /**
mbed_official 0:51ac1d130fd4 267 * Initialize one of the DNS servers.
mbed_official 0:51ac1d130fd4 268 *
mbed_official 0:51ac1d130fd4 269 * @param numdns the index of the DNS server to set must be < DNS_MAX_SERVERS
mbed_official 0:51ac1d130fd4 270 * @param dnsserver IP address of the DNS server to set
mbed_official 0:51ac1d130fd4 271 */
mbed_official 0:51ac1d130fd4 272 void
mbed_official 0:51ac1d130fd4 273 dns_setserver(u8_t numdns, ip_addr_t *dnsserver)
mbed_official 0:51ac1d130fd4 274 {
mbed_official 0:51ac1d130fd4 275 if ((numdns < DNS_MAX_SERVERS) && (dns_pcb != NULL) &&
mbed_official 0:51ac1d130fd4 276 (dnsserver != NULL) && !ip_addr_isany(dnsserver)) {
mbed_official 0:51ac1d130fd4 277 dns_servers[numdns] = (*dnsserver);
mbed_official 0:51ac1d130fd4 278 }
mbed_official 0:51ac1d130fd4 279 }
mbed_official 0:51ac1d130fd4 280
mbed_official 0:51ac1d130fd4 281 /**
mbed_official 0:51ac1d130fd4 282 * Obtain one of the currently configured DNS server.
mbed_official 0:51ac1d130fd4 283 *
mbed_official 0:51ac1d130fd4 284 * @param numdns the index of the DNS server
mbed_official 0:51ac1d130fd4 285 * @return IP address of the indexed DNS server or "ip_addr_any" if the DNS
mbed_official 0:51ac1d130fd4 286 * server has not been configured.
mbed_official 0:51ac1d130fd4 287 */
mbed_official 0:51ac1d130fd4 288 ip_addr_t
mbed_official 0:51ac1d130fd4 289 dns_getserver(u8_t numdns)
mbed_official 0:51ac1d130fd4 290 {
mbed_official 0:51ac1d130fd4 291 if (numdns < DNS_MAX_SERVERS) {
mbed_official 0:51ac1d130fd4 292 return dns_servers[numdns];
mbed_official 0:51ac1d130fd4 293 } else {
mbed_official 0:51ac1d130fd4 294 return *IP_ADDR_ANY;
mbed_official 0:51ac1d130fd4 295 }
mbed_official 0:51ac1d130fd4 296 }
mbed_official 0:51ac1d130fd4 297
mbed_official 0:51ac1d130fd4 298 /**
mbed_official 0:51ac1d130fd4 299 * The DNS resolver client timer - handle retries and timeouts and should
mbed_official 0:51ac1d130fd4 300 * be called every DNS_TMR_INTERVAL milliseconds (every second by default).
mbed_official 0:51ac1d130fd4 301 */
mbed_official 0:51ac1d130fd4 302 void
mbed_official 0:51ac1d130fd4 303 dns_tmr(void)
mbed_official 0:51ac1d130fd4 304 {
mbed_official 0:51ac1d130fd4 305 if (dns_pcb != NULL) {
mbed_official 0:51ac1d130fd4 306 LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n"));
mbed_official 0:51ac1d130fd4 307 dns_check_entries();
mbed_official 0:51ac1d130fd4 308 }
mbed_official 0:51ac1d130fd4 309 }
mbed_official 0:51ac1d130fd4 310
mbed_official 0:51ac1d130fd4 311 #if DNS_LOCAL_HOSTLIST
mbed_official 0:51ac1d130fd4 312 static void
mbed_official 0:51ac1d130fd4 313 dns_init_local()
mbed_official 0:51ac1d130fd4 314 {
mbed_official 0:51ac1d130fd4 315 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT)
mbed_official 0:51ac1d130fd4 316 int i;
mbed_official 0:51ac1d130fd4 317 struct local_hostlist_entry *entry;
mbed_official 0:51ac1d130fd4 318 /* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */
mbed_official 0:51ac1d130fd4 319 struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT;
mbed_official 0:51ac1d130fd4 320 size_t namelen;
mbed_official 0:51ac1d130fd4 321 for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) {
mbed_official 0:51ac1d130fd4 322 struct local_hostlist_entry *init_entry = &local_hostlist_init[i];
mbed_official 0:51ac1d130fd4 323 LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL);
mbed_official 0:51ac1d130fd4 324 namelen = strlen(init_entry->name);
mbed_official 0:51ac1d130fd4 325 LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
mbed_official 0:51ac1d130fd4 326 entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
mbed_official 0:51ac1d130fd4 327 LWIP_ASSERT("mem-error in dns_init_local", entry != NULL);
mbed_official 0:51ac1d130fd4 328 if (entry != NULL) {
mbed_official 0:51ac1d130fd4 329 entry->name = (char*)entry + sizeof(struct local_hostlist_entry);
mbed_official 0:51ac1d130fd4 330 MEMCPY((char*)entry->name, init_entry->name, namelen);
mbed_official 0:51ac1d130fd4 331 ((char*)entry->name)[namelen] = 0;
mbed_official 0:51ac1d130fd4 332 entry->addr = init_entry->addr;
mbed_official 0:51ac1d130fd4 333 entry->next = local_hostlist_dynamic;
mbed_official 0:51ac1d130fd4 334 local_hostlist_dynamic = entry;
mbed_official 0:51ac1d130fd4 335 }
mbed_official 0:51ac1d130fd4 336 }
mbed_official 0:51ac1d130fd4 337 #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */
mbed_official 0:51ac1d130fd4 338 }
mbed_official 0:51ac1d130fd4 339
mbed_official 0:51ac1d130fd4 340 /**
mbed_official 0:51ac1d130fd4 341 * Scans the local host-list for a hostname.
mbed_official 0:51ac1d130fd4 342 *
mbed_official 0:51ac1d130fd4 343 * @param hostname Hostname to look for in the local host-list
mbed_official 0:51ac1d130fd4 344 * @return The first IP address for the hostname in the local host-list or
mbed_official 0:51ac1d130fd4 345 * IPADDR_NONE if not found.
mbed_official 0:51ac1d130fd4 346 */
mbed_official 0:51ac1d130fd4 347 static u32_t
mbed_official 0:51ac1d130fd4 348 dns_lookup_local(const char *hostname)
mbed_official 0:51ac1d130fd4 349 {
mbed_official 0:51ac1d130fd4 350 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
mbed_official 0:51ac1d130fd4 351 struct local_hostlist_entry *entry = local_hostlist_dynamic;
mbed_official 0:51ac1d130fd4 352 while(entry != NULL) {
mbed_official 0:51ac1d130fd4 353 if(strcmp(entry->name, hostname) == 0) {
mbed_official 0:51ac1d130fd4 354 return ip4_addr_get_u32(&entry->addr);
mbed_official 0:51ac1d130fd4 355 }
mbed_official 0:51ac1d130fd4 356 entry = entry->next;
mbed_official 0:51ac1d130fd4 357 }
mbed_official 0:51ac1d130fd4 358 #else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
mbed_official 0:51ac1d130fd4 359 int i;
mbed_official 0:51ac1d130fd4 360 for (i = 0; i < sizeof(local_hostlist_static) / sizeof(struct local_hostlist_entry); i++) {
mbed_official 0:51ac1d130fd4 361 if(strcmp(local_hostlist_static[i].name, hostname) == 0) {
mbed_official 0:51ac1d130fd4 362 return ip4_addr_get_u32(&local_hostlist_static[i].addr);
mbed_official 0:51ac1d130fd4 363 }
mbed_official 0:51ac1d130fd4 364 }
mbed_official 0:51ac1d130fd4 365 #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
mbed_official 0:51ac1d130fd4 366 return IPADDR_NONE;
mbed_official 0:51ac1d130fd4 367 }
mbed_official 0:51ac1d130fd4 368
mbed_official 0:51ac1d130fd4 369 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
mbed_official 0:51ac1d130fd4 370 /** Remove all entries from the local host-list for a specific hostname
mbed_official 0:51ac1d130fd4 371 * and/or IP addess
mbed_official 0:51ac1d130fd4 372 *
mbed_official 0:51ac1d130fd4 373 * @param hostname hostname for which entries shall be removed from the local
mbed_official 0:51ac1d130fd4 374 * host-list
mbed_official 0:51ac1d130fd4 375 * @param addr address for which entries shall be removed from the local host-list
mbed_official 0:51ac1d130fd4 376 * @return the number of removed entries
mbed_official 0:51ac1d130fd4 377 */
mbed_official 0:51ac1d130fd4 378 int
mbed_official 0:51ac1d130fd4 379 dns_local_removehost(const char *hostname, const ip_addr_t *addr)
mbed_official 0:51ac1d130fd4 380 {
mbed_official 0:51ac1d130fd4 381 int removed = 0;
mbed_official 0:51ac1d130fd4 382 struct local_hostlist_entry *entry = local_hostlist_dynamic;
mbed_official 0:51ac1d130fd4 383 struct local_hostlist_entry *last_entry = NULL;
mbed_official 0:51ac1d130fd4 384 while (entry != NULL) {
mbed_official 0:51ac1d130fd4 385 if (((hostname == NULL) || !strcmp(entry->name, hostname)) &&
mbed_official 0:51ac1d130fd4 386 ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) {
mbed_official 0:51ac1d130fd4 387 struct local_hostlist_entry *free_entry;
mbed_official 0:51ac1d130fd4 388 if (last_entry != NULL) {
mbed_official 0:51ac1d130fd4 389 last_entry->next = entry->next;
mbed_official 0:51ac1d130fd4 390 } else {
mbed_official 0:51ac1d130fd4 391 local_hostlist_dynamic = entry->next;
mbed_official 0:51ac1d130fd4 392 }
mbed_official 0:51ac1d130fd4 393 free_entry = entry;
mbed_official 0:51ac1d130fd4 394 entry = entry->next;
mbed_official 0:51ac1d130fd4 395 memp_free(MEMP_LOCALHOSTLIST, free_entry);
mbed_official 0:51ac1d130fd4 396 removed++;
mbed_official 0:51ac1d130fd4 397 } else {
mbed_official 0:51ac1d130fd4 398 last_entry = entry;
mbed_official 0:51ac1d130fd4 399 entry = entry->next;
mbed_official 0:51ac1d130fd4 400 }
mbed_official 0:51ac1d130fd4 401 }
mbed_official 0:51ac1d130fd4 402 return removed;
mbed_official 0:51ac1d130fd4 403 }
mbed_official 0:51ac1d130fd4 404
mbed_official 0:51ac1d130fd4 405 /**
mbed_official 0:51ac1d130fd4 406 * Add a hostname/IP address pair to the local host-list.
mbed_official 0:51ac1d130fd4 407 * Duplicates are not checked.
mbed_official 0:51ac1d130fd4 408 *
mbed_official 0:51ac1d130fd4 409 * @param hostname hostname of the new entry
mbed_official 0:51ac1d130fd4 410 * @param addr IP address of the new entry
mbed_official 0:51ac1d130fd4 411 * @return ERR_OK if succeeded or ERR_MEM on memory error
mbed_official 0:51ac1d130fd4 412 */
mbed_official 0:51ac1d130fd4 413 err_t
mbed_official 0:51ac1d130fd4 414 dns_local_addhost(const char *hostname, const ip_addr_t *addr)
mbed_official 0:51ac1d130fd4 415 {
mbed_official 0:51ac1d130fd4 416 struct local_hostlist_entry *entry;
mbed_official 0:51ac1d130fd4 417 size_t namelen;
mbed_official 0:51ac1d130fd4 418 LWIP_ASSERT("invalid host name (NULL)", hostname != NULL);
mbed_official 0:51ac1d130fd4 419 namelen = strlen(hostname);
mbed_official 0:51ac1d130fd4 420 LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
mbed_official 0:51ac1d130fd4 421 entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
mbed_official 0:51ac1d130fd4 422 if (entry == NULL) {
mbed_official 0:51ac1d130fd4 423 return ERR_MEM;
mbed_official 0:51ac1d130fd4 424 }
mbed_official 0:51ac1d130fd4 425 entry->name = (char*)entry + sizeof(struct local_hostlist_entry);
mbed_official 0:51ac1d130fd4 426 MEMCPY((char*)entry->name, hostname, namelen);
mbed_official 0:51ac1d130fd4 427 ((char*)entry->name)[namelen] = 0;
mbed_official 0:51ac1d130fd4 428 ip_addr_copy(entry->addr, *addr);
mbed_official 0:51ac1d130fd4 429 entry->next = local_hostlist_dynamic;
mbed_official 0:51ac1d130fd4 430 local_hostlist_dynamic = entry;
mbed_official 0:51ac1d130fd4 431 return ERR_OK;
mbed_official 0:51ac1d130fd4 432 }
mbed_official 0:51ac1d130fd4 433 #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/
mbed_official 0:51ac1d130fd4 434 #endif /* DNS_LOCAL_HOSTLIST */
mbed_official 0:51ac1d130fd4 435
mbed_official 0:51ac1d130fd4 436 /**
mbed_official 0:51ac1d130fd4 437 * Look up a hostname in the array of known hostnames.
mbed_official 0:51ac1d130fd4 438 *
mbed_official 0:51ac1d130fd4 439 * @note This function only looks in the internal array of known
mbed_official 0:51ac1d130fd4 440 * hostnames, it does not send out a query for the hostname if none
mbed_official 0:51ac1d130fd4 441 * was found. The function dns_enqueue() can be used to send a query
mbed_official 0:51ac1d130fd4 442 * for a hostname.
mbed_official 0:51ac1d130fd4 443 *
mbed_official 0:51ac1d130fd4 444 * @param name the hostname to look up
mbed_official 0:51ac1d130fd4 445 * @return the hostname's IP address, as u32_t (instead of ip_addr_t to
mbed_official 0:51ac1d130fd4 446 * better check for failure: != IPADDR_NONE) or IPADDR_NONE if the hostname
mbed_official 0:51ac1d130fd4 447 * was not found in the cached dns_table.
mbed_official 0:51ac1d130fd4 448 */
mbed_official 0:51ac1d130fd4 449 static u32_t
mbed_official 0:51ac1d130fd4 450 dns_lookup(const char *name)
mbed_official 0:51ac1d130fd4 451 {
mbed_official 0:51ac1d130fd4 452 u8_t i;
mbed_official 0:51ac1d130fd4 453 #if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN)
mbed_official 0:51ac1d130fd4 454 u32_t addr;
mbed_official 0:51ac1d130fd4 455 #endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */
mbed_official 0:51ac1d130fd4 456 #if DNS_LOCAL_HOSTLIST
mbed_official 0:51ac1d130fd4 457 if ((addr = dns_lookup_local(name)) != IPADDR_NONE) {
mbed_official 0:51ac1d130fd4 458 return addr;
mbed_official 0:51ac1d130fd4 459 }
mbed_official 0:51ac1d130fd4 460 #endif /* DNS_LOCAL_HOSTLIST */
mbed_official 0:51ac1d130fd4 461 #ifdef DNS_LOOKUP_LOCAL_EXTERN
mbed_official 0:51ac1d130fd4 462 if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) != IPADDR_NONE) {
mbed_official 0:51ac1d130fd4 463 return addr;
mbed_official 0:51ac1d130fd4 464 }
mbed_official 0:51ac1d130fd4 465 #endif /* DNS_LOOKUP_LOCAL_EXTERN */
mbed_official 0:51ac1d130fd4 466
mbed_official 0:51ac1d130fd4 467 /* Walk through name list, return entry if found. If not, return NULL. */
mbed_official 0:51ac1d130fd4 468 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
mbed_official 0:51ac1d130fd4 469 if ((dns_table[i].state == DNS_STATE_DONE) &&
mbed_official 0:51ac1d130fd4 470 (strcmp(name, dns_table[i].name) == 0)) {
mbed_official 0:51ac1d130fd4 471 LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name));
mbed_official 0:51ac1d130fd4 472 ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr));
mbed_official 0:51ac1d130fd4 473 LWIP_DEBUGF(DNS_DEBUG, ("\n"));
mbed_official 0:51ac1d130fd4 474 return ip4_addr_get_u32(&dns_table[i].ipaddr);
mbed_official 0:51ac1d130fd4 475 }
mbed_official 0:51ac1d130fd4 476 }
mbed_official 0:51ac1d130fd4 477
mbed_official 0:51ac1d130fd4 478 return IPADDR_NONE;
mbed_official 0:51ac1d130fd4 479 }
mbed_official 0:51ac1d130fd4 480
mbed_official 0:51ac1d130fd4 481 #if DNS_DOES_NAME_CHECK
mbed_official 0:51ac1d130fd4 482 /**
mbed_official 0:51ac1d130fd4 483 * Compare the "dotted" name "query" with the encoded name "response"
mbed_official 0:51ac1d130fd4 484 * to make sure an answer from the DNS server matches the current dns_table
mbed_official 0:51ac1d130fd4 485 * entry (otherwise, answers might arrive late for hostname not on the list
mbed_official 0:51ac1d130fd4 486 * any more).
mbed_official 0:51ac1d130fd4 487 *
mbed_official 0:51ac1d130fd4 488 * @param query hostname (not encoded) from the dns_table
mbed_official 0:51ac1d130fd4 489 * @param response encoded hostname in the DNS response
mbed_official 0:51ac1d130fd4 490 * @return 0: names equal; 1: names differ
mbed_official 0:51ac1d130fd4 491 */
mbed_official 0:51ac1d130fd4 492 static u8_t
mbed_official 0:51ac1d130fd4 493 dns_compare_name(unsigned char *query, unsigned char *response)
mbed_official 0:51ac1d130fd4 494 {
mbed_official 0:51ac1d130fd4 495 unsigned char n;
mbed_official 0:51ac1d130fd4 496
mbed_official 0:51ac1d130fd4 497 do {
mbed_official 0:51ac1d130fd4 498 n = *response++;
mbed_official 0:51ac1d130fd4 499 /** @see RFC 1035 - 4.1.4. Message compression */
mbed_official 0:51ac1d130fd4 500 if ((n & 0xc0) == 0xc0) {
mbed_official 0:51ac1d130fd4 501 /* Compressed name */
mbed_official 0:51ac1d130fd4 502 break;
mbed_official 0:51ac1d130fd4 503 } else {
mbed_official 0:51ac1d130fd4 504 /* Not compressed name */
mbed_official 0:51ac1d130fd4 505 while (n > 0) {
mbed_official 0:51ac1d130fd4 506 if ((*query) != (*response)) {
mbed_official 0:51ac1d130fd4 507 return 1;
mbed_official 0:51ac1d130fd4 508 }
mbed_official 0:51ac1d130fd4 509 ++response;
mbed_official 0:51ac1d130fd4 510 ++query;
mbed_official 0:51ac1d130fd4 511 --n;
mbed_official 0:51ac1d130fd4 512 };
mbed_official 0:51ac1d130fd4 513 ++query;
mbed_official 0:51ac1d130fd4 514 }
mbed_official 0:51ac1d130fd4 515 } while (*response != 0);
mbed_official 0:51ac1d130fd4 516
mbed_official 0:51ac1d130fd4 517 return 0;
mbed_official 0:51ac1d130fd4 518 }
mbed_official 0:51ac1d130fd4 519 #endif /* DNS_DOES_NAME_CHECK */
mbed_official 0:51ac1d130fd4 520
mbed_official 0:51ac1d130fd4 521 /**
mbed_official 0:51ac1d130fd4 522 * Walk through a compact encoded DNS name and return the end of the name.
mbed_official 0:51ac1d130fd4 523 *
mbed_official 0:51ac1d130fd4 524 * @param query encoded DNS name in the DNS server response
mbed_official 0:51ac1d130fd4 525 * @return end of the name
mbed_official 0:51ac1d130fd4 526 */
mbed_official 0:51ac1d130fd4 527 static unsigned char *
mbed_official 0:51ac1d130fd4 528 dns_parse_name(unsigned char *query)
mbed_official 0:51ac1d130fd4 529 {
mbed_official 0:51ac1d130fd4 530 unsigned char n;
mbed_official 0:51ac1d130fd4 531
mbed_official 0:51ac1d130fd4 532 do {
mbed_official 0:51ac1d130fd4 533 n = *query++;
mbed_official 0:51ac1d130fd4 534 /** @see RFC 1035 - 4.1.4. Message compression */
mbed_official 0:51ac1d130fd4 535 if ((n & 0xc0) == 0xc0) {
mbed_official 0:51ac1d130fd4 536 /* Compressed name */
mbed_official 0:51ac1d130fd4 537 break;
mbed_official 0:51ac1d130fd4 538 } else {
mbed_official 0:51ac1d130fd4 539 /* Not compressed name */
mbed_official 0:51ac1d130fd4 540 while (n > 0) {
mbed_official 0:51ac1d130fd4 541 ++query;
mbed_official 0:51ac1d130fd4 542 --n;
mbed_official 0:51ac1d130fd4 543 };
mbed_official 0:51ac1d130fd4 544 }
mbed_official 0:51ac1d130fd4 545 } while (*query != 0);
mbed_official 0:51ac1d130fd4 546
mbed_official 0:51ac1d130fd4 547 return query + 1;
mbed_official 0:51ac1d130fd4 548 }
mbed_official 0:51ac1d130fd4 549
mbed_official 0:51ac1d130fd4 550 /**
mbed_official 0:51ac1d130fd4 551 * Send a DNS query packet.
mbed_official 0:51ac1d130fd4 552 *
mbed_official 0:51ac1d130fd4 553 * @param numdns index of the DNS server in the dns_servers table
mbed_official 0:51ac1d130fd4 554 * @param name hostname to query
mbed_official 0:51ac1d130fd4 555 * @param id index of the hostname in dns_table, used as transaction ID in the
mbed_official 0:51ac1d130fd4 556 * DNS query packet
mbed_official 0:51ac1d130fd4 557 * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise
mbed_official 0:51ac1d130fd4 558 */
mbed_official 0:51ac1d130fd4 559 static err_t
mbed_official 0:51ac1d130fd4 560 dns_send(u8_t numdns, const char* name, u8_t id)
mbed_official 0:51ac1d130fd4 561 {
mbed_official 0:51ac1d130fd4 562 err_t err;
mbed_official 0:51ac1d130fd4 563 struct dns_hdr *hdr;
mbed_official 0:51ac1d130fd4 564 struct dns_query qry;
mbed_official 0:51ac1d130fd4 565 struct pbuf *p;
mbed_official 0:51ac1d130fd4 566 char *query, *nptr;
mbed_official 0:51ac1d130fd4 567 const char *pHostname;
mbed_official 0:51ac1d130fd4 568 u8_t n;
mbed_official 0:51ac1d130fd4 569
mbed_official 0:51ac1d130fd4 570 LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
mbed_official 0:51ac1d130fd4 571 (u16_t)(numdns), name));
mbed_official 0:51ac1d130fd4 572 LWIP_ASSERT("dns server out of array", numdns < DNS_MAX_SERVERS);
mbed_official 0:51ac1d130fd4 573 LWIP_ASSERT("dns server has no IP address set", !ip_addr_isany(&dns_servers[numdns]));
mbed_official 0:51ac1d130fd4 574
mbed_official 0:51ac1d130fd4 575 /* if here, we have either a new query or a retry on a previous query to process */
mbed_official 0:51ac1d130fd4 576 p = pbuf_alloc(PBUF_TRANSPORT, SIZEOF_DNS_HDR + DNS_MAX_NAME_LENGTH +
mbed_official 0:51ac1d130fd4 577 SIZEOF_DNS_QUERY, PBUF_RAM);
mbed_official 0:51ac1d130fd4 578 if (p != NULL) {
mbed_official 0:51ac1d130fd4 579 LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
mbed_official 0:51ac1d130fd4 580 /* fill dns header */
mbed_official 0:51ac1d130fd4 581 hdr = (struct dns_hdr*)p->payload;
mbed_official 0:51ac1d130fd4 582 memset(hdr, 0, SIZEOF_DNS_HDR);
mbed_official 0:51ac1d130fd4 583 hdr->id = htons(id);
mbed_official 0:51ac1d130fd4 584 hdr->flags1 = DNS_FLAG1_RD;
mbed_official 0:51ac1d130fd4 585 hdr->numquestions = PP_HTONS(1);
mbed_official 0:51ac1d130fd4 586 query = (char*)hdr + SIZEOF_DNS_HDR;
mbed_official 0:51ac1d130fd4 587 pHostname = name;
mbed_official 0:51ac1d130fd4 588 --pHostname;
mbed_official 0:51ac1d130fd4 589
mbed_official 0:51ac1d130fd4 590 /* convert hostname into suitable query format. */
mbed_official 0:51ac1d130fd4 591 do {
mbed_official 0:51ac1d130fd4 592 ++pHostname;
mbed_official 0:51ac1d130fd4 593 nptr = query;
mbed_official 0:51ac1d130fd4 594 ++query;
mbed_official 0:51ac1d130fd4 595 for(n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
mbed_official 0:51ac1d130fd4 596 *query = *pHostname;
mbed_official 0:51ac1d130fd4 597 ++query;
mbed_official 0:51ac1d130fd4 598 ++n;
mbed_official 0:51ac1d130fd4 599 }
mbed_official 0:51ac1d130fd4 600 *nptr = n;
mbed_official 0:51ac1d130fd4 601 } while(*pHostname != 0);
mbed_official 0:51ac1d130fd4 602 *query++='\0';
mbed_official 0:51ac1d130fd4 603
mbed_official 0:51ac1d130fd4 604 /* fill dns query */
mbed_official 0:51ac1d130fd4 605 qry.type = PP_HTONS(DNS_RRTYPE_A);
mbed_official 0:51ac1d130fd4 606 qry.cls = PP_HTONS(DNS_RRCLASS_IN);
mbed_official 0:51ac1d130fd4 607 SMEMCPY(query, &qry, SIZEOF_DNS_QUERY);
mbed_official 0:51ac1d130fd4 608
mbed_official 0:51ac1d130fd4 609 /* resize pbuf to the exact dns query */
mbed_official 0:51ac1d130fd4 610 pbuf_realloc(p, (u16_t)((query + SIZEOF_DNS_QUERY) - ((char*)(p->payload))));
mbed_official 0:51ac1d130fd4 611
mbed_official 0:51ac1d130fd4 612 /* connect to the server for faster receiving */
mbed_official 0:51ac1d130fd4 613 udp_connect(dns_pcb, &dns_servers[numdns], DNS_SERVER_PORT);
mbed_official 0:51ac1d130fd4 614 /* send dns packet */
mbed_official 0:51ac1d130fd4 615 err = udp_sendto(dns_pcb, p, &dns_servers[numdns], DNS_SERVER_PORT);
mbed_official 0:51ac1d130fd4 616
mbed_official 0:51ac1d130fd4 617 /* free pbuf */
mbed_official 0:51ac1d130fd4 618 pbuf_free(p);
mbed_official 0:51ac1d130fd4 619 } else {
mbed_official 0:51ac1d130fd4 620 err = ERR_MEM;
mbed_official 0:51ac1d130fd4 621 }
mbed_official 0:51ac1d130fd4 622
mbed_official 0:51ac1d130fd4 623 return err;
mbed_official 0:51ac1d130fd4 624 }
mbed_official 0:51ac1d130fd4 625
mbed_official 0:51ac1d130fd4 626 /**
mbed_official 0:51ac1d130fd4 627 * dns_check_entry() - see if pEntry has not yet been queried and, if so, sends out a query.
mbed_official 0:51ac1d130fd4 628 * Check an entry in the dns_table:
mbed_official 0:51ac1d130fd4 629 * - send out query for new entries
mbed_official 0:51ac1d130fd4 630 * - retry old pending entries on timeout (also with different servers)
mbed_official 0:51ac1d130fd4 631 * - remove completed entries from the table if their TTL has expired
mbed_official 0:51ac1d130fd4 632 *
mbed_official 0:51ac1d130fd4 633 * @param i index of the dns_table entry to check
mbed_official 0:51ac1d130fd4 634 */
mbed_official 0:51ac1d130fd4 635 static void
mbed_official 0:51ac1d130fd4 636 dns_check_entry(u8_t i)
mbed_official 0:51ac1d130fd4 637 {
mbed_official 0:51ac1d130fd4 638 err_t err;
mbed_official 0:51ac1d130fd4 639 struct dns_table_entry *pEntry = &dns_table[i];
mbed_official 0:51ac1d130fd4 640
mbed_official 0:51ac1d130fd4 641 LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE);
mbed_official 0:51ac1d130fd4 642
mbed_official 0:51ac1d130fd4 643 switch(pEntry->state) {
mbed_official 0:51ac1d130fd4 644
mbed_official 0:51ac1d130fd4 645 case DNS_STATE_NEW: {
mbed_official 0:51ac1d130fd4 646 /* initialize new entry */
mbed_official 0:51ac1d130fd4 647 pEntry->state = DNS_STATE_ASKING;
mbed_official 0:51ac1d130fd4 648 pEntry->numdns = 0;
mbed_official 0:51ac1d130fd4 649 pEntry->tmr = 1;
mbed_official 0:51ac1d130fd4 650 pEntry->retries = 0;
mbed_official 0:51ac1d130fd4 651
mbed_official 0:51ac1d130fd4 652 /* send DNS packet for this entry */
mbed_official 0:51ac1d130fd4 653 err = dns_send(pEntry->numdns, pEntry->name, i);
mbed_official 0:51ac1d130fd4 654 if (err != ERR_OK) {
mbed_official 0:51ac1d130fd4 655 LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
mbed_official 0:51ac1d130fd4 656 ("dns_send returned error: %s\n", lwip_strerr(err)));
mbed_official 0:51ac1d130fd4 657 }
mbed_official 0:51ac1d130fd4 658 break;
mbed_official 0:51ac1d130fd4 659 }
mbed_official 0:51ac1d130fd4 660
mbed_official 0:51ac1d130fd4 661 case DNS_STATE_ASKING: {
mbed_official 0:51ac1d130fd4 662 if (--pEntry->tmr == 0) {
mbed_official 0:51ac1d130fd4 663 if (++pEntry->retries == DNS_MAX_RETRIES) {
mbed_official 0:51ac1d130fd4 664 if ((pEntry->numdns+1<DNS_MAX_SERVERS) && !ip_addr_isany(&dns_servers[pEntry->numdns+1])) {
mbed_official 0:51ac1d130fd4 665 /* change of server */
mbed_official 0:51ac1d130fd4 666 pEntry->numdns++;
mbed_official 0:51ac1d130fd4 667 pEntry->tmr = 1;
mbed_official 0:51ac1d130fd4 668 pEntry->retries = 0;
mbed_official 0:51ac1d130fd4 669 break;
mbed_official 0:51ac1d130fd4 670 } else {
mbed_official 0:51ac1d130fd4 671 LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", pEntry->name));
mbed_official 0:51ac1d130fd4 672 /* call specified callback function if provided */
mbed_official 0:51ac1d130fd4 673 if (pEntry->found)
mbed_official 0:51ac1d130fd4 674 (*pEntry->found)(pEntry->name, NULL, pEntry->arg);
mbed_official 0:51ac1d130fd4 675 /* flush this entry */
mbed_official 0:51ac1d130fd4 676 pEntry->state = DNS_STATE_UNUSED;
mbed_official 0:51ac1d130fd4 677 pEntry->found = NULL;
mbed_official 0:51ac1d130fd4 678 break;
mbed_official 0:51ac1d130fd4 679 }
mbed_official 0:51ac1d130fd4 680 }
mbed_official 0:51ac1d130fd4 681
mbed_official 0:51ac1d130fd4 682 /* wait longer for the next retry */
mbed_official 0:51ac1d130fd4 683 pEntry->tmr = pEntry->retries;
mbed_official 0:51ac1d130fd4 684
mbed_official 0:51ac1d130fd4 685 /* send DNS packet for this entry */
mbed_official 0:51ac1d130fd4 686 err = dns_send(pEntry->numdns, pEntry->name, i);
mbed_official 0:51ac1d130fd4 687 if (err != ERR_OK) {
mbed_official 0:51ac1d130fd4 688 LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
mbed_official 0:51ac1d130fd4 689 ("dns_send returned error: %s\n", lwip_strerr(err)));
mbed_official 0:51ac1d130fd4 690 }
mbed_official 0:51ac1d130fd4 691 }
mbed_official 0:51ac1d130fd4 692 break;
mbed_official 0:51ac1d130fd4 693 }
mbed_official 0:51ac1d130fd4 694
mbed_official 0:51ac1d130fd4 695 case DNS_STATE_DONE: {
mbed_official 0:51ac1d130fd4 696 /* if the time to live is nul */
mbed_official 0:51ac1d130fd4 697 if (--pEntry->ttl == 0) {
mbed_official 0:51ac1d130fd4 698 LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", pEntry->name));
mbed_official 0:51ac1d130fd4 699 /* flush this entry */
mbed_official 0:51ac1d130fd4 700 pEntry->state = DNS_STATE_UNUSED;
mbed_official 0:51ac1d130fd4 701 pEntry->found = NULL;
mbed_official 0:51ac1d130fd4 702 }
mbed_official 0:51ac1d130fd4 703 break;
mbed_official 0:51ac1d130fd4 704 }
mbed_official 0:51ac1d130fd4 705 case DNS_STATE_UNUSED:
mbed_official 0:51ac1d130fd4 706 /* nothing to do */
mbed_official 0:51ac1d130fd4 707 break;
mbed_official 0:51ac1d130fd4 708 default:
mbed_official 0:51ac1d130fd4 709 LWIP_ASSERT("unknown dns_table entry state:", 0);
mbed_official 0:51ac1d130fd4 710 break;
mbed_official 0:51ac1d130fd4 711 }
mbed_official 0:51ac1d130fd4 712 }
mbed_official 0:51ac1d130fd4 713
mbed_official 0:51ac1d130fd4 714 /**
mbed_official 0:51ac1d130fd4 715 * Call dns_check_entry for each entry in dns_table - check all entries.
mbed_official 0:51ac1d130fd4 716 */
mbed_official 0:51ac1d130fd4 717 static void
mbed_official 0:51ac1d130fd4 718 dns_check_entries(void)
mbed_official 0:51ac1d130fd4 719 {
mbed_official 0:51ac1d130fd4 720 u8_t i;
mbed_official 0:51ac1d130fd4 721
mbed_official 0:51ac1d130fd4 722 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
mbed_official 0:51ac1d130fd4 723 dns_check_entry(i);
mbed_official 0:51ac1d130fd4 724 }
mbed_official 0:51ac1d130fd4 725 }
mbed_official 0:51ac1d130fd4 726
mbed_official 0:51ac1d130fd4 727 /**
mbed_official 0:51ac1d130fd4 728 * Receive input function for DNS response packets arriving for the dns UDP pcb.
mbed_official 0:51ac1d130fd4 729 *
mbed_official 0:51ac1d130fd4 730 * @params see udp.h
mbed_official 0:51ac1d130fd4 731 */
mbed_official 0:51ac1d130fd4 732 static void
mbed_official 0:51ac1d130fd4 733 dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
mbed_official 0:51ac1d130fd4 734 {
mbed_official 0:51ac1d130fd4 735 u16_t i;
mbed_official 0:51ac1d130fd4 736 char *pHostname;
mbed_official 0:51ac1d130fd4 737 struct dns_hdr *hdr;
mbed_official 0:51ac1d130fd4 738 struct dns_answer ans;
mbed_official 0:51ac1d130fd4 739 struct dns_table_entry *pEntry;
mbed_official 0:51ac1d130fd4 740 u16_t nquestions, nanswers;
mbed_official 0:51ac1d130fd4 741
mbed_official 0:51ac1d130fd4 742 LWIP_UNUSED_ARG(arg);
mbed_official 0:51ac1d130fd4 743 LWIP_UNUSED_ARG(pcb);
mbed_official 0:51ac1d130fd4 744 LWIP_UNUSED_ARG(addr);
mbed_official 0:51ac1d130fd4 745 LWIP_UNUSED_ARG(port);
mbed_official 0:51ac1d130fd4 746
mbed_official 0:51ac1d130fd4 747 /* is the dns message too big ? */
mbed_official 0:51ac1d130fd4 748 if (p->tot_len > DNS_MSG_SIZE) {
mbed_official 0:51ac1d130fd4 749 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n"));
mbed_official 0:51ac1d130fd4 750 /* free pbuf and return */
mbed_official 0:51ac1d130fd4 751 goto memerr;
mbed_official 0:51ac1d130fd4 752 }
mbed_official 0:51ac1d130fd4 753
mbed_official 0:51ac1d130fd4 754 /* is the dns message big enough ? */
mbed_official 0:51ac1d130fd4 755 if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) {
mbed_official 0:51ac1d130fd4 756 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
mbed_official 0:51ac1d130fd4 757 /* free pbuf and return */
mbed_official 0:51ac1d130fd4 758 goto memerr;
mbed_official 0:51ac1d130fd4 759 }
mbed_official 0:51ac1d130fd4 760
mbed_official 0:51ac1d130fd4 761 /* copy dns payload inside static buffer for processing */
mbed_official 0:51ac1d130fd4 762 if (pbuf_copy_partial(p, dns_payload, p->tot_len, 0) == p->tot_len) {
mbed_official 0:51ac1d130fd4 763 /* The ID in the DNS header should be our entry into the name table. */
mbed_official 0:51ac1d130fd4 764 hdr = (struct dns_hdr*)dns_payload;
mbed_official 0:51ac1d130fd4 765 i = htons(hdr->id);
mbed_official 0:51ac1d130fd4 766 if (i < DNS_TABLE_SIZE) {
mbed_official 0:51ac1d130fd4 767 pEntry = &dns_table[i];
mbed_official 0:51ac1d130fd4 768 if(pEntry->state == DNS_STATE_ASKING) {
mbed_official 0:51ac1d130fd4 769 /* This entry is now completed. */
mbed_official 0:51ac1d130fd4 770 pEntry->state = DNS_STATE_DONE;
mbed_official 0:51ac1d130fd4 771 pEntry->err = hdr->flags2 & DNS_FLAG2_ERR_MASK;
mbed_official 0:51ac1d130fd4 772
mbed_official 0:51ac1d130fd4 773 /* We only care about the question(s) and the answers. The authrr
mbed_official 0:51ac1d130fd4 774 and the extrarr are simply discarded. */
mbed_official 0:51ac1d130fd4 775 nquestions = htons(hdr->numquestions);
mbed_official 0:51ac1d130fd4 776 nanswers = htons(hdr->numanswers);
mbed_official 0:51ac1d130fd4 777
mbed_official 0:51ac1d130fd4 778 /* Check for error. If so, call callback to inform. */
mbed_official 0:51ac1d130fd4 779 if (((hdr->flags1 & DNS_FLAG1_RESPONSE) == 0) || (pEntry->err != 0) || (nquestions != 1)) {
mbed_official 0:51ac1d130fd4 780 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", pEntry->name));
mbed_official 0:51ac1d130fd4 781 /* call callback to indicate error, clean up memory and return */
mbed_official 0:51ac1d130fd4 782 goto responseerr;
mbed_official 0:51ac1d130fd4 783 }
mbed_official 0:51ac1d130fd4 784
mbed_official 0:51ac1d130fd4 785 #if DNS_DOES_NAME_CHECK
mbed_official 0:51ac1d130fd4 786 /* Check if the name in the "question" part match with the name in the entry. */
mbed_official 0:51ac1d130fd4 787 if (dns_compare_name((unsigned char *)(pEntry->name), (unsigned char *)dns_payload + SIZEOF_DNS_HDR) != 0) {
mbed_official 0:51ac1d130fd4 788 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", pEntry->name));
mbed_official 0:51ac1d130fd4 789 /* call callback to indicate error, clean up memory and return */
mbed_official 0:51ac1d130fd4 790 goto responseerr;
mbed_official 0:51ac1d130fd4 791 }
mbed_official 0:51ac1d130fd4 792 #endif /* DNS_DOES_NAME_CHECK */
mbed_official 0:51ac1d130fd4 793
mbed_official 0:51ac1d130fd4 794 /* Skip the name in the "question" part */
mbed_official 0:51ac1d130fd4 795 pHostname = (char *) dns_parse_name((unsigned char *)dns_payload + SIZEOF_DNS_HDR) + SIZEOF_DNS_QUERY;
mbed_official 0:51ac1d130fd4 796
mbed_official 0:51ac1d130fd4 797 while (nanswers > 0) {
mbed_official 0:51ac1d130fd4 798 /* skip answer resource record's host name */
mbed_official 0:51ac1d130fd4 799 pHostname = (char *) dns_parse_name((unsigned char *)pHostname);
mbed_official 0:51ac1d130fd4 800
mbed_official 0:51ac1d130fd4 801 /* Check for IP address type and Internet class. Others are discarded. */
mbed_official 0:51ac1d130fd4 802 SMEMCPY(&ans, pHostname, SIZEOF_DNS_ANSWER);
mbed_official 0:51ac1d130fd4 803 if((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) &&
mbed_official 0:51ac1d130fd4 804 (ans.len == PP_HTONS(sizeof(ip_addr_t))) ) {
mbed_official 0:51ac1d130fd4 805 /* read the answer resource record's TTL, and maximize it if needed */
mbed_official 0:51ac1d130fd4 806 pEntry->ttl = ntohl(ans.ttl);
mbed_official 0:51ac1d130fd4 807 if (pEntry->ttl > DNS_MAX_TTL) {
mbed_official 0:51ac1d130fd4 808 pEntry->ttl = DNS_MAX_TTL;
mbed_official 0:51ac1d130fd4 809 }
mbed_official 0:51ac1d130fd4 810 /* read the IP address after answer resource record's header */
mbed_official 0:51ac1d130fd4 811 SMEMCPY(&(pEntry->ipaddr), (pHostname+SIZEOF_DNS_ANSWER), sizeof(ip_addr_t));
mbed_official 0:51ac1d130fd4 812 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", pEntry->name));
mbed_official 0:51ac1d130fd4 813 ip_addr_debug_print(DNS_DEBUG, (&(pEntry->ipaddr)));
mbed_official 0:51ac1d130fd4 814 LWIP_DEBUGF(DNS_DEBUG, ("\n"));
mbed_official 0:51ac1d130fd4 815 /* call specified callback function if provided */
mbed_official 0:51ac1d130fd4 816 if (pEntry->found) {
mbed_official 0:51ac1d130fd4 817 (*pEntry->found)(pEntry->name, &pEntry->ipaddr, pEntry->arg);
mbed_official 0:51ac1d130fd4 818 }
mbed_official 0:51ac1d130fd4 819 /* deallocate memory and return */
mbed_official 0:51ac1d130fd4 820 goto memerr;
mbed_official 0:51ac1d130fd4 821 } else {
mbed_official 0:51ac1d130fd4 822 pHostname = pHostname + SIZEOF_DNS_ANSWER + htons(ans.len);
mbed_official 0:51ac1d130fd4 823 }
mbed_official 0:51ac1d130fd4 824 --nanswers;
mbed_official 0:51ac1d130fd4 825 }
mbed_official 0:51ac1d130fd4 826 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", pEntry->name));
mbed_official 0:51ac1d130fd4 827 /* call callback to indicate error, clean up memory and return */
mbed_official 0:51ac1d130fd4 828 goto responseerr;
mbed_official 0:51ac1d130fd4 829 }
mbed_official 0:51ac1d130fd4 830 }
mbed_official 0:51ac1d130fd4 831 }
mbed_official 0:51ac1d130fd4 832
mbed_official 0:51ac1d130fd4 833 /* deallocate memory and return */
mbed_official 0:51ac1d130fd4 834 goto memerr;
mbed_official 0:51ac1d130fd4 835
mbed_official 0:51ac1d130fd4 836 responseerr:
mbed_official 0:51ac1d130fd4 837 /* ERROR: call specified callback function with NULL as name to indicate an error */
mbed_official 0:51ac1d130fd4 838 if (pEntry->found) {
mbed_official 0:51ac1d130fd4 839 (*pEntry->found)(pEntry->name, NULL, pEntry->arg);
mbed_official 0:51ac1d130fd4 840 }
mbed_official 0:51ac1d130fd4 841 /* flush this entry */
mbed_official 0:51ac1d130fd4 842 pEntry->state = DNS_STATE_UNUSED;
mbed_official 0:51ac1d130fd4 843 pEntry->found = NULL;
mbed_official 0:51ac1d130fd4 844
mbed_official 0:51ac1d130fd4 845 memerr:
mbed_official 0:51ac1d130fd4 846 /* free pbuf */
mbed_official 0:51ac1d130fd4 847 pbuf_free(p);
mbed_official 0:51ac1d130fd4 848 return;
mbed_official 0:51ac1d130fd4 849 }
mbed_official 0:51ac1d130fd4 850
mbed_official 0:51ac1d130fd4 851 /**
mbed_official 0:51ac1d130fd4 852 * Queues a new hostname to resolve and sends out a DNS query for that hostname
mbed_official 0:51ac1d130fd4 853 *
mbed_official 0:51ac1d130fd4 854 * @param name the hostname that is to be queried
mbed_official 0:51ac1d130fd4 855 * @param found a callback founction to be called on success, failure or timeout
mbed_official 0:51ac1d130fd4 856 * @param callback_arg argument to pass to the callback function
mbed_official 0:51ac1d130fd4 857 * @return @return a err_t return code.
mbed_official 0:51ac1d130fd4 858 */
mbed_official 0:51ac1d130fd4 859 static err_t
mbed_official 0:51ac1d130fd4 860 dns_enqueue(const char *name, dns_found_callback found, void *callback_arg)
mbed_official 0:51ac1d130fd4 861 {
mbed_official 0:51ac1d130fd4 862 u8_t i;
mbed_official 0:51ac1d130fd4 863 u8_t lseq, lseqi;
mbed_official 0:51ac1d130fd4 864 struct dns_table_entry *pEntry = NULL;
mbed_official 0:51ac1d130fd4 865 size_t namelen;
mbed_official 0:51ac1d130fd4 866
mbed_official 0:51ac1d130fd4 867 /* search an unused entry, or the oldest one */
mbed_official 0:51ac1d130fd4 868 lseq = lseqi = 0;
mbed_official 0:51ac1d130fd4 869 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
mbed_official 0:51ac1d130fd4 870 pEntry = &dns_table[i];
mbed_official 0:51ac1d130fd4 871 /* is it an unused entry ? */
mbed_official 0:51ac1d130fd4 872 if (pEntry->state == DNS_STATE_UNUSED)
mbed_official 0:51ac1d130fd4 873 break;
mbed_official 0:51ac1d130fd4 874
mbed_official 0:51ac1d130fd4 875 /* check if this is the oldest completed entry */
mbed_official 0:51ac1d130fd4 876 if (pEntry->state == DNS_STATE_DONE) {
mbed_official 0:51ac1d130fd4 877 if ((dns_seqno - pEntry->seqno) > lseq) {
mbed_official 0:51ac1d130fd4 878 lseq = dns_seqno - pEntry->seqno;
mbed_official 0:51ac1d130fd4 879 lseqi = i;
mbed_official 0:51ac1d130fd4 880 }
mbed_official 0:51ac1d130fd4 881 }
mbed_official 0:51ac1d130fd4 882 }
mbed_official 0:51ac1d130fd4 883
mbed_official 0:51ac1d130fd4 884 /* if we don't have found an unused entry, use the oldest completed one */
mbed_official 0:51ac1d130fd4 885 if (i == DNS_TABLE_SIZE) {
mbed_official 0:51ac1d130fd4 886 if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) {
mbed_official 0:51ac1d130fd4 887 /* no entry can't be used now, table is full */
mbed_official 0:51ac1d130fd4 888 LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name));
mbed_official 0:51ac1d130fd4 889 return ERR_MEM;
mbed_official 0:51ac1d130fd4 890 } else {
mbed_official 0:51ac1d130fd4 891 /* use the oldest completed one */
mbed_official 0:51ac1d130fd4 892 i = lseqi;
mbed_official 0:51ac1d130fd4 893 pEntry = &dns_table[i];
mbed_official 0:51ac1d130fd4 894 }
mbed_official 0:51ac1d130fd4 895 }
mbed_official 0:51ac1d130fd4 896
mbed_official 0:51ac1d130fd4 897 /* use this entry */
mbed_official 0:51ac1d130fd4 898 LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i)));
mbed_official 0:51ac1d130fd4 899
mbed_official 0:51ac1d130fd4 900 /* fill the entry */
mbed_official 0:51ac1d130fd4 901 pEntry->state = DNS_STATE_NEW;
mbed_official 0:51ac1d130fd4 902 pEntry->seqno = dns_seqno++;
mbed_official 0:51ac1d130fd4 903 pEntry->found = found;
mbed_official 0:51ac1d130fd4 904 pEntry->arg = callback_arg;
mbed_official 0:51ac1d130fd4 905 namelen = LWIP_MIN(strlen(name), DNS_MAX_NAME_LENGTH-1);
mbed_official 0:51ac1d130fd4 906 MEMCPY(pEntry->name, name, namelen);
mbed_official 0:51ac1d130fd4 907 pEntry->name[namelen] = 0;
mbed_official 0:51ac1d130fd4 908
mbed_official 0:51ac1d130fd4 909 /* force to send query without waiting timer */
mbed_official 0:51ac1d130fd4 910 dns_check_entry(i);
mbed_official 0:51ac1d130fd4 911
mbed_official 0:51ac1d130fd4 912 /* dns query is enqueued */
mbed_official 0:51ac1d130fd4 913 return ERR_INPROGRESS;
mbed_official 0:51ac1d130fd4 914 }
mbed_official 0:51ac1d130fd4 915
mbed_official 0:51ac1d130fd4 916 /**
mbed_official 0:51ac1d130fd4 917 * Resolve a hostname (string) into an IP address.
mbed_official 0:51ac1d130fd4 918 * NON-BLOCKING callback version for use with raw API!!!
mbed_official 0:51ac1d130fd4 919 *
mbed_official 0:51ac1d130fd4 920 * Returns immediately with one of err_t return codes:
mbed_official 0:51ac1d130fd4 921 * - ERR_OK if hostname is a valid IP address string or the host
mbed_official 0:51ac1d130fd4 922 * name is already in the local names table.
mbed_official 0:51ac1d130fd4 923 * - ERR_INPROGRESS enqueue a request to be sent to the DNS server
mbed_official 0:51ac1d130fd4 924 * for resolution if no errors are present.
mbed_official 0:51ac1d130fd4 925 * - ERR_ARG: dns client not initialized or invalid hostname
mbed_official 0:51ac1d130fd4 926 *
mbed_official 0:51ac1d130fd4 927 * @param hostname the hostname that is to be queried
mbed_official 0:51ac1d130fd4 928 * @param addr pointer to a ip_addr_t where to store the address if it is already
mbed_official 0:51ac1d130fd4 929 * cached in the dns_table (only valid if ERR_OK is returned!)
mbed_official 0:51ac1d130fd4 930 * @param found a callback function to be called on success, failure or timeout (only if
mbed_official 0:51ac1d130fd4 931 * ERR_INPROGRESS is returned!)
mbed_official 0:51ac1d130fd4 932 * @param callback_arg argument to pass to the callback function
mbed_official 0:51ac1d130fd4 933 * @return a err_t return code.
mbed_official 0:51ac1d130fd4 934 */
mbed_official 0:51ac1d130fd4 935 err_t
mbed_official 0:51ac1d130fd4 936 dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found,
mbed_official 0:51ac1d130fd4 937 void *callback_arg)
mbed_official 0:51ac1d130fd4 938 {
mbed_official 0:51ac1d130fd4 939 u32_t ipaddr;
mbed_official 0:51ac1d130fd4 940 /* not initialized or no valid server yet, or invalid addr pointer
mbed_official 0:51ac1d130fd4 941 * or invalid hostname or invalid hostname length */
mbed_official 0:51ac1d130fd4 942 if ((dns_pcb == NULL) || (addr == NULL) ||
mbed_official 0:51ac1d130fd4 943 (!hostname) || (!hostname[0]) ||
mbed_official 0:51ac1d130fd4 944 (strlen(hostname) >= DNS_MAX_NAME_LENGTH)) {
mbed_official 0:51ac1d130fd4 945 return ERR_ARG;
mbed_official 0:51ac1d130fd4 946 }
mbed_official 0:51ac1d130fd4 947
mbed_official 0:51ac1d130fd4 948 #if LWIP_HAVE_LOOPIF
mbed_official 0:51ac1d130fd4 949 if (strcmp(hostname, "localhost")==0) {
mbed_official 0:51ac1d130fd4 950 ip_addr_set_loopback(addr);
mbed_official 0:51ac1d130fd4 951 return ERR_OK;
mbed_official 0:51ac1d130fd4 952 }
mbed_official 0:51ac1d130fd4 953 #endif /* LWIP_HAVE_LOOPIF */
mbed_official 0:51ac1d130fd4 954
mbed_official 0:51ac1d130fd4 955 /* host name already in octet notation? set ip addr and return ERR_OK */
mbed_official 0:51ac1d130fd4 956 ipaddr = ipaddr_addr(hostname);
mbed_official 0:51ac1d130fd4 957 if (ipaddr == IPADDR_NONE) {
mbed_official 0:51ac1d130fd4 958 /* already have this address cached? */
mbed_official 0:51ac1d130fd4 959 ipaddr = dns_lookup(hostname);
mbed_official 0:51ac1d130fd4 960 }
mbed_official 0:51ac1d130fd4 961 if (ipaddr != IPADDR_NONE) {
mbed_official 0:51ac1d130fd4 962 ip4_addr_set_u32(addr, ipaddr);
mbed_official 0:51ac1d130fd4 963 return ERR_OK;
mbed_official 0:51ac1d130fd4 964 }
mbed_official 0:51ac1d130fd4 965
mbed_official 0:51ac1d130fd4 966 /* queue query with specified callback */
mbed_official 0:51ac1d130fd4 967 return dns_enqueue(hostname, found, callback_arg);
mbed_official 0:51ac1d130fd4 968 }
mbed_official 0:51ac1d130fd4 969
mbed_official 0:51ac1d130fd4 970 #endif /* LWIP_DNS */