Add BIND 9.2.4rc7.
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / lwres / lwresutil.c
blobcc53bdd1bdab5a27b541a7facfd8ee6cfc9ed84d
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: lwresutil.c,v 1.29.2.1 2004/03/09 06:12:35 marka Exp $ */
20 #include <config.h>
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
27 #include <lwres/lwbuffer.h>
28 #include <lwres/lwres.h>
29 #include <lwres/result.h>
31 #include "assert_p.h"
32 #include "context_p.h"
35 * Requires:
37 * The "current" pointer in "b" points to encoded raw data.
39 * Ensures:
41 * The address of the first byte of the data is returned via "p",
42 * and the length is returned via "len". If NULL, they are not
43 * set.
45 * On return, the current pointer of "b" will point to the character
46 * following the data length and the data.
49 lwres_result_t
50 lwres_data_parse(lwres_buffer_t *b, unsigned char **p, lwres_uint16_t *len)
52 lwres_uint16_t datalen;
53 unsigned char *data;
55 REQUIRE(b != NULL);
58 * Pull off the length (2 bytes)
60 if (!SPACE_REMAINING(b, 2))
61 return (LWRES_R_UNEXPECTEDEND);
62 datalen = lwres_buffer_getuint16(b);
65 * Set the pointer to this string to the right place, then
66 * advance the buffer pointer.
68 if (!SPACE_REMAINING(b, datalen))
69 return (LWRES_R_UNEXPECTEDEND);
70 data = b->base + b->current;
71 lwres_buffer_forward(b, datalen);
73 if (len != NULL)
74 *len = datalen;
75 if (p != NULL)
76 *p = data;
78 return (LWRES_R_SUCCESS);
82 * Requires:
84 * The "current" pointer in "b" point to an encoded string.
86 * Ensures:
88 * The address of the first byte of the string is returned via "c",
89 * and the length is returned via "len". If NULL, they are not
90 * set.
92 * On return, the current pointer of "b" will point to the character
93 * following the string length, the string, and the trailing NULL.
96 lwres_result_t
97 lwres_string_parse(lwres_buffer_t *b, char **c, lwres_uint16_t *len)
99 lwres_uint16_t datalen;
100 char *string;
102 REQUIRE(b != NULL);
105 * Pull off the length (2 bytes)
107 if (!SPACE_REMAINING(b, 2))
108 return (LWRES_R_UNEXPECTEDEND);
109 datalen = lwres_buffer_getuint16(b);
112 * Set the pointer to this string to the right place, then
113 * advance the buffer pointer.
115 if (!SPACE_REMAINING(b, datalen))
116 return (LWRES_R_UNEXPECTEDEND);
117 string = (char *)b->base + b->current;
118 lwres_buffer_forward(b, datalen);
121 * Skip the "must be zero" byte.
123 if (!SPACE_REMAINING(b, 1))
124 return (LWRES_R_UNEXPECTEDEND);
125 if (0 != lwres_buffer_getuint8(b))
126 return (LWRES_R_FAILURE);
128 if (len != NULL)
129 *len = datalen;
130 if (c != NULL)
131 *c = string;
133 return (LWRES_R_SUCCESS);
136 lwres_result_t
137 lwres_addr_parse(lwres_buffer_t *b, lwres_addr_t *addr)
139 REQUIRE(addr != NULL);
141 if (!SPACE_REMAINING(b, 6))
142 return (LWRES_R_UNEXPECTEDEND);
144 addr->family = lwres_buffer_getuint32(b);
145 addr->length = lwres_buffer_getuint16(b);
147 if (!SPACE_REMAINING(b, addr->length))
148 return (LWRES_R_UNEXPECTEDEND);
149 if (addr->length > LWRES_ADDR_MAXLEN)
150 return (LWRES_R_FAILURE);
152 lwres_buffer_getmem(b, addr->address, addr->length);
154 return (LWRES_R_SUCCESS);
157 lwres_result_t
158 lwres_getaddrsbyname(lwres_context_t *ctx, const char *name,
159 lwres_uint32_t addrtypes, lwres_gabnresponse_t **structp)
161 lwres_gabnrequest_t request;
162 lwres_gabnresponse_t *response;
163 int ret;
164 int recvlen;
165 lwres_buffer_t b_in, b_out;
166 lwres_lwpacket_t pkt;
167 lwres_uint32_t serial;
168 char *buffer;
169 char target_name[1024];
170 unsigned int target_length;
172 REQUIRE(ctx != NULL);
173 REQUIRE(name != NULL);
174 REQUIRE(addrtypes != 0);
175 REQUIRE(structp != NULL && *structp == NULL);
177 b_in.base = NULL;
178 b_out.base = NULL;
179 response = NULL;
180 buffer = NULL;
181 serial = lwres_context_nextserial(ctx);
183 buffer = CTXMALLOC(LWRES_RECVLENGTH);
184 if (buffer == NULL) {
185 ret = LWRES_R_NOMEMORY;
186 goto out;
189 target_length = strlen(name);
190 if (target_length >= sizeof(target_name))
191 return (LWRES_R_FAILURE);
192 strcpy(target_name, name); /* strcpy is safe */
195 * Set up our request and render it to a buffer.
197 request.flags = 0;
198 request.addrtypes = addrtypes;
199 request.name = target_name;
200 request.namelen = target_length;
201 pkt.pktflags = 0;
202 pkt.serial = serial;
203 pkt.result = 0;
204 pkt.recvlength = LWRES_RECVLENGTH;
206 again:
207 ret = lwres_gabnrequest_render(ctx, &request, &pkt, &b_out);
208 if (ret != LWRES_R_SUCCESS)
209 goto out;
211 ret = lwres_context_sendrecv(ctx, b_out.base, b_out.length, buffer,
212 LWRES_RECVLENGTH, &recvlen);
213 if (ret != LWRES_R_SUCCESS)
214 goto out;
216 lwres_buffer_init(&b_in, buffer, recvlen);
217 b_in.used = recvlen;
220 * Parse the packet header.
222 ret = lwres_lwpacket_parseheader(&b_in, &pkt);
223 if (ret != LWRES_R_SUCCESS)
224 goto out;
227 * Sanity check.
229 if (pkt.serial != serial)
230 goto again;
231 if (pkt.opcode != LWRES_OPCODE_GETADDRSBYNAME)
232 goto again;
235 * Free what we've transmitted
237 CTXFREE(b_out.base, b_out.length);
238 b_out.base = NULL;
239 b_out.length = 0;
241 if (pkt.result != LWRES_R_SUCCESS) {
242 ret = pkt.result;
243 goto out;
247 * Parse the response.
249 ret = lwres_gabnresponse_parse(ctx, &b_in, &pkt, &response);
250 if (ret != LWRES_R_SUCCESS)
251 goto out;
252 response->base = buffer;
253 response->baselen = LWRES_RECVLENGTH;
254 buffer = NULL; /* don't free this below */
256 *structp = response;
257 return (LWRES_R_SUCCESS);
259 out:
260 if (b_out.base != NULL)
261 CTXFREE(b_out.base, b_out.length);
262 if (buffer != NULL)
263 CTXFREE(buffer, LWRES_RECVLENGTH);
264 if (response != NULL)
265 lwres_gabnresponse_free(ctx, &response);
267 return (ret);
271 lwres_result_t
272 lwres_getnamebyaddr(lwres_context_t *ctx, lwres_uint32_t addrtype,
273 lwres_uint16_t addrlen, const unsigned char *addr,
274 lwres_gnbaresponse_t **structp)
276 lwres_gnbarequest_t request;
277 lwres_gnbaresponse_t *response;
278 int ret;
279 int recvlen;
280 lwres_buffer_t b_in, b_out;
281 lwres_lwpacket_t pkt;
282 lwres_uint32_t serial;
283 char *buffer;
285 REQUIRE(ctx != NULL);
286 REQUIRE(addrtype != 0);
287 REQUIRE(addrlen != 0);
288 REQUIRE(addr != NULL);
289 REQUIRE(structp != NULL && *structp == NULL);
291 b_in.base = NULL;
292 b_out.base = NULL;
293 response = NULL;
294 buffer = NULL;
295 serial = lwres_context_nextserial(ctx);
297 buffer = CTXMALLOC(LWRES_RECVLENGTH);
298 if (buffer == NULL) {
299 ret = LWRES_R_NOMEMORY;
300 goto out;
304 * Set up our request and render it to a buffer.
306 request.flags = 0;
307 request.addr.family = addrtype;
308 request.addr.length = addrlen;
309 memcpy(request.addr.address, addr, addrlen);
310 pkt.pktflags = 0;
311 pkt.serial = serial;
312 pkt.result = 0;
313 pkt.recvlength = LWRES_RECVLENGTH;
315 again:
316 ret = lwres_gnbarequest_render(ctx, &request, &pkt, &b_out);
317 if (ret != LWRES_R_SUCCESS)
318 goto out;
320 ret = lwres_context_sendrecv(ctx, b_out.base, b_out.length, buffer,
321 LWRES_RECVLENGTH, &recvlen);
322 if (ret != LWRES_R_SUCCESS)
323 goto out;
325 lwres_buffer_init(&b_in, buffer, recvlen);
326 b_in.used = recvlen;
329 * Parse the packet header.
331 ret = lwres_lwpacket_parseheader(&b_in, &pkt);
332 if (ret != LWRES_R_SUCCESS)
333 goto out;
336 * Sanity check.
338 if (pkt.serial != serial)
339 goto again;
340 if (pkt.opcode != LWRES_OPCODE_GETNAMEBYADDR)
341 goto again;
344 * Free what we've transmitted
346 CTXFREE(b_out.base, b_out.length);
347 b_out.base = NULL;
348 b_out.length = 0;
350 if (pkt.result != LWRES_R_SUCCESS) {
351 ret = pkt.result;
352 goto out;
356 * Parse the response.
358 ret = lwres_gnbaresponse_parse(ctx, &b_in, &pkt, &response);
359 if (ret != LWRES_R_SUCCESS)
360 goto out;
361 response->base = buffer;
362 response->baselen = LWRES_RECVLENGTH;
363 buffer = NULL; /* don't free this below */
365 *structp = response;
366 return (LWRES_R_SUCCESS);
368 out:
369 if (b_out.base != NULL)
370 CTXFREE(b_out.base, b_out.length);
371 if (buffer != NULL)
372 CTXFREE(buffer, LWRES_RECVLENGTH);
373 if (response != NULL)
374 lwres_gnbaresponse_free(ctx, &response);
376 return (ret);
379 lwres_result_t
380 lwres_getrdatabyname(lwres_context_t *ctx, const char *name,
381 lwres_uint16_t rdclass, lwres_uint16_t rdtype,
382 lwres_uint32_t flags, lwres_grbnresponse_t **structp)
384 int ret;
385 int recvlen;
386 lwres_buffer_t b_in, b_out;
387 lwres_lwpacket_t pkt;
388 lwres_uint32_t serial;
389 char *buffer;
390 lwres_grbnrequest_t request;
391 lwres_grbnresponse_t *response;
392 char target_name[1024];
393 unsigned int target_length;
395 REQUIRE(ctx != NULL);
396 REQUIRE(name != NULL);
397 REQUIRE(structp != NULL && *structp == NULL);
399 b_in.base = NULL;
400 b_out.base = NULL;
401 response = NULL;
402 buffer = NULL;
403 serial = lwres_context_nextserial(ctx);
405 buffer = CTXMALLOC(LWRES_RECVLENGTH);
406 if (buffer == NULL) {
407 ret = LWRES_R_NOMEMORY;
408 goto out;
411 target_length = strlen(name);
412 if (target_length >= sizeof(target_name))
413 return (LWRES_R_FAILURE);
414 strcpy(target_name, name); /* strcpy is safe */
417 * Set up our request and render it to a buffer.
419 request.rdclass = rdclass;
420 request.rdtype = rdtype;
421 request.flags = flags;
422 request.name = target_name;
423 request.namelen = target_length;
424 pkt.pktflags = 0;
425 pkt.serial = serial;
426 pkt.result = 0;
427 pkt.recvlength = LWRES_RECVLENGTH;
429 again:
430 ret = lwres_grbnrequest_render(ctx, &request, &pkt, &b_out);
431 if (ret != LWRES_R_SUCCESS)
432 goto out;
434 ret = lwres_context_sendrecv(ctx, b_out.base, b_out.length, buffer,
435 LWRES_RECVLENGTH, &recvlen);
436 if (ret != LWRES_R_SUCCESS)
437 goto out;
439 lwres_buffer_init(&b_in, buffer, recvlen);
440 b_in.used = recvlen;
443 * Parse the packet header.
445 ret = lwres_lwpacket_parseheader(&b_in, &pkt);
446 if (ret != LWRES_R_SUCCESS)
447 goto out;
450 * Sanity check.
452 if (pkt.serial != serial)
453 goto again;
454 if (pkt.opcode != LWRES_OPCODE_GETRDATABYNAME)
455 goto again;
458 * Free what we've transmitted
460 CTXFREE(b_out.base, b_out.length);
461 b_out.base = NULL;
462 b_out.length = 0;
464 if (pkt.result != LWRES_R_SUCCESS) {
465 ret = pkt.result;
466 goto out;
470 * Parse the response.
472 ret = lwres_grbnresponse_parse(ctx, &b_in, &pkt, &response);
473 if (ret != LWRES_R_SUCCESS)
474 goto out;
475 response->base = buffer;
476 response->baselen = LWRES_RECVLENGTH;
477 buffer = NULL; /* don't free this below */
479 *structp = response;
480 return (LWRES_R_SUCCESS);
482 out:
483 if (b_out.base != NULL)
484 CTXFREE(b_out.base, b_out.length);
485 if (buffer != NULL)
486 CTXFREE(buffer, LWRES_RECVLENGTH);
487 if (response != NULL)
488 lwres_grbnresponse_free(ctx, &response);
490 return (ret);