res_data.c revision 156952
1156952Sume/*
2156952Sume * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3156952Sume * Copyright (c) 1995-1999 by Internet Software Consortium.
4156952Sume *
5156952Sume * Permission to use, copy, modify, and distribute this software for any
6156952Sume * purpose with or without fee is hereby granted, provided that the above
7156952Sume * copyright notice and this permission notice appear in all copies.
8156952Sume *
9156952Sume * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10156952Sume * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11156952Sume * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
12156952Sume * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13156952Sume * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14156952Sume * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15156952Sume * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16156952Sume */
17156952Sume
18156952Sume#if defined(LIBC_SCCS) && !defined(lint)
19156952Sumestatic const char rcsid[] = "$Id: res_data.c,v 1.1.206.2 2004/03/16 12:34:18 marka Exp $";
20156952Sume#endif /* LIBC_SCCS and not lint */
21156952Sume
22156952Sume#include "port_before.h"
23156952Sume
24156952Sume#include <sys/types.h>
25156952Sume#include <sys/param.h>
26156952Sume#include <sys/socket.h>
27156952Sume#include <sys/time.h>
28156952Sume
29156952Sume#include <netinet/in.h>
30156952Sume#include <arpa/inet.h>
31156952Sume#include <arpa/nameser.h>
32156952Sume
33156952Sume#include <ctype.h>
34156952Sume#include <netdb.h>
35156952Sume#include <resolv.h>
36156952Sume#include <res_update.h>
37156952Sume#include <stdio.h>
38156952Sume#include <stdlib.h>
39156952Sume#include <string.h>
40156952Sume#include <unistd.h>
41156952Sume
42156952Sume#include "port_after.h"
43156952Sume#undef _res
44156952Sume
45156952Sumeconst char *_res_opcodes[] = {
46156952Sume	"QUERY",
47156952Sume	"IQUERY",
48156952Sume	"CQUERYM",
49156952Sume	"CQUERYU",	/* experimental */
50156952Sume	"NOTIFY",	/* experimental */
51156952Sume	"UPDATE",
52156952Sume	"6",
53156952Sume	"7",
54156952Sume	"8",
55156952Sume	"9",
56156952Sume	"10",
57156952Sume	"11",
58156952Sume	"12",
59156952Sume	"13",
60156952Sume	"ZONEINIT",
61156952Sume	"ZONEREF",
62156952Sume};
63156952Sume
64156952Sume#ifdef BIND_UPDATE
65156952Sumeconst char *_res_sectioncodes[] = {
66156952Sume	"ZONE",
67156952Sume	"PREREQUISITES",
68156952Sume	"UPDATE",
69156952Sume	"ADDITIONAL",
70156952Sume};
71156952Sume#endif
72156952Sume
73156952Sume#ifndef __BIND_NOSTATIC
74156952Sumestruct __res_state _res
75156952Sume# if defined(__BIND_RES_TEXT)
76156952Sume	= { RES_TIMEOUT, }	/* Motorola, et al. */
77156952Sume# endif
78156952Sume        ;
79156952Sume
80156952Sume/* Proto. */
81156952Sume
82156952Sumeint  res_ourserver_p(const res_state, const struct sockaddr_in *);
83156952Sume
84156952Sumeint
85156952Sumeres_init(void) {
86156952Sume	extern int __res_vinit(res_state, int);
87156952Sume
88156952Sume	/*
89156952Sume	 * These three fields used to be statically initialized.  This made
90156952Sume	 * it hard to use this code in a shared library.  It is necessary,
91156952Sume	 * now that we're doing dynamic initialization here, that we preserve
92156952Sume	 * the old semantics: if an application modifies one of these three
93156952Sume	 * fields of _res before res_init() is called, res_init() will not
94156952Sume	 * alter them.  Of course, if an application is setting them to
95156952Sume	 * _zero_ before calling res_init(), hoping to override what used
96156952Sume	 * to be the static default, we can't detect it and unexpected results
97156952Sume	 * will follow.  Zero for any of these fields would make no sense,
98156952Sume	 * so one can safely assume that the applications were already getting
99156952Sume	 * unexpected results.
100156952Sume	 *
101156952Sume	 * _res.options is tricky since some apps were known to diddle the bits
102156952Sume	 * before res_init() was first called. We can't replicate that semantic
103156952Sume	 * with dynamic initialization (they may have turned bits off that are
104156952Sume	 * set in RES_DEFAULT).  Our solution is to declare such applications
105156952Sume	 * "broken".  They could fool us by setting RES_INIT but none do (yet).
106156952Sume	 */
107156952Sume	if (!_res.retrans)
108156952Sume		_res.retrans = RES_TIMEOUT;
109156952Sume	if (!_res.retry)
110156952Sume		_res.retry = 4;
111156952Sume	if (!(_res.options & RES_INIT))
112156952Sume		_res.options = RES_DEFAULT;
113156952Sume
114156952Sume	/*
115156952Sume	 * This one used to initialize implicitly to zero, so unless the app
116156952Sume	 * has set it to something in particular, we can randomize it now.
117156952Sume	 */
118156952Sume	if (!_res.id)
119156952Sume		_res.id = res_randomid();
120156952Sume
121156952Sume	return (__res_vinit(&_res, 1));
122156952Sume}
123156952Sume
124156952Sumevoid
125156952Sumep_query(const u_char *msg) {
126156952Sume	fp_query(msg, stdout);
127156952Sume}
128156952Sume
129156952Sumevoid
130156952Sumefp_query(const u_char *msg, FILE *file) {
131156952Sume	fp_nquery(msg, PACKETSZ, file);
132156952Sume}
133156952Sume
134156952Sumevoid
135156952Sumefp_nquery(const u_char *msg, int len, FILE *file) {
136156952Sume	if ((_res.options & RES_INIT) == 0U && res_init() == -1)
137156952Sume		return;
138156952Sume
139156952Sume	res_pquery(&_res, msg, len, file);
140156952Sume}
141156952Sume
142156952Sumeint
143156952Sumeres_mkquery(int op,			/* opcode of query */
144156952Sume	    const char *dname,		/* domain name */
145156952Sume	    int class, int type,	/* class and type of query */
146156952Sume	    const u_char *data,		/* resource record data */
147156952Sume	    int datalen,		/* length of data */
148156952Sume	    const u_char *newrr_in,	/* new rr for modify or append */
149156952Sume	    u_char *buf,		/* buffer to put query */
150156952Sume	    int buflen)			/* size of buffer */
151156952Sume{
152156952Sume	if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
153156952Sume		RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
154156952Sume		return (-1);
155156952Sume	}
156156952Sume	return (res_nmkquery(&_res, op, dname, class, type,
157156952Sume			     data, datalen,
158156952Sume			     newrr_in, buf, buflen));
159156952Sume}
160156952Sume
161156952Sumeint
162156952Sumeres_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
163156952Sume	if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
164156952Sume		RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
165156952Sume		return (-1);
166156952Sume	}
167156952Sume
168156952Sume	return (res_nmkupdate(&_res, rrecp_in, buf, buflen));
169156952Sume}
170156952Sume
171156952Sumeint
172156952Sumeres_query(const char *name,	/* domain name */
173156952Sume	  int class, int type,	/* class and type of query */
174156952Sume	  u_char *answer,	/* buffer to put answer */
175156952Sume	  int anslen)		/* size of answer buffer */
176156952Sume{
177156952Sume	if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
178156952Sume		RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
179156952Sume		return (-1);
180156952Sume	}
181156952Sume	return (res_nquery(&_res, name, class, type, answer, anslen));
182156952Sume}
183156952Sume
184156952Sumevoid
185156952Sumeres_send_setqhook(res_send_qhook hook) {
186156952Sume	_res.qhook = hook;
187156952Sume}
188156952Sume
189156952Sumevoid
190156952Sumeres_send_setrhook(res_send_rhook hook) {
191156952Sume	_res.rhook = hook;
192156952Sume}
193156952Sume
194156952Sumeint
195156952Sumeres_isourserver(const struct sockaddr_in *inp) {
196156952Sume	return (res_ourserver_p(&_res, inp));
197156952Sume}
198156952Sume
199156952Sumeint
200156952Sumeres_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
201156952Sume	if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
202156952Sume		/* errno should have been set by res_init() in this case. */
203156952Sume		return (-1);
204156952Sume	}
205156952Sume
206156952Sume	return (res_nsend(&_res, buf, buflen, ans, anssiz));
207156952Sume}
208156952Sume
209156952Sumeint
210156952Sumeres_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key,
211156952Sume	       u_char *ans, int anssiz)
212156952Sume{
213156952Sume	if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
214156952Sume		/* errno should have been set by res_init() in this case. */
215156952Sume		return (-1);
216156952Sume	}
217156952Sume
218156952Sume	return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz));
219156952Sume}
220156952Sume
221156952Sumevoid
222156952Sumeres_close(void) {
223156952Sume	res_nclose(&_res);
224156952Sume}
225156952Sume
226156952Sumeint
227156952Sumeres_update(ns_updrec *rrecp_in) {
228156952Sume	if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
229156952Sume		RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
230156952Sume		return (-1);
231156952Sume	}
232156952Sume
233156952Sume	return (res_nupdate(&_res, rrecp_in, NULL));
234156952Sume}
235156952Sume
236156952Sumeint
237156952Sumeres_search(const char *name,	/* domain name */
238156952Sume	   int class, int type,	/* class and type of query */
239156952Sume	   u_char *answer,	/* buffer to put answer */
240156952Sume	   int anslen)		/* size of answer */
241156952Sume{
242156952Sume	if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
243156952Sume		RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
244156952Sume		return (-1);
245156952Sume	}
246156952Sume
247156952Sume	return (res_nsearch(&_res, name, class, type, answer, anslen));
248156952Sume}
249156952Sume
250156952Sumeint
251156952Sumeres_querydomain(const char *name,
252156952Sume		const char *domain,
253156952Sume		int class, int type,	/* class and type of query */
254156952Sume		u_char *answer,		/* buffer to put answer */
255156952Sume		int anslen)		/* size of answer */
256156952Sume{
257156952Sume	if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
258156952Sume		RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
259156952Sume		return (-1);
260156952Sume	}
261156952Sume
262156952Sume	return (res_nquerydomain(&_res, name, domain,
263156952Sume				 class, type,
264156952Sume				 answer, anslen));
265156952Sume}
266156952Sume
267156952Sumeconst char *
268156952Sumehostalias(const char *name) {
269156952Sume	static char abuf[MAXDNAME];
270156952Sume
271156952Sume	return (res_hostalias(&_res, name, abuf, sizeof abuf));
272156952Sume}
273156952Sume
274156952Sume#ifdef ultrix
275156952Sumeint
276156952Sumelocal_hostname_length(const char *hostname) {
277156952Sume	int len_host, len_domain;
278156952Sume
279156952Sume	if (!*_res.defdname)
280156952Sume		res_init();
281156952Sume	len_host = strlen(hostname);
282156952Sume	len_domain = strlen(_res.defdname);
283156952Sume	if (len_host > len_domain &&
284156952Sume	    !strcasecmp(hostname + len_host - len_domain, _res.defdname) &&
285156952Sume	    hostname[len_host - len_domain - 1] == '.')
286156952Sume		return (len_host - len_domain - 1);
287156952Sume	return (0);
288156952Sume}
289156952Sume#endif /*ultrix*/
290156952Sume
291156952Sume#endif
292