lwres_grbn.c revision 135446
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.12.3 2004/03/08 09:05:11 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
34lwres_result_t
35lwres_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
106lwres_result_t
107lwres_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
193lwres_result_t
194lwres_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
246lwres_result_t
247lwres_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
379void
380lwres_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
393void
394lwres_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}
417