Annotation of embedaddon/dhcp/minires/res_query.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (c) 1988, 1993
! 3: * The Regents of the University of California. All rights reserved.
! 4: *
! 5: * Redistribution and use in source and binary forms, with or without
! 6: * modification, are permitted provided that the following conditions
! 7: * are met:
! 8: * 1. Redistributions of source code must retain the above copyright
! 9: * notice, this list of conditions and the following disclaimer.
! 10: * 2. Redistributions in binary form must reproduce the above copyright
! 11: * notice, this list of conditions and the following disclaimer in the
! 12: * documentation and/or other materials provided with the distribution.
! 13: * 3. All advertising materials mentioning features or use of this software
! 14: * must display the following acknowledgement:
! 15: * This product includes software developed by the University of
! 16: * California, Berkeley and its contributors.
! 17: * 4. Neither the name of the University nor the names of its contributors
! 18: * may be used to endorse or promote products derived from this software
! 19: * without specific prior written permission.
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 31: * SUCH DAMAGE.
! 32: */
! 33:
! 34: /*
! 35: * Portions Copyright (c) 1993 by Digital Equipment Corporation.
! 36: *
! 37: * Permission to use, copy, modify, and distribute this software for any
! 38: * purpose with or without fee is hereby granted, provided that the above
! 39: * copyright notice and this permission notice appear in all copies, and that
! 40: * the name of Digital Equipment Corporation not be used in advertising or
! 41: * publicity pertaining to distribution of the document or software without
! 42: * specific, written prior permission.
! 43: *
! 44: * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
! 45: * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
! 46: * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
! 47: * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
! 48: * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
! 49: * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
! 50: * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
! 51: * SOFTWARE.
! 52: */
! 53:
! 54: /*
! 55: * Portions Copyright (c) 2004,2007,2009 by Internet Systems Consortium, Inc. ("ISC")
! 56: * Portions Copyright (c) 1996-2003 by Internet Software Consortium
! 57: *
! 58: * Permission to use, copy, modify, and distribute this software for any
! 59: * purpose with or without fee is hereby granted, provided that the above
! 60: * copyright notice and this permission notice appear in all copies.
! 61: *
! 62: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
! 63: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 64: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
! 65: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 66: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 67: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
! 68: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 69: *
! 70: * Internet Systems Consortium, Inc.
! 71: * 950 Charter Street
! 72: * Redwood City, CA 94063
! 73: * <info@isc.org>
! 74: * https://www.isc.org/
! 75: */
! 76:
! 77: #if defined(LIBC_SCCS) && !defined(lint)
! 78: static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
! 79: static const char rcsid[] = "$Id: res_query.c,v 1.9.74.2 2009-07-24 22:04:52 sar Exp $";
! 80: #endif /* LIBC_SCCS and not lint */
! 81:
! 82: #include <sys/types.h>
! 83: #include <sys/param.h>
! 84: #include <netinet/in.h>
! 85: #include <arpa/inet.h>
! 86: #include <ctype.h>
! 87: #include <errno.h>
! 88: #include <netdb.h>
! 89: #include <stdio.h>
! 90: #include <stdlib.h>
! 91: #include <string.h>
! 92: #include <sys/socket.h>
! 93:
! 94: #include "minires/minires.h"
! 95: #include "arpa/nameser.h"
! 96:
! 97: /* Options. Leave them on. */
! 98: #if PACKETSZ > 1024
! 99: #define MAXPACKET PACKETSZ
! 100: #else
! 101: #define MAXPACKET 1024
! 102: #endif
! 103:
! 104: /*
! 105: * Formulate a normal query, send, and await answer.
! 106: * Returned answer is placed in supplied buffer "answer".
! 107: * Perform preliminary check of answer, returning success only
! 108: * if no error is indicated and the answer count is nonzero.
! 109: * Return the size of the response on success, -1 on error.
! 110: * Error number is left in H_ERRNO.
! 111: *
! 112: * Caller must parse answer and determine whether it answers the question.
! 113: */
! 114: isc_result_t
! 115: res_nquery(res_state statp,
! 116: const char *name, /* domain name */
! 117: ns_class class, ns_type type, /* class and type of query */
! 118: double *answer, /* buffer to put answer */
! 119: unsigned anslen,
! 120: unsigned *ansret) /* size of answer buffer */
! 121: {
! 122: double buf[MAXPACKET / sizeof (double)];
! 123: HEADER *hp = (HEADER *) answer;
! 124: unsigned n;
! 125: isc_result_t rcode;
! 126:
! 127: hp->rcode = NOERROR; /* default */
! 128:
! 129: if (statp->options & RES_DEBUG)
! 130: printf(";; res_query(%s, %d, %d)\n", name, class, type);
! 131:
! 132: rcode = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL,
! 133: buf, sizeof(buf), &n);
! 134: if (rcode != ISC_R_SUCCESS) {
! 135: if (statp->options & RES_DEBUG)
! 136: printf(";; res_query: mkquery failed\n");
! 137: RES_SET_H_ERRNO(statp, NO_RECOVERY);
! 138: return rcode;
! 139: }
! 140: rcode = res_nsend(statp, buf, n, answer, anslen, &n);
! 141: if (rcode != ISC_R_SUCCESS) {
! 142: if (statp->options & RES_DEBUG)
! 143: printf(";; res_query: send error\n");
! 144: RES_SET_H_ERRNO(statp, TRY_AGAIN);
! 145: return rcode;
! 146: }
! 147:
! 148: if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
! 149: if (statp->options & RES_DEBUG)
! 150: printf(";; rcode = %d, ancount=%d\n", hp->rcode,
! 151: ntohs(hp->ancount));
! 152: switch (hp->rcode) {
! 153: case NXDOMAIN:
! 154: RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
! 155: break;
! 156: case SERVFAIL:
! 157: RES_SET_H_ERRNO(statp, TRY_AGAIN);
! 158: break;
! 159: case NOERROR:
! 160: RES_SET_H_ERRNO(statp, NO_DATA);
! 161: break;
! 162: case FORMERR:
! 163: case NOTIMP:
! 164: case REFUSED:
! 165: default:
! 166: RES_SET_H_ERRNO(statp, NO_RECOVERY);
! 167: break;
! 168: }
! 169: return ns_rcode_to_isc (hp -> rcode);
! 170: }
! 171: *ansret = n;
! 172: return ISC_R_SUCCESS;
! 173: }
! 174:
! 175: #if 0
! 176: /*
! 177: * Formulate a normal query, send, and retrieve answer in supplied buffer.
! 178: * Return the size of the response on success, -1 on error.
! 179: * If enabled, implement search rules until answer or unrecoverable failure
! 180: * is detected. Error code, if any, is left in H_ERRNO.
! 181: */
! 182: isc_result_t
! 183: res_nsearch(res_state statp,
! 184: const char *name, /* domain name */
! 185: ns_class class, ns_type type, /* class and type of query */
! 186: double *answer, /* buffer to put answer */
! 187: unsigned anslen,
! 188: unsigned *ansret) /* size of answer */
! 189: {
! 190: const char *cp, * const *domain;
! 191: HEADER *hp = (HEADER *) answer;
! 192: char tmp[NS_MAXDNAME];
! 193: u_int dots;
! 194: int trailing_dot, ret;
! 195: int got_nodata = 0, got_servfail = 0, root_on_list = 0;
! 196: isc_result_t rcode;
! 197:
! 198: errno = 0;
! 199: RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /* True if we never query. */
! 200:
! 201: dots = 0;
! 202: for (cp = name; *cp != '\0'; cp++)
! 203: dots += (*cp == '.');
! 204: trailing_dot = 0;
! 205: if (cp > name && *--cp == '.')
! 206: trailing_dot++;
! 207:
! 208: /* If there aren't any dots, it could be a user-level alias. */
! 209: if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL)
! 210: return res_nquery(statp, cp, class, type,
! 211: answer, anslen, ansret);
! 212:
! 213: /*
! 214: * If there are enough dots in the name, do no searching.
! 215: * (The threshold can be set with the "ndots" option.)
! 216: */
! 217: if (dots >= statp->ndots || trailing_dot)
! 218: return res_nquerydomain(statp, name, NULL, class, type,
! 219: answer, anslen, ansret);
! 220:
! 221: /*
! 222: * We do at least one level of search if
! 223: * - there is no dot and RES_DEFNAME is set, or
! 224: * - there is at least one dot, there is no trailing dot,
! 225: * and RES_DNSRCH is set.
! 226: */
! 227: if ((!dots && (statp->options & RES_DEFNAMES) != 0) ||
! 228: (dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0)) {
! 229: int done = 0;
! 230:
! 231: for (domain = (const char * const *)statp->dnsrch;
! 232: *domain && !done;
! 233: domain++) {
! 234:
! 235: if (domain[0][0] == '\0' ||
! 236: (domain[0][0] == '.' && domain[0][1] == '\0'))
! 237: root_on_list++;
! 238:
! 239: rcode = res_nquerydomain(statp, name, *domain,
! 240: class, type,
! 241: answer, anslen, &ret);
! 242: if (rcode == ISC_R_SUCCESS && ret > 0) {
! 243: *ansret = ret;
! 244: return rcode;
! 245: }
! 246:
! 247: /*
! 248: * If no server present, give up.
! 249: * If name isn't found in this domain,
! 250: * keep trying higher domains in the search list
! 251: * (if that's enabled).
! 252: * On a NO_DATA error, keep trying, otherwise
! 253: * a wildcard entry of another type could keep us
! 254: * from finding this entry higher in the domain.
! 255: * If we get some other error (negative answer or
! 256: * server failure), then stop searching up,
! 257: * but try the input name below in case it's
! 258: * fully-qualified.
! 259: */
! 260: if (errno == ECONNREFUSED) {
! 261: RES_SET_H_ERRNO(statp, TRY_AGAIN);
! 262: return ISC_R_CONNREFUSED;
! 263: }
! 264:
! 265: switch (statp->res_h_errno) {
! 266: case NO_DATA:
! 267: got_nodata++;
! 268: /* FALLTHROUGH */
! 269: case HOST_NOT_FOUND:
! 270: /* keep trying */
! 271: break;
! 272: case TRY_AGAIN:
! 273: if (hp->rcode == SERVFAIL) {
! 274: /* try next search element, if any */
! 275: got_servfail++;
! 276: break;
! 277: }
! 278: /* FALLTHROUGH */
! 279: default:
! 280: /* anything else implies that we're done */
! 281: done++;
! 282: }
! 283:
! 284: /* if we got here for some reason other than DNSRCH,
! 285: * we only wanted one iteration of the loop, so stop.
! 286: */
! 287: if ((statp->options & RES_DNSRCH) == 0)
! 288: done++;
! 289: }
! 290: }
! 291:
! 292: /*
! 293: * If the name has any dots at all, and "." is not on the search
! 294: * list, then try an as-is query now.
! 295: */
! 296: if (statp->ndots) {
! 297: rcode = res_nquerydomain(statp, name, NULL, class, type,
! 298: answer, anslen, &ret);
! 299: if (rcode == ISC_R_SUCCESS && ret > 0) {
! 300: *ansret = ret;
! 301: return rcode;
! 302: }
! 303: }
! 304:
! 305: /* if we got here, we didn't satisfy the search.
! 306: * if we did an initial full query, return that query's H_ERRNO
! 307: * (note that we wouldn't be here if that query had succeeded).
! 308: * else if we ever got a nodata, send that back as the reason.
! 309: * else send back meaningless H_ERRNO, that being the one from
! 310: * the last DNSRCH we did.
! 311: */
! 312: if (got_nodata) {
! 313: RES_SET_H_ERRNO(statp, NO_DATA);
! 314: return ISC_R_NOTFOUND;
! 315: } else if (got_servfail) {
! 316: RES_SET_H_ERRNO(statp, TRY_AGAIN);
! 317: return ISC_R_TIMEDOUT;
! 318: }
! 319: return ISC_R_UNEXPECTED;
! 320: }
! 321: #endif
! 322:
! 323: /*
! 324: * Perform a call on res_query on the concatenation of name and domain,
! 325: * removing a trailing dot from name if domain is NULL.
! 326: */
! 327: isc_result_t
! 328: res_nquerydomain(res_state statp,
! 329: const char *name,
! 330: const char *domain,
! 331: ns_class class, ns_type type,
! 332: double *answer,
! 333: unsigned anslen,
! 334: unsigned *ansret)
! 335: {
! 336: char nbuf[MAXDNAME];
! 337: const char *longname = nbuf;
! 338: int n, d;
! 339:
! 340: if (statp->options & RES_DEBUG)
! 341: printf(";; res_nquerydomain(%s, %s, %d, %d)\n",
! 342: name, domain?domain:"<Nil>", class, type);
! 343: if (domain == NULL) {
! 344: /*
! 345: * Check for trailing '.';
! 346: * copy without '.' if present.
! 347: */
! 348: n = strlen(name);
! 349: if (n >= MAXDNAME) {
! 350: RES_SET_H_ERRNO(statp, NO_RECOVERY);
! 351: return ISC_R_NOSPACE;
! 352: }
! 353: n--;
! 354: if (n >= 0 && name[n] == '.') {
! 355: strncpy(nbuf, name, (unsigned)n);
! 356: nbuf[n] = '\0';
! 357: } else
! 358: longname = name;
! 359: } else {
! 360: n = strlen(name);
! 361: d = strlen(domain);
! 362: if (n + d + 1 >= MAXDNAME) {
! 363: RES_SET_H_ERRNO(statp, NO_RECOVERY);
! 364: return ISC_R_NOSPACE;
! 365: }
! 366: sprintf(nbuf, "%s.%s", name, domain);
! 367: }
! 368: return res_nquery(statp,
! 369: longname, class, type, answer, anslen, ansret);
! 370: }
! 371:
! 372: const char *
! 373: res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) {
! 374: char *file;
! 375: unsigned char *cp1, *cp2;
! 376: char buf[BUFSIZ];
! 377: FILE *fp;
! 378:
! 379: if (statp->options & RES_NOALIASES)
! 380: return (NULL);
! 381: file = getenv("HOSTALIASES");
! 382: if (file == NULL || (fp = fopen(file, "r")) == NULL)
! 383: return (NULL);
! 384: setbuf(fp, NULL);
! 385: buf[sizeof(buf) - 1] = '\0';
! 386: while (fgets(buf, sizeof(buf), fp)) {
! 387: for (cp1 = (unsigned char *)buf; *cp1 && !isspace(*cp1); ++cp1)
! 388: ;
! 389: if (!*cp1)
! 390: break;
! 391: *cp1 = '\0';
! 392: if (ns_samename(buf, name) == 1) {
! 393: while (isspace(*++cp1))
! 394: ;
! 395: if (!*cp1)
! 396: break;
! 397: for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2)
! 398: ;
! 399: *cp2 = '\0';
! 400: strncpy(dst, (char *)cp1, siz - 1);
! 401: dst[siz - 1] = '\0';
! 402: fclose(fp);
! 403: return (dst);
! 404: }
! 405: }
! 406: fclose(fp);
! 407: return (NULL);
! 408: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>