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