]> git.ipfire.org Git - people/ms/strongswan.git/blob - lib/liblwres/lwres_gabn.c
5e809ba8ee25334477c7aa7315f8f2a7fe87f686
[people/ms/strongswan.git] / lib / liblwres / lwres_gabn.c
1 /*
2 * Copyright (C) 2000, 2001 Internet Software Consortium.
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
9 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
10 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
11 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
13 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
14 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
15 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 /* $Id: lwres_gabn.c,v 1.1 2004/03/15 20:35:25 as Exp $ */
19
20 #include <config.h>
21
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <lwres/lwbuffer.h>
27 #include <lwres/lwpacket.h>
28 #include <lwres/lwres.h>
29 #include <lwres/result.h>
30
31 #include "context_p.h"
32 #include "assert_p.h"
33
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)
37 {
38 unsigned char *buf;
39 size_t buflen;
40 int ret;
41 size_t payload_length;
42 lwres_uint16_t datalen;
43
44 REQUIRE(ctx != NULL);
45 REQUIRE(req != NULL);
46 REQUIRE(req->name != NULL);
47 REQUIRE(pkt != NULL);
48 REQUIRE(b != NULL);
49
50 datalen = strlen(req->name);
51
52 payload_length = 4 + 4 + 2 + req->namelen + 1;
53
54 buflen = LWRES_LWPACKET_LENGTH + payload_length;
55 buf = CTXMALLOC(buflen);
56 if (buf == NULL)
57 return (LWRES_R_NOMEMORY);
58
59 lwres_buffer_init(b, buf, buflen);
60
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;
68
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);
74 }
75
76 INSIST(SPACE_OK(b, payload_length));
77
78 /*
79 * Flags.
80 */
81 lwres_buffer_putuint32(b, req->flags);
82
83 /*
84 * Address types we'll accept.
85 */
86 lwres_buffer_putuint32(b, req->addrtypes);
87
88 /*
89 * Put the length and the data. We know this will fit because we
90 * just checked for it.
91 */
92 lwres_buffer_putuint16(b, datalen);
93 lwres_buffer_putmem(b, (unsigned char *)req->name, datalen);
94 lwres_buffer_putuint8(b, 0); /* trailing NUL */
95
96 INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
97
98 return (LWRES_R_SUCCESS);
99 }
100
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)
104 {
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;
112
113 REQUIRE(ctx != NULL);
114 REQUIRE(req != NULL);
115 REQUIRE(pkt != NULL);
116 REQUIRE(b != NULL);
117
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++;
133 }
134 INSIST(x == req->naddrs);
135
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);
141
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;
148
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);
154 }
155
156 /*
157 * Check space needed here.
158 */
159 INSIST(SPACE_OK(b, payload_length));
160
161 /* Flags. */
162 lwres_buffer_putuint32(b, req->flags);
163
164 /* encode naliases and naddrs */
165 lwres_buffer_putuint16(b, req->naliases);
166 lwres_buffer_putuint16(b, req->naddrs);
167
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);
173
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);
181 }
182
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);
190 }
191
192 INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
193 INSIST(LWRES_BUFFER_USEDCOUNT(b) == pkt->length);
194
195 return (LWRES_R_SUCCESS);
196 }
197
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)
201 {
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;
208
209 REQUIRE(ctx != NULL);
210 REQUIRE(pkt != NULL);
211 REQUIRE(b != NULL);
212 REQUIRE(structp != NULL && *structp == NULL);
213
214 if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) != 0)
215 return (LWRES_R_FAILURE);
216
217 if (!SPACE_REMAINING(b, 4 + 4))
218 return (LWRES_R_UNEXPECTEDEND);
219
220 flags = lwres_buffer_getuint32(b);
221 addrtypes = lwres_buffer_getuint32(b);
222
223 /*
224 * Pull off the name itself
225 */
226 ret = lwres_string_parse(b, &name, &namelen);
227 if (ret != LWRES_R_SUCCESS)
228 return (ret);
229
230 if (LWRES_BUFFER_REMAINING(b) != 0)
231 return (LWRES_R_TRAILINGDATA);
232
233 gabn = CTXMALLOC(sizeof(lwres_gabnrequest_t));
234 if (gabn == NULL)
235 return (LWRES_R_NOMEMORY);
236
237 gabn->flags = flags;
238 gabn->addrtypes = addrtypes;
239 gabn->name = name;
240 gabn->namelen = namelen;
241
242 *structp = gabn;
243 return (LWRES_R_SUCCESS);
244 }
245
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)
249 {
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;
258
259 REQUIRE(ctx != NULL);
260 REQUIRE(pkt != NULL);
261 REQUIRE(b != NULL);
262 REQUIRE(structp != NULL && *structp == NULL);
263
264 gabn = NULL;
265
266 if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0)
267 return (LWRES_R_FAILURE);
268
269 /*
270 * Pull off the name itself
271 */
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);
277
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;
285
286 gabn->flags = flags;
287 gabn->naliases = naliases;
288 gabn->naddrs = naddrs;
289
290 LWRES_LIST_INIT(addrlist);
291
292 if (naliases > 0) {
293 gabn->aliases = CTXMALLOC(sizeof(char *) * naliases);
294 if (gabn->aliases == NULL) {
295 ret = LWRES_R_NOMEMORY;
296 goto out;
297 }
298
299 gabn->aliaslen = CTXMALLOC(sizeof(lwres_uint16_t) * naliases);
300 if (gabn->aliaslen == NULL) {
301 ret = LWRES_R_NOMEMORY;
302 goto out;
303 }
304 }
305
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;
311 }
312 LWRES_LINK_INIT(addr, link);
313 LWRES_LIST_APPEND(addrlist, addr, link);
314 }
315
316 /*
317 * Now, pull off the real name.
318 */
319 ret = lwres_string_parse(b, &gabn->realname, &gabn->realnamelen);
320 if (ret != LWRES_R_SUCCESS)
321 goto out;
322
323 /*
324 * Parse off the aliases.
325 */
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;
331 }
332
333 /*
334 * Pull off the addresses. We already strung the linked list
335 * up above.
336 */
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);
344 }
345
346 if (LWRES_BUFFER_REMAINING(b) != 0) {
347 ret = LWRES_R_TRAILINGDATA;
348 goto out;
349 }
350
351 gabn->addrs = addrlist;
352
353 *structp = gabn;
354 return (LWRES_R_SUCCESS);
355
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);
368 }
369 CTXFREE(gabn, sizeof(lwres_gabnresponse_t));
370 }
371
372 return (ret);
373 }
374
375 void
376 lwres_gabnrequest_free(lwres_context_t *ctx, lwres_gabnrequest_t **structp)
377 {
378 lwres_gabnrequest_t *gabn;
379
380 REQUIRE(ctx != NULL);
381 REQUIRE(structp != NULL && *structp != NULL);
382
383 gabn = *structp;
384 *structp = NULL;
385
386 CTXFREE(gabn, sizeof(lwres_gabnrequest_t));
387 }
388
389 void
390 lwres_gabnresponse_free(lwres_context_t *ctx, lwres_gabnresponse_t **structp)
391 {
392 lwres_gabnresponse_t *gabn;
393 lwres_addr_t *addr;
394
395 REQUIRE(ctx != NULL);
396 REQUIRE(structp != NULL && *structp != NULL);
397
398 gabn = *structp;
399 *structp = NULL;
400
401 if (gabn->naliases > 0) {
402 CTXFREE(gabn->aliases, sizeof(char *) * gabn->naliases);
403 CTXFREE(gabn->aliaslen,
404 sizeof(lwres_uint16_t) * gabn->naliases);
405 }
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);
411 }
412 if (gabn->base != NULL)
413 CTXFREE(gabn->base, gabn->baselen);
414 CTXFREE(gabn, sizeof(lwres_gabnresponse_t));
415 }