1 /* $NetBSD: getrrset.c,v 1.6 2014/12/10 04:38:02 christos Exp $ */
4 * Copyright (C) 2004, 2005, 2007, 2012, 2014 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: getrrset.c,v 1.18 2007/06/19 23:47:22 tbox Exp */
27 * lwres_getrrsetbyname() gets a set of resource records associated with
28 * a hostname, class, and type. hostname is a pointer a to
29 * null-terminated string. The flags field is currently unused and must
32 * After a successful call to lwres_getrrsetbyname(), *res is a pointer
33 * to an #rrsetinfo structure, containing a list of one or more #rdatainfo
34 * structures containing resource records and potentially another list of
35 * rdatainfo structures containing SIG resource records associated with
36 * those records. The members #rri_rdclass and #rri_rdtype are copied from
37 * the parameters. #rri_ttl and #rri_name are properties of the obtained
38 * rrset. The resource records contained in #rri_rdatas and #rri_sigs are
39 * in uncompressed DNS wire format. Properties of the rdataset are
40 * represented in the #rri_flags bitfield. If the #RRSET_VALIDATED bit is
41 * set, the data has been DNSSEC validated and the signatures verified.
43 * All of the information returned by lwres_getrrsetbyname() is
44 * dynamically allocated: the rrsetinfo and rdatainfo structures, and the
45 * canonical host name strings pointed to by the rrsetinfostructure.
46 * Memory allocated for the dynamically allocated structures created by a
47 * successful call to lwres_getrrsetbyname() is released by
48 * lwres_freerrset(). rrset is a pointer to a struct rrset created by a
49 * call to lwres_getrrsetbyname().
51 * The following structures are used:
55 * unsigned int rdi_length; // length of data
56 * unsigned char *rdi_data; // record data
60 * unsigned int rri_flags; // RRSET_VALIDATED...
61 * unsigned int rri_rdclass; // class number
62 * unsigned int rri_rdtype; // RR type number
63 * unsigned int rri_ttl; // time to live
64 * unsigned int rri_nrdatas; // size of rdatas array
65 * unsigned int rri_nsigs; // size of sigs array
66 * char *rri_name; // canonical name
67 * struct rdatainfo *rri_rdatas; // individual records
68 * struct rdatainfo *rri_sigs; // individual signatures
72 * \section getrrset_return Return Values
74 * lwres_getrrsetbyname() returns zero on success, and one of the
75 * following error codes if an error occurred:
77 * \li #ERRSET_NONAME: the name does not exist
80 * the name exists, but does not have data of the desired type
82 * \li #ERRSET_NOMEMORY:
83 * memory could not be allocated
86 * a parameter is invalid
98 #include <lwres/lwres.h>
99 #include <lwres/net.h>
100 #include <lwres/netdb.h> /* XXX #include <netdb.h> */
102 #include "assert_p.h"
105 * Structure to map results
108 lwresult_to_result(lwres_result_t lwresult
) {
110 case LWRES_R_SUCCESS
: return (ERRSET_SUCCESS
);
111 case LWRES_R_NOMEMORY
: return (ERRSET_NOMEMORY
);
112 case LWRES_R_NOTFOUND
: return (ERRSET_NONAME
);
113 case LWRES_R_TYPENOTFOUND
: return (ERRSET_NODATA
);
114 default: return (ERRSET_FAIL
);
120 * malloc / calloc functions that guarantee to only
121 * return NULL if there is an error, like they used
122 * to before the ANSI C committee broke them.
126 sane_malloc(size_t size
) {
129 return (malloc(size
));
133 sane_calloc(size_t number
, size_t size
) {
134 size_t len
= number
* size
;
135 void *mem
= sane_malloc(len
);
142 /*% Returns a set of resource records associated with a hostname, class, and type. hostname is a pointer a to null-terminated string. */
144 lwres_getrrsetbyname(const char *hostname
, unsigned int rdclass
,
145 unsigned int rdtype
, unsigned int flags
,
146 struct rrsetinfo
**res
)
148 lwres_context_t
*lwrctx
= NULL
;
149 lwres_result_t lwresult
;
150 lwres_grbnresponse_t
*response
= NULL
;
151 struct rrsetinfo
*rrset
= NULL
;
153 unsigned int lwflags
;
156 if (rdclass
> 0xffff || rdtype
> 0xffff) {
157 result
= ERRSET_INVAL
;
162 * Don't allow queries of class or type ANY
164 if (rdclass
== 0xff || rdtype
== 0xff) {
165 result
= ERRSET_INVAL
;
169 lwresult
= lwres_context_create(&lwrctx
, NULL
, NULL
, NULL
, 0);
170 if (lwresult
!= LWRES_R_SUCCESS
) {
171 result
= lwresult_to_result(lwresult
);
174 (void) lwres_conf_parse(lwrctx
, lwres_resolv_conf
);
177 * If any input flags were defined, lwflags would be set here
183 lwresult
= lwres_getrdatabyname(lwrctx
, hostname
,
184 (lwres_uint16_t
)rdclass
,
185 (lwres_uint16_t
)rdtype
,
187 if (lwresult
!= LWRES_R_SUCCESS
) {
188 result
= lwresult_to_result(lwresult
);
192 rrset
= sane_malloc(sizeof(struct rrsetinfo
));
194 result
= ERRSET_NOMEMORY
;
197 rrset
->rri_name
= NULL
;
198 rrset
->rri_rdclass
= response
->rdclass
;
199 rrset
->rri_rdtype
= response
->rdtype
;
200 rrset
->rri_ttl
= response
->ttl
;
201 rrset
->rri_flags
= 0;
202 rrset
->rri_nrdatas
= 0;
203 rrset
->rri_rdatas
= NULL
;
204 rrset
->rri_nsigs
= 0;
205 rrset
->rri_sigs
= NULL
;
207 rrset
->rri_name
= sane_malloc(response
->realnamelen
+ 1);
208 if (rrset
->rri_name
== NULL
) {
209 result
= ERRSET_NOMEMORY
;
212 strncpy(rrset
->rri_name
, response
->realname
, response
->realnamelen
);
213 rrset
->rri_name
[response
->realnamelen
] = 0;
215 if ((response
->flags
& LWRDATA_VALIDATED
) != 0)
216 rrset
->rri_flags
|= RRSET_VALIDATED
;
218 rrset
->rri_nrdatas
= response
->nrdatas
;
219 rrset
->rri_rdatas
= sane_calloc(rrset
->rri_nrdatas
,
220 sizeof(struct rdatainfo
));
221 if (rrset
->rri_rdatas
== NULL
) {
222 result
= ERRSET_NOMEMORY
;
225 for (i
= 0; i
< rrset
->rri_nrdatas
; i
++) {
226 rrset
->rri_rdatas
[i
].rdi_length
= response
->rdatalen
[i
];
227 rrset
->rri_rdatas
[i
].rdi_data
=
228 sane_malloc(rrset
->rri_rdatas
[i
].rdi_length
);
229 if (rrset
->rri_rdatas
[i
].rdi_data
== NULL
) {
230 result
= ERRSET_NOMEMORY
;
233 memmove(rrset
->rri_rdatas
[i
].rdi_data
, response
->rdatas
[i
],
234 rrset
->rri_rdatas
[i
].rdi_length
);
236 rrset
->rri_nsigs
= response
->nsigs
;
237 rrset
->rri_sigs
= sane_calloc(rrset
->rri_nsigs
,
238 sizeof(struct rdatainfo
));
239 if (rrset
->rri_sigs
== NULL
) {
240 result
= ERRSET_NOMEMORY
;
243 for (i
= 0; i
< rrset
->rri_nsigs
; i
++) {
244 rrset
->rri_sigs
[i
].rdi_length
= response
->siglen
[i
];
245 rrset
->rri_sigs
[i
].rdi_data
=
246 sane_malloc(rrset
->rri_sigs
[i
].rdi_length
);
247 if (rrset
->rri_sigs
[i
].rdi_data
== NULL
) {
248 result
= ERRSET_NOMEMORY
;
251 memmove(rrset
->rri_sigs
[i
].rdi_data
, response
->sigs
[i
],
252 rrset
->rri_sigs
[i
].rdi_length
);
255 lwres_grbnresponse_free(lwrctx
, &response
);
256 lwres_conf_clear(lwrctx
);
257 lwres_context_destroy(&lwrctx
);
259 return (ERRSET_SUCCESS
);
262 lwres_freerrset(rrset
);
263 if (response
!= NULL
)
264 lwres_grbnresponse_free(lwrctx
, &response
);
265 if (lwrctx
!= NULL
) {
266 lwres_conf_clear(lwrctx
);
267 lwres_context_destroy(&lwrctx
);
272 /*% Releases memory allocated for the dynamically allocated structures created by a successful call to lwres_getrrsetbyname(). */
274 lwres_freerrset(struct rrsetinfo
*rrset
) {
276 if (rrset
->rri_rdatas
!= NULL
) {
277 for (i
= 0; i
< rrset
->rri_nrdatas
; i
++) {
278 if (rrset
->rri_rdatas
[i
].rdi_data
== NULL
)
280 free(rrset
->rri_rdatas
[i
].rdi_data
);
282 free(rrset
->rri_rdatas
);
284 if (rrset
->rri_sigs
!= NULL
) {
285 for (i
= 0; i
< rrset
->rri_nsigs
; i
++) {
286 if (rrset
->rri_sigs
[i
].rdi_data
== NULL
)
288 free(rrset
->rri_sigs
[i
].rdi_data
);
290 free(rrset
->rri_sigs
);
292 free(rrset
->rri_name
);