ソースの整理中ですが、利用はできます。 大きなファイルはできないかもしれません。

Dependencies:   EthernetInterface HttpServer TextLCD expatlib mbed-rpc mbed-rtos mbed Socket lwip-eth lwip-sys lwip

Fork of giken9_HTMLServer_Sample by Yasushi TAUCHI

Committer:
yueee_yt
Date:
Wed Mar 12 04:19:54 2014 +0000
Revision:
0:7766f6712673
???????????????

Who changed what in which revision?

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