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 2015 Gary Mills
24 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
32 * University Copyright- Copyright (c) 1982, 1986, 1988
33 * The Regents of the University of California
36 * University Acknowledgment- Portions of this document are derived from
37 * software developed by the University of California, Berkeley, and its
41 #include <sys/param.h>
42 #include <sys/socket.h>
43 #include <netinet/in.h>
50 #include <arpa/inet.h>
51 #include <arpa/nameser.h>
56 #define MAXPACKET PACKETSZ
58 #define MAXPACKET 1024
64 * Formulate a normal query, send, and await answer.
65 * Returned answer is placed in supplied buffer "answer".
66 * Perform preliminary check of answer, returning success only
67 * if no error is indicated and the answer count is nonzero.
68 * Return the size of the response on success, -1 on error.
69 * Error number is left in h_errno.
70 * Caller must parse answer and determine whether it answers the question.
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 */
83 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1)
86 if (_res
.options
& RES_DEBUG
)
87 printf("res_query(%s, %d, %d)\n", name
, class, type
);
89 n
= res_mkquery(QUERY
, name
, class, type
, (char *)NULL
, 0, NULL
,
94 if (_res
.options
& RES_DEBUG
)
95 printf("res_query: mkquery failed\n");
97 h_errno
= NO_RECOVERY
;
100 n
= res_send(buf
, n
, (char *)answer
, anslen
);
103 if (_res
.options
& RES_DEBUG
)
104 printf("res_query: send error\n");
110 hp
= (HEADER
*) answer
;
111 if (hp
->rcode
!= NOERROR
|| ntohs(hp
->ancount
) == 0) {
113 if (_res
.options
& RES_DEBUG
)
114 printf("rcode = %d, ancount=%d\n", hp
->rcode
,
119 h_errno
= HOST_NOT_FOUND
;
131 h_errno
= NO_RECOVERY
;
136 if (hp
->rcode
== NOERROR
&& ntohs(hp
->ancount
) > 0)
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).
150 res_search(name
, class, type
, answer
, anslen
)
151 char *name
; /* domain name */
152 int class, type
; /* class and type of query */
153 u_char
*answer
; /* buffer to put answer */
154 int anslen
; /* size of answer */
156 register char *cp
, **domain
;
157 int n
, ret
, got_nodata
= 0;
160 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1)
164 h_errno
= HOST_NOT_FOUND
; /* default, if we never query */
165 for (cp
= name
, n
= 0; *cp
; cp
++)
168 if (n
== 0 && (cp
= hostalias(name
)))
169 return (res_query(cp
, class, type
, answer
, anslen
));
172 * We do at least one level of search if
173 * - there is no dot and RES_DEFNAME is set, or
174 * - there is at least one dot, there is no trailing dot,
175 * and RES_DNSRCH is set.
177 if ((n
== 0 && _res
.options
& RES_DEFNAMES
) ||
178 (n
!= 0 && *--cp
!= '.' && _res
.options
& RES_DNSRCH
)) {
179 for (domain
= _res
.dnsrch
; *domain
; domain
++) {
180 ret
= res_querydomain(name
, *domain
, class, type
,
185 * If no server present, give up.
186 * If name isn't found in this domain,
187 * keep trying higher domains in the search list
188 * (if that's enabled).
189 * On a NO_DATA error, keep trying, otherwise
190 * a wildcard entry of another type could keep us
191 * from finding this entry higher in the domain.
192 * If we get some other error (negative answer or
193 * server failure), then stop searching up,
194 * but try the input name below in case it's fully-qualified.
196 if (errno
== ECONNREFUSED
) {
200 if (h_errno
== NO_DATA
)
202 if ((h_errno
!= HOST_NOT_FOUND
&& h_errno
!= NO_DATA
) ||
203 (_res
.options
& RES_DNSRCH
) == 0)
208 * If the search/default failed, try the name as fully-qualified,
209 * but only if it contained at least one dot (even trailing).
210 * This is purely a heuristic; we assume that any reasonable query
211 * about a top-level domain (for servers, SOA, etc) will not use
214 if (n
&& (ret
= res_querydomain(name
, (char *)NULL
, class, type
,
215 answer
, anslen
)) > 0)
223 * Perform a call on res_query on the concatenation of name and domain,
224 * removing a trailing dot from name if domain is NULL.
227 res_querydomain(name
, domain
, class, type
, answer
, anslen
)
229 int class, type
; /* class and type of query */
230 u_char
*answer
; /* buffer to put answer */
231 int anslen
; /* size of answer */
233 char nbuf
[2*MAXDNAME
+2];
234 char *longname
= nbuf
;
238 if (_res
.options
& RES_DEBUG
) {
239 if (domain
== (char *)NULL
)
240 printf("res_querydomain(%s, NULL, %d, %d)\n",
243 printf("res_querydomain(%s, %s, %d, %d)\n",
244 name
, domain
, class, type
);
247 if (domain
== NULL
) {
249 * Check for trailing '.';
250 * copy without '.' if present.
252 n
= strlen(name
) - 1;
253 if (name
[n
] == '.' && n
< sizeof (nbuf
) - 1) {
255 memcpy((void *)nbuf
, (void *)name
, n
);
257 bcopy(name
, nbuf
, n
);
263 (void) sprintf(nbuf
, "%.*s.%.*s",
264 MAXDNAME
, name
, MAXDNAME
, domain
);
266 return (res_query(longname
, class, type
, answer
, anslen
));
273 register char *C1
, *C2
;
277 static char abuf
[MAXDNAME
];
279 file
= getenv("HOSTALIASES");
280 if (file
== NULL
|| (fp
= fopen(file
, "r")) == NULL
)
282 buf
[sizeof (buf
) - 1] = '\0';
283 while (fgets(buf
, sizeof (buf
), fp
)) {
284 for (C1
= buf
; *C1
&& !isspace(*C1
); ++C1
);
288 if (!strcasecmp(buf
, name
)) {
289 while (isspace(*++C1
));
292 for (C2
= C1
+ 1; *C2
&& !isspace(*C2
); ++C2
);
293 abuf
[sizeof (abuf
) - 1] = *C2
= '\0';
294 (void) strncpy(abuf
, C1
, sizeof (abuf
) - 1);