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