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