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