res_data.c revision 1.1.1.4 1 1.1.1.4 christos /* $NetBSD: res_data.c,v 1.1.1.4 2009/04/12 16:35:47 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.1 christos #if defined(LIBC_SCCS) && !defined(lint)
21 1.1.1.4 christos static const char rcsid[] = "Id: res_data.c,v 1.7 2008/12/11 09:59:00 marka Exp";
22 1.1 christos #endif /* LIBC_SCCS and not lint */
23 1.1 christos
24 1.1 christos #include "port_before.h"
25 1.1 christos
26 1.1 christos #include <sys/types.h>
27 1.1 christos #include <sys/param.h>
28 1.1 christos #include <sys/socket.h>
29 1.1 christos #include <sys/time.h>
30 1.1 christos
31 1.1 christos #include <netinet/in.h>
32 1.1 christos #include <arpa/inet.h>
33 1.1 christos #include <arpa/nameser.h>
34 1.1 christos
35 1.1 christos #include <ctype.h>
36 1.1 christos #include <netdb.h>
37 1.1 christos #include <resolv.h>
38 1.1 christos #include <res_update.h>
39 1.1 christos #include <stdio.h>
40 1.1 christos #include <stdlib.h>
41 1.1 christos #include <string.h>
42 1.1 christos #include <unistd.h>
43 1.1 christos
44 1.1 christos #include "port_after.h"
45 1.1 christos
46 1.1 christos const char *_res_opcodes[] = {
47 1.1 christos "QUERY",
48 1.1 christos "IQUERY",
49 1.1 christos "CQUERYM",
50 1.1.1.2 christos "CQUERYU", /*%< experimental */
51 1.1.1.2 christos "NOTIFY", /*%< experimental */
52 1.1 christos "UPDATE",
53 1.1 christos "6",
54 1.1 christos "7",
55 1.1 christos "8",
56 1.1 christos "9",
57 1.1 christos "10",
58 1.1 christos "11",
59 1.1 christos "12",
60 1.1 christos "13",
61 1.1 christos "ZONEINIT",
62 1.1 christos "ZONEREF",
63 1.1 christos };
64 1.1 christos
65 1.1 christos #ifdef BIND_UPDATE
66 1.1 christos const char *_res_sectioncodes[] = {
67 1.1 christos "ZONE",
68 1.1 christos "PREREQUISITES",
69 1.1 christos "UPDATE",
70 1.1 christos "ADDITIONAL",
71 1.1 christos };
72 1.1 christos #endif
73 1.1 christos
74 1.1.1.4 christos #undef _res
75 1.1 christos #ifndef __BIND_NOSTATIC
76 1.1 christos struct __res_state _res
77 1.1 christos # if defined(__BIND_RES_TEXT)
78 1.1.1.2 christos = { RES_TIMEOUT, } /*%< Motorola, et al. */
79 1.1 christos # endif
80 1.1 christos ;
81 1.1 christos
82 1.1.1.4 christos #if defined(DO_PTHREADS) || defined(__linux)
83 1.1.1.4 christos #define _res (*__res_state())
84 1.1.1.4 christos #endif
85 1.1.1.4 christos
86 1.1 christos /* Proto. */
87 1.1 christos
88 1.1 christos int res_ourserver_p(const res_state, const struct sockaddr_in *);
89 1.1 christos
90 1.1 christos int
91 1.1 christos res_init(void) {
92 1.1 christos extern int __res_vinit(res_state, int);
93 1.1 christos
94 1.1 christos /*
95 1.1 christos * These three fields used to be statically initialized. This made
96 1.1 christos * it hard to use this code in a shared library. It is necessary,
97 1.1 christos * now that we're doing dynamic initialization here, that we preserve
98 1.1 christos * the old semantics: if an application modifies one of these three
99 1.1 christos * fields of _res before res_init() is called, res_init() will not
100 1.1 christos * alter them. Of course, if an application is setting them to
101 1.1 christos * _zero_ before calling res_init(), hoping to override what used
102 1.1 christos * to be the static default, we can't detect it and unexpected results
103 1.1 christos * will follow. Zero for any of these fields would make no sense,
104 1.1 christos * so one can safely assume that the applications were already getting
105 1.1 christos * unexpected results.
106 1.1 christos *
107 1.1 christos * _res.options is tricky since some apps were known to diddle the bits
108 1.1 christos * before res_init() was first called. We can't replicate that semantic
109 1.1 christos * with dynamic initialization (they may have turned bits off that are
110 1.1 christos * set in RES_DEFAULT). Our solution is to declare such applications
111 1.1 christos * "broken". They could fool us by setting RES_INIT but none do (yet).
112 1.1 christos */
113 1.1 christos if (!_res.retrans)
114 1.1 christos _res.retrans = RES_TIMEOUT;
115 1.1 christos if (!_res.retry)
116 1.1 christos _res.retry = 4;
117 1.1 christos if (!(_res.options & RES_INIT))
118 1.1 christos _res.options = RES_DEFAULT;
119 1.1 christos
120 1.1 christos /*
121 1.1 christos * This one used to initialize implicitly to zero, so unless the app
122 1.1 christos * has set it to something in particular, we can randomize it now.
123 1.1 christos */
124 1.1 christos if (!_res.id)
125 1.1.1.4 christos _res.id = res_nrandomid(&_res);
126 1.1 christos
127 1.1 christos return (__res_vinit(&_res, 1));
128 1.1 christos }
129 1.1 christos
130 1.1 christos void
131 1.1 christos p_query(const u_char *msg) {
132 1.1 christos fp_query(msg, stdout);
133 1.1 christos }
134 1.1 christos
135 1.1 christos void
136 1.1 christos fp_query(const u_char *msg, FILE *file) {
137 1.1 christos fp_nquery(msg, PACKETSZ, file);
138 1.1 christos }
139 1.1 christos
140 1.1 christos void
141 1.1 christos fp_nquery(const u_char *msg, int len, FILE *file) {
142 1.1 christos if ((_res.options & RES_INIT) == 0U && res_init() == -1)
143 1.1 christos return;
144 1.1 christos
145 1.1 christos res_pquery(&_res, msg, len, file);
146 1.1 christos }
147 1.1 christos
148 1.1 christos int
149 1.1.1.2 christos res_mkquery(int op, /*!< opcode of query */
150 1.1.1.2 christos const char *dname, /*!< domain name */
151 1.1.1.2 christos int class, int type, /*!< class and type of query */
152 1.1.1.2 christos const u_char *data, /*!< resource record data */
153 1.1.1.2 christos int datalen, /*!< length of data */
154 1.1.1.2 christos const u_char *newrr_in, /*!< new rr for modify or append */
155 1.1.1.2 christos u_char *buf, /*!< buffer to put query */
156 1.1.1.2 christos int buflen) /*!< size of buffer */
157 1.1 christos {
158 1.1 christos if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
159 1.1 christos RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
160 1.1 christos return (-1);
161 1.1 christos }
162 1.1 christos return (res_nmkquery(&_res, op, dname, class, type,
163 1.1 christos data, datalen,
164 1.1 christos newrr_in, buf, buflen));
165 1.1 christos }
166 1.1 christos
167 1.1 christos int
168 1.1 christos res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
169 1.1 christos if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
170 1.1 christos RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
171 1.1 christos return (-1);
172 1.1 christos }
173 1.1 christos
174 1.1 christos return (res_nmkupdate(&_res, rrecp_in, buf, buflen));
175 1.1 christos }
176 1.1 christos
177 1.1 christos int
178 1.1.1.2 christos res_query(const char *name, /*!< domain name */
179 1.1.1.2 christos int class, int type, /*!< class and type of query */
180 1.1.1.2 christos u_char *answer, /*!< buffer to put answer */
181 1.1.1.2 christos int anslen) /*!< size of answer buffer */
182 1.1 christos {
183 1.1 christos if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
184 1.1 christos RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
185 1.1 christos return (-1);
186 1.1 christos }
187 1.1 christos return (res_nquery(&_res, name, class, type, answer, anslen));
188 1.1 christos }
189 1.1 christos
190 1.1 christos void
191 1.1 christos res_send_setqhook(res_send_qhook hook) {
192 1.1 christos _res.qhook = hook;
193 1.1 christos }
194 1.1 christos
195 1.1 christos void
196 1.1 christos res_send_setrhook(res_send_rhook hook) {
197 1.1 christos _res.rhook = hook;
198 1.1 christos }
199 1.1 christos
200 1.1 christos int
201 1.1 christos res_isourserver(const struct sockaddr_in *inp) {
202 1.1 christos return (res_ourserver_p(&_res, inp));
203 1.1 christos }
204 1.1 christos
205 1.1 christos int
206 1.1 christos res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
207 1.1 christos if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
208 1.1 christos /* errno should have been set by res_init() in this case. */
209 1.1 christos return (-1);
210 1.1 christos }
211 1.1 christos
212 1.1 christos return (res_nsend(&_res, buf, buflen, ans, anssiz));
213 1.1 christos }
214 1.1 christos
215 1.1 christos int
216 1.1 christos res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key,
217 1.1 christos u_char *ans, int anssiz)
218 1.1 christos {
219 1.1 christos if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
220 1.1 christos /* errno should have been set by res_init() in this case. */
221 1.1 christos return (-1);
222 1.1 christos }
223 1.1 christos
224 1.1 christos return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz));
225 1.1 christos }
226 1.1 christos
227 1.1 christos void
228 1.1 christos res_close(void) {
229 1.1 christos res_nclose(&_res);
230 1.1 christos }
231 1.1 christos
232 1.1 christos int
233 1.1 christos res_update(ns_updrec *rrecp_in) {
234 1.1 christos if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
235 1.1 christos RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
236 1.1 christos return (-1);
237 1.1 christos }
238 1.1 christos
239 1.1 christos return (res_nupdate(&_res, rrecp_in, NULL));
240 1.1 christos }
241 1.1 christos
242 1.1 christos int
243 1.1.1.2 christos res_search(const char *name, /*!< domain name */
244 1.1.1.2 christos int class, int type, /*!< class and type of query */
245 1.1.1.2 christos u_char *answer, /*!< buffer to put answer */
246 1.1.1.2 christos int anslen) /*!< size of answer */
247 1.1 christos {
248 1.1 christos if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
249 1.1 christos RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
250 1.1 christos return (-1);
251 1.1 christos }
252 1.1 christos
253 1.1 christos return (res_nsearch(&_res, name, class, type, answer, anslen));
254 1.1 christos }
255 1.1 christos
256 1.1 christos int
257 1.1 christos res_querydomain(const char *name,
258 1.1 christos const char *domain,
259 1.1.1.2 christos int class, int type, /*!< class and type of query */
260 1.1.1.2 christos u_char *answer, /*!< buffer to put answer */
261 1.1.1.2 christos int anslen) /*!< size of answer */
262 1.1 christos {
263 1.1 christos if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
264 1.1 christos RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
265 1.1 christos return (-1);
266 1.1 christos }
267 1.1 christos
268 1.1 christos return (res_nquerydomain(&_res, name, domain,
269 1.1 christos class, type,
270 1.1 christos answer, anslen));
271 1.1 christos }
272 1.1 christos
273 1.1.1.4 christos u_int
274 1.1.1.4 christos res_randomid(void) {
275 1.1.1.4 christos if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
276 1.1.1.4 christos RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
277 1.1.1.4 christos return (-1);
278 1.1.1.4 christos }
279 1.1.1.4 christos
280 1.1.1.4 christos return (res_nrandomid(&_res));
281 1.1.1.4 christos }
282 1.1.1.4 christos
283 1.1 christos const char *
284 1.1 christos hostalias(const char *name) {
285 1.1 christos static char abuf[MAXDNAME];
286 1.1 christos
287 1.1 christos return (res_hostalias(&_res, name, abuf, sizeof abuf));
288 1.1 christos }
289 1.1 christos
290 1.1 christos #ifdef ultrix
291 1.1 christos int
292 1.1 christos local_hostname_length(const char *hostname) {
293 1.1 christos int len_host, len_domain;
294 1.1 christos
295 1.1 christos if (!*_res.defdname)
296 1.1 christos res_init();
297 1.1 christos len_host = strlen(hostname);
298 1.1 christos len_domain = strlen(_res.defdname);
299 1.1 christos if (len_host > len_domain &&
300 1.1 christos !strcasecmp(hostname + len_host - len_domain, _res.defdname) &&
301 1.1 christos hostname[len_host - len_domain - 1] == '.')
302 1.1 christos return (len_host - len_domain - 1);
303 1.1 christos return (0);
304 1.1 christos }
305 1.1 christos #endif /*ultrix*/
306 1.1 christos
307 1.1 christos #endif
308 1.1.1.2 christos
309 1.1.1.2 christos /*! \file */
310