res_data.c revision 1.14 1 1.14 christos /* $NetBSD: res_data.c,v 1.14 2009/10/24 05:35:37 christos Exp $ */
2 1.1 christos
3 1.1 christos /*
4 1.1 christos * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5 1.1 christos * Copyright (c) 1995-1999 by Internet Software Consortium.
6 1.1 christos *
7 1.1 christos * Permission to use, copy, modify, and distribute this software for any
8 1.1 christos * purpose with or without fee is hereby granted, provided that the above
9 1.1 christos * copyright notice and this permission notice appear in all copies.
10 1.1 christos *
11 1.1 christos * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12 1.1 christos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 1.1 christos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
14 1.1 christos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 1.1 christos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 1.1 christos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 1.1 christos * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 1.1 christos */
19 1.1 christos
20 1.4 christos #include <sys/cdefs.h>
21 1.1 christos #if defined(LIBC_SCCS) && !defined(lint)
22 1.4 christos #ifdef notdef
23 1.12 christos static const char rcsid[] = "Id: res_data.c,v 1.7 2008/12/11 09:59:00 marka Exp";
24 1.4 christos #else
25 1.14 christos __RCSID("$NetBSD: res_data.c,v 1.14 2009/10/24 05:35:37 christos Exp $");
26 1.4 christos #endif
27 1.1 christos #endif /* LIBC_SCCS and not lint */
28 1.1 christos
29 1.1 christos #include "port_before.h"
30 1.1 christos
31 1.5 christos #include "namespace.h"
32 1.1 christos #include <sys/types.h>
33 1.1 christos #include <sys/param.h>
34 1.1 christos #include <sys/socket.h>
35 1.1 christos #include <sys/time.h>
36 1.1 christos
37 1.1 christos #include <netinet/in.h>
38 1.1 christos #include <arpa/inet.h>
39 1.1 christos #include <arpa/nameser.h>
40 1.1 christos
41 1.1 christos #include <ctype.h>
42 1.1 christos #include <netdb.h>
43 1.1 christos #include <resolv.h>
44 1.1 christos #include <res_update.h>
45 1.1 christos #include <stdio.h>
46 1.1 christos #include <stdlib.h>
47 1.1 christos #include <string.h>
48 1.1 christos #include <unistd.h>
49 1.1 christos
50 1.1 christos #include "port_after.h"
51 1.5 christos
52 1.14 christos #include "res_private.h"
53 1.14 christos
54 1.5 christos #ifdef __weak_alias
55 1.5 christos __weak_alias(res_init,_res_init)
56 1.5 christos __weak_alias(res_mkquery,_res_mkquery)
57 1.7 christos __weak_alias(res_query,_res_query)
58 1.7 christos __weak_alias(res_search,_res_search)
59 1.7 christos __weak_alias(res_send,__res_send)
60 1.7 christos __weak_alias(res_close,__res_close)
61 1.7 christos /* XXX: these leaked in the old bind8 libc */
62 1.7 christos __weak_alias(res_querydomain,__res_querydomain)
63 1.5 christos __weak_alias(res_send_setqhook,__res_send_setqhook)
64 1.5 christos __weak_alias(res_send_setrhook,__res_send_setrhook)
65 1.7 christos #if 0
66 1.7 christos __weak_alias(p_query,__p_query)
67 1.7 christos __weak_alias(fp_query,__fp_query)
68 1.7 christos __weak_alias(fp_nquery,__fp_nquery)
69 1.5 christos __weak_alias(res_isourserver,__res_isourserver)
70 1.5 christos __weak_alias(res_opt,_res_opt)
71 1.5 christos __weak_alias(hostalias,__hostalias)
72 1.5 christos #endif
73 1.6 christos #endif
74 1.5 christos
75 1.1 christos const char *_res_opcodes[] = {
76 1.1 christos "QUERY",
77 1.1 christos "IQUERY",
78 1.1 christos "CQUERYM",
79 1.9 christos "CQUERYU", /*%< experimental */
80 1.9 christos "NOTIFY", /*%< experimental */
81 1.1 christos "UPDATE",
82 1.1 christos "6",
83 1.1 christos "7",
84 1.1 christos "8",
85 1.1 christos "9",
86 1.1 christos "10",
87 1.1 christos "11",
88 1.1 christos "12",
89 1.1 christos "13",
90 1.1 christos "ZONEINIT",
91 1.1 christos "ZONEREF",
92 1.1 christos };
93 1.1 christos
94 1.1 christos #ifdef BIND_UPDATE
95 1.1 christos const char *_res_sectioncodes[] = {
96 1.1 christos "ZONE",
97 1.1 christos "PREREQUISITES",
98 1.1 christos "UPDATE",
99 1.1 christos "ADDITIONAL",
100 1.1 christos };
101 1.1 christos #endif
102 1.1 christos
103 1.8 christos #ifndef __BIND_NOSTATIC
104 1.8 christos extern struct __res_state _nres;
105 1.1 christos
106 1.1 christos /* Proto. */
107 1.1 christos
108 1.2 christos int res_ourserver_p(const res_state, const struct sockaddr *);
109 1.1 christos
110 1.1 christos int
111 1.1 christos res_init(void) {
112 1.8 christos int rv;
113 1.8 christos #ifdef COMPAT__RES
114 1.8 christos /*
115 1.8 christos * Compatibility with program that were accessing _res directly
116 1.8 christos * to set options. We keep another struct res that is the same
117 1.8 christos * size as the original res structure, and then copy fields to
118 1.8 christos * it so that we achieve the same initialization
119 1.8 christos */
120 1.8 christos extern void *__res_get_old_state(void);
121 1.8 christos extern void __res_put_old_state(void *);
122 1.8 christos res_state ores = __res_get_old_state();
123 1.8 christos
124 1.8 christos if (ores->options != 0)
125 1.8 christos _nres.options = ores->options;
126 1.8 christos if (ores->retrans != 0)
127 1.8 christos _nres.retrans = ores->retrans;
128 1.8 christos if (ores->retry != 0)
129 1.8 christos _nres.retry = ores->retry;
130 1.8 christos #endif
131 1.1 christos
132 1.1 christos /*
133 1.1 christos * These three fields used to be statically initialized. This made
134 1.1 christos * it hard to use this code in a shared library. It is necessary,
135 1.1 christos * now that we're doing dynamic initialization here, that we preserve
136 1.1 christos * the old semantics: if an application modifies one of these three
137 1.1 christos * fields of _res before res_init() is called, res_init() will not
138 1.1 christos * alter them. Of course, if an application is setting them to
139 1.1 christos * _zero_ before calling res_init(), hoping to override what used
140 1.1 christos * to be the static default, we can't detect it and unexpected results
141 1.1 christos * will follow. Zero for any of these fields would make no sense,
142 1.1 christos * so one can safely assume that the applications were already getting
143 1.1 christos * unexpected results.
144 1.1 christos *
145 1.8 christos * _nres.options is tricky since some apps were known to diddle the bits
146 1.1 christos * before res_init() was first called. We can't replicate that semantic
147 1.1 christos * with dynamic initialization (they may have turned bits off that are
148 1.1 christos * set in RES_DEFAULT). Our solution is to declare such applications
149 1.1 christos * "broken". They could fool us by setting RES_INIT but none do (yet).
150 1.1 christos */
151 1.8 christos if (!_nres.retrans)
152 1.8 christos _nres.retrans = RES_TIMEOUT;
153 1.8 christos if (!_nres.retry)
154 1.8 christos _nres.retry = 4;
155 1.8 christos if (!(_nres.options & RES_INIT))
156 1.8 christos _nres.options = RES_DEFAULT;
157 1.1 christos
158 1.1 christos /*
159 1.1 christos * This one used to initialize implicitly to zero, so unless the app
160 1.1 christos * has set it to something in particular, we can randomize it now.
161 1.1 christos */
162 1.8 christos if (!_nres.id)
163 1.12 christos _nres.id = res_nrandomid(&_nres);
164 1.1 christos
165 1.8 christos rv = __res_vinit(&_nres, 1);
166 1.8 christos #ifdef COMPAT__RES
167 1.8 christos __res_put_old_state(&_nres);
168 1.8 christos #endif
169 1.8 christos return rv;
170 1.1 christos }
171 1.1 christos
172 1.1 christos void
173 1.1 christos p_query(const u_char *msg) {
174 1.1 christos fp_query(msg, stdout);
175 1.1 christos }
176 1.1 christos
177 1.1 christos void
178 1.1 christos fp_query(const u_char *msg, FILE *file) {
179 1.1 christos fp_nquery(msg, PACKETSZ, file);
180 1.1 christos }
181 1.1 christos
182 1.1 christos void
183 1.1 christos fp_nquery(const u_char *msg, int len, FILE *file) {
184 1.8 christos if ((_nres.options & RES_INIT) == 0U && res_init() == -1)
185 1.1 christos return;
186 1.1 christos
187 1.8 christos res_pquery(&_nres, msg, len, file);
188 1.1 christos }
189 1.1 christos
190 1.1 christos int
191 1.9 christos res_mkquery(int op, /*!< opcode of query */
192 1.9 christos const char *dname, /*!< domain name */
193 1.9 christos int class, int type, /*!< class and type of query */
194 1.9 christos const u_char *data, /*!< resource record data */
195 1.9 christos int datalen, /*!< length of data */
196 1.9 christos const u_char *newrr_in, /*!< new rr for modify or append */
197 1.9 christos u_char *buf, /*!< buffer to put query */
198 1.9 christos int buflen) /*!< size of buffer */
199 1.1 christos {
200 1.8 christos if ((_nres.options & RES_INIT) == 0U && res_init() == -1) {
201 1.8 christos RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
202 1.1 christos return (-1);
203 1.1 christos }
204 1.8 christos return (res_nmkquery(&_nres, op, dname, class, type,
205 1.1 christos data, datalen,
206 1.1 christos newrr_in, buf, buflen));
207 1.1 christos }
208 1.1 christos
209 1.2 christos #ifdef _LIBRESOLV
210 1.1 christos int
211 1.1 christos res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
212 1.8 christos if ((_nres.options & RES_INIT) == 0U && res_init() == -1) {
213 1.8 christos RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
214 1.1 christos return (-1);
215 1.1 christos }
216 1.1 christos
217 1.8 christos return (res_nmkupdate(&_nres, rrecp_in, buf, buflen));
218 1.1 christos }
219 1.2 christos #endif
220 1.1 christos
221 1.1 christos int
222 1.9 christos res_query(const char *name, /*!< domain name */
223 1.9 christos int class, int type, /*!< class and type of query */
224 1.9 christos u_char *answer, /*!< buffer to put answer */
225 1.9 christos int anslen) /*!< size of answer buffer */
226 1.1 christos {
227 1.8 christos if ((_nres.options & RES_INIT) == 0U && res_init() == -1) {
228 1.8 christos RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
229 1.1 christos return (-1);
230 1.1 christos }
231 1.8 christos return (res_nquery(&_nres, name, class, type, answer, anslen));
232 1.1 christos }
233 1.1 christos
234 1.1 christos void
235 1.1 christos res_send_setqhook(res_send_qhook hook) {
236 1.8 christos _nres.qhook = hook;
237 1.1 christos }
238 1.1 christos
239 1.1 christos void
240 1.1 christos res_send_setrhook(res_send_rhook hook) {
241 1.8 christos _nres.rhook = hook;
242 1.1 christos }
243 1.1 christos
244 1.1 christos int
245 1.1 christos res_isourserver(const struct sockaddr_in *inp) {
246 1.8 christos return (res_ourserver_p(&_nres, (const struct sockaddr *)(const void *)inp));
247 1.1 christos }
248 1.1 christos
249 1.1 christos int
250 1.1 christos res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
251 1.8 christos if ((_nres.options & RES_INIT) == 0U && res_init() == -1) {
252 1.1 christos /* errno should have been set by res_init() in this case. */
253 1.1 christos return (-1);
254 1.1 christos }
255 1.1 christos
256 1.8 christos return (res_nsend(&_nres, buf, buflen, ans, anssiz));
257 1.1 christos }
258 1.1 christos
259 1.2 christos #ifdef _LIBRESOLV
260 1.1 christos int
261 1.1 christos res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key,
262 1.1 christos u_char *ans, int anssiz)
263 1.1 christos {
264 1.8 christos if ((_nres.options & RES_INIT) == 0U && res_init() == -1) {
265 1.1 christos /* errno should have been set by res_init() in this case. */
266 1.1 christos return (-1);
267 1.1 christos }
268 1.1 christos
269 1.8 christos return (res_nsendsigned(&_nres, buf, buflen, key, ans, anssiz));
270 1.1 christos }
271 1.2 christos #endif
272 1.1 christos
273 1.1 christos void
274 1.1 christos res_close(void) {
275 1.8 christos res_nclose(&_nres);
276 1.1 christos }
277 1.1 christos
278 1.2 christos #ifdef _LIBRESOLV
279 1.1 christos int
280 1.1 christos res_update(ns_updrec *rrecp_in) {
281 1.8 christos if ((_nres.options & RES_INIT) == 0U && res_init() == -1) {
282 1.8 christos RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
283 1.1 christos return (-1);
284 1.1 christos }
285 1.1 christos
286 1.8 christos return (res_nupdate(&_nres, rrecp_in, NULL));
287 1.1 christos }
288 1.2 christos #endif
289 1.1 christos
290 1.1 christos int
291 1.9 christos res_search(const char *name, /*!< domain name */
292 1.9 christos int class, int type, /*!< class and type of query */
293 1.9 christos u_char *answer, /*!< buffer to put answer */
294 1.9 christos int anslen) /*!< size of answer */
295 1.1 christos {
296 1.8 christos if ((_nres.options & RES_INIT) == 0U && res_init() == -1) {
297 1.8 christos RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
298 1.1 christos return (-1);
299 1.1 christos }
300 1.1 christos
301 1.8 christos return (res_nsearch(&_nres, name, class, type, answer, anslen));
302 1.1 christos }
303 1.1 christos
304 1.1 christos int
305 1.1 christos res_querydomain(const char *name,
306 1.1 christos const char *domain,
307 1.9 christos int class, int type, /*!< class and type of query */
308 1.9 christos u_char *answer, /*!< buffer to put answer */
309 1.9 christos int anslen) /*!< size of answer */
310 1.1 christos {
311 1.8 christos if ((_nres.options & RES_INIT) == 0U && res_init() == -1) {
312 1.8 christos RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
313 1.1 christos return (-1);
314 1.1 christos }
315 1.1 christos
316 1.8 christos return (res_nquerydomain(&_nres, name, domain,
317 1.1 christos class, type,
318 1.1 christos answer, anslen));
319 1.1 christos }
320 1.1 christos
321 1.2 christos int
322 1.2 christos res_opt(int a, u_char *b, int c, int d)
323 1.2 christos {
324 1.8 christos return res_nopt(&_nres, a, b, c, d);
325 1.2 christos }
326 1.2 christos
327 1.12 christos u_int
328 1.12 christos res_randomid(void) {
329 1.12 christos if ((_nres.options & RES_INIT) == 0U && res_init() == -1) {
330 1.12 christos RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
331 1.13 christos return (u_int)-1;
332 1.12 christos }
333 1.12 christos
334 1.12 christos return (res_nrandomid(&_nres));
335 1.12 christos }
336 1.12 christos
337 1.1 christos const char *
338 1.1 christos hostalias(const char *name) {
339 1.1 christos static char abuf[MAXDNAME];
340 1.1 christos
341 1.8 christos return (res_hostalias(&_nres, name, abuf, sizeof abuf));
342 1.1 christos }
343 1.1 christos
344 1.1 christos #ifdef ultrix
345 1.1 christos int
346 1.1 christos local_hostname_length(const char *hostname) {
347 1.1 christos int len_host, len_domain;
348 1.1 christos
349 1.8 christos if (!*_nres.defdname)
350 1.1 christos res_init();
351 1.1 christos len_host = strlen(hostname);
352 1.8 christos len_domain = strlen(_nres.defdname);
353 1.1 christos if (len_host > len_domain &&
354 1.8 christos !strcasecmp(hostname + len_host - len_domain, _nres.defdname) &&
355 1.1 christos hostname[len_host - len_domain - 1] == '.')
356 1.1 christos return (len_host - len_domain - 1);
357 1.1 christos return (0);
358 1.1 christos }
359 1.1 christos #endif /*ultrix*/
360 1.1 christos
361 1.1 christos #endif
362 1.9 christos
363 1.9 christos /*! \file */
364