resconf.c revision 5fa46bc91672ef5737aee6f99763161511566c24
/*
* Copyright (C) 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
*
* 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 ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC 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.
*/
/* $Id$ */
/*! \file resconf.c */
/**
* Module for parsing resolv.conf files (largely derived from lwconfig.c).
*
* irs_resconf_load() opens the file filename and parses it to initialize
* the configuration structure.
*
* \section lwconfig_return Return Values
*
* irs_resconf_load() returns #IRS_R_SUCCESS if it successfully read and
* parsed filename. It returns a non-0 error code if filename could not be
* opened or contained incorrect resolver statements.
*
* \section lwconfig_see See Also
*
* stdio(3), \link resolver resolver \endlink
*
* \section files Files
*
* /etc/resolv.conf
*/
#include <config.h>
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <isc/sockaddr.h>
/*!
* protocol constants
*/
#if ! defined(NS_INADDRSZ)
#define NS_INADDRSZ 4
#endif
#if ! defined(NS_IN6ADDRSZ)
#define NS_IN6ADDRSZ 16
#endif
/*!
* resolv.conf parameters
*/
/*!
* configuration data structure
*/
struct irs_resconf {
/*
* The configuration data is a thread-specific object, and does not
* need to be locked.
*/
unsigned int magic;
unsigned int numns; /*%< number of configured servers */
char *domainname;
char *search[RESCONFMAXSEARCH];
struct {
/*% mask has a non-zero 'family' if set */
/*%< non-zero if 'options debug' set */
/*%< set to n in 'options ndots:n' */
};
static isc_result_t
static isc_result_t
static isc_result_t
static isc_result_t
static isc_result_t
/*!
* Eat characters from FP until EOL or EOF. Returns EOF or '\n'
*/
static int
int ch;
return (ch);
}
/*!
* Eats white space up to next newline or non-whitespace character (of
* EOF). Returns the last character read. Comments are considered white
* space.
*/
static int
int ch;
return (ch);
}
/*!
* Skip over any leading whitespace and then read in the next sequence of
* non-whitespace characters. In this context newline is not considered
* whitespace. Returns EOF on end-of-file, or the character
* that caused the reading to stop.
*/
static int
int ch;
char *p = buffer;
*p = '\0';
return (EOF);
do {
*p = '\0';
break;
return (EOF); /* Not enough space. */
*p++ = (char)ch;
} while (1);
return (ch);
}
static isc_result_t
{
int error;
if (error != 0)
return (ISC_R_BADADDRESSFORM);
/* XXX: special case: treat all-0 IPv4 address as loopback */
unsigned char zeroaddress[] = {0, 0, 0, 0};
}
goto cleanup;
}
goto cleanup;
}
return (result);
}
static isc_result_t
if (convert_zero) {
unsigned char zeroaddress[] = {0, 0, 0, 0};
}
} else
return (ISC_R_BADADDRESSFORM); /* Unrecognised format. */
return (ISC_R_SUCCESS);
}
static isc_result_t
char word[RESCONFMAXLINELEN];
int cp;
return (ISC_R_SUCCESS);
return (ISC_R_UNEXPECTEDEND); /* Nothing on line. */
return (ISC_R_UNEXPECTEDTOKEN); /* Extra junk on line. */
if (result != ISC_R_SUCCESS)
return (result);
return (ISC_R_SUCCESS);
}
static isc_result_t
char word[RESCONFMAXLINELEN];
int res, i;
return (ISC_R_UNEXPECTEDEND); /* Nothing else on line. */
return (ISC_R_UNEXPECTEDTOKEN); /* Extra junk on line. */
/*
* Search and domain are mutually exclusive.
*/
for (i = 0; i < RESCONFMAXSEARCH; i++) {
}
}
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
}
static isc_result_t
char word[RESCONFMAXLINELEN];
/*
* Search and domain are mutually exclusive.
*/
}
/*
* Remove any previous search definitions.
*/
}
}
return (ISC_R_UNEXPECTEDEND); /* Nothing else on line. */
idx = 0;
goto ignore; /* Too many domains. */
return (ISC_R_NOMEMORY);
idx++;
break;
else
}
return (ISC_R_SUCCESS);
}
static isc_result_t
char word[RESCONFMAXLINELEN];
char *p;
return (ISC_R_UNEXPECTEDEND); /* Empty line after keyword. */
return (ISC_R_QUOTA); /* Too many values. */
if (p != NULL)
*p++ = '\0';
if (res != ISC_R_SUCCESS)
return (res);
if (p != NULL) {
if (res != ISC_R_SUCCESS)
return (res);
} else {
/*
* Make up a mask. (XXX: is this correct?)
*/
}
conf->sortlistnxt++;
break;
else
}
return (ISC_R_SUCCESS);
}
static isc_result_t
int delim;
long ndots;
char *p;
char word[RESCONFMAXLINELEN];
return (ISC_R_UNEXPECTEDEND); /* Empty line after keyword. */
if (*p != '\0') /* Bad string. */
return (ISC_R_UNEXPECTEDTOKEN);
return (ISC_R_RANGE);
}
break;
else
}
return (ISC_R_SUCCESS);
}
static isc_result_t
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
}
/*% parses a file and fills in the data structure. */
{
char word[256];
int i, stopchar;
return (ISC_R_NOMEMORY);
for (i = 0; i < RESCONFMAXSEARCH; i++)
errno = 0;
return (ISC_R_INVALIDFILE);
}
ret = ISC_R_SUCCESS;
do {
break;
}
else {
/* unrecognised word. Ignore entire line */
break;
}
}
} while (1);
/* If we don't find a nameserver fall back to localhost */
/* XXX: should we catch errors? */
}
/*
* Construct unified search list from domain or configured
* search list
*/
if (ret != ISC_R_SUCCESS)
break;
}
}
if (ret != ISC_R_SUCCESS)
else
return (ret);
}
void
int i;
}
}
for (i = 0; i < RESCONFMAXSEARCH; i++) {
}
}
return (&conf->nameservers);
}
return (&conf->searchlist);
}
unsigned int
}