lwres_grbn.c revision 170223
16448Sache/*
26448Sache * Copyright (C) 2004, 2005  Internet Systems Consortium, Inc. ("ISC")
36448Sache * Copyright (C) 2000, 2001  Internet Software Consortium.
46448Sache *
58857Srgrimes * Permission to use, copy, modify, and distribute this software for any
66448Sache * purpose with or without fee is hereby granted, provided that the above
76448Sache * copyright notice and this permission notice appear in all copies.
86448Sache *
96448Sache * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
1029612Sjmg * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1129612Sjmg * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
126448Sache * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
136448Sache * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14114601Sobrien * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15114601Sobrien * PERFORMANCE OF THIS SOFTWARE.
1629963Scharnier */
1729963Scharnier
1829963Scharnier/* $Id: lwres_grbn.c,v 1.6.18.2 2005/04/29 00:17:20 marka Exp $ */
19177195Sjkim
20177195Sjkim/*! \file lwres_grbn.c
216448Sache
226448Sache */
2329612Sjmg
2429612Sjmg#include <config.h>
256448Sache
266448Sache#include <assert.h>
27227255Sed#include <stdlib.h>
286448Sache#include <string.h>
29177197Sjkim
30177197Sjkim#include <lwres/lwbuffer.h>
31177197Sjkim#include <lwres/lwpacket.h>
326448Sache#include <lwres/lwres.h>
33177197Sjkim#include <lwres/result.h>
3429612Sjmg
356448Sache#include "context_p.h"
36177197Sjkim#include "assert_p.h"
376448Sache
38144999Smdodd/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
39177197Sjkimlwres_result_t
40177197Sjkimlwres_grbnrequest_render(lwres_context_t *ctx, lwres_grbnrequest_t *req,
41177195Sjkim			 lwres_lwpacket_t *pkt, lwres_buffer_t *b)
42177195Sjkim{
43177195Sjkim	unsigned char *buf;
44177195Sjkim	size_t buflen;
45177195Sjkim	int ret;
46177195Sjkim	size_t payload_length;
47177195Sjkim	lwres_uint16_t datalen;
48177197Sjkim
49177195Sjkim	REQUIRE(ctx != NULL);
50177195Sjkim	REQUIRE(req != NULL);
51177195Sjkim	REQUIRE(req->name != NULL);
52177195Sjkim	REQUIRE(pkt != NULL);
53177195Sjkim	REQUIRE(b != NULL);
54177195Sjkim
55177195Sjkim	datalen = strlen(req->name);
56177195Sjkim
57177195Sjkim	payload_length = 4 + 2 + 2 + 2 + req->namelen + 1;
58177197Sjkim
59177195Sjkim	buflen = LWRES_LWPACKET_LENGTH + payload_length;
60177195Sjkim	buf = CTXMALLOC(buflen);
6129612Sjmg	if (buf == NULL)
626448Sache		return (LWRES_R_NOMEMORY);
636448Sache
646448Sache	lwres_buffer_init(b, buf, buflen);
65177197Sjkim
6629612Sjmg	pkt->length = buflen;
676448Sache	pkt->version = LWRES_LWPACKETVERSION_0;
68177197Sjkim	pkt->pktflags &= ~LWRES_LWPACKETFLAG_RESPONSE;
6929612Sjmg	pkt->opcode = LWRES_OPCODE_GETRDATABYNAME;
7029612Sjmg	pkt->result = 0;
71177197Sjkim	pkt->authtype = 0;
7229612Sjmg	pkt->authlength = 0;
7329612Sjmg
74177197Sjkim	ret = lwres_lwpacket_renderheader(b, pkt);
7529612Sjmg	if (ret != LWRES_R_SUCCESS) {
7629612Sjmg		lwres_buffer_invalidate(b);
77177197Sjkim		CTXFREE(buf, buflen);
78177197Sjkim		return (ret);
7929612Sjmg	}
80177197Sjkim
816448Sache	INSIST(SPACE_OK(b, payload_length));
82177195Sjkim
83177195Sjkim	/*
84177195Sjkim	 * Flags.
85177197Sjkim	 */
86153953Sariff	lwres_buffer_putuint32(b, req->flags);
87153953Sariff
88177197Sjkim	/*
896448Sache	 * Class.
90177197Sjkim	 */
91177197Sjkim	lwres_buffer_putuint16(b, req->rdclass);
92177197Sjkim
93153953Sariff	/*
94153953Sariff	 * Type.
95177197Sjkim	 */
966448Sache	lwres_buffer_putuint16(b, req->rdtype);
97177197Sjkim
98153953Sariff	/*
996448Sache	 * Put the length and the data.  We know this will fit because we
1006448Sache	 * just checked for it.
1018857Srgrimes	 */
1026448Sache	lwres_buffer_putuint16(b, datalen);
1036448Sache	lwres_buffer_putmem(b, (unsigned char *)req->name, datalen);
104177197Sjkim	lwres_buffer_putuint8(b, 0); /* trailing NUL */
105177197Sjkim
106177197Sjkim	INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
107177197Sjkim
108177197Sjkim	return (LWRES_R_SUCCESS);
109177197Sjkim}
110177197Sjkim
1116448Sache/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
112177195Sjkimlwres_result_t
113177195Sjkimlwres_grbnresponse_render(lwres_context_t *ctx, lwres_grbnresponse_t *req,
114177195Sjkim			  lwres_lwpacket_t *pkt, lwres_buffer_t *b)
115177195Sjkim{
116177195Sjkim	unsigned char *buf;
117177195Sjkim	size_t buflen;
118177195Sjkim	int ret;
119177195Sjkim	size_t payload_length;
120177195Sjkim	lwres_uint16_t datalen;
1216448Sache	int x;
122177195Sjkim
123177195Sjkim	REQUIRE(ctx != NULL);
124177195Sjkim	REQUIRE(req != NULL);
125177195Sjkim	REQUIRE(pkt != NULL);
126177195Sjkim	REQUIRE(b != NULL);
127177195Sjkim
12864657Ssobomax	/* flags, class, type, ttl, nrdatas, nsigs */
129177195Sjkim	payload_length = 4 + 2 + 2 + 4 + 2 + 2;
13064657Ssobomax	/* real name encoding */
131177195Sjkim	payload_length += 2 + req->realnamelen + 1;
132177195Sjkim	/* each rr */
133177195Sjkim	for (x = 0; x < req->nrdatas; x++)
134177195Sjkim		payload_length += 2 + req->rdatalen[x];
135177195Sjkim	for (x = 0; x < req->nsigs; x++)
136177197Sjkim		payload_length += 2 + req->siglen[x];
137177195Sjkim
138177195Sjkim	buflen = LWRES_LWPACKET_LENGTH + payload_length;
139177197Sjkim	buf = CTXMALLOC(buflen);
140177195Sjkim	if (buf == NULL)
141177195Sjkim		return (LWRES_R_NOMEMORY);
142177195Sjkim	lwres_buffer_init(b, buf, buflen);
143177195Sjkim
144177195Sjkim	pkt->length = buflen;
145177195Sjkim	pkt->version = LWRES_LWPACKETVERSION_0;
146177197Sjkim	pkt->pktflags |= LWRES_LWPACKETFLAG_RESPONSE;
147177195Sjkim	pkt->opcode = LWRES_OPCODE_GETRDATABYNAME;
14829612Sjmg	pkt->authtype = 0;
149177195Sjkim	pkt->authlength = 0;
150177195Sjkim
151177195Sjkim	ret = lwres_lwpacket_renderheader(b, pkt);
15229963Scharnier	if (ret != LWRES_R_SUCCESS) {
15329963Scharnier		lwres_buffer_invalidate(b);
15429963Scharnier		CTXFREE(buf, buflen);
15530028Scharnier		return (ret);
15629963Scharnier	}
15730028Scharnier
15829963Scharnier	/*
15930028Scharnier	 * Check space needed here.
16029612Sjmg	 */
1616448Sache	INSIST(SPACE_OK(b, payload_length));
162177197Sjkim
163177197Sjkim	/* Flags. */
164177197Sjkim	lwres_buffer_putuint32(b, req->flags);
16513803Smpp
166177197Sjkim	/* encode class, type, ttl, and nrdatas */
16729963Scharnier	lwres_buffer_putuint16(b, req->rdclass);
16813803Smpp	lwres_buffer_putuint16(b, req->rdtype);
16913803Smpp	lwres_buffer_putuint32(b, req->ttl);
170177197Sjkim	lwres_buffer_putuint16(b, req->nrdatas);
171177197Sjkim	lwres_buffer_putuint16(b, req->nsigs);
172177197Sjkim
173177197Sjkim	/* encode the real name */
174177197Sjkim	datalen = req->realnamelen;
175177197Sjkim	lwres_buffer_putuint16(b, datalen);
176177197Sjkim	lwres_buffer_putmem(b, (unsigned char *)req->realname, datalen);
177177197Sjkim	lwres_buffer_putuint8(b, 0);
178177197Sjkim
17913803Smpp	/* encode the rdatas */
180177197Sjkim	for (x = 0; x < req->nrdatas; x++) {
181177197Sjkim		datalen = req->rdatalen[x];
182177198Sjkim		lwres_buffer_putuint16(b, datalen);
183177197Sjkim		lwres_buffer_putmem(b, req->rdatas[x], datalen);
18413803Smpp	}
18513803Smpp
186177197Sjkim	/* encode the signatures */
187177197Sjkim	for (x = 0; x < req->nsigs; x++) {
1886448Sache		datalen = req->siglen[x];
189177197Sjkim		lwres_buffer_putuint16(b, datalen);
190177197Sjkim		lwres_buffer_putmem(b, req->sigs[x], datalen);
191177197Sjkim	}
19229612Sjmg
193177197Sjkim	INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
194177197Sjkim	INSIST(LWRES_BUFFER_USEDCOUNT(b) == pkt->length);
19529612Sjmg
196230611Smav	return (LWRES_R_SUCCESS);
19729612Sjmg}
19829612Sjmg
19964657Ssobomax/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
20029612Sjmglwres_result_t
20164657Ssobomaxlwres_grbnrequest_parse(lwres_context_t *ctx, lwres_buffer_t *b,
20213435Smpp			lwres_lwpacket_t *pkt, lwres_grbnrequest_t **structp)
203230611Smav{
204230611Smav	int ret;
205230611Smav	char *name;
206230611Smav	lwres_grbnrequest_t *grbn;
207230611Smav	lwres_uint32_t flags;
20829612Sjmg	lwres_uint16_t rdclass, rdtype;
20964657Ssobomax	lwres_uint16_t namelen;
21029612Sjmg
21164657Ssobomax	REQUIRE(ctx != NULL);
2126448Sache	REQUIRE(pkt != NULL);
213177197Sjkim	REQUIRE(b != NULL);
21429612Sjmg	REQUIRE(structp != NULL && *structp == NULL);
2156448Sache
21629612Sjmg	if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) != 0)
21729612Sjmg		return (LWRES_R_FAILURE);
2186448Sache
21929612Sjmg	if (!SPACE_REMAINING(b, 4 + 2 + 2))
22029612Sjmg		return (LWRES_R_UNEXPECTEDEND);
22129612Sjmg
22229612Sjmg	/*
22329612Sjmg	 * Pull off the flags, class, and type.
22429612Sjmg	 */
22529612Sjmg	flags = lwres_buffer_getuint32(b);
22629612Sjmg	rdclass = lwres_buffer_getuint16(b);
22729612Sjmg	rdtype = lwres_buffer_getuint16(b);
228177197Sjkim
229177197Sjkim	/*
23029612Sjmg	 * Pull off the name itself
23129612Sjmg	 */
2326448Sache	ret = lwres_string_parse(b, &name, &namelen);
233177197Sjkim	if (ret != LWRES_R_SUCCESS)
23475334Sgreid		return (ret);
235177197Sjkim
23664657Ssobomax	if (LWRES_BUFFER_REMAINING(b) != 0)
23729612Sjmg		return (LWRES_R_TRAILINGDATA);
23864657Ssobomax
23929612Sjmg	grbn = CTXMALLOC(sizeof(lwres_grbnrequest_t));
24029612Sjmg	if (grbn == NULL)
241177197Sjkim		return (LWRES_R_NOMEMORY);
242113299Smdodd
243177197Sjkim	grbn->flags = flags;
244177197Sjkim	grbn->rdclass = rdclass;
245177197Sjkim	grbn->rdtype = rdtype;
246113299Smdodd	grbn->name = name;
247177197Sjkim	grbn->namelen = namelen;
248113299Smdodd
249177197Sjkim	*structp = grbn;
250177197Sjkim	return (LWRES_R_SUCCESS);
251113299Smdodd}
252177197Sjkim
253113299Smdodd/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
254113299Smdoddlwres_result_t
255113299Smdoddlwres_grbnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b,
256177197Sjkim			lwres_lwpacket_t *pkt, lwres_grbnresponse_t **structp)
25729612Sjmg{
258177197Sjkim	lwres_result_t ret;
25929963Scharnier	unsigned int x;
260177197Sjkim	lwres_uint32_t flags;
261177197Sjkim	lwres_uint16_t rdclass, rdtype;
26229612Sjmg	lwres_uint32_t ttl;
2636448Sache	lwres_uint16_t nrdatas, nsigs;
264177197Sjkim	lwres_grbnresponse_t *grbn;
265177197Sjkim
266177197Sjkim	REQUIRE(ctx != NULL);
267177197Sjkim	REQUIRE(pkt != NULL);
268177197Sjkim	REQUIRE(b != NULL);
269177197Sjkim	REQUIRE(structp != NULL && *structp == NULL);
270177197Sjkim
271177197Sjkim	grbn = NULL;
272177197Sjkim
2736448Sache	if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0)
274177197Sjkim		return (LWRES_R_FAILURE);
275177197Sjkim
27629612Sjmg	/*
27729612Sjmg	 * Pull off the flags, class, type, ttl, nrdatas, and nsigs
27829612Sjmg	 */
279177197Sjkim	if (!SPACE_REMAINING(b, 4 + 2 + 2 + 4 + 2 + 2))
28029612Sjmg		return (LWRES_R_UNEXPECTEDEND);
281177197Sjkim	flags = lwres_buffer_getuint32(b);
282113299Smdodd	rdclass = lwres_buffer_getuint16(b);
283177197Sjkim	rdtype = lwres_buffer_getuint16(b);
284177197Sjkim	ttl = lwres_buffer_getuint32(b);
285113299Smdodd	nrdatas = lwres_buffer_getuint16(b);
286113299Smdodd	nsigs = lwres_buffer_getuint16(b);
287113299Smdodd
288113299Smdodd	/*
289113299Smdodd	 * Pull off the name itself
290113299Smdodd	 */
291113299Smdodd
292113299Smdodd	grbn = CTXMALLOC(sizeof(lwres_grbnresponse_t));
29329612Sjmg	if (grbn == NULL)
29429612Sjmg		return (LWRES_R_NOMEMORY);
29529612Sjmg	grbn->rdatas = NULL;
29629612Sjmg	grbn->rdatalen = NULL;
29729612Sjmg	grbn->sigs = NULL;
29829612Sjmg	grbn->siglen = NULL;
29929612Sjmg	grbn->base = NULL;
30029612Sjmg
3018857Srgrimes	grbn->flags = flags;
302177197Sjkim	grbn->rdclass = rdclass;
303177197Sjkim	grbn->rdtype = rdtype;
304177197Sjkim	grbn->ttl = ttl;
305177197Sjkim	grbn->nrdatas = nrdatas;
306108421Sjmallett	grbn->nsigs = nsigs;
30729612Sjmg
30829612Sjmg	if (nrdatas > 0) {
30929963Scharnier		grbn->rdatas = CTXMALLOC(sizeof(char *) * nrdatas);
3106448Sache		if (grbn->rdatas == NULL) {
311177197Sjkim			ret = LWRES_R_NOMEMORY;
312177197Sjkim			goto out;
31329612Sjmg		}
3146448Sache
3156448Sache		grbn->rdatalen = CTXMALLOC(sizeof(lwres_uint16_t) * nrdatas);
3166448Sache		if (grbn->rdatalen == NULL) {
31764657Ssobomax			ret = LWRES_R_NOMEMORY;
31864657Ssobomax			goto out;
31964657Ssobomax		}
320177197Sjkim	}
32164657Ssobomax
32264657Ssobomax	if (nsigs > 0) {
323177195Sjkim		grbn->sigs = CTXMALLOC(sizeof(char *) * nsigs);
32429963Scharnier		if (grbn->sigs == NULL) {
32530028Scharnier			ret = LWRES_R_NOMEMORY;
32629963Scharnier			goto out;
32730028Scharnier		}
32829612Sjmg
329177197Sjkim		grbn->siglen = CTXMALLOC(sizeof(lwres_uint16_t) * nsigs);
330177195Sjkim		if (grbn->siglen == NULL) {
331177197Sjkim			ret = LWRES_R_NOMEMORY;
33229612Sjmg			goto out;
3336448Sache		}
33429612Sjmg	}
335177197Sjkim
3366448Sache	/*
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. */
388void
389lwres_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. */
403void
404lwres_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}
427