3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 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 <stdio.h>
43 #include <sys/types.h>
44 #include <sys/socket.h>
45 #include <sys/stat.h>
46 #include <netinet/in.h>
47 #include <arpa/nameser.h>
48 #include <resolv.h>
49 #include <errno.h>
50 #include <netdb.h>
51
52 /*
53 * Kludge to time out quickly if there is no /etc/resolv.conf
54 * and a TCP connection to the local DNS server fails.
55 *
56 * Moved function from res_send.c to res_mkquery.c. This
57 * solves a long timeout problem with nslookup.
58 *
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.
62 */
63
64 int __areweinnamed()
65 {
66 return (0);
67 }
68
69 static int _confcheck()
70 {
80 if (stat(_PATH_RESCONF, &rc_stat) == -1 && errno == ENOENT) {
81
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.
85 */
86 if (__areweinnamed())
87 return (0);
88
89 if (_res.nsaddr.sin_addr.S_un.S_addr == htonl(INADDR_LOOPBACK)) {
90
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.
94 */
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) {
100 close(ns);
101 return(-1);
102 }
103 else {
104 close(ns);
105 return(0);
106 }
107 }
108
109 return(0);
110 }
111
112 return (0);
113 }
114
115 /*
116 * Form all types of queries.
117 * Returns the size of the result or -1.
118 */
119 int
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 */
129 {
130 register HEADER *hp;
131 register char *cp;
132 register int n;
133 char *dnptrs[10], **dpp, **lastdnptr;
134
135 #ifdef DEBUG
136 if (_res.options & RES_DEBUG)
137 printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type);
138 #endif /* DEBUG */
139
140 /*
141 * Check to see if we can bailout quickly.
142 * Also rerun res_init if we failed in the past.
143 */
144
145 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
146 h_errno = NO_RECOVERY;
147 return(-1);
148 }
149
150 if (_confcheck() == -1) {
151 _res.options &= ~RES_INIT;
152 h_errno = NO_RECOVERY;
153 return(-1);
154 }
155
156 /*
157 * Initialize header fields.
158 */
159 if ((buf == NULL) || (buflen < sizeof (HEADER)))
160 return (-1);
161 #ifdef SYSV
162 memset(buf, 0, sizeof (HEADER));
163 #else
164 bzero(buf, sizeof (HEADER));
165 #endif
166 hp = (HEADER *) buf;
167 hp->id = htons(++_res.id);
168 hp->opcode = op;
169 hp->pr = (_res.options & RES_PRIMARY) != 0;
170 hp->rd = (_res.options & RES_RECURSE) != 0;
171 hp->rcode = NOERROR;
172 cp = buf + sizeof (HEADER);
173 buflen -= sizeof (HEADER);
174 dpp = dnptrs;
175 *dpp++ = buf;
176 *dpp++ = NULL;
177 lastdnptr = dnptrs + sizeof (dnptrs) / sizeof (dnptrs[0]);
178 /*
179 * perform opcode specific processing
180 */
181 switch (op) {
182 case QUERY:
183 if ((buflen -= QFIXEDSZ) < 0)
184 return (-1);
185 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
186 return (-1);
187 cp += n;
188 buflen -= n;
189 putshort(type, cp);
190 cp += sizeof (u_short);
191 putshort(class, cp);
192 cp += sizeof (u_short);
193 hp->qdcount = htons(1);
194 if (op == QUERY || data == NULL)
195 break;
196 /*
197 * Make an additional record for completion domain.
198 */
199 buflen -= RRFIXEDSZ;
200 if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0)
201 return (-1);
202 cp += n;
203 buflen -= n;
204 putshort(T_NULL, cp);
205 cp += sizeof (u_short);
206 putshort(class, cp);
207 cp += sizeof (u_short);
208 putlong(0, cp);
209 cp += sizeof (u_long);
210 putshort(0, cp);
211 cp += sizeof (u_short);
212 hp->arcount = htons(1);
213 break;
214
215 case IQUERY:
216 /*
217 * Initialize answer section
218 */
219 if (buflen < 1 + RRFIXEDSZ + datalen)
220 return (-1);
221 *cp++ = '\0'; /* no domain name */
222 putshort(type, cp);
223 cp += sizeof (u_short);
224 putshort(class, cp);
225 cp += sizeof (u_short);
226 putlong(0, cp);
227 cp += sizeof (u_long);
228 putshort(datalen, cp);
229 cp += sizeof (u_short);
230 if (datalen) {
231 #ifdef SYSV
232 memcpy((void *)cp, (void *)data, datalen);
233 #else
234 bcopy(data, cp, datalen);
235 #endif
236 cp += datalen;
237 }
238 hp->ancount = htons(1);
239 break;
240
241 #ifdef ALLOW_UPDATES
242 /*
243 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
244 * (Record to be modified is followed by its replacement in msg.)
245 */
246 case UPDATEM:
247 case UPDATEMA:
248
249 case UPDATED:
250 /*
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.
254 */
255 case UPDATEDA:
256 buflen -= RRFIXEDSZ + datalen;
257 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
258 return (-1);
259 cp += n;
260 putshort(type, cp);
261 cp += sizeof (u_short);
262 putshort(class, cp);
263 cp += sizeof (u_short);
264 putlong(0, cp);
265 cp += sizeof (u_long);
266 putshort(datalen, cp);
267 cp += sizeof (u_short);
268 if (datalen) {
269 #ifdef SYSV
270 memcpy((void *)cp, (void *)data, datalen);
271 #else
272 bcopy(data, cp, datalen);
273 #endif
274 cp += datalen;
275 }
276 if ((op == UPDATED) || (op == UPDATEDA)) {
277 hp->ancount = htons(0);
278 break;
279 }
280 /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
281
282 case UPDATEA: /* Add new resource record */
283 buflen -= RRFIXEDSZ + datalen;
284 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
285 return (-1);
286 cp += n;
287 putshort(newrr->r_type, cp);
288 cp += sizeof (u_short);
289 putshort(newrr->r_class, cp);
290 cp += sizeof (u_short);
291 putlong(0, cp);
292 cp += sizeof (u_long);
293 putshort(newrr->r_size, cp);
294 cp += sizeof (u_short);
295 if (newrr->r_size) {
296 #ifdef SYSV
297 memcpy((void *)cp, newrr->r_data, newrr->r_size);
298 #else
299 bcopy(newrr->r_data, cp, newrr->r_size);
300 #endif
301 cp += newrr->r_size;
302 }
303 hp->ancount = htons(0);
304 break;
305
306 #endif /* ALLOW_UPDATES */
307 }
308 return (cp - buf);
309 }
|
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2015 Gary Mills
24 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
30
31 /*
32 * University Copyright- Copyright (c) 1982, 1986, 1988
33 * The Regents of the University of California
34 * All Rights Reserved
35 *
36 * University Acknowledgment- Portions of this document are derived from
37 * software developed by the University of California, Berkeley, and its
38 * contributors.
39 */
40
41 #include <stdio.h>
42 #include <sys/types.h>
43 #include <sys/socket.h>
44 #include <sys/stat.h>
45 #include <netinet/in.h>
46 #include <arpa/nameser.h>
47 #include <resolv.h>
48 #include <string.h>
49 #include <stdlib.h>
50 #include <unistd.h>
51 #include <errno.h>
52 #include <netdb.h>
53 #include "crossl.h"
54
55 /*
56 * Kludge to time out quickly if there is no /etc/resolv.conf
57 * and a TCP connection to the local DNS server fails.
58 *
59 * Moved function from res_send.c to res_mkquery.c. This
60 * solves a long timeout problem with nslookup.
61 *
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.
65 */
66
67 int __areweinnamed()
68 {
69 return (0);
70 }
71
72 static int _confcheck()
73 {
83 if (stat(_PATH_RESCONF, &rc_stat) == -1 && errno == ENOENT) {
84
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.
88 */
89 if (__areweinnamed())
90 return (0);
91
92 if (_res.nsaddr.sin_addr.S_un.S_addr == htonl(INADDR_LOOPBACK)) {
93
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.
97 */
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) {
103 (void) close(ns);
104 return(-1);
105 }
106 else {
107 (void) close(ns);
108 return(0);
109 }
110 }
111
112 return(0);
113 }
114
115 return (0);
116 }
117
118 /*
119 * Form all types of queries.
120 * Returns the size of the result or -1.
121 */
122 int
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 */
132 {
133 register HEADER *hp;
134 register u_char *cp;
135 register int n;
136 u_char *dnptrs[10], **dpp, **lastdnptr;
137
138 #ifdef DEBUG
139 if (_res.options & RES_DEBUG)
140 printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type);
141 #endif /* DEBUG */
142
143 /*
144 * Check to see if we can bailout quickly.
145 * Also rerun res_init if we failed in the past.
146 */
147
148 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
149 h_errno = NO_RECOVERY;
150 return(-1);
151 }
152
153 if (_confcheck() == -1) {
154 _res.options &= ~RES_INIT;
155 h_errno = NO_RECOVERY;
156 return(-1);
157 }
158
159 /*
160 * Initialize header fields.
161 */
162 if ((buf == NULL) || (buflen < sizeof (HEADER)))
163 return (-1);
164 #ifdef SYSV
165 (void) memset(buf, 0, sizeof (HEADER));
166 #else
167 bzero(buf, sizeof (HEADER));
168 #endif
169 hp = (HEADER *) buf;
170 hp->id = htons(++_res.id);
171 hp->opcode = op;
172 hp->pr = (_res.options & RES_PRIMARY) != 0;
173 hp->rd = (_res.options & RES_RECURSE) != 0;
174 hp->rcode = NOERROR;
175 cp = (u_char *)(buf + sizeof (HEADER));
176 buflen -= sizeof (HEADER);
177 dpp = dnptrs;
178 *dpp++ = (u_char *)buf;
179 *dpp++ = NULL;
180 lastdnptr = dnptrs + sizeof (dnptrs) / sizeof (dnptrs[0]);
181 /*
182 * perform opcode specific processing
183 */
184 switch (op) {
185 case QUERY:
186 if ((buflen -= QFIXEDSZ) < 0)
187 return (-1);
188 if ((n = dn_comp((u_char *)dname, cp, buflen,
189 dnptrs, lastdnptr)) < 0)
190 return (-1);
191 cp += n;
192 buflen -= n;
193 putshort(type, cp);
194 cp += sizeof (u_short);
195 putshort(class, cp);
196 cp += sizeof (u_short);
197 hp->qdcount = htons(1);
198 if (op == QUERY || data == NULL)
199 break;
200 /*
201 * Make an additional record for completion domain.
202 */
203 buflen -= RRFIXEDSZ;
204 if ((n = dn_comp((u_char *)data, cp, buflen,
205 dnptrs, lastdnptr)) < 0)
206 return (-1);
207 cp += n;
208 buflen -= n;
209 putshort(T_NULL, cp);
210 cp += sizeof (u_short);
211 putshort(class, cp);
212 cp += sizeof (u_short);
213 putlong(0, cp);
214 cp += sizeof (u_long);
215 putshort(0, cp);
216 cp += sizeof (u_short);
217 hp->arcount = htons(1);
218 break;
219
220 case IQUERY:
221 /*
222 * Initialize answer section
223 */
224 if (buflen < 1 + RRFIXEDSZ + datalen)
225 return (-1);
226 *cp++ = '\0'; /* no domain name */
227 putshort(type, cp);
228 cp += sizeof (u_short);
229 putshort(class, cp);
230 cp += sizeof (u_short);
231 putlong(0, cp);
232 cp += sizeof (u_long);
233 putshort(datalen, cp);
234 cp += sizeof (u_short);
235 if (datalen) {
236 #ifdef SYSV
237 (void) memcpy((void *)cp, (void *)data, datalen);
238 #else
239 bcopy(data, cp, datalen);
240 #endif
241 cp += datalen;
242 }
243 hp->ancount = htons(1);
244 break;
245
246 #ifdef ALLOW_UPDATES
247 /*
248 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
249 * (Record to be modified is followed by its replacement in msg.)
250 */
251 case UPDATEM:
252 case UPDATEMA:
253
254 case UPDATED:
255 /*
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.
259 */
260 case UPDATEDA:
261 buflen -= RRFIXEDSZ + datalen;
262 if ((n = dn_comp((u_char *)dname, cp, buflen,
263 dnptrs, lastdnptr)) < 0)
264 return (-1);
265 cp += n;
266 putshort(type, cp);
267 cp += sizeof (u_short);
268 putshort(class, cp);
269 cp += sizeof (u_short);
270 putlong(0, cp);
271 cp += sizeof (u_long);
272 putshort(datalen, cp);
273 cp += sizeof (u_short);
274 if (datalen) {
275 #ifdef SYSV
276 memcpy((void *)cp, (void *)data, datalen);
277 #else
278 bcopy(data, cp, datalen);
279 #endif
280 cp += datalen;
281 }
282 if ((op == UPDATED) || (op == UPDATEDA)) {
283 hp->ancount = htons(0);
284 break;
285 }
286 /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
287
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)
292 return (-1);
293 cp += n;
294 putshort(newrr->r_type, cp);
295 cp += sizeof (u_short);
296 putshort(newrr->r_class, cp);
297 cp += sizeof (u_short);
298 putlong(0, cp);
299 cp += sizeof (u_long);
300 putshort(newrr->r_size, cp);
301 cp += sizeof (u_short);
302 if (newrr->r_size) {
303 #ifdef SYSV
304 memcpy((void *)cp, newrr->r_data, newrr->r_size);
305 #else
306 bcopy(newrr->r_data, cp, newrr->r_size);
307 #endif
308 cp += newrr->r_size;
309 }
310 hp->ancount = htons(0);
311 break;
312
313 #endif /* ALLOW_UPDATES */
314 }
315 return ((char *)cp - buf);
316 }
|