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