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"
43 #include <sys/types.h>
44 #include <sys/socket.h>
46 #include <netinet/in.h>
47 #include <arpa/nameser.h>
53 * Kludge to time out quickly if there is no /etc/resolv.conf
54 * and a TCP connection to the local DNS server fails.
56 * Moved function from res_send.c to res_mkquery.c. This
57 * solves a long timeout problem with nslookup.
59 * __areweinnamed is needed because there is a possibility that the
60 * user might do bad things to resolv.conf and cause in.named to call
61 * _confcheck and deadlock the server.
69 static int _confcheck()
73 struct sockaddr_in ns_sin
;
76 /* First, we check to see if /etc/resolv.conf exists.
77 * If it doesn't, then localhost is mostlikely to be
80 if (stat(_PATH_RESCONF
, &rc_stat
) == -1 && errno
== ENOENT
) {
82 /* Next, we check to see if _res.nsaddr is set to loopback.
83 * If it isn't, it has been altered by the application
84 * explicitly and we then want to bail with success.
89 if (_res
.nsaddr
.sin_addr
.S_un
.S_addr
== htonl(INADDR_LOOPBACK
)) {
91 /* Lastly, we try to connect to the TCP port of the
92 * nameserver. If this fails, then we know that
93 * DNS is misconfigured and we can quickly exit.
95 ns
= socket(AF_INET
, SOCK_STREAM
, 0);
96 IN_SET_LOOPBACK_ADDR(&ns_sin
);
97 ns_sin
.sin_port
= htons(NAMESERVER_PORT
);
98 if (connect(ns
, (struct sockaddr
*) &ns_sin
,
99 sizeof ns_sin
) == -1) {
116 * Form all types of queries.
117 * Returns the size of the result or -1.
120 res_mkquery(op
, dname
, class, type
, data
, datalen
, newrr
, buf
, buflen
)
121 int op
; /* opcode of query */
122 char *dname
; /* domain name */
123 int class, type
; /* class and type of query */
124 char *data
; /* resource record data */
125 int datalen
; /* length of data */
126 struct rrec
*newrr
; /* new rr for modify or append */
127 char *buf
; /* buffer to put query */
128 int buflen
; /* size of buffer */
133 char *dnptrs
[10], **dpp
, **lastdnptr
;
136 if (_res
.options
& RES_DEBUG
)
137 printf("res_mkquery(%d, %s, %d, %d)\n", op
, dname
, class, type
);
141 * Check to see if we can bailout quickly.
142 * Also rerun res_init if we failed in the past.
145 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1) {
146 h_errno
= NO_RECOVERY
;
150 if (_confcheck() == -1) {
151 _res
.options
&= ~RES_INIT
;
152 h_errno
= NO_RECOVERY
;
157 * Initialize header fields.
159 if ((buf
== NULL
) || (buflen
< sizeof (HEADER
)))
162 memset(buf
, 0, sizeof (HEADER
));
164 bzero(buf
, sizeof (HEADER
));
167 hp
->id
= htons(++_res
.id
);
169 hp
->pr
= (_res
.options
& RES_PRIMARY
) != 0;
170 hp
->rd
= (_res
.options
& RES_RECURSE
) != 0;
172 cp
= buf
+ sizeof (HEADER
);
173 buflen
-= sizeof (HEADER
);
177 lastdnptr
= dnptrs
+ sizeof (dnptrs
) / sizeof (dnptrs
[0]);
179 * perform opcode specific processing
183 if ((buflen
-= QFIXEDSZ
) < 0)
185 if ((n
= dn_comp(dname
, cp
, buflen
, dnptrs
, lastdnptr
)) < 0)
190 cp
+= sizeof (u_short
);
192 cp
+= sizeof (u_short
);
193 hp
->qdcount
= htons(1);
194 if (op
== QUERY
|| data
== NULL
)
197 * Make an additional record for completion domain.
200 if ((n
= dn_comp(data
, cp
, buflen
, dnptrs
, lastdnptr
)) < 0)
204 putshort(T_NULL
, cp
);
205 cp
+= sizeof (u_short
);
207 cp
+= sizeof (u_short
);
209 cp
+= sizeof (u_long
);
211 cp
+= sizeof (u_short
);
212 hp
->arcount
= htons(1);
217 * Initialize answer section
219 if (buflen
< 1 + RRFIXEDSZ
+ datalen
)
221 *cp
++ = '\0'; /* no domain name */
223 cp
+= sizeof (u_short
);
225 cp
+= sizeof (u_short
);
227 cp
+= sizeof (u_long
);
228 putshort(datalen
, cp
);
229 cp
+= sizeof (u_short
);
232 memcpy((void *)cp
, (void *)data
, datalen
);
234 bcopy(data
, cp
, datalen
);
238 hp
->ancount
= htons(1);
243 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
244 * (Record to be modified is followed by its replacement in msg.)
251 * The res code for UPDATED and UPDATEDA is the same; user
252 * calls them differently: specifies data for UPDATED; server
253 * ignores data if specified for UPDATEDA.
256 buflen
-= RRFIXEDSZ
+ datalen
;
257 if ((n
= dn_comp(dname
, cp
, buflen
, dnptrs
, lastdnptr
)) < 0)
261 cp
+= sizeof (u_short
);
263 cp
+= sizeof (u_short
);
265 cp
+= sizeof (u_long
);
266 putshort(datalen
, cp
);
267 cp
+= sizeof (u_short
);
270 memcpy((void *)cp
, (void *)data
, datalen
);
272 bcopy(data
, cp
, datalen
);
276 if ((op
== UPDATED
) || (op
== UPDATEDA
)) {
277 hp
->ancount
= htons(0);
280 /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
282 case UPDATEA
: /* Add new resource record */
283 buflen
-= RRFIXEDSZ
+ datalen
;
284 if ((n
= dn_comp(dname
, cp
, buflen
, dnptrs
, lastdnptr
)) < 0)
287 putshort(newrr
->r_type
, cp
);
288 cp
+= sizeof (u_short
);
289 putshort(newrr
->r_class
, cp
);
290 cp
+= sizeof (u_short
);
292 cp
+= sizeof (u_long
);
293 putshort(newrr
->r_size
, cp
);
294 cp
+= sizeof (u_short
);
297 memcpy((void *)cp
, newrr
->r_data
, newrr
->r_size
);
299 bcopy(newrr
->r_data
, cp
, newrr
->r_size
);
303 hp
->ancount
= htons(0);
306 #endif /* ALLOW_UPDATES */