diff --git a/bin/lwresd/client.c b/bin/lwresd/client.c index 9b1eb9ce84..708b03c678 100644 --- a/bin/lwresd/client.c +++ b/bin/lwresd/client.c @@ -351,6 +351,7 @@ client_init_aliases(client_t *client) client->addrs[i].family = 0; client->addrs[i].length = 0; client->addrs[i].address = NULL; + LWRES_LINK_INIT(&client->addrs[i], link); } } @@ -368,7 +369,7 @@ client_init_gabn(client_t *client) client->gabn.aliases = client->aliases; client->gabn.realnamelen = 0; client->gabn.aliaslen = client->aliaslen; - client->gabn.addrs = client->addrs; + LWRES_LIST_INIT(client->gabn.addrs); client->gabn.base = NULL; client->gabn.baselen = 0; diff --git a/bin/lwresd/process_gabn.c b/bin/lwresd/process_gabn.c index 44326dc2dc..c23f86bd96 100644 --- a/bin/lwresd/process_gabn.c +++ b/bin/lwresd/process_gabn.c @@ -110,6 +110,8 @@ setup_addresses(client_t *client, dns_adbfind_t *find, unsigned int at) addr->address, addr->family, addr->length); client->gabn.naddrs++; + REQUIRE(!LWRES_LINK_LINKED(addr, link)); + LWRES_LIST_APPEND(client->gabn.addrs, addr, link); next: ai = ISC_LIST_NEXT(ai, publink); @@ -151,6 +153,7 @@ generate_reply(client_t *client) * Run through the finds we have and wire them up to the gabn * structure. */ + LWRES_LIST_INIT(client->gabn.addrs); if (client->v4find != NULL) setup_addresses(client, client->v4find, DNS_ADBFIND_INET); if (client->v6find != NULL) diff --git a/bin/tests/lwres_test.c b/bin/tests/lwres_test.c index 5283fec5ca..f7eed98b4a 100644 --- a/bin/tests/lwres_test.c +++ b/bin/tests/lwres_test.c @@ -158,6 +158,7 @@ static void test_gabn(char *target) { lwres_gabnresponse_t *res; + lwres_addr_t *addr; int ret; unsigned int i; char outbuf[64]; @@ -180,15 +181,19 @@ test_gabn(char *target) for (i = 0 ; i < res->naliases ; i++) printf("\t(%u, %s)\n", res->aliaslen[i], res->aliases[i]); printf("%u addresses:\n", res->naddrs); + addr = LWRES_LIST_HEAD(res->addrs); for (i = 0 ; i < res->naddrs ; i++) { - if (res->addrs[i].family == LWRES_ADDRTYPE_V4) - (void)inet_ntop(AF_INET, res->addrs[i].address, + INSIST(addr != NULL); + + if (addr->family == LWRES_ADDRTYPE_V4) + (void)inet_ntop(AF_INET, addr->address, outbuf, sizeof(outbuf)); else - (void)inet_ntop(AF_INET6, res->addrs[i].address, + (void)inet_ntop(AF_INET6, addr->address, outbuf, sizeof(outbuf)); printf("\tAddr len %u family %08x %s\n", - res->addrs[i].length, res->addrs[i].family, outbuf); + addr->length, addr->family, outbuf); + addr = LWRES_LIST_NEXT(addr, link); } lwres_gabnresponse_free(ctx, &res); diff --git a/lib/lwres/context.c b/lib/lwres/context.c index ea294278d2..cce57eb69a 100644 --- a/lib/lwres/context.c +++ b/lib/lwres/context.c @@ -77,6 +77,11 @@ lwres_context_create(lwres_context_t **contextp, void *arg, (void)context_connect(ctx); /* XXXMLG */ + /* + * Init resolv.conf bits. + */ + lwres_conf_init(ctx); + *contextp = ctx; return (LWRES_R_SUCCESS); } diff --git a/lib/lwres/context_p.h b/lib/lwres/context_p.h index ba26b87f30..c646252798 100644 --- a/lib/lwres/context_p.h +++ b/lib/lwres/context_p.h @@ -46,6 +46,11 @@ struct lwres_context { lwres_malloc_t malloc; lwres_free_t free; void *arg; + + /* + * resolv.conf-like data + */ + lwres_conf_t confdata; }; #endif /* LWRES_CONTEXT_P_H */ diff --git a/lib/lwres/getaddrinfo.c b/lib/lwres/getaddrinfo.c index b1b8a19dee..1dcf1691a9 100644 --- a/lib/lwres/getaddrinfo.c +++ b/lib/lwres/getaddrinfo.c @@ -3,7 +3,7 @@ * The Berkeley Software Design Inc. software License Agreement specifies * the terms and conditions for redistribution. * - * BSDI $Id: getaddrinfo.c,v 1.13 2000/02/04 06:17:22 halley Exp $ + * BSDI $Id: getaddrinfo.c,v 1.14 2000/03/10 23:11:27 explorer Exp $ */ @@ -353,11 +353,12 @@ add_ipv4(const char *hostname, int flags, struct addrinfo **aip, struct addrinfo *ai; lwres_context_t *lwrctx = NULL; lwres_gabnresponse_t *by = NULL; - int i; + lwres_addr_t *addr; + lwres_result_t lwres; int result = 0; - i = lwres_context_create(&lwrctx, NULL, NULL, NULL); - if (i != 0) + lwres = lwres_context_create(&lwrctx, NULL, NULL, NULL); + if (lwres != 0) ERR(EAI_FAIL); if (hostname == NULL && (flags & AI_PASSIVE) == 0) { if ((ai = ai_clone(*aip, AF_INET)) == NULL) { @@ -371,7 +372,8 @@ add_ipv4(const char *hostname, int flags, struct addrinfo **aip, memcpy(&SIN(ai->ai_addr)->sin_addr, v4_loop, 4); } else if (lwres_getaddrsbyname(lwrctx, hostname, LWRES_ADDRTYPE_V4, &by) == 0) { - for (i = 0; i < by->naddrs; i++) { + addr = LWRES_LIST_HEAD(by->addrs); + while (addr != NULL) { ai = ai_clone(*aip, AF_INET); if (ai == NULL) { lwres_freeaddrinfo(*aip); @@ -381,9 +383,10 @@ add_ipv4(const char *hostname, int flags, struct addrinfo **aip, ai->ai_socktype = socktype; SIN(ai->ai_addr)->sin_port = port; memcpy(&SIN(ai->ai_addr)->sin_addr, - by->addrs[i].address, 4); + addr->address, 4); if (flags & AI_CANONNAME) ai->ai_canonname = strdup(by->realname); + addr = LWRES_LIST_NEXT(addr, link); } } cleanup: @@ -403,12 +406,14 @@ add_ipv6(const char *hostname, int flags, struct addrinfo **aip, struct addrinfo *ai; lwres_context_t *lwrctx = NULL; lwres_gabnresponse_t *by = NULL; - int i; + lwres_addr_t *addr; + lwres_result_t lwres; int result = 0; - i = lwres_context_create(&lwrctx, NULL, NULL, NULL); - if (i != 0) + lwres = lwres_context_create(&lwrctx, NULL, NULL, NULL); + if (lwres != 0) ERR(EAI_FAIL); + if (hostname == NULL && (flags & AI_PASSIVE) == 0) { if ((ai = ai_clone(*aip, AF_INET6)) == NULL) { lwres_freeaddrinfo(*aip); @@ -421,7 +426,8 @@ add_ipv6(const char *hostname, int flags, struct addrinfo **aip, memcpy(&SIN6(ai->ai_addr)->sin6_addr, v6_loop, 16); } else if (lwres_getaddrsbyname(lwrctx, hostname, LWRES_ADDRTYPE_V6, &by) == 0) { - for (i = 0; i < by->naddrs; i++) { + addr = LWRES_LIST_HEAD(by->addrs); + while (addr != NULL) { if ((ai = ai_clone(*aip, AF_INET6)) == NULL) { lwres_freeaddrinfo(*aip); ERR(EAI_MEMORY); @@ -430,9 +436,10 @@ add_ipv6(const char *hostname, int flags, struct addrinfo **aip, ai->ai_socktype = socktype; SIN6(ai->ai_addr)->sin6_port = port; memcpy(&SIN6(ai->ai_addr)->sin6_addr, - by->addrs[i].address, 16); + addr->address, 16); if (flags & AI_CANONNAME) ai->ai_canonname = strdup(by->realname); + addr = LWRES_LIST_NEXT(addr, link); } } cleanup: diff --git a/lib/lwres/getipnode.c b/lib/lwres/getipnode.c index 78a49960ec..a5e11c0c4c 100644 --- a/lib/lwres/getipnode.c +++ b/lib/lwres/getipnode.c @@ -680,9 +680,11 @@ hostfromaddr(lwres_gnbaresponse_t *addr, int af, const void *src) { } static struct hostent * -hostfromname(lwres_gabnresponse_t *name, int af) { +hostfromname(lwres_gabnresponse_t *name, int af) +{ struct hostent *he; int i; + lwres_addr_t *addr; he = malloc(sizeof *he); if (he == NULL) @@ -718,11 +720,15 @@ hostfromname(lwres_gabnresponse_t *name, int af) { /* copy addresses */ he->h_addr_list = malloc(sizeof(char *) * (name->naddrs + 1)); - for (i = 0 ; i < name->naddrs; i++) { + addr = LWRES_LIST_HEAD(name->addrs); + i = 0; + while (addr != NULL) { he->h_addr_list[i] = malloc(he->h_length); if (he->h_addr_list[i] == NULL) goto cleanup; - memcpy(he->h_addr_list[i], name->addrs[i].address, he->h_length); + memcpy(he->h_addr_list[i], addr->address, he->h_length); + addr = LWRES_LIST_NEXT(addr, link); + i++; } he->h_addr_list[i] = NULL; return (he); diff --git a/lib/lwres/include/lwres/Makefile.in b/lib/lwres/include/lwres/Makefile.in index 2bf33548f0..ee93cb78e0 100644 --- a/lib/lwres/include/lwres/Makefile.in +++ b/lib/lwres/include/lwres/Makefile.in @@ -21,7 +21,7 @@ top_srcdir = @top_srcdir@ # Only list headers that are to be installed! # HEADERS = context.h lwbuffer.h lwpacket.h lwres.h netdb.h result.h \ - int.h lang.h net.h ipv6.h platform.h + int.h lang.h list.h net.h ipv6.h platform.h SUBDIRS = TARGETS = diff --git a/lib/lwres/include/lwres/list.h b/lib/lwres/include/lwres/list.h new file mode 100644 index 0000000000..e222a6e8db --- /dev/null +++ b/lib/lwres/include/lwres/list.h @@ -0,0 +1,116 @@ +/* + * Copyright (C) 1997, 1999, 2000 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef LWRES_LIST_H +#define LWRES_LIST_H 1 + +#define LWRES_LIST(type) struct { type *head, *tail; } +#define LWRES_LIST_INIT(list) \ + do { (list).head = NULL; (list).tail = NULL; } while (0) + +#define LWRES_LINK(type) struct { type *prev, *next; } +#define LWRES_LINK_INIT(elt, link) \ + do { \ + (elt)->link.prev = (void *)(-1); \ + (elt)->link.next = (void *)(-1); \ + } while (0) +#define LWRES_LINK_LINKED(elt, link) ((void *)((elt)->link.prev) != (void *)(-1)) + +#define LWRES_LIST_HEAD(list) ((list).head) +#define LWRES_LIST_TAIL(list) ((list).tail) +#define LWRES_LIST_EMPTY(list) LWRES_TF((list).head == NULL) + +#define LWRES_LIST_PREPEND(list, elt, link) \ + do { \ + if ((list).head != NULL) \ + (list).head->link.prev = (elt); \ + else \ + (list).tail = (elt); \ + (elt)->link.prev = NULL; \ + (elt)->link.next = (list).head; \ + (list).head = (elt); \ + } while (0) + +#define LWRES_LIST_APPEND(list, elt, link) \ + do { \ + if ((list).tail != NULL) \ + (list).tail->link.next = (elt); \ + else \ + (list).head = (elt); \ + (elt)->link.prev = (list).tail; \ + (elt)->link.next = NULL; \ + (list).tail = (elt); \ + } while (0) + +#define LWRES_LIST_UNLINK(list, elt, link) \ + do { \ + if ((elt)->link.next != NULL) \ + (elt)->link.next->link.prev = (elt)->link.prev; \ + else \ + (list).tail = (elt)->link.prev; \ + if ((elt)->link.prev != NULL) \ + (elt)->link.prev->link.next = (elt)->link.next; \ + else \ + (list).head = (elt)->link.next; \ + (elt)->link.prev = (void *)(-1); \ + (elt)->link.next = (void *)(-1); \ + } while (0) + +#define LWRES_LIST_PREV(elt, link) ((elt)->link.prev) +#define LWRES_LIST_NEXT(elt, link) ((elt)->link.next) + +#define LWRES_LIST_INSERTBEFORE(list, before, elt, link) \ + do { \ + if ((before)->link.prev == NULL) \ + LWRES_LIST_PREPEND(list, elt, link); \ + else { \ + (elt)->link.prev = (before)->link.prev; \ + (before)->link.prev = (elt); \ + (elt)->link.prev->link.next = (elt); \ + (elt)->link.next = (before); \ + } \ + } while (0) + +#define LWRES_LIST_INSERTAFTER(list, after, elt, link) \ + do { \ + if ((after)->link.next == NULL) \ + LWRES_LIST_APPEND(list, elt, link); \ + else { \ + (elt)->link.next = (after)->link.next; \ + (after)->link.next = (elt); \ + (elt)->link.next->link.prev = (elt); \ + (elt)->link.prev = (after); \ + } \ + } while (0) + +#define LWRES_LIST_APPENDLIST(list1, list2, link) \ + do { \ + if (LWRES_LIST_EMPTY(list1)) \ + (list1) = (list2); \ + else if (!LWRES_LIST_EMPTY(list2)) { \ + (list1).tail->link.next = (list2).head; \ + (list2).head->link.prev = (list1).tail; \ + (list1).tail = (list2).tail; \ + } \ + (list2).head = NULL; \ + (list2).tail = NULL; \ + } while (0) + +#define LWRES_LIST_ENQUEUE(list, elt, link) LWRES_LIST_APPEND(list, elt, link) +#define LWRES_LIST_DEQUEUE(list, elt, link) LWRES_LIST_UNLINK(list, elt, link) + +#endif /* LWRES_LIST_H */ diff --git a/lib/lwres/include/lwres/lwres.h b/lib/lwres/include/lwres/lwres.h index 6cb1ac0e4e..e3db24bed5 100644 --- a/lib/lwres/include/lwres/lwres.h +++ b/lib/lwres/include/lwres/lwres.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -102,14 +103,14 @@ typedef struct { /* public */ - lwres_uint16_t datalength; - unsigned char *data; + lwres_uint16_t datalength; + unsigned char *data; } lwres_nooprequest_t; typedef struct { /* public */ - lwres_uint16_t datalength; - unsigned char *data; + lwres_uint16_t datalength; + unsigned char *data; } lwres_noopresponse_t; /* @@ -117,31 +118,35 @@ typedef struct { */ #define LWRES_OPCODE_GETADDRSBYNAME 0x00010001U -typedef struct { - lwres_uint32_t family; - lwres_uint16_t length; - const unsigned char *address; -} lwres_addr_t; +typedef struct lwres_addr lwres_addr_t; +typedef LWRES_LIST(lwres_addr_t) lwres_addrlist_t; + +struct lwres_addr { + lwres_uint32_t family; + lwres_uint16_t length; + const unsigned char *address; + LWRES_LINK(lwres_addr_t) link; +}; typedef struct { /* public */ - lwres_uint32_t addrtypes; - lwres_uint16_t namelen; - char *name; + lwres_uint32_t addrtypes; + lwres_uint16_t namelen; + char *name; } lwres_gabnrequest_t; typedef struct { /* public */ - lwres_uint16_t naliases; - lwres_uint16_t naddrs; - char *realname; - char **aliases; - lwres_uint16_t realnamelen; - lwres_uint16_t *aliaslen; - lwres_addr_t *addrs; + lwres_uint16_t naliases; + lwres_uint16_t naddrs; + char *realname; + char **aliases; + lwres_uint16_t realnamelen; + lwres_uint16_t *aliaslen; + lwres_addrlist_t addrs; /* if base != NULL, it will be freed when this structure is freed. */ - void *base; - size_t baselen; + void *base; + size_t baselen; } lwres_gabnresponse_t; /* @@ -150,19 +155,19 @@ typedef struct { #define LWRES_OPCODE_GETNAMEBYADDR 0x00010002U typedef struct { /* public */ - lwres_addr_t addr; + lwres_addr_t addr; } lwres_gnbarequest_t; typedef struct { /* public */ - lwres_uint16_t naliases; - char *realname; - char **aliases; - lwres_uint16_t realnamelen; - lwres_uint16_t *aliaslen; + lwres_uint16_t naliases; + char *realname; + char **aliases; + lwres_uint16_t realnamelen; + lwres_uint16_t *aliaslen; /* if base != NULL, it will be freed when this structure is freed. */ - void *base; - size_t baselen; + void *base; + size_t baselen; } lwres_gnbaresponse_t; @@ -195,8 +200,6 @@ typedef struct { lwres_uint8_t ndots; /* set to n in 'options ndots:n' */ lwres_uint8_t no_tld_query; /* non-zero if 'options no_tld_query' */ } lwres_conf_t; - - #define LWRES_ADDRTYPE_V4 0x00000001U /* ipv4 */ #define LWRES_ADDRTYPE_V6 0x00000002U /* ipv6 */ @@ -386,7 +389,7 @@ lwres_noopresponse_free(lwres_context_t *ctx, lwres_noopresponse_t **structp); */ lwres_result_t -lwres_conf_parse(const char *filename, lwres_conf_t *confdata); +lwres_conf_parse(lwres_context_t *ctx, const char *filename); /* * parses a resolv.conf-format file and puts the results into *confdata; * @@ -400,7 +403,7 @@ lwres_conf_parse(const char *filename, lwres_conf_t *confdata); */ void -lwres_conf_free(lwres_conf_t *confdata); +lwres_conf_free(lwres_context_t *ctx); /* * Returns the data in confdata to the system. * @@ -410,27 +413,34 @@ lwres_conf_free(lwres_conf_t *confdata); */ lwres_result_t -lwres_conf_print(FILE *fp, lwres_conf_t *confdata); +lwres_conf_print(lwres_context_t *ctx, FILE *fp); /* * Prints a resolv.conf-format of confdata output to fp. */ void -lwres_conf_init(lwres_context_t *ctx, lwres_conf_t *confdata); +lwres_conf_init(lwres_context_t *ctx); /* * sets all internal fields to a default state. Used to initialize a new * lwres_conf_t structure (not reset a used on). */ - void -lwres_conf_clear(lwres_conf_t *confdata); +lwres_conf_clear(lwres_context_t *ctx); /* * frees all internally allocated memory in confdata. Uses the memory * routines supplies by ctx (so that should probably be the same value as * given to lwres_conf_parse()). */ +lwres_conf_t * +lwres_conf_get(lwres_context_t *ctx); +/* + * returns a pointer to the current config structure. + * Be extremely cautions in modifying the contents of this structure; it + * needs an API to return the various bits of data, walk lists, etc. + */ + /* * Helper functions */ @@ -450,9 +460,6 @@ lwres_getnamebyaddr(lwres_context_t *ctx, lwres_uint32_t addrtype, lwres_uint16_t addrlen, const unsigned char *addr, lwres_gnbaresponse_t **structp); - - - LWRES_LANG_ENDDECLS #endif /* LWRES_LWRES_H */ diff --git a/lib/lwres/include/lwres/result.h b/lib/lwres/include/lwres/result.h index c045168467..f0ae4aa0e6 100644 --- a/lib/lwres/include/lwres/result.h +++ b/lib/lwres/include/lwres/result.h @@ -21,14 +21,14 @@ typedef unsigned int lwres_result_t; #define LWRES_R_SUCCESS 0 -#define LWRES_R_NOMEMORY -1 -#define LWRES_R_TIMEOUT -2 -#define LWRES_R_NOTFOUND -3 -#define LWRES_R_UNEXPECTEDEND -4 /* unexpected end of input */ -#define LWRES_R_FAILURE -5 /* generic failure */ -#define LWRES_R_IOERROR -6 -#define LWRES_R_NOTIMPLEMENTED -7 -#define LWRES_R_UNEXPECTED -8 -#define LWRES_R_TRAILINGDATA -9 +#define LWRES_R_NOMEMORY 1 +#define LWRES_R_TIMEOUT 2 +#define LWRES_R_NOTFOUND 3 +#define LWRES_R_UNEXPECTEDEND 4 /* unexpected end of input */ +#define LWRES_R_FAILURE 5 /* generic failure */ +#define LWRES_R_IOERROR 6 +#define LWRES_R_NOTIMPLEMENTED 7 +#define LWRES_R_UNEXPECTED 8 +#define LWRES_R_TRAILINGDATA 9 #endif /* LWRES_RESULT_H */ diff --git a/lib/lwres/lwconfig.c b/lib/lwres/lwconfig.c index 9832238b49..769e9e142a 100644 --- a/lib/lwres/lwconfig.c +++ b/lib/lwres/lwconfig.c @@ -70,23 +70,19 @@ extern const char *lwres_net_ntop(int af, const void *src, char *dst, size_t size); static lwres_result_t -lwres_conf_parsenameserver(lwres_context_t *ctx, FILE *fp, - lwres_conf_t *confdata); +lwres_conf_parsenameserver(lwres_context_t *ctx, FILE *fp); static lwres_result_t -lwres_conf_parsedomain(lwres_context_t *ctx, FILE *fp, lwres_conf_t *confdata); +lwres_conf_parsedomain(lwres_context_t *ctx, FILE *fp); static lwres_result_t -lwres_conf_parsesearch(lwres_context_t *ctx, FILE *fp, - lwres_conf_t *confdata); +lwres_conf_parsesearch(lwres_context_t *ctx, FILE *fp); static lwres_result_t -lwres_conf_parsesortlist(lwres_context_t *ctx, FILE *fp, - lwres_conf_t *confdata); +lwres_conf_parsesortlist(lwres_context_t *ctx, FILE *fp); static lwres_result_t -lwres_conf_parseoption(lwres_context_t *ctx, FILE *fp, - lwres_conf_t *confdata); +lwres_conf_parseoption(lwres_context_t *ctx, FILE *fp); static void lwres_resetaddr(lwres_context_t *ctx, lwres_addr_t *addr, int freeit); @@ -162,20 +158,20 @@ lwres_strdup(lwres_context_t *ctx, const char *str) } void -lwres_conf_init(lwres_context_t *ctx, lwres_conf_t *confdata) +lwres_conf_init(lwres_context_t *ctx) { int i; + lwres_conf_t *confdata; REQUIRE(ctx != NULL); - REQUIRE(confdata != NULL); + confdata = &ctx->confdata; - confdata->lwctx = ctx; confdata->nsnext = 0; confdata->domainname = NULL; confdata->searchnxt = 0; confdata->sortlistnxt = 0; confdata->resdebug = 0; - confdata->ndots = 0; + confdata->ndots = 1; confdata->no_tld_query = 0; for (i = 0 ; i < LWRES_CONFMAXNAMESERVERS ; i++) @@ -191,12 +187,13 @@ lwres_conf_init(lwres_context_t *ctx, lwres_conf_t *confdata) } void -lwres_conf_clear(lwres_conf_t *confdata) +lwres_conf_clear(lwres_context_t *ctx) { int i; - lwres_context_t *ctx; + lwres_conf_t *confdata; - ctx = confdata->lwctx; + REQUIRE(ctx != NULL); + confdata = &ctx->confdata; for (i = 0 ; i < confdata->nsnext ; i++) lwres_resetaddr(ctx, &confdata->nameservers[i], 1); @@ -225,16 +222,18 @@ lwres_conf_clear(lwres_conf_t *confdata) confdata->searchnxt = 0; confdata->sortlistnxt = 0; confdata->resdebug = 0; - confdata->ndots = 0; + confdata->ndots = 1; confdata->no_tld_query = 0; } static lwres_result_t -lwres_conf_parsenameserver(lwres_context_t *ctx, FILE *fp, - lwres_conf_t *confdata) +lwres_conf_parsenameserver(lwres_context_t *ctx, FILE *fp) { char word[LWRES_CONFMAXLINELEN]; int res; + lwres_conf_t *confdata; + + confdata = &ctx->confdata; if (confdata->nsnext == LWRES_CONFMAXNAMESERVERS) return (LWRES_R_FAILURE); @@ -254,10 +253,13 @@ lwres_conf_parsenameserver(lwres_context_t *ctx, FILE *fp, } static lwres_result_t -lwres_conf_parsedomain(lwres_context_t *ctx, FILE *fp, lwres_conf_t *confdata) +lwres_conf_parsedomain(lwres_context_t *ctx, FILE *fp) { char word[LWRES_CONFMAXLINELEN]; int res, i; + lwres_conf_t *confdata; + + confdata = &ctx->confdata; res = getword(fp, word, sizeof(word)); if (strlen(word) == 0) @@ -288,11 +290,13 @@ lwres_conf_parsedomain(lwres_context_t *ctx, FILE *fp, lwres_conf_t *confdata) } static lwres_result_t -lwres_conf_parsesearch(lwres_context_t *ctx, FILE *fp, - lwres_conf_t *confdata) +lwres_conf_parsesearch(lwres_context_t *ctx, FILE *fp) { int idx, delim; char word[LWRES_CONFMAXLINELEN]; + lwres_conf_t *confdata; + + confdata = &ctx->confdata; if (confdata->domainname != NULL) { /* search and domain are mutually exclusive */ @@ -360,12 +364,14 @@ lwres_create_addr(lwres_context_t *ctx, const char *buffer, lwres_addr_t *addr) } static lwres_result_t -lwres_conf_parsesortlist(lwres_context_t *ctx, FILE *fp, - lwres_conf_t *confdata) +lwres_conf_parsesortlist(lwres_context_t *ctx, FILE *fp) { int delim, res, idx; char word[LWRES_CONFMAXLINELEN]; char *p; + lwres_conf_t *confdata; + + confdata = &ctx->confdata; delim = getword(fp, word, sizeof(word)); if (strlen(word) == 0) @@ -404,17 +410,16 @@ lwres_conf_parsesortlist(lwres_context_t *ctx, FILE *fp, } static lwres_result_t -lwres_conf_parseoption(lwres_context_t *ctx, FILE *fp, - lwres_conf_t *confdata) +lwres_conf_parseoption(lwres_context_t *ctx, FILE *fp) { int delim; long ndots; char *p; char word[LWRES_CONFMAXLINELEN]; + lwres_conf_t *confdata; - UNUSED(ctx); - - REQUIRE(confdata != NULL); + REQUIRE(ctx != NULL); + confdata = &ctx->confdata; delim = getword(fp, word, sizeof(word)); if (strlen(word) == 0) @@ -442,20 +447,21 @@ lwres_conf_parseoption(lwres_context_t *ctx, FILE *fp, } lwres_result_t -lwres_conf_parse(const char *filename, lwres_conf_t *confdata) +lwres_conf_parse(lwres_context_t *ctx, const char *filename) { FILE *fp = NULL; char word[256]; int delim; lwres_result_t rval; - lwres_context_t *ctx; + lwres_conf_t *confdata; + + REQUIRE(ctx != NULL); + confdata = &ctx->confdata; REQUIRE(filename != NULL); REQUIRE(strlen(filename) > 0); REQUIRE(confdata != NULL); - ctx = confdata->lwctx; - rval = LWRES_R_FAILURE; /* Make compiler happy. */ errno = 0; if ((fp = fopen(filename, "r")) == NULL) @@ -469,15 +475,15 @@ lwres_conf_parse(const char *filename, lwres_conf_t *confdata) } if (strcmp(word, "nameserver") == 0) - rval = lwres_conf_parsenameserver(ctx, fp, confdata); + rval = lwres_conf_parsenameserver(ctx, fp); else if (strcmp(word, "domain") == 0) - rval = lwres_conf_parsedomain(ctx, fp, confdata); + rval = lwres_conf_parsedomain(ctx, fp); else if (strcmp(word, "search") == 0) - rval = lwres_conf_parsesearch(ctx, fp, confdata); + rval = lwres_conf_parsesearch(ctx, fp); else if (strcmp(word, "sortlist") == 0) - rval = lwres_conf_parsesortlist(ctx, fp, confdata); + rval = lwres_conf_parsesortlist(ctx, fp); else if (strcmp(word, "option") == 0) - rval = lwres_conf_parseoption(ctx, fp, confdata); + rval = lwres_conf_parseoption(ctx, fp); } while (rval == LWRES_R_SUCCESS); fclose(fp); @@ -486,11 +492,15 @@ lwres_conf_parse(const char *filename, lwres_conf_t *confdata) } lwres_result_t -lwres_conf_print(FILE *fp, lwres_conf_t *confdata) +lwres_conf_print(lwres_context_t *ctx, FILE *fp) { int i; char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; const char *p; + lwres_conf_t *confdata; + + REQUIRE(ctx != NULL); + confdata = &ctx->confdata; REQUIRE(confdata->nsnext <= LWRES_CONFMAXNAMESERVERS); @@ -553,3 +563,11 @@ lwres_conf_print(FILE *fp, lwres_conf_t *confdata) return (LWRES_R_SUCCESS); } + +lwres_conf_t * +lwres_conf_get(lwres_context_t *ctx) +{ + REQUIRE(ctx != NULL); + + return (&ctx->confdata); +} diff --git a/lib/lwres/lwres_gabn.c b/lib/lwres/lwres_gabn.c index 7ab6e0df17..92ddea972c 100644 --- a/lib/lwres/lwres_gabn.c +++ b/lib/lwres/lwres_gabn.c @@ -100,6 +100,7 @@ lwres_gabnresponse_render(lwres_context_t *ctx, lwres_gabnresponse_t *req, int ret; size_t payload_length; lwres_uint16_t datalen; + lwres_addr_t *addr; int x; REQUIRE(ctx != NULL); @@ -108,17 +109,22 @@ lwres_gabnresponse_render(lwres_context_t *ctx, lwres_gabnresponse_t *req, REQUIRE(b != NULL); /* naliases, naddrs */ - payload_length = sizeof(lwres_uint16_t) * 2; + payload_length = 2 * 2; /* real name encoding */ payload_length += 2 + req->realnamelen + 1; /* each alias */ for (x = 0 ; x < req->naliases ; x++) payload_length += 2 + req->aliaslen[x] + 1; /* each address */ - for (x = 0 ; x < req->naddrs ; x++) { - payload_length += sizeof(lwres_uint32_t) + sizeof(lwres_uint16_t); - payload_length += req->addrs[x].length; + x = 0; + addr = LWRES_LIST_HEAD(req->addrs); + while (addr != NULL) { + payload_length += 4 + 2; + payload_length += addr->length; + addr = LWRES_LIST_NEXT(addr, link); + x++; } + INSIST(x == req->naddrs); buflen = LWRES_LWPACKET_LENGTH + payload_length; buf = CTXMALLOC(buflen); @@ -163,14 +169,14 @@ lwres_gabnresponse_render(lwres_context_t *ctx, lwres_gabnresponse_t *req, } /* encode the addresses */ - for (x = 0 ; x < req->naddrs ; x++) { - datalen = req->addrs[x].length + sizeof(lwres_uint16_t) - + sizeof(lwres_uint32_t); + addr = LWRES_LIST_HEAD(req->addrs); + while (addr != NULL) { + datalen = addr->length + 2 + 4; INSIST(SPACE_OK(b, datalen)); - lwres_buffer_putuint32(b, req->addrs[x].family); - lwres_buffer_putuint16(b, req->addrs[x].length); - lwres_buffer_putmem(b, req->addrs[x].address, - req->addrs[x].length); + lwres_buffer_putuint32(b, addr->family); + lwres_buffer_putuint16(b, addr->length); + lwres_buffer_putmem(b, addr->address, addr->length); + addr = LWRES_LIST_NEXT(addr, link); } INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0); @@ -228,11 +234,13 @@ lwres_result_t lwres_gabnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b, lwres_lwpacket_t *pkt, lwres_gabnresponse_t **structp) { - int ret; - unsigned int x; - lwres_uint16_t naliases; - lwres_uint16_t naddrs; - lwres_gabnresponse_t *gabn; + lwres_result_t ret; + unsigned int x; + lwres_uint16_t naliases; + lwres_uint16_t naddrs; + lwres_gabnresponse_t *gabn; + lwres_addrlist_t addrlist; + lwres_addr_t *addr; REQUIRE(ctx != NULL); REQUIRE(pkt != NULL); @@ -257,7 +265,7 @@ lwres_gabnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b, return (LWRES_R_NOMEMORY); gabn->aliases = NULL; gabn->aliaslen = NULL; - gabn->addrs = NULL; + LWRES_LIST_INIT(gabn->addrs); gabn->base = NULL; gabn->naliases = naliases; @@ -277,12 +285,15 @@ lwres_gabnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b, } } - if (naddrs > 0) { - gabn->addrs = CTXMALLOC(sizeof(lwres_addr_t) * naddrs); - if (gabn->addrs == NULL) { + LWRES_LIST_INIT(addrlist); + for (x = 0 ; x < naddrs ; x++) { + addr = CTXMALLOC(sizeof(lwres_addr_t)); + if (addr == NULL) { ret = LWRES_R_NOMEMORY; goto out; } + LWRES_LINK_INIT(addr, link); + LWRES_LIST_APPEND(addrlist, addr, link); } /* @@ -303,14 +314,23 @@ lwres_gabnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b, } /* - * Pull off the addresses. + * Pull off the addresses. We already strung the linked list + * up above. */ + addr = LWRES_LIST_HEAD(addrlist); for (x = 0 ; x < gabn->naddrs ; x++) { - ret = lwres_addr_parse(b, &gabn->addrs[x]); + INSIST(addr != NULL); + ret = lwres_addr_parse(b, addr); if (ret != LWRES_R_SUCCESS) goto out; + addr = LWRES_LIST_NEXT(addr, link); } + /* + * Do the sortlist thing here. XXXMLG + */ + gabn->addrs = addrlist; + if (LWRES_BUFFER_REMAINING(b) != 0) { ret = LWRES_R_TRAILINGDATA; goto out; @@ -326,8 +346,12 @@ lwres_gabnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b, if (gabn->aliaslen != NULL) CTXFREE(gabn->aliaslen, sizeof(lwres_uint16_t) * naliases); - if (gabn->addrs != NULL) - CTXFREE(gabn->addrs, sizeof(lwres_addr_t) * naddrs); + addr = LWRES_LIST_HEAD(addrlist); + while (addr != NULL) { + LWRES_LIST_UNLINK(addrlist, addr, link); + CTXFREE(addr, sizeof(lwres_addr_t)); + addr = LWRES_LIST_HEAD(addrlist); + } CTXFREE(gabn, sizeof(lwres_gabnresponse_t)); } @@ -352,6 +376,7 @@ void lwres_gabnresponse_free(lwres_context_t *ctx, lwres_gabnresponse_t **structp) { lwres_gabnresponse_t *gabn; + lwres_addr_t *addr; REQUIRE(ctx != NULL); REQUIRE(structp != NULL && *structp != NULL); @@ -363,8 +388,12 @@ lwres_gabnresponse_free(lwres_context_t *ctx, lwres_gabnresponse_t **structp) CTXFREE(gabn->aliases, sizeof(char *) * gabn->naliases); CTXFREE(gabn->aliaslen, sizeof(lwres_uint16_t) * gabn->naliases); } - if (gabn->naddrs > 0) - CTXFREE(gabn->addrs, sizeof(lwres_addr_t) * gabn->naddrs); + addr = LWRES_LIST_HEAD(gabn->addrs); + while (addr != NULL) { + LWRES_LIST_UNLINK(gabn->addrs, addr, link); + CTXFREE(addr, sizeof(lwres_addr_t)); + addr = LWRES_LIST_HEAD(gabn->addrs); + } if (gabn->base != NULL) CTXFREE(gabn->base, gabn->baselen); CTXFREE(gabn, sizeof(lwres_gabnresponse_t)); diff --git a/lib/lwres/lwresutil.c b/lib/lwres/lwresutil.c index f395ee99e4..b478b7cd95 100644 --- a/lib/lwres/lwresutil.c +++ b/lib/lwres/lwresutil.c @@ -108,6 +108,25 @@ lwres_addr_parse(lwres_buffer_t *b, lwres_addr_t *addr) return (LWRES_R_SUCCESS); } +static void +count_dots(const char *name, unsigned int *ndots, unsigned int *last_was_dot) +{ + const char *p; + + p = name; + *ndots = 0; + *last_was_dot = 0; + + while (*p != 0) { + if (*p++ == '.') { + (*ndots)++; + *last_was_dot = 1; + } else { + *last_was_dot = 0; + } + } +} + lwres_result_t lwres_getaddrsbyname(lwres_context_t *ctx, const char *name, lwres_uint32_t addrtypes, lwres_gabnresponse_t **structp) @@ -120,12 +139,30 @@ lwres_getaddrsbyname(lwres_context_t *ctx, const char *name, lwres_lwpacket_t pkt; lwres_uint32_t serial; char *buffer; + int current_suffix; + unsigned int ndots; + unsigned int last_was_dot; + unsigned int exact_first; + char target_name[1024]; + unsigned int target_length; + unsigned int tried_exact; + unsigned int tried_search; REQUIRE(ctx != NULL); REQUIRE(name != NULL); REQUIRE(addrtypes != 0); REQUIRE(structp != NULL && *structp == NULL); + count_dots(name, &ndots, &last_was_dot); + if (last_was_dot || (ndots >= ctx->confdata.ndots)) + exact_first = 1; + else + exact_first = 0; + + current_suffix = 0; + tried_exact = 0; + tried_search = 0; + b_in.base = NULL; b_out.base = NULL; response = NULL; @@ -138,12 +175,56 @@ lwres_getaddrsbyname(lwres_context_t *ctx, const char *name, goto out; } + next_suffix: + + /* + * First, if the name ends in a dot, do an exact search. Lie and + * pretend we have already done a search. + */ + if (last_was_dot) + tried_search = 1; + + if (tried_exact && tried_search) { + ret = LWRES_R_NOTFOUND; + goto out; + } + + /* + * Try the exact search first. If this fails, try the + * search list. + */ + if (exact_first && !tried_exact) { + tried_exact = 1; + target_length = strlen(name); + if (target_length >= sizeof(target_name)) + goto next_suffix; + strcpy(target_name, name); /* strcpy is safe */ + } else { + INSIST(!tried_search); + if (current_suffix >= ctx->confdata.searchnxt) { + tried_search = 1; + exact_first = 1; + goto next_suffix; + } + + target_length = strlen(name) + + strlen(ctx->confdata.search[current_suffix]) + + 1; + if (target_length >= sizeof(target_name)) { + current_suffix++; + goto next_suffix; /* XXXMLG */ + } + sprintf(target_name, "%s.%s", /* sprintf is safe */ + name, ctx->confdata.search[current_suffix]); + current_suffix++; + } + /* * Set up our request and render it to a buffer. */ request.addrtypes = addrtypes; - request.name = (char *)name; - request.namelen = strlen(name); + request.name = target_name; + request.namelen = target_length; pkt.flags = 0; pkt.serial = serial; pkt.result = 0; @@ -184,6 +265,9 @@ lwres_getaddrsbyname(lwres_context_t *ctx, const char *name, b_out.base = NULL; b_out.length = 0; + if (pkt.result == LWRES_R_NOTFOUND) + goto next_suffix; + if (pkt.result != LWRES_R_SUCCESS) { ret = pkt.result; goto out; diff --git a/util/copyrights b/util/copyrights index b8f4573865..d01c7cb574 100644 --- a/util/copyrights +++ b/util/copyrights @@ -742,6 +742,7 @@ ./lib/lwres/include/lwres/Makefile.in MAKE 2000 ./lib/lwres/include/lwres/context.h C 2000 ./lib/lwres/include/lwres/ipv6.h C 2000 +./lib/lwres/include/lwres/list.h C 1999,2000 ./lib/lwres/include/lwres/lwbuffer.h C 2000 ./lib/lwres/include/lwres/lwpacket.h C 1999,2000 ./lib/lwres/include/lwres/lwres.h C 2000