No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / bind / dist / lib / lwres / lwres_gnba.c
blob8749ee43a594c3b2888ec090a9f5f504c54504c8
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000-2002 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: lwres_gnba.c,v 1.28 2007/09/24 17:18:25 each Exp */
22 /*! \file lwres_gnba.c
23 These are low-level routines for creating and parsing lightweight
24 resolver address-to-name lookup request and response messages.
26 There are four main functions for the getnamebyaddr opcode. One
27 render function converts a getnamebyaddr request structure --
28 lwres_gnbarequest_t -- to the lightweight resolver's canonical
29 format. It is complemented by a parse function that converts a
30 packet in this canonical format to a getnamebyaddr request
31 structure. Another render function converts the getnamebyaddr
32 response structure -- lwres_gnbaresponse_t to the canonical format.
33 This is complemented by a parse function which converts a packet in
34 canonical format to a getnamebyaddr response structure.
36 These structures are defined in \link lwres.h <lwres/lwres.h.>\endlink They are shown
37 below.
39 \code
40 #define LWRES_OPCODE_GETNAMEBYADDR 0x00010002U
42 typedef struct {
43 lwres_uint32_t flags;
44 lwres_addr_t addr;
45 } lwres_gnbarequest_t;
47 typedef struct {
48 lwres_uint32_t flags;
49 lwres_uint16_t naliases;
50 char *realname;
51 char **aliases;
52 lwres_uint16_t realnamelen;
53 lwres_uint16_t *aliaslen;
54 void *base;
55 size_t baselen;
56 } lwres_gnbaresponse_t;
57 \endcode
59 lwres_gnbarequest_render() uses resolver context ctx to convert
60 getnamebyaddr request structure req to canonical format. The packet
61 header structure pkt is initialised and transferred to buffer b.
62 The contents of *req are then appended to the buffer in canonical
63 format. lwres_gnbaresponse_render() performs the same task, except
64 it converts a getnamebyaddr response structure lwres_gnbaresponse_t
65 to the lightweight resolver's canonical format.
67 lwres_gnbarequest_parse() uses context ctx to convert the contents
68 of packet pkt to a lwres_gnbarequest_t structure. Buffer b provides
69 space to be used for storing this structure. When the function
70 succeeds, the resulting lwres_gnbarequest_t is made available
71 through *structp. lwres_gnbaresponse_parse() offers the same
72 semantics as lwres_gnbarequest_parse() except it yields a
73 lwres_gnbaresponse_t structure.
75 lwres_gnbaresponse_free() and lwres_gnbarequest_free() release the
76 memory in resolver context ctx that was allocated to the
77 lwres_gnbaresponse_t or lwres_gnbarequest_t structures referenced
78 via structp. Any memory associated with ancillary buffers and
79 strings for those structures is also discarded.
81 \section lwres_gbna_return Return Values
83 The getnamebyaddr opcode functions lwres_gnbarequest_render(),
84 lwres_gnbaresponse_render() lwres_gnbarequest_parse() and
85 lwres_gnbaresponse_parse() all return #LWRES_R_SUCCESS on success.
86 They return #LWRES_R_NOMEMORY if memory allocation fails.
87 #LWRES_R_UNEXPECTEDEND is returned if the available space in the
88 buffer b is too small to accommodate the packet header or the
89 lwres_gnbarequest_t and lwres_gnbaresponse_t structures.
90 lwres_gnbarequest_parse() and lwres_gnbaresponse_parse() will
91 return #LWRES_R_UNEXPECTEDEND if the buffer is not empty after
92 decoding the received packet. These functions will return
93 #LWRES_R_FAILURE if pktflags in the packet header structure
94 #lwres_lwpacket_t indicate that the packet is not a response to an
95 earlier query.
97 \section lwres_gbna_see See Also
99 \link lwpacket.c lwres_packet\endlink
103 #include <config.h>
105 #include <assert.h>
106 #include <stdlib.h>
107 #include <string.h>
109 #include <lwres/lwbuffer.h>
110 #include <lwres/lwpacket.h>
111 #include <lwres/lwres.h>
112 #include <lwres/result.h>
114 #include "context_p.h"
115 #include "assert_p.h"
117 /*% Uses resolver context ctx to convert getnamebyaddr request structure req to canonical format. */
118 lwres_result_t
119 lwres_gnbarequest_render(lwres_context_t *ctx, lwres_gnbarequest_t *req,
120 lwres_lwpacket_t *pkt, lwres_buffer_t *b)
122 unsigned char *buf;
123 size_t buflen;
124 int ret;
125 size_t payload_length;
127 REQUIRE(ctx != NULL);
128 REQUIRE(req != NULL);
129 REQUIRE(req->addr.family != 0);
130 REQUIRE(req->addr.length != 0);
131 REQUIRE(pkt != NULL);
132 REQUIRE(b != NULL);
134 payload_length = 4 + 4 + 2 + + req->addr.length;
136 buflen = LWRES_LWPACKET_LENGTH + payload_length;
137 buf = CTXMALLOC(buflen);
138 if (buf == NULL)
139 return (LWRES_R_NOMEMORY);
140 lwres_buffer_init(b, buf, buflen);
142 pkt->length = buflen;
143 pkt->version = LWRES_LWPACKETVERSION_0;
144 pkt->pktflags &= ~LWRES_LWPACKETFLAG_RESPONSE;
145 pkt->opcode = LWRES_OPCODE_GETNAMEBYADDR;
146 pkt->result = 0;
147 pkt->authtype = 0;
148 pkt->authlength = 0;
150 ret = lwres_lwpacket_renderheader(b, pkt);
151 if (ret != LWRES_R_SUCCESS) {
152 lwres_buffer_invalidate(b);
153 CTXFREE(buf, buflen);
154 return (ret);
157 INSIST(SPACE_OK(b, payload_length));
160 * Put the length and the data. We know this will fit because we
161 * just checked for it.
163 lwres_buffer_putuint32(b, req->flags);
164 lwres_buffer_putuint32(b, req->addr.family);
165 lwres_buffer_putuint16(b, req->addr.length);
166 lwres_buffer_putmem(b, (unsigned char *)req->addr.address,
167 req->addr.length);
169 INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
171 return (LWRES_R_SUCCESS);
174 /*% Converts a getnamebyaddr response structure lwres_gnbaresponse_t to the lightweight resolver's canonical format. */
175 lwres_result_t
176 lwres_gnbaresponse_render(lwres_context_t *ctx, lwres_gnbaresponse_t *req,
177 lwres_lwpacket_t *pkt, lwres_buffer_t *b)
179 unsigned char *buf;
180 size_t buflen;
181 int ret;
182 size_t payload_length;
183 lwres_uint16_t datalen;
184 int x;
186 REQUIRE(ctx != NULL);
187 REQUIRE(req != NULL);
188 REQUIRE(pkt != NULL);
189 REQUIRE(b != NULL);
192 * Calculate packet size.
194 payload_length = 4; /* flags */
195 payload_length += 2; /* naliases */
196 payload_length += 2 + req->realnamelen + 1; /* real name encoding */
197 for (x = 0; x < req->naliases; x++) /* each alias */
198 payload_length += 2 + req->aliaslen[x] + 1;
200 buflen = LWRES_LWPACKET_LENGTH + payload_length;
201 buf = CTXMALLOC(buflen);
202 if (buf == NULL)
203 return (LWRES_R_NOMEMORY);
204 lwres_buffer_init(b, buf, buflen);
206 pkt->length = buflen;
207 pkt->version = LWRES_LWPACKETVERSION_0;
208 pkt->pktflags |= LWRES_LWPACKETFLAG_RESPONSE;
209 pkt->opcode = LWRES_OPCODE_GETNAMEBYADDR;
210 pkt->authtype = 0;
211 pkt->authlength = 0;
213 ret = lwres_lwpacket_renderheader(b, pkt);
214 if (ret != LWRES_R_SUCCESS) {
215 lwres_buffer_invalidate(b);
216 CTXFREE(buf, buflen);
217 return (ret);
220 INSIST(SPACE_OK(b, payload_length));
221 lwres_buffer_putuint32(b, req->flags);
223 /* encode naliases */
224 lwres_buffer_putuint16(b, req->naliases);
226 /* encode the real name */
227 datalen = req->realnamelen;
228 lwres_buffer_putuint16(b, datalen);
229 lwres_buffer_putmem(b, (unsigned char *)req->realname, datalen);
230 lwres_buffer_putuint8(b, 0);
232 /* encode the aliases */
233 for (x = 0; x < req->naliases; x++) {
234 datalen = req->aliaslen[x];
235 lwres_buffer_putuint16(b, datalen);
236 lwres_buffer_putmem(b, (unsigned char *)req->aliases[x],
237 datalen);
238 lwres_buffer_putuint8(b, 0);
241 INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
243 return (LWRES_R_SUCCESS);
246 /*% Uses context ctx to convert the contents of packet pkt to a lwres_gnbarequest_t structure. */
247 lwres_result_t
248 lwres_gnbarequest_parse(lwres_context_t *ctx, lwres_buffer_t *b,
249 lwres_lwpacket_t *pkt, lwres_gnbarequest_t **structp)
251 int ret;
252 lwres_gnbarequest_t *gnba;
254 REQUIRE(ctx != NULL);
255 REQUIRE(pkt != NULL);
256 REQUIRE(b != NULL);
257 REQUIRE(structp != NULL && *structp == NULL);
259 if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) != 0)
260 return (LWRES_R_FAILURE);
262 if (!SPACE_REMAINING(b, 4))
263 return (LWRES_R_UNEXPECTEDEND);
265 gnba = CTXMALLOC(sizeof(lwres_gnbarequest_t));
266 if (gnba == NULL)
267 return (LWRES_R_NOMEMORY);
269 gnba->flags = lwres_buffer_getuint32(b);
271 ret = lwres_addr_parse(b, &gnba->addr);
272 if (ret != LWRES_R_SUCCESS)
273 goto out;
275 if (LWRES_BUFFER_REMAINING(b) != 0) {
276 ret = LWRES_R_TRAILINGDATA;
277 goto out;
280 *structp = gnba;
281 return (LWRES_R_SUCCESS);
283 out:
284 if (gnba != NULL)
285 lwres_gnbarequest_free(ctx, &gnba);
287 return (ret);
290 /*% Offers the same semantics as lwres_gnbarequest_parse() except it yields a lwres_gnbaresponse_t structure. */
292 lwres_result_t
293 lwres_gnbaresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b,
294 lwres_lwpacket_t *pkt, lwres_gnbaresponse_t **structp)
296 int ret;
297 unsigned int x;
298 lwres_uint32_t flags;
299 lwres_uint16_t naliases;
300 lwres_gnbaresponse_t *gnba;
302 REQUIRE(ctx != NULL);
303 REQUIRE(pkt != NULL);
304 REQUIRE(b != NULL);
305 REQUIRE(structp != NULL && *structp == NULL);
307 gnba = NULL;
309 if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0)
310 return (LWRES_R_FAILURE);
313 * Pull off flags & naliases
315 if (!SPACE_REMAINING(b, 4 + 2))
316 return (LWRES_R_UNEXPECTEDEND);
317 flags = lwres_buffer_getuint32(b);
318 naliases = lwres_buffer_getuint16(b);
320 gnba = CTXMALLOC(sizeof(lwres_gnbaresponse_t));
321 if (gnba == NULL)
322 return (LWRES_R_NOMEMORY);
323 gnba->base = NULL;
324 gnba->aliases = NULL;
325 gnba->aliaslen = NULL;
327 gnba->flags = flags;
328 gnba->naliases = naliases;
330 if (naliases > 0) {
331 gnba->aliases = CTXMALLOC(sizeof(char *) * naliases);
332 if (gnba->aliases == NULL) {
333 ret = LWRES_R_NOMEMORY;
334 goto out;
337 gnba->aliaslen = CTXMALLOC(sizeof(lwres_uint16_t) * naliases);
338 if (gnba->aliaslen == NULL) {
339 ret = LWRES_R_NOMEMORY;
340 goto out;
345 * Now, pull off the real name.
347 ret = lwres_string_parse(b, &gnba->realname, &gnba->realnamelen);
348 if (ret != LWRES_R_SUCCESS)
349 goto out;
352 * Parse off the aliases.
354 for (x = 0; x < gnba->naliases; x++) {
355 ret = lwres_string_parse(b, &gnba->aliases[x],
356 &gnba->aliaslen[x]);
357 if (ret != LWRES_R_SUCCESS)
358 goto out;
361 if (LWRES_BUFFER_REMAINING(b) != 0) {
362 ret = LWRES_R_TRAILINGDATA;
363 goto out;
366 *structp = gnba;
367 return (LWRES_R_SUCCESS);
369 out:
370 if (gnba != NULL) {
371 if (gnba->aliases != NULL)
372 CTXFREE(gnba->aliases, sizeof(char *) * naliases);
373 if (gnba->aliaslen != NULL)
374 CTXFREE(gnba->aliaslen,
375 sizeof(lwres_uint16_t) * naliases);
376 CTXFREE(gnba, sizeof(lwres_gnbaresponse_t));
379 return (ret);
382 /*% Release the memory in resolver context ctx that was allocated to the lwres_gnbarequest_t. */
383 void
384 lwres_gnbarequest_free(lwres_context_t *ctx, lwres_gnbarequest_t **structp)
386 lwres_gnbarequest_t *gnba;
388 REQUIRE(ctx != NULL);
389 REQUIRE(structp != NULL && *structp != NULL);
391 gnba = *structp;
392 *structp = NULL;
394 CTXFREE(gnba, sizeof(lwres_gnbarequest_t));
397 /*% Release the memory in resolver context ctx that was allocated to the lwres_gnbaresponse_t. */
398 void
399 lwres_gnbaresponse_free(lwres_context_t *ctx, lwres_gnbaresponse_t **structp)
401 lwres_gnbaresponse_t *gnba;
403 REQUIRE(ctx != NULL);
404 REQUIRE(structp != NULL && *structp != NULL);
406 gnba = *structp;
407 *structp = NULL;
409 if (gnba->naliases > 0) {
410 CTXFREE(gnba->aliases, sizeof(char *) * gnba->naliases);
411 CTXFREE(gnba->aliaslen,
412 sizeof(lwres_uint16_t) * gnba->naliases);
414 if (gnba->base != NULL)
415 CTXFREE(gnba->base, gnba->baselen);
416 CTXFREE(gnba, sizeof(lwres_gnbaresponse_t));