getrrsetbyname.c revision 157016
1157016Sdes/* $OpenBSD: getrrsetbyname.c,v 1.10 2005/03/30 02:58:28 tedu Exp $ */ 2126274Sdes 3124208Sdes/* 4124208Sdes * Copyright (c) 2001 Jakob Schlyter. All rights reserved. 5124208Sdes * 6124208Sdes * Redistribution and use in source and binary forms, with or without 7124208Sdes * modification, are permitted provided that the following conditions 8124208Sdes * are met: 9124208Sdes * 10124208Sdes * 1. Redistributions of source code must retain the above copyright 11124208Sdes * notice, this list of conditions and the following disclaimer. 12124208Sdes * 13124208Sdes * 2. Redistributions in binary form must reproduce the above copyright 14124208Sdes * notice, this list of conditions and the following disclaimer in the 15124208Sdes * documentation and/or other materials provided with the distribution. 16124208Sdes * 17124208Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18124208Sdes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19124208Sdes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20124208Sdes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21124208Sdes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22124208Sdes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23124208Sdes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24124208Sdes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25124208Sdes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26124208Sdes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27124208Sdes */ 28124208Sdes 29124208Sdes/* 30124208Sdes * Portions Copyright (c) 1999-2001 Internet Software Consortium. 31124208Sdes * 32124208Sdes * Permission to use, copy, modify, and distribute this software for any 33124208Sdes * purpose with or without fee is hereby granted, provided that the above 34124208Sdes * copyright notice and this permission notice appear in all copies. 35124208Sdes * 36124208Sdes * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM 37124208Sdes * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 38124208Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 39124208Sdes * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 40124208Sdes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING 41124208Sdes * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 42124208Sdes * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 43124208Sdes * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 44124208Sdes */ 45124208Sdes 46157016Sdes/* OPENBSD ORIGINAL: lib/libc/net/getrrsetbyname.c */ 47157016Sdes 48124208Sdes#include "includes.h" 49124208Sdes 50126274Sdes#ifndef HAVE_GETRRSETBYNAME 51124208Sdes 52124208Sdes#include "getrrsetbyname.h" 53124208Sdes 54137015Sdes#if defined(HAVE_DECL_H_ERRNO) && !HAVE_DECL_H_ERRNO 55137015Sdesextern int h_errno; 56137015Sdes#endif 57137015Sdes 58157016Sdes/* We don't need multithread support here */ 59157016Sdes#ifdef _THREAD_PRIVATE 60157016Sdes# undef _THREAD_PRIVATE 61157016Sdes#endif 62157016Sdes#define _THREAD_PRIVATE(a,b,c) (c) 63157016Sdesstruct __res_state _res; 64124208Sdes 65157016Sdes/* Necessary functions and macros */ 66124208Sdes 67124208Sdes/* 68124208Sdes * Inline versions of get/put short/long. Pointer is advanced. 69124208Sdes * 70124208Sdes * These macros demonstrate the property of C whereby it can be 71124208Sdes * portable or it can be elegant but rarely both. 72124208Sdes */ 73124208Sdes 74124208Sdes#ifndef INT32SZ 75124208Sdes# define INT32SZ 4 76124208Sdes#endif 77124208Sdes#ifndef INT16SZ 78124208Sdes# define INT16SZ 2 79124208Sdes#endif 80124208Sdes 81124208Sdes#ifndef GETSHORT 82124208Sdes#define GETSHORT(s, cp) { \ 83124208Sdes register u_char *t_cp = (u_char *)(cp); \ 84124208Sdes (s) = ((u_int16_t)t_cp[0] << 8) \ 85124208Sdes | ((u_int16_t)t_cp[1]) \ 86124208Sdes ; \ 87124208Sdes (cp) += INT16SZ; \ 88124208Sdes} 89124208Sdes#endif 90124208Sdes 91124208Sdes#ifndef GETLONG 92124208Sdes#define GETLONG(l, cp) { \ 93124208Sdes register u_char *t_cp = (u_char *)(cp); \ 94124208Sdes (l) = ((u_int32_t)t_cp[0] << 24) \ 95124208Sdes | ((u_int32_t)t_cp[1] << 16) \ 96124208Sdes | ((u_int32_t)t_cp[2] << 8) \ 97124208Sdes | ((u_int32_t)t_cp[3]) \ 98124208Sdes ; \ 99124208Sdes (cp) += INT32SZ; \ 100124208Sdes} 101124208Sdes#endif 102124208Sdes 103124208Sdes/* 104124208Sdes * Routines to insert/extract short/long's. 105124208Sdes */ 106124208Sdes 107124208Sdes#ifndef HAVE__GETSHORT 108124208Sdesstatic u_int16_t 109124208Sdes_getshort(msgp) 110124208Sdes register const u_char *msgp; 111124208Sdes{ 112124208Sdes register u_int16_t u; 113124208Sdes 114124208Sdes GETSHORT(u, msgp); 115124208Sdes return (u); 116124208Sdes} 117149749Sdes#elif defined(HAVE_DECL__GETSHORT) && (HAVE_DECL__GETSHORT == 0) 118149749Sdesu_int16_t _getshort(register const u_char *); 119124208Sdes#endif 120124208Sdes 121124208Sdes#ifndef HAVE__GETLONG 122124208Sdesstatic u_int32_t 123124208Sdes_getlong(msgp) 124124208Sdes register const u_char *msgp; 125124208Sdes{ 126124208Sdes register u_int32_t u; 127124208Sdes 128124208Sdes GETLONG(u, msgp); 129124208Sdes return (u); 130124208Sdes} 131149749Sdes#elif defined(HAVE_DECL__GETLONG) && (HAVE_DECL__GETLONG == 0) 132149749Sdesu_int32_t _getlong(register const u_char *); 133124208Sdes#endif 134124208Sdes 135157016Sdes/* ************** */ 136157016Sdes 137157016Sdes#define ANSWER_BUFFER_SIZE 1024*64 138157016Sdes 139157016Sdesstruct dns_query { 140157016Sdes char *name; 141157016Sdes u_int16_t type; 142157016Sdes u_int16_t class; 143157016Sdes struct dns_query *next; 144157016Sdes}; 145157016Sdes 146157016Sdesstruct dns_rr { 147157016Sdes char *name; 148157016Sdes u_int16_t type; 149157016Sdes u_int16_t class; 150157016Sdes u_int16_t ttl; 151157016Sdes u_int16_t size; 152157016Sdes void *rdata; 153157016Sdes struct dns_rr *next; 154157016Sdes}; 155157016Sdes 156157016Sdesstruct dns_response { 157157016Sdes HEADER header; 158157016Sdes struct dns_query *query; 159157016Sdes struct dns_rr *answer; 160157016Sdes struct dns_rr *authority; 161157016Sdes struct dns_rr *additional; 162157016Sdes}; 163157016Sdes 164157016Sdesstatic struct dns_response *parse_dns_response(const u_char *, int); 165157016Sdesstatic struct dns_query *parse_dns_qsection(const u_char *, int, 166157016Sdes const u_char **, int); 167157016Sdesstatic struct dns_rr *parse_dns_rrsection(const u_char *, int, const u_char **, 168157016Sdes int); 169157016Sdes 170157016Sdesstatic void free_dns_query(struct dns_query *); 171157016Sdesstatic void free_dns_rr(struct dns_rr *); 172157016Sdesstatic void free_dns_response(struct dns_response *); 173157016Sdes 174157016Sdesstatic int count_dns_rr(struct dns_rr *, u_int16_t, u_int16_t); 175157016Sdes 176124208Sdesint 177124208Sdesgetrrsetbyname(const char *hostname, unsigned int rdclass, 178124208Sdes unsigned int rdtype, unsigned int flags, 179124208Sdes struct rrsetinfo **res) 180124208Sdes{ 181157016Sdes struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res); 182124208Sdes int result; 183124208Sdes struct rrsetinfo *rrset = NULL; 184157016Sdes struct dns_response *response = NULL; 185124208Sdes struct dns_rr *rr; 186124208Sdes struct rdatainfo *rdata; 187124208Sdes int length; 188124208Sdes unsigned int index_ans, index_sig; 189124208Sdes u_char answer[ANSWER_BUFFER_SIZE]; 190124208Sdes 191124208Sdes /* check for invalid class and type */ 192124208Sdes if (rdclass > 0xffff || rdtype > 0xffff) { 193124208Sdes result = ERRSET_INVAL; 194124208Sdes goto fail; 195124208Sdes } 196124208Sdes 197124208Sdes /* don't allow queries of class or type ANY */ 198124208Sdes if (rdclass == 0xff || rdtype == 0xff) { 199124208Sdes result = ERRSET_INVAL; 200124208Sdes goto fail; 201124208Sdes } 202124208Sdes 203124208Sdes /* don't allow flags yet, unimplemented */ 204124208Sdes if (flags) { 205124208Sdes result = ERRSET_INVAL; 206124208Sdes goto fail; 207124208Sdes } 208124208Sdes 209124208Sdes /* initialize resolver */ 210157016Sdes if ((_resp->options & RES_INIT) == 0 && res_init() == -1) { 211124208Sdes result = ERRSET_FAIL; 212124208Sdes goto fail; 213124208Sdes } 214124208Sdes 215124208Sdes#ifdef DEBUG 216157016Sdes _resp->options |= RES_DEBUG; 217124208Sdes#endif /* DEBUG */ 218124208Sdes 219124208Sdes#ifdef RES_USE_DNSSEC 220124208Sdes /* turn on DNSSEC if EDNS0 is configured */ 221157016Sdes if (_resp->options & RES_USE_EDNS0) 222157016Sdes _resp->options |= RES_USE_DNSSEC; 223124208Sdes#endif /* RES_USE_DNSEC */ 224124208Sdes 225124208Sdes /* make query */ 226124208Sdes length = res_query(hostname, (signed int) rdclass, (signed int) rdtype, 227124208Sdes answer, sizeof(answer)); 228124208Sdes if (length < 0) { 229124208Sdes switch(h_errno) { 230124208Sdes case HOST_NOT_FOUND: 231124208Sdes result = ERRSET_NONAME; 232124208Sdes goto fail; 233124208Sdes case NO_DATA: 234124208Sdes result = ERRSET_NODATA; 235124208Sdes goto fail; 236124208Sdes default: 237124208Sdes result = ERRSET_FAIL; 238124208Sdes goto fail; 239124208Sdes } 240124208Sdes } 241124208Sdes 242124208Sdes /* parse result */ 243124208Sdes response = parse_dns_response(answer, length); 244124208Sdes if (response == NULL) { 245124208Sdes result = ERRSET_FAIL; 246124208Sdes goto fail; 247124208Sdes } 248124208Sdes 249124208Sdes if (response->header.qdcount != 1) { 250124208Sdes result = ERRSET_FAIL; 251124208Sdes goto fail; 252124208Sdes } 253124208Sdes 254124208Sdes /* initialize rrset */ 255124208Sdes rrset = calloc(1, sizeof(struct rrsetinfo)); 256124208Sdes if (rrset == NULL) { 257124208Sdes result = ERRSET_NOMEMORY; 258124208Sdes goto fail; 259124208Sdes } 260124208Sdes rrset->rri_rdclass = response->query->class; 261124208Sdes rrset->rri_rdtype = response->query->type; 262124208Sdes rrset->rri_ttl = response->answer->ttl; 263124208Sdes rrset->rri_nrdatas = response->header.ancount; 264124208Sdes 265124208Sdes#ifdef HAVE_HEADER_AD 266124208Sdes /* check for authenticated data */ 267124208Sdes if (response->header.ad == 1) 268124208Sdes rrset->rri_flags |= RRSET_VALIDATED; 269124208Sdes#endif 270124208Sdes 271124208Sdes /* copy name from answer section */ 272157016Sdes rrset->rri_name = strdup(response->answer->name); 273124208Sdes if (rrset->rri_name == NULL) { 274124208Sdes result = ERRSET_NOMEMORY; 275124208Sdes goto fail; 276124208Sdes } 277124208Sdes 278124208Sdes /* count answers */ 279124208Sdes rrset->rri_nrdatas = count_dns_rr(response->answer, rrset->rri_rdclass, 280124208Sdes rrset->rri_rdtype); 281124208Sdes rrset->rri_nsigs = count_dns_rr(response->answer, rrset->rri_rdclass, 282124208Sdes T_SIG); 283124208Sdes 284124208Sdes /* allocate memory for answers */ 285124208Sdes rrset->rri_rdatas = calloc(rrset->rri_nrdatas, 286124208Sdes sizeof(struct rdatainfo)); 287124208Sdes if (rrset->rri_rdatas == NULL) { 288124208Sdes result = ERRSET_NOMEMORY; 289124208Sdes goto fail; 290124208Sdes } 291124208Sdes 292124208Sdes /* allocate memory for signatures */ 293124208Sdes rrset->rri_sigs = calloc(rrset->rri_nsigs, sizeof(struct rdatainfo)); 294157016Sdes if (rrset->rri_sigs == NULL) { 295124208Sdes result = ERRSET_NOMEMORY; 296124208Sdes goto fail; 297124208Sdes } 298124208Sdes 299124208Sdes /* copy answers & signatures */ 300124208Sdes for (rr = response->answer, index_ans = 0, index_sig = 0; 301124208Sdes rr; rr = rr->next) { 302124208Sdes 303124208Sdes rdata = NULL; 304124208Sdes 305124208Sdes if (rr->class == rrset->rri_rdclass && 306124208Sdes rr->type == rrset->rri_rdtype) 307124208Sdes rdata = &rrset->rri_rdatas[index_ans++]; 308124208Sdes 309124208Sdes if (rr->class == rrset->rri_rdclass && 310124208Sdes rr->type == T_SIG) 311124208Sdes rdata = &rrset->rri_sigs[index_sig++]; 312124208Sdes 313124208Sdes if (rdata) { 314124208Sdes rdata->rdi_length = rr->size; 315124208Sdes rdata->rdi_data = malloc(rr->size); 316124208Sdes 317124208Sdes if (rdata->rdi_data == NULL) { 318124208Sdes result = ERRSET_NOMEMORY; 319124208Sdes goto fail; 320124208Sdes } 321124208Sdes memcpy(rdata->rdi_data, rr->rdata, rr->size); 322124208Sdes } 323124208Sdes } 324157016Sdes free_dns_response(response); 325124208Sdes 326124208Sdes *res = rrset; 327124208Sdes return (ERRSET_SUCCESS); 328124208Sdes 329124208Sdesfail: 330124208Sdes if (rrset != NULL) 331124208Sdes freerrset(rrset); 332157016Sdes if (response != NULL) 333157016Sdes free_dns_response(response); 334124208Sdes return (result); 335124208Sdes} 336124208Sdes 337124208Sdesvoid 338124208Sdesfreerrset(struct rrsetinfo *rrset) 339124208Sdes{ 340124208Sdes u_int16_t i; 341124208Sdes 342124208Sdes if (rrset == NULL) 343124208Sdes return; 344124208Sdes 345124208Sdes if (rrset->rri_rdatas) { 346124208Sdes for (i = 0; i < rrset->rri_nrdatas; i++) { 347124208Sdes if (rrset->rri_rdatas[i].rdi_data == NULL) 348124208Sdes break; 349124208Sdes free(rrset->rri_rdatas[i].rdi_data); 350124208Sdes } 351124208Sdes free(rrset->rri_rdatas); 352124208Sdes } 353124208Sdes 354124208Sdes if (rrset->rri_sigs) { 355124208Sdes for (i = 0; i < rrset->rri_nsigs; i++) { 356124208Sdes if (rrset->rri_sigs[i].rdi_data == NULL) 357124208Sdes break; 358124208Sdes free(rrset->rri_sigs[i].rdi_data); 359124208Sdes } 360124208Sdes free(rrset->rri_sigs); 361124208Sdes } 362124208Sdes 363124208Sdes if (rrset->rri_name) 364124208Sdes free(rrset->rri_name); 365124208Sdes free(rrset); 366124208Sdes} 367124208Sdes 368124208Sdes/* 369124208Sdes * DNS response parsing routines 370124208Sdes */ 371124208Sdesstatic struct dns_response * 372124208Sdesparse_dns_response(const u_char *answer, int size) 373124208Sdes{ 374124208Sdes struct dns_response *resp; 375124208Sdes const u_char *cp; 376124208Sdes 377124208Sdes /* allocate memory for the response */ 378124208Sdes resp = calloc(1, sizeof(*resp)); 379124208Sdes if (resp == NULL) 380124208Sdes return (NULL); 381124208Sdes 382124208Sdes /* initialize current pointer */ 383124208Sdes cp = answer; 384124208Sdes 385124208Sdes /* copy header */ 386124208Sdes memcpy(&resp->header, cp, HFIXEDSZ); 387124208Sdes cp += HFIXEDSZ; 388124208Sdes 389124208Sdes /* fix header byte order */ 390124208Sdes resp->header.qdcount = ntohs(resp->header.qdcount); 391124208Sdes resp->header.ancount = ntohs(resp->header.ancount); 392124208Sdes resp->header.nscount = ntohs(resp->header.nscount); 393124208Sdes resp->header.arcount = ntohs(resp->header.arcount); 394124208Sdes 395124208Sdes /* there must be at least one query */ 396124208Sdes if (resp->header.qdcount < 1) { 397124208Sdes free_dns_response(resp); 398124208Sdes return (NULL); 399124208Sdes } 400124208Sdes 401124208Sdes /* parse query section */ 402124208Sdes resp->query = parse_dns_qsection(answer, size, &cp, 403124208Sdes resp->header.qdcount); 404124208Sdes if (resp->header.qdcount && resp->query == NULL) { 405124208Sdes free_dns_response(resp); 406124208Sdes return (NULL); 407124208Sdes } 408124208Sdes 409124208Sdes /* parse answer section */ 410124208Sdes resp->answer = parse_dns_rrsection(answer, size, &cp, 411124208Sdes resp->header.ancount); 412124208Sdes if (resp->header.ancount && resp->answer == NULL) { 413124208Sdes free_dns_response(resp); 414124208Sdes return (NULL); 415124208Sdes } 416124208Sdes 417124208Sdes /* parse authority section */ 418124208Sdes resp->authority = parse_dns_rrsection(answer, size, &cp, 419124208Sdes resp->header.nscount); 420124208Sdes if (resp->header.nscount && resp->authority == NULL) { 421124208Sdes free_dns_response(resp); 422124208Sdes return (NULL); 423124208Sdes } 424124208Sdes 425124208Sdes /* parse additional section */ 426124208Sdes resp->additional = parse_dns_rrsection(answer, size, &cp, 427124208Sdes resp->header.arcount); 428124208Sdes if (resp->header.arcount && resp->additional == NULL) { 429124208Sdes free_dns_response(resp); 430124208Sdes return (NULL); 431124208Sdes } 432124208Sdes 433124208Sdes return (resp); 434124208Sdes} 435124208Sdes 436124208Sdesstatic struct dns_query * 437124208Sdesparse_dns_qsection(const u_char *answer, int size, const u_char **cp, int count) 438124208Sdes{ 439124208Sdes struct dns_query *head, *curr, *prev; 440124208Sdes int i, length; 441124208Sdes char name[MAXDNAME]; 442124208Sdes 443124208Sdes for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) { 444124208Sdes 445124208Sdes /* allocate and initialize struct */ 446124208Sdes curr = calloc(1, sizeof(struct dns_query)); 447124208Sdes if (curr == NULL) { 448124208Sdes free_dns_query(head); 449124208Sdes return (NULL); 450124208Sdes } 451124208Sdes if (head == NULL) 452124208Sdes head = curr; 453124208Sdes if (prev != NULL) 454124208Sdes prev->next = curr; 455124208Sdes 456124208Sdes /* name */ 457124208Sdes length = dn_expand(answer, answer + size, *cp, name, 458124208Sdes sizeof(name)); 459124208Sdes if (length < 0) { 460124208Sdes free_dns_query(head); 461124208Sdes return (NULL); 462124208Sdes } 463124208Sdes curr->name = strdup(name); 464124208Sdes if (curr->name == NULL) { 465124208Sdes free_dns_query(head); 466124208Sdes return (NULL); 467124208Sdes } 468124208Sdes *cp += length; 469124208Sdes 470124208Sdes /* type */ 471124208Sdes curr->type = _getshort(*cp); 472124208Sdes *cp += INT16SZ; 473124208Sdes 474124208Sdes /* class */ 475124208Sdes curr->class = _getshort(*cp); 476124208Sdes *cp += INT16SZ; 477124208Sdes } 478124208Sdes 479124208Sdes return (head); 480124208Sdes} 481124208Sdes 482124208Sdesstatic struct dns_rr * 483157016Sdesparse_dns_rrsection(const u_char *answer, int size, const u_char **cp, 484157016Sdes int count) 485124208Sdes{ 486124208Sdes struct dns_rr *head, *curr, *prev; 487124208Sdes int i, length; 488124208Sdes char name[MAXDNAME]; 489124208Sdes 490124208Sdes for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) { 491124208Sdes 492124208Sdes /* allocate and initialize struct */ 493124208Sdes curr = calloc(1, sizeof(struct dns_rr)); 494124208Sdes if (curr == NULL) { 495124208Sdes free_dns_rr(head); 496124208Sdes return (NULL); 497124208Sdes } 498124208Sdes if (head == NULL) 499124208Sdes head = curr; 500124208Sdes if (prev != NULL) 501124208Sdes prev->next = curr; 502124208Sdes 503124208Sdes /* name */ 504124208Sdes length = dn_expand(answer, answer + size, *cp, name, 505124208Sdes sizeof(name)); 506124208Sdes if (length < 0) { 507124208Sdes free_dns_rr(head); 508124208Sdes return (NULL); 509124208Sdes } 510124208Sdes curr->name = strdup(name); 511124208Sdes if (curr->name == NULL) { 512124208Sdes free_dns_rr(head); 513124208Sdes return (NULL); 514124208Sdes } 515124208Sdes *cp += length; 516124208Sdes 517124208Sdes /* type */ 518124208Sdes curr->type = _getshort(*cp); 519124208Sdes *cp += INT16SZ; 520124208Sdes 521124208Sdes /* class */ 522124208Sdes curr->class = _getshort(*cp); 523124208Sdes *cp += INT16SZ; 524124208Sdes 525124208Sdes /* ttl */ 526124208Sdes curr->ttl = _getlong(*cp); 527124208Sdes *cp += INT32SZ; 528124208Sdes 529124208Sdes /* rdata size */ 530124208Sdes curr->size = _getshort(*cp); 531124208Sdes *cp += INT16SZ; 532124208Sdes 533124208Sdes /* rdata itself */ 534124208Sdes curr->rdata = malloc(curr->size); 535124208Sdes if (curr->rdata == NULL) { 536124208Sdes free_dns_rr(head); 537124208Sdes return (NULL); 538124208Sdes } 539124208Sdes memcpy(curr->rdata, *cp, curr->size); 540124208Sdes *cp += curr->size; 541124208Sdes } 542124208Sdes 543124208Sdes return (head); 544124208Sdes} 545124208Sdes 546124208Sdesstatic void 547124208Sdesfree_dns_query(struct dns_query *p) 548124208Sdes{ 549124208Sdes if (p == NULL) 550124208Sdes return; 551124208Sdes 552124208Sdes if (p->name) 553124208Sdes free(p->name); 554124208Sdes free_dns_query(p->next); 555124208Sdes free(p); 556124208Sdes} 557124208Sdes 558124208Sdesstatic void 559124208Sdesfree_dns_rr(struct dns_rr *p) 560124208Sdes{ 561124208Sdes if (p == NULL) 562124208Sdes return; 563124208Sdes 564124208Sdes if (p->name) 565124208Sdes free(p->name); 566124208Sdes if (p->rdata) 567124208Sdes free(p->rdata); 568124208Sdes free_dns_rr(p->next); 569124208Sdes free(p); 570124208Sdes} 571124208Sdes 572124208Sdesstatic void 573124208Sdesfree_dns_response(struct dns_response *p) 574124208Sdes{ 575124208Sdes if (p == NULL) 576124208Sdes return; 577124208Sdes 578124208Sdes free_dns_query(p->query); 579124208Sdes free_dns_rr(p->answer); 580124208Sdes free_dns_rr(p->authority); 581124208Sdes free_dns_rr(p->additional); 582124208Sdes free(p); 583124208Sdes} 584124208Sdes 585124208Sdesstatic int 586124208Sdescount_dns_rr(struct dns_rr *p, u_int16_t class, u_int16_t type) 587124208Sdes{ 588124208Sdes int n = 0; 589124208Sdes 590124208Sdes while(p) { 591124208Sdes if (p->class == class && p->type == type) 592124208Sdes n++; 593124208Sdes p = p->next; 594124208Sdes } 595124208Sdes 596124208Sdes return (n); 597124208Sdes} 598124208Sdes 599126274Sdes#endif /* !defined(HAVE_GETRRSETBYNAME) */ 600