1d059297112922cabb0c674840589be8db821fd9aAdam Langley/* $OpenBSD: getrrsetbyname.c,v 1.11 2007/10/11 18:36:41 jakob Exp $ */ 2d059297112922cabb0c674840589be8db821fd9aAdam Langley 3d059297112922cabb0c674840589be8db821fd9aAdam Langley/* 4d059297112922cabb0c674840589be8db821fd9aAdam Langley * Copyright (c) 2001 Jakob Schlyter. All rights reserved. 5d059297112922cabb0c674840589be8db821fd9aAdam Langley * 6d059297112922cabb0c674840589be8db821fd9aAdam Langley * Redistribution and use in source and binary forms, with or without 7d059297112922cabb0c674840589be8db821fd9aAdam Langley * modification, are permitted provided that the following conditions 8d059297112922cabb0c674840589be8db821fd9aAdam Langley * are met: 9d059297112922cabb0c674840589be8db821fd9aAdam Langley * 10d059297112922cabb0c674840589be8db821fd9aAdam Langley * 1. Redistributions of source code must retain the above copyright 11d059297112922cabb0c674840589be8db821fd9aAdam Langley * notice, this list of conditions and the following disclaimer. 12d059297112922cabb0c674840589be8db821fd9aAdam Langley * 13d059297112922cabb0c674840589be8db821fd9aAdam Langley * 2. Redistributions in binary form must reproduce the above copyright 14d059297112922cabb0c674840589be8db821fd9aAdam Langley * notice, this list of conditions and the following disclaimer in the 15d059297112922cabb0c674840589be8db821fd9aAdam Langley * documentation and/or other materials provided with the distribution. 16d059297112922cabb0c674840589be8db821fd9aAdam Langley * 17d059297112922cabb0c674840589be8db821fd9aAdam Langley * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18d059297112922cabb0c674840589be8db821fd9aAdam Langley * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19d059297112922cabb0c674840589be8db821fd9aAdam Langley * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20d059297112922cabb0c674840589be8db821fd9aAdam Langley * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21d059297112922cabb0c674840589be8db821fd9aAdam Langley * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22d059297112922cabb0c674840589be8db821fd9aAdam Langley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23d059297112922cabb0c674840589be8db821fd9aAdam Langley * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24d059297112922cabb0c674840589be8db821fd9aAdam Langley * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25d059297112922cabb0c674840589be8db821fd9aAdam Langley * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26d059297112922cabb0c674840589be8db821fd9aAdam Langley * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27d059297112922cabb0c674840589be8db821fd9aAdam Langley */ 28d059297112922cabb0c674840589be8db821fd9aAdam Langley 29d059297112922cabb0c674840589be8db821fd9aAdam Langley/* 30d059297112922cabb0c674840589be8db821fd9aAdam Langley * Portions Copyright (c) 1999-2001 Internet Software Consortium. 31d059297112922cabb0c674840589be8db821fd9aAdam Langley * 32d059297112922cabb0c674840589be8db821fd9aAdam Langley * Permission to use, copy, modify, and distribute this software for any 33d059297112922cabb0c674840589be8db821fd9aAdam Langley * purpose with or without fee is hereby granted, provided that the above 34d059297112922cabb0c674840589be8db821fd9aAdam Langley * copyright notice and this permission notice appear in all copies. 35d059297112922cabb0c674840589be8db821fd9aAdam Langley * 36d059297112922cabb0c674840589be8db821fd9aAdam Langley * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM 37d059297112922cabb0c674840589be8db821fd9aAdam Langley * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 38d059297112922cabb0c674840589be8db821fd9aAdam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 39d059297112922cabb0c674840589be8db821fd9aAdam Langley * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 40d059297112922cabb0c674840589be8db821fd9aAdam Langley * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING 41d059297112922cabb0c674840589be8db821fd9aAdam Langley * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 42d059297112922cabb0c674840589be8db821fd9aAdam Langley * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 43d059297112922cabb0c674840589be8db821fd9aAdam Langley * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 44d059297112922cabb0c674840589be8db821fd9aAdam Langley */ 45d059297112922cabb0c674840589be8db821fd9aAdam Langley 46d059297112922cabb0c674840589be8db821fd9aAdam Langley/* OPENBSD ORIGINAL: lib/libc/net/getrrsetbyname.c */ 47d059297112922cabb0c674840589be8db821fd9aAdam Langley 48d059297112922cabb0c674840589be8db821fd9aAdam Langley#include "includes.h" 49d059297112922cabb0c674840589be8db821fd9aAdam Langley 50d059297112922cabb0c674840589be8db821fd9aAdam Langley#if !defined (HAVE_GETRRSETBYNAME) && !defined (HAVE_LDNS) 51d059297112922cabb0c674840589be8db821fd9aAdam Langley 52d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <stdlib.h> 53d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <string.h> 54d059297112922cabb0c674840589be8db821fd9aAdam Langley 55d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <netinet/in.h> 56d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <arpa/inet.h> 57d059297112922cabb0c674840589be8db821fd9aAdam Langley 58d059297112922cabb0c674840589be8db821fd9aAdam Langley#include "getrrsetbyname.h" 59d059297112922cabb0c674840589be8db821fd9aAdam Langley 60d059297112922cabb0c674840589be8db821fd9aAdam Langley#if defined(HAVE_DECL_H_ERRNO) && !HAVE_DECL_H_ERRNO 61d059297112922cabb0c674840589be8db821fd9aAdam Langleyextern int h_errno; 62d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 63d059297112922cabb0c674840589be8db821fd9aAdam Langley 64d059297112922cabb0c674840589be8db821fd9aAdam Langley/* We don't need multithread support here */ 65d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef _THREAD_PRIVATE 66d059297112922cabb0c674840589be8db821fd9aAdam Langley# undef _THREAD_PRIVATE 67d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 68d059297112922cabb0c674840589be8db821fd9aAdam Langley#define _THREAD_PRIVATE(a,b,c) (c) 69d059297112922cabb0c674840589be8db821fd9aAdam Langley 70d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifndef HAVE__RES_EXTERN 71d059297112922cabb0c674840589be8db821fd9aAdam Langleystruct __res_state _res; 72d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 73d059297112922cabb0c674840589be8db821fd9aAdam Langley 74d059297112922cabb0c674840589be8db821fd9aAdam Langley/* Necessary functions and macros */ 75d059297112922cabb0c674840589be8db821fd9aAdam Langley 76d059297112922cabb0c674840589be8db821fd9aAdam Langley/* 77d059297112922cabb0c674840589be8db821fd9aAdam Langley * Inline versions of get/put short/long. Pointer is advanced. 78d059297112922cabb0c674840589be8db821fd9aAdam Langley * 79d059297112922cabb0c674840589be8db821fd9aAdam Langley * These macros demonstrate the property of C whereby it can be 80d059297112922cabb0c674840589be8db821fd9aAdam Langley * portable or it can be elegant but rarely both. 81d059297112922cabb0c674840589be8db821fd9aAdam Langley */ 82d059297112922cabb0c674840589be8db821fd9aAdam Langley 83d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifndef INT32SZ 84d059297112922cabb0c674840589be8db821fd9aAdam Langley# define INT32SZ 4 85d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 86d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifndef INT16SZ 87d059297112922cabb0c674840589be8db821fd9aAdam Langley# define INT16SZ 2 88d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 89d059297112922cabb0c674840589be8db821fd9aAdam Langley 90d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifndef GETSHORT 91d059297112922cabb0c674840589be8db821fd9aAdam Langley#define GETSHORT(s, cp) { \ 92d059297112922cabb0c674840589be8db821fd9aAdam Langley register u_char *t_cp = (u_char *)(cp); \ 93d059297112922cabb0c674840589be8db821fd9aAdam Langley (s) = ((u_int16_t)t_cp[0] << 8) \ 94d059297112922cabb0c674840589be8db821fd9aAdam Langley | ((u_int16_t)t_cp[1]) \ 95d059297112922cabb0c674840589be8db821fd9aAdam Langley ; \ 96d059297112922cabb0c674840589be8db821fd9aAdam Langley (cp) += INT16SZ; \ 97d059297112922cabb0c674840589be8db821fd9aAdam Langley} 98d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 99d059297112922cabb0c674840589be8db821fd9aAdam Langley 100d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifndef GETLONG 101d059297112922cabb0c674840589be8db821fd9aAdam Langley#define GETLONG(l, cp) { \ 102d059297112922cabb0c674840589be8db821fd9aAdam Langley register u_char *t_cp = (u_char *)(cp); \ 103d059297112922cabb0c674840589be8db821fd9aAdam Langley (l) = ((u_int32_t)t_cp[0] << 24) \ 104d059297112922cabb0c674840589be8db821fd9aAdam Langley | ((u_int32_t)t_cp[1] << 16) \ 105d059297112922cabb0c674840589be8db821fd9aAdam Langley | ((u_int32_t)t_cp[2] << 8) \ 106d059297112922cabb0c674840589be8db821fd9aAdam Langley | ((u_int32_t)t_cp[3]) \ 107d059297112922cabb0c674840589be8db821fd9aAdam Langley ; \ 108d059297112922cabb0c674840589be8db821fd9aAdam Langley (cp) += INT32SZ; \ 109d059297112922cabb0c674840589be8db821fd9aAdam Langley} 110d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 111d059297112922cabb0c674840589be8db821fd9aAdam Langley 112d059297112922cabb0c674840589be8db821fd9aAdam Langley/* 113d059297112922cabb0c674840589be8db821fd9aAdam Langley * Routines to insert/extract short/long's. 114d059297112922cabb0c674840589be8db821fd9aAdam Langley */ 115d059297112922cabb0c674840589be8db821fd9aAdam Langley 116d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifndef HAVE__GETSHORT 117d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic u_int16_t 118d059297112922cabb0c674840589be8db821fd9aAdam Langley_getshort(msgp) 119d059297112922cabb0c674840589be8db821fd9aAdam Langley register const u_char *msgp; 120d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 121d059297112922cabb0c674840589be8db821fd9aAdam Langley register u_int16_t u; 122d059297112922cabb0c674840589be8db821fd9aAdam Langley 123d059297112922cabb0c674840589be8db821fd9aAdam Langley GETSHORT(u, msgp); 124d059297112922cabb0c674840589be8db821fd9aAdam Langley return (u); 125d059297112922cabb0c674840589be8db821fd9aAdam Langley} 126d059297112922cabb0c674840589be8db821fd9aAdam Langley#elif defined(HAVE_DECL__GETSHORT) && (HAVE_DECL__GETSHORT == 0) 127d059297112922cabb0c674840589be8db821fd9aAdam Langleyu_int16_t _getshort(register const u_char *); 128d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 129d059297112922cabb0c674840589be8db821fd9aAdam Langley 130d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifndef HAVE__GETLONG 131d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic u_int32_t 132d059297112922cabb0c674840589be8db821fd9aAdam Langley_getlong(msgp) 133d059297112922cabb0c674840589be8db821fd9aAdam Langley register const u_char *msgp; 134d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 135d059297112922cabb0c674840589be8db821fd9aAdam Langley register u_int32_t u; 136d059297112922cabb0c674840589be8db821fd9aAdam Langley 137d059297112922cabb0c674840589be8db821fd9aAdam Langley GETLONG(u, msgp); 138d059297112922cabb0c674840589be8db821fd9aAdam Langley return (u); 139d059297112922cabb0c674840589be8db821fd9aAdam Langley} 140d059297112922cabb0c674840589be8db821fd9aAdam Langley#elif defined(HAVE_DECL__GETLONG) && (HAVE_DECL__GETLONG == 0) 141d059297112922cabb0c674840589be8db821fd9aAdam Langleyu_int32_t _getlong(register const u_char *); 142d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 143d059297112922cabb0c674840589be8db821fd9aAdam Langley 144d059297112922cabb0c674840589be8db821fd9aAdam Langley/* ************** */ 145d059297112922cabb0c674840589be8db821fd9aAdam Langley 146d059297112922cabb0c674840589be8db821fd9aAdam Langley#define ANSWER_BUFFER_SIZE 0xffff 147d059297112922cabb0c674840589be8db821fd9aAdam Langley 148d059297112922cabb0c674840589be8db821fd9aAdam Langleystruct dns_query { 149d059297112922cabb0c674840589be8db821fd9aAdam Langley char *name; 150d059297112922cabb0c674840589be8db821fd9aAdam Langley u_int16_t type; 151d059297112922cabb0c674840589be8db821fd9aAdam Langley u_int16_t class; 152d059297112922cabb0c674840589be8db821fd9aAdam Langley struct dns_query *next; 153d059297112922cabb0c674840589be8db821fd9aAdam Langley}; 154d059297112922cabb0c674840589be8db821fd9aAdam Langley 155d059297112922cabb0c674840589be8db821fd9aAdam Langleystruct dns_rr { 156d059297112922cabb0c674840589be8db821fd9aAdam Langley char *name; 157d059297112922cabb0c674840589be8db821fd9aAdam Langley u_int16_t type; 158d059297112922cabb0c674840589be8db821fd9aAdam Langley u_int16_t class; 159d059297112922cabb0c674840589be8db821fd9aAdam Langley u_int16_t ttl; 160d059297112922cabb0c674840589be8db821fd9aAdam Langley u_int16_t size; 161d059297112922cabb0c674840589be8db821fd9aAdam Langley void *rdata; 162d059297112922cabb0c674840589be8db821fd9aAdam Langley struct dns_rr *next; 163d059297112922cabb0c674840589be8db821fd9aAdam Langley}; 164d059297112922cabb0c674840589be8db821fd9aAdam Langley 165d059297112922cabb0c674840589be8db821fd9aAdam Langleystruct dns_response { 166d059297112922cabb0c674840589be8db821fd9aAdam Langley HEADER header; 167d059297112922cabb0c674840589be8db821fd9aAdam Langley struct dns_query *query; 168d059297112922cabb0c674840589be8db821fd9aAdam Langley struct dns_rr *answer; 169d059297112922cabb0c674840589be8db821fd9aAdam Langley struct dns_rr *authority; 170d059297112922cabb0c674840589be8db821fd9aAdam Langley struct dns_rr *additional; 171d059297112922cabb0c674840589be8db821fd9aAdam Langley}; 172d059297112922cabb0c674840589be8db821fd9aAdam Langley 173d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic struct dns_response *parse_dns_response(const u_char *, int); 174d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic struct dns_query *parse_dns_qsection(const u_char *, int, 175d059297112922cabb0c674840589be8db821fd9aAdam Langley const u_char **, int); 176d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic struct dns_rr *parse_dns_rrsection(const u_char *, int, const u_char **, 177d059297112922cabb0c674840589be8db821fd9aAdam Langley int); 178d059297112922cabb0c674840589be8db821fd9aAdam Langley 179d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic void free_dns_query(struct dns_query *); 180d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic void free_dns_rr(struct dns_rr *); 181d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic void free_dns_response(struct dns_response *); 182d059297112922cabb0c674840589be8db821fd9aAdam Langley 183d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic int count_dns_rr(struct dns_rr *, u_int16_t, u_int16_t); 184d059297112922cabb0c674840589be8db821fd9aAdam Langley 185d059297112922cabb0c674840589be8db821fd9aAdam Langleyint 186d059297112922cabb0c674840589be8db821fd9aAdam Langleygetrrsetbyname(const char *hostname, unsigned int rdclass, 187d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int rdtype, unsigned int flags, 188d059297112922cabb0c674840589be8db821fd9aAdam Langley struct rrsetinfo **res) 189d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 190d059297112922cabb0c674840589be8db821fd9aAdam Langley struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res); 191d059297112922cabb0c674840589be8db821fd9aAdam Langley int result; 192d059297112922cabb0c674840589be8db821fd9aAdam Langley struct rrsetinfo *rrset = NULL; 193d059297112922cabb0c674840589be8db821fd9aAdam Langley struct dns_response *response = NULL; 194d059297112922cabb0c674840589be8db821fd9aAdam Langley struct dns_rr *rr; 195d059297112922cabb0c674840589be8db821fd9aAdam Langley struct rdatainfo *rdata; 196d059297112922cabb0c674840589be8db821fd9aAdam Langley int length; 197d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned int index_ans, index_sig; 198d059297112922cabb0c674840589be8db821fd9aAdam Langley u_char answer[ANSWER_BUFFER_SIZE]; 199d059297112922cabb0c674840589be8db821fd9aAdam Langley 200d059297112922cabb0c674840589be8db821fd9aAdam Langley /* check for invalid class and type */ 201d059297112922cabb0c674840589be8db821fd9aAdam Langley if (rdclass > 0xffff || rdtype > 0xffff) { 202d059297112922cabb0c674840589be8db821fd9aAdam Langley result = ERRSET_INVAL; 203d059297112922cabb0c674840589be8db821fd9aAdam Langley goto fail; 204d059297112922cabb0c674840589be8db821fd9aAdam Langley } 205d059297112922cabb0c674840589be8db821fd9aAdam Langley 206d059297112922cabb0c674840589be8db821fd9aAdam Langley /* don't allow queries of class or type ANY */ 207d059297112922cabb0c674840589be8db821fd9aAdam Langley if (rdclass == 0xff || rdtype == 0xff) { 208d059297112922cabb0c674840589be8db821fd9aAdam Langley result = ERRSET_INVAL; 209d059297112922cabb0c674840589be8db821fd9aAdam Langley goto fail; 210d059297112922cabb0c674840589be8db821fd9aAdam Langley } 211d059297112922cabb0c674840589be8db821fd9aAdam Langley 212d059297112922cabb0c674840589be8db821fd9aAdam Langley /* don't allow flags yet, unimplemented */ 213d059297112922cabb0c674840589be8db821fd9aAdam Langley if (flags) { 214d059297112922cabb0c674840589be8db821fd9aAdam Langley result = ERRSET_INVAL; 215d059297112922cabb0c674840589be8db821fd9aAdam Langley goto fail; 216d059297112922cabb0c674840589be8db821fd9aAdam Langley } 217d059297112922cabb0c674840589be8db821fd9aAdam Langley 218d059297112922cabb0c674840589be8db821fd9aAdam Langley /* initialize resolver */ 219d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((_resp->options & RES_INIT) == 0 && res_init() == -1) { 220d059297112922cabb0c674840589be8db821fd9aAdam Langley result = ERRSET_FAIL; 221d059297112922cabb0c674840589be8db821fd9aAdam Langley goto fail; 222d059297112922cabb0c674840589be8db821fd9aAdam Langley } 223d059297112922cabb0c674840589be8db821fd9aAdam Langley 224d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef DEBUG 225d059297112922cabb0c674840589be8db821fd9aAdam Langley _resp->options |= RES_DEBUG; 226d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif /* DEBUG */ 227d059297112922cabb0c674840589be8db821fd9aAdam Langley 228d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef RES_USE_DNSSEC 229d059297112922cabb0c674840589be8db821fd9aAdam Langley /* turn on DNSSEC if EDNS0 is configured */ 230d059297112922cabb0c674840589be8db821fd9aAdam Langley if (_resp->options & RES_USE_EDNS0) 231d059297112922cabb0c674840589be8db821fd9aAdam Langley _resp->options |= RES_USE_DNSSEC; 232d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif /* RES_USE_DNSEC */ 233d059297112922cabb0c674840589be8db821fd9aAdam Langley 234d059297112922cabb0c674840589be8db821fd9aAdam Langley /* make query */ 235d059297112922cabb0c674840589be8db821fd9aAdam Langley length = res_query(hostname, (signed int) rdclass, (signed int) rdtype, 236d059297112922cabb0c674840589be8db821fd9aAdam Langley answer, sizeof(answer)); 237d059297112922cabb0c674840589be8db821fd9aAdam Langley if (length < 0) { 238d059297112922cabb0c674840589be8db821fd9aAdam Langley switch(h_errno) { 239d059297112922cabb0c674840589be8db821fd9aAdam Langley case HOST_NOT_FOUND: 240d059297112922cabb0c674840589be8db821fd9aAdam Langley result = ERRSET_NONAME; 241d059297112922cabb0c674840589be8db821fd9aAdam Langley goto fail; 242d059297112922cabb0c674840589be8db821fd9aAdam Langley case NO_DATA: 243d059297112922cabb0c674840589be8db821fd9aAdam Langley result = ERRSET_NODATA; 244d059297112922cabb0c674840589be8db821fd9aAdam Langley goto fail; 245d059297112922cabb0c674840589be8db821fd9aAdam Langley default: 246d059297112922cabb0c674840589be8db821fd9aAdam Langley result = ERRSET_FAIL; 247d059297112922cabb0c674840589be8db821fd9aAdam Langley goto fail; 248d059297112922cabb0c674840589be8db821fd9aAdam Langley } 249d059297112922cabb0c674840589be8db821fd9aAdam Langley } 250d059297112922cabb0c674840589be8db821fd9aAdam Langley 251d059297112922cabb0c674840589be8db821fd9aAdam Langley /* parse result */ 252d059297112922cabb0c674840589be8db821fd9aAdam Langley response = parse_dns_response(answer, length); 253d059297112922cabb0c674840589be8db821fd9aAdam Langley if (response == NULL) { 254d059297112922cabb0c674840589be8db821fd9aAdam Langley result = ERRSET_FAIL; 255d059297112922cabb0c674840589be8db821fd9aAdam Langley goto fail; 256d059297112922cabb0c674840589be8db821fd9aAdam Langley } 257d059297112922cabb0c674840589be8db821fd9aAdam Langley 258d059297112922cabb0c674840589be8db821fd9aAdam Langley if (response->header.qdcount != 1) { 259d059297112922cabb0c674840589be8db821fd9aAdam Langley result = ERRSET_FAIL; 260d059297112922cabb0c674840589be8db821fd9aAdam Langley goto fail; 261d059297112922cabb0c674840589be8db821fd9aAdam Langley } 262d059297112922cabb0c674840589be8db821fd9aAdam Langley 263d059297112922cabb0c674840589be8db821fd9aAdam Langley /* initialize rrset */ 264d059297112922cabb0c674840589be8db821fd9aAdam Langley rrset = calloc(1, sizeof(struct rrsetinfo)); 265d059297112922cabb0c674840589be8db821fd9aAdam Langley if (rrset == NULL) { 266d059297112922cabb0c674840589be8db821fd9aAdam Langley result = ERRSET_NOMEMORY; 267d059297112922cabb0c674840589be8db821fd9aAdam Langley goto fail; 268d059297112922cabb0c674840589be8db821fd9aAdam Langley } 269d059297112922cabb0c674840589be8db821fd9aAdam Langley rrset->rri_rdclass = response->query->class; 270d059297112922cabb0c674840589be8db821fd9aAdam Langley rrset->rri_rdtype = response->query->type; 271d059297112922cabb0c674840589be8db821fd9aAdam Langley rrset->rri_ttl = response->answer->ttl; 272d059297112922cabb0c674840589be8db821fd9aAdam Langley rrset->rri_nrdatas = response->header.ancount; 273d059297112922cabb0c674840589be8db821fd9aAdam Langley 274d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef HAVE_HEADER_AD 275d059297112922cabb0c674840589be8db821fd9aAdam Langley /* check for authenticated data */ 276d059297112922cabb0c674840589be8db821fd9aAdam Langley if (response->header.ad == 1) 277d059297112922cabb0c674840589be8db821fd9aAdam Langley rrset->rri_flags |= RRSET_VALIDATED; 278d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 279d059297112922cabb0c674840589be8db821fd9aAdam Langley 280d059297112922cabb0c674840589be8db821fd9aAdam Langley /* copy name from answer section */ 281d059297112922cabb0c674840589be8db821fd9aAdam Langley rrset->rri_name = strdup(response->answer->name); 282d059297112922cabb0c674840589be8db821fd9aAdam Langley if (rrset->rri_name == NULL) { 283d059297112922cabb0c674840589be8db821fd9aAdam Langley result = ERRSET_NOMEMORY; 284d059297112922cabb0c674840589be8db821fd9aAdam Langley goto fail; 285d059297112922cabb0c674840589be8db821fd9aAdam Langley } 286d059297112922cabb0c674840589be8db821fd9aAdam Langley 287d059297112922cabb0c674840589be8db821fd9aAdam Langley /* count answers */ 288d059297112922cabb0c674840589be8db821fd9aAdam Langley rrset->rri_nrdatas = count_dns_rr(response->answer, rrset->rri_rdclass, 289d059297112922cabb0c674840589be8db821fd9aAdam Langley rrset->rri_rdtype); 290d059297112922cabb0c674840589be8db821fd9aAdam Langley rrset->rri_nsigs = count_dns_rr(response->answer, rrset->rri_rdclass, 291d059297112922cabb0c674840589be8db821fd9aAdam Langley T_RRSIG); 292d059297112922cabb0c674840589be8db821fd9aAdam Langley 293d059297112922cabb0c674840589be8db821fd9aAdam Langley /* allocate memory for answers */ 294d059297112922cabb0c674840589be8db821fd9aAdam Langley rrset->rri_rdatas = calloc(rrset->rri_nrdatas, 295d059297112922cabb0c674840589be8db821fd9aAdam Langley sizeof(struct rdatainfo)); 296d059297112922cabb0c674840589be8db821fd9aAdam Langley if (rrset->rri_rdatas == NULL) { 297d059297112922cabb0c674840589be8db821fd9aAdam Langley result = ERRSET_NOMEMORY; 298d059297112922cabb0c674840589be8db821fd9aAdam Langley goto fail; 299d059297112922cabb0c674840589be8db821fd9aAdam Langley } 300d059297112922cabb0c674840589be8db821fd9aAdam Langley 301d059297112922cabb0c674840589be8db821fd9aAdam Langley /* allocate memory for signatures */ 302d059297112922cabb0c674840589be8db821fd9aAdam Langley if (rrset->rri_nsigs > 0) { 303d059297112922cabb0c674840589be8db821fd9aAdam Langley rrset->rri_sigs = calloc(rrset->rri_nsigs, sizeof(struct rdatainfo)); 304d059297112922cabb0c674840589be8db821fd9aAdam Langley if (rrset->rri_sigs == NULL) { 305d059297112922cabb0c674840589be8db821fd9aAdam Langley result = ERRSET_NOMEMORY; 306d059297112922cabb0c674840589be8db821fd9aAdam Langley goto fail; 307d059297112922cabb0c674840589be8db821fd9aAdam Langley } 308d059297112922cabb0c674840589be8db821fd9aAdam Langley } 309d059297112922cabb0c674840589be8db821fd9aAdam Langley 310d059297112922cabb0c674840589be8db821fd9aAdam Langley /* copy answers & signatures */ 311d059297112922cabb0c674840589be8db821fd9aAdam Langley for (rr = response->answer, index_ans = 0, index_sig = 0; 312d059297112922cabb0c674840589be8db821fd9aAdam Langley rr; rr = rr->next) { 313d059297112922cabb0c674840589be8db821fd9aAdam Langley 314d059297112922cabb0c674840589be8db821fd9aAdam Langley rdata = NULL; 315d059297112922cabb0c674840589be8db821fd9aAdam Langley 316d059297112922cabb0c674840589be8db821fd9aAdam Langley if (rr->class == rrset->rri_rdclass && 317d059297112922cabb0c674840589be8db821fd9aAdam Langley rr->type == rrset->rri_rdtype) 318d059297112922cabb0c674840589be8db821fd9aAdam Langley rdata = &rrset->rri_rdatas[index_ans++]; 319d059297112922cabb0c674840589be8db821fd9aAdam Langley 320d059297112922cabb0c674840589be8db821fd9aAdam Langley if (rr->class == rrset->rri_rdclass && 321d059297112922cabb0c674840589be8db821fd9aAdam Langley rr->type == T_RRSIG) 322d059297112922cabb0c674840589be8db821fd9aAdam Langley rdata = &rrset->rri_sigs[index_sig++]; 323d059297112922cabb0c674840589be8db821fd9aAdam Langley 324d059297112922cabb0c674840589be8db821fd9aAdam Langley if (rdata) { 325d059297112922cabb0c674840589be8db821fd9aAdam Langley rdata->rdi_length = rr->size; 326d059297112922cabb0c674840589be8db821fd9aAdam Langley rdata->rdi_data = malloc(rr->size); 327d059297112922cabb0c674840589be8db821fd9aAdam Langley 328d059297112922cabb0c674840589be8db821fd9aAdam Langley if (rdata->rdi_data == NULL) { 329d059297112922cabb0c674840589be8db821fd9aAdam Langley result = ERRSET_NOMEMORY; 330d059297112922cabb0c674840589be8db821fd9aAdam Langley goto fail; 331d059297112922cabb0c674840589be8db821fd9aAdam Langley } 332d059297112922cabb0c674840589be8db821fd9aAdam Langley memcpy(rdata->rdi_data, rr->rdata, rr->size); 333d059297112922cabb0c674840589be8db821fd9aAdam Langley } 334d059297112922cabb0c674840589be8db821fd9aAdam Langley } 335d059297112922cabb0c674840589be8db821fd9aAdam Langley free_dns_response(response); 336d059297112922cabb0c674840589be8db821fd9aAdam Langley 337d059297112922cabb0c674840589be8db821fd9aAdam Langley *res = rrset; 338d059297112922cabb0c674840589be8db821fd9aAdam Langley return (ERRSET_SUCCESS); 339d059297112922cabb0c674840589be8db821fd9aAdam Langley 340d059297112922cabb0c674840589be8db821fd9aAdam Langleyfail: 341d059297112922cabb0c674840589be8db821fd9aAdam Langley if (rrset != NULL) 342d059297112922cabb0c674840589be8db821fd9aAdam Langley freerrset(rrset); 343d059297112922cabb0c674840589be8db821fd9aAdam Langley if (response != NULL) 344d059297112922cabb0c674840589be8db821fd9aAdam Langley free_dns_response(response); 345d059297112922cabb0c674840589be8db821fd9aAdam Langley return (result); 346d059297112922cabb0c674840589be8db821fd9aAdam Langley} 347d059297112922cabb0c674840589be8db821fd9aAdam Langley 348d059297112922cabb0c674840589be8db821fd9aAdam Langleyvoid 349d059297112922cabb0c674840589be8db821fd9aAdam Langleyfreerrset(struct rrsetinfo *rrset) 350d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 351d059297112922cabb0c674840589be8db821fd9aAdam Langley u_int16_t i; 352d059297112922cabb0c674840589be8db821fd9aAdam Langley 353d059297112922cabb0c674840589be8db821fd9aAdam Langley if (rrset == NULL) 354d059297112922cabb0c674840589be8db821fd9aAdam Langley return; 355d059297112922cabb0c674840589be8db821fd9aAdam Langley 356d059297112922cabb0c674840589be8db821fd9aAdam Langley if (rrset->rri_rdatas) { 357d059297112922cabb0c674840589be8db821fd9aAdam Langley for (i = 0; i < rrset->rri_nrdatas; i++) { 358d059297112922cabb0c674840589be8db821fd9aAdam Langley if (rrset->rri_rdatas[i].rdi_data == NULL) 359d059297112922cabb0c674840589be8db821fd9aAdam Langley break; 360d059297112922cabb0c674840589be8db821fd9aAdam Langley free(rrset->rri_rdatas[i].rdi_data); 361d059297112922cabb0c674840589be8db821fd9aAdam Langley } 362d059297112922cabb0c674840589be8db821fd9aAdam Langley free(rrset->rri_rdatas); 363d059297112922cabb0c674840589be8db821fd9aAdam Langley } 364d059297112922cabb0c674840589be8db821fd9aAdam Langley 365d059297112922cabb0c674840589be8db821fd9aAdam Langley if (rrset->rri_sigs) { 366d059297112922cabb0c674840589be8db821fd9aAdam Langley for (i = 0; i < rrset->rri_nsigs; i++) { 367d059297112922cabb0c674840589be8db821fd9aAdam Langley if (rrset->rri_sigs[i].rdi_data == NULL) 368d059297112922cabb0c674840589be8db821fd9aAdam Langley break; 369d059297112922cabb0c674840589be8db821fd9aAdam Langley free(rrset->rri_sigs[i].rdi_data); 370d059297112922cabb0c674840589be8db821fd9aAdam Langley } 371d059297112922cabb0c674840589be8db821fd9aAdam Langley free(rrset->rri_sigs); 372d059297112922cabb0c674840589be8db821fd9aAdam Langley } 373d059297112922cabb0c674840589be8db821fd9aAdam Langley 374d059297112922cabb0c674840589be8db821fd9aAdam Langley if (rrset->rri_name) 375d059297112922cabb0c674840589be8db821fd9aAdam Langley free(rrset->rri_name); 376d059297112922cabb0c674840589be8db821fd9aAdam Langley free(rrset); 377d059297112922cabb0c674840589be8db821fd9aAdam Langley} 378d059297112922cabb0c674840589be8db821fd9aAdam Langley 379d059297112922cabb0c674840589be8db821fd9aAdam Langley/* 380d059297112922cabb0c674840589be8db821fd9aAdam Langley * DNS response parsing routines 381d059297112922cabb0c674840589be8db821fd9aAdam Langley */ 382d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic struct dns_response * 383d059297112922cabb0c674840589be8db821fd9aAdam Langleyparse_dns_response(const u_char *answer, int size) 384d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 385d059297112922cabb0c674840589be8db821fd9aAdam Langley struct dns_response *resp; 386d059297112922cabb0c674840589be8db821fd9aAdam Langley const u_char *cp; 387d059297112922cabb0c674840589be8db821fd9aAdam Langley 388d059297112922cabb0c674840589be8db821fd9aAdam Langley /* allocate memory for the response */ 389d059297112922cabb0c674840589be8db821fd9aAdam Langley resp = calloc(1, sizeof(*resp)); 390d059297112922cabb0c674840589be8db821fd9aAdam Langley if (resp == NULL) 391d059297112922cabb0c674840589be8db821fd9aAdam Langley return (NULL); 392d059297112922cabb0c674840589be8db821fd9aAdam Langley 393d059297112922cabb0c674840589be8db821fd9aAdam Langley /* initialize current pointer */ 394d059297112922cabb0c674840589be8db821fd9aAdam Langley cp = answer; 395d059297112922cabb0c674840589be8db821fd9aAdam Langley 396d059297112922cabb0c674840589be8db821fd9aAdam Langley /* copy header */ 397d059297112922cabb0c674840589be8db821fd9aAdam Langley memcpy(&resp->header, cp, HFIXEDSZ); 398d059297112922cabb0c674840589be8db821fd9aAdam Langley cp += HFIXEDSZ; 399d059297112922cabb0c674840589be8db821fd9aAdam Langley 400d059297112922cabb0c674840589be8db821fd9aAdam Langley /* fix header byte order */ 401d059297112922cabb0c674840589be8db821fd9aAdam Langley resp->header.qdcount = ntohs(resp->header.qdcount); 402d059297112922cabb0c674840589be8db821fd9aAdam Langley resp->header.ancount = ntohs(resp->header.ancount); 403d059297112922cabb0c674840589be8db821fd9aAdam Langley resp->header.nscount = ntohs(resp->header.nscount); 404d059297112922cabb0c674840589be8db821fd9aAdam Langley resp->header.arcount = ntohs(resp->header.arcount); 405d059297112922cabb0c674840589be8db821fd9aAdam Langley 406d059297112922cabb0c674840589be8db821fd9aAdam Langley /* there must be at least one query */ 407d059297112922cabb0c674840589be8db821fd9aAdam Langley if (resp->header.qdcount < 1) { 408d059297112922cabb0c674840589be8db821fd9aAdam Langley free_dns_response(resp); 409d059297112922cabb0c674840589be8db821fd9aAdam Langley return (NULL); 410d059297112922cabb0c674840589be8db821fd9aAdam Langley } 411d059297112922cabb0c674840589be8db821fd9aAdam Langley 412d059297112922cabb0c674840589be8db821fd9aAdam Langley /* parse query section */ 413d059297112922cabb0c674840589be8db821fd9aAdam Langley resp->query = parse_dns_qsection(answer, size, &cp, 414d059297112922cabb0c674840589be8db821fd9aAdam Langley resp->header.qdcount); 415d059297112922cabb0c674840589be8db821fd9aAdam Langley if (resp->header.qdcount && resp->query == NULL) { 416d059297112922cabb0c674840589be8db821fd9aAdam Langley free_dns_response(resp); 417d059297112922cabb0c674840589be8db821fd9aAdam Langley return (NULL); 418d059297112922cabb0c674840589be8db821fd9aAdam Langley } 419d059297112922cabb0c674840589be8db821fd9aAdam Langley 420d059297112922cabb0c674840589be8db821fd9aAdam Langley /* parse answer section */ 421d059297112922cabb0c674840589be8db821fd9aAdam Langley resp->answer = parse_dns_rrsection(answer, size, &cp, 422d059297112922cabb0c674840589be8db821fd9aAdam Langley resp->header.ancount); 423d059297112922cabb0c674840589be8db821fd9aAdam Langley if (resp->header.ancount && resp->answer == NULL) { 424d059297112922cabb0c674840589be8db821fd9aAdam Langley free_dns_response(resp); 425d059297112922cabb0c674840589be8db821fd9aAdam Langley return (NULL); 426d059297112922cabb0c674840589be8db821fd9aAdam Langley } 427d059297112922cabb0c674840589be8db821fd9aAdam Langley 428d059297112922cabb0c674840589be8db821fd9aAdam Langley /* parse authority section */ 429d059297112922cabb0c674840589be8db821fd9aAdam Langley resp->authority = parse_dns_rrsection(answer, size, &cp, 430d059297112922cabb0c674840589be8db821fd9aAdam Langley resp->header.nscount); 431d059297112922cabb0c674840589be8db821fd9aAdam Langley if (resp->header.nscount && resp->authority == NULL) { 432d059297112922cabb0c674840589be8db821fd9aAdam Langley free_dns_response(resp); 433d059297112922cabb0c674840589be8db821fd9aAdam Langley return (NULL); 434d059297112922cabb0c674840589be8db821fd9aAdam Langley } 435d059297112922cabb0c674840589be8db821fd9aAdam Langley 436d059297112922cabb0c674840589be8db821fd9aAdam Langley /* parse additional section */ 437d059297112922cabb0c674840589be8db821fd9aAdam Langley resp->additional = parse_dns_rrsection(answer, size, &cp, 438d059297112922cabb0c674840589be8db821fd9aAdam Langley resp->header.arcount); 439d059297112922cabb0c674840589be8db821fd9aAdam Langley if (resp->header.arcount && resp->additional == NULL) { 440d059297112922cabb0c674840589be8db821fd9aAdam Langley free_dns_response(resp); 441d059297112922cabb0c674840589be8db821fd9aAdam Langley return (NULL); 442d059297112922cabb0c674840589be8db821fd9aAdam Langley } 443d059297112922cabb0c674840589be8db821fd9aAdam Langley 444d059297112922cabb0c674840589be8db821fd9aAdam Langley return (resp); 445d059297112922cabb0c674840589be8db821fd9aAdam Langley} 446d059297112922cabb0c674840589be8db821fd9aAdam Langley 447d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic struct dns_query * 448d059297112922cabb0c674840589be8db821fd9aAdam Langleyparse_dns_qsection(const u_char *answer, int size, const u_char **cp, int count) 449d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 450d059297112922cabb0c674840589be8db821fd9aAdam Langley struct dns_query *head, *curr, *prev; 451d059297112922cabb0c674840589be8db821fd9aAdam Langley int i, length; 452d059297112922cabb0c674840589be8db821fd9aAdam Langley char name[MAXDNAME]; 453d059297112922cabb0c674840589be8db821fd9aAdam Langley 454d059297112922cabb0c674840589be8db821fd9aAdam Langley for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) { 455d059297112922cabb0c674840589be8db821fd9aAdam Langley 456d059297112922cabb0c674840589be8db821fd9aAdam Langley /* allocate and initialize struct */ 457d059297112922cabb0c674840589be8db821fd9aAdam Langley curr = calloc(1, sizeof(struct dns_query)); 458d059297112922cabb0c674840589be8db821fd9aAdam Langley if (curr == NULL) { 459d059297112922cabb0c674840589be8db821fd9aAdam Langley free_dns_query(head); 460d059297112922cabb0c674840589be8db821fd9aAdam Langley return (NULL); 461d059297112922cabb0c674840589be8db821fd9aAdam Langley } 462d059297112922cabb0c674840589be8db821fd9aAdam Langley if (head == NULL) 463d059297112922cabb0c674840589be8db821fd9aAdam Langley head = curr; 464d059297112922cabb0c674840589be8db821fd9aAdam Langley if (prev != NULL) 465d059297112922cabb0c674840589be8db821fd9aAdam Langley prev->next = curr; 466d059297112922cabb0c674840589be8db821fd9aAdam Langley 467d059297112922cabb0c674840589be8db821fd9aAdam Langley /* name */ 468d059297112922cabb0c674840589be8db821fd9aAdam Langley length = dn_expand(answer, answer + size, *cp, name, 469d059297112922cabb0c674840589be8db821fd9aAdam Langley sizeof(name)); 470d059297112922cabb0c674840589be8db821fd9aAdam Langley if (length < 0) { 471d059297112922cabb0c674840589be8db821fd9aAdam Langley free_dns_query(head); 472d059297112922cabb0c674840589be8db821fd9aAdam Langley return (NULL); 473d059297112922cabb0c674840589be8db821fd9aAdam Langley } 474d059297112922cabb0c674840589be8db821fd9aAdam Langley curr->name = strdup(name); 475d059297112922cabb0c674840589be8db821fd9aAdam Langley if (curr->name == NULL) { 476d059297112922cabb0c674840589be8db821fd9aAdam Langley free_dns_query(head); 477d059297112922cabb0c674840589be8db821fd9aAdam Langley return (NULL); 478d059297112922cabb0c674840589be8db821fd9aAdam Langley } 479d059297112922cabb0c674840589be8db821fd9aAdam Langley *cp += length; 480d059297112922cabb0c674840589be8db821fd9aAdam Langley 481d059297112922cabb0c674840589be8db821fd9aAdam Langley /* type */ 482d059297112922cabb0c674840589be8db821fd9aAdam Langley curr->type = _getshort(*cp); 483d059297112922cabb0c674840589be8db821fd9aAdam Langley *cp += INT16SZ; 484d059297112922cabb0c674840589be8db821fd9aAdam Langley 485d059297112922cabb0c674840589be8db821fd9aAdam Langley /* class */ 486d059297112922cabb0c674840589be8db821fd9aAdam Langley curr->class = _getshort(*cp); 487d059297112922cabb0c674840589be8db821fd9aAdam Langley *cp += INT16SZ; 488d059297112922cabb0c674840589be8db821fd9aAdam Langley } 489d059297112922cabb0c674840589be8db821fd9aAdam Langley 490d059297112922cabb0c674840589be8db821fd9aAdam Langley return (head); 491d059297112922cabb0c674840589be8db821fd9aAdam Langley} 492d059297112922cabb0c674840589be8db821fd9aAdam Langley 493d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic struct dns_rr * 494d059297112922cabb0c674840589be8db821fd9aAdam Langleyparse_dns_rrsection(const u_char *answer, int size, const u_char **cp, 495d059297112922cabb0c674840589be8db821fd9aAdam Langley int count) 496d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 497d059297112922cabb0c674840589be8db821fd9aAdam Langley struct dns_rr *head, *curr, *prev; 498d059297112922cabb0c674840589be8db821fd9aAdam Langley int i, length; 499d059297112922cabb0c674840589be8db821fd9aAdam Langley char name[MAXDNAME]; 500d059297112922cabb0c674840589be8db821fd9aAdam Langley 501d059297112922cabb0c674840589be8db821fd9aAdam Langley for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) { 502d059297112922cabb0c674840589be8db821fd9aAdam Langley 503d059297112922cabb0c674840589be8db821fd9aAdam Langley /* allocate and initialize struct */ 504d059297112922cabb0c674840589be8db821fd9aAdam Langley curr = calloc(1, sizeof(struct dns_rr)); 505d059297112922cabb0c674840589be8db821fd9aAdam Langley if (curr == NULL) { 506d059297112922cabb0c674840589be8db821fd9aAdam Langley free_dns_rr(head); 507d059297112922cabb0c674840589be8db821fd9aAdam Langley return (NULL); 508d059297112922cabb0c674840589be8db821fd9aAdam Langley } 509d059297112922cabb0c674840589be8db821fd9aAdam Langley if (head == NULL) 510d059297112922cabb0c674840589be8db821fd9aAdam Langley head = curr; 511d059297112922cabb0c674840589be8db821fd9aAdam Langley if (prev != NULL) 512d059297112922cabb0c674840589be8db821fd9aAdam Langley prev->next = curr; 513d059297112922cabb0c674840589be8db821fd9aAdam Langley 514d059297112922cabb0c674840589be8db821fd9aAdam Langley /* name */ 515d059297112922cabb0c674840589be8db821fd9aAdam Langley length = dn_expand(answer, answer + size, *cp, name, 516d059297112922cabb0c674840589be8db821fd9aAdam Langley sizeof(name)); 517d059297112922cabb0c674840589be8db821fd9aAdam Langley if (length < 0) { 518d059297112922cabb0c674840589be8db821fd9aAdam Langley free_dns_rr(head); 519d059297112922cabb0c674840589be8db821fd9aAdam Langley return (NULL); 520d059297112922cabb0c674840589be8db821fd9aAdam Langley } 521d059297112922cabb0c674840589be8db821fd9aAdam Langley curr->name = strdup(name); 522d059297112922cabb0c674840589be8db821fd9aAdam Langley if (curr->name == NULL) { 523d059297112922cabb0c674840589be8db821fd9aAdam Langley free_dns_rr(head); 524d059297112922cabb0c674840589be8db821fd9aAdam Langley return (NULL); 525d059297112922cabb0c674840589be8db821fd9aAdam Langley } 526d059297112922cabb0c674840589be8db821fd9aAdam Langley *cp += length; 527d059297112922cabb0c674840589be8db821fd9aAdam Langley 528d059297112922cabb0c674840589be8db821fd9aAdam Langley /* type */ 529d059297112922cabb0c674840589be8db821fd9aAdam Langley curr->type = _getshort(*cp); 530d059297112922cabb0c674840589be8db821fd9aAdam Langley *cp += INT16SZ; 531d059297112922cabb0c674840589be8db821fd9aAdam Langley 532d059297112922cabb0c674840589be8db821fd9aAdam Langley /* class */ 533d059297112922cabb0c674840589be8db821fd9aAdam Langley curr->class = _getshort(*cp); 534d059297112922cabb0c674840589be8db821fd9aAdam Langley *cp += INT16SZ; 535d059297112922cabb0c674840589be8db821fd9aAdam Langley 536d059297112922cabb0c674840589be8db821fd9aAdam Langley /* ttl */ 537d059297112922cabb0c674840589be8db821fd9aAdam Langley curr->ttl = _getlong(*cp); 538d059297112922cabb0c674840589be8db821fd9aAdam Langley *cp += INT32SZ; 539d059297112922cabb0c674840589be8db821fd9aAdam Langley 540d059297112922cabb0c674840589be8db821fd9aAdam Langley /* rdata size */ 541d059297112922cabb0c674840589be8db821fd9aAdam Langley curr->size = _getshort(*cp); 542d059297112922cabb0c674840589be8db821fd9aAdam Langley *cp += INT16SZ; 543d059297112922cabb0c674840589be8db821fd9aAdam Langley 544d059297112922cabb0c674840589be8db821fd9aAdam Langley /* rdata itself */ 545d059297112922cabb0c674840589be8db821fd9aAdam Langley curr->rdata = malloc(curr->size); 546d059297112922cabb0c674840589be8db821fd9aAdam Langley if (curr->rdata == NULL) { 547d059297112922cabb0c674840589be8db821fd9aAdam Langley free_dns_rr(head); 548d059297112922cabb0c674840589be8db821fd9aAdam Langley return (NULL); 549d059297112922cabb0c674840589be8db821fd9aAdam Langley } 550d059297112922cabb0c674840589be8db821fd9aAdam Langley memcpy(curr->rdata, *cp, curr->size); 551d059297112922cabb0c674840589be8db821fd9aAdam Langley *cp += curr->size; 552d059297112922cabb0c674840589be8db821fd9aAdam Langley } 553d059297112922cabb0c674840589be8db821fd9aAdam Langley 554d059297112922cabb0c674840589be8db821fd9aAdam Langley return (head); 555d059297112922cabb0c674840589be8db821fd9aAdam Langley} 556d059297112922cabb0c674840589be8db821fd9aAdam Langley 557d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic void 558d059297112922cabb0c674840589be8db821fd9aAdam Langleyfree_dns_query(struct dns_query *p) 559d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 560d059297112922cabb0c674840589be8db821fd9aAdam Langley if (p == NULL) 561d059297112922cabb0c674840589be8db821fd9aAdam Langley return; 562d059297112922cabb0c674840589be8db821fd9aAdam Langley 563d059297112922cabb0c674840589be8db821fd9aAdam Langley if (p->name) 564d059297112922cabb0c674840589be8db821fd9aAdam Langley free(p->name); 565d059297112922cabb0c674840589be8db821fd9aAdam Langley free_dns_query(p->next); 566d059297112922cabb0c674840589be8db821fd9aAdam Langley free(p); 567d059297112922cabb0c674840589be8db821fd9aAdam Langley} 568d059297112922cabb0c674840589be8db821fd9aAdam Langley 569d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic void 570d059297112922cabb0c674840589be8db821fd9aAdam Langleyfree_dns_rr(struct dns_rr *p) 571d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 572d059297112922cabb0c674840589be8db821fd9aAdam Langley if (p == NULL) 573d059297112922cabb0c674840589be8db821fd9aAdam Langley return; 574d059297112922cabb0c674840589be8db821fd9aAdam Langley 575d059297112922cabb0c674840589be8db821fd9aAdam Langley if (p->name) 576d059297112922cabb0c674840589be8db821fd9aAdam Langley free(p->name); 577d059297112922cabb0c674840589be8db821fd9aAdam Langley if (p->rdata) 578d059297112922cabb0c674840589be8db821fd9aAdam Langley free(p->rdata); 579d059297112922cabb0c674840589be8db821fd9aAdam Langley free_dns_rr(p->next); 580d059297112922cabb0c674840589be8db821fd9aAdam Langley free(p); 581d059297112922cabb0c674840589be8db821fd9aAdam Langley} 582d059297112922cabb0c674840589be8db821fd9aAdam Langley 583d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic void 584d059297112922cabb0c674840589be8db821fd9aAdam Langleyfree_dns_response(struct dns_response *p) 585d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 586d059297112922cabb0c674840589be8db821fd9aAdam Langley if (p == NULL) 587d059297112922cabb0c674840589be8db821fd9aAdam Langley return; 588d059297112922cabb0c674840589be8db821fd9aAdam Langley 589d059297112922cabb0c674840589be8db821fd9aAdam Langley free_dns_query(p->query); 590d059297112922cabb0c674840589be8db821fd9aAdam Langley free_dns_rr(p->answer); 591d059297112922cabb0c674840589be8db821fd9aAdam Langley free_dns_rr(p->authority); 592d059297112922cabb0c674840589be8db821fd9aAdam Langley free_dns_rr(p->additional); 593d059297112922cabb0c674840589be8db821fd9aAdam Langley free(p); 594d059297112922cabb0c674840589be8db821fd9aAdam Langley} 595d059297112922cabb0c674840589be8db821fd9aAdam Langley 596d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic int 597d059297112922cabb0c674840589be8db821fd9aAdam Langleycount_dns_rr(struct dns_rr *p, u_int16_t class, u_int16_t type) 598d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 599d059297112922cabb0c674840589be8db821fd9aAdam Langley int n = 0; 600d059297112922cabb0c674840589be8db821fd9aAdam Langley 601d059297112922cabb0c674840589be8db821fd9aAdam Langley while(p) { 602d059297112922cabb0c674840589be8db821fd9aAdam Langley if (p->class == class && p->type == type) 603d059297112922cabb0c674840589be8db821fd9aAdam Langley n++; 604d059297112922cabb0c674840589be8db821fd9aAdam Langley p = p->next; 605d059297112922cabb0c674840589be8db821fd9aAdam Langley } 606d059297112922cabb0c674840589be8db821fd9aAdam Langley 607d059297112922cabb0c674840589be8db821fd9aAdam Langley return (n); 608d059297112922cabb0c674840589be8db821fd9aAdam Langley} 609d059297112922cabb0c674840589be8db821fd9aAdam Langley 610d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif /* !defined (HAVE_GETRRSETBYNAME) && !defined (HAVE_LDNS) */ 611