4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
40 #pragma ident "%Z%%M% %I% %E% SMI"
42 #include <sys/param.h>
43 #include <sys/socket.h>
44 #include <netinet/in.h>
50 #include <arpa/inet.h>
51 #include <arpa/nameser.h>
55 #define MAXPACKET PACKETSZ
57 #define MAXPACKET 1024
63 * Formulate a normal query, send, and await answer.
64 * Returned answer is placed in supplied buffer "answer".
65 * Perform preliminary check of answer, returning success only
66 * if no error is indicated and the answer count is nonzero.
67 * Return the size of the response on success, -1 on error.
68 * Error number is left in h_errno.
69 * Caller must parse answer and determine whether it answers the question.
72 res_query(name
, class, type
, answer
, anslen
)
73 char *name
; /* domain name */
74 int class, type
; /* class and type of query */
75 u_char
*answer
; /* buffer to put answer */
76 int anslen
; /* size of answer buffer */
82 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1)
85 if (_res
.options
& RES_DEBUG
)
86 printf("res_query(%s, %d, %d)\n", name
, class, type
);
88 n
= res_mkquery(QUERY
, name
, class, type
, (char *)NULL
, 0, NULL
,
93 if (_res
.options
& RES_DEBUG
)
94 printf("res_query: mkquery failed\n");
96 h_errno
= NO_RECOVERY
;
99 n
= res_send(buf
, n
, answer
, anslen
);
102 if (_res
.options
& RES_DEBUG
)
103 printf("res_query: send error\n");
109 hp
= (HEADER
*) answer
;
110 if (hp
->rcode
!= NOERROR
|| ntohs(hp
->ancount
) == 0) {
112 if (_res
.options
& RES_DEBUG
)
113 printf("rcode = %d, ancount=%d\n", hp
->rcode
,
118 h_errno
= HOST_NOT_FOUND
;
130 h_errno
= NO_RECOVERY
;
135 if (hp
->rcode
== NOERROR
&& ntohs(hp
->ancount
) > 0)
141 * Formulate a normal query, send, and retrieve answer in supplied buffer.
142 * Return the size of the response on success, -1 on error.
143 * If enabled, implement search rules until answer or unrecoverable failure
144 * is detected. Error number is left in h_errno.
145 * Only useful for queries in the same name hierarchy as the local host
146 * (not, for example, for host address-to-name lookups in domain in-addr.arpa).
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 */
155 register char *cp
, **domain
;
156 int n
, ret
, got_nodata
= 0;
159 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1)
163 h_errno
= HOST_NOT_FOUND
; /* default, if we never query */
164 for (cp
= name
, n
= 0; *cp
; cp
++)
167 if (n
== 0 && (cp
= hostalias(name
)))
168 return (res_query(cp
, class, type
, answer
, anslen
));
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.
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
,
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.
195 if (errno
== ECONNREFUSED
) {
199 if (h_errno
== NO_DATA
)
201 if ((h_errno
!= HOST_NOT_FOUND
&& h_errno
!= NO_DATA
) ||
202 (_res
.options
& RES_DNSRCH
) == 0)
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
213 if (n
&& (ret
= res_querydomain(name
, (char *)NULL
, class, type
,
214 answer
, anslen
)) > 0)
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.
226 res_querydomain(name
, domain
, class, type
, answer
, anslen
)
228 int class, type
; /* class and type of query */
229 u_char
*answer
; /* buffer to put answer */
230 int anslen
; /* size of answer */
232 char nbuf
[2*MAXDNAME
+2];
233 char *longname
= nbuf
;
237 if (_res
.options
& RES_DEBUG
) {
238 if (domain
== (char *)NULL
)
239 printf("res_querydomain(%s, NULL, %d, %d)\n",
242 printf("res_querydomain(%s, %s, %d, %d)\n",
243 name
, domain
, class, type
);
246 if (domain
== NULL
) {
248 * Check for trailing '.';
249 * copy without '.' if present.
251 n
= strlen(name
) - 1;
252 if (name
[n
] == '.' && n
< sizeof (nbuf
) - 1) {
254 memcpy((void *)nbuf
, (void *)name
, n
);
256 bcopy(name
, nbuf
, n
);
262 (void) sprintf(nbuf
, "%.*s.%.*s",
263 MAXDNAME
, name
, MAXDNAME
, domain
);
265 return (res_query(longname
, class, type
, answer
, anslen
));
272 register char *C1
, *C2
;
274 char *file
, *getenv(), *strcpy(), *strncpy();
276 static char abuf
[MAXDNAME
];
278 file
= getenv("HOSTALIASES");
279 if (file
== NULL
|| (fp
= fopen(file
, "r")) == NULL
)
281 buf
[sizeof (buf
) - 1] = '\0';
282 while (fgets(buf
, sizeof (buf
), fp
)) {
283 for (C1
= buf
; *C1
&& !isspace(*C1
); ++C1
);
287 if (!strcasecmp(buf
, name
)) {
288 while (isspace(*++C1
));
291 for (C2
= C1
+ 1; *C2
&& !isspace(*C2
); ++C2
);
292 abuf
[sizeof (abuf
) - 1] = *C2
= '\0';
293 (void) strncpy(abuf
, C1
, sizeof (abuf
) - 1);