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
42 #include <sys/types.h>
43 #include <sys/socket.h>
45 #include <netinet/in.h>
46 #include <arpa/nameser.h>
56 * Kludge to time out quickly if there is no /etc/resolv.conf
57 * and a TCP connection to the local DNS server fails.
59 * Moved function from res_send.c to res_mkquery.c. This
60 * solves a long timeout problem with nslookup.
62 * __areweinnamed is needed because there is a possibility that the
63 * user might do bad things to resolv.conf and cause in.named to call
64 * _confcheck and deadlock the server.
72 static int _confcheck()
76 struct sockaddr_in ns_sin
;
79 /* First, we check to see if /etc/resolv.conf exists.
80 * If it doesn't, then localhost is mostlikely to be
83 if (stat(_PATH_RESCONF
, &rc_stat
) == -1 && errno
== ENOENT
) {
85 /* Next, we check to see if _res.nsaddr is set to loopback.
86 * If it isn't, it has been altered by the application
87 * explicitly and we then want to bail with success.
92 if (_res
.nsaddr
.sin_addr
.S_un
.S_addr
== htonl(INADDR_LOOPBACK
)) {
94 /* Lastly, we try to connect to the TCP port of the
95 * nameserver. If this fails, then we know that
96 * DNS is misconfigured and we can quickly exit.
98 ns
= socket(AF_INET
, SOCK_STREAM
, 0);
99 IN_SET_LOOPBACK_ADDR(&ns_sin
);
100 ns_sin
.sin_port
= htons(NAMESERVER_PORT
);
101 if (connect(ns
, (struct sockaddr
*) &ns_sin
,
102 sizeof ns_sin
) == -1) {
119 * Form all types of queries.
120 * Returns the size of the result or -1.
123 res_mkquery(op
, dname
, class, type
, data
, datalen
, newrr
, buf
, buflen
)
124 int op
; /* opcode of query */
125 char *dname
; /* domain name */
126 int class, type
; /* class and type of query */
127 char *data
; /* resource record data */
128 int datalen
; /* length of data */
129 struct rrec
*newrr
; /* new rr for modify or append */
130 char *buf
; /* buffer to put query */
131 int buflen
; /* size of buffer */
136 u_char
*dnptrs
[10], **dpp
, **lastdnptr
;
139 if (_res
.options
& RES_DEBUG
)
140 printf("res_mkquery(%d, %s, %d, %d)\n", op
, dname
, class, type
);
144 * Check to see if we can bailout quickly.
145 * Also rerun res_init if we failed in the past.
148 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1) {
149 h_errno
= NO_RECOVERY
;
153 if (_confcheck() == -1) {
154 _res
.options
&= ~RES_INIT
;
155 h_errno
= NO_RECOVERY
;
160 * Initialize header fields.
162 if ((buf
== NULL
) || (buflen
< sizeof (HEADER
)))
165 (void) memset(buf
, 0, sizeof (HEADER
));
167 bzero(buf
, sizeof (HEADER
));
170 hp
->id
= htons(++_res
.id
);
172 hp
->pr
= (_res
.options
& RES_PRIMARY
) != 0;
173 hp
->rd
= (_res
.options
& RES_RECURSE
) != 0;
175 cp
= (u_char
*)(buf
+ sizeof (HEADER
));
176 buflen
-= sizeof (HEADER
);
178 *dpp
++ = (u_char
*)buf
;
180 lastdnptr
= dnptrs
+ sizeof (dnptrs
) / sizeof (dnptrs
[0]);
182 * perform opcode specific processing
186 if ((buflen
-= QFIXEDSZ
) < 0)
188 if ((n
= dn_comp((u_char
*)dname
, cp
, buflen
,
189 dnptrs
, lastdnptr
)) < 0)
194 cp
+= sizeof (u_short
);
196 cp
+= sizeof (u_short
);
197 hp
->qdcount
= htons(1);
198 if (op
== QUERY
|| data
== NULL
)
201 * Make an additional record for completion domain.
204 if ((n
= dn_comp((u_char
*)data
, cp
, buflen
,
205 dnptrs
, lastdnptr
)) < 0)
209 putshort(T_NULL
, cp
);
210 cp
+= sizeof (u_short
);
212 cp
+= sizeof (u_short
);
214 cp
+= sizeof (u_long
);
216 cp
+= sizeof (u_short
);
217 hp
->arcount
= htons(1);
222 * Initialize answer section
224 if (buflen
< 1 + RRFIXEDSZ
+ datalen
)
226 *cp
++ = '\0'; /* no domain name */
228 cp
+= sizeof (u_short
);
230 cp
+= sizeof (u_short
);
232 cp
+= sizeof (u_long
);
233 putshort(datalen
, cp
);
234 cp
+= sizeof (u_short
);
237 (void) memcpy((void *)cp
, (void *)data
, datalen
);
239 bcopy(data
, cp
, datalen
);
243 hp
->ancount
= htons(1);
248 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
249 * (Record to be modified is followed by its replacement in msg.)
256 * The res code for UPDATED and UPDATEDA is the same; user
257 * calls them differently: specifies data for UPDATED; server
258 * ignores data if specified for UPDATEDA.
261 buflen
-= RRFIXEDSZ
+ datalen
;
262 if ((n
= dn_comp((u_char
*)dname
, cp
, buflen
,
263 dnptrs
, lastdnptr
)) < 0)
267 cp
+= sizeof (u_short
);
269 cp
+= sizeof (u_short
);
271 cp
+= sizeof (u_long
);
272 putshort(datalen
, cp
);
273 cp
+= sizeof (u_short
);
276 memcpy((void *)cp
, (void *)data
, datalen
);
278 bcopy(data
, cp
, datalen
);
282 if ((op
== UPDATED
) || (op
== UPDATEDA
)) {
283 hp
->ancount
= htons(0);
286 /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
288 case UPDATEA
: /* Add new resource record */
289 buflen
-= RRFIXEDSZ
+ datalen
;
290 if ((n
= dn_comp((u_char
*)dname
, cp
, buflen
,
291 dnptrs
, lastdnptr
)) < 0)
294 putshort(newrr
->r_type
, cp
);
295 cp
+= sizeof (u_short
);
296 putshort(newrr
->r_class
, cp
);
297 cp
+= sizeof (u_short
);
299 cp
+= sizeof (u_long
);
300 putshort(newrr
->r_size
, cp
);
301 cp
+= sizeof (u_short
);
304 memcpy((void *)cp
, newrr
->r_data
, newrr
->r_size
);
306 bcopy(newrr
->r_data
, cp
, newrr
->r_size
);
310 hp
->ancount
= htons(0);
313 #endif /* ALLOW_UPDATES */
315 return ((char *)cp
- buf
);