From 915723e4007e177b10c0e1c9d1bfe77ac2bfe853 Mon Sep 17 00:00:00 2001 From: Michael Graff Date: Sun, 12 Mar 2000 01:58:41 +0000 Subject: [PATCH] Copy addresses out, rather than keeping pointers to them from a buffer. This simplifies code at the expense of copying more. It is, however, the easiest way to get sortlist working correctly. ipv6 addresses now sort as well. --- bin/lwresd/client.c | 2 +- bin/lwresd/process_gabn.c | 4 +- lib/lwres/include/lwres/lwbuffer.h | 17 ++++++- lib/lwres/include/lwres/lwres.h | 5 +- lib/lwres/lwbuffer.c | 19 +++++++- lib/lwres/lwconfig.c | 51 ++++++++++---------- lib/lwres/lwres_gabn.c | 76 ++++++++++++++++++++++++++++-- lib/lwres/lwresutil.c | 8 ++-- 8 files changed, 143 insertions(+), 39 deletions(-) diff --git a/bin/lwresd/client.c b/bin/lwresd/client.c index 708b03c678..13d6d9a0d9 100644 --- a/bin/lwresd/client.c +++ b/bin/lwresd/client.c @@ -350,7 +350,7 @@ client_init_aliases(client_t *client) for (i = 0 ; i < LWRES_MAX_ADDRS ; i++) { client->addrs[i].family = 0; client->addrs[i].length = 0; - client->addrs[i].address = NULL; + memset(client->addrs[i].address, 0, LWRES_ADDR_MAXLEN); LWRES_LINK_INIT(&client->addrs[i], link); } } diff --git a/bin/lwresd/process_gabn.c b/bin/lwresd/process_gabn.c index c23f86bd96..5781e9f663 100644 --- a/bin/lwresd/process_gabn.c +++ b/bin/lwresd/process_gabn.c @@ -93,13 +93,13 @@ setup_addresses(client_t *client, dns_adbfind_t *find, unsigned int at) case AF_INET: sin = &ai->sockaddr->type.sin; addr->family = LWRES_ADDRTYPE_V4; - addr->address = (unsigned char *)&sin->sin_addr; + memcpy(addr->address, &sin->sin_addr, 4); addr->length = 4; break; case AF_INET6: sin6 = &ai->sockaddr->type.sin6; addr->family = LWRES_ADDRTYPE_V6; - addr->address = (unsigned char *)&sin6->sin6_addr; + memcpy(addr->address, &sin6->sin6_addr, 16); addr->length = 16; break; default: diff --git a/lib/lwres/include/lwres/lwbuffer.h b/lib/lwres/include/lwres/lwbuffer.h index 23cade5ceb..c5f1eae15c 100644 --- a/lib/lwres/include/lwres/lwbuffer.h +++ b/lib/lwres/include/lwres/lwbuffer.h @@ -369,7 +369,8 @@ lwres_buffer_putuint32(lwres_buffer_t *b, lwres_uint32_t val); */ void -lwres_buffer_putmem(lwres_buffer_t *b, const unsigned char *base, unsigned int length); +lwres_buffer_putmem(lwres_buffer_t *b, const unsigned char *base, + unsigned int length); /* * Copy 'length' bytes of memory at 'base' into 'b'. * @@ -380,6 +381,20 @@ lwres_buffer_putmem(lwres_buffer_t *b, const unsigned char *base, unsigned int l * */ +void +lwres_buffer_getmem(lwres_buffer_t *b, unsigned char *base, + unsigned int length); +/* + * Copy 'length' bytes of memory from 'b' into 'base'. + * + * Requires: + * 'b' is a valid buffer. + * + * 'base' points to at least 'length' bytes of valid memory. + * + * 'b' have at least 'length' bytes remaining. + */ + LWRES_LANG_ENDDECLS #endif /* LWRES_BUFFER_H */ diff --git a/lib/lwres/include/lwres/lwres.h b/lib/lwres/include/lwres/lwres.h index e3db24bed5..e95fc78baa 100644 --- a/lib/lwres/include/lwres/lwres.h +++ b/lib/lwres/include/lwres/lwres.h @@ -88,6 +88,7 @@ #define LWRES_UDP_PORT 921 /* XXXMLG */ #define LWRES_RECVLENGTH 2048 /* XXXMLG */ +#define LWRES_ADDR_MAXLEN 16 /* XXXMLG changing this breaks ABI */ /* * XXXMLG @@ -124,7 +125,7 @@ typedef LWRES_LIST(lwres_addr_t) lwres_addrlist_t; struct lwres_addr { lwres_uint32_t family; lwres_uint16_t length; - const unsigned char *address; + unsigned char address[LWRES_ADDR_MAXLEN]; LWRES_LINK(lwres_addr_t) link; }; @@ -174,7 +175,7 @@ typedef struct { /* * resolv.conf DATA */ - + #define LWRES_CONFMAXNAMESERVERS 3 /* max 3 "nameserver" entries */ #define LWRES_CONFMAXSEARCH 6 /* max 6 domains in "search" entry */ #define LWRES_CONFMAXLINELEN 256 /* max size of a line */ diff --git a/lib/lwres/lwbuffer.c b/lib/lwres/lwbuffer.c index 8769ad38e5..72c0bcdb46 100644 --- a/lib/lwres/lwbuffer.c +++ b/lib/lwres/lwbuffer.c @@ -256,7 +256,8 @@ lwres_buffer_putuint32(lwres_buffer_t *b, lwres_uint32_t val) } void -lwres_buffer_putmem(lwres_buffer_t *b, const unsigned char *base, unsigned int length) +lwres_buffer_putmem(lwres_buffer_t *b, const unsigned char *base, + unsigned int length) { unsigned char *cp; @@ -267,3 +268,19 @@ lwres_buffer_putmem(lwres_buffer_t *b, const unsigned char *base, unsigned int l memcpy(cp, base, length); b->used += length; } + +void +lwres_buffer_getmem(lwres_buffer_t *b, unsigned char *base, + unsigned int length) +{ + unsigned char *cp; + + REQUIRE(LWRES_BUFFER_VALID(b)); + REQUIRE(b->used - b->current >= length); + + cp = b->base; + cp += b->current; + b->current += length; + + memcpy(base, cp, length); +} diff --git a/lib/lwres/lwconfig.c b/lib/lwres/lwconfig.c index 769e9e142a..2b5cd1824a 100644 --- a/lib/lwres/lwconfig.c +++ b/lib/lwres/lwconfig.c @@ -85,11 +85,10 @@ static lwres_result_t lwres_conf_parseoption(lwres_context_t *ctx, FILE *fp); static void -lwres_resetaddr(lwres_context_t *ctx, lwres_addr_t *addr, int freeit); +lwres_resetaddr(lwres_addr_t *addr); static lwres_result_t -lwres_create_addr(lwres_context_t *ctx, const char *buff, - lwres_addr_t *addr); +lwres_create_addr(const char *buff, lwres_addr_t *addr); /* * Skip over any leading whitespace and then read in the next sequence of @@ -130,14 +129,11 @@ getword(FILE *fp, char *buffer, size_t size) } static void -lwres_resetaddr(lwres_context_t *ctx, lwres_addr_t *addr, int freeit) +lwres_resetaddr(lwres_addr_t *addr) { REQUIRE(addr != NULL); - if (freeit && addr->address != NULL) - CTXFREE((void *)addr->address, addr->length); - - addr->address = NULL; + memset(addr->address, 0, LWRES_ADDR_MAXLEN); addr->family = 0; addr->length = 0; } @@ -175,14 +171,14 @@ lwres_conf_init(lwres_context_t *ctx) confdata->no_tld_query = 0; for (i = 0 ; i < LWRES_CONFMAXNAMESERVERS ; i++) - lwres_resetaddr(NULL, &confdata->nameservers[i], 0); + lwres_resetaddr(&confdata->nameservers[i]); for (i = 0 ; i < LWRES_CONFMAXSEARCH ; i++) confdata->search[i] = NULL; for (i = 0 ; i < LWRES_CONFMAXSORTLIST ; i++) { - lwres_resetaddr(NULL, &confdata->sortlist[i].addr, 0); - lwres_resetaddr(NULL, &confdata->sortlist[i].mask, 0); + lwres_resetaddr(&confdata->sortlist[i].addr); + lwres_resetaddr(&confdata->sortlist[i].mask); } } @@ -196,7 +192,7 @@ lwres_conf_clear(lwres_context_t *ctx) confdata = &ctx->confdata; for (i = 0 ; i < confdata->nsnext ; i++) - lwres_resetaddr(ctx, &confdata->nameservers[i], 1); + lwres_resetaddr(&confdata->nameservers[i]); if (confdata->domainname != NULL) { CTXFREE(confdata->domainname, @@ -213,8 +209,8 @@ lwres_conf_clear(lwres_context_t *ctx) } for (i = 0 ; i < LWRES_CONFMAXSORTLIST ; i++) { - lwres_resetaddr(ctx, &confdata->sortlist[i].addr, 1); - lwres_resetaddr(ctx, &confdata->sortlist[i].mask, 1); + lwres_resetaddr(&confdata->sortlist[i].addr); + lwres_resetaddr(&confdata->sortlist[i].mask); } confdata->nsnext = 0; @@ -244,7 +240,7 @@ lwres_conf_parsenameserver(lwres_context_t *ctx, FILE *fp) else if (res != EOF && res != '\n') return (LWRES_R_FAILURE); /* extra junk on line */ - res = lwres_create_addr(ctx, word, + res = lwres_create_addr(word, &confdata->nameservers[confdata->nsnext++]); if (res != LWRES_R_SUCCESS) return (res); @@ -340,25 +336,26 @@ lwres_conf_parsesearch(lwres_context_t *ctx, FILE *fp) } static lwres_result_t -lwres_create_addr(lwres_context_t *ctx, const char *buffer, lwres_addr_t *addr) +lwres_create_addr(const char *buffer, lwres_addr_t *addr) { unsigned char addrbuff[NS_IN6ADDRSZ]; + unsigned int len; if (lwres_net_pton(AF_INET, buffer, &addrbuff) == 1) { - addr->family = AF_INET; + addr->family = LWRES_ADDRTYPE_V4; addr->length = NS_INADDRSZ; - addr->address = CTXMALLOC(NS_INADDRSZ); + len = 4; #if defined(AF_INET6) } else if (lwres_net_pton(AF_INET6, buffer, &addrbuff) == 1) { - addr->family = AF_INET6; + addr->family = LWRES_ADDRTYPE_V6; addr->length = NS_IN6ADDRSZ; - addr->address = CTXMALLOC(NS_IN6ADDRSZ); + len = 16; #endif } else { return (LWRES_R_FAILURE); /* unrecongnised format */ } - memcpy((void *)addr->address, addrbuff, 4); + memcpy((void *)addr->address, addrbuff, len); return (LWRES_R_SUCCESS); } @@ -386,16 +383,22 @@ lwres_conf_parsesortlist(lwres_context_t *ctx, FILE *fp) *p++ = '\0'; idx = confdata->sortlistnxt; - res = lwres_create_addr(ctx, word, - &confdata->sortlist[idx].addr); + res = lwres_create_addr(word, &confdata->sortlist[idx].addr); if (res != LWRES_R_SUCCESS) return (res); if (p != NULL) { - res = lwres_create_addr(ctx, p, + res = lwres_create_addr(p, &confdata->sortlist[idx].mask); if (res != LWRES_R_SUCCESS) return (res); + } else { + /* Make up a mask. */ + confdata->sortlist[idx].mask = + confdata->sortlist[idx].addr; + + memset(&confdata->sortlist[idx].mask, 0xff, + confdata->sortlist[idx].addr.length); } confdata->sortlistnxt++; diff --git a/lib/lwres/lwres_gabn.c b/lib/lwres/lwres_gabn.c index 92ddea972c..be0588b49e 100644 --- a/lib/lwres/lwres_gabn.c +++ b/lib/lwres/lwres_gabn.c @@ -29,6 +29,71 @@ #include "context_p.h" #include "assert_p.h" +static void +lwres_sortlist(lwres_context_t *ctx, lwres_addrlist_t *inlist, + lwres_addrlist_t *outlist) +{ + unsigned int i, x; + lwres_conf_t *confdata; + unsigned char mask[LWRES_ADDR_MAXLEN]; + unsigned char sortaddr[LWRES_ADDR_MAXLEN]; + unsigned char listaddr[LWRES_ADDR_MAXLEN]; + unsigned int length; + lwres_addr_t *addr; + lwres_addr_t *nextaddr; + + confdata = &ctx->confdata; + + /* + * If there is no sortlist, we're done. + */ + if (confdata->sortlistnxt == 0) { + *outlist = *inlist; + return; + } + + LWRES_LIST_INIT(*outlist); + + for (i = 0 ; i < confdata->sortlistnxt ; i++) { + length = confdata->sortlist[i].addr.length; + INSIST(length == confdata->sortlist[i].mask.length); + memcpy(mask, confdata->sortlist[i].mask.address, length); + memcpy(sortaddr, confdata->sortlist[i].addr.address, length); + for (x = 0 ; x < length ; x++) + sortaddr[x] &= mask[x]; + + addr = LWRES_LIST_HEAD(*inlist); + while (addr != NULL) { + nextaddr = LWRES_LIST_NEXT(addr, link); + + if (addr->family != confdata->sortlist[i].addr.family) + goto next; + + memcpy(listaddr, addr->address, length); + for (x = 0 ; x < length ; x++) + listaddr[x] &= mask[x]; + + if (memcmp(listaddr, sortaddr, length) == 0) { + LWRES_LIST_UNLINK(*inlist, addr, link); + LWRES_LIST_APPEND(*outlist, addr, link); + } + + next: + addr = nextaddr; + } + } + + /* + * Get everything that doesn't match any sortlist lines. + */ + addr = LWRES_LIST_HEAD(*inlist); + while (addr != NULL) { + LWRES_LIST_UNLINK(*inlist, addr, link); + LWRES_LIST_APPEND(*outlist, addr, link); + addr = LWRES_LIST_HEAD(*inlist); + } +} + lwres_result_t lwres_gabnrequest_render(lwres_context_t *ctx, lwres_gabnrequest_t *req, lwres_lwpacket_t *pkt, lwres_buffer_t *b) @@ -326,16 +391,17 @@ lwres_gabnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b, 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; } + /* + * Do the sortlist thing here. After this is done, "addrlist" + * must NOT be used again, since it will be very very bogus. + */ + lwres_sortlist(ctx, &addrlist, &gabn->addrs); + *structp = gabn; return (LWRES_R_SUCCESS); diff --git a/lib/lwres/lwresutil.c b/lib/lwres/lwresutil.c index b478b7cd95..9a88390c57 100644 --- a/lib/lwres/lwresutil.c +++ b/lib/lwres/lwresutil.c @@ -102,8 +102,10 @@ lwres_addr_parse(lwres_buffer_t *b, lwres_addr_t *addr) if (!SPACE_REMAINING(b, addr->length)) return (LWRES_R_UNEXPECTEDEND); - addr->address = b->base + b->current; - lwres_buffer_forward(b, addr->length); + if (addr->length > LWRES_ADDR_MAXLEN) + return (LWRES_R_FAILURE); + + lwres_buffer_getmem(b, addr->address, addr->length); return (LWRES_R_SUCCESS); } @@ -335,7 +337,7 @@ lwres_getnamebyaddr(lwres_context_t *ctx, lwres_uint32_t addrtype, */ request.addr.family = addrtype; request.addr.length = addrlen; - request.addr.address = addr; + memcpy(request.addr.address, addr, addrlen); pkt.flags = 0; pkt.serial = serial; pkt.result = 0;