2 * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2003 Internet Software Consortium.
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.
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.
18 /* $Id: getrrset.c,v 1.18 2007/06/19 23:47:22 tbox Exp $ */
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
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.
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().
49 * The following structures are used:
53 * unsigned int rdi_length; // length of data
54 * unsigned char *rdi_data; // record data
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
70 * \section getrrset_return Return Values
72 * lwres_getrrsetbyname() returns zero on success, and one of the
73 * following error codes if an error occurred:
75 * \li #ERRSET_NONAME: the name does not exist
78 * the name exists, but does not have data of the desired type
80 * \li #ERRSET_NOMEMORY:
81 * memory could not be allocated
84 * a parameter is invalid
96 #include <lwres/lwres.h>
97 #include <lwres/net.h>
98 #include <lwres/netdb.h> /* XXX #include <netdb.h> */
100 #include "assert_p.h"
103 * Structure to map results
106 lwresult_to_result(lwres_result_t 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
);
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.
124 sane_malloc(size_t size
) {
127 return (malloc(size
));
131 sane_calloc(size_t number
, size_t size
) {
132 size_t len
= number
* size
;
133 void *mem
= sane_malloc(len
);
140 /*% Returns a set of resource records associated with a hostname, class, and type. hostname is a pointer a to null-terminated string. */
142 lwres_getrrsetbyname(const char *hostname
, unsigned int rdclass
,
143 unsigned int rdtype
, unsigned int flags
,
144 struct rrsetinfo
**res
)
146 lwres_context_t
*lwrctx
= NULL
;
147 lwres_result_t lwresult
;
148 lwres_grbnresponse_t
*response
= NULL
;
149 struct rrsetinfo
*rrset
= NULL
;
151 unsigned int lwflags
;
154 if (rdclass
> 0xffff || rdtype
> 0xffff) {
155 result
= ERRSET_INVAL
;
160 * Don't allow queries of class or type ANY
162 if (rdclass
== 0xff || rdtype
== 0xff) {
163 result
= ERRSET_INVAL
;
167 lwresult
= lwres_context_create(&lwrctx
, NULL
, NULL
, NULL
, 0);
168 if (lwresult
!= LWRES_R_SUCCESS
) {
169 result
= lwresult_to_result(lwresult
);
172 (void) lwres_conf_parse(lwrctx
, lwres_resolv_conf
);
175 * If any input flags were defined, lwflags would be set here
181 lwresult
= lwres_getrdatabyname(lwrctx
, hostname
,
182 (lwres_uint16_t
)rdclass
,
183 (lwres_uint16_t
)rdtype
,
185 if (lwresult
!= LWRES_R_SUCCESS
) {
186 result
= lwresult_to_result(lwresult
);
190 rrset
= sane_malloc(sizeof(struct rrsetinfo
));
192 result
= ERRSET_NOMEMORY
;
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
;
205 rrset
->rri_name
= sane_malloc(response
->realnamelen
+ 1);
206 if (rrset
->rri_name
== NULL
) {
207 result
= ERRSET_NOMEMORY
;
210 strncpy(rrset
->rri_name
, response
->realname
, response
->realnamelen
);
211 rrset
->rri_name
[response
->realnamelen
] = 0;
213 if ((response
->flags
& LWRDATA_VALIDATED
) != 0)
214 rrset
->rri_flags
|= RRSET_VALIDATED
;
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
;
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
;
231 memcpy(rrset
->rri_rdatas
[i
].rdi_data
, response
->rdatas
[i
],
232 rrset
->rri_rdatas
[i
].rdi_length
);
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
;
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
;
249 memcpy(rrset
->rri_sigs
[i
].rdi_data
, response
->sigs
[i
],
250 rrset
->rri_sigs
[i
].rdi_length
);
253 lwres_grbnresponse_free(lwrctx
, &response
);
254 lwres_conf_clear(lwrctx
);
255 lwres_context_destroy(&lwrctx
);
257 return (ERRSET_SUCCESS
);
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
);
270 /*% Releases memory allocated for the dynamically allocated structures created by a successful call to lwres_getrrsetbyname(). */
272 lwres_freerrset(struct rrsetinfo
*rrset
) {
274 for (i
= 0; i
< rrset
->rri_nrdatas
; i
++) {
275 if (rrset
->rri_rdatas
[i
].rdi_data
== NULL
)
277 free(rrset
->rri_rdatas
[i
].rdi_data
);
279 free(rrset
->rri_rdatas
);
280 for (i
= 0; i
< rrset
->rri_nsigs
; i
++) {
281 if (rrset
->rri_sigs
[i
].rdi_data
== NULL
)
283 free(rrset
->rri_sigs
[i
].rdi_data
);
285 free(rrset
->rri_sigs
);
286 free(rrset
->rri_name
);