]>
Commit | Line | Data |
---|---|---|
a2e1b046 | 1 | /* |
b43b13ac | 2 | * Copyright (c) 1995-1999 by Internet Software Consortium. |
df21c858 | 3 | * |
a2e1b046 RM |
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 | |
b43b13ac | 6 | * copyright notice and this permission notice appear in all copies. |
df21c858 | 7 | * |
b43b13ac UD |
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 | |
a2e1b046 RM |
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. | |
a2e1b046 RM |
16 | */ |
17 | ||
18 | #if defined(LIBC_SCCS) && !defined(lint) | |
b43b13ac | 19 | static const char rcsid[] = "$Id$"; |
a2e1b046 RM |
20 | #endif /* LIBC_SCCS and not lint */ |
21 | ||
df21c858 | 22 | #include <sys/types.h> |
a2e1b046 RM |
23 | #include <sys/param.h> |
24 | #include <sys/socket.h> | |
25 | #include <sys/time.h> | |
b43b13ac | 26 | |
a2e1b046 RM |
27 | #include <netinet/in.h> |
28 | #include <arpa/inet.h> | |
29 | #include <arpa/nameser.h> | |
30 | ||
a2e1b046 | 31 | #include <ctype.h> |
b43b13ac | 32 | #include <netdb.h> |
a2e1b046 | 33 | #include <resolv.h> |
b43b13ac UD |
34 | #include <stdio.h> |
35 | #include <stdlib.h> | |
36 | #include <string.h> | |
37 | #include <unistd.h> | |
38 | ||
39 | #undef _res | |
a2e1b046 RM |
40 | |
41 | const char *_res_opcodes[] = { | |
42 | "QUERY", | |
43 | "IQUERY", | |
44 | "CQUERYM", | |
45 | "CQUERYU", /* experimental */ | |
46 | "NOTIFY", /* experimental */ | |
b43b13ac | 47 | "UPDATE", |
a2e1b046 RM |
48 | "6", |
49 | "7", | |
50 | "8", | |
51 | "9", | |
52 | "10", | |
53 | "11", | |
54 | "12", | |
55 | "13", | |
b43b13ac UD |
56 | "ZONEINIT", |
57 | "ZONEREF", | |
58 | }; | |
59 | ||
60 | #ifdef BIND_UPDATE | |
61 | const char *_res_sectioncodes[] = { | |
62 | "ZONE", | |
63 | "PREREQUISITES", | |
64 | "UPDATE", | |
65 | "ADDITIONAL", | |
a2e1b046 | 66 | }; |
b43b13ac UD |
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 |