Annotation of embedaddon/dhcp/minires/res_findzonecut.c, revision 1.1
1.1 ! misho 1: #if !defined(lint) && !defined(SABER)
! 2: static const char rcsid[] = "$Id: res_findzonecut.c,v 1.16.786.3 2010-07-27 21:23:34 sar Exp $";
! 3: #endif /* not lint */
! 4:
! 5: /*
! 6: * Copyright (c) 2009-2010 by Internet Systems Consortium, Inc. ("ISC")
! 7: * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
! 8: * Copyright (c) 1999-2003 by Internet Software Consortium
! 9: *
! 10: * Permission to use, copy, modify, and distribute this software for any
! 11: * purpose with or without fee is hereby granted, provided that the above
! 12: * copyright notice and this permission notice appear in all copies.
! 13: *
! 14: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
! 15: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 16: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
! 17: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 18: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 19: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
! 20: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 21: *
! 22: * Internet Systems Consortium, Inc.
! 23: * 950 Charter Street
! 24: * Redwood City, CA 94063
! 25: * <info@isc.org>
! 26: * https://www.isc.org/
! 27: */
! 28:
! 29: /* Import. */
! 30:
! 31: #include <sys/param.h>
! 32: #include <sys/socket.h>
! 33: #include <sys/time.h>
! 34:
! 35: #include <netinet/in.h>
! 36: #include <arpa/inet.h>
! 37:
! 38: #include <errno.h>
! 39: #include <limits.h>
! 40: #include <netdb.h>
! 41: #include <stdarg.h>
! 42: #include <stdio.h>
! 43: #include <stdlib.h>
! 44: #include <string.h>
! 45:
! 46: #include <isc-dhcp/list.h>
! 47:
! 48: #include "minires/minires.h"
! 49: #include "arpa/nameser.h"
! 50:
! 51: /* Data structures. */
! 52:
! 53: typedef struct rr_a {
! 54: ISC_LINK(struct rr_a) link;
! 55: struct in_addr addr;
! 56: } rr_a;
! 57: typedef ISC_LIST(rr_a) rrset_a;
! 58:
! 59: typedef struct rr_ns {
! 60: ISC_LINK(struct rr_ns) link;
! 61: char *name;
! 62: rrset_a addrs;
! 63: } rr_ns;
! 64: typedef ISC_LIST(rr_ns) rrset_ns;
! 65:
! 66: /* Forward. */
! 67:
! 68: static int satisfy(res_state,
! 69: const char *, rrset_ns *, struct in_addr *, int);
! 70: static int add_addrs(res_state, rr_ns *, struct in_addr *, int);
! 71: static isc_result_t get_soa(res_state, const char *, ns_class,
! 72: char *, size_t, char *, size_t,
! 73: rrset_ns *);
! 74: static isc_result_t get_ns(res_state, const char *, ns_class, rrset_ns *);
! 75: static isc_result_t get_glue(res_state, ns_class, rrset_ns *);
! 76: static isc_result_t save_ns(res_state, ns_msg *, ns_sect,
! 77: const char *, ns_class, rrset_ns *);
! 78: static isc_result_t save_a(res_state, ns_msg *, ns_sect,
! 79: const char *, ns_class, rrset_a *);
! 80: static void free_nsrrset(rrset_ns *);
! 81: static void free_nsrr(rrset_ns *, rr_ns *);
! 82: static rr_ns * find_ns(rrset_ns *, const char *);
! 83: static isc_result_t do_query(res_state, const char *, ns_class, ns_type,
! 84: double *, ns_msg *, int *);
! 85:
! 86: /* Public. */
! 87:
! 88: /*
! 89: * int
! 90: * res_findzonecut(res, dname, class, zname, zsize, addrs, naddrs)
! 91: * find enclosing zone for a <dname,class>, and some server addresses
! 92: * parameters:
! 93: * res - resolver context to work within (is modified)
! 94: * dname - domain name whose enclosing zone is desired
! 95: * class - class of dname (and its enclosing zone)
! 96: * zname - found zone name
! 97: * zsize - allocated size of zname
! 98: * addrs - found server addresses
! 99: * naddrs - max number of addrs
! 100: * return values:
! 101: * < 0 - an error occurred (check errno)
! 102: * = 0 - zname is now valid, but addrs[] wasn't changed
! 103: * > 0 - zname is now valid, and return value is number of addrs[] found
! 104: * notes:
! 105: * this function calls res_nsend() which means it depends on correctly
! 106: * functioning recursive nameservers (usually defined in /etc/resolv.conf
! 107: * or its local equivilent).
! 108: *
! 109: * we start by asking for an SOA<dname,class>. if we get one as an
! 110: * answer, that just means <dname,class> is a zone top, which is fine.
! 111: * more than likely we'll be told to go pound sand, in the form of a
! 112: * negative answer.
! 113: *
! 114: * note that we are not prepared to deal with referrals since that would
! 115: * only come from authority servers and our correctly functioning local
! 116: * recursive server would have followed the referral and got us something
! 117: * more definite.
! 118: *
! 119: * if the authority section contains an SOA, this SOA should also be the
! 120: * closest enclosing zone, since any intermediary zone cuts would've been
! 121: * returned as referrals and dealt with by our correctly functioning local
! 122: * recursive name server. but an SOA in the authority section should NOT
! 123: * match our dname (since that would have been returned in the answer
! 124: * section). an authority section SOA has to be "above" our dname.
! 125: *
! 126: * we cannot fail to find an SOA in this way. ultimately we'll return
! 127: * a zname indicating the root zone if that's the closest enclosing zone.
! 128: * however, since authority section SOA's were once optional, it's
! 129: * possible that we'll have to go hunting for the enclosing SOA by
! 130: * ripping labels off the front of our dname -- this is known as "doing
! 131: * it the hard way."
! 132: *
! 133: * ultimately we want some server addresses, which are ideally the ones
! 134: * pertaining to the SOA.MNAME, but only if there is a matching NS RR.
! 135: * so the second phase (after we find an SOA) is to go looking for the
! 136: * NS RRset for that SOA's zone.
! 137: *
! 138: * no answer section processed by this code is allowed to contain CNAME
! 139: * or DNAME RR's. for the SOA query this means we strip a label and
! 140: * keep going. for the NS and A queries this means we just give up.
! 141: */
! 142:
! 143: isc_result_t
! 144: res_findzonecut(res_state statp, const char *dname, ns_class class, int opts,
! 145: char *zname, size_t zsize, struct in_addr *addrs, int naddrs,
! 146: int *count, void *zcookie)
! 147: {
! 148: char mname[NS_MAXDNAME];
! 149: u_long save_pfcode;
! 150: rrset_ns nsrrs;
! 151: int n = 0;
! 152: isc_result_t rcode;
! 153:
! 154: DPRINTF(("START dname='%s' class=%s, zsize=%ld, naddrs=%d",
! 155: dname, p_class(class), (long)zsize, naddrs));
! 156: save_pfcode = statp->pfcode;
! 157: statp->pfcode |= RES_PRF_HEAD2 | RES_PRF_HEAD1 | RES_PRF_HEADX |
! 158: RES_PRF_QUES | RES_PRF_ANS |
! 159: RES_PRF_AUTH | RES_PRF_ADD;
! 160: ISC_LIST_INIT(nsrrs);
! 161:
! 162: DPRINTF (("look for a predefined zone statement"));
! 163: rcode = find_cached_zone (dname, class, zname, zsize,
! 164: addrs, naddrs, &n, zcookie);
! 165: if (rcode == ISC_R_SUCCESS)
! 166: goto done;
! 167:
! 168: DPRINTF(("get the soa, and see if it has enough glue"));
! 169: if ((rcode = get_soa(statp, dname, class, zname, zsize,
! 170: mname, sizeof mname, &nsrrs)) != ISC_R_SUCCESS ||
! 171: ((opts & RES_EXHAUSTIVE) == 0 &&
! 172: (n = satisfy(statp, mname, &nsrrs, addrs, naddrs)) > 0))
! 173: goto done;
! 174:
! 175: DPRINTF(("get the ns rrset and see if it has enough glue"));
! 176: if ((rcode = get_ns(statp, zname, class, &nsrrs)) != ISC_R_SUCCESS ||
! 177: ((opts & RES_EXHAUSTIVE) == 0 &&
! 178: (n = satisfy(statp, mname, &nsrrs, addrs, naddrs)) > 0))
! 179: goto done;
! 180:
! 181: DPRINTF(("get the missing glue and see if it's finally enough"));
! 182: if ((rcode = get_glue(statp, class, &nsrrs)) == ISC_R_SUCCESS)
! 183: n = satisfy(statp, mname, &nsrrs, addrs, naddrs);
! 184:
! 185: /* If we found the zone, cache it. */
! 186: if (n > 0)
! 187: cache_found_zone (class, zname, addrs, n);
! 188: done:
! 189: DPRINTF(("FINISH n=%d (%s)", n, (n < 0) ? strerror(errno) : "OK"));
! 190: free_nsrrset(&nsrrs);
! 191: statp->pfcode = save_pfcode;
! 192: if (count)
! 193: *count = n;
! 194: return rcode;
! 195: }
! 196:
! 197: /* Private. */
! 198:
! 199: static int
! 200: satisfy(res_state statp,
! 201: const char *mname, rrset_ns *nsrrsp, struct in_addr *addrs, int naddrs)
! 202: {
! 203: rr_ns *nsrr;
! 204: int n, x;
! 205:
! 206: n = 0;
! 207: nsrr = find_ns(nsrrsp, mname);
! 208: if (nsrr != NULL) {
! 209: x = add_addrs(statp, nsrr, addrs, naddrs);
! 210: addrs += x;
! 211: naddrs -= x;
! 212: n += x;
! 213: }
! 214: for (nsrr = ISC_LIST_HEAD(*nsrrsp);
! 215: nsrr != NULL && naddrs > 0;
! 216: nsrr = ISC_LIST_NEXT(nsrr, link))
! 217: if (ns_samename(nsrr->name, mname) != 1) {
! 218: x = add_addrs(statp, nsrr, addrs, naddrs);
! 219: addrs += x;
! 220: naddrs -= x;
! 221: n += x;
! 222: }
! 223: DPRINTF(("satisfy(%s): %d", mname, n));
! 224: return (n);
! 225: }
! 226:
! 227: static int
! 228: add_addrs(res_state statp, rr_ns *nsrr, struct in_addr *addrs, int naddrs) {
! 229: rr_a *arr;
! 230: int n = 0;
! 231:
! 232: for (arr = ISC_LIST_HEAD(nsrr->addrs);
! 233: arr != NULL; arr = ISC_LIST_NEXT(arr, link)) {
! 234: if (naddrs <= 0)
! 235: return (0);
! 236: *addrs++ = arr->addr;
! 237: naddrs--;
! 238: n++;
! 239: }
! 240: DPRINTF(("add_addrs: %d", n));
! 241: return (n);
! 242: }
! 243:
! 244: static isc_result_t
! 245: get_soa(res_state statp, const char *dname, ns_class class,
! 246: char *zname, size_t zsize, char *mname, size_t msize,
! 247: rrset_ns *nsrrsp)
! 248: {
! 249: char tname[NS_MAXDNAME];
! 250: double resp[NS_PACKETSZ / sizeof (double)];
! 251: int n, i, ancount, nscount;
! 252: ns_sect sect;
! 253: ns_msg msg;
! 254: isc_result_t rcode;
! 255:
! 256: /*
! 257: * Find closest enclosing SOA, even if it's for the root zone.
! 258: */
! 259:
! 260: /* First canonicalize dname (exactly one unescaped trailing "."). */
! 261: rcode = ns_makecanon(dname, tname, sizeof tname);
! 262: if (rcode != ISC_R_SUCCESS)
! 263: return rcode;
! 264: dname = tname;
! 265:
! 266: /* Now grovel the subdomains, hunting for an SOA answer or auth. */
! 267: for (;;) {
! 268: /* Leading or inter-label '.' are skipped here. */
! 269: while (*dname == '.')
! 270: dname++;
! 271:
! 272: /* Is there an SOA? */
! 273: rcode = do_query(statp, dname, class, ns_t_soa,
! 274: resp, &msg, &n);
! 275: if (rcode != ISC_R_SUCCESS) {
! 276: DPRINTF(("get_soa: do_query('%s', %s) failed (%d)",
! 277: dname, p_class(class), n));
! 278: return rcode;
! 279: }
! 280: if (n > 0) {
! 281: DPRINTF(("get_soa: CNAME or DNAME found"));
! 282: sect = ns_s_max, n = 0;
! 283: } else {
! 284: ancount = ns_msg_count(msg, ns_s_an);
! 285: nscount = ns_msg_count(msg, ns_s_ns);
! 286: if (ancount > 0 && rcode == ISC_R_SUCCESS)
! 287: sect = ns_s_an, n = ancount;
! 288: else if (nscount > 0)
! 289: sect = ns_s_ns, n = nscount;
! 290: else
! 291: sect = ns_s_max, n = 0;
! 292: }
! 293: for (i = 0; i < n; i++) {
! 294: const char *t;
! 295: const u_char *rdata;
! 296: int rdlen;
! 297: ns_rr rr;
! 298:
! 299: rcode = ns_parserr(&msg, sect, i, &rr) < 0;
! 300: if (rcode != ISC_R_SUCCESS) {
! 301: DPRINTF(("get_soa: ns_parserr(%s, %d) failed",
! 302: p_section(sect, ns_o_query), i));
! 303: return rcode;
! 304: }
! 305: if (ns_rr_type(rr) == ns_t_cname ||
! 306: ns_rr_type(rr) == ns_t_dname)
! 307: break;
! 308: if (ns_rr_type(rr) != ns_t_soa ||
! 309: ns_rr_class(rr) != class)
! 310: continue;
! 311: t = ns_rr_name(rr);
! 312: switch (sect) {
! 313: case ns_s_an:
! 314: if (ns_samedomain(dname, t) == 0) {
! 315: DPRINTF(("get_soa: %s'%s', '%s') == 0",
! 316: "ns_samedomain(", dname, t));
! 317: return ISC_R_NOTZONE;
! 318: }
! 319: break;
! 320: case ns_s_ns:
! 321: if (ns_samename(dname, t) == 1 ||
! 322: ns_samedomain(dname, t) == 0) {
! 323: DPRINTF(("get_soa: %smain('%s', '%s')",
! 324: "ns_samename() || !ns_samedo",
! 325: dname, t));
! 326: return ISC_R_NOTZONE;
! 327: }
! 328: break;
! 329: default:
! 330: abort();
! 331: }
! 332: if (strlen(t) + 1 > zsize) {
! 333: DPRINTF(("get_soa: zname(%d) too small (%d)",
! 334: zsize, strlen(t) + 1));
! 335: return ISC_R_NOSPACE;
! 336: }
! 337: strcpy(zname, t);
! 338: rdata = ns_rr_rdata(rr);
! 339: rdlen = ns_rr_rdlen(rr);
! 340: if (ns_name_uncompress((u_char *)resp,
! 341: ns_msg_end(msg), rdata,
! 342: mname, msize) < 0) {
! 343: DPRINTF(("get_soa: %s failed",
! 344: "ns_name_uncompress"));
! 345: return ISC_R_NOMEMORY;
! 346: }
! 347: rcode = save_ns(statp, &msg,
! 348: ns_s_ns, zname, class, nsrrsp);
! 349: if (rcode != ISC_R_SUCCESS) {
! 350: DPRINTF(("get_soa: save_ns failed"));
! 351: return rcode;
! 352: }
! 353: return ISC_R_SUCCESS;
! 354: }
! 355:
! 356: /* If we're out of labels, then not even "." has an SOA! */
! 357: if (*dname == '\0')
! 358: break;
! 359:
! 360: /* Find label-terminating "."; top of loop will skip it. */
! 361: while (*dname != '.') {
! 362: if (*dname == '\\')
! 363: if (*++dname == '\0') {
! 364: return ISC_R_NOSPACE;
! 365: }
! 366: dname++;
! 367: }
! 368: }
! 369: DPRINTF(("get_soa: out of labels"));
! 370: return ISC_R_DESTADDRREQ;
! 371: }
! 372:
! 373: static isc_result_t
! 374: get_ns(res_state statp, const char *zname, ns_class class, rrset_ns *nsrrsp) {
! 375: double resp[NS_PACKETSZ / sizeof (double)];
! 376: ns_msg msg;
! 377: int n;
! 378: isc_result_t rcode;
! 379:
! 380: /* Go and get the NS RRs for this zone. */
! 381: rcode = do_query(statp, zname, class, ns_t_ns, resp, &msg, &n);
! 382: if (rcode != ISC_R_SUCCESS) {
! 383: DPRINTF(("get_ns: do_query('zname', %s) failed (%d)",
! 384: zname, p_class(class), rcode));
! 385: return rcode;
! 386: }
! 387:
! 388: /* Remember the NS RRs and associated A RRs that came back. */
! 389: rcode = save_ns(statp, &msg, ns_s_an, zname, class, nsrrsp);
! 390: if (rcode != ISC_R_SUCCESS) {
! 391: DPRINTF(("get_ns save_ns('%s', %s) failed",
! 392: zname, p_class(class)));
! 393: return rcode;
! 394: }
! 395:
! 396: return ISC_R_SUCCESS;
! 397: }
! 398:
! 399: static isc_result_t
! 400: get_glue(res_state statp, ns_class class, rrset_ns *nsrrsp) {
! 401: rr_ns *nsrr, *nsrr_n;
! 402:
! 403: /* Go and get the A RRs for each empty NS RR on our list. */
! 404: for (nsrr = ISC_LIST_HEAD(*nsrrsp); nsrr != NULL; nsrr = nsrr_n) {
! 405: double resp[NS_PACKETSZ / sizeof (double)];
! 406: ns_msg msg;
! 407: int n;
! 408: isc_result_t rcode;
! 409:
! 410: nsrr_n = ISC_LIST_NEXT(nsrr, link);
! 411:
! 412: if (ISC_LIST_EMPTY(nsrr->addrs)) {
! 413: rcode = do_query(statp, nsrr->name, class, ns_t_a,
! 414: resp, &msg, &n);
! 415: if (rcode != ISC_R_SUCCESS) {
! 416: DPRINTF(("get_glue: do_query('%s', %s') failed",
! 417: nsrr->name, p_class(class)));
! 418: return rcode;
! 419: }
! 420: if (n > 0) {
! 421: DPRINTF((
! 422: "get_glue: do_query('%s', %s') CNAME or DNAME found",
! 423: nsrr->name, p_class(class)));
! 424: }
! 425: rcode = save_a(statp, &msg, ns_s_an, nsrr->name, class,
! 426: &nsrr->addrs);
! 427: if (rcode != ISC_R_SUCCESS) {
! 428: DPRINTF(("get_glue: save_r('%s', %s) failed",
! 429: nsrr->name, p_class(class)));
! 430: return rcode;
! 431: }
! 432: /* If it's still empty, it's just chaff. */
! 433: if (ISC_LIST_EMPTY(nsrr->addrs)) {
! 434: DPRINTF(("get_glue: removing empty '%s' NS",
! 435: nsrr->name));
! 436: free_nsrr(nsrrsp, nsrr);
! 437: }
! 438: }
! 439: }
! 440: return ISC_R_SUCCESS;
! 441: }
! 442:
! 443: static isc_result_t
! 444: save_ns(res_state statp, ns_msg *msg, ns_sect sect,
! 445: const char *owner, ns_class class,
! 446: rrset_ns *nsrrsp)
! 447: {
! 448: int i;
! 449: isc_result_t rcode;
! 450:
! 451: for (i = 0; i < ns_msg_count(*msg, sect); i++) {
! 452: char tname[MAXDNAME];
! 453: const u_char *rdata;
! 454: rr_ns *nsrr;
! 455: ns_rr rr;
! 456: int rdlen;
! 457:
! 458: rcode = ns_parserr(msg, sect, i, &rr);
! 459: if (rcode != ISC_R_SUCCESS) {
! 460: DPRINTF(("save_ns: ns_parserr(%s, %d) failed",
! 461: p_section(sect, ns_o_query), i));
! 462: return rcode;
! 463: }
! 464: if (ns_rr_type(rr) != ns_t_ns ||
! 465: ns_rr_class(rr) != class ||
! 466: ns_samename(ns_rr_name(rr), owner) != 1)
! 467: continue;
! 468: nsrr = find_ns(nsrrsp, ns_rr_name(rr));
! 469: if (nsrr == NULL) {
! 470: nsrr = malloc(sizeof *nsrr);
! 471: if (nsrr == NULL) {
! 472: DPRINTF(("save_ns: malloc failed"));
! 473: return ISC_R_NOMEMORY;
! 474: }
! 475: rdata = ns_rr_rdata(rr);
! 476: rdlen = ns_rr_rdlen(rr);
! 477: if (ns_name_uncompress(ns_msg_base(*msg),
! 478: ns_msg_end(*msg), rdata,
! 479: tname, sizeof tname) < 0) {
! 480: DPRINTF(("save_ns: ns_name_uncompress failed"));
! 481: free(nsrr);
! 482: return ISC_R_NOMEMORY;
! 483: }
! 484: nsrr->name = strdup(tname);
! 485: if (nsrr->name == NULL) {
! 486: DPRINTF(("save_ns: strdup failed"));
! 487: free(nsrr);
! 488: return ISC_R_NOMEMORY;
! 489: }
! 490: ISC_LIST_INIT(nsrr->addrs);
! 491: ISC_LIST_APPEND(*nsrrsp, nsrr, link);
! 492: }
! 493: rcode = save_a(statp, msg, ns_s_ar,
! 494: nsrr->name, class, &nsrr->addrs);
! 495: if (rcode != ISC_R_SUCCESS) {
! 496: DPRINTF(("save_ns: save_r('%s', %s) failed",
! 497: nsrr->name, p_class(class)));
! 498: return rcode;
! 499: }
! 500: }
! 501: return ISC_R_SUCCESS;
! 502: }
! 503:
! 504: static isc_result_t
! 505: save_a(res_state statp, ns_msg *msg, ns_sect sect,
! 506: const char *owner, ns_class class,
! 507: rrset_a *arrsp)
! 508: {
! 509: int i;
! 510: isc_result_t rcode;
! 511:
! 512: for (i = 0; i < ns_msg_count(*msg, sect); i++) {
! 513: ns_rr rr;
! 514: rr_a *arr;
! 515:
! 516: rcode = ns_parserr(msg, sect, i, &rr);
! 517: if (rcode != ISC_R_SUCCESS) {
! 518: DPRINTF(("save_a: ns_parserr(%s, %d) failed",
! 519: p_section(sect, ns_o_query), i));
! 520: return rcode;
! 521: }
! 522: if (ns_rr_type(rr) != ns_t_a ||
! 523: ns_rr_class(rr) != class ||
! 524: ns_samename(ns_rr_name(rr), owner) != 1 ||
! 525: ns_rr_rdlen(rr) != NS_INADDRSZ)
! 526: continue;
! 527: arr = malloc(sizeof *arr);
! 528: if (arr == NULL) {
! 529: DPRINTF(("save_a: malloc failed"));
! 530: return ISC_R_NOMEMORY;
! 531: }
! 532: memcpy(&arr->addr, ns_rr_rdata(rr), NS_INADDRSZ);
! 533: ISC_LIST_APPEND(*arrsp, arr, link);
! 534: }
! 535: return ISC_R_SUCCESS;
! 536: }
! 537:
! 538: static void
! 539: free_nsrrset(rrset_ns *nsrrsp) {
! 540: rr_ns *nsrr;
! 541:
! 542: while ((nsrr = ISC_LIST_HEAD(*nsrrsp)) != NULL)
! 543: free_nsrr(nsrrsp, nsrr);
! 544: }
! 545:
! 546: static void
! 547: free_nsrr(rrset_ns *nsrrsp, rr_ns *nsrr) {
! 548: rr_a *arr;
! 549:
! 550: while ((arr = ISC_LIST_HEAD(nsrr->addrs)) != NULL) {
! 551: ISC_LIST_UNLINK(nsrr->addrs, arr, link);
! 552: free(arr);
! 553: }
! 554: free((char *)nsrr->name);
! 555: ISC_LIST_UNLINK(*nsrrsp, nsrr, link);
! 556: free(nsrr);
! 557: }
! 558:
! 559: static rr_ns *
! 560: find_ns(rrset_ns *nsrrsp, const char *dname) {
! 561: rr_ns *nsrr;
! 562:
! 563: for (nsrr = ISC_LIST_HEAD(*nsrrsp);
! 564: nsrr != NULL; nsrr = ISC_LIST_NEXT(nsrr, link))
! 565: if (ns_samename(nsrr->name, dname) == 1)
! 566: return (nsrr);
! 567: return (NULL);
! 568: }
! 569:
! 570: static isc_result_t
! 571: do_query(res_state statp, const char *dname, ns_class class, ns_type qtype,
! 572: double *resp, ns_msg *msg, int *alias_count)
! 573: {
! 574: double req[NS_PACKETSZ / sizeof (double)];
! 575: int i;
! 576: unsigned n;
! 577: isc_result_t status;
! 578:
! 579: status = res_nmkquery(statp, ns_o_query, dname, class, qtype,
! 580: NULL, 0, NULL, req, NS_PACKETSZ, &n);
! 581: if (status != ISC_R_SUCCESS) {
! 582: DPRINTF(("do_query: res_nmkquery failed"));
! 583: return status;
! 584: }
! 585: status = res_nsend(statp, req, n, resp, NS_PACKETSZ, &n);
! 586: if (status != ISC_R_SUCCESS) {
! 587: DPRINTF(("do_query: res_nsend failed"));
! 588: return status;
! 589: }
! 590: if (n == 0) {
! 591: DPRINTF(("do_query: res_nsend returned 0"));
! 592: return ISC_R_NOTFOUND;
! 593: }
! 594: if (ns_initparse((u_char *)resp, n, msg) < 0) {
! 595: DPRINTF(("do_query: ns_initparse failed"));
! 596: return ISC_R_NOSPACE;
! 597: }
! 598: n = 0;
! 599: for (i = 0; i < ns_msg_count(*msg, ns_s_an); i++) {
! 600: ns_rr rr;
! 601:
! 602: status = ns_parserr(msg, ns_s_an, i, &rr);
! 603: if (status != ISC_R_SUCCESS) {
! 604: DPRINTF(("do_query: ns_parserr failed"));
! 605: return status;
! 606: }
! 607: n += (ns_rr_class(rr) == class &&
! 608: (ns_rr_type(rr) == ns_t_cname ||
! 609: ns_rr_type(rr) == ns_t_dname));
! 610: }
! 611: if (alias_count)
! 612: *alias_count = n;
! 613: return ISC_R_SUCCESS;
! 614: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>