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