1968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* Copyright 1998 by the Massachusetts Institute of Technology. 2968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * 3968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * Permission to use, copy, modify, and distribute this 4968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * software and its documentation for any purpose and without 5968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * fee is hereby granted, provided that the above copyright 6968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * notice appear in all copies and that both that copyright 7968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * notice and this permission notice appear in supporting 8968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * documentation, and that the name of M.I.T. not be used in 9968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * advertising or publicity pertaining to distribution of the 10968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * software without specific, written prior permission. 11968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * M.I.T. makes no representations about the suitability of 12968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * this software for any purpose. It is provided "as is" 13968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * without express or implied warranty. 14968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 15968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 16968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* 17968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * ares_parse_ns_reply created by Vlad Dinulescu <vlad.dinulescu@avira.com> 18968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * on behalf of AVIRA Gmbh - http://www.avira.com 19968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 20968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 21968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_setup.h" 22968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 23968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_SYS_SOCKET_H 24968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <sys/socket.h> 25968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 26968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_NETINET_IN_H 27968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <netinet/in.h> 28968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 29968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_NETDB_H 30968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <netdb.h> 31968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 32968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_ARPA_INET_H 33968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <arpa/inet.h> 34968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 35968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_ARPA_NAMESER_H 36968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <arpa/nameser.h> 37968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#else 38968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include "nameser.h" 39968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 40968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_ARPA_NAMESER_COMPAT_H 41968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <arpa/nameser_compat.h> 42968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 43968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 44968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <stdlib.h> 45968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <string.h> 46968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares.h" 47968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_dns.h" 48968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_private.h" 49968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 50968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldint ares_parse_ns_reply( const unsigned char* abuf, int alen, 51968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct hostent** host ) 52968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 53968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold unsigned int qdcount, ancount; 54968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int status, i, rr_type, rr_class, rr_len; 55968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int nameservers_num; 56968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold long len; 57968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold const unsigned char *aptr; 58968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold char* hostname, *rr_name, *rr_data, **nameservers; 59968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct hostent *hostent; 60968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 61968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Set *host to NULL for all failure cases. */ 62968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *host = NULL; 63968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 64968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Give up if abuf doesn't have room for a header. */ 65968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ( alen < HFIXEDSZ ) 66968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return ARES_EBADRESP; 67968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 68968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Fetch the question and answer count from the header. */ 69968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold qdcount = DNS_HEADER_QDCOUNT( abuf ); 70968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ancount = DNS_HEADER_ANCOUNT( abuf ); 71968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ( qdcount != 1 ) 72968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return ARES_EBADRESP; 73968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 74968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Expand the name from the question, and skip past the question. */ 75968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold aptr = abuf + HFIXEDSZ; 76968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold status = ares__expand_name_for_response( aptr, abuf, alen, &hostname, &len); 77968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ( status != ARES_SUCCESS ) 78968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return status; 79968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ( aptr + len + QFIXEDSZ > abuf + alen ) 80968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 81968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free( hostname ); 82968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return ARES_EBADRESP; 83968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 84968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold aptr += len + QFIXEDSZ; 85968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 86968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Allocate nameservers array; ancount gives an upper bound */ 87968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold nameservers = malloc( ( ancount + 1 ) * sizeof( char * ) ); 88968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ( !nameservers ) 89968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 90968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free( hostname ); 91968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return ARES_ENOMEM; 92968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 93968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold nameservers_num = 0; 94968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 95968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Examine each answer resource record (RR) in turn. */ 96968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold for ( i = 0; i < ( int ) ancount; i++ ) 97968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 98968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Decode the RR up to the data field. */ 99968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold status = ares__expand_name_for_response( aptr, abuf, alen, &rr_name, &len ); 100968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ( status != ARES_SUCCESS ) 101968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold break; 102968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold aptr += len; 103968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ( aptr + RRFIXEDSZ > abuf + alen ) 104968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 105968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold status = ARES_EBADRESP; 106968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(rr_name); 107968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold break; 108968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 109968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold rr_type = DNS_RR_TYPE( aptr ); 110968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold rr_class = DNS_RR_CLASS( aptr ); 111968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold rr_len = DNS_RR_LEN( aptr ); 112968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold aptr += RRFIXEDSZ; 113968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 114968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ( rr_class == C_IN && rr_type == T_NS ) 115968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 116968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Decode the RR data and add it to the nameservers list */ 117968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold status = ares__expand_name_for_response( aptr, abuf, alen, &rr_data, 118968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold &len); 119968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ( status != ARES_SUCCESS ) 120968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 121968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(rr_name); 122968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold break; 123968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 124968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 125968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold nameservers[nameservers_num] = malloc(strlen(rr_data)+1); 126968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 127968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (nameservers[nameservers_num]==NULL) 128968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 129968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(rr_name); 130968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(rr_data); 131968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold status=ARES_ENOMEM; 132968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold break; 133968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 134968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold strcpy(nameservers[nameservers_num],rr_data); 135968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(rr_data); 136968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 137968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold nameservers_num++; 138968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 139968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 140968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free( rr_name ); 141968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 142968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold aptr += rr_len; 143968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ( aptr > abuf + alen ) 144968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 145968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold status = ARES_EBADRESP; 146968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold break; 147968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 148968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 149968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 150968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ( status == ARES_SUCCESS && nameservers_num == 0 ) 151968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 152968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold status = ARES_ENODATA; 153968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 154968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ( status == ARES_SUCCESS ) 155968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 156968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* We got our answer. Allocate memory to build the host entry. */ 157968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold nameservers[nameservers_num] = NULL; 158968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold hostent = malloc( sizeof( struct hostent ) ); 159968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ( hostent ) 160968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 161968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold hostent->h_addr_list = malloc( 1 * sizeof( char * ) ); 162968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ( hostent->h_addr_list ) 163968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 164968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Fill in the hostent and return successfully. */ 165968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold hostent->h_name = hostname; 166968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold hostent->h_aliases = nameservers; 167968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold hostent->h_addrtype = AF_INET; 168968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold hostent->h_length = sizeof( struct in_addr ); 169968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold hostent->h_addr_list[0] = NULL; 170968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *host = hostent; 171968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return ARES_SUCCESS; 172968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 173968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free( hostent ); 174968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 175968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold status = ARES_ENOMEM; 176968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 177968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold for ( i = 0; i < nameservers_num; i++ ) 178968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free( nameservers[i] ); 179968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free( nameservers ); 180968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free( hostname ); 181968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return status; 182968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 183