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