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