lwres_grbn.c revision 170222
1207618Srdivacky/*
2207618Srdivacky * Copyright (C) 2004, 2005  Internet Systems Consortium, Inc. ("ISC")
3207618Srdivacky * Copyright (C) 2000, 2001  Internet Software Consortium.
4207618Srdivacky *
5207618Srdivacky * Permission to use, copy, modify, and distribute this software for any
6207618Srdivacky * purpose with or without fee is hereby granted, provided that the above
7207618Srdivacky * copyright notice and this permission notice appear in all copies.
8207618Srdivacky *
9207618Srdivacky * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10207618Srdivacky * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11207618Srdivacky * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12207618Srdivacky * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13207618Srdivacky * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14207618Srdivacky * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15207618Srdivacky * PERFORMANCE OF THIS SOFTWARE.
16207618Srdivacky */
17207618Srdivacky
18207618Srdivacky/* $Id: lwres_grbn.c,v 1.6.18.2 2005/04/29 00:17:20 marka Exp $ */
19207618Srdivacky
20207618Srdivacky/*! \file lwres_grbn.c
21207618Srdivacky
22210299Sed */
23210299Sed
24207618Srdivacky#include <config.h>
25207618Srdivacky
26207618Srdivacky#include <assert.h>
27207618Srdivacky#include <stdlib.h>
28207618Srdivacky#include <string.h>
29207618Srdivacky
30207618Srdivacky#include <lwres/lwbuffer.h>
31207618Srdivacky#include <lwres/lwpacket.h>
32207618Srdivacky#include <lwres/lwres.h>
33207618Srdivacky#include <lwres/result.h>
34207618Srdivacky
35207618Srdivacky#include "context_p.h"
36207618Srdivacky#include "assert_p.h"
37252723Sdim
38252723Sdim/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
39207618Srdivackylwres_result_t
40210299Sedlwres_grbnrequest_render(lwres_context_t *ctx, lwres_grbnrequest_t *req,
41210299Sed			 lwres_lwpacket_t *pkt, lwres_buffer_t *b)
42252723Sdim{
43210299Sed	unsigned char *buf;
44252723Sdim	size_t buflen;
45207618Srdivacky	int ret;
46207618Srdivacky	size_t payload_length;
47252723Sdim	lwres_uint16_t datalen;
48252723Sdim
49252723Sdim	REQUIRE(ctx != NULL);
50252723Sdim	REQUIRE(req != NULL);
51207618Srdivacky	REQUIRE(req->name != NULL);
52207618Srdivacky	REQUIRE(pkt != NULL);
53207618Srdivacky	REQUIRE(b != NULL);
54207618Srdivacky
55207618Srdivacky	datalen = strlen(req->name);
56252723Sdim
57207618Srdivacky	payload_length = 4 + 2 + 2 + 2 + req->namelen + 1;
58207618Srdivacky
59207618Srdivacky	buflen = LWRES_LWPACKET_LENGTH + payload_length;
60207618Srdivacky	buf = CTXMALLOC(buflen);
61207618Srdivacky	if (buf == NULL)
62207618Srdivacky		return (LWRES_R_NOMEMORY);
63207618Srdivacky
64207618Srdivacky	lwres_buffer_init(b, buf, buflen);
65207618Srdivacky
66207618Srdivacky	pkt->length = buflen;
67207618Srdivacky	pkt->version = LWRES_LWPACKETVERSION_0;
68207618Srdivacky	pkt->pktflags &= ~LWRES_LWPACKETFLAG_RESPONSE;
69207618Srdivacky	pkt->opcode = LWRES_OPCODE_GETRDATABYNAME;
70207618Srdivacky	pkt->result = 0;
71207618Srdivacky	pkt->authtype = 0;
72207618Srdivacky	pkt->authlength = 0;
73210299Sed
74218893Sdim	ret = lwres_lwpacket_renderheader(b, pkt);
75226890Sdim	if (ret != LWRES_R_SUCCESS) {
76207618Srdivacky		lwres_buffer_invalidate(b);
77207618Srdivacky		CTXFREE(buf, buflen);
78207618Srdivacky		return (ret);
79207618Srdivacky	}
80207618Srdivacky
81207618Srdivacky	INSIST(SPACE_OK(b, payload_length));
82207618Srdivacky
83207618Srdivacky	/*
84207618Srdivacky	 * Flags.
85207618Srdivacky	 */
86207618Srdivacky	lwres_buffer_putuint32(b, req->flags);
87207618Srdivacky
88207618Srdivacky	/*
89207618Srdivacky	 * Class.
90207618Srdivacky	 */
91207618Srdivacky	lwres_buffer_putuint16(b, req->rdclass);
92207618Srdivacky
93207618Srdivacky	/*
94207618Srdivacky	 * Type.
95207618Srdivacky	 */
96207618Srdivacky	lwres_buffer_putuint16(b, req->rdtype);
97207618Srdivacky
98210299Sed	/*
99210299Sed	 * Put the length and the data.  We know this will fit because we
100210299Sed	 * just checked for it.
101210299Sed	 */
102207618Srdivacky	lwres_buffer_putuint16(b, datalen);
103207618Srdivacky	lwres_buffer_putmem(b, (unsigned char *)req->name, datalen);
104207618Srdivacky	lwres_buffer_putuint8(b, 0); /* trailing NUL */
105210299Sed
106245431Sdim	INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
107235633Sdim
108207618Srdivacky	return (LWRES_R_SUCCESS);
109207618Srdivacky}
110207618Srdivacky
111207618Srdivacky/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
112207618Srdivackylwres_result_t
113218893Sdimlwres_grbnresponse_render(lwres_context_t *ctx, lwres_grbnresponse_t *req,
114218893Sdim			  lwres_lwpacket_t *pkt, lwres_buffer_t *b)
115218893Sdim{
116207618Srdivacky	unsigned char *buf;
117207618Srdivacky	size_t buflen;
118207618Srdivacky	int ret;
119207618Srdivacky	size_t payload_length;
120207618Srdivacky	lwres_uint16_t datalen;
121207618Srdivacky	int x;
122235633Sdim
123210299Sed	REQUIRE(ctx != NULL);
124207618Srdivacky	REQUIRE(req != NULL);
125207618Srdivacky	REQUIRE(pkt != NULL);
126207618Srdivacky	REQUIRE(b != NULL);
127207618Srdivacky
128207618Srdivacky	/* flags, class, type, ttl, nrdatas, nsigs */
129207618Srdivacky	payload_length = 4 + 2 + 2 + 4 + 2 + 2;
130207618Srdivacky	/* real name encoding */
131207618Srdivacky	payload_length += 2 + req->realnamelen + 1;
132207618Srdivacky	/* each rr */
133207618Srdivacky	for (x = 0; x < req->nrdatas; x++)
134207618Srdivacky		payload_length += 2 + req->rdatalen[x];
135207618Srdivacky	for (x = 0; x < req->nsigs; x++)
136207618Srdivacky		payload_length += 2 + req->siglen[x];
137207618Srdivacky
138207618Srdivacky	buflen = LWRES_LWPACKET_LENGTH + payload_length;
139207618Srdivacky	buf = CTXMALLOC(buflen);
140207618Srdivacky	if (buf == NULL)
141207618Srdivacky		return (LWRES_R_NOMEMORY);
142207618Srdivacky	lwres_buffer_init(b, buf, buflen);
143207618Srdivacky
144207618Srdivacky	pkt->length = buflen;
145207618Srdivacky	pkt->version = LWRES_LWPACKETVERSION_0;
146207618Srdivacky	pkt->pktflags |= LWRES_LWPACKETFLAG_RESPONSE;
147207618Srdivacky	pkt->opcode = LWRES_OPCODE_GETRDATABYNAME;
148207618Srdivacky	pkt->authtype = 0;
149207618Srdivacky	pkt->authlength = 0;
150207618Srdivacky
151207618Srdivacky	ret = lwres_lwpacket_renderheader(b, pkt);
152207618Srdivacky	if (ret != LWRES_R_SUCCESS) {
153218893Sdim		lwres_buffer_invalidate(b);
154218893Sdim		CTXFREE(buf, buflen);
155235633Sdim		return (ret);
156218893Sdim	}
157218893Sdim
158218893Sdim	/*
159218893Sdim	 * Check space needed here.
160207618Srdivacky	 */
161207618Srdivacky	INSIST(SPACE_OK(b, payload_length));
162207618Srdivacky
163207618Srdivacky	/* Flags. */
164207618Srdivacky	lwres_buffer_putuint32(b, req->flags);
165207618Srdivacky
166207618Srdivacky	/* encode class, type, ttl, and nrdatas */
167207618Srdivacky	lwres_buffer_putuint16(b, req->rdclass);
168207618Srdivacky	lwres_buffer_putuint16(b, req->rdtype);
169207618Srdivacky	lwres_buffer_putuint32(b, req->ttl);
170207618Srdivacky	lwres_buffer_putuint16(b, req->nrdatas);
171207618Srdivacky	lwres_buffer_putuint16(b, req->nsigs);
172207618Srdivacky
173207618Srdivacky	/* encode the real name */
174207618Srdivacky	datalen = req->realnamelen;
175207618Srdivacky	lwres_buffer_putuint16(b, datalen);
176207618Srdivacky	lwres_buffer_putmem(b, (unsigned char *)req->realname, datalen);
177207618Srdivacky	lwres_buffer_putuint8(b, 0);
178207618Srdivacky
179210299Sed	/* encode the rdatas */
180245431Sdim	for (x = 0; x < req->nrdatas; x++) {
181235633Sdim		datalen = req->rdatalen[x];
182207618Srdivacky		lwres_buffer_putuint16(b, datalen);
183207618Srdivacky		lwres_buffer_putmem(b, req->rdatas[x], datalen);
184208599Srdivacky	}
185207618Srdivacky
186207618Srdivacky	/* encode the signatures */
187207618Srdivacky	for (x = 0; x < req->nsigs; x++) {
188207618Srdivacky		datalen = req->siglen[x];
189207618Srdivacky		lwres_buffer_putuint16(b, datalen);
190207618Srdivacky		lwres_buffer_putmem(b, req->sigs[x], datalen);
191207618Srdivacky	}
192207618Srdivacky
193210299Sed	INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
194210299Sed	INSIST(LWRES_BUFFER_USEDCOUNT(b) == pkt->length);
195207618Srdivacky
196207618Srdivacky	return (LWRES_R_SUCCESS);
197207618Srdivacky}
198207618Srdivacky
199207618Srdivacky/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
200207618Srdivackylwres_result_t
201218893Sdimlwres_grbnrequest_parse(lwres_context_t *ctx, lwres_buffer_t *b,
202218893Sdim			lwres_lwpacket_t *pkt, lwres_grbnrequest_t **structp)
203207618Srdivacky{
204210299Sed	int ret;
205207618Srdivacky	char *name;
206207618Srdivacky	lwres_grbnrequest_t *grbn;
207207618Srdivacky	lwres_uint32_t flags;
208207618Srdivacky	lwres_uint16_t rdclass, rdtype;
209226890Sdim	lwres_uint16_t namelen;
210263509Sdim
211207618Srdivacky	REQUIRE(ctx != NULL);
212207618Srdivacky	REQUIRE(pkt != NULL);
213207618Srdivacky	REQUIRE(b != NULL);
214207618Srdivacky	REQUIRE(structp != NULL && *structp == NULL);
215207618Srdivacky
216207618Srdivacky	if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) != 0)
217207618Srdivacky		return (LWRES_R_FAILURE);
218210299Sed
219210299Sed	if (!SPACE_REMAINING(b, 4 + 2 + 2))
220210299Sed		return (LWRES_R_UNEXPECTEDEND);
221207618Srdivacky
222210299Sed	/*
223210299Sed	 * Pull off the flags, class, and type.
224210299Sed	 */
225210299Sed	flags = lwres_buffer_getuint32(b);
226210299Sed	rdclass = lwres_buffer_getuint16(b);
227210299Sed	rdtype = lwres_buffer_getuint16(b);
228210299Sed
229210299Sed	/*
230210299Sed	 * Pull off the name itself
231210299Sed	 */
232210299Sed	ret = lwres_string_parse(b, &name, &namelen);
233207618Srdivacky	if (ret != LWRES_R_SUCCESS)
234218893Sdim		return (ret);
235218893Sdim
236218893Sdim	if (LWRES_BUFFER_REMAINING(b) != 0)
237210299Sed		return (LWRES_R_TRAILINGDATA);
238218893Sdim
239218893Sdim	grbn = CTXMALLOC(sizeof(lwres_grbnrequest_t));
240218893Sdim	if (grbn == NULL)
241218893Sdim		return (LWRES_R_NOMEMORY);
242218893Sdim
243218893Sdim	grbn->flags = flags;
244218893Sdim	grbn->rdclass = rdclass;
245210299Sed	grbn->rdtype = rdtype;
246210299Sed	grbn->name = name;
247210299Sed	grbn->namelen = namelen;
248226890Sdim
249210299Sed	*structp = grbn;
250210299Sed	return (LWRES_R_SUCCESS);
251210299Sed}
252210299Sed
253210299Sed/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
254210299Sedlwres_result_t
255210299Sedlwres_grbnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b,
256207618Srdivacky			lwres_lwpacket_t *pkt, lwres_grbnresponse_t **structp)
257207618Srdivacky{
258208599Srdivacky	lwres_result_t ret;
259208599Srdivacky	unsigned int x;
260208599Srdivacky	lwres_uint32_t flags;
261210299Sed	lwres_uint16_t rdclass, rdtype;
262210299Sed	lwres_uint32_t ttl;
263208599Srdivacky	lwres_uint16_t nrdatas, nsigs;
264210299Sed	lwres_grbnresponse_t *grbn;
265208599Srdivacky
266207618Srdivacky	REQUIRE(ctx != NULL);
267208599Srdivacky	REQUIRE(pkt != NULL);
268207618Srdivacky	REQUIRE(b != NULL);
269207618Srdivacky	REQUIRE(structp != NULL && *structp == NULL);
270207618Srdivacky
271207618Srdivacky	grbn = NULL;
272207618Srdivacky
273207618Srdivacky	if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0)
274207618Srdivacky		return (LWRES_R_FAILURE);
275207618Srdivacky
276210299Sed	/*
277218893Sdim	 * Pull off the flags, class, type, ttl, nrdatas, and nsigs
278218893Sdim	 */
279207618Srdivacky	if (!SPACE_REMAINING(b, 4 + 2 + 2 + 4 + 2 + 2))
280218893Sdim		return (LWRES_R_UNEXPECTEDEND);
281218893Sdim	flags = lwres_buffer_getuint32(b);
282207618Srdivacky	rdclass = lwres_buffer_getuint16(b);
283207618Srdivacky	rdtype = lwres_buffer_getuint16(b);
284207618Srdivacky	ttl = lwres_buffer_getuint32(b);
285207618Srdivacky	nrdatas = lwres_buffer_getuint16(b);
286207618Srdivacky	nsigs = lwres_buffer_getuint16(b);
287218893Sdim
288207618Srdivacky	/*
289210299Sed	 * Pull off the name itself
290210299Sed	 */
291207618Srdivacky
292207618Srdivacky	grbn = CTXMALLOC(sizeof(lwres_grbnresponse_t));
293207618Srdivacky	if (grbn == NULL)
294207618Srdivacky		return (LWRES_R_NOMEMORY);
295207618Srdivacky	grbn->rdatas = NULL;
296207618Srdivacky	grbn->rdatalen = NULL;
297207618Srdivacky	grbn->sigs = NULL;
298207618Srdivacky	grbn->siglen = NULL;
299207618Srdivacky	grbn->base = NULL;
300210299Sed
301218893Sdim	grbn->flags = flags;
302218893Sdim	grbn->rdclass = rdclass;
303207618Srdivacky	grbn->rdtype = rdtype;
304218893Sdim	grbn->ttl = ttl;
305218893Sdim	grbn->nrdatas = nrdatas;
306207618Srdivacky	grbn->nsigs = nsigs;
307207618Srdivacky
308207618Srdivacky	if (nrdatas > 0) {
309207618Srdivacky		grbn->rdatas = CTXMALLOC(sizeof(char *) * nrdatas);
310207618Srdivacky		if (grbn->rdatas == NULL) {
311210299Sed			ret = LWRES_R_NOMEMORY;
312218893Sdim			goto out;
313218893Sdim		}
314207618Srdivacky
315207618Srdivacky		grbn->rdatalen = CTXMALLOC(sizeof(lwres_uint16_t) * nrdatas);
316207618Srdivacky		if (grbn->rdatalen == NULL) {
317207618Srdivacky			ret = LWRES_R_NOMEMORY;
318207618Srdivacky			goto out;
319207618Srdivacky		}
320207618Srdivacky	}
321207618Srdivacky
322207618Srdivacky	if (nsigs > 0) {
323218893Sdim		grbn->sigs = CTXMALLOC(sizeof(char *) * nsigs);
324218893Sdim		if (grbn->sigs == NULL) {
325207618Srdivacky			ret = LWRES_R_NOMEMORY;
326207618Srdivacky			goto out;
327218893Sdim		}
328218893Sdim
329218893Sdim		grbn->siglen = CTXMALLOC(sizeof(lwres_uint16_t) * nsigs);
330218893Sdim		if (grbn->siglen == NULL) {
331207618Srdivacky			ret = LWRES_R_NOMEMORY;
332207618Srdivacky			goto out;
333218893Sdim		}
334218893Sdim	}
335207618Srdivacky
336207618Srdivacky	/*
337207618Srdivacky	 * Now, pull off the real name.
338208599Srdivacky	 */
339208599Srdivacky	ret = lwres_string_parse(b, &grbn->realname, &grbn->realnamelen);
340208599Srdivacky	if (ret != LWRES_R_SUCCESS)
341218893Sdim		goto out;
342218893Sdim
343207618Srdivacky	/*
344207618Srdivacky	 * Parse off the rdatas.
345207618Srdivacky	 */
346207618Srdivacky	for (x = 0; x < grbn->nrdatas; x++) {
347207618Srdivacky		ret = lwres_data_parse(b, &grbn->rdatas[x],
348207618Srdivacky					 &grbn->rdatalen[x]);
349207618Srdivacky		if (ret != LWRES_R_SUCCESS)
350207618Srdivacky			goto out;
351207618Srdivacky	}
352207618Srdivacky
353207618Srdivacky	/*
354207618Srdivacky	 * Parse off the signatures.
355207618Srdivacky	 */
356207618Srdivacky	for (x = 0; x < grbn->nsigs; x++) {
357207618Srdivacky		ret = lwres_data_parse(b, &grbn->sigs[x], &grbn->siglen[x]);
358207618Srdivacky		if (ret != LWRES_R_SUCCESS)
359207618Srdivacky			goto out;
360210299Sed	}
361210299Sed
362210299Sed	if (LWRES_BUFFER_REMAINING(b) != 0) {
363210299Sed		ret = LWRES_R_TRAILINGDATA;
364210299Sed		goto out;
365210299Sed	}
366207618Srdivacky
367207618Srdivacky	*structp = grbn;
368210299Sed	return (LWRES_R_SUCCESS);
369210299Sed
370207618Srdivacky out:
371218893Sdim	if (grbn != NULL) {
372226890Sdim		if (grbn->rdatas != NULL)
373210299Sed			CTXFREE(grbn->rdatas, sizeof(char *) * nrdatas);
374210299Sed		if (grbn->rdatalen != NULL)
375210299Sed			CTXFREE(grbn->rdatalen,
376210299Sed				sizeof(lwres_uint16_t) * nrdatas);
377210299Sed		if (grbn->sigs != NULL)
378210299Sed			CTXFREE(grbn->sigs, sizeof(char *) * nsigs);
379207618Srdivacky		if (grbn->siglen != NULL)
380207618Srdivacky			CTXFREE(grbn->siglen, sizeof(lwres_uint16_t) * nsigs);
381207618Srdivacky		CTXFREE(grbn, sizeof(lwres_grbnresponse_t));
382207618Srdivacky	}
383210299Sed
384210299Sed	return (ret);
385210299Sed}
386210299Sed
387210299Sed/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
388210299Sedvoid
389207618Srdivackylwres_grbnrequest_free(lwres_context_t *ctx, lwres_grbnrequest_t **structp)
390207618Srdivacky{
391207618Srdivacky	lwres_grbnrequest_t *grbn;
392207618Srdivacky
393207618Srdivacky	REQUIRE(ctx != NULL);
394207618Srdivacky	REQUIRE(structp != NULL && *structp != NULL);
395207618Srdivacky
396207618Srdivacky	grbn = *structp;
397207618Srdivacky	*structp = NULL;
398207618Srdivacky
399207618Srdivacky	CTXFREE(grbn, sizeof(lwres_grbnrequest_t));
400207618Srdivacky}
401207618Srdivacky
402207618Srdivacky/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
403207618Srdivackyvoid
404207618Srdivackylwres_grbnresponse_free(lwres_context_t *ctx, lwres_grbnresponse_t **structp)
405207618Srdivacky{
406207618Srdivacky	lwres_grbnresponse_t *grbn;
407207618Srdivacky
408207618Srdivacky	REQUIRE(ctx != NULL);
409207618Srdivacky	REQUIRE(structp != NULL && *structp != NULL);
410207618Srdivacky
411207618Srdivacky	grbn = *structp;
412207618Srdivacky	*structp = NULL;
413207618Srdivacky
414245431Sdim	if (grbn->nrdatas > 0) {
415252723Sdim		CTXFREE(grbn->rdatas, sizeof(char *) * grbn->nrdatas);
416252723Sdim		CTXFREE(grbn->rdatalen,
417252723Sdim			sizeof(lwres_uint16_t) * grbn->nrdatas);
418252723Sdim	}
419252723Sdim	if (grbn->nsigs > 0) {
420252723Sdim		CTXFREE(grbn->sigs, sizeof(char *) * grbn->nsigs);
421252723Sdim		CTXFREE(grbn->siglen, sizeof(lwres_uint16_t) * grbn->nsigs);
422252723Sdim	}
423252723Sdim	if (grbn->base != NULL)
424207618Srdivacky		CTXFREE(grbn->base, grbn->baselen);
425252723Sdim	CTXFREE(grbn, sizeof(lwres_grbnresponse_t));
426252723Sdim}
427252723Sdim