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.206.1 2004/03/06 08:15:33 marka Exp $ */
27 #include <lwres/lwbuffer.h>
28 #include <lwres/lwres.h>
29 #include <lwres/result.h>
32 #include "context_p.h"
37 * The "current" pointer in "b" points to encoded raw data.
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
45 * On return, the current pointer of "b" will point to the character
46 * following the data length and the data.
50 lwres_data_parse(lwres_buffer_t *b, unsigned char **p, lwres_uint16_t *len)
52 lwres_uint16_t datalen;
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);
78 return (LWRES_R_SUCCESS);
84 * The "current" pointer in "b" point to an encoded string.
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
92 * On return, the current pointer of "b" will point to the character
93 * following the string length, the string, and the trailing NULL.
97 lwres_string_parse(lwres_buffer_t *b, char **c, lwres_uint16_t *len)
99 lwres_uint16_t datalen;
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);
133 return (LWRES_R_SUCCESS);
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);
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;
165 lwres_buffer_t b_in, b_out;
166 lwres_lwpacket_t pkt;
167 lwres_uint32_t serial;
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);
181 serial = lwres_context_nextserial(ctx);
183 buffer = CTXMALLOC(LWRES_RECVLENGTH);
184 if (buffer == NULL) {
185 ret = LWRES_R_NOMEMORY;
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.
198 request.addrtypes = addrtypes;
199 request.name = target_name;
200 request.namelen = target_length;
204 pkt.recvlength = LWRES_RECVLENGTH;
207 ret = lwres_gabnrequest_render(ctx, &request, &pkt, &b_out);
208 if (ret != LWRES_R_SUCCESS)
211 ret = lwres_context_sendrecv(ctx, b_out.base, b_out.length, buffer,
212 LWRES_RECVLENGTH, &recvlen);
213 if (ret != LWRES_R_SUCCESS)
216 lwres_buffer_init(&b_in, buffer, recvlen);
220 * Parse the packet header.
222 ret = lwres_lwpacket_parseheader(&b_in, &pkt);
223 if (ret != LWRES_R_SUCCESS)
229 if (pkt.serial != serial)
231 if (pkt.opcode != LWRES_OPCODE_GETADDRSBYNAME)
235 * Free what we've transmitted
237 CTXFREE(b_out.base, b_out.length);
241 if (pkt.result != LWRES_R_SUCCESS) {
247 * Parse the response.
249 ret = lwres_gabnresponse_parse(ctx, &b_in, &pkt, &response);
250 if (ret != LWRES_R_SUCCESS)
252 response->base = buffer;
253 response->baselen = LWRES_RECVLENGTH;
254 buffer = NULL; /* don't free this below */
257 return (LWRES_R_SUCCESS);
260 if (b_out.base != NULL)
261 CTXFREE(b_out.base, b_out.length);
263 CTXFREE(buffer, LWRES_RECVLENGTH);
264 if (response != NULL)
265 lwres_gabnresponse_free(ctx, &response);
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;
280 lwres_buffer_t b_in, b_out;
281 lwres_lwpacket_t pkt;
282 lwres_uint32_t serial;
285 REQUIRE(ctx != NULL);
286 REQUIRE(addrtype != 0);
287 REQUIRE(addrlen != 0);
288 REQUIRE(addr != NULL);
289 REQUIRE(structp != NULL && *structp == NULL);
295 serial = lwres_context_nextserial(ctx);
297 buffer = CTXMALLOC(LWRES_RECVLENGTH);
298 if (buffer == NULL) {
299 ret = LWRES_R_NOMEMORY;
304 * Set up our request and render it to a buffer.
307 request.addr.family = addrtype;
308 request.addr.length = addrlen;
309 memcpy(request.addr.address, addr, addrlen);
313 pkt.recvlength = LWRES_RECVLENGTH;
316 ret = lwres_gnbarequest_render(ctx, &request, &pkt, &b_out);
317 if (ret != LWRES_R_SUCCESS)
320 ret = lwres_context_sendrecv(ctx, b_out.base, b_out.length, buffer,
321 LWRES_RECVLENGTH, &recvlen);
322 if (ret != LWRES_R_SUCCESS)
325 lwres_buffer_init(&b_in, buffer, recvlen);
329 * Parse the packet header.
331 ret = lwres_lwpacket_parseheader(&b_in, &pkt);
332 if (ret != LWRES_R_SUCCESS)
338 if (pkt.serial != serial)
340 if (pkt.opcode != LWRES_OPCODE_GETNAMEBYADDR)
344 * Free what we've transmitted
346 CTXFREE(b_out.base, b_out.length);
350 if (pkt.result != LWRES_R_SUCCESS) {
356 * Parse the response.
358 ret = lwres_gnbaresponse_parse(ctx, &b_in, &pkt, &response);
359 if (ret != LWRES_R_SUCCESS)
361 response->base = buffer;
362 response->baselen = LWRES_RECVLENGTH;
363 buffer = NULL; /* don't free this below */
366 return (LWRES_R_SUCCESS);
369 if (b_out.base != NULL)
370 CTXFREE(b_out.base, b_out.length);
372 CTXFREE(buffer, LWRES_RECVLENGTH);
373 if (response != NULL)
374 lwres_gnbaresponse_free(ctx, &response);
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)
386 lwres_buffer_t b_in, b_out;
387 lwres_lwpacket_t pkt;
388 lwres_uint32_t serial;
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);
403 serial = lwres_context_nextserial(ctx);
405 buffer = CTXMALLOC(LWRES_RECVLENGTH);
406 if (buffer == NULL) {
407 ret = LWRES_R_NOMEMORY;
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;
427 pkt.recvlength = LWRES_RECVLENGTH;
430 ret = lwres_grbnrequest_render(ctx, &request, &pkt, &b_out);
431 if (ret != LWRES_R_SUCCESS)
434 ret = lwres_context_sendrecv(ctx, b_out.base, b_out.length, buffer,
435 LWRES_RECVLENGTH, &recvlen);
436 if (ret != LWRES_R_SUCCESS)
439 lwres_buffer_init(&b_in, buffer, recvlen);
443 * Parse the packet header.
445 ret = lwres_lwpacket_parseheader(&b_in, &pkt);
446 if (ret != LWRES_R_SUCCESS)
452 if (pkt.serial != serial)
454 if (pkt.opcode != LWRES_OPCODE_GETRDATABYNAME)
458 * Free what we've transmitted
460 CTXFREE(b_out.base, b_out.length);
464 if (pkt.result != LWRES_R_SUCCESS) {
470 * Parse the response.
472 ret = lwres_grbnresponse_parse(ctx, &b_in, &pkt, &response);
473 if (ret != LWRES_R_SUCCESS)
475 response->base = buffer;
476 response->baselen = LWRES_RECVLENGTH;
477 buffer = NULL; /* don't free this below */
480 return (LWRES_R_SUCCESS);
483 if (b_out.base != NULL)
484 CTXFREE(b_out.base, b_out.length);
486 CTXFREE(buffer, LWRES_RECVLENGTH);
487 if (response != NULL)
488 lwres_grbnresponse_free(ctx, &response);