diff --git a/bin/tests/lwres_test.c b/bin/tests/lwres_test.c index db64193df4..fbaa5db78b 100644 --- a/bin/tests/lwres_test.c +++ b/bin/tests/lwres_test.c @@ -76,10 +76,14 @@ main(int argc, char *argv[]) lwres_noopresponse_t noopresponse, *noopresponse2; lwres_buffer_t b; + (void)argc; + (void)argv; + ctx = NULL; ret = lwres_context_create(&ctx, NULL, NULL, NULL); CHECK(ret, "lwres_context_create"); + pkt.flags = 0; pkt.serial = 0x11223344; pkt.recvlength = 0x55667788; pkt.result = 0; @@ -114,6 +118,41 @@ main(int argc, char *argv[]) b.base = NULL; b.length = 0; + pkt.flags = 0; + pkt.serial = 0x11223344; + pkt.recvlength = 0x55667788; + pkt.result = 0xdeadbeef; + + noopresponse.datalength = strlen(TESTSTRING); + noopresponse.data = TESTSTRING; + ret = lwres_noopresponse_render(ctx, &noopresponse, &pkt, &b); + CHECK(ret, "lwres_noopresponse_render"); + + hexdump("rendered noop response", b.base, b.used); + + /* + * Now, parse it into a new structure. + */ + lwres_buffer_first(&b); + ret = lwres_lwpacket_parseheader(&b, &pkt2); + CHECK(ret, "lwres_lwpacket_parseheader"); + + hexdump("parsed pkt2", &pkt2, sizeof(pkt2)); + + noopresponse2 = NULL; + ret = lwres_noopresponse_parse(ctx, &b, &pkt2, &noopresponse2); + CHECK(ret, "lwres_noopresponse_parse"); + + assert(noopresponse.datalength == noopresponse2->datalength); + assert(memcmp(noopresponse.data, noopresponse2->data, + noopresponse.datalength) == 0); + + lwres_noopresponse_free(ctx, &noopresponse2); + + lwres_context_freemem(ctx, b.base, b.length); + b.base = NULL; + b.length = 0; + lwres_context_destroy(&ctx); return (0); diff --git a/lib/lwres/include/lwres/lwpacket.h b/lib/lwres/include/lwres/lwpacket.h index 031ab84c95..3060aa9808 100644 --- a/lib/lwres/include/lwres/lwpacket.h +++ b/lib/lwres/include/lwres/lwpacket.h @@ -39,6 +39,8 @@ struct lwres_lwpacket { isc_uint16_t authlength; }; +#define LWRES_LWPACKET_LENGTH (4 * 5 + 2 * 4) + #define LWRES_LWPACKETFLAG_RESPONSE 0x0001U /* if set, pkt is a response */ #define LWRES_LWPACKETVERSION_0 0 diff --git a/lib/lwres/include/lwres/lwres.h b/lib/lwres/include/lwres/lwres.h index 899a2cf9b7..f9a8c95420 100644 --- a/lib/lwres/include/lwres/lwres.h +++ b/lib/lwres/include/lwres/lwres.h @@ -175,17 +175,19 @@ ISC_LANG_BEGINDECLS int lwres_gabnrequest_render(lwres_context_t *ctx, lwres_gabnrequest_t *req, - isc_uint32_t maxrecv, lwres_buffer_t *b); + lwres_lwpacket_t *pkt, lwres_buffer_t *b); int lwres_gabnresponse_render(lwres_context_t *ctx, lwres_gabnresponse_t *req, - isc_uint32_t maxrecv, lwres_buffer_t *b); + lwres_lwpacket_t *pkt, lwres_buffer_t *b); int -lwres_gabnrequest_parse(lwres_context_t *ctx, lwres_gabnrequest_t **structp); +lwres_gabnrequest_parse(lwres_context_t *ctx, lwres_lwpacket_t *pkt, + lwres_buffer_t *b, lwres_gabnrequest_t **structp); int -lwres_gabnresponse_parse(lwres_context_t *ctx, lwres_gabnresponse_t **structp); +lwres_gabnresponse_parse(lwres_context_t *ctx, lwres_lwpacket_t *pkt, + lwres_buffer_t *b, lwres_gabnresponse_t **structp); void lwres_gabnrequest_free(lwres_context_t *ctx, lwres_gabnrequest_t **structp); @@ -227,20 +229,20 @@ lwres_gabnresponse_free(lwres_context_t *ctx, lwres_gabnresponse_t **structp); int -lwres_gnbarequest_render(lwres_context_t *ctx, - lwres_gnbarequest_t *req, - isc_uint32_t maxrecv, lwres_buffer_t *b); +lwres_gnbarequest_render(lwres_context_t *ctx, lwres_gnbarequest_t *req, + lwres_lwpacket_t *pkt, lwres_buffer_t *b); int -lwres_gnbaresponse_render(lwres_context_t *ctx, - lwres_gnbaresponse_t *req, - isc_uint32_t maxrecv, lwres_buffer_t *b); +lwres_gnbaresponse_render(lwres_context_t *ctx, lwres_gnbaresponse_t *req, + lwres_lwpacket_t *pkt, lwres_buffer_t *b); int -lwres_gnbarequest_parse(lwres_context_t *ctx, lwres_gnbarequest_t **structp); +lwres_gnbarequest_parse(lwres_context_t *ctx, lwres_lwpacket_t *pkt, + lwres_buffer_t *b, lwres_gnbarequest_t **structp); int -lwres_gnbaresponse_parse(lwres_context_t *ctx, lwres_gnbaresponse_t **structp); +lwres_gnbaresponse_parse(lwres_context_t *ctx, lwres_lwpacket_t *pkt, + lwres_buffer_t *b, lwres_gnbaresponse_t **structp); void lwres_gnbarequest_free(lwres_context_t *ctx, lwres_gnbarequest_t **structp); diff --git a/lib/lwres/lwres_gabn.c b/lib/lwres/lwres_gabn.c index 1ae6701fb6..4edfbd9ee9 100644 --- a/lib/lwres/lwres_gabn.c +++ b/lib/lwres/lwres_gabn.c @@ -31,9 +31,8 @@ int lwres_gabnrequest_render(lwres_context_t *ctx, lwres_gabnrequest_t *req, - isc_uint32_t maxrecv, lwres_buffer_t *b) + lwres_lwpacket_t *pkt, lwres_buffer_t *b) { - lwres_lwpacket_t pkt; unsigned char *buf; size_t buflen; int ret; @@ -43,13 +42,14 @@ lwres_gabnrequest_render(lwres_context_t *ctx, lwres_gabnrequest_t *req, REQUIRE(ctx != NULL); REQUIRE(req != NULL); REQUIRE(req->name != NULL); + REQUIRE(pkt != NULL); REQUIRE(b != NULL); datalen = strlen(req->name); payload_length = LWRES_STRING_LENGTH(req->name); - buflen = sizeof(lwres_lwpacket_t) + payload_length; + buflen = LWRES_LWPACKET_LENGTH + payload_length; buf = CTXMALLOC(buflen); if (buf == NULL) { errno = ENOMEM; @@ -57,17 +57,15 @@ lwres_gabnrequest_render(lwres_context_t *ctx, lwres_gabnrequest_t *req, } lwres_buffer_init(b, buf, buflen); - pkt.length = buflen; - pkt.version = LWRES_LWPACKETVERSION_0; - pkt.flags = 0; - pkt.serial = req->serial; - pkt.opcode = LWRES_OPCODE_GETADDRSBYNAME; - pkt.result = 0; - pkt.recvlength = maxrecv; - pkt.authtype = 0; - pkt.authlength = 0; + pkt->length = buflen; + pkt->version = LWRES_LWPACKETVERSION_0; + pkt->flags &= ~LWRES_LWPACKETFLAG_RESPONSE; + pkt->opcode = LWRES_OPCODE_GETADDRSBYNAME; + pkt->result = 0; + pkt->authtype = 0; + pkt->authlength = 0; - ret = lwres_lwpacket_renderheader(b, &pkt); + ret = lwres_lwpacket_renderheader(b, pkt); if (ret != 0) { lwres_buffer_invalidate(b); CTXFREE(buf, buflen); @@ -90,9 +88,8 @@ lwres_gabnrequest_render(lwres_context_t *ctx, lwres_gabnrequest_t *req, int lwres_gabnresponse_render(lwres_context_t *ctx, lwres_gabnresponse_t *req, - isc_uint32_t maxrecv, lwres_buffer_t *b) + lwres_lwpacket_t *pkt, lwres_buffer_t *b) { - lwres_lwpacket_t pkt; unsigned char *buf; size_t buflen; int ret; @@ -102,6 +99,7 @@ lwres_gabnresponse_render(lwres_context_t *ctx, lwres_gabnresponse_t *req, REQUIRE(ctx != NULL); REQUIRE(req != NULL); + REQUIRE(pkt != NULL); REQUIRE(b != NULL); /* naliases, naddrs */ @@ -117,7 +115,7 @@ lwres_gabnresponse_render(lwres_context_t *ctx, lwres_gabnresponse_t *req, payload_length += req->addrs[x]->length; } - buflen = sizeof(lwres_lwpacket_t) + payload_length; + buflen = LWRES_LWPACKET_LENGTH + payload_length; buf = CTXMALLOC(buflen); if (buf == NULL) { errno = ENOMEM; @@ -125,17 +123,14 @@ lwres_gabnresponse_render(lwres_context_t *ctx, lwres_gabnresponse_t *req, } lwres_buffer_init(b, buf, buflen); - pkt.length = buflen; - pkt.version = LWRES_LWPACKETVERSION_0; - pkt.flags = LWRES_LWPACKETFLAG_RESPONSE; - pkt.serial = req->serial; - pkt.opcode = LWRES_OPCODE_GETADDRSBYNAME; - pkt.result = req->result; - pkt.recvlength = maxrecv; - pkt.authtype = 0; - pkt.authlength = 0; + pkt->length = buflen; + pkt->version = LWRES_LWPACKETVERSION_0; + pkt->flags |= LWRES_LWPACKETFLAG_RESPONSE; + pkt->opcode = LWRES_OPCODE_GETADDRSBYNAME; + pkt->authtype = 0; + pkt->authlength = 0; - ret = lwres_lwpacket_renderheader(b, &pkt); + ret = lwres_lwpacket_renderheader(b, pkt); if (ret != 0) { lwres_buffer_invalidate(b); CTXFREE(buf, buflen); @@ -179,17 +174,23 @@ lwres_gabnresponse_render(lwres_context_t *ctx, lwres_gabnresponse_t *req, } int -lwres_gabnrequest_parse(lwres_context_t *ctx, lwres_gabnrequest_t **structp) +lwres_gabnrequest_parse(lwres_context_t *ctx, lwres_lwpacket_t *pkt, + lwres_buffer_t *b, lwres_gabnrequest_t **structp) { REQUIRE(ctx != NULL); + REQUIRE(b != NULL); + REQUIRE(pkt != NULL); REQUIRE(structp != NULL && *structp == NULL); } int -lwres_gabnresponse_parse(lwres_context_t *ctx, lwres_gabnresponse_t **structp) +lwres_gabnresponse_parse(lwres_context_t *ctx, lwres_lwpacket_t *pkt, + lwres_buffer_t *b, lwres_gabnresponse_t **structp) { REQUIRE(ctx != NULL); + REQUIRE(b != NULL); + REQUIRE(pkt != NULL); REQUIRE(structp != NULL && *structp == NULL); } @@ -205,8 +206,6 @@ lwres_gabnrequest_free(lwres_context_t *ctx, lwres_gabnrequest_t **structp) gabn = *structp; *structp = NULL; - if (gabn->buffer != NULL) - CTXFREE(gabn->buffer, gabn->buflen); CTXFREE(gabn, sizeof(lwres_gabnrequest_t)); } @@ -221,7 +220,5 @@ lwres_gabnresponse_free(lwres_context_t *ctx, lwres_gabnresponse_t **structp) gabn = *structp; *structp = NULL; - if (gabn->buffer != NULL) - CTXFREE(gabn->buffer, gabn->buflen); CTXFREE(gabn, sizeof(lwres_gabnresponse_t)); } diff --git a/lib/lwres/lwres_gnba.c b/lib/lwres/lwres_gnba.c index 5dbe6af0ca..9e4c81e34e 100644 --- a/lib/lwres/lwres_gnba.c +++ b/lib/lwres/lwres_gnba.c @@ -30,35 +30,179 @@ #include "assert_p.h" int -lwres_gnbarequest_render(lwres_context_t *ctx, - lwres_gnbarequest_t *req, - isc_uint32_t maxrecv, lwres_buffer_t *b) +lwres_gnbarequest_render(lwres_context_t *ctx, lwres_gnbarequest_t *req, + lwres_lwpacket_t *pkt, lwres_buffer_t *b) { + unsigned char *buf; + size_t buflen; + int ret; + size_t payload_length; + + REQUIRE(ctx != NULL); + REQUIRE(req != NULL); + REQUIRE(req->addr.family != 0); + REQUIRE(req->addr.length != 0); + REQUIRE(req->addr.address != NULL); + REQUIRE(pkt != NULL); + REQUIRE(b != NULL); + + payload_length = sizeof(isc_uint32_t) + sizeof(isc_uint16_t) + + req->addr.length; + + buflen = LWRES_LWPACKET_LENGTH + payload_length; + buf = CTXMALLOC(buflen); + if (buf == NULL) { + errno = ENOMEM; + return (-1); + } + lwres_buffer_init(b, buf, buflen); + + pkt->length = buflen; + pkt->version = LWRES_LWPACKETVERSION_0; + pkt->flags &= ~LWRES_LWPACKETFLAG_RESPONSE; + pkt->opcode = LWRES_OPCODE_GETNAMEBYADDR; + pkt->result = 0; + pkt->authtype = 0; + pkt->authlength = 0; + + ret = lwres_lwpacket_renderheader(b, pkt); + if (ret != 0) { + lwres_buffer_invalidate(b); + CTXFREE(buf, buflen); + return (ret); + } + + INSIST(SPACE_OK(b, payload_length)); + + /* + * Put the length and the data. We know this will fit because we + * just checked for it. + */ + lwres_buffer_putuint32(b, req->addr.family); + lwres_buffer_putuint16(b, req->addr.length); + lwres_buffer_putmem(b, req->addr.address, req->addr.length); + + INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0); + + return (0); } int -lwres_gnbaresponse_render(lwres_context_t *ctx, - lwres_gnbaresponse_t *req, - isc_uint32_t maxrecv, lwres_buffer_t *b) +lwres_gnbaresponse_render(lwres_context_t *ctx, lwres_gnbaresponse_t *req, + lwres_lwpacket_t *pkt, lwres_buffer_t *b) { + unsigned char *buf; + size_t buflen; + int ret; + size_t payload_length; + isc_uint16_t datalen; + int x; + + REQUIRE(ctx != NULL); + REQUIRE(req != NULL); + REQUIRE(pkt != NULL); + REQUIRE(b != NULL); + + /* naliases */ + payload_length = sizeof(isc_uint16_t); + /* real name encoding */ + payload_length += LWRES_STRING_LENGTH(req->real_name); + /* each alias */ + for (x = 0 ; x < req->naliases ; x++) + payload_length += LWRES_STRING_LENGTH(req->aliases[x]); + + buflen = LWRES_LWPACKET_LENGTH + payload_length; + buf = CTXMALLOC(buflen); + if (buf == NULL) { + errno = ENOMEM; + return (-1); + } + lwres_buffer_init(b, buf, buflen); + + pkt->length = buflen; + pkt->version = LWRES_LWPACKETVERSION_0; + pkt->flags |= LWRES_LWPACKETFLAG_RESPONSE; + pkt->opcode = LWRES_OPCODE_GETNAMEBYADDR; + pkt->authtype = 0; + pkt->authlength = 0; + + ret = lwres_lwpacket_renderheader(b, pkt); + if (ret != 0) { + lwres_buffer_invalidate(b); + CTXFREE(buf, buflen); + return (ret); + } + + /* encode naliases */ + + INSIST(SPACE_OK(b, sizeof(isc_uint16_t) * 2)); + lwres_buffer_putuint16(b, req->naliases); + + /* encode the real name */ + datalen = strlen(req->real_name); + INSIST(SPACE_OK(b, LWRES_STRING_LENGTH(req->real_name))); + lwres_buffer_putuint16(b, datalen); + lwres_buffer_putmem(b, req->real_name, datalen + 1); + + /* encode the aliases */ + for (x = 0 ; x < req->naliases ; x++) { + datalen = strlen(req->aliases[x]); + INSIST(SPACE_OK(b, LWRES_STRING_LENGTH(req->aliases[x]))); + lwres_buffer_putuint16(b, datalen); + lwres_buffer_putmem(b, req->aliases[x], datalen + 1); + } + + INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0); + + return (0); } int -lwres_gnbarequest_parse(lwres_context_t *ctx, lwres_gnbarequest_t **structp) +lwres_gnbarequest_parse(lwres_context_t *ctx, lwres_lwpacket_t *pkt, + lwres_buffer_t *b, lwres_gnbarequest_t **structp) { + REQUIRE(ctx != NULL); + REQUIRE(pkt != NULL); + REQUIRE(b != NULL); + REQUIRE(structp != NULL && *structp == NULL); + } int -lwres_gnbaresponse_parse(lwres_context_t *ctx, lwres_gnbaresponse_t **structp) +lwres_gnbaresponse_parse(lwres_context_t *ctx, lwres_lwpacket_t *pkt, + lwres_buffer_t *b, lwres_gnbaresponse_t **structp) { + REQUIRE(ctx != NULL); + REQUIRE(pkt != NULL); + REQUIRE(b != NULL); + REQUIRE(structp != NULL && *structp == NULL); + } void lwres_gnbarequest_free(lwres_context_t *ctx, lwres_gnbarequest_t **structp) { + lwres_gnbarequest_t *gnba; + + REQUIRE(ctx != NULL); + REQUIRE(structp != NULL && *structp != NULL); + + gnba = *structp; + *structp = NULL; + + CTXFREE(gnba, sizeof(lwres_gnbarequest_t)); } void lwres_gnbaresponse_free(lwres_context_t *ctx, lwres_gnbaresponse_t **structp) { + lwres_gnbaresponse_t *gnba; + + REQUIRE(ctx != NULL); + REQUIRE(structp != NULL && *structp != NULL); + + gnba = *structp; + *structp = NULL; + + CTXFREE(gnba, sizeof(lwres_gnbaresponse_t)); } diff --git a/lib/lwres/lwres_noop.c b/lib/lwres/lwres_noop.c index 444cfc0110..0cdf2e76b4 100644 --- a/lib/lwres/lwres_noop.c +++ b/lib/lwres/lwres_noop.c @@ -40,11 +40,12 @@ lwres_nooprequest_render(lwres_context_t *ctx, lwres_nooprequest_t *req, REQUIRE(ctx != NULL); REQUIRE(req != NULL); + REQUIRE(pkt != NULL); REQUIRE(b != NULL); payload_length = sizeof(isc_uint16_t) + req->datalength; - buflen = sizeof(lwres_lwpacket_t) + payload_length; + buflen = LWRES_LWPACKET_LENGTH + payload_length; buf = CTXMALLOC(buflen); if (buf == NULL) { errno = ENOMEM; @@ -54,7 +55,7 @@ lwres_nooprequest_render(lwres_context_t *ctx, lwres_nooprequest_t *req, pkt->length = buflen; pkt->version = LWRES_LWPACKETVERSION_0; - pkt->flags = 0; + pkt->flags &= ~LWRES_LWPACKETFLAG_RESPONSE; pkt->opcode = LWRES_OPCODE_NOOP; pkt->result = 0; pkt->authtype = 0; @@ -92,11 +93,12 @@ lwres_noopresponse_render(lwres_context_t *ctx, lwres_noopresponse_t *req, REQUIRE(ctx != NULL); REQUIRE(req != NULL); + REQUIRE(pkt != NULL); REQUIRE(b != NULL); payload_length = sizeof(isc_uint16_t) + req->datalength; - buflen = sizeof(lwres_lwpacket_t) + payload_length; + buflen = LWRES_LWPACKET_LENGTH + payload_length; buf = CTXMALLOC(buflen); if (buf == NULL) { errno = ENOMEM;