1968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 2968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* Copyright 1998 by the Massachusetts Institute of Technology. 3968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * Copyright (C) 2009 by Jakub Hrozek <jhrozek@redhat.com> 4968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * 5968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * Permission to use, copy, modify, and distribute this 6968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * software and its documentation for any purpose and without 7968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * fee is hereby granted, provided that the above copyright 8968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * notice appear in all copies and that both that copyright 9968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * notice and this permission notice appear in supporting 10968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * documentation, and that the name of M.I.T. not be used in 11968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * advertising or publicity pertaining to distribution of the 12968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * software without specific, written prior permission. 13968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * M.I.T. makes no representations about the suitability of 14968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * this software for any purpose. It is provided "as is" 15968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * without express or implied warranty. 16968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 17968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 18968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_setup.h" 19968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 20968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_SYS_SOCKET_H 21968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <sys/socket.h> 22968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 23968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_NETINET_IN_H 24968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <netinet/in.h> 25968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 26968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_NETDB_H 27968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <netdb.h> 28968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 29968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_ARPA_INET_H 30968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <arpa/inet.h> 31968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 32968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_ARPA_NAMESER_H 33968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <arpa/nameser.h> 34968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#else 35968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include "nameser.h" 36968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 37968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_ARPA_NAMESER_COMPAT_H 38968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <arpa/nameser_compat.h> 39968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 40968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 41968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_STRINGS_H 42968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <strings.h> 43968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 44968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 45968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <stdlib.h> 46968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <string.h> 47968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 48968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares.h" 49968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_dns.h" 50968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_data.h" 51968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_private.h" 52968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 53968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldint 54968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldares_parse_txt_reply (const unsigned char *abuf, int alen, 55968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct ares_txt_reply **txt_out) 56968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 57968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold size_t substr_len, str_len; 58968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold unsigned int qdcount, ancount, i; 59968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold const unsigned char *aptr; 60968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold const unsigned char *strptr; 61968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int status, rr_type, rr_class, rr_len; 62968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold long len; 63968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold char *hostname = NULL, *rr_name = NULL; 64968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct ares_txt_reply *txt_head = NULL; 65968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct ares_txt_reply *txt_last = NULL; 66968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct ares_txt_reply *txt_curr; 67968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 68968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Set *txt_out to NULL for all failure cases. */ 69968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *txt_out = NULL; 70968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 71968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Give up if abuf doesn't have room for a header. */ 72968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (alen < HFIXEDSZ) 73968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return ARES_EBADRESP; 74968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 75968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Fetch the question and answer count from the header. */ 76968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold qdcount = DNS_HEADER_QDCOUNT (abuf); 77968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ancount = DNS_HEADER_ANCOUNT (abuf); 78968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (qdcount != 1) 79968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return ARES_EBADRESP; 80968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (ancount == 0) 81968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return ARES_ENODATA; 82968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 83968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Expand the name from the question, and skip past the question. */ 84968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold aptr = abuf + HFIXEDSZ; 85968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold status = ares_expand_name (aptr, abuf, alen, &hostname, &len); 86968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (status != ARES_SUCCESS) 87968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return status; 88968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 89968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (aptr + len + QFIXEDSZ > abuf + alen) 90968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 91968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free (hostname); 92968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return ARES_EBADRESP; 93968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 94968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold aptr += len + QFIXEDSZ; 95968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 96968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Examine each answer resource record (RR) in turn. */ 97968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold for (i = 0; i < ancount; i++) 98968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 99968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Decode the RR up to the data field. */ 100968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); 101968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (status != ARES_SUCCESS) 102968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 103968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold break; 104968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 105968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold aptr += len; 106968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (aptr + RRFIXEDSZ > abuf + alen) 107968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 108968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold status = ARES_EBADRESP; 109968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold break; 110968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 111968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold rr_type = DNS_RR_TYPE (aptr); 112968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold rr_class = DNS_RR_CLASS (aptr); 113968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold rr_len = DNS_RR_LEN (aptr); 114968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold aptr += RRFIXEDSZ; 115968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 116968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Check if we are really looking at a TXT record */ 117968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (rr_class == C_IN && rr_type == T_TXT) 118968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 119968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Allocate storage for this TXT answer appending it to the list */ 120968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold txt_curr = ares_malloc_data(ARES_DATATYPE_TXT_REPLY); 121968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (!txt_curr) 122968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 123968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold status = ARES_ENOMEM; 124968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold break; 125968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 126968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (txt_last) 127968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 128968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold txt_last->next = txt_curr; 129968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 130968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 131968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 132968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold txt_head = txt_curr; 133968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 134968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold txt_last = txt_curr; 135968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 136968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* 137968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * There may be multiple substrings in a single TXT record. Each 138968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * substring may be up to 255 characters in length, with a 139968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * "length byte" indicating the size of the substring payload. 140968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * RDATA contains both the length-bytes and payloads of all 141968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * substrings contained therein. 142968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 143968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 144968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Compute total length to allow a single memory allocation */ 145968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold strptr = aptr; 146968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold while (strptr < (aptr + rr_len)) 147968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 148968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold substr_len = (unsigned char)*strptr; 149968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold txt_curr->length += substr_len; 150968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold strptr += substr_len + 1; 151968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 152968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 153968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Including null byte */ 154968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold txt_curr->txt = malloc (txt_curr->length + 1); 155968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (txt_curr->txt == NULL) 156968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 157968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold status = ARES_ENOMEM; 158968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold break; 159968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 160968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 161968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Step through the list of substrings, concatenating them */ 162968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold str_len = 0; 163968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold strptr = aptr; 164968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold while (strptr < (aptr + rr_len)) 165968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 166968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold substr_len = (unsigned char)*strptr; 167968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold strptr++; 168968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold memcpy ((char *) txt_curr->txt + str_len, strptr, substr_len); 169968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold str_len += substr_len; 170968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold strptr += substr_len; 171968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 172968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Make sure we NULL-terminate */ 173968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *((char *) txt_curr->txt + txt_curr->length) = '\0'; 174968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 175968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 176968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Don't lose memory in the next iteration */ 177968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free (rr_name); 178968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold rr_name = NULL; 179968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 180968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Move on to the next record */ 181968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold aptr += rr_len; 182968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 183968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 184968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (hostname) 185968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free (hostname); 186968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (rr_name) 187968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free (rr_name); 188968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 189968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* clean up on error */ 190968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (status != ARES_SUCCESS) 191968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 192968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (txt_head) 193968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_free_data (txt_head); 194968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return status; 195968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 196968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 197968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* everything looks fine, return the data */ 198968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *txt_out = txt_head; 199968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 200968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return ARES_SUCCESS; 201968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 202