1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
7 *
8 * See the COPYRIGHT file distributed with this work for additional
9 * information regarding copyright ownership.
10 */
11
12 /*! \file lwres_grbn.c
13
14 */
15
16 #include <config.h>
17
18 #include <assert.h>
19 #include <inttypes.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include <lwres/lwbuffer.h>
24 #include <lwres/lwpacket.h>
25 #include <lwres/lwres.h>
26 #include <lwres/result.h>
27
28 #include "context_p.h"
29 #include "assert_p.h"
30
31 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
32 lwres_result_t
lwres_grbnrequest_render(lwres_context_t * ctx,lwres_grbnrequest_t * req,lwres_lwpacket_t * pkt,lwres_buffer_t * b)33 lwres_grbnrequest_render(lwres_context_t *ctx, lwres_grbnrequest_t *req,
34 lwres_lwpacket_t *pkt, lwres_buffer_t *b)
35 {
36 unsigned char *buf;
37 size_t buflen;
38 int ret;
39 size_t payload_length;
40 uint16_t datalen;
41
42 REQUIRE(ctx != NULL);
43 REQUIRE(req != NULL);
44 REQUIRE(req->name != NULL);
45 REQUIRE(pkt != NULL);
46 REQUIRE(b != NULL);
47
48 datalen = (uint16_t) strlen(req->name);
49
50 payload_length = 4 + 2 + 2 + 2 + req->namelen + 1;
51
52 buflen = LWRES_LWPACKET_LENGTH + payload_length;
53 buf = CTXMALLOC(buflen);
54 if (buf == NULL)
55 return (LWRES_R_NOMEMORY);
56
57 lwres_buffer_init(b, buf, (unsigned int)buflen);
58
59 pkt->length = (uint32_t)buflen;
60 pkt->version = LWRES_LWPACKETVERSION_0;
61 pkt->pktflags &= ~LWRES_LWPACKETFLAG_RESPONSE;
62 pkt->opcode = LWRES_OPCODE_GETRDATABYNAME;
63 pkt->result = 0;
64 pkt->authtype = 0;
65 pkt->authlength = 0;
66
67 ret = lwres_lwpacket_renderheader(b, pkt);
68 if (ret != LWRES_R_SUCCESS) {
69 lwres_buffer_invalidate(b);
70 CTXFREE(buf, buflen);
71 return (ret);
72 }
73
74 INSIST(SPACE_OK(b, payload_length));
75
76 /*
77 * Flags.
78 */
79 lwres_buffer_putuint32(b, req->flags);
80
81 /*
82 * Class.
83 */
84 lwres_buffer_putuint16(b, req->rdclass);
85
86 /*
87 * Type.
88 */
89 lwres_buffer_putuint16(b, req->rdtype);
90
91 /*
92 * Put the length and the data. We know this will fit because we
93 * just checked for it.
94 */
95 lwres_buffer_putuint16(b, datalen);
96 lwres_buffer_putmem(b, (unsigned char *)req->name, datalen);
97 lwres_buffer_putuint8(b, 0); /* trailing NUL */
98
99 INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
100
101 return (LWRES_R_SUCCESS);
102 }
103
104 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
105 lwres_result_t
lwres_grbnresponse_render(lwres_context_t * ctx,lwres_grbnresponse_t * req,lwres_lwpacket_t * pkt,lwres_buffer_t * b)106 lwres_grbnresponse_render(lwres_context_t *ctx, lwres_grbnresponse_t *req,
107 lwres_lwpacket_t *pkt, lwres_buffer_t *b)
108 {
109 unsigned char *buf;
110 size_t buflen;
111 int ret;
112 size_t payload_length;
113 uint16_t datalen;
114 int x;
115
116 REQUIRE(ctx != NULL);
117 REQUIRE(req != NULL);
118 REQUIRE(pkt != NULL);
119 REQUIRE(b != NULL);
120
121 /* flags, class, type, ttl, nrdatas, nsigs */
122 payload_length = 4 + 2 + 2 + 4 + 2 + 2;
123 /* real name encoding */
124 payload_length += 2 + req->realnamelen + 1;
125 /* each rr */
126 for (x = 0; x < req->nrdatas; x++)
127 payload_length += 2 + req->rdatalen[x];
128 for (x = 0; x < req->nsigs; x++)
129 payload_length += 2 + req->siglen[x];
130
131 buflen = LWRES_LWPACKET_LENGTH + payload_length;
132 buf = CTXMALLOC(buflen);
133 if (buf == NULL)
134 return (LWRES_R_NOMEMORY);
135 lwres_buffer_init(b, buf, (unsigned int)buflen);
136
137 pkt->length = (uint32_t)buflen;
138 pkt->version = LWRES_LWPACKETVERSION_0;
139 pkt->pktflags |= LWRES_LWPACKETFLAG_RESPONSE;
140 pkt->opcode = LWRES_OPCODE_GETRDATABYNAME;
141 pkt->authtype = 0;
142 pkt->authlength = 0;
143
144 ret = lwres_lwpacket_renderheader(b, pkt);
145 if (ret != LWRES_R_SUCCESS) {
146 lwres_buffer_invalidate(b);
147 CTXFREE(buf, buflen);
148 return (ret);
149 }
150
151 /*
152 * Check space needed here.
153 */
154 INSIST(SPACE_OK(b, payload_length));
155
156 /* Flags. */
157 lwres_buffer_putuint32(b, req->flags);
158
159 /* encode class, type, ttl, and nrdatas */
160 lwres_buffer_putuint16(b, req->rdclass);
161 lwres_buffer_putuint16(b, req->rdtype);
162 lwres_buffer_putuint32(b, req->ttl);
163 lwres_buffer_putuint16(b, req->nrdatas);
164 lwres_buffer_putuint16(b, req->nsigs);
165
166 /* encode the real name */
167 datalen = req->realnamelen;
168 lwres_buffer_putuint16(b, datalen);
169 lwres_buffer_putmem(b, (unsigned char *)req->realname, datalen);
170 lwres_buffer_putuint8(b, 0);
171
172 /* encode the rdatas */
173 for (x = 0; x < req->nrdatas; x++) {
174 datalen = req->rdatalen[x];
175 lwres_buffer_putuint16(b, datalen);
176 lwres_buffer_putmem(b, req->rdatas[x], datalen);
177 }
178
179 /* encode the signatures */
180 for (x = 0; x < req->nsigs; x++) {
181 datalen = req->siglen[x];
182 lwres_buffer_putuint16(b, datalen);
183 lwres_buffer_putmem(b, req->sigs[x], datalen);
184 }
185
186 INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
187 INSIST(LWRES_BUFFER_USEDCOUNT(b) == pkt->length);
188
189 return (LWRES_R_SUCCESS);
190 }
191
192 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
193 lwres_result_t
lwres_grbnrequest_parse(lwres_context_t * ctx,lwres_buffer_t * b,lwres_lwpacket_t * pkt,lwres_grbnrequest_t ** structp)194 lwres_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 uint32_t flags;
201 uint16_t rdclass, rdtype;
202 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
246 /*% Thread-safe equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
247 lwres_result_t
lwres_grbnresponse_parse(lwres_context_t * ctx,lwres_buffer_t * b,lwres_lwpacket_t * pkt,lwres_grbnresponse_t ** structp)248 lwres_grbnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b,
249 lwres_lwpacket_t *pkt, lwres_grbnresponse_t **structp)
250 {
251 lwres_result_t ret;
252 unsigned int x;
253 uint32_t flags;
254 uint16_t rdclass, rdtype;
255 uint32_t ttl;
256 uint16_t nrdatas, nsigs;
257 lwres_grbnresponse_t *grbn;
258
259 REQUIRE(ctx != NULL);
260 REQUIRE(pkt != NULL);
261 REQUIRE(b != NULL);
262 REQUIRE(structp != NULL && *structp == NULL);
263
264 grbn = NULL;
265
266 if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0)
267 return (LWRES_R_FAILURE);
268
269 /*
270 * Pull off the flags, class, type, ttl, nrdatas, and nsigs
271 */
272 if (!SPACE_REMAINING(b, 4 + 2 + 2 + 4 + 2 + 2))
273 return (LWRES_R_UNEXPECTEDEND);
274 flags = lwres_buffer_getuint32(b);
275 rdclass = lwres_buffer_getuint16(b);
276 rdtype = lwres_buffer_getuint16(b);
277 ttl = lwres_buffer_getuint32(b);
278 nrdatas = lwres_buffer_getuint16(b);
279 nsigs = lwres_buffer_getuint16(b);
280
281 /*
282 * Pull off the name itself
283 */
284
285 grbn = CTXMALLOC(sizeof(lwres_grbnresponse_t));
286 if (grbn == NULL)
287 return (LWRES_R_NOMEMORY);
288 grbn->rdatas = NULL;
289 grbn->rdatalen = NULL;
290 grbn->sigs = NULL;
291 grbn->siglen = NULL;
292 grbn->base = NULL;
293
294 grbn->flags = flags;
295 grbn->rdclass = rdclass;
296 grbn->rdtype = rdtype;
297 grbn->ttl = ttl;
298 grbn->nrdatas = nrdatas;
299 grbn->nsigs = nsigs;
300
301 if (nrdatas > 0) {
302 grbn->rdatas = CTXMALLOC(sizeof(char *) * nrdatas);
303 if (grbn->rdatas == NULL) {
304 ret = LWRES_R_NOMEMORY;
305 goto out;
306 }
307
308 grbn->rdatalen = CTXMALLOC(sizeof(uint16_t) * nrdatas);
309 if (grbn->rdatalen == NULL) {
310 ret = LWRES_R_NOMEMORY;
311 goto out;
312 }
313 }
314
315 if (nsigs > 0) {
316 grbn->sigs = CTXMALLOC(sizeof(char *) * nsigs);
317 if (grbn->sigs == NULL) {
318 ret = LWRES_R_NOMEMORY;
319 goto out;
320 }
321
322 grbn->siglen = CTXMALLOC(sizeof(uint16_t) * nsigs);
323 if (grbn->siglen == NULL) {
324 ret = LWRES_R_NOMEMORY;
325 goto out;
326 }
327 }
328
329 /*
330 * Now, pull off the real name.
331 */
332 ret = lwres_string_parse(b, &grbn->realname, &grbn->realnamelen);
333 if (ret != LWRES_R_SUCCESS)
334 goto out;
335
336 /*
337 * Parse off the rdatas.
338 */
339 for (x = 0; x < grbn->nrdatas; x++) {
340 ret = lwres_data_parse(b, &grbn->rdatas[x],
341 &grbn->rdatalen[x]);
342 if (ret != LWRES_R_SUCCESS)
343 goto out;
344 }
345
346 /*
347 * Parse off the signatures.
348 */
349 for (x = 0; x < grbn->nsigs; x++) {
350 ret = lwres_data_parse(b, &grbn->sigs[x], &grbn->siglen[x]);
351 if (ret != LWRES_R_SUCCESS)
352 goto out;
353 }
354
355 if (LWRES_BUFFER_REMAINING(b) != 0) {
356 ret = LWRES_R_TRAILINGDATA;
357 goto out;
358 }
359
360 *structp = grbn;
361 return (LWRES_R_SUCCESS);
362
363 out:
364 if (grbn != NULL) {
365 if (grbn->rdatas != NULL)
366 CTXFREE(grbn->rdatas, sizeof(char *) * nrdatas);
367 if (grbn->rdatalen != NULL)
368 CTXFREE(grbn->rdatalen,
369 sizeof(uint16_t) * nrdatas);
370 if (grbn->sigs != NULL)
371 CTXFREE(grbn->sigs, sizeof(char *) * nsigs);
372 if (grbn->siglen != NULL)
373 CTXFREE(grbn->siglen, sizeof(uint16_t) * nsigs);
374 CTXFREE(grbn, sizeof(lwres_grbnresponse_t));
375 }
376
377 return (ret);
378 }
379
380 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
381 void
lwres_grbnrequest_free(lwres_context_t * ctx,lwres_grbnrequest_t ** structp)382 lwres_grbnrequest_free(lwres_context_t *ctx, lwres_grbnrequest_t **structp)
383 {
384 lwres_grbnrequest_t *grbn;
385
386 REQUIRE(ctx != NULL);
387 REQUIRE(structp != NULL && *structp != NULL);
388
389 grbn = *structp;
390 *structp = NULL;
391
392 CTXFREE(grbn, sizeof(lwres_grbnrequest_t));
393 }
394
395 /*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
396 void
lwres_grbnresponse_free(lwres_context_t * ctx,lwres_grbnresponse_t ** structp)397 lwres_grbnresponse_free(lwres_context_t *ctx, lwres_grbnresponse_t **structp)
398 {
399 lwres_grbnresponse_t *grbn;
400
401 REQUIRE(ctx != NULL);
402 REQUIRE(structp != NULL && *structp != NULL);
403
404 grbn = *structp;
405 *structp = NULL;
406
407 if (grbn->nrdatas > 0) {
408 CTXFREE(grbn->rdatas, sizeof(char *) * grbn->nrdatas);
409 CTXFREE(grbn->rdatalen,
410 sizeof(uint16_t) * grbn->nrdatas);
411 }
412 if (grbn->nsigs > 0) {
413 CTXFREE(grbn->sigs, sizeof(char *) * grbn->nsigs);
414 CTXFREE(grbn->siglen, sizeof(uint16_t) * grbn->nsigs);
415 }
416 if (grbn->base != NULL)
417 CTXFREE(grbn->base, grbn->baselen);
418 CTXFREE(grbn, sizeof(lwres_grbnresponse_t));
419 }
420