BIND: update vendor tree to 9.5.2-P2
[dragonfly.git] / contrib / bind / lib / lwres / getrrset.c
CommitLineData
bbbf71a3
JL
1/*
2 * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2003 Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/* $Id: getrrset.c,v 1.18 2007/06/19 23:47:22 tbox Exp $ */
19
20/*! \file */
21
22/**
23 * DESCRIPTION
24 *
25 * lwres_getrrsetbyname() gets a set of resource records associated with
26 * a hostname, class, and type. hostname is a pointer a to
27 * null-terminated string. The flags field is currently unused and must
28 * be zero.
29 *
30 * After a successful call to lwres_getrrsetbyname(), *res is a pointer
31 * to an #rrsetinfo structure, containing a list of one or more #rdatainfo
32 * structures containing resource records and potentially another list of
33 * rdatainfo structures containing SIG resource records associated with
34 * those records. The members #rri_rdclass and #rri_rdtype are copied from
35 * the parameters. #rri_ttl and #rri_name are properties of the obtained
36 * rrset. The resource records contained in #rri_rdatas and #rri_sigs are
37 * in uncompressed DNS wire format. Properties of the rdataset are
38 * represented in the #rri_flags bitfield. If the #RRSET_VALIDATED bit is
39 * set, the data has been DNSSEC validated and the signatures verified.
40 *
41 * All of the information returned by lwres_getrrsetbyname() is
42 * dynamically allocated: the rrsetinfo and rdatainfo structures, and the
43 * canonical host name strings pointed to by the rrsetinfostructure.
44 * Memory allocated for the dynamically allocated structures created by a
45 * successful call to lwres_getrrsetbyname() is released by
46 * lwres_freerrset(). rrset is a pointer to a struct rrset created by a
47 * call to lwres_getrrsetbyname().
48 *
49 * The following structures are used:
50 *
51 * \code
52 * struct rdatainfo {
53 * unsigned int rdi_length; // length of data
54 * unsigned char *rdi_data; // record data
55 * };
56 *
57 * struct rrsetinfo {
58 * unsigned int rri_flags; // RRSET_VALIDATED...
59 * unsigned int rri_rdclass; // class number
60 * unsigned int rri_rdtype; // RR type number
61 * unsigned int rri_ttl; // time to live
62 * unsigned int rri_nrdatas; // size of rdatas array
63 * unsigned int rri_nsigs; // size of sigs array
64 * char *rri_name; // canonical name
65 * struct rdatainfo *rri_rdatas; // individual records
66 * struct rdatainfo *rri_sigs; // individual signatures
67 * };
68 * \endcode
69 *
70 * \section getrrset_return Return Values
71 *
72 * lwres_getrrsetbyname() returns zero on success, and one of the
73 * following error codes if an error occurred:
74 *
75 * \li #ERRSET_NONAME: the name does not exist
76 *
77 * \li #ERRSET_NODATA:
78 * the name exists, but does not have data of the desired type
79 *
80 * \li #ERRSET_NOMEMORY:
81 * memory could not be allocated
82 *
83 * \li #ERRSET_INVAL:
84 * a parameter is invalid
85 *
86 * \li #ERRSET_FAIL:
87 * other failure
88 */
89
90#include <config.h>
91
92#include <string.h>
93#include <errno.h>
94#include <stdlib.h>
95
96#include <lwres/lwres.h>
97#include <lwres/net.h>
98#include <lwres/netdb.h> /* XXX #include <netdb.h> */
99
100#include "assert_p.h"
101
102/*!
103 * Structure to map results
104 */
105static unsigned int
106lwresult_to_result(lwres_result_t lwresult) {
107 switch (lwresult) {
108 case LWRES_R_SUCCESS: return (ERRSET_SUCCESS);
109 case LWRES_R_NOMEMORY: return (ERRSET_NOMEMORY);
110 case LWRES_R_NOTFOUND: return (ERRSET_NONAME);
111 case LWRES_R_TYPENOTFOUND: return (ERRSET_NODATA);
112 default: return (ERRSET_FAIL);
113 }
114}
115
116/*@{*/
117/*!
118 * malloc / calloc functions that guarantee to only
119 * return NULL if there is an error, like they used
120 * to before the ANSI C committee broke them.
121 */
122
123static void *
124sane_malloc(size_t size) {
125 if (size == 0U)
126 size = 1;
127 return (malloc(size));
128}
129
130static void *
131sane_calloc(size_t number, size_t size) {
132 size_t len = number * size;
133 void *mem = sane_malloc(len);
134 if (mem != NULL)
135 memset(mem, 0, len);
136 return (mem);
137}
138/*@}*/
139
140/*% Returns a set of resource records associated with a hostname, class, and type. hostname is a pointer a to null-terminated string. */
141int
142lwres_getrrsetbyname(const char *hostname, unsigned int rdclass,
143 unsigned int rdtype, unsigned int flags,
144 struct rrsetinfo **res)
145{
146 lwres_context_t *lwrctx = NULL;
147 lwres_result_t lwresult;
148 lwres_grbnresponse_t *response = NULL;
149 struct rrsetinfo *rrset = NULL;
150 unsigned int i;
151 unsigned int lwflags;
152 unsigned int result;
153
154 if (rdclass > 0xffff || rdtype > 0xffff) {
155 result = ERRSET_INVAL;
156 goto fail;
157 }
158
159 /*
160 * Don't allow queries of class or type ANY
161 */
162 if (rdclass == 0xff || rdtype == 0xff) {
163 result = ERRSET_INVAL;
164 goto fail;
165 }
166
167 lwresult = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
168 if (lwresult != LWRES_R_SUCCESS) {
169 result = lwresult_to_result(lwresult);
170 goto fail;
171 }
172 (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
173
174 /*
175 * If any input flags were defined, lwflags would be set here
176 * based on them
177 */
178 UNUSED(flags);
179 lwflags = 0;
180
181 lwresult = lwres_getrdatabyname(lwrctx, hostname,
182 (lwres_uint16_t)rdclass,
183 (lwres_uint16_t)rdtype,
184 lwflags, &response);
185 if (lwresult != LWRES_R_SUCCESS) {
186 result = lwresult_to_result(lwresult);
187 goto fail;
188 }
189
190 rrset = sane_malloc(sizeof(struct rrsetinfo));
191 if (rrset == NULL) {
192 result = ERRSET_NOMEMORY;
193 goto fail;
194 }
195 rrset->rri_name = NULL;
196 rrset->rri_rdclass = response->rdclass;
197 rrset->rri_rdtype = response->rdtype;
198 rrset->rri_ttl = response->ttl;
199 rrset->rri_flags = 0;
200 rrset->rri_nrdatas = 0;
201 rrset->rri_rdatas = NULL;
202 rrset->rri_nsigs = 0;
203 rrset->rri_sigs = NULL;
204
205 rrset->rri_name = sane_malloc(response->realnamelen + 1);
206 if (rrset->rri_name == NULL) {
207 result = ERRSET_NOMEMORY;
208 goto fail;
209 }
210 strncpy(rrset->rri_name, response->realname, response->realnamelen);
211 rrset->rri_name[response->realnamelen] = 0;
212
213 if ((response->flags & LWRDATA_VALIDATED) != 0)
214 rrset->rri_flags |= RRSET_VALIDATED;
215
216 rrset->rri_nrdatas = response->nrdatas;
217 rrset->rri_rdatas = sane_calloc(rrset->rri_nrdatas,
218 sizeof(struct rdatainfo));
219 if (rrset->rri_rdatas == NULL) {
220 result = ERRSET_NOMEMORY;
221 goto fail;
222 }
223 for (i = 0; i < rrset->rri_nrdatas; i++) {
224 rrset->rri_rdatas[i].rdi_length = response->rdatalen[i];
225 rrset->rri_rdatas[i].rdi_data =
226 sane_malloc(rrset->rri_rdatas[i].rdi_length);
227 if (rrset->rri_rdatas[i].rdi_data == NULL) {
228 result = ERRSET_NOMEMORY;
229 goto fail;
230 }
231 memcpy(rrset->rri_rdatas[i].rdi_data, response->rdatas[i],
232 rrset->rri_rdatas[i].rdi_length);
233 }
234 rrset->rri_nsigs = response->nsigs;
235 rrset->rri_sigs = sane_calloc(rrset->rri_nsigs,
236 sizeof(struct rdatainfo));
237 if (rrset->rri_sigs == NULL) {
238 result = ERRSET_NOMEMORY;
239 goto fail;
240 }
241 for (i = 0; i < rrset->rri_nsigs; i++) {
242 rrset->rri_sigs[i].rdi_length = response->siglen[i];
243 rrset->rri_sigs[i].rdi_data =
244 sane_malloc(rrset->rri_sigs[i].rdi_length);
245 if (rrset->rri_sigs[i].rdi_data == NULL) {
246 result = ERRSET_NOMEMORY;
247 goto fail;
248 }
249 memcpy(rrset->rri_sigs[i].rdi_data, response->sigs[i],
250 rrset->rri_sigs[i].rdi_length);
251 }
252
253 lwres_grbnresponse_free(lwrctx, &response);
254 lwres_conf_clear(lwrctx);
255 lwres_context_destroy(&lwrctx);
256 *res = rrset;
257 return (ERRSET_SUCCESS);
258 fail:
259 if (rrset != NULL)
260 lwres_freerrset(rrset);
261 if (response != NULL)
262 lwres_grbnresponse_free(lwrctx, &response);
263 if (lwrctx != NULL) {
264 lwres_conf_clear(lwrctx);
265 lwres_context_destroy(&lwrctx);
266 }
267 return (result);
268}
269
270/*% Releases memory allocated for the dynamically allocated structures created by a successful call to lwres_getrrsetbyname(). */
271void
272lwres_freerrset(struct rrsetinfo *rrset) {
273 unsigned int i;
274 for (i = 0; i < rrset->rri_nrdatas; i++) {
275 if (rrset->rri_rdatas[i].rdi_data == NULL)
276 break;
277 free(rrset->rri_rdatas[i].rdi_data);
278 }
279 free(rrset->rri_rdatas);
280 for (i = 0; i < rrset->rri_nsigs; i++) {
281 if (rrset->rri_sigs[i].rdi_data == NULL)
282 break;
283 free(rrset->rri_sigs[i].rdi_data);
284 }
285 free(rrset->rri_sigs);
286 free(rrset->rri_name);
287 free(rrset);
288}