xref: /minix/external/bsd/bind/dist/lib/lwres/lwres_grbn.c (revision 00b67f09)
1 /*	$NetBSD: lwres_grbn.c,v 1.5 2014/12/10 04:38:02 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2004, 2005, 2007, 2013  Internet Systems Consortium, Inc. ("ISC")
5  * Copyright (C) 2000, 2001  Internet Software Consortium.
6  *
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.
10  *
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.
18  */
19 
20 /* Id: lwres_grbn.c,v 1.10 2007/06/19 23:47:22 tbox Exp  */
21 
22 /*! \file lwres_grbn.c
23 
24  */
25 
26 #include <config.h>
27 
28 #include <assert.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #include <lwres/lwbuffer.h>
33 #include <lwres/lwpacket.h>
34 #include <lwres/lwres.h>
35 #include <lwres/result.h>
36 
37 #include "context_p.h"
38 #include "assert_p.h"
39 
40 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
41 lwres_result_t
lwres_grbnrequest_render(lwres_context_t * ctx,lwres_grbnrequest_t * req,lwres_lwpacket_t * pkt,lwres_buffer_t * b)42 lwres_grbnrequest_render(lwres_context_t *ctx, lwres_grbnrequest_t *req,
43 			 lwres_lwpacket_t *pkt, lwres_buffer_t *b)
44 {
45 	unsigned char *buf;
46 	size_t buflen;
47 	int ret;
48 	size_t payload_length;
49 	lwres_uint16_t datalen;
50 
51 	REQUIRE(ctx != NULL);
52 	REQUIRE(req != NULL);
53 	REQUIRE(req->name != NULL);
54 	REQUIRE(pkt != NULL);
55 	REQUIRE(b != NULL);
56 
57 	datalen = strlen(req->name);
58 
59 	payload_length = 4 + 2 + 2 + 2 + req->namelen + 1;
60 
61 	buflen = LWRES_LWPACKET_LENGTH + payload_length;
62 	buf = CTXMALLOC(buflen);
63 	if (buf == NULL)
64 		return (LWRES_R_NOMEMORY);
65 
66 	lwres_buffer_init(b, buf, (unsigned int)buflen);
67 
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;
72 	pkt->result = 0;
73 	pkt->authtype = 0;
74 	pkt->authlength = 0;
75 
76 	ret = lwres_lwpacket_renderheader(b, pkt);
77 	if (ret != LWRES_R_SUCCESS) {
78 		lwres_buffer_invalidate(b);
79 		CTXFREE(buf, buflen);
80 		return (ret);
81 	}
82 
83 	INSIST(SPACE_OK(b, payload_length));
84 
85 	/*
86 	 * Flags.
87 	 */
88 	lwres_buffer_putuint32(b, req->flags);
89 
90 	/*
91 	 * Class.
92 	 */
93 	lwres_buffer_putuint16(b, req->rdclass);
94 
95 	/*
96 	 * Type.
97 	 */
98 	lwres_buffer_putuint16(b, req->rdtype);
99 
100 	/*
101 	 * Put the length and the data.  We know this will fit because we
102 	 * just checked for it.
103 	 */
104 	lwres_buffer_putuint16(b, datalen);
105 	lwres_buffer_putmem(b, (unsigned char *)req->name, datalen);
106 	lwres_buffer_putuint8(b, 0); /* trailing NUL */
107 
108 	INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
109 
110 	return (LWRES_R_SUCCESS);
111 }
112 
113 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
114 lwres_result_t
lwres_grbnresponse_render(lwres_context_t * ctx,lwres_grbnresponse_t * req,lwres_lwpacket_t * pkt,lwres_buffer_t * b)115 lwres_grbnresponse_render(lwres_context_t *ctx, lwres_grbnresponse_t *req,
116 			  lwres_lwpacket_t *pkt, lwres_buffer_t *b)
117 {
118 	unsigned char *buf;
119 	size_t buflen;
120 	int ret;
121 	size_t payload_length;
122 	lwres_uint16_t datalen;
123 	int x;
124 
125 	REQUIRE(ctx != NULL);
126 	REQUIRE(req != NULL);
127 	REQUIRE(pkt != NULL);
128 	REQUIRE(b != NULL);
129 
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;
134 	/* each rr */
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];
139 
140 	buflen = LWRES_LWPACKET_LENGTH + payload_length;
141 	buf = CTXMALLOC(buflen);
142 	if (buf == NULL)
143 		return (LWRES_R_NOMEMORY);
144 	lwres_buffer_init(b, buf, (unsigned int)buflen);
145 
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;
150 	pkt->authtype = 0;
151 	pkt->authlength = 0;
152 
153 	ret = lwres_lwpacket_renderheader(b, pkt);
154 	if (ret != LWRES_R_SUCCESS) {
155 		lwres_buffer_invalidate(b);
156 		CTXFREE(buf, buflen);
157 		return (ret);
158 	}
159 
160 	/*
161 	 * Check space needed here.
162 	 */
163 	INSIST(SPACE_OK(b, payload_length));
164 
165 	/* Flags. */
166 	lwres_buffer_putuint32(b, req->flags);
167 
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);
174 
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);
180 
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);
186 	}
187 
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);
193 	}
194 
195 	INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
196 	INSIST(LWRES_BUFFER_USEDCOUNT(b) == pkt->length);
197 
198 	return (LWRES_R_SUCCESS);
199 }
200 
201 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
202 lwres_result_t
lwres_grbnrequest_parse(lwres_context_t * ctx,lwres_buffer_t * b,lwres_lwpacket_t * pkt,lwres_grbnrequest_t ** structp)203 lwres_grbnrequest_parse(lwres_context_t *ctx, lwres_buffer_t *b,
204 			lwres_lwpacket_t *pkt, lwres_grbnrequest_t **structp)
205 {
206 	int ret;
207 	char *name;
208 	lwres_grbnrequest_t *grbn;
209 	lwres_uint32_t flags;
210 	lwres_uint16_t rdclass, rdtype;
211 	lwres_uint16_t namelen;
212 
213 	REQUIRE(ctx != NULL);
214 	REQUIRE(pkt != NULL);
215 	REQUIRE(b != NULL);
216 	REQUIRE(structp != NULL && *structp == NULL);
217 
218 	if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) != 0)
219 		return (LWRES_R_FAILURE);
220 
221 	if (!SPACE_REMAINING(b, 4 + 2 + 2))
222 		return (LWRES_R_UNEXPECTEDEND);
223 
224 	/*
225 	 * Pull off the flags, class, and type.
226 	 */
227 	flags = lwres_buffer_getuint32(b);
228 	rdclass = lwres_buffer_getuint16(b);
229 	rdtype = lwres_buffer_getuint16(b);
230 
231 	/*
232 	 * Pull off the name itself
233 	 */
234 	ret = lwres_string_parse(b, &name, &namelen);
235 	if (ret != LWRES_R_SUCCESS)
236 		return (ret);
237 
238 	if (LWRES_BUFFER_REMAINING(b) != 0)
239 		return (LWRES_R_TRAILINGDATA);
240 
241 	grbn = CTXMALLOC(sizeof(lwres_grbnrequest_t));
242 	if (grbn == NULL)
243 		return (LWRES_R_NOMEMORY);
244 
245 	grbn->flags = flags;
246 	grbn->rdclass = rdclass;
247 	grbn->rdtype = rdtype;
248 	grbn->name = name;
249 	grbn->namelen = namelen;
250 
251 	*structp = grbn;
252 	return (LWRES_R_SUCCESS);
253 }
254 
255 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
256 lwres_result_t
lwres_grbnresponse_parse(lwres_context_t * ctx,lwres_buffer_t * b,lwres_lwpacket_t * pkt,lwres_grbnresponse_t ** structp)257 lwres_grbnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b,
258 			lwres_lwpacket_t *pkt, lwres_grbnresponse_t **structp)
259 {
260 	lwres_result_t ret;
261 	unsigned int x;
262 	lwres_uint32_t flags;
263 	lwres_uint16_t rdclass, rdtype;
264 	lwres_uint32_t ttl;
265 	lwres_uint16_t nrdatas, nsigs;
266 	lwres_grbnresponse_t *grbn;
267 
268 	REQUIRE(ctx != NULL);
269 	REQUIRE(pkt != NULL);
270 	REQUIRE(b != NULL);
271 	REQUIRE(structp != NULL && *structp == NULL);
272 
273 	grbn = NULL;
274 
275 	if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0)
276 		return (LWRES_R_FAILURE);
277 
278 	/*
279 	 * Pull off the flags, class, type, ttl, nrdatas, and nsigs
280 	 */
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);
289 
290 	/*
291 	 * Pull off the name itself
292 	 */
293 
294 	grbn = CTXMALLOC(sizeof(lwres_grbnresponse_t));
295 	if (grbn == NULL)
296 		return (LWRES_R_NOMEMORY);
297 	grbn->rdatas = NULL;
298 	grbn->rdatalen = NULL;
299 	grbn->sigs = NULL;
300 	grbn->siglen = NULL;
301 	grbn->base = NULL;
302 
303 	grbn->flags = flags;
304 	grbn->rdclass = rdclass;
305 	grbn->rdtype = rdtype;
306 	grbn->ttl = ttl;
307 	grbn->nrdatas = nrdatas;
308 	grbn->nsigs = nsigs;
309 
310 	if (nrdatas > 0) {
311 		grbn->rdatas = CTXMALLOC(sizeof(char *) * nrdatas);
312 		if (grbn->rdatas == NULL) {
313 			ret = LWRES_R_NOMEMORY;
314 			goto out;
315 		}
316 
317 		grbn->rdatalen = CTXMALLOC(sizeof(lwres_uint16_t) * nrdatas);
318 		if (grbn->rdatalen == NULL) {
319 			ret = LWRES_R_NOMEMORY;
320 			goto out;
321 		}
322 	}
323 
324 	if (nsigs > 0) {
325 		grbn->sigs = CTXMALLOC(sizeof(char *) * nsigs);
326 		if (grbn->sigs == NULL) {
327 			ret = LWRES_R_NOMEMORY;
328 			goto out;
329 		}
330 
331 		grbn->siglen = CTXMALLOC(sizeof(lwres_uint16_t) * nsigs);
332 		if (grbn->siglen == NULL) {
333 			ret = LWRES_R_NOMEMORY;
334 			goto out;
335 		}
336 	}
337 
338 	/*
339 	 * Now, pull off the real name.
340 	 */
341 	ret = lwres_string_parse(b, &grbn->realname, &grbn->realnamelen);
342 	if (ret != LWRES_R_SUCCESS)
343 		goto out;
344 
345 	/*
346 	 * Parse off the rdatas.
347 	 */
348 	for (x = 0; x < grbn->nrdatas; x++) {
349 		ret = lwres_data_parse(b, &grbn->rdatas[x],
350 					 &grbn->rdatalen[x]);
351 		if (ret != LWRES_R_SUCCESS)
352 			goto out;
353 	}
354 
355 	/*
356 	 * Parse off the signatures.
357 	 */
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)
361 			goto out;
362 	}
363 
364 	if (LWRES_BUFFER_REMAINING(b) != 0) {
365 		ret = LWRES_R_TRAILINGDATA;
366 		goto out;
367 	}
368 
369 	*structp = grbn;
370 	return (LWRES_R_SUCCESS);
371 
372  out:
373 	if (grbn != NULL) {
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));
384 	}
385 
386 	return (ret);
387 }
388 
389 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
390 void
lwres_grbnrequest_free(lwres_context_t * ctx,lwres_grbnrequest_t ** structp)391 lwres_grbnrequest_free(lwres_context_t *ctx, lwres_grbnrequest_t **structp)
392 {
393 	lwres_grbnrequest_t *grbn;
394 
395 	REQUIRE(ctx != NULL);
396 	REQUIRE(structp != NULL && *structp != NULL);
397 
398 	grbn = *structp;
399 	*structp = NULL;
400 
401 	CTXFREE(grbn, sizeof(lwres_grbnrequest_t));
402 }
403 
404 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
405 void
lwres_grbnresponse_free(lwres_context_t * ctx,lwres_grbnresponse_t ** structp)406 lwres_grbnresponse_free(lwres_context_t *ctx, lwres_grbnresponse_t **structp)
407 {
408 	lwres_grbnresponse_t *grbn;
409 
410 	REQUIRE(ctx != NULL);
411 	REQUIRE(structp != NULL && *structp != NULL);
412 
413 	grbn = *structp;
414 	*structp = NULL;
415 
416 	if (grbn->nrdatas > 0) {
417 		CTXFREE(grbn->rdatas, sizeof(char *) * grbn->nrdatas);
418 		CTXFREE(grbn->rdatalen,
419 			sizeof(lwres_uint16_t) * grbn->nrdatas);
420 	}
421 	if (grbn->nsigs > 0) {
422 		CTXFREE(grbn->sigs, sizeof(char *) * grbn->nsigs);
423 		CTXFREE(grbn->siglen, sizeof(lwres_uint16_t) * grbn->nsigs);
424 	}
425 	if (grbn->base != NULL)
426 		CTXFREE(grbn->base, grbn->baselen);
427 	CTXFREE(grbn, sizeof(lwres_grbnresponse_t));
428 }
429