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