Import bind-9.3.4
[dragonfly.git] / contrib / bind-9.3 / lib / lwres / lwres_gabn.c
blob9df87ce6706c63d7df6ec04e4a1ad5141a7216a6
1 /*
2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000, 2001 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_gabn.c,v 1.27.12.3 2004/03/08 09:05:10 marka Exp $ */
20 #include <config.h>
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <string.h>
26 #include <lwres/lwbuffer.h>
27 #include <lwres/lwpacket.h>
28 #include <lwres/lwres.h>
29 #include <lwres/result.h>
31 #include "context_p.h"
32 #include "assert_p.h"
34 lwres_result_t
35 lwres_gabnrequest_render(lwres_context_t *ctx, lwres_gabnrequest_t *req,
36 lwres_lwpacket_t *pkt, lwres_buffer_t *b)
38 unsigned char *buf;
39 size_t buflen;
40 int ret;
41 size_t payload_length;
42 lwres_uint16_t datalen;
44 REQUIRE(ctx != NULL);
45 REQUIRE(req != NULL);
46 REQUIRE(req->name != NULL);
47 REQUIRE(pkt != NULL);
48 REQUIRE(b != NULL);
50 datalen = strlen(req->name);
52 payload_length = 4 + 4 + 2 + req->namelen + 1;
54 buflen = LWRES_LWPACKET_LENGTH + payload_length;
55 buf = CTXMALLOC(buflen);
56 if (buf == NULL)
57 return (LWRES_R_NOMEMORY);
59 lwres_buffer_init(b, buf, buflen);
61 pkt->length = buflen;
62 pkt->version = LWRES_LWPACKETVERSION_0;
63 pkt->pktflags &= ~LWRES_LWPACKETFLAG_RESPONSE;
64 pkt->opcode = LWRES_OPCODE_GETADDRSBYNAME;
65 pkt->result = 0;
66 pkt->authtype = 0;
67 pkt->authlength = 0;
69 ret = lwres_lwpacket_renderheader(b, pkt);
70 if (ret != LWRES_R_SUCCESS) {
71 lwres_buffer_invalidate(b);
72 CTXFREE(buf, buflen);
73 return (ret);
76 INSIST(SPACE_OK(b, payload_length));
79 * Flags.
81 lwres_buffer_putuint32(b, req->flags);
84 * Address types we'll accept.
86 lwres_buffer_putuint32(b, req->addrtypes);
89 * Put the length and the data. We know this will fit because we
90 * just checked for it.
92 lwres_buffer_putuint16(b, datalen);
93 lwres_buffer_putmem(b, (unsigned char *)req->name, datalen);
94 lwres_buffer_putuint8(b, 0); /* trailing NUL */
96 INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
98 return (LWRES_R_SUCCESS);
101 lwres_result_t
102 lwres_gabnresponse_render(lwres_context_t *ctx, lwres_gabnresponse_t *req,
103 lwres_lwpacket_t *pkt, lwres_buffer_t *b)
105 unsigned char *buf;
106 size_t buflen;
107 int ret;
108 size_t payload_length;
109 lwres_uint16_t datalen;
110 lwres_addr_t *addr;
111 int x;
113 REQUIRE(ctx != NULL);
114 REQUIRE(req != NULL);
115 REQUIRE(pkt != NULL);
116 REQUIRE(b != NULL);
118 /* naliases, naddrs */
119 payload_length = 4 + 2 + 2;
120 /* real name encoding */
121 payload_length += 2 + req->realnamelen + 1;
122 /* each alias */
123 for (x = 0; x < req->naliases; x++)
124 payload_length += 2 + req->aliaslen[x] + 1;
125 /* each address */
126 x = 0;
127 addr = LWRES_LIST_HEAD(req->addrs);
128 while (addr != NULL) {
129 payload_length += 4 + 2;
130 payload_length += addr->length;
131 addr = LWRES_LIST_NEXT(addr, link);
132 x++;
134 INSIST(x == req->naddrs);
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_GETADDRSBYNAME;
146 pkt->authtype = 0;
147 pkt->authlength = 0;
149 ret = lwres_lwpacket_renderheader(b, pkt);
150 if (ret != LWRES_R_SUCCESS) {
151 lwres_buffer_invalidate(b);
152 CTXFREE(buf, buflen);
153 return (ret);
157 * Check space needed here.
159 INSIST(SPACE_OK(b, payload_length));
161 /* Flags. */
162 lwres_buffer_putuint32(b, req->flags);
164 /* encode naliases and naddrs */
165 lwres_buffer_putuint16(b, req->naliases);
166 lwres_buffer_putuint16(b, req->naddrs);
168 /* encode the real name */
169 datalen = req->realnamelen;
170 lwres_buffer_putuint16(b, datalen);
171 lwres_buffer_putmem(b, (unsigned char *)req->realname, datalen);
172 lwres_buffer_putuint8(b, 0);
174 /* encode the aliases */
175 for (x = 0; x < req->naliases; x++) {
176 datalen = req->aliaslen[x];
177 lwres_buffer_putuint16(b, datalen);
178 lwres_buffer_putmem(b, (unsigned char *)req->aliases[x],
179 datalen);
180 lwres_buffer_putuint8(b, 0);
183 /* encode the addresses */
184 addr = LWRES_LIST_HEAD(req->addrs);
185 while (addr != NULL) {
186 lwres_buffer_putuint32(b, addr->family);
187 lwres_buffer_putuint16(b, addr->length);
188 lwres_buffer_putmem(b, addr->address, addr->length);
189 addr = LWRES_LIST_NEXT(addr, link);
192 INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
193 INSIST(LWRES_BUFFER_USEDCOUNT(b) == pkt->length);
195 return (LWRES_R_SUCCESS);
198 lwres_result_t
199 lwres_gabnrequest_parse(lwres_context_t *ctx, lwres_buffer_t *b,
200 lwres_lwpacket_t *pkt, lwres_gabnrequest_t **structp)
202 int ret;
203 char *name;
204 lwres_gabnrequest_t *gabn;
205 lwres_uint32_t addrtypes;
206 lwres_uint32_t flags;
207 lwres_uint16_t namelen;
209 REQUIRE(ctx != NULL);
210 REQUIRE(pkt != NULL);
211 REQUIRE(b != NULL);
212 REQUIRE(structp != NULL && *structp == NULL);
214 if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) != 0)
215 return (LWRES_R_FAILURE);
217 if (!SPACE_REMAINING(b, 4 + 4))
218 return (LWRES_R_UNEXPECTEDEND);
220 flags = lwres_buffer_getuint32(b);
221 addrtypes = lwres_buffer_getuint32(b);
224 * Pull off the name itself
226 ret = lwres_string_parse(b, &name, &namelen);
227 if (ret != LWRES_R_SUCCESS)
228 return (ret);
230 if (LWRES_BUFFER_REMAINING(b) != 0)
231 return (LWRES_R_TRAILINGDATA);
233 gabn = CTXMALLOC(sizeof(lwres_gabnrequest_t));
234 if (gabn == NULL)
235 return (LWRES_R_NOMEMORY);
237 gabn->flags = flags;
238 gabn->addrtypes = addrtypes;
239 gabn->name = name;
240 gabn->namelen = namelen;
242 *structp = gabn;
243 return (LWRES_R_SUCCESS);
246 lwres_result_t
247 lwres_gabnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b,
248 lwres_lwpacket_t *pkt, lwres_gabnresponse_t **structp)
250 lwres_result_t ret;
251 unsigned int x;
252 lwres_uint32_t flags;
253 lwres_uint16_t naliases;
254 lwres_uint16_t naddrs;
255 lwres_gabnresponse_t *gabn;
256 lwres_addrlist_t addrlist;
257 lwres_addr_t *addr;
259 REQUIRE(ctx != NULL);
260 REQUIRE(pkt != NULL);
261 REQUIRE(b != NULL);
262 REQUIRE(structp != NULL && *structp == NULL);
264 gabn = NULL;
266 if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0)
267 return (LWRES_R_FAILURE);
270 * Pull off the name itself
272 if (!SPACE_REMAINING(b, 4 + 2 + 2))
273 return (LWRES_R_UNEXPECTEDEND);
274 flags = lwres_buffer_getuint32(b);
275 naliases = lwres_buffer_getuint16(b);
276 naddrs = lwres_buffer_getuint16(b);
278 gabn = CTXMALLOC(sizeof(lwres_gabnresponse_t));
279 if (gabn == NULL)
280 return (LWRES_R_NOMEMORY);
281 gabn->aliases = NULL;
282 gabn->aliaslen = NULL;
283 LWRES_LIST_INIT(gabn->addrs);
284 gabn->base = NULL;
286 gabn->flags = flags;
287 gabn->naliases = naliases;
288 gabn->naddrs = naddrs;
290 LWRES_LIST_INIT(addrlist);
292 if (naliases > 0) {
293 gabn->aliases = CTXMALLOC(sizeof(char *) * naliases);
294 if (gabn->aliases == NULL) {
295 ret = LWRES_R_NOMEMORY;
296 goto out;
299 gabn->aliaslen = CTXMALLOC(sizeof(lwres_uint16_t) * naliases);
300 if (gabn->aliaslen == NULL) {
301 ret = LWRES_R_NOMEMORY;
302 goto out;
306 for (x = 0; x < naddrs; x++) {
307 addr = CTXMALLOC(sizeof(lwres_addr_t));
308 if (addr == NULL) {
309 ret = LWRES_R_NOMEMORY;
310 goto out;
312 LWRES_LINK_INIT(addr, link);
313 LWRES_LIST_APPEND(addrlist, addr, link);
317 * Now, pull off the real name.
319 ret = lwres_string_parse(b, &gabn->realname, &gabn->realnamelen);
320 if (ret != LWRES_R_SUCCESS)
321 goto out;
324 * Parse off the aliases.
326 for (x = 0; x < gabn->naliases; x++) {
327 ret = lwres_string_parse(b, &gabn->aliases[x],
328 &gabn->aliaslen[x]);
329 if (ret != LWRES_R_SUCCESS)
330 goto out;
334 * Pull off the addresses. We already strung the linked list
335 * up above.
337 addr = LWRES_LIST_HEAD(addrlist);
338 for (x = 0; x < gabn->naddrs; x++) {
339 INSIST(addr != NULL);
340 ret = lwres_addr_parse(b, addr);
341 if (ret != LWRES_R_SUCCESS)
342 goto out;
343 addr = LWRES_LIST_NEXT(addr, link);
346 if (LWRES_BUFFER_REMAINING(b) != 0) {
347 ret = LWRES_R_TRAILINGDATA;
348 goto out;
351 gabn->addrs = addrlist;
353 *structp = gabn;
354 return (LWRES_R_SUCCESS);
356 out:
357 if (gabn != NULL) {
358 if (gabn->aliases != NULL)
359 CTXFREE(gabn->aliases, sizeof(char *) * naliases);
360 if (gabn->aliaslen != NULL)
361 CTXFREE(gabn->aliaslen,
362 sizeof(lwres_uint16_t) * naliases);
363 addr = LWRES_LIST_HEAD(addrlist);
364 while (addr != NULL) {
365 LWRES_LIST_UNLINK(addrlist, addr, link);
366 CTXFREE(addr, sizeof(lwres_addr_t));
367 addr = LWRES_LIST_HEAD(addrlist);
369 CTXFREE(gabn, sizeof(lwres_gabnresponse_t));
372 return (ret);
375 void
376 lwres_gabnrequest_free(lwres_context_t *ctx, lwres_gabnrequest_t **structp)
378 lwres_gabnrequest_t *gabn;
380 REQUIRE(ctx != NULL);
381 REQUIRE(structp != NULL && *structp != NULL);
383 gabn = *structp;
384 *structp = NULL;
386 CTXFREE(gabn, sizeof(lwres_gabnrequest_t));
389 void
390 lwres_gabnresponse_free(lwres_context_t *ctx, lwres_gabnresponse_t **structp)
392 lwres_gabnresponse_t *gabn;
393 lwres_addr_t *addr;
395 REQUIRE(ctx != NULL);
396 REQUIRE(structp != NULL && *structp != NULL);
398 gabn = *structp;
399 *structp = NULL;
401 if (gabn->naliases > 0) {
402 CTXFREE(gabn->aliases, sizeof(char *) * gabn->naliases);
403 CTXFREE(gabn->aliaslen,
404 sizeof(lwres_uint16_t) * gabn->naliases);
406 addr = LWRES_LIST_HEAD(gabn->addrs);
407 while (addr != NULL) {
408 LWRES_LIST_UNLINK(gabn->addrs, addr, link);
409 CTXFREE(addr, sizeof(lwres_addr_t));
410 addr = LWRES_LIST_HEAD(gabn->addrs);
412 if (gabn->base != NULL)
413 CTXFREE(gabn->base, gabn->baselen);
414 CTXFREE(gabn, sizeof(lwres_gabnresponse_t));