100b67f09SDavid van Moolenbroek /* $NetBSD: lwconfig.c,v 1.6 2014/12/10 04:38:02 christos Exp $ */
200b67f09SDavid van Moolenbroek
300b67f09SDavid van Moolenbroek /*
400b67f09SDavid van Moolenbroek * Copyright (C) 2004-2008, 2011, 2012, 2014 Internet Systems Consortium, Inc. ("ISC")
500b67f09SDavid van Moolenbroek * Copyright (C) 2000-2003 Internet Software Consortium.
600b67f09SDavid van Moolenbroek *
700b67f09SDavid van Moolenbroek * Permission to use, copy, modify, and/or distribute this software for any
800b67f09SDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above
900b67f09SDavid van Moolenbroek * copyright notice and this permission notice appear in all copies.
1000b67f09SDavid van Moolenbroek *
1100b67f09SDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
1200b67f09SDavid van Moolenbroek * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1300b67f09SDavid van Moolenbroek * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
1400b67f09SDavid van Moolenbroek * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1500b67f09SDavid van Moolenbroek * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
1600b67f09SDavid van Moolenbroek * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1700b67f09SDavid van Moolenbroek * PERFORMANCE OF THIS SOFTWARE.
1800b67f09SDavid van Moolenbroek */
1900b67f09SDavid van Moolenbroek
2000b67f09SDavid van Moolenbroek /*! \file */
2100b67f09SDavid van Moolenbroek
2200b67f09SDavid van Moolenbroek /**
2300b67f09SDavid van Moolenbroek * Module for parsing resolv.conf files.
2400b67f09SDavid van Moolenbroek *
2500b67f09SDavid van Moolenbroek * lwres_conf_init() creates an empty lwres_conf_t structure for
2600b67f09SDavid van Moolenbroek * lightweight resolver context ctx.
2700b67f09SDavid van Moolenbroek *
2800b67f09SDavid van Moolenbroek * lwres_conf_clear() frees up all the internal memory used by that
2900b67f09SDavid van Moolenbroek * lwres_conf_t structure in resolver context ctx.
3000b67f09SDavid van Moolenbroek *
3100b67f09SDavid van Moolenbroek * lwres_conf_parse() opens the file filename and parses it to initialise
3200b67f09SDavid van Moolenbroek * the resolver context ctx's lwres_conf_t structure.
3300b67f09SDavid van Moolenbroek *
3400b67f09SDavid van Moolenbroek * lwres_conf_print() prints the lwres_conf_t structure for resolver
3500b67f09SDavid van Moolenbroek * context ctx to the FILE fp.
3600b67f09SDavid van Moolenbroek *
3700b67f09SDavid van Moolenbroek * \section lwconfig_return Return Values
3800b67f09SDavid van Moolenbroek *
3900b67f09SDavid van Moolenbroek * lwres_conf_parse() returns #LWRES_R_SUCCESS if it successfully read and
4000b67f09SDavid van Moolenbroek * parsed filename. It returns #LWRES_R_FAILURE if filename could not be
4100b67f09SDavid van Moolenbroek * opened or contained incorrect resolver statements.
4200b67f09SDavid van Moolenbroek *
4300b67f09SDavid van Moolenbroek * lwres_conf_print() returns #LWRES_R_SUCCESS unless an error occurred
4400b67f09SDavid van Moolenbroek * when converting the network addresses to a numeric host address
4500b67f09SDavid van Moolenbroek * string. If this happens, the function returns #LWRES_R_FAILURE.
4600b67f09SDavid van Moolenbroek *
4700b67f09SDavid van Moolenbroek * \section lwconfig_see See Also
4800b67f09SDavid van Moolenbroek *
4900b67f09SDavid van Moolenbroek * stdio(3), \link resolver resolver \endlink
5000b67f09SDavid van Moolenbroek *
5100b67f09SDavid van Moolenbroek * \section files Files
5200b67f09SDavid van Moolenbroek *
5300b67f09SDavid van Moolenbroek * /etc/resolv.conf
5400b67f09SDavid van Moolenbroek */
5500b67f09SDavid van Moolenbroek
5600b67f09SDavid van Moolenbroek #include <config.h>
5700b67f09SDavid van Moolenbroek
5800b67f09SDavid van Moolenbroek #include <assert.h>
5900b67f09SDavid van Moolenbroek #include <ctype.h>
6000b67f09SDavid van Moolenbroek #include <errno.h>
6100b67f09SDavid van Moolenbroek #include <stdlib.h>
6200b67f09SDavid van Moolenbroek #include <stdio.h>
6300b67f09SDavid van Moolenbroek #include <string.h>
6400b67f09SDavid van Moolenbroek #include <unistd.h>
6500b67f09SDavid van Moolenbroek
6600b67f09SDavid van Moolenbroek #include <lwres/lwbuffer.h>
6700b67f09SDavid van Moolenbroek #include <lwres/lwres.h>
6800b67f09SDavid van Moolenbroek #include <lwres/net.h>
6900b67f09SDavid van Moolenbroek #include <lwres/result.h>
7000b67f09SDavid van Moolenbroek #include <lwres/stdlib.h>
7100b67f09SDavid van Moolenbroek #include <lwres/string.h>
7200b67f09SDavid van Moolenbroek
7300b67f09SDavid van Moolenbroek #include "assert_p.h"
7400b67f09SDavid van Moolenbroek #include "context_p.h"
7500b67f09SDavid van Moolenbroek #include "print_p.h"
7600b67f09SDavid van Moolenbroek
7700b67f09SDavid van Moolenbroek
7800b67f09SDavid van Moolenbroek #if ! defined(NS_INADDRSZ)
7900b67f09SDavid van Moolenbroek #define NS_INADDRSZ 4
8000b67f09SDavid van Moolenbroek #endif
8100b67f09SDavid van Moolenbroek
8200b67f09SDavid van Moolenbroek #if ! defined(NS_IN6ADDRSZ)
8300b67f09SDavid van Moolenbroek #define NS_IN6ADDRSZ 16
8400b67f09SDavid van Moolenbroek #endif
8500b67f09SDavid van Moolenbroek
8600b67f09SDavid van Moolenbroek static lwres_result_t
8700b67f09SDavid van Moolenbroek lwres_conf_parsenameserver(lwres_context_t *ctx, FILE *fp);
8800b67f09SDavid van Moolenbroek
8900b67f09SDavid van Moolenbroek static lwres_result_t
9000b67f09SDavid van Moolenbroek lwres_conf_parselwserver(lwres_context_t *ctx, FILE *fp);
9100b67f09SDavid van Moolenbroek
9200b67f09SDavid van Moolenbroek static lwres_result_t
9300b67f09SDavid van Moolenbroek lwres_conf_parsedomain(lwres_context_t *ctx, FILE *fp);
9400b67f09SDavid van Moolenbroek
9500b67f09SDavid van Moolenbroek static lwres_result_t
9600b67f09SDavid van Moolenbroek lwres_conf_parsesearch(lwres_context_t *ctx, FILE *fp);
9700b67f09SDavid van Moolenbroek
9800b67f09SDavid van Moolenbroek static lwres_result_t
9900b67f09SDavid van Moolenbroek lwres_conf_parsesortlist(lwres_context_t *ctx, FILE *fp);
10000b67f09SDavid van Moolenbroek
10100b67f09SDavid van Moolenbroek static lwres_result_t
10200b67f09SDavid van Moolenbroek lwres_conf_parseoption(lwres_context_t *ctx, FILE *fp);
10300b67f09SDavid van Moolenbroek
10400b67f09SDavid van Moolenbroek static void
10500b67f09SDavid van Moolenbroek lwres_resetaddr(lwres_addr_t *addr);
10600b67f09SDavid van Moolenbroek
10700b67f09SDavid van Moolenbroek static lwres_result_t
10800b67f09SDavid van Moolenbroek lwres_create_addr(const char *buff, lwres_addr_t *addr, int convert_zero);
10900b67f09SDavid van Moolenbroek
11000b67f09SDavid van Moolenbroek static int lwresaddr2af(int lwresaddrtype);
11100b67f09SDavid van Moolenbroek
11200b67f09SDavid van Moolenbroek
11300b67f09SDavid van Moolenbroek static int
lwresaddr2af(int lwresaddrtype)11400b67f09SDavid van Moolenbroek lwresaddr2af(int lwresaddrtype)
11500b67f09SDavid van Moolenbroek {
11600b67f09SDavid van Moolenbroek int af = 0;
11700b67f09SDavid van Moolenbroek
11800b67f09SDavid van Moolenbroek switch (lwresaddrtype) {
11900b67f09SDavid van Moolenbroek case LWRES_ADDRTYPE_V4:
12000b67f09SDavid van Moolenbroek af = AF_INET;
12100b67f09SDavid van Moolenbroek break;
12200b67f09SDavid van Moolenbroek
12300b67f09SDavid van Moolenbroek case LWRES_ADDRTYPE_V6:
12400b67f09SDavid van Moolenbroek af = AF_INET6;
12500b67f09SDavid van Moolenbroek break;
12600b67f09SDavid van Moolenbroek }
12700b67f09SDavid van Moolenbroek
12800b67f09SDavid van Moolenbroek return (af);
12900b67f09SDavid van Moolenbroek }
13000b67f09SDavid van Moolenbroek
13100b67f09SDavid van Moolenbroek
13200b67f09SDavid van Moolenbroek /*!
13300b67f09SDavid van Moolenbroek * Eat characters from FP until EOL or EOF. Returns EOF or '\n'
13400b67f09SDavid van Moolenbroek */
13500b67f09SDavid van Moolenbroek static int
eatline(FILE * fp)13600b67f09SDavid van Moolenbroek eatline(FILE *fp) {
13700b67f09SDavid van Moolenbroek int ch;
13800b67f09SDavid van Moolenbroek
13900b67f09SDavid van Moolenbroek ch = fgetc(fp);
14000b67f09SDavid van Moolenbroek while (ch != '\n' && ch != EOF)
14100b67f09SDavid van Moolenbroek ch = fgetc(fp);
14200b67f09SDavid van Moolenbroek
14300b67f09SDavid van Moolenbroek return (ch);
14400b67f09SDavid van Moolenbroek }
14500b67f09SDavid van Moolenbroek
14600b67f09SDavid van Moolenbroek
14700b67f09SDavid van Moolenbroek /*!
14800b67f09SDavid van Moolenbroek * Eats white space up to next newline or non-whitespace character (of
14900b67f09SDavid van Moolenbroek * EOF). Returns the last character read. Comments are considered white
15000b67f09SDavid van Moolenbroek * space.
15100b67f09SDavid van Moolenbroek */
15200b67f09SDavid van Moolenbroek static int
eatwhite(FILE * fp)15300b67f09SDavid van Moolenbroek eatwhite(FILE *fp) {
15400b67f09SDavid van Moolenbroek int ch;
15500b67f09SDavid van Moolenbroek
15600b67f09SDavid van Moolenbroek ch = fgetc(fp);
15700b67f09SDavid van Moolenbroek while (ch != '\n' && ch != EOF && isspace((unsigned char)ch))
15800b67f09SDavid van Moolenbroek ch = fgetc(fp);
15900b67f09SDavid van Moolenbroek
16000b67f09SDavid van Moolenbroek if (ch == ';' || ch == '#')
16100b67f09SDavid van Moolenbroek ch = eatline(fp);
16200b67f09SDavid van Moolenbroek
16300b67f09SDavid van Moolenbroek return (ch);
16400b67f09SDavid van Moolenbroek }
16500b67f09SDavid van Moolenbroek
16600b67f09SDavid van Moolenbroek
16700b67f09SDavid van Moolenbroek /*!
16800b67f09SDavid van Moolenbroek * Skip over any leading whitespace and then read in the next sequence of
16900b67f09SDavid van Moolenbroek * non-whitespace characters. In this context newline is not considered
17000b67f09SDavid van Moolenbroek * whitespace. Returns EOF on end-of-file, or the character
17100b67f09SDavid van Moolenbroek * that caused the reading to stop.
17200b67f09SDavid van Moolenbroek */
17300b67f09SDavid van Moolenbroek static int
getword(FILE * fp,char * buffer,size_t size)17400b67f09SDavid van Moolenbroek getword(FILE *fp, char *buffer, size_t size) {
17500b67f09SDavid van Moolenbroek int ch;
17600b67f09SDavid van Moolenbroek char *p = buffer;
17700b67f09SDavid van Moolenbroek
17800b67f09SDavid van Moolenbroek REQUIRE(buffer != NULL);
17900b67f09SDavid van Moolenbroek REQUIRE(size > 0U);
18000b67f09SDavid van Moolenbroek
18100b67f09SDavid van Moolenbroek *p = '\0';
18200b67f09SDavid van Moolenbroek
18300b67f09SDavid van Moolenbroek ch = eatwhite(fp);
18400b67f09SDavid van Moolenbroek
18500b67f09SDavid van Moolenbroek if (ch == EOF)
18600b67f09SDavid van Moolenbroek return (EOF);
18700b67f09SDavid van Moolenbroek
18800b67f09SDavid van Moolenbroek for (;;) {
18900b67f09SDavid van Moolenbroek *p = '\0';
19000b67f09SDavid van Moolenbroek
19100b67f09SDavid van Moolenbroek if (ch == EOF || isspace((unsigned char)ch))
19200b67f09SDavid van Moolenbroek break;
19300b67f09SDavid van Moolenbroek else if ((size_t) (p - buffer) == size - 1)
19400b67f09SDavid van Moolenbroek return (EOF); /* Not enough space. */
19500b67f09SDavid van Moolenbroek
19600b67f09SDavid van Moolenbroek *p++ = (char)ch;
19700b67f09SDavid van Moolenbroek ch = fgetc(fp);
19800b67f09SDavid van Moolenbroek }
19900b67f09SDavid van Moolenbroek
20000b67f09SDavid van Moolenbroek return (ch);
20100b67f09SDavid van Moolenbroek }
20200b67f09SDavid van Moolenbroek
20300b67f09SDavid van Moolenbroek static void
lwres_resetaddr(lwres_addr_t * addr)20400b67f09SDavid van Moolenbroek lwres_resetaddr(lwres_addr_t *addr) {
20500b67f09SDavid van Moolenbroek REQUIRE(addr != NULL);
20600b67f09SDavid van Moolenbroek
20700b67f09SDavid van Moolenbroek memset(addr->address, 0, LWRES_ADDR_MAXLEN);
20800b67f09SDavid van Moolenbroek addr->family = 0;
20900b67f09SDavid van Moolenbroek addr->length = 0;
21000b67f09SDavid van Moolenbroek addr->zone = 0;
21100b67f09SDavid van Moolenbroek }
21200b67f09SDavid van Moolenbroek
21300b67f09SDavid van Moolenbroek static char *
lwres_strdup(lwres_context_t * ctx,const char * str)21400b67f09SDavid van Moolenbroek lwres_strdup(lwres_context_t *ctx, const char *str) {
21500b67f09SDavid van Moolenbroek char *p;
21600b67f09SDavid van Moolenbroek
21700b67f09SDavid van Moolenbroek REQUIRE(str != NULL);
21800b67f09SDavid van Moolenbroek REQUIRE(strlen(str) > 0U);
21900b67f09SDavid van Moolenbroek
22000b67f09SDavid van Moolenbroek p = CTXMALLOC(strlen(str) + 1);
22100b67f09SDavid van Moolenbroek if (p != NULL)
22200b67f09SDavid van Moolenbroek strcpy(p, str);
22300b67f09SDavid van Moolenbroek
22400b67f09SDavid van Moolenbroek return (p);
22500b67f09SDavid van Moolenbroek }
22600b67f09SDavid van Moolenbroek
22700b67f09SDavid van Moolenbroek /*% intializes data structure for subsequent config parsing. */
22800b67f09SDavid van Moolenbroek void
lwres_conf_init(lwres_context_t * ctx)22900b67f09SDavid van Moolenbroek lwres_conf_init(lwres_context_t *ctx) {
23000b67f09SDavid van Moolenbroek int i;
23100b67f09SDavid van Moolenbroek lwres_conf_t *confdata;
23200b67f09SDavid van Moolenbroek
23300b67f09SDavid van Moolenbroek REQUIRE(ctx != NULL);
23400b67f09SDavid van Moolenbroek confdata = &ctx->confdata;
23500b67f09SDavid van Moolenbroek
23600b67f09SDavid van Moolenbroek confdata->nsnext = 0;
23700b67f09SDavid van Moolenbroek confdata->lwnext = 0;
23800b67f09SDavid van Moolenbroek confdata->domainname = NULL;
23900b67f09SDavid van Moolenbroek confdata->searchnxt = 0;
24000b67f09SDavid van Moolenbroek confdata->sortlistnxt = 0;
24100b67f09SDavid van Moolenbroek confdata->resdebug = 0;
24200b67f09SDavid van Moolenbroek confdata->ndots = 1;
24300b67f09SDavid van Moolenbroek confdata->no_tld_query = 0;
24400b67f09SDavid van Moolenbroek
24500b67f09SDavid van Moolenbroek for (i = 0; i < LWRES_CONFMAXNAMESERVERS; i++)
24600b67f09SDavid van Moolenbroek lwres_resetaddr(&confdata->nameservers[i]);
24700b67f09SDavid van Moolenbroek
24800b67f09SDavid van Moolenbroek for (i = 0; i < LWRES_CONFMAXSEARCH; i++)
24900b67f09SDavid van Moolenbroek confdata->search[i] = NULL;
25000b67f09SDavid van Moolenbroek
25100b67f09SDavid van Moolenbroek for (i = 0; i < LWRES_CONFMAXSORTLIST; i++) {
25200b67f09SDavid van Moolenbroek lwres_resetaddr(&confdata->sortlist[i].addr);
25300b67f09SDavid van Moolenbroek lwres_resetaddr(&confdata->sortlist[i].mask);
25400b67f09SDavid van Moolenbroek }
25500b67f09SDavid van Moolenbroek }
25600b67f09SDavid van Moolenbroek
25700b67f09SDavid van Moolenbroek /*% Frees up all the internal memory used by the config data structure, returning it to the lwres_context_t. */
25800b67f09SDavid van Moolenbroek void
lwres_conf_clear(lwres_context_t * ctx)25900b67f09SDavid van Moolenbroek lwres_conf_clear(lwres_context_t *ctx) {
26000b67f09SDavid van Moolenbroek int i;
26100b67f09SDavid van Moolenbroek lwres_conf_t *confdata;
26200b67f09SDavid van Moolenbroek
26300b67f09SDavid van Moolenbroek REQUIRE(ctx != NULL);
26400b67f09SDavid van Moolenbroek confdata = &ctx->confdata;
26500b67f09SDavid van Moolenbroek
26600b67f09SDavid van Moolenbroek for (i = 0; i < confdata->nsnext; i++)
26700b67f09SDavid van Moolenbroek lwres_resetaddr(&confdata->nameservers[i]);
26800b67f09SDavid van Moolenbroek
26900b67f09SDavid van Moolenbroek if (confdata->domainname != NULL) {
27000b67f09SDavid van Moolenbroek CTXFREE(confdata->domainname,
27100b67f09SDavid van Moolenbroek strlen(confdata->domainname) + 1);
27200b67f09SDavid van Moolenbroek confdata->domainname = NULL;
27300b67f09SDavid van Moolenbroek }
27400b67f09SDavid van Moolenbroek
27500b67f09SDavid van Moolenbroek for (i = 0; i < confdata->searchnxt; i++) {
27600b67f09SDavid van Moolenbroek if (confdata->search[i] != NULL) {
27700b67f09SDavid van Moolenbroek CTXFREE(confdata->search[i],
27800b67f09SDavid van Moolenbroek strlen(confdata->search[i]) + 1);
27900b67f09SDavid van Moolenbroek confdata->search[i] = NULL;
28000b67f09SDavid van Moolenbroek }
28100b67f09SDavid van Moolenbroek }
28200b67f09SDavid van Moolenbroek
28300b67f09SDavid van Moolenbroek for (i = 0; i < LWRES_CONFMAXSORTLIST; i++) {
28400b67f09SDavid van Moolenbroek lwres_resetaddr(&confdata->sortlist[i].addr);
28500b67f09SDavid van Moolenbroek lwres_resetaddr(&confdata->sortlist[i].mask);
28600b67f09SDavid van Moolenbroek }
28700b67f09SDavid van Moolenbroek
28800b67f09SDavid van Moolenbroek confdata->nsnext = 0;
28900b67f09SDavid van Moolenbroek confdata->lwnext = 0;
29000b67f09SDavid van Moolenbroek confdata->domainname = NULL;
29100b67f09SDavid van Moolenbroek confdata->searchnxt = 0;
29200b67f09SDavid van Moolenbroek confdata->sortlistnxt = 0;
29300b67f09SDavid van Moolenbroek confdata->resdebug = 0;
29400b67f09SDavid van Moolenbroek confdata->ndots = 1;
29500b67f09SDavid van Moolenbroek confdata->no_tld_query = 0;
29600b67f09SDavid van Moolenbroek }
29700b67f09SDavid van Moolenbroek
29800b67f09SDavid van Moolenbroek static lwres_result_t
lwres_conf_parsenameserver(lwres_context_t * ctx,FILE * fp)29900b67f09SDavid van Moolenbroek lwres_conf_parsenameserver(lwres_context_t *ctx, FILE *fp) {
30000b67f09SDavid van Moolenbroek char word[LWRES_CONFMAXLINELEN];
30100b67f09SDavid van Moolenbroek int res;
30200b67f09SDavid van Moolenbroek lwres_conf_t *confdata;
30300b67f09SDavid van Moolenbroek lwres_addr_t address;
30400b67f09SDavid van Moolenbroek
30500b67f09SDavid van Moolenbroek confdata = &ctx->confdata;
30600b67f09SDavid van Moolenbroek
30700b67f09SDavid van Moolenbroek if (confdata->nsnext == LWRES_CONFMAXNAMESERVERS)
30800b67f09SDavid van Moolenbroek return (LWRES_R_SUCCESS);
30900b67f09SDavid van Moolenbroek
31000b67f09SDavid van Moolenbroek res = getword(fp, word, sizeof(word));
31100b67f09SDavid van Moolenbroek if (strlen(word) == 0U)
31200b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE); /* Nothing on line. */
31300b67f09SDavid van Moolenbroek else if (res == ' ' || res == '\t')
31400b67f09SDavid van Moolenbroek res = eatwhite(fp);
31500b67f09SDavid van Moolenbroek
31600b67f09SDavid van Moolenbroek if (res != EOF && res != '\n')
31700b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE); /* Extra junk on line. */
31800b67f09SDavid van Moolenbroek
31900b67f09SDavid van Moolenbroek res = lwres_create_addr(word, &address, 1);
32000b67f09SDavid van Moolenbroek if (res == LWRES_R_SUCCESS &&
32100b67f09SDavid van Moolenbroek ((address.family == LWRES_ADDRTYPE_V4 && ctx->use_ipv4 == 1) ||
32200b67f09SDavid van Moolenbroek (address.family == LWRES_ADDRTYPE_V6 && ctx->use_ipv6 == 1))) {
32300b67f09SDavid van Moolenbroek confdata->nameservers[confdata->nsnext++] = address;
32400b67f09SDavid van Moolenbroek }
32500b67f09SDavid van Moolenbroek
32600b67f09SDavid van Moolenbroek return (LWRES_R_SUCCESS);
32700b67f09SDavid van Moolenbroek }
32800b67f09SDavid van Moolenbroek
32900b67f09SDavid van Moolenbroek static lwres_result_t
lwres_conf_parselwserver(lwres_context_t * ctx,FILE * fp)33000b67f09SDavid van Moolenbroek lwres_conf_parselwserver(lwres_context_t *ctx, FILE *fp) {
33100b67f09SDavid van Moolenbroek char word[LWRES_CONFMAXLINELEN];
33200b67f09SDavid van Moolenbroek int res;
33300b67f09SDavid van Moolenbroek lwres_conf_t *confdata;
33400b67f09SDavid van Moolenbroek
33500b67f09SDavid van Moolenbroek confdata = &ctx->confdata;
33600b67f09SDavid van Moolenbroek
33700b67f09SDavid van Moolenbroek if (confdata->lwnext == LWRES_CONFMAXLWSERVERS)
33800b67f09SDavid van Moolenbroek return (LWRES_R_SUCCESS);
33900b67f09SDavid van Moolenbroek
34000b67f09SDavid van Moolenbroek res = getword(fp, word, sizeof(word));
34100b67f09SDavid van Moolenbroek if (strlen(word) == 0U)
34200b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE); /* Nothing on line. */
34300b67f09SDavid van Moolenbroek else if (res == ' ' || res == '\t')
34400b67f09SDavid van Moolenbroek res = eatwhite(fp);
34500b67f09SDavid van Moolenbroek
34600b67f09SDavid van Moolenbroek if (res != EOF && res != '\n')
34700b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE); /* Extra junk on line. */
34800b67f09SDavid van Moolenbroek
34900b67f09SDavid van Moolenbroek res = lwres_create_addr(word,
35000b67f09SDavid van Moolenbroek &confdata->lwservers[confdata->lwnext++], 1);
35100b67f09SDavid van Moolenbroek if (res != LWRES_R_SUCCESS)
35200b67f09SDavid van Moolenbroek return (res);
35300b67f09SDavid van Moolenbroek
35400b67f09SDavid van Moolenbroek return (LWRES_R_SUCCESS);
35500b67f09SDavid van Moolenbroek }
35600b67f09SDavid van Moolenbroek
35700b67f09SDavid van Moolenbroek static lwres_result_t
lwres_conf_parsedomain(lwres_context_t * ctx,FILE * fp)35800b67f09SDavid van Moolenbroek lwres_conf_parsedomain(lwres_context_t *ctx, FILE *fp) {
35900b67f09SDavid van Moolenbroek char word[LWRES_CONFMAXLINELEN];
36000b67f09SDavid van Moolenbroek int res, i;
36100b67f09SDavid van Moolenbroek lwres_conf_t *confdata;
36200b67f09SDavid van Moolenbroek
36300b67f09SDavid van Moolenbroek confdata = &ctx->confdata;
36400b67f09SDavid van Moolenbroek
36500b67f09SDavid van Moolenbroek res = getword(fp, word, sizeof(word));
36600b67f09SDavid van Moolenbroek if (strlen(word) == 0U)
36700b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE); /* Nothing else on line. */
36800b67f09SDavid van Moolenbroek else if (res == ' ' || res == '\t')
36900b67f09SDavid van Moolenbroek res = eatwhite(fp);
37000b67f09SDavid van Moolenbroek
37100b67f09SDavid van Moolenbroek if (res != EOF && res != '\n')
37200b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE); /* Extra junk on line. */
37300b67f09SDavid van Moolenbroek
37400b67f09SDavid van Moolenbroek if (confdata->domainname != NULL)
37500b67f09SDavid van Moolenbroek CTXFREE(confdata->domainname,
37600b67f09SDavid van Moolenbroek strlen(confdata->domainname) + 1); /* */
37700b67f09SDavid van Moolenbroek
37800b67f09SDavid van Moolenbroek /*
37900b67f09SDavid van Moolenbroek * Search and domain are mutually exclusive.
38000b67f09SDavid van Moolenbroek */
38100b67f09SDavid van Moolenbroek for (i = 0; i < LWRES_CONFMAXSEARCH; i++) {
38200b67f09SDavid van Moolenbroek if (confdata->search[i] != NULL) {
38300b67f09SDavid van Moolenbroek CTXFREE(confdata->search[i],
38400b67f09SDavid van Moolenbroek strlen(confdata->search[i])+1);
38500b67f09SDavid van Moolenbroek confdata->search[i] = NULL;
38600b67f09SDavid van Moolenbroek }
38700b67f09SDavid van Moolenbroek }
38800b67f09SDavid van Moolenbroek confdata->searchnxt = 0;
38900b67f09SDavid van Moolenbroek
39000b67f09SDavid van Moolenbroek confdata->domainname = lwres_strdup(ctx, word);
39100b67f09SDavid van Moolenbroek
39200b67f09SDavid van Moolenbroek if (confdata->domainname == NULL)
39300b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE);
39400b67f09SDavid van Moolenbroek
39500b67f09SDavid van Moolenbroek return (LWRES_R_SUCCESS);
39600b67f09SDavid van Moolenbroek }
39700b67f09SDavid van Moolenbroek
39800b67f09SDavid van Moolenbroek static lwres_result_t
lwres_conf_parsesearch(lwres_context_t * ctx,FILE * fp)39900b67f09SDavid van Moolenbroek lwres_conf_parsesearch(lwres_context_t *ctx, FILE *fp) {
40000b67f09SDavid van Moolenbroek int idx, delim;
40100b67f09SDavid van Moolenbroek char word[LWRES_CONFMAXLINELEN];
40200b67f09SDavid van Moolenbroek lwres_conf_t *confdata;
40300b67f09SDavid van Moolenbroek
40400b67f09SDavid van Moolenbroek confdata = &ctx->confdata;
40500b67f09SDavid van Moolenbroek
40600b67f09SDavid van Moolenbroek if (confdata->domainname != NULL) {
40700b67f09SDavid van Moolenbroek /*
40800b67f09SDavid van Moolenbroek * Search and domain are mutually exclusive.
40900b67f09SDavid van Moolenbroek */
41000b67f09SDavid van Moolenbroek CTXFREE(confdata->domainname,
41100b67f09SDavid van Moolenbroek strlen(confdata->domainname) + 1);
41200b67f09SDavid van Moolenbroek confdata->domainname = NULL;
41300b67f09SDavid van Moolenbroek }
41400b67f09SDavid van Moolenbroek
41500b67f09SDavid van Moolenbroek /*
41600b67f09SDavid van Moolenbroek * Remove any previous search definitions.
41700b67f09SDavid van Moolenbroek */
41800b67f09SDavid van Moolenbroek for (idx = 0; idx < LWRES_CONFMAXSEARCH; idx++) {
41900b67f09SDavid van Moolenbroek if (confdata->search[idx] != NULL) {
42000b67f09SDavid van Moolenbroek CTXFREE(confdata->search[idx],
42100b67f09SDavid van Moolenbroek strlen(confdata->search[idx])+1);
42200b67f09SDavid van Moolenbroek confdata->search[idx] = NULL;
42300b67f09SDavid van Moolenbroek }
42400b67f09SDavid van Moolenbroek }
42500b67f09SDavid van Moolenbroek confdata->searchnxt = 0;
42600b67f09SDavid van Moolenbroek
42700b67f09SDavid van Moolenbroek delim = getword(fp, word, sizeof(word));
42800b67f09SDavid van Moolenbroek if (strlen(word) == 0U)
42900b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE); /* Nothing else on line. */
43000b67f09SDavid van Moolenbroek
43100b67f09SDavid van Moolenbroek idx = 0;
43200b67f09SDavid van Moolenbroek while (strlen(word) > 0U) {
43300b67f09SDavid van Moolenbroek if (confdata->searchnxt == LWRES_CONFMAXSEARCH)
43400b67f09SDavid van Moolenbroek goto ignore; /* Too many domains. */
43500b67f09SDavid van Moolenbroek
43600b67f09SDavid van Moolenbroek confdata->search[idx] = lwres_strdup(ctx, word);
43700b67f09SDavid van Moolenbroek if (confdata->search[idx] == NULL)
43800b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE);
43900b67f09SDavid van Moolenbroek idx++;
44000b67f09SDavid van Moolenbroek confdata->searchnxt++;
44100b67f09SDavid van Moolenbroek
44200b67f09SDavid van Moolenbroek ignore:
44300b67f09SDavid van Moolenbroek if (delim == EOF || delim == '\n')
44400b67f09SDavid van Moolenbroek break;
44500b67f09SDavid van Moolenbroek else
44600b67f09SDavid van Moolenbroek delim = getword(fp, word, sizeof(word));
44700b67f09SDavid van Moolenbroek }
44800b67f09SDavid van Moolenbroek
44900b67f09SDavid van Moolenbroek return (LWRES_R_SUCCESS);
45000b67f09SDavid van Moolenbroek }
45100b67f09SDavid van Moolenbroek
45200b67f09SDavid van Moolenbroek static lwres_result_t
lwres_create_addr(const char * buffer,lwres_addr_t * addr,int convert_zero)45300b67f09SDavid van Moolenbroek lwres_create_addr(const char *buffer, lwres_addr_t *addr, int convert_zero) {
45400b67f09SDavid van Moolenbroek struct in_addr v4;
45500b67f09SDavid van Moolenbroek struct in6_addr v6;
45600b67f09SDavid van Moolenbroek char buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") +
45700b67f09SDavid van Moolenbroek sizeof("%4294967295")];
45800b67f09SDavid van Moolenbroek char *percent;
45900b67f09SDavid van Moolenbroek size_t n;
46000b67f09SDavid van Moolenbroek
46100b67f09SDavid van Moolenbroek n = strlcpy(buf, buffer, sizeof(buf));
46200b67f09SDavid van Moolenbroek if (n >= sizeof(buf))
46300b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE);
46400b67f09SDavid van Moolenbroek
46500b67f09SDavid van Moolenbroek percent = strchr(buf, '%');
46600b67f09SDavid van Moolenbroek if (percent != NULL)
46700b67f09SDavid van Moolenbroek *percent = 0;
46800b67f09SDavid van Moolenbroek
46900b67f09SDavid van Moolenbroek if (lwres_net_aton(buffer, &v4) == 1) {
47000b67f09SDavid van Moolenbroek if (convert_zero) {
47100b67f09SDavid van Moolenbroek unsigned char zeroaddress[] = {0, 0, 0, 0};
47200b67f09SDavid van Moolenbroek unsigned char loopaddress[] = {127, 0, 0, 1};
47300b67f09SDavid van Moolenbroek if (memcmp(&v4, zeroaddress, 4) == 0)
47400b67f09SDavid van Moolenbroek memmove(&v4, loopaddress, 4);
47500b67f09SDavid van Moolenbroek }
47600b67f09SDavid van Moolenbroek addr->family = LWRES_ADDRTYPE_V4;
47700b67f09SDavid van Moolenbroek addr->length = NS_INADDRSZ;
47800b67f09SDavid van Moolenbroek addr->zone = 0;
47900b67f09SDavid van Moolenbroek memmove((void *)addr->address, &v4, NS_INADDRSZ);
48000b67f09SDavid van Moolenbroek
48100b67f09SDavid van Moolenbroek } else if (lwres_net_pton(AF_INET6, buf, &v6) == 1) {
48200b67f09SDavid van Moolenbroek addr->family = LWRES_ADDRTYPE_V6;
48300b67f09SDavid van Moolenbroek addr->length = NS_IN6ADDRSZ;
48400b67f09SDavid van Moolenbroek memmove((void *)addr->address, &v6, NS_IN6ADDRSZ);
48500b67f09SDavid van Moolenbroek if (percent != NULL) {
48600b67f09SDavid van Moolenbroek unsigned long zone;
48700b67f09SDavid van Moolenbroek char *ep;
48800b67f09SDavid van Moolenbroek
48900b67f09SDavid van Moolenbroek percent++;
49000b67f09SDavid van Moolenbroek
49100b67f09SDavid van Moolenbroek #ifdef HAVE_IF_NAMETOINDEX
49200b67f09SDavid van Moolenbroek zone = if_nametoindex(percent);
49300b67f09SDavid van Moolenbroek if (zone != 0U) {
49400b67f09SDavid van Moolenbroek addr->zone = zone;
49500b67f09SDavid van Moolenbroek return (LWRES_R_SUCCESS);
49600b67f09SDavid van Moolenbroek }
49700b67f09SDavid van Moolenbroek #endif
49800b67f09SDavid van Moolenbroek zone = strtoul(percent, &ep, 10);
49900b67f09SDavid van Moolenbroek if (ep != percent && *ep == 0)
50000b67f09SDavid van Moolenbroek addr->zone = zone;
50100b67f09SDavid van Moolenbroek else
50200b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE);
50300b67f09SDavid van Moolenbroek } else
50400b67f09SDavid van Moolenbroek addr->zone = 0;
50500b67f09SDavid van Moolenbroek } else
50600b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE); /* Unrecognised format. */
50700b67f09SDavid van Moolenbroek
50800b67f09SDavid van Moolenbroek return (LWRES_R_SUCCESS);
50900b67f09SDavid van Moolenbroek }
51000b67f09SDavid van Moolenbroek
51100b67f09SDavid van Moolenbroek static lwres_result_t
lwres_conf_parsesortlist(lwres_context_t * ctx,FILE * fp)51200b67f09SDavid van Moolenbroek lwres_conf_parsesortlist(lwres_context_t *ctx, FILE *fp) {
51300b67f09SDavid van Moolenbroek int delim, res, idx;
51400b67f09SDavid van Moolenbroek char word[LWRES_CONFMAXLINELEN];
51500b67f09SDavid van Moolenbroek char *p;
51600b67f09SDavid van Moolenbroek lwres_conf_t *confdata;
51700b67f09SDavid van Moolenbroek
51800b67f09SDavid van Moolenbroek confdata = &ctx->confdata;
51900b67f09SDavid van Moolenbroek
52000b67f09SDavid van Moolenbroek delim = getword(fp, word, sizeof(word));
52100b67f09SDavid van Moolenbroek if (strlen(word) == 0U)
52200b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE); /* Empty line after keyword. */
52300b67f09SDavid van Moolenbroek
52400b67f09SDavid van Moolenbroek while (strlen(word) > 0U) {
52500b67f09SDavid van Moolenbroek if (confdata->sortlistnxt == LWRES_CONFMAXSORTLIST)
52600b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE); /* Too many values. */
52700b67f09SDavid van Moolenbroek
52800b67f09SDavid van Moolenbroek p = strchr(word, '/');
52900b67f09SDavid van Moolenbroek if (p != NULL)
53000b67f09SDavid van Moolenbroek *p++ = '\0';
53100b67f09SDavid van Moolenbroek
53200b67f09SDavid van Moolenbroek idx = confdata->sortlistnxt;
53300b67f09SDavid van Moolenbroek res = lwres_create_addr(word, &confdata->sortlist[idx].addr, 1);
53400b67f09SDavid van Moolenbroek if (res != LWRES_R_SUCCESS)
53500b67f09SDavid van Moolenbroek return (res);
53600b67f09SDavid van Moolenbroek
53700b67f09SDavid van Moolenbroek if (p != NULL) {
53800b67f09SDavid van Moolenbroek res = lwres_create_addr(p,
53900b67f09SDavid van Moolenbroek &confdata->sortlist[idx].mask,
54000b67f09SDavid van Moolenbroek 0);
54100b67f09SDavid van Moolenbroek if (res != LWRES_R_SUCCESS)
54200b67f09SDavid van Moolenbroek return (res);
54300b67f09SDavid van Moolenbroek } else {
54400b67f09SDavid van Moolenbroek /*
54500b67f09SDavid van Moolenbroek * Make up a mask.
54600b67f09SDavid van Moolenbroek */
54700b67f09SDavid van Moolenbroek confdata->sortlist[idx].mask =
54800b67f09SDavid van Moolenbroek confdata->sortlist[idx].addr;
54900b67f09SDavid van Moolenbroek
55000b67f09SDavid van Moolenbroek memset(&confdata->sortlist[idx].mask.address, 0xff,
55100b67f09SDavid van Moolenbroek confdata->sortlist[idx].addr.length);
55200b67f09SDavid van Moolenbroek }
55300b67f09SDavid van Moolenbroek
55400b67f09SDavid van Moolenbroek confdata->sortlistnxt++;
55500b67f09SDavid van Moolenbroek
55600b67f09SDavid van Moolenbroek if (delim == EOF || delim == '\n')
55700b67f09SDavid van Moolenbroek break;
55800b67f09SDavid van Moolenbroek else
55900b67f09SDavid van Moolenbroek delim = getword(fp, word, sizeof(word));
56000b67f09SDavid van Moolenbroek }
56100b67f09SDavid van Moolenbroek
56200b67f09SDavid van Moolenbroek return (LWRES_R_SUCCESS);
56300b67f09SDavid van Moolenbroek }
56400b67f09SDavid van Moolenbroek
56500b67f09SDavid van Moolenbroek static lwres_result_t
lwres_conf_parseoption(lwres_context_t * ctx,FILE * fp)56600b67f09SDavid van Moolenbroek lwres_conf_parseoption(lwres_context_t *ctx, FILE *fp) {
56700b67f09SDavid van Moolenbroek int delim;
56800b67f09SDavid van Moolenbroek long ndots;
56900b67f09SDavid van Moolenbroek char *p;
57000b67f09SDavid van Moolenbroek char word[LWRES_CONFMAXLINELEN];
57100b67f09SDavid van Moolenbroek lwres_conf_t *confdata;
57200b67f09SDavid van Moolenbroek
57300b67f09SDavid van Moolenbroek REQUIRE(ctx != NULL);
57400b67f09SDavid van Moolenbroek confdata = &ctx->confdata;
57500b67f09SDavid van Moolenbroek
57600b67f09SDavid van Moolenbroek delim = getword(fp, word, sizeof(word));
57700b67f09SDavid van Moolenbroek if (strlen(word) == 0U)
57800b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE); /* Empty line after keyword. */
57900b67f09SDavid van Moolenbroek
58000b67f09SDavid van Moolenbroek while (strlen(word) > 0U) {
58100b67f09SDavid van Moolenbroek if (strcmp("debug", word) == 0) {
58200b67f09SDavid van Moolenbroek confdata->resdebug = 1;
58300b67f09SDavid van Moolenbroek } else if (strcmp("no_tld_query", word) == 0) {
58400b67f09SDavid van Moolenbroek confdata->no_tld_query = 1;
58500b67f09SDavid van Moolenbroek } else if (strncmp("ndots:", word, 6) == 0) {
58600b67f09SDavid van Moolenbroek ndots = strtol(word + 6, &p, 10);
58700b67f09SDavid van Moolenbroek if (*p != '\0') /* Bad string. */
58800b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE);
58900b67f09SDavid van Moolenbroek if (ndots < 0 || ndots > 0xff) /* Out of range. */
59000b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE);
59100b67f09SDavid van Moolenbroek confdata->ndots = (lwres_uint8_t)ndots;
59200b67f09SDavid van Moolenbroek }
59300b67f09SDavid van Moolenbroek
59400b67f09SDavid van Moolenbroek if (delim == EOF || delim == '\n')
59500b67f09SDavid van Moolenbroek break;
59600b67f09SDavid van Moolenbroek else
59700b67f09SDavid van Moolenbroek delim = getword(fp, word, sizeof(word));
59800b67f09SDavid van Moolenbroek }
59900b67f09SDavid van Moolenbroek
60000b67f09SDavid van Moolenbroek return (LWRES_R_SUCCESS);
60100b67f09SDavid van Moolenbroek }
60200b67f09SDavid van Moolenbroek
60300b67f09SDavid van Moolenbroek /*% parses a file and fills in the data structure. */
60400b67f09SDavid van Moolenbroek lwres_result_t
lwres_conf_parse(lwres_context_t * ctx,const char * filename)60500b67f09SDavid van Moolenbroek lwres_conf_parse(lwres_context_t *ctx, const char *filename) {
60600b67f09SDavid van Moolenbroek FILE *fp = NULL;
60700b67f09SDavid van Moolenbroek char word[256];
60800b67f09SDavid van Moolenbroek lwres_result_t rval, ret;
609*03ac74edSLionel Sambuc #if !defined(NDEBUG) && defined(__minix)
61000b67f09SDavid van Moolenbroek lwres_conf_t *confdata;
611*03ac74edSLionel Sambuc #endif /* !defined(NDEBUG) && defined(__minix) */
61200b67f09SDavid van Moolenbroek int stopchar;
61300b67f09SDavid van Moolenbroek
61400b67f09SDavid van Moolenbroek REQUIRE(ctx != NULL);
615*03ac74edSLionel Sambuc #if !defined(NDEBUG) && defined(__minix)
61600b67f09SDavid van Moolenbroek confdata = &ctx->confdata;
617*03ac74edSLionel Sambuc #endif /* !defined(NDEBUG) && defined(__minix) */
61800b67f09SDavid van Moolenbroek
61900b67f09SDavid van Moolenbroek REQUIRE(filename != NULL);
62000b67f09SDavid van Moolenbroek REQUIRE(strlen(filename) > 0U);
621*03ac74edSLionel Sambuc #if !defined(NDEBUG) && defined(__minix)
62200b67f09SDavid van Moolenbroek REQUIRE(confdata != NULL);
623*03ac74edSLionel Sambuc #endif /* !defined(NDEBUG) && defined(__minix) */
62400b67f09SDavid van Moolenbroek
62500b67f09SDavid van Moolenbroek errno = 0;
62600b67f09SDavid van Moolenbroek if ((fp = fopen(filename, "r")) == NULL)
62700b67f09SDavid van Moolenbroek return (LWRES_R_NOTFOUND);
62800b67f09SDavid van Moolenbroek
62900b67f09SDavid van Moolenbroek ret = LWRES_R_SUCCESS;
63000b67f09SDavid van Moolenbroek for (;;) {
63100b67f09SDavid van Moolenbroek stopchar = getword(fp, word, sizeof(word));
63200b67f09SDavid van Moolenbroek if (stopchar == EOF) {
63300b67f09SDavid van Moolenbroek rval = LWRES_R_SUCCESS;
63400b67f09SDavid van Moolenbroek POST(rval);
63500b67f09SDavid van Moolenbroek break;
63600b67f09SDavid van Moolenbroek }
63700b67f09SDavid van Moolenbroek
63800b67f09SDavid van Moolenbroek if (strlen(word) == 0U)
63900b67f09SDavid van Moolenbroek rval = LWRES_R_SUCCESS;
64000b67f09SDavid van Moolenbroek else if (strcmp(word, "nameserver") == 0)
64100b67f09SDavid van Moolenbroek rval = lwres_conf_parsenameserver(ctx, fp);
64200b67f09SDavid van Moolenbroek else if (strcmp(word, "lwserver") == 0)
64300b67f09SDavid van Moolenbroek rval = lwres_conf_parselwserver(ctx, fp);
64400b67f09SDavid van Moolenbroek else if (strcmp(word, "domain") == 0)
64500b67f09SDavid van Moolenbroek rval = lwres_conf_parsedomain(ctx, fp);
64600b67f09SDavid van Moolenbroek else if (strcmp(word, "search") == 0)
64700b67f09SDavid van Moolenbroek rval = lwres_conf_parsesearch(ctx, fp);
64800b67f09SDavid van Moolenbroek else if (strcmp(word, "sortlist") == 0)
64900b67f09SDavid van Moolenbroek rval = lwres_conf_parsesortlist(ctx, fp);
65000b67f09SDavid van Moolenbroek else if (strcmp(word, "options") == 0)
65100b67f09SDavid van Moolenbroek rval = lwres_conf_parseoption(ctx, fp);
65200b67f09SDavid van Moolenbroek else {
65300b67f09SDavid van Moolenbroek /* unrecognised word. Ignore entire line */
65400b67f09SDavid van Moolenbroek rval = LWRES_R_SUCCESS;
65500b67f09SDavid van Moolenbroek stopchar = eatline(fp);
65600b67f09SDavid van Moolenbroek if (stopchar == EOF) {
65700b67f09SDavid van Moolenbroek break;
65800b67f09SDavid van Moolenbroek }
65900b67f09SDavid van Moolenbroek }
66000b67f09SDavid van Moolenbroek if (ret == LWRES_R_SUCCESS && rval != LWRES_R_SUCCESS)
66100b67f09SDavid van Moolenbroek ret = rval;
66200b67f09SDavid van Moolenbroek }
66300b67f09SDavid van Moolenbroek
66400b67f09SDavid van Moolenbroek fclose(fp);
66500b67f09SDavid van Moolenbroek
66600b67f09SDavid van Moolenbroek return (ret);
66700b67f09SDavid van Moolenbroek }
66800b67f09SDavid van Moolenbroek
66900b67f09SDavid van Moolenbroek /*% Prints the config data structure to the FILE. */
67000b67f09SDavid van Moolenbroek lwres_result_t
lwres_conf_print(lwres_context_t * ctx,FILE * fp)67100b67f09SDavid van Moolenbroek lwres_conf_print(lwres_context_t *ctx, FILE *fp) {
67200b67f09SDavid van Moolenbroek int i;
67300b67f09SDavid van Moolenbroek int af;
67400b67f09SDavid van Moolenbroek char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
67500b67f09SDavid van Moolenbroek char buf[sizeof("%4000000000")];
67600b67f09SDavid van Moolenbroek const char *p;
67700b67f09SDavid van Moolenbroek lwres_conf_t *confdata;
67800b67f09SDavid van Moolenbroek lwres_addr_t tmpaddr;
67900b67f09SDavid van Moolenbroek
68000b67f09SDavid van Moolenbroek REQUIRE(ctx != NULL);
68100b67f09SDavid van Moolenbroek confdata = &ctx->confdata;
68200b67f09SDavid van Moolenbroek
68300b67f09SDavid van Moolenbroek REQUIRE(confdata->nsnext <= LWRES_CONFMAXNAMESERVERS);
68400b67f09SDavid van Moolenbroek
68500b67f09SDavid van Moolenbroek for (i = 0; i < confdata->nsnext; i++) {
68600b67f09SDavid van Moolenbroek af = lwresaddr2af(confdata->nameservers[i].family);
68700b67f09SDavid van Moolenbroek
68800b67f09SDavid van Moolenbroek p = lwres_net_ntop(af, confdata->nameservers[i].address,
68900b67f09SDavid van Moolenbroek tmp, sizeof(tmp));
69000b67f09SDavid van Moolenbroek if (p != tmp)
69100b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE);
69200b67f09SDavid van Moolenbroek
69300b67f09SDavid van Moolenbroek if (af == AF_INET6 && confdata->lwservers[i].zone != 0) {
69400b67f09SDavid van Moolenbroek snprintf(buf, sizeof(buf), "%%%u",
69500b67f09SDavid van Moolenbroek confdata->nameservers[i].zone);
69600b67f09SDavid van Moolenbroek } else
69700b67f09SDavid van Moolenbroek buf[0] = 0;
69800b67f09SDavid van Moolenbroek
69900b67f09SDavid van Moolenbroek fprintf(fp, "nameserver %s%s\n", tmp, buf);
70000b67f09SDavid van Moolenbroek }
70100b67f09SDavid van Moolenbroek
70200b67f09SDavid van Moolenbroek for (i = 0; i < confdata->lwnext; i++) {
70300b67f09SDavid van Moolenbroek af = lwresaddr2af(confdata->lwservers[i].family);
70400b67f09SDavid van Moolenbroek
70500b67f09SDavid van Moolenbroek p = lwres_net_ntop(af, confdata->lwservers[i].address,
70600b67f09SDavid van Moolenbroek tmp, sizeof(tmp));
70700b67f09SDavid van Moolenbroek if (p != tmp)
70800b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE);
70900b67f09SDavid van Moolenbroek
71000b67f09SDavid van Moolenbroek if (af == AF_INET6 && confdata->lwservers[i].zone != 0) {
71100b67f09SDavid van Moolenbroek snprintf(buf, sizeof(buf), "%%%u",
71200b67f09SDavid van Moolenbroek confdata->nameservers[i].zone);
71300b67f09SDavid van Moolenbroek } else
71400b67f09SDavid van Moolenbroek buf[0] = 0;
71500b67f09SDavid van Moolenbroek
71600b67f09SDavid van Moolenbroek fprintf(fp, "lwserver %s%s\n", tmp, buf);
71700b67f09SDavid van Moolenbroek }
71800b67f09SDavid van Moolenbroek
71900b67f09SDavid van Moolenbroek if (confdata->domainname != NULL) {
72000b67f09SDavid van Moolenbroek fprintf(fp, "domain %s\n", confdata->domainname);
72100b67f09SDavid van Moolenbroek } else if (confdata->searchnxt > 0) {
72200b67f09SDavid van Moolenbroek REQUIRE(confdata->searchnxt <= LWRES_CONFMAXSEARCH);
72300b67f09SDavid van Moolenbroek
72400b67f09SDavid van Moolenbroek fprintf(fp, "search");
72500b67f09SDavid van Moolenbroek for (i = 0; i < confdata->searchnxt; i++)
72600b67f09SDavid van Moolenbroek fprintf(fp, " %s", confdata->search[i]);
72700b67f09SDavid van Moolenbroek fputc('\n', fp);
72800b67f09SDavid van Moolenbroek }
72900b67f09SDavid van Moolenbroek
73000b67f09SDavid van Moolenbroek REQUIRE(confdata->sortlistnxt <= LWRES_CONFMAXSORTLIST);
73100b67f09SDavid van Moolenbroek
73200b67f09SDavid van Moolenbroek if (confdata->sortlistnxt > 0) {
73300b67f09SDavid van Moolenbroek fputs("sortlist", fp);
73400b67f09SDavid van Moolenbroek for (i = 0; i < confdata->sortlistnxt; i++) {
73500b67f09SDavid van Moolenbroek af = lwresaddr2af(confdata->sortlist[i].addr.family);
73600b67f09SDavid van Moolenbroek
73700b67f09SDavid van Moolenbroek p = lwres_net_ntop(af,
73800b67f09SDavid van Moolenbroek confdata->sortlist[i].addr.address,
73900b67f09SDavid van Moolenbroek tmp, sizeof(tmp));
74000b67f09SDavid van Moolenbroek if (p != tmp)
74100b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE);
74200b67f09SDavid van Moolenbroek
74300b67f09SDavid van Moolenbroek fprintf(fp, " %s", tmp);
74400b67f09SDavid van Moolenbroek
74500b67f09SDavid van Moolenbroek tmpaddr = confdata->sortlist[i].mask;
74600b67f09SDavid van Moolenbroek memset(&tmpaddr.address, 0xff, tmpaddr.length);
74700b67f09SDavid van Moolenbroek
74800b67f09SDavid van Moolenbroek if (memcmp(&tmpaddr.address,
74900b67f09SDavid van Moolenbroek confdata->sortlist[i].mask.address,
75000b67f09SDavid van Moolenbroek confdata->sortlist[i].mask.length) != 0) {
75100b67f09SDavid van Moolenbroek af = lwresaddr2af(
75200b67f09SDavid van Moolenbroek confdata->sortlist[i].mask.family);
75300b67f09SDavid van Moolenbroek p = lwres_net_ntop
75400b67f09SDavid van Moolenbroek (af,
75500b67f09SDavid van Moolenbroek confdata->sortlist[i].mask.address,
75600b67f09SDavid van Moolenbroek tmp, sizeof(tmp));
75700b67f09SDavid van Moolenbroek if (p != tmp)
75800b67f09SDavid van Moolenbroek return (LWRES_R_FAILURE);
75900b67f09SDavid van Moolenbroek
76000b67f09SDavid van Moolenbroek fprintf(fp, "/%s", tmp);
76100b67f09SDavid van Moolenbroek }
76200b67f09SDavid van Moolenbroek }
76300b67f09SDavid van Moolenbroek fputc('\n', fp);
76400b67f09SDavid van Moolenbroek }
76500b67f09SDavid van Moolenbroek
76600b67f09SDavid van Moolenbroek if (confdata->resdebug)
76700b67f09SDavid van Moolenbroek fprintf(fp, "options debug\n");
76800b67f09SDavid van Moolenbroek
76900b67f09SDavid van Moolenbroek if (confdata->ndots > 0)
77000b67f09SDavid van Moolenbroek fprintf(fp, "options ndots:%d\n", confdata->ndots);
77100b67f09SDavid van Moolenbroek
77200b67f09SDavid van Moolenbroek if (confdata->no_tld_query)
77300b67f09SDavid van Moolenbroek fprintf(fp, "options no_tld_query\n");
77400b67f09SDavid van Moolenbroek
77500b67f09SDavid van Moolenbroek return (LWRES_R_SUCCESS);
77600b67f09SDavid van Moolenbroek }
77700b67f09SDavid van Moolenbroek
77800b67f09SDavid van Moolenbroek /*% Returns a pointer to the current config structure. */
77900b67f09SDavid van Moolenbroek lwres_conf_t *
lwres_conf_get(lwres_context_t * ctx)78000b67f09SDavid van Moolenbroek lwres_conf_get(lwres_context_t *ctx) {
78100b67f09SDavid van Moolenbroek REQUIRE(ctx != NULL);
78200b67f09SDavid van Moolenbroek
78300b67f09SDavid van Moolenbroek return (&ctx->confdata);
78400b67f09SDavid van Moolenbroek }
785