DNS fixes from Darcy Gong (part 1 of 2)

git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5235 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2012-10-20 13:47:30 +00:00
parent 860e5f0524
commit 78ba846c06
7 changed files with 172 additions and 105 deletions

View File

@ -370,3 +370,5 @@
when I was trying to add correct handling for loss of connection (Darcy Gong)
* apps/nshlib/nsh_telnetd.c: Add support for login to Telnet session via
username and password (Darcy Gong).
* apps/netutils/resolv/resolv.c (and files using the DNS resolver): Various
DNS address resolution improvements from Darcy Gong.

View File

@ -74,6 +74,11 @@ EXTERN void resolv_getserver(FAR struct in_addr *dnsserver);
EXTERN int resolv_query(FAR const char *name, FAR struct sockaddr_in *addr);
#endif
EXTERN int dns_gethostip(const char *hostname, in_addr_t *ipaddr);
#define dns_setserver resolv_conf
#define dns_getserver resolv_getserver
#define dns_whois resolv_query
#undef EXTERN
#if defined(__cplusplus)
}

View File

@ -352,9 +352,9 @@ void *dhcpc_open(const void *macaddr, int maclen)
struct sockaddr_in addr;
struct timeval tv;
dbg("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
((uint8_t*)macaddr)[0], ((uint8_t*)macaddr)[1], ((uint8_t*)macaddr)[2],
((uint8_t*)macaddr)[3], ((uint8_t*)macaddr)[4], ((uint8_t*)macaddr)[5]);
ndbg("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
((uint8_t*)macaddr)[0], ((uint8_t*)macaddr)[1], ((uint8_t*)macaddr)[2],
((uint8_t*)macaddr)[3], ((uint8_t*)macaddr)[4], ((uint8_t*)macaddr)[5]);
/* Allocate an internal DHCP structure */
@ -456,7 +456,7 @@ int dhcpc_request(void *handle, struct dhcpc_state *presult)
{
/* Send the DISCOVER command */
dbg("Broadcast DISCOVER\n");
ndbg("Broadcast DISCOVER\n");
if (dhcpc_sendmsg(pdhcpc, presult, DHCPDISCOVER) < 0)
{
return ERROR;
@ -474,7 +474,7 @@ int dhcpc_request(void *handle, struct dhcpc_state *presult)
* by a new OFFER.
*/
dbg("Received OFFER from %08x\n", ntohl(presult->serverid.s_addr));
ndbg("Received OFFER from %08x\n", ntohl(presult->serverid.s_addr));
pdhcpc->ipaddr.s_addr = presult->ipaddr.s_addr;
pdhcpc->serverid.s_addr = presult->serverid.s_addr;
@ -509,7 +509,7 @@ int dhcpc_request(void *handle, struct dhcpc_state *presult)
{
/* Send the REQUEST message to obtain the lease that was offered to us. */
dbg("Send REQUEST\n");
ndbg("Send REQUEST\n");
if (dhcpc_sendmsg(pdhcpc, presult, DHCPREQUEST) < 0)
{
return ERROR;
@ -531,7 +531,7 @@ int dhcpc_request(void *handle, struct dhcpc_state *presult)
if (msgtype == DHCPACK)
{
dbg("Received ACK\n");
ndbg("Received ACK\n");
state = STATE_HAVE_LEASE;
}
@ -541,7 +541,7 @@ int dhcpc_request(void *handle, struct dhcpc_state *presult)
else if (msgtype == DHCPNAK)
{
dbg("Received NAK\n");
ndbg("Received NAK\n");
break;
}
@ -552,7 +552,7 @@ int dhcpc_request(void *handle, struct dhcpc_state *presult)
else if (msgtype == DHCPOFFER)
{
dbg("Received another OFFER, send DECLINE\n");
ndbg("Received another OFFER, send DECLINE\n");
(void)dhcpc_sendmsg(pdhcpc, presult, DHCPDECLINE);
}
@ -560,7 +560,7 @@ int dhcpc_request(void *handle, struct dhcpc_state *presult)
else
{
dbg("Ignoring msgtype=%d\n", msgtype);
ndbg("Ignoring msgtype=%d\n", msgtype);
}
}
@ -582,26 +582,26 @@ int dhcpc_request(void *handle, struct dhcpc_state *presult)
}
while (state != STATE_HAVE_LEASE);
dbg("Got IP address %d.%d.%d.%d\n",
(presult->ipaddr.s_addr >> 24 ) & 0xff,
(presult->ipaddr.s_addr >> 16 ) & 0xff,
(presult->ipaddr.s_addr >> 8 ) & 0xff,
(presult->ipaddr.s_addr ) & 0xff);
dbg("Got netmask %d.%d.%d.%d\n",
(presult->netmask.s_addr >> 24 ) & 0xff,
(presult->netmask.s_addr >> 16 ) & 0xff,
(presult->netmask.s_addr >> 8 ) & 0xff,
(presult->netmask.s_addr ) & 0xff);
dbg("Got DNS server %d.%d.%d.%d\n",
(presult->dnsaddr.s_addr >> 24 ) & 0xff,
(presult->dnsaddr.s_addr >> 16 ) & 0xff,
(presult->dnsaddr.s_addr >> 8 ) & 0xff,
(presult->dnsaddr.s_addr ) & 0xff);
dbg("Got default router %d.%d.%d.%d\n",
(presult->default_router.s_addr >> 24 ) & 0xff,
(presult->default_router.s_addr >> 16 ) & 0xff,
(presult->default_router.s_addr >> 8 ) & 0xff,
(presult->default_router.s_addr ) & 0xff);
dbg("Lease expires in %d seconds\n", presult->lease_time);
ndbg("Got IP address %d.%d.%d.%d\n",
(presult->ipaddr.s_addr ) & 0xff,
(presult->ipaddr.s_addr >> 8 ) & 0xff,
(presult->ipaddr.s_addr >> 16 ) & 0xff,
(presult->ipaddr.s_addr >> 24 ) & 0xff);
ndbg("Got netmask %d.%d.%d.%d\n",
(presult->netmask.s_addr ) & 0xff,
(presult->netmask.s_addr >> 8 ) & 0xff,
(presult->netmask.s_addr >> 16 ) & 0xff,
(presult->netmask.s_addr >> 24 ) & 0xff);
ndbg("Got DNS server %d.%d.%d.%d\n",
(presult->dnsaddr.s_addr ) & 0xff,
(presult->dnsaddr.s_addr >> 8 ) & 0xff,
(presult->dnsaddr.s_addr >> 16 ) & 0xff,
(presult->dnsaddr.s_addr >> 24 ) & 0xff);
ndbg("Got default router %d.%d.%d.%d\n",
(presult->default_router.s_addr ) & 0xff,
(presult->default_router.s_addr >> 8 ) & 0xff,
(presult->default_router.s_addr >> 16 ) & 0xff,
(presult->default_router.s_addr >> 24 ) & 0xff);
ndbg("Lease expires in %d seconds\n", presult->lease_time);
return OK;
}

View File

@ -15,3 +15,12 @@ config NET_RESOLV_ENTRIES
depends on NETUTILS_RESOLV
---help---
Number of resolver entries. Default: 8
NET_RESOLV_MAXRESPONSE
int "Max response size"
default 96
depends on NETUTILS_RESOLV
---help---
This setting determines the maximum size of DHCP response message that
can be received. The default is 96 but may need to be larger on enterprise
networks (perhaps 176).

View File

@ -59,11 +59,13 @@
#include <time.h>
#include <errno.h>
#include <debug.h>
#include <assert.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <apps/netutils/resolv.h>
#include <apps/netutils/uiplib.h>
/****************************************************************************
* Definitions
@ -96,7 +98,12 @@
#define DNS_FLAG2_ERR_NAME 0x03
#define SEND_BUFFER_SIZE 64
#define RECV_BUFFER_SIZE 64
#ifdef CONFIG_NET_RESOLV_MAXRESPONSE
# define RECV_BUFFER_SIZE CONFIG_NET_RESOLV_MAXRESPONSE
#else
# define RECV_BUFFER_SIZE 96
#endif
#ifdef CONFIG_NET_IPv6
#define ADDRLEN sizeof(struct sockaddr_in6)
@ -233,6 +240,13 @@ static int send_query(const char *name, struct sockaddr_in *addr)
while(*nameptr != 0);
memcpy(query, endquery, 5);
#ifdef CONFIG_NET_IPv6
DEBUGASSERT(((struct sockaddr *)addr)->sa_family == AF_INET6);
#else
DEBUGASSERT(((struct sockaddr *)addr)->sa_family == AF_INET);
#endif
return sendto(g_sockfd, buffer, query + 5 - buffer, 0, (struct sockaddr*)addr, ADDRLEN);
}
@ -262,10 +276,10 @@ int recv_response(struct sockaddr_in *addr)
hdr = (struct dns_hdr *)buffer;
dbg( "ID %d\n", htons(hdr->id));
dbg( "Query %d\n", hdr->flags1 & DNS_FLAG1_RESPONSE);
dbg( "Error %d\n", hdr->flags2 & DNS_FLAG2_ERR_MASK);
dbg( "Num questions %d, answers %d, authrr %d, extrarr %d\n",
ndbg("ID %d\n", htons(hdr->id));
ndbg("Query %d\n", hdr->flags1 & DNS_FLAG1_RESPONSE);
ndbg("Error %d\n", hdr->flags2 & DNS_FLAG2_ERR_MASK);
ndbg("Num questions %d, answers %d, authrr %d, extrarr %d\n",
htons(hdr->numquestions), htons(hdr->numanswers),
htons(hdr->numauthrr), htons(hdr->numextrarr));
@ -286,7 +300,28 @@ int recv_response(struct sockaddr_in *addr)
/* Skip the name in the question. XXX: This should really be
* checked agains the name in the question, to be sure that they
* match.
*/
*/
#ifdef CONFIG_DEBUG_NET
{
int d = 64;
nameptr = parse_name((unsigned char *)buffer + 12) + 4;
for (;;)
{
ndbg("%02X %02X %02X %02X %02X %02X %02X %02X \n",
nameptr[0],nameptr[1],nameptr[2],nameptr[3],
nameptr[4],nameptr[5],nameptr[6],nameptr[7]);
nameptr += 8;
d -= 8;
if (d < 0)
{
break;
}
}
}
#endif
nameptr = parse_name((unsigned char *)buffer + 12) + 4;
@ -301,7 +336,7 @@ int recv_response(struct sockaddr_in *addr)
/* Compressed name. */
nameptr +=2;
dbg("Compressed anwser\n");
ndbg("Compressed anwser\n");
}
else
{
@ -310,21 +345,23 @@ int recv_response(struct sockaddr_in *addr)
}
ans = (struct dns_answer *)nameptr;
dbg("Answer: type %x, class %x, ttl %x, length %x\n",
htons(ans->type), htons(ans->class), (htons(ans->ttl[0]) << 16) | htons(ans->ttl[1]),
htons(ans->len));
ndbg("Answer: type %x, class %x, ttl %x, length %x \n", /* 0x%08X\n", */
htons(ans->type), htons(ans->class),
(htons(ans->ttl[0]) << 16) | htons(ans->ttl[1]),
htons(ans->len) /* , ans->ipaddr.s_addr */);
/* Check for IP address type and Internet class. Others are discarded. */
if (ans->type == HTONS(1) && ans->class == HTONS(1) && ans->len == HTONS(4))
{
dbg("IP address %d.%d.%d.%d\n",
(ans->ipaddr.s_addr >> 24 ) & 0xff,
(ans->ipaddr.s_addr >> 16 ) & 0xff,
(ans->ipaddr.s_addr >> 8 ) & 0xff,
(ans->ipaddr.s_addr ) & 0xff);
ans->ipaddr.s_addr = *(uint32_t*)(nameptr+10);
ndbg("IP address %d.%d.%d.%d\n",
(ans->ipaddr.s_addr ) & 0xff,
(ans->ipaddr.s_addr >> 8 ) & 0xff,
(ans->ipaddr.s_addr >> 16 ) & 0xff,
(ans->ipaddr.s_addr >> 24 ) & 0xff);
/* XXX: we should really check that this IP address is the one
/* XXX: we should really check that this IP address is the one
* we want.
*/
@ -336,6 +373,7 @@ int recv_response(struct sockaddr_in *addr)
nameptr = nameptr + 10 + htons(ans->len);
}
}
return ERROR;
}
@ -343,6 +381,62 @@ int recv_response(struct sockaddr_in *addr)
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: dns_gethostip
****************************************************************************/
int dns_gethostip(const char *hostname, in_addr_t *ipaddr)
{
#ifdef CONFIG_HAVE_GETHOSTBYNAME
struct hostent *he;
nvdbg("Getting address of %s\n", hostname);
he = gethostbyname(hostname);
if (!he)
{
ndbg("gethostbyname failed: %d\n", h_errno);
return ERROR;
}
nvdbg("Using IP address %04x%04x\n",
(uint16_t)he->h_addr[1], (uint16_t)he->h_addr[0]);
memcpy(ipaddr, he->h_addr, sizeof(in_addr_t));
return OK;
#else
# ifdef CONFIG_NET_IPv6
struct sockaddr_in6 addr;
# else
struct sockaddr_in addr;
# endif
/* First check if the host is an IP address. */
if (!uiplib_ipaddrconv(hostname, (uint8_t*)ipaddr))
{
/* 'host' does not point to a valid address string. Try to resolve
* the host name to an IP address.
*/
if (resolv_query(hostname, &addr) < 0)
{
/* Needs to set the errno here */
return ERROR;
}
/* Save the host address -- Needs fixed for IPv6 */
*ipaddr = addr.sin_addr.s_addr;
}
return OK;
#endif
}
/* Get the binding for name. */
#ifdef CONFIG_NET_IPv6
@ -358,7 +452,7 @@ int resolv_query(FAR const char *name, FAR struct sockaddr_in *addr)
for (retries = 0; retries < 3; retries++)
{
if (send_query(name, addr) < 0)
if (send_query(name, &g_dnsserver) < 0)
{
return ERROR;
}

View File

@ -167,60 +167,6 @@ static char *wget_strcpy(char *dest, const char *src)
return dest + len;
}
/****************************************************************************
* Name: wget_resolvehost
****************************************************************************/
static inline int wget_resolvehost(const char *hostname, in_addr_t *ipaddr)
{
#ifdef CONFIG_HAVE_GETHOSTBYNAME
struct hostent *he;
nvdbg("Getting address of %s\n", hostname);
he = gethostbyname(hostname);
if (!he)
{
ndbg("gethostbyname failed: %d\n", h_errno);
return ERROR;
}
nvdbg("Using IP address %04x%04x\n", (uint16_t)he->h_addr[1], (uint16_t)he->h_addr[0]);
memcpy(ipaddr, he->h_addr, sizeof(in_addr_t));
return OK;
#else
# ifdef CONFIG_NET_IPv6
struct sockaddr_in6 addr;
# else
struct sockaddr_in addr;
# endif
/* First check if the host is an IP address. */
if (!uiplib_ipaddrconv(hostname, (uint8_t*)ipaddr))
{
/* 'host' does not point to a valid address string. Try to resolve
* the host name to an IP address.
*/
if (resolv_query(hostname, &addr) < 0)
{
/* Needs to set the errno here */
return ERROR;
}
/* Save the host address -- Needs fixed for IPv6 */
*ipaddr = addr.sin_addr.s_addr;
}
return OK;
#endif
}
/****************************************************************************
* Name: wget_parsestatus
****************************************************************************/
@ -465,7 +411,7 @@ int wget(FAR const char *url, FAR char *buffer, int buflen,
server.sin_family = AF_INET;
server.sin_port = htons(ws.port);
ret = wget_resolvehost(ws.hostname, &server.sin_addr.s_addr);
ret = dns_gethostip(ws.hostname, &server.sin_addr.s_addr);
if (ret < 0)
{
/* Could not resolve host (or malformed IP address) */

View File

@ -51,6 +51,7 @@
#include <fcntl.h> /* Needed for open */
#include <libgen.h> /* Needed for basename */
#include <errno.h>
#include <debug.h>
#include <nuttx/net/net.h>
#include <nuttx/clock.h>
@ -80,6 +81,12 @@
# endif
#endif
#ifdef CONFIG_HAVE_GETHOSTBYNAME
# include <netdb.h>
#else
# include <apps/netutils/resolv.h>
#endif
#include "nsh.h"
#include "nsh_console.h"
@ -599,7 +606,7 @@ int cmd_ping(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
if (optind == argc-1)
{
staddr = argv[optind];
if (!uiplib_ipaddrconv(staddr, (FAR unsigned char*)&ipaddr))
if (dns_gethostip(staddr, &ipaddr) < 0)
{
goto errout;
}
@ -621,7 +628,11 @@ int cmd_ping(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
/* Loop for the specified count */
nsh_output(vtbl, "PING %s %d bytes of data\n", staddr, DEFAULT_PING_DATALEN);
nsh_output(vtbl, "PING %d.%d.%d.%d %d bytes of data\n",
(ipaddr ) & 0xff, (ipaddr >> 8 ) & 0xff,
(ipaddr >> 16 ) & 0xff, (ipaddr >> 24 ) & 0xff,
DEFAULT_PING_DATALEN);
start = g_system_timer;
for (i = 1; i <= count; i++)
{