Merge from vendor branch NTPD:
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / lwres / getrrset.c
1 /*
2  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2000-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and 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.11.2.5 2004/03/09 06:12:33 marka Exp $ */
19
20 #include <config.h>
21
22 #include <string.h>
23 #include <errno.h>
24 #include <stdlib.h>
25
26 #include <lwres/lwres.h>
27 #include <lwres/net.h>
28 #include <lwres/netdb.h>        /* XXX #include <netdb.h> */
29
30 #include "assert_p.h"
31
32 static unsigned int
33 lwresult_to_result(lwres_result_t lwresult) {
34         switch (lwresult) {
35         case LWRES_R_SUCCESS:   return (ERRSET_SUCCESS);
36         case LWRES_R_NOMEMORY:  return (ERRSET_NOMEMORY);
37         case LWRES_R_NOTFOUND:  return (ERRSET_NONAME);
38         case LWRES_R_TYPENOTFOUND: return (ERRSET_NODATA);
39         default:                return (ERRSET_FAIL);
40         }
41 }
42
43 /*
44  * malloc / calloc functions that guarantee to only
45  * return NULL if there is an error, like they used
46  * to before the ANSI C committee broke them.
47  */
48
49 static void *
50 sane_malloc(size_t size) {
51         if (size == 0U)
52                 size = 1;
53         return (malloc(size));
54 }
55
56 static void *
57 sane_calloc(size_t number, size_t size) {
58         size_t len = number * size;
59         void *mem  = sane_malloc(len);
60         if (mem != NULL)
61                 memset(mem, 0, len);
62         return (mem);
63 }
64
65 int
66 lwres_getrrsetbyname(const char *hostname, unsigned int rdclass,
67                      unsigned int rdtype, unsigned int flags,
68                      struct rrsetinfo **res)
69 {
70         lwres_context_t *lwrctx = NULL;
71         lwres_result_t lwresult;
72         lwres_grbnresponse_t *response = NULL;
73         struct rrsetinfo *rrset = NULL;
74         unsigned int i;
75         unsigned int lwflags;
76         unsigned int result;
77
78         if (rdclass > 0xffff || rdtype > 0xffff) {
79                 result = ERRSET_INVAL;
80                 goto fail;
81         }
82
83         /*
84          * Don't allow queries of class or type ANY
85          */
86         if (rdclass == 0xff || rdtype == 0xff) {
87                 result = ERRSET_INVAL;
88                 goto fail;
89         }
90
91         lwresult = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
92         if (lwresult != LWRES_R_SUCCESS) {
93                 result = lwresult_to_result(lwresult);
94                 goto fail;
95         }
96         (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
97
98         /*
99          * If any input flags were defined, lwflags would be set here
100          * based on them
101          */
102         UNUSED(flags);
103         lwflags = 0;
104
105         lwresult = lwres_getrdatabyname(lwrctx, hostname,
106                                         (lwres_uint16_t)rdclass, 
107                                         (lwres_uint16_t)rdtype,
108                                         lwflags, &response);
109         if (lwresult != LWRES_R_SUCCESS) {
110                 result = lwresult_to_result(lwresult);
111                 goto fail;
112         }
113
114         rrset = sane_malloc(sizeof(struct rrsetinfo));
115         if (rrset == NULL) {
116                 result = ERRSET_NOMEMORY;
117                 goto fail;
118         }
119         rrset->rri_name = NULL;
120         rrset->rri_rdclass = response->rdclass;
121         rrset->rri_rdtype = response->rdtype;
122         rrset->rri_ttl = response->ttl;
123         rrset->rri_flags = 0;
124         rrset->rri_nrdatas = 0;
125         rrset->rri_rdatas = NULL;
126         rrset->rri_nsigs = 0;
127         rrset->rri_sigs = NULL;
128
129         rrset->rri_name = sane_malloc(response->realnamelen + 1);
130         if (rrset->rri_name == NULL) {
131                 result = ERRSET_NOMEMORY;
132                 goto fail;
133         }
134         strncpy(rrset->rri_name, response->realname, response->realnamelen);
135         rrset->rri_name[response->realnamelen] = 0;
136
137         if ((response->flags & LWRDATA_VALIDATED) != 0)
138                 rrset->rri_flags |= RRSET_VALIDATED;
139
140         rrset->rri_nrdatas = response->nrdatas;
141         rrset->rri_rdatas = sane_calloc(rrset->rri_nrdatas,
142                                    sizeof(struct rdatainfo));
143         if (rrset->rri_rdatas == NULL) {
144                 result = ERRSET_NOMEMORY;
145                 goto fail;
146         }
147         for (i = 0; i < rrset->rri_nrdatas; i++) {
148                 rrset->rri_rdatas[i].rdi_length = response->rdatalen[i];
149                 rrset->rri_rdatas[i].rdi_data =
150                                 sane_malloc(rrset->rri_rdatas[i].rdi_length);
151                 if (rrset->rri_rdatas[i].rdi_data == NULL) {
152                         result = ERRSET_NOMEMORY;
153                         goto fail;
154                 }
155                 memcpy(rrset->rri_rdatas[i].rdi_data, response->rdatas[i],
156                        rrset->rri_rdatas[i].rdi_length);
157         }
158         rrset->rri_nsigs = response->nsigs;
159         rrset->rri_sigs = sane_calloc(rrset->rri_nsigs,
160                                       sizeof(struct rdatainfo));
161         if (rrset->rri_sigs == NULL) {
162                 result = ERRSET_NOMEMORY;
163                 goto fail;
164         }
165         for (i = 0; i < rrset->rri_nsigs; i++) {
166                 rrset->rri_sigs[i].rdi_length = response->siglen[i];
167                 rrset->rri_sigs[i].rdi_data =
168                                 sane_malloc(rrset->rri_sigs[i].rdi_length);
169                 if (rrset->rri_sigs[i].rdi_data == NULL) {
170                         result = ERRSET_NOMEMORY;
171                         goto fail;
172                 }
173                 memcpy(rrset->rri_sigs[i].rdi_data, response->sigs[i],
174                        rrset->rri_sigs[i].rdi_length);
175         }
176
177         lwres_grbnresponse_free(lwrctx, &response);
178         lwres_conf_clear(lwrctx);
179         lwres_context_destroy(&lwrctx);
180         *res = rrset;
181         return (ERRSET_SUCCESS);
182  fail:
183         if (rrset != NULL)
184                 lwres_freerrset(rrset);
185         if (response != NULL)
186                 lwres_grbnresponse_free(lwrctx, &response);
187         if (lwrctx != NULL) {
188                 lwres_conf_clear(lwrctx);
189                 lwres_context_destroy(&lwrctx);
190         }
191         return (result);
192 }
193
194 void
195 lwres_freerrset(struct rrsetinfo *rrset) {
196         unsigned int i;
197         for (i = 0; i < rrset->rri_nrdatas; i++) {
198                 if (rrset->rri_rdatas[i].rdi_data == NULL)
199                         break;
200                 free(rrset->rri_rdatas[i].rdi_data);
201         }
202         free(rrset->rri_rdatas);
203         for (i = 0; i < rrset->rri_nsigs; i++) {
204                 if (rrset->rri_sigs[i].rdi_data == NULL)
205                         break;
206                 free(rrset->rri_sigs[i].rdi_data);
207         }
208         free(rrset->rri_sigs);
209         free(rrset->rri_name);
210         free(rrset);
211 }