diff options
Diffstat (limited to '')
-rw-r--r-- | lib/lwres/lwres_grbn.c | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/lib/lwres/lwres_grbn.c b/lib/lwres/lwres_grbn.c new file mode 100644 index 0000000..c736a41 --- /dev/null +++ b/lib/lwres/lwres_grbn.c @@ -0,0 +1,421 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* $Id: lwres_grbn.c,v 1.10 2007/06/19 23:47:22 tbox Exp $ */ + +/*! \file lwres_grbn.c + + */ + +#include <config.h> + +#include <assert.h> +#include <inttypes.h> +#include <stdlib.h> +#include <string.h> + +#include <lwres/lwbuffer.h> +#include <lwres/lwpacket.h> +#include <lwres/lwres.h> +#include <lwres/result.h> + +#include "context_p.h" +#include "assert_p.h" + +/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */ +lwres_result_t +lwres_grbnrequest_render(lwres_context_t *ctx, lwres_grbnrequest_t *req, + lwres_lwpacket_t *pkt, lwres_buffer_t *b) +{ + unsigned char *buf; + size_t buflen; + int ret; + size_t payload_length; + uint16_t datalen; + + REQUIRE(ctx != NULL); + REQUIRE(req != NULL); + REQUIRE(req->name != NULL); + REQUIRE(pkt != NULL); + REQUIRE(b != NULL); + + datalen = (uint16_t) strlen(req->name); + + payload_length = 4 + 2 + 2 + 2 + req->namelen + 1; + + buflen = LWRES_LWPACKET_LENGTH + payload_length; + buf = CTXMALLOC(buflen); + if (buf == NULL) + return (LWRES_R_NOMEMORY); + + lwres_buffer_init(b, buf, (unsigned int)buflen); + + pkt->length = (uint32_t)buflen; + pkt->version = LWRES_LWPACKETVERSION_0; + pkt->pktflags &= ~LWRES_LWPACKETFLAG_RESPONSE; + pkt->opcode = LWRES_OPCODE_GETRDATABYNAME; + pkt->result = 0; + pkt->authtype = 0; + pkt->authlength = 0; + + ret = lwres_lwpacket_renderheader(b, pkt); + if (ret != LWRES_R_SUCCESS) { + lwres_buffer_invalidate(b); + CTXFREE(buf, buflen); + return (ret); + } + + INSIST(SPACE_OK(b, payload_length)); + + /* + * Flags. + */ + lwres_buffer_putuint32(b, req->flags); + + /* + * Class. + */ + lwres_buffer_putuint16(b, req->rdclass); + + /* + * Type. + */ + lwres_buffer_putuint16(b, req->rdtype); + + /* + * Put the length and the data. We know this will fit because we + * just checked for it. + */ + lwres_buffer_putuint16(b, datalen); + lwres_buffer_putmem(b, (unsigned char *)req->name, datalen); + lwres_buffer_putuint8(b, 0); /* trailing NUL */ + + INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0); + + return (LWRES_R_SUCCESS); +} + +/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */ +lwres_result_t +lwres_grbnresponse_render(lwres_context_t *ctx, lwres_grbnresponse_t *req, + lwres_lwpacket_t *pkt, lwres_buffer_t *b) +{ + unsigned char *buf; + size_t buflen; + int ret; + size_t payload_length; + uint16_t datalen; + int x; + + REQUIRE(ctx != NULL); + REQUIRE(req != NULL); + REQUIRE(pkt != NULL); + REQUIRE(b != NULL); + + /* flags, class, type, ttl, nrdatas, nsigs */ + payload_length = 4 + 2 + 2 + 4 + 2 + 2; + /* real name encoding */ + payload_length += 2 + req->realnamelen + 1; + /* each rr */ + for (x = 0; x < req->nrdatas; x++) + payload_length += 2 + req->rdatalen[x]; + for (x = 0; x < req->nsigs; x++) + payload_length += 2 + req->siglen[x]; + + buflen = LWRES_LWPACKET_LENGTH + payload_length; + buf = CTXMALLOC(buflen); + if (buf == NULL) + return (LWRES_R_NOMEMORY); + lwres_buffer_init(b, buf, (unsigned int)buflen); + + pkt->length = (uint32_t)buflen; + pkt->version = LWRES_LWPACKETVERSION_0; + pkt->pktflags |= LWRES_LWPACKETFLAG_RESPONSE; + pkt->opcode = LWRES_OPCODE_GETRDATABYNAME; + pkt->authtype = 0; + pkt->authlength = 0; + + ret = lwres_lwpacket_renderheader(b, pkt); + if (ret != LWRES_R_SUCCESS) { + lwres_buffer_invalidate(b); + CTXFREE(buf, buflen); + return (ret); + } + + /* + * Check space needed here. + */ + INSIST(SPACE_OK(b, payload_length)); + + /* Flags. */ + lwres_buffer_putuint32(b, req->flags); + + /* encode class, type, ttl, and nrdatas */ + lwres_buffer_putuint16(b, req->rdclass); + lwres_buffer_putuint16(b, req->rdtype); + lwres_buffer_putuint32(b, req->ttl); + lwres_buffer_putuint16(b, req->nrdatas); + lwres_buffer_putuint16(b, req->nsigs); + + /* encode the real name */ + datalen = req->realnamelen; + lwres_buffer_putuint16(b, datalen); + lwres_buffer_putmem(b, (unsigned char *)req->realname, datalen); + lwres_buffer_putuint8(b, 0); + + /* encode the rdatas */ + for (x = 0; x < req->nrdatas; x++) { + datalen = req->rdatalen[x]; + lwres_buffer_putuint16(b, datalen); + lwres_buffer_putmem(b, req->rdatas[x], datalen); + } + + /* encode the signatures */ + for (x = 0; x < req->nsigs; x++) { + datalen = req->siglen[x]; + lwres_buffer_putuint16(b, datalen); + lwres_buffer_putmem(b, req->sigs[x], datalen); + } + + INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0); + INSIST(LWRES_BUFFER_USEDCOUNT(b) == pkt->length); + + return (LWRES_R_SUCCESS); +} + +/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */ +lwres_result_t +lwres_grbnrequest_parse(lwres_context_t *ctx, lwres_buffer_t *b, + lwres_lwpacket_t *pkt, lwres_grbnrequest_t **structp) +{ + int ret; + char *name; + lwres_grbnrequest_t *grbn; + uint32_t flags; + uint16_t rdclass, rdtype; + uint16_t namelen; + + REQUIRE(ctx != NULL); + REQUIRE(pkt != NULL); + REQUIRE(b != NULL); + REQUIRE(structp != NULL && *structp == NULL); + + if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) != 0) + return (LWRES_R_FAILURE); + + if (!SPACE_REMAINING(b, 4 + 2 + 2)) + return (LWRES_R_UNEXPECTEDEND); + + /* + * Pull off the flags, class, and type. + */ + flags = lwres_buffer_getuint32(b); + rdclass = lwres_buffer_getuint16(b); + rdtype = lwres_buffer_getuint16(b); + + /* + * Pull off the name itself + */ + ret = lwres_string_parse(b, &name, &namelen); + if (ret != LWRES_R_SUCCESS) + return (ret); + + if (LWRES_BUFFER_REMAINING(b) != 0) + return (LWRES_R_TRAILINGDATA); + + grbn = CTXMALLOC(sizeof(lwres_grbnrequest_t)); + if (grbn == NULL) + return (LWRES_R_NOMEMORY); + + grbn->flags = flags; + grbn->rdclass = rdclass; + grbn->rdtype = rdtype; + grbn->name = name; + grbn->namelen = namelen; + + *structp = grbn; + return (LWRES_R_SUCCESS); +} + +/*% Thread-safe equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */ +lwres_result_t +lwres_grbnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b, + lwres_lwpacket_t *pkt, lwres_grbnresponse_t **structp) +{ + lwres_result_t ret; + unsigned int x; + uint32_t flags; + uint16_t rdclass, rdtype; + uint32_t ttl; + uint16_t nrdatas, nsigs; + lwres_grbnresponse_t *grbn; + + REQUIRE(ctx != NULL); + REQUIRE(pkt != NULL); + REQUIRE(b != NULL); + REQUIRE(structp != NULL && *structp == NULL); + + grbn = NULL; + + if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0) + return (LWRES_R_FAILURE); + + /* + * Pull off the flags, class, type, ttl, nrdatas, and nsigs + */ + if (!SPACE_REMAINING(b, 4 + 2 + 2 + 4 + 2 + 2)) + return (LWRES_R_UNEXPECTEDEND); + flags = lwres_buffer_getuint32(b); + rdclass = lwres_buffer_getuint16(b); + rdtype = lwres_buffer_getuint16(b); + ttl = lwres_buffer_getuint32(b); + nrdatas = lwres_buffer_getuint16(b); + nsigs = lwres_buffer_getuint16(b); + + /* + * Pull off the name itself + */ + + grbn = CTXMALLOC(sizeof(lwres_grbnresponse_t)); + if (grbn == NULL) + return (LWRES_R_NOMEMORY); + grbn->rdatas = NULL; + grbn->rdatalen = NULL; + grbn->sigs = NULL; + grbn->siglen = NULL; + grbn->base = NULL; + + grbn->flags = flags; + grbn->rdclass = rdclass; + grbn->rdtype = rdtype; + grbn->ttl = ttl; + grbn->nrdatas = nrdatas; + grbn->nsigs = nsigs; + + if (nrdatas > 0) { + grbn->rdatas = CTXMALLOC(sizeof(char *) * nrdatas); + if (grbn->rdatas == NULL) { + ret = LWRES_R_NOMEMORY; + goto out; + } + + grbn->rdatalen = CTXMALLOC(sizeof(uint16_t) * nrdatas); + if (grbn->rdatalen == NULL) { + ret = LWRES_R_NOMEMORY; + goto out; + } + } + + if (nsigs > 0) { + grbn->sigs = CTXMALLOC(sizeof(char *) * nsigs); + if (grbn->sigs == NULL) { + ret = LWRES_R_NOMEMORY; + goto out; + } + + grbn->siglen = CTXMALLOC(sizeof(uint16_t) * nsigs); + if (grbn->siglen == NULL) { + ret = LWRES_R_NOMEMORY; + goto out; + } + } + + /* + * Now, pull off the real name. + */ + ret = lwres_string_parse(b, &grbn->realname, &grbn->realnamelen); + if (ret != LWRES_R_SUCCESS) + goto out; + + /* + * Parse off the rdatas. + */ + for (x = 0; x < grbn->nrdatas; x++) { + ret = lwres_data_parse(b, &grbn->rdatas[x], + &grbn->rdatalen[x]); + if (ret != LWRES_R_SUCCESS) + goto out; + } + + /* + * Parse off the signatures. + */ + for (x = 0; x < grbn->nsigs; x++) { + ret = lwres_data_parse(b, &grbn->sigs[x], &grbn->siglen[x]); + if (ret != LWRES_R_SUCCESS) + goto out; + } + + if (LWRES_BUFFER_REMAINING(b) != 0) { + ret = LWRES_R_TRAILINGDATA; + goto out; + } + + *structp = grbn; + return (LWRES_R_SUCCESS); + + out: + if (grbn != NULL) { + if (grbn->rdatas != NULL) + CTXFREE(grbn->rdatas, sizeof(char *) * nrdatas); + if (grbn->rdatalen != NULL) + CTXFREE(grbn->rdatalen, + sizeof(uint16_t) * nrdatas); + if (grbn->sigs != NULL) + CTXFREE(grbn->sigs, sizeof(char *) * nsigs); + if (grbn->siglen != NULL) + CTXFREE(grbn->siglen, sizeof(uint16_t) * nsigs); + CTXFREE(grbn, sizeof(lwres_grbnresponse_t)); + } + + return (ret); +} + +/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */ +void +lwres_grbnrequest_free(lwres_context_t *ctx, lwres_grbnrequest_t **structp) +{ + lwres_grbnrequest_t *grbn; + + REQUIRE(ctx != NULL); + REQUIRE(structp != NULL && *structp != NULL); + + grbn = *structp; + *structp = NULL; + + CTXFREE(grbn, sizeof(lwres_grbnrequest_t)); +} + +/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */ +void +lwres_grbnresponse_free(lwres_context_t *ctx, lwres_grbnresponse_t **structp) +{ + lwres_grbnresponse_t *grbn; + + REQUIRE(ctx != NULL); + REQUIRE(structp != NULL && *structp != NULL); + + grbn = *structp; + *structp = NULL; + + if (grbn->nrdatas > 0) { + CTXFREE(grbn->rdatas, sizeof(char *) * grbn->nrdatas); + CTXFREE(grbn->rdatalen, + sizeof(uint16_t) * grbn->nrdatas); + } + if (grbn->nsigs > 0) { + CTXFREE(grbn->sigs, sizeof(char *) * grbn->nsigs); + CTXFREE(grbn->siglen, sizeof(uint16_t) * grbn->nsigs); + } + if (grbn->base != NULL) + CTXFREE(grbn->base, grbn->baselen); + CTXFREE(grbn, sizeof(lwres_grbnresponse_t)); +} |