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