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