1 /* $NetBSD: lwres_grbn.c,v 1.5 2014/12/10 04:38:02 christos Exp $ */
4 * Copyright (C) 2004, 2005, 2007, 2013 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000, 2001 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: lwres_grbn.c,v 1.10 2007/06/19 23:47:22 tbox Exp */
22 /*! \file lwres_grbn.c
32 #include <lwres/lwbuffer.h>
33 #include <lwres/lwpacket.h>
34 #include <lwres/lwres.h>
35 #include <lwres/result.h>
37 #include "context_p.h"
40 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
42 lwres_grbnrequest_render(lwres_context_t
*ctx
, lwres_grbnrequest_t
*req
,
43 lwres_lwpacket_t
*pkt
, lwres_buffer_t
*b
)
48 size_t payload_length
;
49 lwres_uint16_t datalen
;
53 REQUIRE(req
->name
!= NULL
);
57 datalen
= strlen(req
->name
);
59 payload_length
= 4 + 2 + 2 + 2 + req
->namelen
+ 1;
61 buflen
= LWRES_LWPACKET_LENGTH
+ payload_length
;
62 buf
= CTXMALLOC(buflen
);
64 return (LWRES_R_NOMEMORY
);
66 lwres_buffer_init(b
, buf
, (unsigned int)buflen
);
68 pkt
->length
= (lwres_uint32_t
)buflen
;
69 pkt
->version
= LWRES_LWPACKETVERSION_0
;
70 pkt
->pktflags
&= ~LWRES_LWPACKETFLAG_RESPONSE
;
71 pkt
->opcode
= LWRES_OPCODE_GETRDATABYNAME
;
76 ret
= lwres_lwpacket_renderheader(b
, pkt
);
77 if (ret
!= LWRES_R_SUCCESS
) {
78 lwres_buffer_invalidate(b
);
83 INSIST(SPACE_OK(b
, payload_length
));
88 lwres_buffer_putuint32(b
, req
->flags
);
93 lwres_buffer_putuint16(b
, req
->rdclass
);
98 lwres_buffer_putuint16(b
, req
->rdtype
);
101 * Put the length and the data. We know this will fit because we
102 * just checked for it.
104 lwres_buffer_putuint16(b
, datalen
);
105 lwres_buffer_putmem(b
, (unsigned char *)req
->name
, datalen
);
106 lwres_buffer_putuint8(b
, 0); /* trailing NUL */
108 INSIST(LWRES_BUFFER_AVAILABLECOUNT(b
) == 0);
110 return (LWRES_R_SUCCESS
);
113 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
115 lwres_grbnresponse_render(lwres_context_t
*ctx
, lwres_grbnresponse_t
*req
,
116 lwres_lwpacket_t
*pkt
, lwres_buffer_t
*b
)
121 size_t payload_length
;
122 lwres_uint16_t datalen
;
125 REQUIRE(ctx
!= NULL
);
126 REQUIRE(req
!= NULL
);
127 REQUIRE(pkt
!= NULL
);
130 /* flags, class, type, ttl, nrdatas, nsigs */
131 payload_length
= 4 + 2 + 2 + 4 + 2 + 2;
132 /* real name encoding */
133 payload_length
+= 2 + req
->realnamelen
+ 1;
135 for (x
= 0; x
< req
->nrdatas
; x
++)
136 payload_length
+= 2 + req
->rdatalen
[x
];
137 for (x
= 0; x
< req
->nsigs
; x
++)
138 payload_length
+= 2 + req
->siglen
[x
];
140 buflen
= LWRES_LWPACKET_LENGTH
+ payload_length
;
141 buf
= CTXMALLOC(buflen
);
143 return (LWRES_R_NOMEMORY
);
144 lwres_buffer_init(b
, buf
, (unsigned int)buflen
);
146 pkt
->length
= (lwres_uint32_t
)buflen
;
147 pkt
->version
= LWRES_LWPACKETVERSION_0
;
148 pkt
->pktflags
|= LWRES_LWPACKETFLAG_RESPONSE
;
149 pkt
->opcode
= LWRES_OPCODE_GETRDATABYNAME
;
153 ret
= lwres_lwpacket_renderheader(b
, pkt
);
154 if (ret
!= LWRES_R_SUCCESS
) {
155 lwres_buffer_invalidate(b
);
156 CTXFREE(buf
, buflen
);
161 * Check space needed here.
163 INSIST(SPACE_OK(b
, payload_length
));
166 lwres_buffer_putuint32(b
, req
->flags
);
168 /* encode class, type, ttl, and nrdatas */
169 lwres_buffer_putuint16(b
, req
->rdclass
);
170 lwres_buffer_putuint16(b
, req
->rdtype
);
171 lwres_buffer_putuint32(b
, req
->ttl
);
172 lwres_buffer_putuint16(b
, req
->nrdatas
);
173 lwres_buffer_putuint16(b
, req
->nsigs
);
175 /* encode the real name */
176 datalen
= req
->realnamelen
;
177 lwres_buffer_putuint16(b
, datalen
);
178 lwres_buffer_putmem(b
, (unsigned char *)req
->realname
, datalen
);
179 lwres_buffer_putuint8(b
, 0);
181 /* encode the rdatas */
182 for (x
= 0; x
< req
->nrdatas
; x
++) {
183 datalen
= req
->rdatalen
[x
];
184 lwres_buffer_putuint16(b
, datalen
);
185 lwres_buffer_putmem(b
, req
->rdatas
[x
], datalen
);
188 /* encode the signatures */
189 for (x
= 0; x
< req
->nsigs
; x
++) {
190 datalen
= req
->siglen
[x
];
191 lwres_buffer_putuint16(b
, datalen
);
192 lwres_buffer_putmem(b
, req
->sigs
[x
], datalen
);
195 INSIST(LWRES_BUFFER_AVAILABLECOUNT(b
) == 0);
196 INSIST(LWRES_BUFFER_USEDCOUNT(b
) == pkt
->length
);
198 return (LWRES_R_SUCCESS
);
201 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
203 lwres_grbnrequest_parse(lwres_context_t
*ctx
, lwres_buffer_t
*b
,
204 lwres_lwpacket_t
*pkt
, lwres_grbnrequest_t
**structp
)
208 lwres_grbnrequest_t
*grbn
;
209 lwres_uint32_t flags
;
210 lwres_uint16_t rdclass
, rdtype
;
211 lwres_uint16_t namelen
;
213 REQUIRE(ctx
!= NULL
);
214 REQUIRE(pkt
!= NULL
);
216 REQUIRE(structp
!= NULL
&& *structp
== NULL
);
218 if ((pkt
->pktflags
& LWRES_LWPACKETFLAG_RESPONSE
) != 0)
219 return (LWRES_R_FAILURE
);
221 if (!SPACE_REMAINING(b
, 4 + 2 + 2))
222 return (LWRES_R_UNEXPECTEDEND
);
225 * Pull off the flags, class, and type.
227 flags
= lwres_buffer_getuint32(b
);
228 rdclass
= lwres_buffer_getuint16(b
);
229 rdtype
= lwres_buffer_getuint16(b
);
232 * Pull off the name itself
234 ret
= lwres_string_parse(b
, &name
, &namelen
);
235 if (ret
!= LWRES_R_SUCCESS
)
238 if (LWRES_BUFFER_REMAINING(b
) != 0)
239 return (LWRES_R_TRAILINGDATA
);
241 grbn
= CTXMALLOC(sizeof(lwres_grbnrequest_t
));
243 return (LWRES_R_NOMEMORY
);
246 grbn
->rdclass
= rdclass
;
247 grbn
->rdtype
= rdtype
;
249 grbn
->namelen
= namelen
;
252 return (LWRES_R_SUCCESS
);
255 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
257 lwres_grbnresponse_parse(lwres_context_t
*ctx
, lwres_buffer_t
*b
,
258 lwres_lwpacket_t
*pkt
, lwres_grbnresponse_t
**structp
)
262 lwres_uint32_t flags
;
263 lwres_uint16_t rdclass
, rdtype
;
265 lwres_uint16_t nrdatas
, nsigs
;
266 lwres_grbnresponse_t
*grbn
;
268 REQUIRE(ctx
!= NULL
);
269 REQUIRE(pkt
!= NULL
);
271 REQUIRE(structp
!= NULL
&& *structp
== NULL
);
275 if ((pkt
->pktflags
& LWRES_LWPACKETFLAG_RESPONSE
) == 0)
276 return (LWRES_R_FAILURE
);
279 * Pull off the flags, class, type, ttl, nrdatas, and nsigs
281 if (!SPACE_REMAINING(b
, 4 + 2 + 2 + 4 + 2 + 2))
282 return (LWRES_R_UNEXPECTEDEND
);
283 flags
= lwres_buffer_getuint32(b
);
284 rdclass
= lwres_buffer_getuint16(b
);
285 rdtype
= lwres_buffer_getuint16(b
);
286 ttl
= lwres_buffer_getuint32(b
);
287 nrdatas
= lwres_buffer_getuint16(b
);
288 nsigs
= lwres_buffer_getuint16(b
);
291 * Pull off the name itself
294 grbn
= CTXMALLOC(sizeof(lwres_grbnresponse_t
));
296 return (LWRES_R_NOMEMORY
);
298 grbn
->rdatalen
= NULL
;
304 grbn
->rdclass
= rdclass
;
305 grbn
->rdtype
= rdtype
;
307 grbn
->nrdatas
= nrdatas
;
311 grbn
->rdatas
= CTXMALLOC(sizeof(char *) * nrdatas
);
312 if (grbn
->rdatas
== NULL
) {
313 ret
= LWRES_R_NOMEMORY
;
317 grbn
->rdatalen
= CTXMALLOC(sizeof(lwres_uint16_t
) * nrdatas
);
318 if (grbn
->rdatalen
== NULL
) {
319 ret
= LWRES_R_NOMEMORY
;
325 grbn
->sigs
= CTXMALLOC(sizeof(char *) * nsigs
);
326 if (grbn
->sigs
== NULL
) {
327 ret
= LWRES_R_NOMEMORY
;
331 grbn
->siglen
= CTXMALLOC(sizeof(lwres_uint16_t
) * nsigs
);
332 if (grbn
->siglen
== NULL
) {
333 ret
= LWRES_R_NOMEMORY
;
339 * Now, pull off the real name.
341 ret
= lwres_string_parse(b
, &grbn
->realname
, &grbn
->realnamelen
);
342 if (ret
!= LWRES_R_SUCCESS
)
346 * Parse off the rdatas.
348 for (x
= 0; x
< grbn
->nrdatas
; x
++) {
349 ret
= lwres_data_parse(b
, &grbn
->rdatas
[x
],
351 if (ret
!= LWRES_R_SUCCESS
)
356 * Parse off the signatures.
358 for (x
= 0; x
< grbn
->nsigs
; x
++) {
359 ret
= lwres_data_parse(b
, &grbn
->sigs
[x
], &grbn
->siglen
[x
]);
360 if (ret
!= LWRES_R_SUCCESS
)
364 if (LWRES_BUFFER_REMAINING(b
) != 0) {
365 ret
= LWRES_R_TRAILINGDATA
;
370 return (LWRES_R_SUCCESS
);
374 if (grbn
->rdatas
!= NULL
)
375 CTXFREE(grbn
->rdatas
, sizeof(char *) * nrdatas
);
376 if (grbn
->rdatalen
!= NULL
)
377 CTXFREE(grbn
->rdatalen
,
378 sizeof(lwres_uint16_t
) * nrdatas
);
379 if (grbn
->sigs
!= NULL
)
380 CTXFREE(grbn
->sigs
, sizeof(char *) * nsigs
);
381 if (grbn
->siglen
!= NULL
)
382 CTXFREE(grbn
->siglen
, sizeof(lwres_uint16_t
) * nsigs
);
383 CTXFREE(grbn
, sizeof(lwres_grbnresponse_t
));
389 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
391 lwres_grbnrequest_free(lwres_context_t
*ctx
, lwres_grbnrequest_t
**structp
)
393 lwres_grbnrequest_t
*grbn
;
395 REQUIRE(ctx
!= NULL
);
396 REQUIRE(structp
!= NULL
&& *structp
!= NULL
);
401 CTXFREE(grbn
, sizeof(lwres_grbnrequest_t
));
404 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
406 lwres_grbnresponse_free(lwres_context_t
*ctx
, lwres_grbnresponse_t
**structp
)
408 lwres_grbnresponse_t
*grbn
;
410 REQUIRE(ctx
!= NULL
);
411 REQUIRE(structp
!= NULL
&& *structp
!= NULL
);
416 if (grbn
->nrdatas
> 0) {
417 CTXFREE(grbn
->rdatas
, sizeof(char *) * grbn
->nrdatas
);
418 CTXFREE(grbn
->rdatalen
,
419 sizeof(lwres_uint16_t
) * grbn
->nrdatas
);
421 if (grbn
->nsigs
> 0) {
422 CTXFREE(grbn
->sigs
, sizeof(char *) * grbn
->nsigs
);
423 CTXFREE(grbn
->siglen
, sizeof(lwres_uint16_t
) * grbn
->nsigs
);
425 if (grbn
->base
!= NULL
)
426 CTXFREE(grbn
->base
, grbn
->baselen
);
427 CTXFREE(grbn
, sizeof(lwres_grbnresponse_t
));