1181111Sdes/* $OpenBSD: getrrsetbyname.c,v 1.11 2007/10/11 18:36:41 jakob 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 50240075Sdes#if !defined (HAVE_GETRRSETBYNAME) && !defined (HAVE_LDNS) 51124208Sdes 52162852Sdes#include <stdlib.h> 53162852Sdes#include <string.h> 54162852Sdes 55162852Sdes#include <netinet/in.h> 56162852Sdes#include <arpa/inet.h> 57162852Sdes 58124208Sdes#include "getrrsetbyname.h" 59124208Sdes 60137015Sdes#if defined(HAVE_DECL_H_ERRNO) && !HAVE_DECL_H_ERRNO 61137015Sdesextern int h_errno; 62137015Sdes#endif 63137015Sdes 64157016Sdes/* We don't need multithread support here */ 65157016Sdes#ifdef _THREAD_PRIVATE 66157016Sdes# undef _THREAD_PRIVATE 67157016Sdes#endif 68157016Sdes#define _THREAD_PRIVATE(a,b,c) (c) 69162852Sdes 70181111Sdes#ifndef HAVE__RES_EXTERN 71181111Sdesstruct __res_state _res; 72162852Sdes#endif 73162852Sdes 74157016Sdes/* Necessary functions and macros */ 75124208Sdes 76124208Sdes/* 77124208Sdes * Inline versions of get/put short/long. Pointer is advanced. 78124208Sdes * 79124208Sdes * These macros demonstrate the property of C whereby it can be 80124208Sdes * portable or it can be elegant but rarely both. 81124208Sdes */ 82124208Sdes 83124208Sdes#ifndef INT32SZ 84124208Sdes# define INT32SZ 4 85124208Sdes#endif 86124208Sdes#ifndef INT16SZ 87124208Sdes# define INT16SZ 2 88124208Sdes#endif 89124208Sdes 90124208Sdes#ifndef GETSHORT 91124208Sdes#define GETSHORT(s, cp) { \ 92124208Sdes register u_char *t_cp = (u_char *)(cp); \ 93124208Sdes (s) = ((u_int16_t)t_cp[0] << 8) \ 94124208Sdes | ((u_int16_t)t_cp[1]) \ 95124208Sdes ; \ 96124208Sdes (cp) += INT16SZ; \ 97124208Sdes} 98124208Sdes#endif 99124208Sdes 100124208Sdes#ifndef GETLONG 101124208Sdes#define GETLONG(l, cp) { \ 102124208Sdes register u_char *t_cp = (u_char *)(cp); \ 103124208Sdes (l) = ((u_int32_t)t_cp[0] << 24) \ 104124208Sdes | ((u_int32_t)t_cp[1] << 16) \ 105124208Sdes | ((u_int32_t)t_cp[2] << 8) \ 106124208Sdes | ((u_int32_t)t_cp[3]) \ 107124208Sdes ; \ 108124208Sdes (cp) += INT32SZ; \ 109124208Sdes} 110124208Sdes#endif 111124208Sdes 112124208Sdes/* 113124208Sdes * Routines to insert/extract short/long's. 114124208Sdes */ 115124208Sdes 116124208Sdes#ifndef HAVE__GETSHORT 117124208Sdesstatic u_int16_t 118124208Sdes_getshort(msgp) 119124208Sdes register const u_char *msgp; 120124208Sdes{ 121124208Sdes register u_int16_t u; 122124208Sdes 123124208Sdes GETSHORT(u, msgp); 124124208Sdes return (u); 125124208Sdes} 126149749Sdes#elif defined(HAVE_DECL__GETSHORT) && (HAVE_DECL__GETSHORT == 0) 127149749Sdesu_int16_t _getshort(register const u_char *); 128124208Sdes#endif 129124208Sdes 130124208Sdes#ifndef HAVE__GETLONG 131124208Sdesstatic u_int32_t 132124208Sdes_getlong(msgp) 133124208Sdes register const u_char *msgp; 134124208Sdes{ 135124208Sdes register u_int32_t u; 136124208Sdes 137124208Sdes GETLONG(u, msgp); 138124208Sdes return (u); 139124208Sdes} 140149749Sdes#elif defined(HAVE_DECL__GETLONG) && (HAVE_DECL__GETLONG == 0) 141149749Sdesu_int32_t _getlong(register const u_char *); 142124208Sdes#endif 143124208Sdes 144157016Sdes/* ************** */ 145157016Sdes 146197679Sdes#define ANSWER_BUFFER_SIZE 0xffff 147157016Sdes 148157016Sdesstruct dns_query { 149157016Sdes char *name; 150157016Sdes u_int16_t type; 151157016Sdes u_int16_t class; 152157016Sdes struct dns_query *next; 153157016Sdes}; 154157016Sdes 155157016Sdesstruct dns_rr { 156157016Sdes char *name; 157157016Sdes u_int16_t type; 158157016Sdes u_int16_t class; 159157016Sdes u_int16_t ttl; 160157016Sdes u_int16_t size; 161157016Sdes void *rdata; 162157016Sdes struct dns_rr *next; 163157016Sdes}; 164157016Sdes 165157016Sdesstruct dns_response { 166157016Sdes HEADER header; 167157016Sdes struct dns_query *query; 168157016Sdes struct dns_rr *answer; 169157016Sdes struct dns_rr *authority; 170157016Sdes struct dns_rr *additional; 171157016Sdes}; 172157016Sdes 173157016Sdesstatic struct dns_response *parse_dns_response(const u_char *, int); 174157016Sdesstatic struct dns_query *parse_dns_qsection(const u_char *, int, 175157016Sdes const u_char **, int); 176157016Sdesstatic struct dns_rr *parse_dns_rrsection(const u_char *, int, const u_char **, 177157016Sdes int); 178157016Sdes 179157016Sdesstatic void free_dns_query(struct dns_query *); 180157016Sdesstatic void free_dns_rr(struct dns_rr *); 181157016Sdesstatic void free_dns_response(struct dns_response *); 182157016Sdes 183157016Sdesstatic int count_dns_rr(struct dns_rr *, u_int16_t, u_int16_t); 184157016Sdes 185124208Sdesint 186124208Sdesgetrrsetbyname(const char *hostname, unsigned int rdclass, 187124208Sdes unsigned int rdtype, unsigned int flags, 188124208Sdes struct rrsetinfo **res) 189124208Sdes{ 190157016Sdes struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res); 191124208Sdes int result; 192124208Sdes struct rrsetinfo *rrset = NULL; 193157016Sdes struct dns_response *response = NULL; 194124208Sdes struct dns_rr *rr; 195124208Sdes struct rdatainfo *rdata; 196124208Sdes int length; 197124208Sdes unsigned int index_ans, index_sig; 198124208Sdes u_char answer[ANSWER_BUFFER_SIZE]; 199124208Sdes 200124208Sdes /* check for invalid class and type */ 201124208Sdes if (rdclass > 0xffff || rdtype > 0xffff) { 202124208Sdes result = ERRSET_INVAL; 203124208Sdes goto fail; 204124208Sdes } 205124208Sdes 206124208Sdes /* don't allow queries of class or type ANY */ 207124208Sdes if (rdclass == 0xff || rdtype == 0xff) { 208124208Sdes result = ERRSET_INVAL; 209124208Sdes goto fail; 210124208Sdes } 211124208Sdes 212124208Sdes /* don't allow flags yet, unimplemented */ 213124208Sdes if (flags) { 214124208Sdes result = ERRSET_INVAL; 215124208Sdes goto fail; 216124208Sdes } 217124208Sdes 218124208Sdes /* initialize resolver */ 219157016Sdes if ((_resp->options & RES_INIT) == 0 && res_init() == -1) { 220124208Sdes result = ERRSET_FAIL; 221124208Sdes goto fail; 222124208Sdes } 223124208Sdes 224124208Sdes#ifdef DEBUG 225157016Sdes _resp->options |= RES_DEBUG; 226124208Sdes#endif /* DEBUG */ 227124208Sdes 228124208Sdes#ifdef RES_USE_DNSSEC 229124208Sdes /* turn on DNSSEC if EDNS0 is configured */ 230157016Sdes if (_resp->options & RES_USE_EDNS0) 231157016Sdes _resp->options |= RES_USE_DNSSEC; 232124208Sdes#endif /* RES_USE_DNSEC */ 233124208Sdes 234124208Sdes /* make query */ 235124208Sdes length = res_query(hostname, (signed int) rdclass, (signed int) rdtype, 236124208Sdes answer, sizeof(answer)); 237124208Sdes if (length < 0) { 238124208Sdes switch(h_errno) { 239124208Sdes case HOST_NOT_FOUND: 240124208Sdes result = ERRSET_NONAME; 241124208Sdes goto fail; 242124208Sdes case NO_DATA: 243124208Sdes result = ERRSET_NODATA; 244124208Sdes goto fail; 245124208Sdes default: 246124208Sdes result = ERRSET_FAIL; 247124208Sdes goto fail; 248124208Sdes } 249124208Sdes } 250124208Sdes 251124208Sdes /* parse result */ 252124208Sdes response = parse_dns_response(answer, length); 253124208Sdes if (response == NULL) { 254124208Sdes result = ERRSET_FAIL; 255124208Sdes goto fail; 256124208Sdes } 257124208Sdes 258124208Sdes if (response->header.qdcount != 1) { 259124208Sdes result = ERRSET_FAIL; 260124208Sdes goto fail; 261124208Sdes } 262124208Sdes 263124208Sdes /* initialize rrset */ 264124208Sdes rrset = calloc(1, sizeof(struct rrsetinfo)); 265124208Sdes if (rrset == NULL) { 266124208Sdes result = ERRSET_NOMEMORY; 267124208Sdes goto fail; 268124208Sdes } 269124208Sdes rrset->rri_rdclass = response->query->class; 270124208Sdes rrset->rri_rdtype = response->query->type; 271124208Sdes rrset->rri_ttl = response->answer->ttl; 272124208Sdes rrset->rri_nrdatas = response->header.ancount; 273124208Sdes 274124208Sdes#ifdef HAVE_HEADER_AD 275124208Sdes /* check for authenticated data */ 276124208Sdes if (response->header.ad == 1) 277124208Sdes rrset->rri_flags |= RRSET_VALIDATED; 278124208Sdes#endif 279124208Sdes 280124208Sdes /* copy name from answer section */ 281157016Sdes rrset->rri_name = strdup(response->answer->name); 282124208Sdes if (rrset->rri_name == NULL) { 283124208Sdes result = ERRSET_NOMEMORY; 284124208Sdes goto fail; 285124208Sdes } 286124208Sdes 287124208Sdes /* count answers */ 288124208Sdes rrset->rri_nrdatas = count_dns_rr(response->answer, rrset->rri_rdclass, 289124208Sdes rrset->rri_rdtype); 290124208Sdes rrset->rri_nsigs = count_dns_rr(response->answer, rrset->rri_rdclass, 291181111Sdes T_RRSIG); 292124208Sdes 293124208Sdes /* allocate memory for answers */ 294124208Sdes rrset->rri_rdatas = calloc(rrset->rri_nrdatas, 295124208Sdes sizeof(struct rdatainfo)); 296124208Sdes if (rrset->rri_rdatas == NULL) { 297124208Sdes result = ERRSET_NOMEMORY; 298124208Sdes goto fail; 299124208Sdes } 300124208Sdes 301124208Sdes /* allocate memory for signatures */ 302181111Sdes if (rrset->rri_nsigs > 0) { 303181111Sdes rrset->rri_sigs = calloc(rrset->rri_nsigs, sizeof(struct rdatainfo)); 304181111Sdes if (rrset->rri_sigs == NULL) { 305181111Sdes result = ERRSET_NOMEMORY; 306181111Sdes goto fail; 307181111Sdes } 308124208Sdes } 309124208Sdes 310124208Sdes /* copy answers & signatures */ 311124208Sdes for (rr = response->answer, index_ans = 0, index_sig = 0; 312124208Sdes rr; rr = rr->next) { 313124208Sdes 314124208Sdes rdata = NULL; 315124208Sdes 316124208Sdes if (rr->class == rrset->rri_rdclass && 317124208Sdes rr->type == rrset->rri_rdtype) 318124208Sdes rdata = &rrset->rri_rdatas[index_ans++]; 319124208Sdes 320124208Sdes if (rr->class == rrset->rri_rdclass && 321181111Sdes rr->type == T_RRSIG) 322124208Sdes rdata = &rrset->rri_sigs[index_sig++]; 323124208Sdes 324124208Sdes if (rdata) { 325124208Sdes rdata->rdi_length = rr->size; 326124208Sdes rdata->rdi_data = malloc(rr->size); 327124208Sdes 328124208Sdes if (rdata->rdi_data == NULL) { 329124208Sdes result = ERRSET_NOMEMORY; 330124208Sdes goto fail; 331124208Sdes } 332124208Sdes memcpy(rdata->rdi_data, rr->rdata, rr->size); 333124208Sdes } 334124208Sdes } 335157016Sdes free_dns_response(response); 336124208Sdes 337124208Sdes *res = rrset; 338124208Sdes return (ERRSET_SUCCESS); 339124208Sdes 340124208Sdesfail: 341124208Sdes if (rrset != NULL) 342124208Sdes freerrset(rrset); 343157016Sdes if (response != NULL) 344157016Sdes free_dns_response(response); 345124208Sdes return (result); 346124208Sdes} 347124208Sdes 348124208Sdesvoid 349124208Sdesfreerrset(struct rrsetinfo *rrset) 350124208Sdes{ 351124208Sdes u_int16_t i; 352124208Sdes 353124208Sdes if (rrset == NULL) 354124208Sdes return; 355124208Sdes 356124208Sdes if (rrset->rri_rdatas) { 357124208Sdes for (i = 0; i < rrset->rri_nrdatas; i++) { 358124208Sdes if (rrset->rri_rdatas[i].rdi_data == NULL) 359124208Sdes break; 360124208Sdes free(rrset->rri_rdatas[i].rdi_data); 361124208Sdes } 362124208Sdes free(rrset->rri_rdatas); 363124208Sdes } 364124208Sdes 365124208Sdes if (rrset->rri_sigs) { 366124208Sdes for (i = 0; i < rrset->rri_nsigs; i++) { 367124208Sdes if (rrset->rri_sigs[i].rdi_data == NULL) 368124208Sdes break; 369124208Sdes free(rrset->rri_sigs[i].rdi_data); 370124208Sdes } 371124208Sdes free(rrset->rri_sigs); 372124208Sdes } 373124208Sdes 374124208Sdes if (rrset->rri_name) 375124208Sdes free(rrset->rri_name); 376124208Sdes free(rrset); 377124208Sdes} 378124208Sdes 379124208Sdes/* 380124208Sdes * DNS response parsing routines 381124208Sdes */ 382124208Sdesstatic struct dns_response * 383124208Sdesparse_dns_response(const u_char *answer, int size) 384124208Sdes{ 385124208Sdes struct dns_response *resp; 386124208Sdes const u_char *cp; 387124208Sdes 388124208Sdes /* allocate memory for the response */ 389124208Sdes resp = calloc(1, sizeof(*resp)); 390124208Sdes if (resp == NULL) 391124208Sdes return (NULL); 392124208Sdes 393124208Sdes /* initialize current pointer */ 394124208Sdes cp = answer; 395124208Sdes 396124208Sdes /* copy header */ 397124208Sdes memcpy(&resp->header, cp, HFIXEDSZ); 398124208Sdes cp += HFIXEDSZ; 399124208Sdes 400124208Sdes /* fix header byte order */ 401124208Sdes resp->header.qdcount = ntohs(resp->header.qdcount); 402124208Sdes resp->header.ancount = ntohs(resp->header.ancount); 403124208Sdes resp->header.nscount = ntohs(resp->header.nscount); 404124208Sdes resp->header.arcount = ntohs(resp->header.arcount); 405124208Sdes 406124208Sdes /* there must be at least one query */ 407124208Sdes if (resp->header.qdcount < 1) { 408124208Sdes free_dns_response(resp); 409124208Sdes return (NULL); 410124208Sdes } 411124208Sdes 412124208Sdes /* parse query section */ 413124208Sdes resp->query = parse_dns_qsection(answer, size, &cp, 414124208Sdes resp->header.qdcount); 415124208Sdes if (resp->header.qdcount && resp->query == NULL) { 416124208Sdes free_dns_response(resp); 417124208Sdes return (NULL); 418124208Sdes } 419124208Sdes 420124208Sdes /* parse answer section */ 421124208Sdes resp->answer = parse_dns_rrsection(answer, size, &cp, 422124208Sdes resp->header.ancount); 423124208Sdes if (resp->header.ancount && resp->answer == NULL) { 424124208Sdes free_dns_response(resp); 425124208Sdes return (NULL); 426124208Sdes } 427124208Sdes 428124208Sdes /* parse authority section */ 429124208Sdes resp->authority = parse_dns_rrsection(answer, size, &cp, 430124208Sdes resp->header.nscount); 431124208Sdes if (resp->header.nscount && resp->authority == NULL) { 432124208Sdes free_dns_response(resp); 433124208Sdes return (NULL); 434124208Sdes } 435124208Sdes 436124208Sdes /* parse additional section */ 437124208Sdes resp->additional = parse_dns_rrsection(answer, size, &cp, 438124208Sdes resp->header.arcount); 439124208Sdes if (resp->header.arcount && resp->additional == NULL) { 440124208Sdes free_dns_response(resp); 441124208Sdes return (NULL); 442124208Sdes } 443124208Sdes 444124208Sdes return (resp); 445124208Sdes} 446124208Sdes 447124208Sdesstatic struct dns_query * 448124208Sdesparse_dns_qsection(const u_char *answer, int size, const u_char **cp, int count) 449124208Sdes{ 450124208Sdes struct dns_query *head, *curr, *prev; 451124208Sdes int i, length; 452124208Sdes char name[MAXDNAME]; 453124208Sdes 454124208Sdes for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) { 455124208Sdes 456124208Sdes /* allocate and initialize struct */ 457124208Sdes curr = calloc(1, sizeof(struct dns_query)); 458124208Sdes if (curr == NULL) { 459124208Sdes free_dns_query(head); 460124208Sdes return (NULL); 461124208Sdes } 462124208Sdes if (head == NULL) 463124208Sdes head = curr; 464124208Sdes if (prev != NULL) 465124208Sdes prev->next = curr; 466124208Sdes 467124208Sdes /* name */ 468124208Sdes length = dn_expand(answer, answer + size, *cp, name, 469124208Sdes sizeof(name)); 470124208Sdes if (length < 0) { 471124208Sdes free_dns_query(head); 472124208Sdes return (NULL); 473124208Sdes } 474124208Sdes curr->name = strdup(name); 475124208Sdes if (curr->name == NULL) { 476124208Sdes free_dns_query(head); 477124208Sdes return (NULL); 478124208Sdes } 479124208Sdes *cp += length; 480124208Sdes 481124208Sdes /* type */ 482124208Sdes curr->type = _getshort(*cp); 483124208Sdes *cp += INT16SZ; 484124208Sdes 485124208Sdes /* class */ 486124208Sdes curr->class = _getshort(*cp); 487124208Sdes *cp += INT16SZ; 488124208Sdes } 489124208Sdes 490124208Sdes return (head); 491124208Sdes} 492124208Sdes 493124208Sdesstatic struct dns_rr * 494157016Sdesparse_dns_rrsection(const u_char *answer, int size, const u_char **cp, 495157016Sdes int count) 496124208Sdes{ 497124208Sdes struct dns_rr *head, *curr, *prev; 498124208Sdes int i, length; 499124208Sdes char name[MAXDNAME]; 500124208Sdes 501124208Sdes for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) { 502124208Sdes 503124208Sdes /* allocate and initialize struct */ 504124208Sdes curr = calloc(1, sizeof(struct dns_rr)); 505124208Sdes if (curr == NULL) { 506124208Sdes free_dns_rr(head); 507124208Sdes return (NULL); 508124208Sdes } 509124208Sdes if (head == NULL) 510124208Sdes head = curr; 511124208Sdes if (prev != NULL) 512124208Sdes prev->next = curr; 513124208Sdes 514124208Sdes /* name */ 515124208Sdes length = dn_expand(answer, answer + size, *cp, name, 516124208Sdes sizeof(name)); 517124208Sdes if (length < 0) { 518124208Sdes free_dns_rr(head); 519124208Sdes return (NULL); 520124208Sdes } 521124208Sdes curr->name = strdup(name); 522124208Sdes if (curr->name == NULL) { 523124208Sdes free_dns_rr(head); 524124208Sdes return (NULL); 525124208Sdes } 526124208Sdes *cp += length; 527124208Sdes 528124208Sdes /* type */ 529124208Sdes curr->type = _getshort(*cp); 530124208Sdes *cp += INT16SZ; 531124208Sdes 532124208Sdes /* class */ 533124208Sdes curr->class = _getshort(*cp); 534124208Sdes *cp += INT16SZ; 535124208Sdes 536124208Sdes /* ttl */ 537124208Sdes curr->ttl = _getlong(*cp); 538124208Sdes *cp += INT32SZ; 539124208Sdes 540124208Sdes /* rdata size */ 541124208Sdes curr->size = _getshort(*cp); 542124208Sdes *cp += INT16SZ; 543124208Sdes 544124208Sdes /* rdata itself */ 545124208Sdes curr->rdata = malloc(curr->size); 546124208Sdes if (curr->rdata == NULL) { 547124208Sdes free_dns_rr(head); 548124208Sdes return (NULL); 549124208Sdes } 550124208Sdes memcpy(curr->rdata, *cp, curr->size); 551124208Sdes *cp += curr->size; 552124208Sdes } 553124208Sdes 554124208Sdes return (head); 555124208Sdes} 556124208Sdes 557124208Sdesstatic void 558124208Sdesfree_dns_query(struct dns_query *p) 559124208Sdes{ 560124208Sdes if (p == NULL) 561124208Sdes return; 562124208Sdes 563124208Sdes if (p->name) 564124208Sdes free(p->name); 565124208Sdes free_dns_query(p->next); 566124208Sdes free(p); 567124208Sdes} 568124208Sdes 569124208Sdesstatic void 570124208Sdesfree_dns_rr(struct dns_rr *p) 571124208Sdes{ 572124208Sdes if (p == NULL) 573124208Sdes return; 574124208Sdes 575124208Sdes if (p->name) 576124208Sdes free(p->name); 577124208Sdes if (p->rdata) 578124208Sdes free(p->rdata); 579124208Sdes free_dns_rr(p->next); 580124208Sdes free(p); 581124208Sdes} 582124208Sdes 583124208Sdesstatic void 584124208Sdesfree_dns_response(struct dns_response *p) 585124208Sdes{ 586124208Sdes if (p == NULL) 587124208Sdes return; 588124208Sdes 589124208Sdes free_dns_query(p->query); 590124208Sdes free_dns_rr(p->answer); 591124208Sdes free_dns_rr(p->authority); 592124208Sdes free_dns_rr(p->additional); 593124208Sdes free(p); 594124208Sdes} 595124208Sdes 596124208Sdesstatic int 597124208Sdescount_dns_rr(struct dns_rr *p, u_int16_t class, u_int16_t type) 598124208Sdes{ 599124208Sdes int n = 0; 600124208Sdes 601124208Sdes while(p) { 602124208Sdes if (p->class == class && p->type == type) 603124208Sdes n++; 604124208Sdes p = p->next; 605124208Sdes } 606124208Sdes 607124208Sdes return (n); 608124208Sdes} 609124208Sdes 610240075Sdes#endif /* !defined (HAVE_GETRRSETBYNAME) && !defined (HAVE_LDNS) */ 611