bind - Upgraded vendor branch to 9.5.2-P1
[dragonfly.git] / contrib / bind-9.5.2 / lib / lwres / lwres_grbn.c
1 /*
2  * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2000, 2001  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_grbn.c,v 1.10 2007/06/19 23:47:22 tbox Exp $ */
19
20 /*! \file lwres_grbn.c
21
22  */
23
24 #include <config.h>
25
26 #include <assert.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <lwres/lwbuffer.h>
31 #include <lwres/lwpacket.h>
32 #include <lwres/lwres.h>
33 #include <lwres/result.h>
34
35 #include "context_p.h"
36 #include "assert_p.h"
37
38 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
39 lwres_result_t
40 lwres_grbnrequest_render(lwres_context_t *ctx, lwres_grbnrequest_t *req,
41                          lwres_lwpacket_t *pkt, lwres_buffer_t *b)
42 {
43         unsigned char *buf;
44         size_t buflen;
45         int ret;
46         size_t payload_length;
47         lwres_uint16_t datalen;
48
49         REQUIRE(ctx != NULL);
50         REQUIRE(req != NULL);
51         REQUIRE(req->name != NULL);
52         REQUIRE(pkt != NULL);
53         REQUIRE(b != NULL);
54
55         datalen = strlen(req->name);
56
57         payload_length = 4 + 2 + 2 + 2 + req->namelen + 1;
58
59         buflen = LWRES_LWPACKET_LENGTH + payload_length;
60         buf = CTXMALLOC(buflen);
61         if (buf == NULL)
62                 return (LWRES_R_NOMEMORY);
63
64         lwres_buffer_init(b, buf, buflen);
65
66         pkt->length = buflen;
67         pkt->version = LWRES_LWPACKETVERSION_0;
68         pkt->pktflags &= ~LWRES_LWPACKETFLAG_RESPONSE;
69         pkt->opcode = LWRES_OPCODE_GETRDATABYNAME;
70         pkt->result = 0;
71         pkt->authtype = 0;
72         pkt->authlength = 0;
73
74         ret = lwres_lwpacket_renderheader(b, pkt);
75         if (ret != LWRES_R_SUCCESS) {
76                 lwres_buffer_invalidate(b);
77                 CTXFREE(buf, buflen);
78                 return (ret);
79         }
80
81         INSIST(SPACE_OK(b, payload_length));
82
83         /*
84          * Flags.
85          */
86         lwres_buffer_putuint32(b, req->flags);
87
88         /*
89          * Class.
90          */
91         lwres_buffer_putuint16(b, req->rdclass);
92
93         /*
94          * Type.
95          */
96         lwres_buffer_putuint16(b, req->rdtype);
97
98         /*
99          * Put the length and the data.  We know this will fit because we
100          * just checked for it.
101          */
102         lwres_buffer_putuint16(b, datalen);
103         lwres_buffer_putmem(b, (unsigned char *)req->name, datalen);
104         lwres_buffer_putuint8(b, 0); /* trailing NUL */
105
106         INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
107
108         return (LWRES_R_SUCCESS);
109 }
110
111 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
112 lwres_result_t
113 lwres_grbnresponse_render(lwres_context_t *ctx, lwres_grbnresponse_t *req,
114                           lwres_lwpacket_t *pkt, lwres_buffer_t *b)
115 {
116         unsigned char *buf;
117         size_t buflen;
118         int ret;
119         size_t payload_length;
120         lwres_uint16_t datalen;
121         int x;
122
123         REQUIRE(ctx != NULL);
124         REQUIRE(req != NULL);
125         REQUIRE(pkt != NULL);
126         REQUIRE(b != NULL);
127
128         /* flags, class, type, ttl, nrdatas, nsigs */
129         payload_length = 4 + 2 + 2 + 4 + 2 + 2;
130         /* real name encoding */
131         payload_length += 2 + req->realnamelen + 1;
132         /* each rr */
133         for (x = 0; x < req->nrdatas; x++)
134                 payload_length += 2 + req->rdatalen[x];
135         for (x = 0; x < req->nsigs; x++)
136                 payload_length += 2 + req->siglen[x];
137
138         buflen = LWRES_LWPACKET_LENGTH + payload_length;
139         buf = CTXMALLOC(buflen);
140         if (buf == NULL)
141                 return (LWRES_R_NOMEMORY);
142         lwres_buffer_init(b, buf, buflen);
143
144         pkt->length = buflen;
145         pkt->version = LWRES_LWPACKETVERSION_0;
146         pkt->pktflags |= LWRES_LWPACKETFLAG_RESPONSE;
147         pkt->opcode = LWRES_OPCODE_GETRDATABYNAME;
148         pkt->authtype = 0;
149         pkt->authlength = 0;
150
151         ret = lwres_lwpacket_renderheader(b, pkt);
152         if (ret != LWRES_R_SUCCESS) {
153                 lwres_buffer_invalidate(b);
154                 CTXFREE(buf, buflen);
155                 return (ret);
156         }
157
158         /*
159          * Check space needed here.
160          */
161         INSIST(SPACE_OK(b, payload_length));
162
163         /* Flags. */
164         lwres_buffer_putuint32(b, req->flags);
165
166         /* encode class, type, ttl, and nrdatas */
167         lwres_buffer_putuint16(b, req->rdclass);
168         lwres_buffer_putuint16(b, req->rdtype);
169         lwres_buffer_putuint32(b, req->ttl);
170         lwres_buffer_putuint16(b, req->nrdatas);
171         lwres_buffer_putuint16(b, req->nsigs);
172
173         /* encode the real name */
174         datalen = req->realnamelen;
175         lwres_buffer_putuint16(b, datalen);
176         lwres_buffer_putmem(b, (unsigned char *)req->realname, datalen);
177         lwres_buffer_putuint8(b, 0);
178
179         /* encode the rdatas */
180         for (x = 0; x < req->nrdatas; x++) {
181                 datalen = req->rdatalen[x];
182                 lwres_buffer_putuint16(b, datalen);
183                 lwres_buffer_putmem(b, req->rdatas[x], datalen);
184         }
185
186         /* encode the signatures */
187         for (x = 0; x < req->nsigs; x++) {
188                 datalen = req->siglen[x];
189                 lwres_buffer_putuint16(b, datalen);
190                 lwres_buffer_putmem(b, req->sigs[x], datalen);
191         }
192
193         INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
194         INSIST(LWRES_BUFFER_USEDCOUNT(b) == pkt->length);
195
196         return (LWRES_R_SUCCESS);
197 }
198
199 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
200 lwres_result_t
201 lwres_grbnrequest_parse(lwres_context_t *ctx, lwres_buffer_t *b,
202                         lwres_lwpacket_t *pkt, lwres_grbnrequest_t **structp)
203 {
204         int ret;
205         char *name;
206         lwres_grbnrequest_t *grbn;
207         lwres_uint32_t flags;
208         lwres_uint16_t rdclass, rdtype;
209         lwres_uint16_t namelen;
210
211         REQUIRE(ctx != NULL);
212         REQUIRE(pkt != NULL);
213         REQUIRE(b != NULL);
214         REQUIRE(structp != NULL && *structp == NULL);
215
216         if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) != 0)
217                 return (LWRES_R_FAILURE);
218
219         if (!SPACE_REMAINING(b, 4 + 2 + 2))
220                 return (LWRES_R_UNEXPECTEDEND);
221
222         /*
223          * Pull off the flags, class, and type.
224          */
225         flags = lwres_buffer_getuint32(b);
226         rdclass = lwres_buffer_getuint16(b);
227         rdtype = lwres_buffer_getuint16(b);
228
229         /*
230          * Pull off the name itself
231          */
232         ret = lwres_string_parse(b, &name, &namelen);
233         if (ret != LWRES_R_SUCCESS)
234                 return (ret);
235
236         if (LWRES_BUFFER_REMAINING(b) != 0)
237                 return (LWRES_R_TRAILINGDATA);
238
239         grbn = CTXMALLOC(sizeof(lwres_grbnrequest_t));
240         if (grbn == NULL)
241                 return (LWRES_R_NOMEMORY);
242
243         grbn->flags = flags;
244         grbn->rdclass = rdclass;
245         grbn->rdtype = rdtype;
246         grbn->name = name;
247         grbn->namelen = namelen;
248
249         *structp = grbn;
250         return (LWRES_R_SUCCESS);
251 }
252
253 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
254 lwres_result_t
255 lwres_grbnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b,
256                         lwres_lwpacket_t *pkt, lwres_grbnresponse_t **structp)
257 {
258         lwres_result_t ret;
259         unsigned int x;
260         lwres_uint32_t flags;
261         lwres_uint16_t rdclass, rdtype;
262         lwres_uint32_t ttl;
263         lwres_uint16_t nrdatas, nsigs;
264         lwres_grbnresponse_t *grbn;
265
266         REQUIRE(ctx != NULL);
267         REQUIRE(pkt != NULL);
268         REQUIRE(b != NULL);
269         REQUIRE(structp != NULL && *structp == NULL);
270
271         grbn = NULL;
272
273         if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0)
274                 return (LWRES_R_FAILURE);
275
276         /*
277          * Pull off the flags, class, type, ttl, nrdatas, and nsigs
278          */
279         if (!SPACE_REMAINING(b, 4 + 2 + 2 + 4 + 2 + 2))
280                 return (LWRES_R_UNEXPECTEDEND);
281         flags = lwres_buffer_getuint32(b);
282         rdclass = lwres_buffer_getuint16(b);
283         rdtype = lwres_buffer_getuint16(b);
284         ttl = lwres_buffer_getuint32(b);
285         nrdatas = lwres_buffer_getuint16(b);
286         nsigs = lwres_buffer_getuint16(b);
287
288         /*
289          * Pull off the name itself
290          */
291
292         grbn = CTXMALLOC(sizeof(lwres_grbnresponse_t));
293         if (grbn == NULL)
294                 return (LWRES_R_NOMEMORY);
295         grbn->rdatas = NULL;
296         grbn->rdatalen = NULL;
297         grbn->sigs = NULL;
298         grbn->siglen = NULL;
299         grbn->base = NULL;
300
301         grbn->flags = flags;
302         grbn->rdclass = rdclass;
303         grbn->rdtype = rdtype;
304         grbn->ttl = ttl;
305         grbn->nrdatas = nrdatas;
306         grbn->nsigs = nsigs;
307
308         if (nrdatas > 0) {
309                 grbn->rdatas = CTXMALLOC(sizeof(char *) * nrdatas);
310                 if (grbn->rdatas == NULL) {
311                         ret = LWRES_R_NOMEMORY;
312                         goto out;
313                 }
314
315                 grbn->rdatalen = CTXMALLOC(sizeof(lwres_uint16_t) * nrdatas);
316                 if (grbn->rdatalen == NULL) {
317                         ret = LWRES_R_NOMEMORY;
318                         goto out;
319                 }
320         }
321
322         if (nsigs > 0) {
323                 grbn->sigs = CTXMALLOC(sizeof(char *) * nsigs);
324                 if (grbn->sigs == NULL) {
325                         ret = LWRES_R_NOMEMORY;
326                         goto out;
327                 }
328
329                 grbn->siglen = CTXMALLOC(sizeof(lwres_uint16_t) * nsigs);
330                 if (grbn->siglen == NULL) {
331                         ret = LWRES_R_NOMEMORY;
332                         goto out;
333                 }
334         }
335
336         /*
337          * Now, pull off the real name.
338          */
339         ret = lwres_string_parse(b, &grbn->realname, &grbn->realnamelen);
340         if (ret != LWRES_R_SUCCESS)
341                 goto out;
342
343         /*
344          * Parse off the rdatas.
345          */
346         for (x = 0; x < grbn->nrdatas; x++) {
347                 ret = lwres_data_parse(b, &grbn->rdatas[x],
348                                          &grbn->rdatalen[x]);
349                 if (ret != LWRES_R_SUCCESS)
350                         goto out;
351         }
352
353         /*
354          * Parse off the signatures.
355          */
356         for (x = 0; x < grbn->nsigs; x++) {
357                 ret = lwres_data_parse(b, &grbn->sigs[x], &grbn->siglen[x]);
358                 if (ret != LWRES_R_SUCCESS)
359                         goto out;
360         }
361
362         if (LWRES_BUFFER_REMAINING(b) != 0) {
363                 ret = LWRES_R_TRAILINGDATA;
364                 goto out;
365         }
366
367         *structp = grbn;
368         return (LWRES_R_SUCCESS);
369
370  out:
371         if (grbn != NULL) {
372                 if (grbn->rdatas != NULL)
373                         CTXFREE(grbn->rdatas, sizeof(char *) * nrdatas);
374                 if (grbn->rdatalen != NULL)
375                         CTXFREE(grbn->rdatalen,
376                                 sizeof(lwres_uint16_t) * nrdatas);
377                 if (grbn->sigs != NULL)
378                         CTXFREE(grbn->sigs, sizeof(char *) * nsigs);
379                 if (grbn->siglen != NULL)
380                         CTXFREE(grbn->siglen, sizeof(lwres_uint16_t) * nsigs);
381                 CTXFREE(grbn, sizeof(lwres_grbnresponse_t));
382         }
383
384         return (ret);
385 }
386
387 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
388 void
389 lwres_grbnrequest_free(lwres_context_t *ctx, lwres_grbnrequest_t **structp)
390 {
391         lwres_grbnrequest_t *grbn;
392
393         REQUIRE(ctx != NULL);
394         REQUIRE(structp != NULL && *structp != NULL);
395
396         grbn = *structp;
397         *structp = NULL;
398
399         CTXFREE(grbn, sizeof(lwres_grbnrequest_t));
400 }
401
402 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
403 void
404 lwres_grbnresponse_free(lwres_context_t *ctx, lwres_grbnresponse_t **structp)
405 {
406         lwres_grbnresponse_t *grbn;
407
408         REQUIRE(ctx != NULL);
409         REQUIRE(structp != NULL && *structp != NULL);
410
411         grbn = *structp;
412         *structp = NULL;
413
414         if (grbn->nrdatas > 0) {
415                 CTXFREE(grbn->rdatas, sizeof(char *) * grbn->nrdatas);
416                 CTXFREE(grbn->rdatalen,
417                         sizeof(lwres_uint16_t) * grbn->nrdatas);
418         }
419         if (grbn->nsigs > 0) {
420                 CTXFREE(grbn->sigs, sizeof(char *) * grbn->nsigs);
421                 CTXFREE(grbn->siglen, sizeof(lwres_uint16_t) * grbn->nsigs);
422         }
423         if (grbn->base != NULL)
424                 CTXFREE(grbn->base, grbn->baselen);
425         CTXFREE(grbn, sizeof(lwres_grbnresponse_t));
426 }