]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - 6/contrib/bind9/lib/lwres/lwres_gnba.c
merge fix for boot-time hang on centos' xen
[FreeBSD/FreeBSD.git] / 6 / contrib / bind9 / lib / lwres / lwres_gnba.c
1 /*
2  * Copyright (C) 2004, 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: lwres_gnba.c,v 1.20.2.2.8.8 2007/09/24 17:26:10 each Exp $ */
19
20 #include <config.h>
21
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <lwres/lwbuffer.h>
27 #include <lwres/lwpacket.h>
28 #include <lwres/lwres.h>
29 #include <lwres/result.h>
30
31 #include "context_p.h"
32 #include "assert_p.h"
33
34 lwres_result_t
35 lwres_gnbarequest_render(lwres_context_t *ctx, lwres_gnbarequest_t *req,
36                          lwres_lwpacket_t *pkt, lwres_buffer_t *b)
37 {
38         unsigned char *buf;
39         size_t buflen;
40         int ret;
41         size_t payload_length;
42
43         REQUIRE(ctx != NULL);
44         REQUIRE(req != NULL);
45         REQUIRE(req->addr.family != 0);
46         REQUIRE(req->addr.length != 0);
47         REQUIRE(pkt != NULL);
48         REQUIRE(b != NULL);
49
50         payload_length = 4 + 4 + 2 + + req->addr.length;
51
52         buflen = LWRES_LWPACKET_LENGTH + payload_length;
53         buf = CTXMALLOC(buflen);
54         if (buf == NULL)
55                 return (LWRES_R_NOMEMORY);
56         lwres_buffer_init(b, buf, buflen);
57
58         pkt->length = buflen;
59         pkt->version = LWRES_LWPACKETVERSION_0;
60         pkt->pktflags &= ~LWRES_LWPACKETFLAG_RESPONSE;
61         pkt->opcode = LWRES_OPCODE_GETNAMEBYADDR;
62         pkt->result = 0;
63         pkt->authtype = 0;
64         pkt->authlength = 0;
65
66         ret = lwres_lwpacket_renderheader(b, pkt);
67         if (ret != LWRES_R_SUCCESS) {
68                 lwres_buffer_invalidate(b);
69                 CTXFREE(buf, buflen);
70                 return (ret);
71         }
72
73         INSIST(SPACE_OK(b, payload_length));
74
75         /*
76          * Put the length and the data.  We know this will fit because we
77          * just checked for it.
78          */
79         lwres_buffer_putuint32(b, req->flags);
80         lwres_buffer_putuint32(b, req->addr.family);
81         lwres_buffer_putuint16(b, req->addr.length);
82         lwres_buffer_putmem(b, (unsigned char *)req->addr.address,
83                             req->addr.length);
84
85         INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
86
87         return (LWRES_R_SUCCESS);
88 }
89
90 lwres_result_t
91 lwres_gnbaresponse_render(lwres_context_t *ctx, lwres_gnbaresponse_t *req,
92                           lwres_lwpacket_t *pkt, lwres_buffer_t *b)
93 {
94         unsigned char *buf;
95         size_t buflen;
96         int ret;
97         size_t payload_length;
98         lwres_uint16_t datalen;
99         int x;
100
101         REQUIRE(ctx != NULL);
102         REQUIRE(req != NULL);
103         REQUIRE(pkt != NULL);
104         REQUIRE(b != NULL);
105
106         /*
107          * Calculate packet size.
108          */
109         payload_length = 4;                            /* flags */
110         payload_length += 2;                           /* naliases */
111         payload_length += 2 + req->realnamelen + 1;    /* real name encoding */
112         for (x = 0; x < req->naliases; x++)            /* each alias */
113                 payload_length += 2 + req->aliaslen[x] + 1;
114
115         buflen = LWRES_LWPACKET_LENGTH + payload_length;
116         buf = CTXMALLOC(buflen);
117         if (buf == NULL)
118                 return (LWRES_R_NOMEMORY);
119         lwres_buffer_init(b, buf, buflen);
120
121         pkt->length = buflen;
122         pkt->version = LWRES_LWPACKETVERSION_0;
123         pkt->pktflags |= LWRES_LWPACKETFLAG_RESPONSE;
124         pkt->opcode = LWRES_OPCODE_GETNAMEBYADDR;
125         pkt->authtype = 0;
126         pkt->authlength = 0;
127
128         ret = lwres_lwpacket_renderheader(b, pkt);
129         if (ret != LWRES_R_SUCCESS) {
130                 lwres_buffer_invalidate(b);
131                 CTXFREE(buf, buflen);
132                 return (ret);
133         }
134
135         INSIST(SPACE_OK(b, payload_length));
136         lwres_buffer_putuint32(b, req->flags);
137
138         /* encode naliases */
139         lwres_buffer_putuint16(b, req->naliases);
140
141         /* encode the real name */
142         datalen = req->realnamelen;
143         lwres_buffer_putuint16(b, datalen);
144         lwres_buffer_putmem(b, (unsigned char *)req->realname, datalen);
145         lwres_buffer_putuint8(b, 0);
146
147         /* encode the aliases */
148         for (x = 0; x < req->naliases; x++) {
149                 datalen = req->aliaslen[x];
150                 lwres_buffer_putuint16(b, datalen);
151                 lwres_buffer_putmem(b, (unsigned char *)req->aliases[x],
152                                     datalen);
153                 lwres_buffer_putuint8(b, 0);
154         }
155
156         INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
157
158         return (LWRES_R_SUCCESS);
159 }
160
161 lwres_result_t
162 lwres_gnbarequest_parse(lwres_context_t *ctx, lwres_buffer_t *b,
163                         lwres_lwpacket_t *pkt, lwres_gnbarequest_t **structp)
164 {
165         int ret;
166         lwres_gnbarequest_t *gnba;
167
168         REQUIRE(ctx != NULL);
169         REQUIRE(pkt != NULL);
170         REQUIRE(b != NULL);
171         REQUIRE(structp != NULL && *structp == NULL);
172
173         if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) != 0)
174                 return (LWRES_R_FAILURE);
175
176         if (!SPACE_REMAINING(b, 4))
177                 return (LWRES_R_UNEXPECTEDEND);
178
179         gnba = CTXMALLOC(sizeof(lwres_gnbarequest_t));
180         if (gnba == NULL)
181                 return (LWRES_R_NOMEMORY);
182
183         gnba->flags = lwres_buffer_getuint32(b);
184
185         ret = lwres_addr_parse(b, &gnba->addr);
186         if (ret != LWRES_R_SUCCESS)
187                 goto out;
188
189         if (LWRES_BUFFER_REMAINING(b) != 0) {
190                 ret = LWRES_R_TRAILINGDATA;
191                 goto out;
192         }
193
194         *structp = gnba;
195         return (LWRES_R_SUCCESS);
196
197  out:
198         if (gnba != NULL)
199                 lwres_gnbarequest_free(ctx, &gnba);
200
201         return (ret);
202 }
203
204 lwres_result_t
205 lwres_gnbaresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b,
206                          lwres_lwpacket_t *pkt, lwres_gnbaresponse_t **structp)
207 {
208         int ret;
209         unsigned int x;
210         lwres_uint32_t flags;
211         lwres_uint16_t naliases;
212         lwres_gnbaresponse_t *gnba;
213
214         REQUIRE(ctx != NULL);
215         REQUIRE(pkt != NULL);
216         REQUIRE(b != NULL);
217         REQUIRE(structp != NULL && *structp == NULL);
218
219         gnba = NULL;
220
221         if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0)
222                 return (LWRES_R_FAILURE);
223
224         /*
225          * Pull off flags & naliases
226          */
227         if (!SPACE_REMAINING(b, 4 + 2))
228                 return (LWRES_R_UNEXPECTEDEND);
229         flags = lwres_buffer_getuint32(b);
230         naliases = lwres_buffer_getuint16(b);
231
232         gnba = CTXMALLOC(sizeof(lwres_gnbaresponse_t));
233         if (gnba == NULL)
234                 return (LWRES_R_NOMEMORY);
235         gnba->base = NULL;
236         gnba->aliases = NULL;
237         gnba->aliaslen = NULL;
238
239         gnba->flags = flags;
240         gnba->naliases = naliases;
241
242         if (naliases > 0) {
243                 gnba->aliases = CTXMALLOC(sizeof(char *) * naliases);
244                 if (gnba->aliases == NULL) {
245                         ret = LWRES_R_NOMEMORY;
246                         goto out;
247                 }
248
249                 gnba->aliaslen = CTXMALLOC(sizeof(lwres_uint16_t) * naliases);
250                 if (gnba->aliaslen == NULL) {
251                         ret = LWRES_R_NOMEMORY;
252                         goto out;
253                 }
254         }
255
256         /*
257          * Now, pull off the real name.
258          */
259         ret = lwres_string_parse(b, &gnba->realname, &gnba->realnamelen);
260         if (ret != LWRES_R_SUCCESS)
261                 goto out;
262
263         /*
264          * Parse off the aliases.
265          */
266         for (x = 0; x < gnba->naliases; x++) {
267                 ret = lwres_string_parse(b, &gnba->aliases[x],
268                                          &gnba->aliaslen[x]);
269                 if (ret != LWRES_R_SUCCESS)
270                         goto out;
271         }
272
273         if (LWRES_BUFFER_REMAINING(b) != 0) {
274                 ret = LWRES_R_TRAILINGDATA;
275                 goto out;
276         }
277
278         *structp = gnba;
279         return (LWRES_R_SUCCESS);
280
281  out:
282         if (gnba != NULL) {
283                 if (gnba->aliases != NULL)
284                         CTXFREE(gnba->aliases, sizeof(char *) * naliases);
285                 if (gnba->aliaslen != NULL)
286                         CTXFREE(gnba->aliaslen,
287                                 sizeof(lwres_uint16_t) * naliases);
288                 CTXFREE(gnba, sizeof(lwres_gnbaresponse_t));
289         }
290
291         return (ret);
292 }
293
294 void
295 lwres_gnbarequest_free(lwres_context_t *ctx, lwres_gnbarequest_t **structp)
296 {
297         lwres_gnbarequest_t *gnba;
298
299         REQUIRE(ctx != NULL);
300         REQUIRE(structp != NULL && *structp != NULL);
301
302         gnba = *structp;
303         *structp = NULL;
304
305         CTXFREE(gnba, sizeof(lwres_gnbarequest_t));
306 }
307
308 void
309 lwres_gnbaresponse_free(lwres_context_t *ctx, lwres_gnbaresponse_t **structp)
310 {
311         lwres_gnbaresponse_t *gnba;
312
313         REQUIRE(ctx != NULL);
314         REQUIRE(structp != NULL && *structp != NULL);
315
316         gnba = *structp;
317         *structp = NULL;
318
319         if (gnba->naliases > 0) {
320                 CTXFREE(gnba->aliases, sizeof(char *) * gnba->naliases);
321                 CTXFREE(gnba->aliaslen,
322                         sizeof(lwres_uint16_t) * gnba->naliases);
323         }
324         if (gnba->base != NULL)
325                 CTXFREE(gnba->base, gnba->baselen);
326         CTXFREE(gnba, sizeof(lwres_gnbaresponse_t));
327 }