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 $ */
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"
35 lwres_gabnrequest_render(lwres_context_t
*ctx
, lwres_gabnrequest_t
*req
,
36 lwres_lwpacket_t
*pkt
, lwres_buffer_t
*b
)
41 size_t payload_length
;
42 lwres_uint16_t datalen
;
46 REQUIRE(req
->name
!= 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
);
57 return (LWRES_R_NOMEMORY
);
59 lwres_buffer_init(b
, buf
, buflen
);
62 pkt
->version
= LWRES_LWPACKETVERSION_0
;
63 pkt
->pktflags
&= ~LWRES_LWPACKETFLAG_RESPONSE
;
64 pkt
->opcode
= LWRES_OPCODE_GETADDRSBYNAME
;
69 ret
= lwres_lwpacket_renderheader(b
, pkt
);
70 if (ret
!= LWRES_R_SUCCESS
) {
71 lwres_buffer_invalidate(b
);
76 INSIST(SPACE_OK(b
, payload_length
));
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
);
102 lwres_gabnresponse_render(lwres_context_t
*ctx
, lwres_gabnresponse_t
*req
,
103 lwres_lwpacket_t
*pkt
, lwres_buffer_t
*b
)
108 size_t payload_length
;
109 lwres_uint16_t datalen
;
113 REQUIRE(ctx
!= NULL
);
114 REQUIRE(req
!= NULL
);
115 REQUIRE(pkt
!= NULL
);
118 /* naliases, naddrs */
119 payload_length
= 4 + 2 + 2;
120 /* real name encoding */
121 payload_length
+= 2 + req
->realnamelen
+ 1;
123 for (x
= 0; x
< req
->naliases
; x
++)
124 payload_length
+= 2 + req
->aliaslen
[x
] + 1;
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
);
134 INSIST(x
== req
->naddrs
);
136 buflen
= LWRES_LWPACKET_LENGTH
+ payload_length
;
137 buf
= CTXMALLOC(buflen
);
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
;
149 ret
= lwres_lwpacket_renderheader(b
, pkt
);
150 if (ret
!= LWRES_R_SUCCESS
) {
151 lwres_buffer_invalidate(b
);
152 CTXFREE(buf
, buflen
);
157 * Check space needed here.
159 INSIST(SPACE_OK(b
, payload_length
));
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
],
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
);
199 lwres_gabnrequest_parse(lwres_context_t
*ctx
, lwres_buffer_t
*b
,
200 lwres_lwpacket_t
*pkt
, lwres_gabnrequest_t
**structp
)
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
);
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
)
230 if (LWRES_BUFFER_REMAINING(b
) != 0)
231 return (LWRES_R_TRAILINGDATA
);
233 gabn
= CTXMALLOC(sizeof(lwres_gabnrequest_t
));
235 return (LWRES_R_NOMEMORY
);
238 gabn
->addrtypes
= addrtypes
;
240 gabn
->namelen
= namelen
;
243 return (LWRES_R_SUCCESS
);
247 lwres_gabnresponse_parse(lwres_context_t
*ctx
, lwres_buffer_t
*b
,
248 lwres_lwpacket_t
*pkt
, lwres_gabnresponse_t
**structp
)
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
;
259 REQUIRE(ctx
!= NULL
);
260 REQUIRE(pkt
!= NULL
);
262 REQUIRE(structp
!= NULL
&& *structp
== 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
));
280 return (LWRES_R_NOMEMORY
);
281 gabn
->aliases
= NULL
;
282 gabn
->aliaslen
= NULL
;
283 LWRES_LIST_INIT(gabn
->addrs
);
287 gabn
->naliases
= naliases
;
288 gabn
->naddrs
= naddrs
;
290 LWRES_LIST_INIT(addrlist
);
293 gabn
->aliases
= CTXMALLOC(sizeof(char *) * naliases
);
294 if (gabn
->aliases
== NULL
) {
295 ret
= LWRES_R_NOMEMORY
;
299 gabn
->aliaslen
= CTXMALLOC(sizeof(lwres_uint16_t
) * naliases
);
300 if (gabn
->aliaslen
== NULL
) {
301 ret
= LWRES_R_NOMEMORY
;
306 for (x
= 0; x
< naddrs
; x
++) {
307 addr
= CTXMALLOC(sizeof(lwres_addr_t
));
309 ret
= LWRES_R_NOMEMORY
;
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
)
324 * Parse off the aliases.
326 for (x
= 0; x
< gabn
->naliases
; x
++) {
327 ret
= lwres_string_parse(b
, &gabn
->aliases
[x
],
329 if (ret
!= LWRES_R_SUCCESS
)
334 * Pull off the addresses. We already strung the linked list
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
)
343 addr
= LWRES_LIST_NEXT(addr
, link
);
346 if (LWRES_BUFFER_REMAINING(b
) != 0) {
347 ret
= LWRES_R_TRAILINGDATA
;
351 gabn
->addrs
= addrlist
;
354 return (LWRES_R_SUCCESS
);
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
));
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
);
386 CTXFREE(gabn
, sizeof(lwres_gabnrequest_t
));
390 lwres_gabnresponse_free(lwres_context_t
*ctx
, lwres_gabnresponse_t
**structp
)
392 lwres_gabnresponse_t
*gabn
;
395 REQUIRE(ctx
!= NULL
);
396 REQUIRE(structp
!= NULL
&& *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
));