/* * 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 #include #include #include #include #include #include #include #include #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)); }