2 * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2002 Internet Software Consortium.
5 * Permission to use, copy, modify, and 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.
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.
18 /* $Id: lwres_gnba.c,v 1.23.18.2 2005/04/29 00:17:20 marka Exp $ */
20 /*! \file lwres_gnba.c
21 These are low-level routines for creating and parsing lightweight
22 resolver address-to-name lookup request and response messages.
24 There are four main functions for the getnamebyaddr opcode. One
25 render function converts a getnamebyaddr request structure --
26 lwres_gnbarequest_t -- to the lightweight resolver's canonical
27 format. It is complemented by a parse function that converts a
28 packet in this canonical format to a getnamebyaddr request
29 structure. Another render function converts the getnamebyaddr
30 response structure -- lwres_gnbaresponse_t to the canonical format.
31 This is complemented by a parse function which converts a packet in
32 canonical format to a getnamebyaddr response structure.
34 These structures are defined in \link lwres.h <lwres/lwres.h.>\endlink They are shown
38 #define LWRES_OPCODE_GETNAMEBYADDR 0x00010002U
43 } lwres_gnbarequest_t;
47 lwres_uint16_t naliases;
50 lwres_uint16_t realnamelen;
51 lwres_uint16_t *aliaslen;
54 } lwres_gnbaresponse_t;
57 lwres_gnbarequest_render() uses resolver context ctx to convert
58 getnamebyaddr request structure req to canonical format. The packet
59 header structure pkt is initialised and transferred to buffer b.
60 The contents of *req are then appended to the buffer in canonical
61 format. lwres_gnbaresponse_render() performs the same task, except
62 it converts a getnamebyaddr response structure lwres_gnbaresponse_t
63 to the lightweight resolver's canonical format.
65 lwres_gnbarequest_parse() uses context ctx to convert the contents
66 of packet pkt to a lwres_gnbarequest_t structure. Buffer b provides
67 space to be used for storing this structure. When the function
68 succeeds, the resulting lwres_gnbarequest_t is made available
69 through *structp. lwres_gnbaresponse_parse() offers the same
70 semantics as lwres_gnbarequest_parse() except it yields a
71 lwres_gnbaresponse_t structure.
73 lwres_gnbaresponse_free() and lwres_gnbarequest_free() release the
74 memory in resolver context ctx that was allocated to the
75 lwres_gnbaresponse_t or lwres_gnbarequest_t structures referenced
76 via structp. Any memory associated with ancillary buffers and
77 strings for those structures is also discarded.
79 \section lwres_gbna_return Return Values
81 The getnamebyaddr opcode functions lwres_gnbarequest_render(),
82 lwres_gnbaresponse_render() lwres_gnbarequest_parse() and
83 lwres_gnbaresponse_parse() all return #LWRES_R_SUCCESS on success.
84 They return #LWRES_R_NOMEMORY if memory allocation fails.
85 #LWRES_R_UNEXPECTEDEND is returned if the available space in the
86 buffer b is too small to accommodate the packet header or the
87 lwres_gnbarequest_t and lwres_gnbaresponse_t structures.
88 lwres_gnbarequest_parse() and lwres_gnbaresponse_parse() will
89 return #LWRES_R_UNEXPECTEDEND if the buffer is not empty after
90 decoding the received packet. These functions will return
91 #LWRES_R_FAILURE if pktflags in the packet header structure
92 #lwres_lwpacket_t indicate that the packet is not a response to an
95 \section lwres_gbna_see See Also
97 \link lwpacket.c lwres_packet\endlink
107 #include <lwres/lwbuffer.h>
108 #include <lwres/lwpacket.h>
109 #include <lwres/lwres.h>
110 #include <lwres/result.h>
112 #include "context_p.h"
113 #include "assert_p.h"
115 /*% Uses resolver context ctx to convert getnamebyaddr request structure req to canonical format. */
117 lwres_gnbarequest_render(lwres_context_t *ctx, lwres_gnbarequest_t *req,
118 lwres_lwpacket_t *pkt, lwres_buffer_t *b)
123 size_t payload_length;
125 REQUIRE(ctx != NULL);
126 REQUIRE(req != NULL);
127 REQUIRE(req->addr.family != 0);
128 REQUIRE(req->addr.length != 0);
129 REQUIRE(req->addr.address != NULL);
130 REQUIRE(pkt != NULL);
133 payload_length = 4 + 4 + 2 + + req->addr.length;
135 buflen = LWRES_LWPACKET_LENGTH + payload_length;
136 buf = CTXMALLOC(buflen);
138 return (LWRES_R_NOMEMORY);
139 lwres_buffer_init(b, buf, buflen);
141 pkt->length = buflen;
142 pkt->version = LWRES_LWPACKETVERSION_0;
143 pkt->pktflags &= ~LWRES_LWPACKETFLAG_RESPONSE;
144 pkt->opcode = LWRES_OPCODE_GETNAMEBYADDR;
149 ret = lwres_lwpacket_renderheader(b, pkt);
150 if (ret != LWRES_R_SUCCESS) {
151 lwres_buffer_invalidate(b);
152 CTXFREE(buf, buflen);
156 INSIST(SPACE_OK(b, payload_length));
159 * Put the length and the data. We know this will fit because we
160 * just checked for it.
162 lwres_buffer_putuint32(b, req->flags);
163 lwres_buffer_putuint32(b, req->addr.family);
164 lwres_buffer_putuint16(b, req->addr.length);
165 lwres_buffer_putmem(b, (unsigned char *)req->addr.address,
168 INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
170 return (LWRES_R_SUCCESS);
173 /*% Converts a getnamebyaddr response structure lwres_gnbaresponse_t to the lightweight resolver's canonical format. */
175 lwres_gnbaresponse_render(lwres_context_t *ctx, lwres_gnbaresponse_t *req,
176 lwres_lwpacket_t *pkt, lwres_buffer_t *b)
181 size_t payload_length;
182 lwres_uint16_t datalen;
185 REQUIRE(ctx != NULL);
186 REQUIRE(req != NULL);
187 REQUIRE(pkt != NULL);
191 * Calculate packet size.
193 payload_length = 4; /* flags */
194 payload_length += 2; /* naliases */
195 payload_length += 2 + req->realnamelen + 1; /* real name encoding */
196 for (x = 0; x < req->naliases; x++) /* each alias */
197 payload_length += 2 + req->aliaslen[x] + 1;
199 buflen = LWRES_LWPACKET_LENGTH + payload_length;
200 buf = CTXMALLOC(buflen);
202 return (LWRES_R_NOMEMORY);
203 lwres_buffer_init(b, buf, buflen);
205 pkt->length = buflen;
206 pkt->version = LWRES_LWPACKETVERSION_0;
207 pkt->pktflags |= LWRES_LWPACKETFLAG_RESPONSE;
208 pkt->opcode = LWRES_OPCODE_GETNAMEBYADDR;
212 ret = lwres_lwpacket_renderheader(b, pkt);
213 if (ret != LWRES_R_SUCCESS) {
214 lwres_buffer_invalidate(b);
215 CTXFREE(buf, buflen);
219 INSIST(SPACE_OK(b, payload_length));
220 lwres_buffer_putuint32(b, req->flags);
222 /* encode naliases */
223 lwres_buffer_putuint16(b, req->naliases);
225 /* encode the real name */
226 datalen = req->realnamelen;
227 lwres_buffer_putuint16(b, datalen);
228 lwres_buffer_putmem(b, (unsigned char *)req->realname, datalen);
229 lwres_buffer_putuint8(b, 0);
231 /* encode the aliases */
232 for (x = 0; x < req->naliases; x++) {
233 datalen = req->aliaslen[x];
234 lwres_buffer_putuint16(b, datalen);
235 lwres_buffer_putmem(b, (unsigned char *)req->aliases[x],
237 lwres_buffer_putuint8(b, 0);
240 INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
242 return (LWRES_R_SUCCESS);
245 /*% Uses context ctx to convert the contents of packet pkt to a lwres_gnbarequest_t structure. */
247 lwres_gnbarequest_parse(lwres_context_t *ctx, lwres_buffer_t *b,
248 lwres_lwpacket_t *pkt, lwres_gnbarequest_t **structp)
251 lwres_gnbarequest_t *gnba;
253 REQUIRE(ctx != NULL);
254 REQUIRE(pkt != NULL);
256 REQUIRE(structp != NULL && *structp == NULL);
258 if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) != 0)
259 return (LWRES_R_FAILURE);
261 if (!SPACE_REMAINING(b, 4))
262 return (LWRES_R_UNEXPECTEDEND);
264 gnba = CTXMALLOC(sizeof(lwres_gnbarequest_t));
266 return (LWRES_R_NOMEMORY);
268 gnba->flags = lwres_buffer_getuint32(b);
270 ret = lwres_addr_parse(b, &gnba->addr);
271 if (ret != LWRES_R_SUCCESS)
274 if (LWRES_BUFFER_REMAINING(b) != 0) {
275 ret = LWRES_R_TRAILINGDATA;
280 return (LWRES_R_SUCCESS);
284 lwres_gnbarequest_free(ctx, &gnba);
289 /*% Offers the same semantics as lwres_gnbarequest_parse() except it yields a lwres_gnbaresponse_t structure. */
292 lwres_gnbaresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b,
293 lwres_lwpacket_t *pkt, lwres_gnbaresponse_t **structp)
297 lwres_uint32_t flags;
298 lwres_uint16_t naliases;
299 lwres_gnbaresponse_t *gnba;
301 REQUIRE(ctx != NULL);
302 REQUIRE(pkt != NULL);
304 REQUIRE(structp != NULL && *structp == NULL);
308 if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0)
309 return (LWRES_R_FAILURE);
312 * Pull off flags & naliases
314 if (!SPACE_REMAINING(b, 4 + 2))
315 return (LWRES_R_UNEXPECTEDEND);
316 flags = lwres_buffer_getuint32(b);
317 naliases = lwres_buffer_getuint16(b);
319 gnba = CTXMALLOC(sizeof(lwres_gnbaresponse_t));
321 return (LWRES_R_NOMEMORY);
323 gnba->aliases = NULL;
324 gnba->aliaslen = NULL;
327 gnba->naliases = naliases;
330 gnba->aliases = CTXMALLOC(sizeof(char *) * naliases);
331 if (gnba->aliases == NULL) {
332 ret = LWRES_R_NOMEMORY;
336 gnba->aliaslen = CTXMALLOC(sizeof(lwres_uint16_t) * naliases);
337 if (gnba->aliaslen == NULL) {
338 ret = LWRES_R_NOMEMORY;
344 * Now, pull off the real name.
346 ret = lwres_string_parse(b, &gnba->realname, &gnba->realnamelen);
347 if (ret != LWRES_R_SUCCESS)
351 * Parse off the aliases.
353 for (x = 0; x < gnba->naliases; x++) {
354 ret = lwres_string_parse(b, &gnba->aliases[x],
356 if (ret != LWRES_R_SUCCESS)
360 if (LWRES_BUFFER_REMAINING(b) != 0) {
361 ret = LWRES_R_TRAILINGDATA;
366 return (LWRES_R_SUCCESS);
370 if (gnba->aliases != NULL)
371 CTXFREE(gnba->aliases, sizeof(char *) * naliases);
372 if (gnba->aliaslen != NULL)
373 CTXFREE(gnba->aliaslen,
374 sizeof(lwres_uint16_t) * naliases);
375 CTXFREE(gnba, sizeof(lwres_gnbaresponse_t));
381 /*% Release the memory in resolver context ctx that was allocated to the lwres_gnbarequest_t. */
383 lwres_gnbarequest_free(lwres_context_t *ctx, lwres_gnbarequest_t **structp)
385 lwres_gnbarequest_t *gnba;
387 REQUIRE(ctx != NULL);
388 REQUIRE(structp != NULL && *structp != NULL);
393 CTXFREE(gnba, sizeof(lwres_gnbarequest_t));
396 /*% Release the memory in resolver context ctx that was allocated to the lwres_gnbaresponse_t. */
398 lwres_gnbaresponse_free(lwres_context_t *ctx, lwres_gnbaresponse_t **structp)
400 lwres_gnbaresponse_t *gnba;
402 REQUIRE(ctx != NULL);
403 REQUIRE(structp != NULL && *structp != NULL);
408 if (gnba->naliases > 0) {
409 CTXFREE(gnba->aliases, sizeof(char *) * gnba->naliases);
410 CTXFREE(gnba->aliaslen,
411 sizeof(lwres_uint16_t) * gnba->naliases);
413 if (gnba->base != NULL)
414 CTXFREE(gnba->base, gnba->baselen);
415 CTXFREE(gnba, sizeof(lwres_gnbaresponse_t));