diff --git a/bin/named/lwresd.c b/bin/named/lwresd.c index bd6e7da3c5..d7277370e7 100644 --- a/bin/named/lwresd.c +++ b/bin/named/lwresd.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lwresd.c,v 1.16 2000/10/04 23:18:55 bwelling Exp $ */ +/* $Id: lwresd.c,v 1.17 2000/10/05 22:27:46 bwelling Exp $ */ /* * Main program for the Lightweight Resolver Daemon. @@ -219,11 +219,31 @@ ns_lwresd_parseresolvconf(isc_mem_t *mctx, dns_c_ctx_t **ctxp) { if (result != ISC_R_SUCCESS) goto cleanup; - localhost.s_addr = htonl(INADDR_LOOPBACK); port = lwresd_g_listenport; if (port == 0) port = LWRES_UDP_PORT; - isc_sockaddr_fromin(&sa, &localhost, port); + + if (lwc->lwnext == 0) { + localhost.s_addr = htonl(INADDR_LOOPBACK); + isc_sockaddr_fromin(&sa, &localhost, port); + } else { + if (lwc->lwservers[0].family != LWRES_ADDRTYPE_V4 && + lwc->lwservers[0].family != LWRES_ADDRTYPE_V6) + { + result = ISC_R_FAMILYNOSUPPORT; + goto cleanup; + } + + if (lwc->lwservers[0].family == LWRES_ADDRTYPE_V4) { + struct in_addr ina; + memcpy(&ina.s_addr, lwc->lwservers[0].address, 4); + isc_sockaddr_fromin(&sa, &ina, port); + } else { + struct in6_addr ina6; + memcpy(&ina6.s6_addr, lwc->lwservers[0].address, 16); + isc_sockaddr_fromin6(&sa, &ina6, port); + } + } result = dns_c_iplist_new(mctx, 1, &locallist); if (result != ISC_R_SUCCESS) @@ -499,9 +519,6 @@ add_listener(isc_mem_t *mctx, ns_lwreslistener_t **listenerp, NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, "couldn't add lwres channel %s: %s", socktext, isc_result_totext(result)); - - dns_view_detach(&listener->view); - *listenerp = NULL; } } diff --git a/lib/lwres/context.c b/lib/lwres/context.c index 364395a5f4..59ccef27e9 100644 --- a/lib/lwres/context.c +++ b/lib/lwres/context.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: context.c,v 1.29 2000/08/22 16:20:19 gson Exp $ */ +/* $Id: context.c,v 1.30 2000/10/05 22:27:47 bwelling Exp $ */ #include @@ -46,6 +46,7 @@ #endif lwres_uint16_t lwres_udp_port = LWRES_UDP_PORT; +const char *lwres_resolv_conf = LWRES_RESOLV_CONF; static void * lwres_malloc(void *, size_t); @@ -65,6 +66,7 @@ lwres_context_create(lwres_context_t **contextp, void *arg, lwres_context_t *ctx; REQUIRE(contextp != NULL && *contextp == NULL); + UNUSED(flags); /* * If we were not given anything special to use, use our own @@ -92,9 +94,6 @@ lwres_context_create(lwres_context_t **contextp, void *arg, ctx->timeout = LWRES_DEFAULT_TIMEOUT; ctx->serial = time(NULL); /* XXXMLG or BEW */ - if ((flags & LWRES_CONTEXT_SERVERMODE) == 0) - (void)context_connect(ctx); /* XXXMLG */ - /* * Init resolv.conf bits. */ @@ -177,19 +176,49 @@ static lwres_result_t context_connect(lwres_context_t *ctx) { int s; int ret; - struct sockaddr_in localhost; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr *sa; + socklen_t salen; int flags; + int domain; - memset(&localhost, 0, sizeof(localhost)); - localhost.sin_family = AF_INET; - localhost.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - localhost.sin_port = htons(lwres_udp_port); + if (ctx->confdata.lwnext != 0) { + memcpy(&ctx->address, &ctx->confdata.lwservers[0], + sizeof(lwres_addr_t)); + LWRES_LINK_INIT(&ctx->address, link); + } else { + char localhost[] = "127.0.0.1"; + lwres_buffer_t b; + lwres_buffer_init(&b, localhost, sizeof(localhost)); + lwres_buffer_add(&b, strlen(localhost)); + (void)lwres_addr_parse(&b, &ctx->address); + } - s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (ctx->address.family == LWRES_ADDRTYPE_V4) { + memcpy(&sin.sin_addr, ctx->address.address, + sizeof(sin.sin_addr)); + sin.sin_port = htons(lwres_udp_port); + sin.sin_family = AF_INET; + sa = (struct sockaddr *)&sin; + salen = sizeof(sin); + domain = PF_INET; + } else if (ctx->address.family == LWRES_ADDRTYPE_V6) { + memcpy(&sin6.sin6_addr, ctx->address.address, + sizeof(sin6.sin6_addr)); + sin6.sin6_port = htons(lwres_udp_port); + sin6.sin6_family = AF_INET6; + sa = (struct sockaddr *)&sin6; + salen = sizeof(sin6); + domain = PF_INET6; + } else + return (LWRES_R_IOERROR); + + s = socket(domain, SOCK_DGRAM, IPPROTO_UDP); if (s < 0) return (LWRES_R_IOERROR); - ret = connect(s, (struct sockaddr *)&localhost, sizeof(localhost)); + ret = connect(s, sa, salen); if (ret != 0) { close(s); return (LWRES_R_IOERROR); @@ -215,6 +244,14 @@ lwres_result_t lwres_context_send(lwres_context_t *ctx, void *sendbase, int sendlen) { int ret; + lwres_result_t lwresult; + + if (ctx->sock == -1) { + lwresult = context_connect(ctx); + if (lwresult != LWRES_R_SUCCESS) + return (lwresult); + } + ret = sendto(ctx->sock, sendbase, sendlen, 0, NULL, 0); if (ret < 0) return (LWRES_R_IOERROR); @@ -231,17 +268,25 @@ lwres_context_recv(lwres_context_t *ctx, { LWRES_SOCKADDR_LEN_T fromlen; struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr *sa; int ret; - fromlen = sizeof(sin); + if (ctx->address.family == LWRES_ADDRTYPE_V4) { + sa = (struct sockaddr *)&sin; + fromlen = sizeof(sin); + } else { + sa = (struct sockaddr *)&sin6; + fromlen = sizeof(sin6); + } + /* * The address of fromlen is cast to void * to shut up compiler * warnings, namely on systems that have the sixth parameter * prototyped as a signed int when LWRES_SOCKADDR_LEN_T is * defined as unsigned. */ - ret = recvfrom(ctx->sock, recvbase, recvlen, 0, - (struct sockaddr *)&sin, (void *)&fromlen); + ret = recvfrom(ctx->sock, recvbase, recvlen, 0, sa, (void *)&fromlen); if (ret < 0) return (LWRES_R_IOERROR); @@ -251,9 +296,19 @@ lwres_context_recv(lwres_context_t *ctx, * wait for another packet. This can happen if an old result * comes in, or if someone is sending us random stuff. */ - if (sin.sin_addr.s_addr != htonl(INADDR_LOOPBACK) - || sin.sin_port != htons(lwres_udp_port)) - return (LWRES_R_RETRY); + if (ctx->address.family == LWRES_ADDRTYPE_V4) { + if (fromlen != sizeof(sin) + || memcmp(&sin.sin_addr, ctx->address.address, + sizeof(sin.sin_addr)) != 0 + || sin.sin_port != htons(lwres_udp_port)) + return (LWRES_R_RETRY); + } else { + if (fromlen != sizeof(sin6) + || memcmp(&sin6.sin6_addr, ctx->address.address, + sizeof(sin6.sin6_addr)) != 0 + || sin6.sin6_port != htons(lwres_udp_port)) + return (LWRES_R_RETRY); + } if (recvd_len != NULL) *recvd_len = ret; diff --git a/lib/lwres/context_p.h b/lib/lwres/context_p.h index ff88b24bd1..a96a57638f 100644 --- a/lib/lwres/context_p.h +++ b/lib/lwres/context_p.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: context_p.h,v 1.10 2000/08/01 01:32:11 tale Exp $ */ +/* $Id: context_p.h,v 1.11 2000/10/05 22:27:49 bwelling Exp $ */ #ifndef LWRES_CONTEXT_P_H #define LWRES_CONTEXT_P_H 1 @@ -41,6 +41,7 @@ struct lwres_context { * For network I/O. */ int sock; /* socket to send on */ + lwres_addr_t address; /* address to send to */ /* * Function pointers for allocating memory. diff --git a/lib/lwres/getaddrinfo.c b/lib/lwres/getaddrinfo.c index 6405d55dd4..e1fc87e58e 100644 --- a/lib/lwres/getaddrinfo.c +++ b/lib/lwres/getaddrinfo.c @@ -19,7 +19,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: getaddrinfo.c,v 1.32 2000/09/19 21:21:59 bwelling Exp $ */ +/* $Id: getaddrinfo.c,v 1.33 2000/10/05 22:27:50 bwelling Exp $ */ #include @@ -463,7 +463,7 @@ add_ipv4(const char *hostname, int flags, struct addrinfo **aip, lwres = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0); if (lwres != 0) ERR(EAI_FAIL); - (void) lwres_conf_parse(lwrctx, "/etc/resolv.conf"); + (void) lwres_conf_parse(lwrctx, lwres_resolv_conf); if (hostname == NULL && (flags & AI_PASSIVE) == 0) { ai = ai_clone(*aip, AF_INET); if (ai == NULL) { @@ -523,7 +523,7 @@ add_ipv6(const char *hostname, int flags, struct addrinfo **aip, lwres = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0); if (lwres != 0) ERR(EAI_FAIL); - (void) lwres_conf_parse(lwrctx, "/etc/resolv.conf"); + (void) lwres_conf_parse(lwrctx, lwres_resolv_conf); if (hostname == NULL && (flags & AI_PASSIVE) == 0) { ai = ai_clone(*aip, AF_INET6); diff --git a/lib/lwres/getipnode.c b/lib/lwres/getipnode.c index 53f0866185..90565259a9 100644 --- a/lib/lwres/getipnode.c +++ b/lib/lwres/getipnode.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: getipnode.c,v 1.25 2000/08/01 01:32:15 tale Exp $ */ +/* $Id: getipnode.c,v 1.26 2000/10/05 22:27:51 bwelling Exp $ */ #include @@ -166,7 +166,7 @@ lwres_getipnodebyname(const char *name, int af, int flags, int *error_num) { *error_num = NO_RECOVERY; goto cleanup; } - (void) lwres_conf_parse(lwrctx, "/etc/resolv.conf"); + (void) lwres_conf_parse(lwrctx, lwres_resolv_conf); tmp_err = NO_RECOVERY; if (have_v6 && af == AF_INET6) { @@ -279,7 +279,7 @@ lwres_getipnodebyaddr(const void *src, size_t len, int af, int *error_num) { cp += 12; n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0); if (n == LWRES_R_SUCCESS) - (void) lwres_conf_parse(lwrctx, "/etc/resolv.conf"); + (void) lwres_conf_parse(lwrctx, lwres_resolv_conf); if (n == LWRES_R_SUCCESS) n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V4, INADDRSZ, cp, &by); @@ -323,7 +323,7 @@ lwres_getipnodebyaddr(const void *src, size_t len, int af, int *error_num) { n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0); if (n == LWRES_R_SUCCESS) - (void) lwres_conf_parse(lwrctx, "/etc/resolv.conf"); + (void) lwres_conf_parse(lwrctx, lwres_resolv_conf); if (n == LWRES_R_SUCCESS) n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V6, IN6ADDRSZ, src, &by); diff --git a/lib/lwres/getnameinfo.c b/lib/lwres/getnameinfo.c index ff0e0f570d..901b8ea6bd 100644 --- a/lib/lwres/getnameinfo.c +++ b/lib/lwres/getnameinfo.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: getnameinfo.c,v 1.25 2000/08/01 01:32:16 tale Exp $ */ +/* $Id: getnameinfo.c,v 1.26 2000/10/05 22:27:52 bwelling Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -255,7 +255,7 @@ lwres_getnameinfo(const struct sockaddr *sa, size_t salen, char *host, n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0); if (n == 0) - (void) lwres_conf_parse(lwrctx, "/etc/resolv.conf"); + (void) lwres_conf_parse(lwrctx, lwres_resolv_conf); if (n == 0) n = lwres_getnamebyaddr(lwrctx, lwf, afd->a_addrlen, diff --git a/lib/lwres/include/lwres/lwres.h b/lib/lwres/include/lwres/lwres.h index 9e05d30885..764c8a7d3c 100644 --- a/lib/lwres/include/lwres/lwres.h +++ b/lib/lwres/include/lwres/lwres.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lwres.h,v 1.43 2000/08/01 01:32:41 tale Exp $ */ +/* $Id: lwres.h,v 1.44 2000/10/05 22:27:54 bwelling Exp $ */ #ifndef LWRES_LWRES_H #define LWRES_LWRES_H 1 @@ -80,6 +80,7 @@ #define LWRES_UDP_PORT 921 /* XXXMLG */ #define LWRES_RECVLENGTH 4096 /* XXXMLG */ #define LWRES_ADDR_MAXLEN 16 /* changing this breaks ABI */ +#define LWRES_RESOLV_CONF "/etc/resolv.conf" /* * XXXMLG @@ -194,6 +195,7 @@ typedef struct { */ #define LWRES_CONFMAXNAMESERVERS 3 /* max 3 "nameserver" entries */ +#define LWRES_CONFMAXLWSERVERS 1 /* max 1 "lwserver" entry */ #define LWRES_CONFMAXSEARCH 8 /* max 8 domains in "search" entry */ #define LWRES_CONFMAXLINELEN 256 /* max size of a line */ #define LWRES_CONFMAXSORTLIST 10 @@ -202,6 +204,9 @@ typedef struct { lwres_addr_t nameservers[LWRES_CONFMAXNAMESERVERS]; lwres_uint8_t nsnext; /* index for next free slot */ + lwres_addr_t lwservers[LWRES_CONFMAXLWSERVERS]; + lwres_uint8_t lwnext; /* index for next free slot */ + char *domainname; char *search[LWRES_CONFMAXSEARCH]; @@ -232,6 +237,8 @@ LWRES_LANG_BEGINDECLS */ extern lwres_uint16_t lwres_udp_port; +extern const char *lwres_resolv_conf; + lwres_result_t lwres_gabnrequest_render(lwres_context_t *ctx, lwres_gabnrequest_t *req, lwres_lwpacket_t *pkt, lwres_buffer_t *b); diff --git a/lib/lwres/lwconfig.c b/lib/lwres/lwconfig.c index 29ceaf1865..9e577c16a5 100644 --- a/lib/lwres/lwconfig.c +++ b/lib/lwres/lwconfig.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lwconfig.c,v 1.24 2000/08/01 01:32:20 tale Exp $ */ +/* $Id: lwconfig.c,v 1.25 2000/10/05 22:27:53 bwelling Exp $ */ /*** *** Module for parsing resolv.conf files. @@ -76,6 +76,9 @@ extern const char *lwres_net_ntop(int af, const void *src, char *dst, static lwres_result_t lwres_conf_parsenameserver(lwres_context_t *ctx, FILE *fp); +static lwres_result_t +lwres_conf_parselwserver(lwres_context_t *ctx, FILE *fp); + static lwres_result_t lwres_conf_parsedomain(lwres_context_t *ctx, FILE *fp); @@ -219,6 +222,7 @@ lwres_conf_init(lwres_context_t *ctx) { confdata = &ctx->confdata; confdata->nsnext = 0; + confdata->lwnext = 0; confdata->domainname = NULL; confdata->searchnxt = 0; confdata->sortlistnxt = 0; @@ -269,6 +273,7 @@ lwres_conf_clear(lwres_context_t *ctx) { } confdata->nsnext = 0; + confdata->lwnext = 0; confdata->domainname = NULL; confdata->searchnxt = 0; confdata->sortlistnxt = 0; @@ -305,6 +310,34 @@ lwres_conf_parsenameserver(lwres_context_t *ctx, FILE *fp) { return (LWRES_R_SUCCESS); } +static lwres_result_t +lwres_conf_parselwserver(lwres_context_t *ctx, FILE *fp) { + char word[LWRES_CONFMAXLINELEN]; + int res; + lwres_conf_t *confdata; + + confdata = &ctx->confdata; + + if (confdata->lwnext == LWRES_CONFMAXLWSERVERS) + return (LWRES_R_SUCCESS); + + res = getword(fp, word, sizeof(word)); + if (strlen(word) == 0) + return (LWRES_R_FAILURE); /* Nothing on line. */ + else if (res == ' ' || res == '\t') + res = eatwhite(fp); + + if (res != EOF && res != '\n') + return (LWRES_R_FAILURE); /* Extra junk on line. */ + + res = lwres_create_addr(word, + &confdata->lwservers[confdata->lwnext++]); + if (res != LWRES_R_SUCCESS) + return (res); + + return (LWRES_R_SUCCESS); +} + static lwres_result_t lwres_conf_parsedomain(lwres_context_t *ctx, FILE *fp) { char word[LWRES_CONFMAXLINELEN]; @@ -544,6 +577,8 @@ lwres_conf_parse(lwres_context_t *ctx, const char *filename) { rval = LWRES_R_SUCCESS; else if (strcmp(word, "nameserver") == 0) rval = lwres_conf_parsenameserver(ctx, fp); + else if (strcmp(word, "lwserver") == 0) + rval = lwres_conf_parselwserver(ctx, fp); else if (strcmp(word, "domain") == 0) rval = lwres_conf_parsedomain(ctx, fp); else if (strcmp(word, "search") == 0) @@ -594,6 +629,17 @@ lwres_conf_print(lwres_context_t *ctx, FILE *fp) { fprintf(fp, "nameserver %s\n", tmp); } + for (i = 0 ; i < confdata->lwnext ; i++) { + af = lwresaddr2af(confdata->lwservers[i].family); + + p = lwres_net_ntop(af, confdata->lwservers[i].address, + tmp, sizeof(tmp)); + if (p != tmp) + return (LWRES_R_FAILURE); + + fprintf(fp, "lwserver %s\n", tmp); + } + if (confdata->domainname != NULL) { fprintf(fp, "domain %s\n", confdata->domainname); } else if (confdata->searchnxt > 0) {