diff options
-rw-r--r-- | CHANGES | 4 | ||||
-rw-r--r-- | Makefile.inc | 13 | ||||
-rw-r--r-- | ares.h | 2 | ||||
-rw-r--r-- | ares_parse_ns_reply.3 | 66 | ||||
-rw-r--r-- | ares_parse_ns_reply.c | 172 |
5 files changed, 251 insertions, 6 deletions
@@ -1,5 +1,9 @@ Changelog for the c-ares project +* February 19 + +- Vlad Dinulescu added ares_parse_ns_reply(). + * February 13 - Yang Tse: Fix failure to get the search sequence of /etc/hosts and diff --git a/Makefile.inc b/Makefile.inc index ea87108..55735e2 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -5,17 +5,18 @@ ares_gethostbyname.c ares_strerror.c ares_cancel.c ares_init.c \ ares_timeout.c ares_destroy.c ares_mkquery.c ares_version.c \ ares_expand_name.c ares_parse_a_reply.c windows_port.c \ ares_expand_string.c ares_parse_ptr_reply.c ares_parse_aaaa_reply.c \ -ares_getnameinfo.c inet_net_pton.c bitncmp.c inet_ntop.c +ares_getnameinfo.c inet_net_pton.c bitncmp.c inet_ntop.c \ +ares_parse_ns_reply.c HHEADERS = ares.h ares_private.h setup.h ares_dns.h ares_version.h \ nameser.h inet_net_pton.h inet_ntop.h ares_ipv6.h bitncmp.h \ setup_once.h MANPAGES= ares_destroy.3 ares_expand_name.3 ares_expand_string.3 ares_fds.3 \ - ares_free_hostent.3 ares_free_string.3 ares_gethostbyaddr.3 \ - ares_gethostbyname.3 ares_init.3 ares_init_options.3 ares_mkquery.3 \ - ares_parse_a_reply.3 ares_parse_ptr_reply.3 ares_process.3 \ - ares_query.3 ares_search.3 ares_send.3 ares_strerror.3 ares_timeout.3 \ + ares_free_hostent.3 ares_free_string.3 ares_gethostbyaddr.3 \ + ares_gethostbyname.3 ares_init.3 ares_init_options.3 ares_mkquery.3 \ + ares_parse_a_reply.3 ares_parse_ptr_reply.3 ares_process.3 \ + ares_query.3 ares_search.3 ares_send.3 ares_strerror.3 ares_timeout.3 \ ares_version.3 ares_cancel.3 ares_parse_aaaa_reply.3 ares_getnameinfo.3 \ - ares_getsock.3 + ares_getsock.3 ares_parse_ns_reply.3 @@ -213,6 +213,8 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, struct hostent **host); int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, int addrlen, int family, struct hostent **host); +int ares_parse_ns_reply(const unsigned char *abuf, int alen, + struct hostent **host); void ares_free_string(void *str); void ares_free_hostent(struct hostent *host); const char *ares_strerror(int code); diff --git a/ares_parse_ns_reply.3 b/ares_parse_ns_reply.3 new file mode 100644 index 0000000..b6340ac --- /dev/null +++ b/ares_parse_ns_reply.3 @@ -0,0 +1,66 @@ +.\" +.\" Copyright 1998 by the Massachusetts Institute of Technology. +.\" +.\" Permission to use, copy, modify, and distribute this +.\" software and its documentation for any purpose and without +.\" fee is hereby granted, provided that the above copyright +.\" notice appear in all copies and that both that copyright +.\" notice and this permission notice appear in supporting +.\" documentation, and that the name of M.I.T. not be used in +.\" advertising or publicity pertaining to distribution of the +.\" software without specific, written prior permission. +.\" M.I.T. makes no representations about the suitability of +.\" this software for any purpose. It is provided "as is" +.\" without express or implied warranty. +.\" +.TH ARES_PARSE_NS_REPLY 3 "10 February 2007" +.SH NAME +ares_parse_ns_reply \- Parse a reply to a DNS query of type NS into a hostent +.SH SYNOPSIS +.nf +.B #include <ares.h> +.PP +.B int ares_parse_ns_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP, +.B struct hostent **\fIhost\fP); +.fi +.SH DESCRIPTION +The +.B ares_parse_ns_reply +function parses the response to a query of type NS into a +.BR "struct hostent" . +The parameters +.I abuf +and +.I alen +give the contents of the response. The result is stored in allocated +memory and a pointer to it stored into the variable pointed to by +.IR host . +The nameservers are stored into the +.BR aliases +field of the +.IR host +structure. +It is the caller's responsibility to free the resulting host structure +using +.BR ares_free_hostent (3) +when it is no longer needed. +.SH RETURN VALUES +.B ares_parse_ns_reply +can return any of the following values: +.TP 15 +.B ARES_SUCCESS +The response was successfully parsed. +.TP 15 +.B ARES_EBADRESP +The response was malformatted. +.TP 15 +.B ARES_ENODATA +The response did not contain an answer to the query. +.TP 15 +.B ARES_ENOMEM +Memory was exhausted. +.SH SEE ALSO +.BR ares_query (3), +.BR ares_free_hostent (3) +.SH AUTHOR +Written by Vlad Dinulescu <vlad.dinulescu@avira.com>, on behalf of AVIRA Gmbh http://www.avira.com diff --git a/ares_parse_ns_reply.c b/ares_parse_ns_reply.c new file mode 100644 index 0000000..b8b258a --- /dev/null +++ b/ares_parse_ns_reply.c @@ -0,0 +1,172 @@ +/* Copyright 1998 by the Massachusetts Institute of Technology. + * +* Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without +* fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting +* documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the +* software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +/* + * ares_parse_ns_reply created by Vlad Dinulescu <vlad.dinulescu@avira.com> + * on behalf of AVIRA Gmbh - http://www.avira.com + */ + +#include "setup.h" +#include <sys/types.h> + +#if defined(WIN32) && !defined(WATT32) +#include "nameser.h" +#else +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <arpa/nameser.h> +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +#include <arpa/nameser_compat.h> +#endif +#endif + +#include <stdlib.h> +#include <string.h> +#include "ares.h" +#include "ares_dns.h" +#include "ares_private.h" + +int ares_parse_ns_reply( const unsigned char* abuf, int alen, + struct hostent** host ) +{ + unsigned int qdcount, ancount; + int status, i, rr_type, rr_class, rr_len; + int nameservers_num; + long len; + const unsigned char *aptr; + char* hostname, *rr_name, *rr_data, **nameservers; + struct hostent *hostent; + + /* Set *host to NULL for all failure cases. */ + *host = NULL; + + /* Give up if abuf doesn't have room for a header. */ + if ( alen < HFIXEDSZ ) + return ARES_EBADRESP; + + /* Fetch the question and answer count from the header. */ + qdcount = DNS_HEADER_QDCOUNT( abuf ); + ancount = DNS_HEADER_ANCOUNT( abuf ); + if ( qdcount != 1 ) + return ARES_EBADRESP; + + /* Expand the name from the question, and skip past the question. */ + aptr = abuf + HFIXEDSZ; + status = ares_expand_name( aptr, abuf, alen, &hostname, &len ); + if ( status != ARES_SUCCESS ) + return status; + if ( aptr + len + QFIXEDSZ > abuf + alen ) + { + free( hostname ); + return ARES_EBADRESP; + } + aptr += len + QFIXEDSZ; + + /* Allocate nameservers array; ancount gives an upper bound */ + nameservers = malloc( ( ancount + 1 ) * sizeof( char * ) ); + if ( !nameservers ) + { + free( hostname ); + return ARES_ENOMEM; + } + nameservers_num = 0; + + /* Examine each answer resource record (RR) in turn. */ + for ( i = 0; i < ( int ) ancount; i++ ) + { + /* Decode the RR up to the data field. */ + status = ares_expand_name( aptr, abuf, alen, &rr_name, &len ); + if ( status != ARES_SUCCESS ) + break; + aptr += len; + if ( aptr + RRFIXEDSZ > abuf + alen ) + { + status = ARES_EBADRESP; + break; + } + rr_type = DNS_RR_TYPE( aptr ); + rr_class = DNS_RR_CLASS( aptr ); + rr_len = DNS_RR_LEN( aptr ); + aptr += RRFIXEDSZ; + + if ( rr_class == C_IN && rr_type == T_NS ) + { + /* Decode the RR data and add it to the nameservers list */ + status = ares_expand_name( aptr, abuf, alen, &rr_data, &len ); + if ( status != ARES_SUCCESS ) + { + break; + } + + nameservers[nameservers_num] = malloc(strlen(rr_data)+1); + + if (nameservers[nameservers_num]==NULL) + { + free(rr_name); + free(rr_data); + status=ARES_ENOMEM; + break; + } + strcpy(nameservers[nameservers_num],rr_data); + free(rr_data); + + nameservers_num++; + } + + free( rr_name ); + + aptr += rr_len; + if ( aptr > abuf + alen ) + { + status = ARES_EBADRESP; + break; + } + } + + if ( status == ARES_SUCCESS && nameservers_num == 0 ) + { + status = ARES_ENODATA; + } + if ( status == ARES_SUCCESS ) + { + /* We got our answer. Allocate memory to build the host entry. */ + nameservers[nameservers_num] = NULL; + hostent = malloc( sizeof( struct hostent ) ); + if ( hostent ) + { + hostent->h_addr_list = malloc( 1 * sizeof( char * ) ); + if ( hostent->h_addr_list ) + { + /* Fill in the hostent and return successfully. */ + hostent->h_name = hostname; + hostent->h_aliases = nameservers; + hostent->h_addrtype = AF_INET; + hostent->h_length = sizeof( struct in_addr ); + hostent->h_addr_list[0] = NULL; + *host = hostent; + return ARES_SUCCESS; + } + free( hostent ); + } + status = ARES_ENOMEM; + } + for ( i = 0; i < nameservers_num; i++ ) + free( nameservers[i] ); + free( nameservers ); + free( hostname ); + return status; +} |