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 $ */
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
);