1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 1997 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate /* 31*7c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 32*7c478bd9Sstevel@tonic-gate * The Regents of the University of California 33*7c478bd9Sstevel@tonic-gate * All Rights Reserved 34*7c478bd9Sstevel@tonic-gate * 35*7c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 36*7c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 37*7c478bd9Sstevel@tonic-gate * contributors. 38*7c478bd9Sstevel@tonic-gate */ 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate #include "synonyms.h" 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 46*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 47*7c478bd9Sstevel@tonic-gate #include <ctype.h> 48*7c478bd9Sstevel@tonic-gate #include <netdb.h> 49*7c478bd9Sstevel@tonic-gate #include <stdio.h> 50*7c478bd9Sstevel@tonic-gate #include <errno.h> 51*7c478bd9Sstevel@tonic-gate #include <string.h> 52*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 53*7c478bd9Sstevel@tonic-gate #include <arpa/nameser.h> 54*7c478bd9Sstevel@tonic-gate #include <resolv.h> 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate #if PACKETSZ > 1024 57*7c478bd9Sstevel@tonic-gate #define MAXPACKET PACKETSZ 58*7c478bd9Sstevel@tonic-gate #else 59*7c478bd9Sstevel@tonic-gate #define MAXPACKET 1024 60*7c478bd9Sstevel@tonic-gate #endif 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate int h_errno; 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate /* 65*7c478bd9Sstevel@tonic-gate * Formulate a normal query, send, and await answer. 66*7c478bd9Sstevel@tonic-gate * Returned answer is placed in supplied buffer "answer". 67*7c478bd9Sstevel@tonic-gate * Perform preliminary check of answer, returning success only 68*7c478bd9Sstevel@tonic-gate * if no error is indicated and the answer count is nonzero. 69*7c478bd9Sstevel@tonic-gate * Return the size of the response on success, -1 on error. 70*7c478bd9Sstevel@tonic-gate * Error number is left in h_errno. 71*7c478bd9Sstevel@tonic-gate * Caller must parse answer and determine whether it answers the question. 72*7c478bd9Sstevel@tonic-gate */ 73*7c478bd9Sstevel@tonic-gate res_query(name, class, type, answer, anslen) 74*7c478bd9Sstevel@tonic-gate char *name; /* domain name */ 75*7c478bd9Sstevel@tonic-gate int class, type; /* class and type of query */ 76*7c478bd9Sstevel@tonic-gate u_char *answer; /* buffer to put answer */ 77*7c478bd9Sstevel@tonic-gate int anslen; /* size of answer buffer */ 78*7c478bd9Sstevel@tonic-gate { 79*7c478bd9Sstevel@tonic-gate char buf[MAXPACKET]; 80*7c478bd9Sstevel@tonic-gate HEADER *hp; 81*7c478bd9Sstevel@tonic-gate int n; 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate if ((_res.options & RES_INIT) == 0 && res_init() == -1) 84*7c478bd9Sstevel@tonic-gate return (-1); 85*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 86*7c478bd9Sstevel@tonic-gate if (_res.options & RES_DEBUG) 87*7c478bd9Sstevel@tonic-gate printf("res_query(%s, %d, %d)\n", name, class, type); 88*7c478bd9Sstevel@tonic-gate #endif 89*7c478bd9Sstevel@tonic-gate n = res_mkquery(QUERY, name, class, type, (char *)NULL, 0, NULL, 90*7c478bd9Sstevel@tonic-gate buf, sizeof (buf)); 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate if (n <= 0) { 93*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 94*7c478bd9Sstevel@tonic-gate if (_res.options & RES_DEBUG) 95*7c478bd9Sstevel@tonic-gate printf("res_query: mkquery failed\n"); 96*7c478bd9Sstevel@tonic-gate #endif 97*7c478bd9Sstevel@tonic-gate h_errno = NO_RECOVERY; 98*7c478bd9Sstevel@tonic-gate return (n); 99*7c478bd9Sstevel@tonic-gate } 100*7c478bd9Sstevel@tonic-gate n = res_send(buf, n, answer, anslen); 101*7c478bd9Sstevel@tonic-gate if (n < 0) { 102*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 103*7c478bd9Sstevel@tonic-gate if (_res.options & RES_DEBUG) 104*7c478bd9Sstevel@tonic-gate printf("res_query: send error\n"); 105*7c478bd9Sstevel@tonic-gate #endif 106*7c478bd9Sstevel@tonic-gate h_errno = TRY_AGAIN; 107*7c478bd9Sstevel@tonic-gate return (n); 108*7c478bd9Sstevel@tonic-gate } 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate hp = (HEADER *) answer; 111*7c478bd9Sstevel@tonic-gate if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { 112*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 113*7c478bd9Sstevel@tonic-gate if (_res.options & RES_DEBUG) 114*7c478bd9Sstevel@tonic-gate printf("rcode = %d, ancount=%d\n", hp->rcode, 115*7c478bd9Sstevel@tonic-gate ntohs(hp->ancount)); 116*7c478bd9Sstevel@tonic-gate #endif 117*7c478bd9Sstevel@tonic-gate switch (hp->rcode) { 118*7c478bd9Sstevel@tonic-gate case NXDOMAIN: 119*7c478bd9Sstevel@tonic-gate h_errno = HOST_NOT_FOUND; 120*7c478bd9Sstevel@tonic-gate break; 121*7c478bd9Sstevel@tonic-gate case SERVFAIL: 122*7c478bd9Sstevel@tonic-gate h_errno = TRY_AGAIN; 123*7c478bd9Sstevel@tonic-gate break; 124*7c478bd9Sstevel@tonic-gate case NOERROR: 125*7c478bd9Sstevel@tonic-gate h_errno = NO_DATA; 126*7c478bd9Sstevel@tonic-gate break; 127*7c478bd9Sstevel@tonic-gate case FORMERR: 128*7c478bd9Sstevel@tonic-gate case NOTIMP: 129*7c478bd9Sstevel@tonic-gate case REFUSED: 130*7c478bd9Sstevel@tonic-gate default: 131*7c478bd9Sstevel@tonic-gate h_errno = NO_RECOVERY; 132*7c478bd9Sstevel@tonic-gate break; 133*7c478bd9Sstevel@tonic-gate } 134*7c478bd9Sstevel@tonic-gate return (-1); 135*7c478bd9Sstevel@tonic-gate } 136*7c478bd9Sstevel@tonic-gate if (hp->rcode == NOERROR && ntohs(hp->ancount) > 0) 137*7c478bd9Sstevel@tonic-gate h_errno = 0; 138*7c478bd9Sstevel@tonic-gate return (n); 139*7c478bd9Sstevel@tonic-gate } 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate /* 142*7c478bd9Sstevel@tonic-gate * Formulate a normal query, send, and retrieve answer in supplied buffer. 143*7c478bd9Sstevel@tonic-gate * Return the size of the response on success, -1 on error. 144*7c478bd9Sstevel@tonic-gate * If enabled, implement search rules until answer or unrecoverable failure 145*7c478bd9Sstevel@tonic-gate * is detected. Error number is left in h_errno. 146*7c478bd9Sstevel@tonic-gate * Only useful for queries in the same name hierarchy as the local host 147*7c478bd9Sstevel@tonic-gate * (not, for example, for host address-to-name lookups in domain in-addr.arpa). 148*7c478bd9Sstevel@tonic-gate */ 149*7c478bd9Sstevel@tonic-gate res_search(name, class, type, answer, anslen) 150*7c478bd9Sstevel@tonic-gate char *name; /* domain name */ 151*7c478bd9Sstevel@tonic-gate int class, type; /* class and type of query */ 152*7c478bd9Sstevel@tonic-gate u_char *answer; /* buffer to put answer */ 153*7c478bd9Sstevel@tonic-gate int anslen; /* size of answer */ 154*7c478bd9Sstevel@tonic-gate { 155*7c478bd9Sstevel@tonic-gate register char *cp, **domain; 156*7c478bd9Sstevel@tonic-gate int n, ret, got_nodata = 0; 157*7c478bd9Sstevel@tonic-gate char *hostalias(); 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate if ((_res.options & RES_INIT) == 0 && res_init() == -1) 160*7c478bd9Sstevel@tonic-gate return (-1); 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate errno = 0; 163*7c478bd9Sstevel@tonic-gate h_errno = HOST_NOT_FOUND; /* default, if we never query */ 164*7c478bd9Sstevel@tonic-gate for (cp = name, n = 0; *cp; cp++) 165*7c478bd9Sstevel@tonic-gate if (*cp == '.') 166*7c478bd9Sstevel@tonic-gate n++; 167*7c478bd9Sstevel@tonic-gate if (n == 0 && (cp = hostalias(name))) 168*7c478bd9Sstevel@tonic-gate return (res_query(cp, class, type, answer, anslen)); 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate /* 171*7c478bd9Sstevel@tonic-gate * We do at least one level of search if 172*7c478bd9Sstevel@tonic-gate * - there is no dot and RES_DEFNAME is set, or 173*7c478bd9Sstevel@tonic-gate * - there is at least one dot, there is no trailing dot, 174*7c478bd9Sstevel@tonic-gate * and RES_DNSRCH is set. 175*7c478bd9Sstevel@tonic-gate */ 176*7c478bd9Sstevel@tonic-gate if ((n == 0 && _res.options & RES_DEFNAMES) || 177*7c478bd9Sstevel@tonic-gate (n != 0 && *--cp != '.' && _res.options & RES_DNSRCH)) { 178*7c478bd9Sstevel@tonic-gate for (domain = _res.dnsrch; *domain; domain++) { 179*7c478bd9Sstevel@tonic-gate ret = res_querydomain(name, *domain, class, type, 180*7c478bd9Sstevel@tonic-gate answer, anslen); 181*7c478bd9Sstevel@tonic-gate if (ret > 0) 182*7c478bd9Sstevel@tonic-gate return (ret); 183*7c478bd9Sstevel@tonic-gate /* 184*7c478bd9Sstevel@tonic-gate * If no server present, give up. 185*7c478bd9Sstevel@tonic-gate * If name isn't found in this domain, 186*7c478bd9Sstevel@tonic-gate * keep trying higher domains in the search list 187*7c478bd9Sstevel@tonic-gate * (if that's enabled). 188*7c478bd9Sstevel@tonic-gate * On a NO_DATA error, keep trying, otherwise 189*7c478bd9Sstevel@tonic-gate * a wildcard entry of another type could keep us 190*7c478bd9Sstevel@tonic-gate * from finding this entry higher in the domain. 191*7c478bd9Sstevel@tonic-gate * If we get some other error (negative answer or 192*7c478bd9Sstevel@tonic-gate * server failure), then stop searching up, 193*7c478bd9Sstevel@tonic-gate * but try the input name below in case it's fully-qualified. 194*7c478bd9Sstevel@tonic-gate */ 195*7c478bd9Sstevel@tonic-gate if (errno == ECONNREFUSED) { 196*7c478bd9Sstevel@tonic-gate h_errno = TRY_AGAIN; 197*7c478bd9Sstevel@tonic-gate return (-1); 198*7c478bd9Sstevel@tonic-gate } 199*7c478bd9Sstevel@tonic-gate if (h_errno == NO_DATA) 200*7c478bd9Sstevel@tonic-gate got_nodata++; 201*7c478bd9Sstevel@tonic-gate if ((h_errno != HOST_NOT_FOUND && h_errno != NO_DATA) || 202*7c478bd9Sstevel@tonic-gate (_res.options & RES_DNSRCH) == 0) 203*7c478bd9Sstevel@tonic-gate break; 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate } 206*7c478bd9Sstevel@tonic-gate /* 207*7c478bd9Sstevel@tonic-gate * If the search/default failed, try the name as fully-qualified, 208*7c478bd9Sstevel@tonic-gate * but only if it contained at least one dot (even trailing). 209*7c478bd9Sstevel@tonic-gate * This is purely a heuristic; we assume that any reasonable query 210*7c478bd9Sstevel@tonic-gate * about a top-level domain (for servers, SOA, etc) will not use 211*7c478bd9Sstevel@tonic-gate * res_search. 212*7c478bd9Sstevel@tonic-gate */ 213*7c478bd9Sstevel@tonic-gate if (n && (ret = res_querydomain(name, (char *)NULL, class, type, 214*7c478bd9Sstevel@tonic-gate answer, anslen)) > 0) 215*7c478bd9Sstevel@tonic-gate return (ret); 216*7c478bd9Sstevel@tonic-gate if (got_nodata) 217*7c478bd9Sstevel@tonic-gate h_errno = NO_DATA; 218*7c478bd9Sstevel@tonic-gate return (-1); 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate /* 222*7c478bd9Sstevel@tonic-gate * Perform a call on res_query on the concatenation of name and domain, 223*7c478bd9Sstevel@tonic-gate * removing a trailing dot from name if domain is NULL. 224*7c478bd9Sstevel@tonic-gate */ 225*7c478bd9Sstevel@tonic-gate res_querydomain(name, domain, class, type, answer, anslen) 226*7c478bd9Sstevel@tonic-gate char *name, *domain; 227*7c478bd9Sstevel@tonic-gate int class, type; /* class and type of query */ 228*7c478bd9Sstevel@tonic-gate u_char *answer; /* buffer to put answer */ 229*7c478bd9Sstevel@tonic-gate int anslen; /* size of answer */ 230*7c478bd9Sstevel@tonic-gate { 231*7c478bd9Sstevel@tonic-gate char nbuf[2*MAXDNAME+2]; 232*7c478bd9Sstevel@tonic-gate char *longname = nbuf; 233*7c478bd9Sstevel@tonic-gate int n; 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 236*7c478bd9Sstevel@tonic-gate if (_res.options & RES_DEBUG) { 237*7c478bd9Sstevel@tonic-gate if (domain == (char *)NULL) 238*7c478bd9Sstevel@tonic-gate printf("res_querydomain(%s, NULL, %d, %d)\n", 239*7c478bd9Sstevel@tonic-gate name, class, type); 240*7c478bd9Sstevel@tonic-gate else 241*7c478bd9Sstevel@tonic-gate printf("res_querydomain(%s, %s, %d, %d)\n", 242*7c478bd9Sstevel@tonic-gate name, domain, class, type); 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate #endif 245*7c478bd9Sstevel@tonic-gate if (domain == NULL) { 246*7c478bd9Sstevel@tonic-gate /* 247*7c478bd9Sstevel@tonic-gate * Check for trailing '.'; 248*7c478bd9Sstevel@tonic-gate * copy without '.' if present. 249*7c478bd9Sstevel@tonic-gate */ 250*7c478bd9Sstevel@tonic-gate n = strlen(name) - 1; 251*7c478bd9Sstevel@tonic-gate if (name[n] == '.' && n < sizeof (nbuf) - 1) { 252*7c478bd9Sstevel@tonic-gate #ifdef SYSV 253*7c478bd9Sstevel@tonic-gate memcpy((void *)nbuf, (void *)name, n); 254*7c478bd9Sstevel@tonic-gate #else 255*7c478bd9Sstevel@tonic-gate bcopy(name, nbuf, n); 256*7c478bd9Sstevel@tonic-gate #endif 257*7c478bd9Sstevel@tonic-gate nbuf[n] = '\0'; 258*7c478bd9Sstevel@tonic-gate } else 259*7c478bd9Sstevel@tonic-gate longname = name; 260*7c478bd9Sstevel@tonic-gate } else 261*7c478bd9Sstevel@tonic-gate (void) sprintf(nbuf, "%.*s.%.*s", 262*7c478bd9Sstevel@tonic-gate MAXDNAME, name, MAXDNAME, domain); 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate return (res_query(longname, class, type, answer, anslen)); 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate char * 268*7c478bd9Sstevel@tonic-gate hostalias(name) 269*7c478bd9Sstevel@tonic-gate register char *name; 270*7c478bd9Sstevel@tonic-gate { 271*7c478bd9Sstevel@tonic-gate register char *C1, *C2; 272*7c478bd9Sstevel@tonic-gate FILE *fp; 273*7c478bd9Sstevel@tonic-gate char *file, *getenv(), *strcpy(), *strncpy(); 274*7c478bd9Sstevel@tonic-gate char buf[BUFSIZ]; 275*7c478bd9Sstevel@tonic-gate static char abuf[MAXDNAME]; 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate file = getenv("HOSTALIASES"); 278*7c478bd9Sstevel@tonic-gate if (file == NULL || (fp = fopen(file, "r")) == NULL) 279*7c478bd9Sstevel@tonic-gate return (NULL); 280*7c478bd9Sstevel@tonic-gate buf[sizeof (buf) - 1] = '\0'; 281*7c478bd9Sstevel@tonic-gate while (fgets(buf, sizeof (buf), fp)) { 282*7c478bd9Sstevel@tonic-gate for (C1 = buf; *C1 && !isspace(*C1); ++C1); 283*7c478bd9Sstevel@tonic-gate if (!*C1) 284*7c478bd9Sstevel@tonic-gate break; 285*7c478bd9Sstevel@tonic-gate *C1 = '\0'; 286*7c478bd9Sstevel@tonic-gate if (!strcasecmp(buf, name)) { 287*7c478bd9Sstevel@tonic-gate while (isspace(*++C1)); 288*7c478bd9Sstevel@tonic-gate if (!*C1) 289*7c478bd9Sstevel@tonic-gate break; 290*7c478bd9Sstevel@tonic-gate for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2); 291*7c478bd9Sstevel@tonic-gate abuf[sizeof (abuf) - 1] = *C2 = '\0'; 292*7c478bd9Sstevel@tonic-gate (void) strncpy(abuf, C1, sizeof (abuf) - 1); 293*7c478bd9Sstevel@tonic-gate fclose(fp); 294*7c478bd9Sstevel@tonic-gate return (abuf); 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate fclose(fp); 298*7c478bd9Sstevel@tonic-gate return (NULL); 299*7c478bd9Sstevel@tonic-gate } 300