1 /*
2  * Copyright (C) 2004, 2005, 2007, 2013  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2000, 2001  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or 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.10 2007/06/19 23:47:22 tbox Exp $ */
19 
20 /*! \file lwres_grbn.c
21 
22  */
23 
24 #include <config.h>
25 
26 #include <assert.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #include <lwres/lwbuffer.h>
31 #include <lwres/lwpacket.h>
32 #include <lwres/lwres.h>
33 #include <lwres/result.h>
34 
35 #include "context_p.h"
36 #include "assert_p.h"
37 
38 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
39 lwres_result_t
lwres_grbnrequest_render(lwres_context_t * ctx,lwres_grbnrequest_t * req,lwres_lwpacket_t * pkt,lwres_buffer_t * b)40 lwres_grbnrequest_render(lwres_context_t *ctx, lwres_grbnrequest_t *req,
41 			 lwres_lwpacket_t *pkt, lwres_buffer_t *b)
42 {
43 	unsigned char *buf;
44 	size_t buflen;
45 	int ret;
46 	size_t payload_length;
47 	lwres_uint16_t datalen;
48 
49 	REQUIRE(ctx != NULL);
50 	REQUIRE(req != NULL);
51 	REQUIRE(req->name != NULL);
52 	REQUIRE(pkt != NULL);
53 	REQUIRE(b != NULL);
54 
55 	datalen = strlen(req->name);
56 
57 	payload_length = 4 + 2 + 2 + 2 + req->namelen + 1;
58 
59 	buflen = LWRES_LWPACKET_LENGTH + payload_length;
60 	buf = CTXMALLOC(buflen);
61 	if (buf == NULL)
62 		return (LWRES_R_NOMEMORY);
63 
64 	lwres_buffer_init(b, buf, (unsigned int)buflen);
65 
66 	pkt->length = (lwres_uint32_t)buflen;
67 	pkt->version = LWRES_LWPACKETVERSION_0;
68 	pkt->pktflags &= ~LWRES_LWPACKETFLAG_RESPONSE;
69 	pkt->opcode = LWRES_OPCODE_GETRDATABYNAME;
70 	pkt->result = 0;
71 	pkt->authtype = 0;
72 	pkt->authlength = 0;
73 
74 	ret = lwres_lwpacket_renderheader(b, pkt);
75 	if (ret != LWRES_R_SUCCESS) {
76 		lwres_buffer_invalidate(b);
77 		CTXFREE(buf, buflen);
78 		return (ret);
79 	}
80 
81 	INSIST(SPACE_OK(b, payload_length));
82 
83 	/*
84 	 * Flags.
85 	 */
86 	lwres_buffer_putuint32(b, req->flags);
87 
88 	/*
89 	 * Class.
90 	 */
91 	lwres_buffer_putuint16(b, req->rdclass);
92 
93 	/*
94 	 * Type.
95 	 */
96 	lwres_buffer_putuint16(b, req->rdtype);
97 
98 	/*
99 	 * Put the length and the data.  We know this will fit because we
100 	 * just checked for it.
101 	 */
102 	lwres_buffer_putuint16(b, datalen);
103 	lwres_buffer_putmem(b, (unsigned char *)req->name, datalen);
104 	lwres_buffer_putuint8(b, 0); /* trailing NUL */
105 
106 	INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
107 
108 	return (LWRES_R_SUCCESS);
109 }
110 
111 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
112 lwres_result_t
lwres_grbnresponse_render(lwres_context_t * ctx,lwres_grbnresponse_t * req,lwres_lwpacket_t * pkt,lwres_buffer_t * b)113 lwres_grbnresponse_render(lwres_context_t *ctx, lwres_grbnresponse_t *req,
114 			  lwres_lwpacket_t *pkt, lwres_buffer_t *b)
115 {
116 	unsigned char *buf;
117 	size_t buflen;
118 	int ret;
119 	size_t payload_length;
120 	lwres_uint16_t datalen;
121 	int x;
122 
123 	REQUIRE(ctx != NULL);
124 	REQUIRE(req != NULL);
125 	REQUIRE(pkt != NULL);
126 	REQUIRE(b != NULL);
127 
128 	/* flags, class, type, ttl, nrdatas, nsigs */
129 	payload_length = 4 + 2 + 2 + 4 + 2 + 2;
130 	/* real name encoding */
131 	payload_length += 2 + req->realnamelen + 1;
132 	/* each rr */
133 	for (x = 0; x < req->nrdatas; x++)
134 		payload_length += 2 + req->rdatalen[x];
135 	for (x = 0; x < req->nsigs; x++)
136 		payload_length += 2 + req->siglen[x];
137 
138 	buflen = LWRES_LWPACKET_LENGTH + payload_length;
139 	buf = CTXMALLOC(buflen);
140 	if (buf == NULL)
141 		return (LWRES_R_NOMEMORY);
142 	lwres_buffer_init(b, buf, (unsigned int)buflen);
143 
144 	pkt->length = (lwres_uint32_t)buflen;
145 	pkt->version = LWRES_LWPACKETVERSION_0;
146 	pkt->pktflags |= LWRES_LWPACKETFLAG_RESPONSE;
147 	pkt->opcode = LWRES_OPCODE_GETRDATABYNAME;
148 	pkt->authtype = 0;
149 	pkt->authlength = 0;
150 
151 	ret = lwres_lwpacket_renderheader(b, pkt);
152 	if (ret != LWRES_R_SUCCESS) {
153 		lwres_buffer_invalidate(b);
154 		CTXFREE(buf, buflen);
155 		return (ret);
156 	}
157 
158 	/*
159 	 * Check space needed here.
160 	 */
161 	INSIST(SPACE_OK(b, payload_length));
162 
163 	/* Flags. */
164 	lwres_buffer_putuint32(b, req->flags);
165 
166 	/* encode class, type, ttl, and nrdatas */
167 	lwres_buffer_putuint16(b, req->rdclass);
168 	lwres_buffer_putuint16(b, req->rdtype);
169 	lwres_buffer_putuint32(b, req->ttl);
170 	lwres_buffer_putuint16(b, req->nrdatas);
171 	lwres_buffer_putuint16(b, req->nsigs);
172 
173 	/* encode the real name */
174 	datalen = req->realnamelen;
175 	lwres_buffer_putuint16(b, datalen);
176 	lwres_buffer_putmem(b, (unsigned char *)req->realname, datalen);
177 	lwres_buffer_putuint8(b, 0);
178 
179 	/* encode the rdatas */
180 	for (x = 0; x < req->nrdatas; x++) {
181 		datalen = req->rdatalen[x];
182 		lwres_buffer_putuint16(b, datalen);
183 		lwres_buffer_putmem(b, req->rdatas[x], datalen);
184 	}
185 
186 	/* encode the signatures */
187 	for (x = 0; x < req->nsigs; x++) {
188 		datalen = req->siglen[x];
189 		lwres_buffer_putuint16(b, datalen);
190 		lwres_buffer_putmem(b, req->sigs[x], datalen);
191 	}
192 
193 	INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
194 	INSIST(LWRES_BUFFER_USEDCOUNT(b) == pkt->length);
195 
196 	return (LWRES_R_SUCCESS);
197 }
198 
199 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
200 lwres_result_t
lwres_grbnrequest_parse(lwres_context_t * ctx,lwres_buffer_t * b,lwres_lwpacket_t * pkt,lwres_grbnrequest_t ** structp)201 lwres_grbnrequest_parse(lwres_context_t *ctx, lwres_buffer_t *b,
202 			lwres_lwpacket_t *pkt, lwres_grbnrequest_t **structp)
203 {
204 	int ret;
205 	char *name;
206 	lwres_grbnrequest_t *grbn;
207 	lwres_uint32_t flags;
208 	lwres_uint16_t rdclass, rdtype;
209 	lwres_uint16_t namelen;
210 
211 	REQUIRE(ctx != NULL);
212 	REQUIRE(pkt != NULL);
213 	REQUIRE(b != NULL);
214 	REQUIRE(structp != NULL && *structp == NULL);
215 
216 	if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) != 0)
217 		return (LWRES_R_FAILURE);
218 
219 	if (!SPACE_REMAINING(b, 4 + 2 + 2))
220 		return (LWRES_R_UNEXPECTEDEND);
221 
222 	/*
223 	 * Pull off the flags, class, and type.
224 	 */
225 	flags = lwres_buffer_getuint32(b);
226 	rdclass = lwres_buffer_getuint16(b);
227 	rdtype = lwres_buffer_getuint16(b);
228 
229 	/*
230 	 * Pull off the name itself
231 	 */
232 	ret = lwres_string_parse(b, &name, &namelen);
233 	if (ret != LWRES_R_SUCCESS)
234 		return (ret);
235 
236 	if (LWRES_BUFFER_REMAINING(b) != 0)
237 		return (LWRES_R_TRAILINGDATA);
238 
239 	grbn = CTXMALLOC(sizeof(lwres_grbnrequest_t));
240 	if (grbn == NULL)
241 		return (LWRES_R_NOMEMORY);
242 
243 	grbn->flags = flags;
244 	grbn->rdclass = rdclass;
245 	grbn->rdtype = rdtype;
246 	grbn->name = name;
247 	grbn->namelen = namelen;
248 
249 	*structp = grbn;
250 	return (LWRES_R_SUCCESS);
251 }
252 
253 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
254 lwres_result_t
lwres_grbnresponse_parse(lwres_context_t * ctx,lwres_buffer_t * b,lwres_lwpacket_t * pkt,lwres_grbnresponse_t ** structp)255 lwres_grbnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b,
256 			lwres_lwpacket_t *pkt, lwres_grbnresponse_t **structp)
257 {
258 	lwres_result_t ret;
259 	unsigned int x;
260 	lwres_uint32_t flags;
261 	lwres_uint16_t rdclass, rdtype;
262 	lwres_uint32_t ttl;
263 	lwres_uint16_t nrdatas, nsigs;
264 	lwres_grbnresponse_t *grbn;
265 
266 	REQUIRE(ctx != NULL);
267 	REQUIRE(pkt != NULL);
268 	REQUIRE(b != NULL);
269 	REQUIRE(structp != NULL && *structp == NULL);
270 
271 	grbn = NULL;
272 
273 	if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0)
274 		return (LWRES_R_FAILURE);
275 
276 	/*
277 	 * Pull off the flags, class, type, ttl, nrdatas, and nsigs
278 	 */
279 	if (!SPACE_REMAINING(b, 4 + 2 + 2 + 4 + 2 + 2))
280 		return (LWRES_R_UNEXPECTEDEND);
281 	flags = lwres_buffer_getuint32(b);
282 	rdclass = lwres_buffer_getuint16(b);
283 	rdtype = lwres_buffer_getuint16(b);
284 	ttl = lwres_buffer_getuint32(b);
285 	nrdatas = lwres_buffer_getuint16(b);
286 	nsigs = lwres_buffer_getuint16(b);
287 
288 	/*
289 	 * Pull off the name itself
290 	 */
291 
292 	grbn = CTXMALLOC(sizeof(lwres_grbnresponse_t));
293 	if (grbn == NULL)
294 		return (LWRES_R_NOMEMORY);
295 	grbn->rdatas = NULL;
296 	grbn->rdatalen = NULL;
297 	grbn->sigs = NULL;
298 	grbn->siglen = NULL;
299 	grbn->base = NULL;
300 
301 	grbn->flags = flags;
302 	grbn->rdclass = rdclass;
303 	grbn->rdtype = rdtype;
304 	grbn->ttl = ttl;
305 	grbn->nrdatas = nrdatas;
306 	grbn->nsigs = nsigs;
307 
308 	if (nrdatas > 0) {
309 		grbn->rdatas = CTXMALLOC(sizeof(char *) * nrdatas);
310 		if (grbn->rdatas == NULL) {
311 			ret = LWRES_R_NOMEMORY;
312 			goto out;
313 		}
314 
315 		grbn->rdatalen = CTXMALLOC(sizeof(lwres_uint16_t) * nrdatas);
316 		if (grbn->rdatalen == NULL) {
317 			ret = LWRES_R_NOMEMORY;
318 			goto out;
319 		}
320 	}
321 
322 	if (nsigs > 0) {
323 		grbn->sigs = CTXMALLOC(sizeof(char *) * nsigs);
324 		if (grbn->sigs == NULL) {
325 			ret = LWRES_R_NOMEMORY;
326 			goto out;
327 		}
328 
329 		grbn->siglen = CTXMALLOC(sizeof(lwres_uint16_t) * nsigs);
330 		if (grbn->siglen == NULL) {
331 			ret = LWRES_R_NOMEMORY;
332 			goto out;
333 		}
334 	}
335 
336 	/*
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. */
388 void
lwres_grbnrequest_free(lwres_context_t * ctx,lwres_grbnrequest_t ** structp)389 lwres_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. */
403 void
lwres_grbnresponse_free(lwres_context_t * ctx,lwres_grbnresponse_t ** structp)404 lwres_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