resolv_conf_parser.c revision 5979821e2c16d1fcec5b9a3ef64e13246fc9a93a
/* $Id$ */
/** @file
* resolv_conf_parser.c - parser of resolv.conf resolver(5)
*/
/*
* Copyright (C) 2014 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include <iprt/initterm.h>
#ifdef RT_OS_FREEBSD
#endif
#include <ctype.h>
#include "resolv_conf_parser.h"
/* XXX: it's required to add the aliases for keywords and
* types to handle conditions more clearly */
enum RCP_TOKEN
{
/* keywords */
tok_error = -20
};
#define RCP_BUFFER_SIZE 256
struct rcp_parser
{
enum RCP_TOKEN rcpp_token;
char rcpp_str_buffer[RCP_BUFFER_SIZE];
struct rcp_state *rcpp_state;
};
#define EOF (-1)
do { \
return tok_error; \
} \
}while(0);
{
char tok = ' ';
char *ptr;
/* tok can't be ipv4 */
dot_number = 0;
xdigit = 1;
digit = 1;
do {
break;
/**
* if before ':' there were only [0-9][a-f][A-F],
* then it can't be option.
*/
/**
* We want hint to differ ipv4 and network name.
*/
if (tok == ':')
{
if (xdigit == 1)
{
int port = 0;
do
{
if (tok == '.')
port++;
if (port == 0)
return tok_ipv6;
else if (port == 1)
return tok_ipv6_port;
else
{
/* eats rest of the token */
do
{
return tok_string;
}
}
else {
/* XXX: need further experiments */
return tok_option; /* option with value */
}
}
if (tok == '.')
{
do {
return tok_ipv4;
return tok_ipv4_port;
else
return tok_string;
}
return tok_number;
return tok_nameserver;
return tok_port;
return tok_domain;
return tok_search;
return tok_search_order;
return tok_sortlist;
return tok_timeout;
return tok_options;
return tok_string;
}
if (tok == '#')
{
do{
return tok_comment;
}
return tok;
}
/**
* nameserverexpr ::= 'nameserver' ip+
* @note: resolver(5) ip ::= (ipv4|ipv6)(.number)?
*/
{
&& tok != tok_ipv4_port
&& tok != tok_ipv6_port)
return tok_error;
|| tok == tok_ipv4_port
|| tok == tok_ipv6_port)
{
char *str_address;
/* It's still valid resolv.conf file, just rest of the nameservers should be ignored */
return rcp_get_token(parser);
#ifdef RT_OS_DARWIN
if ( tok == tok_ipv4_port
|| ( tok == tok_ipv6_port
{
while (*(--ptr) != '.');
*ptr = '\0';
}
#endif
/**
* if we on Darwin upper code will cut off port if it's.
*/
{
return tok_error;
goto loop_prolog;
}
switch (tok)
{
case tok_ipv4:
case tok_ipv4_port:
{
}
break;
case tok_ipv6:
case tok_ipv6_port:
{
int rc;
return rcp_get_token(parser);
if (rc == -1)
return tok_error;
}
break;
default: /* loop condition doesn't let enter enything */
break;
}
}
return tok;
}
/**
* portexpr ::= 'port' [0-9]+
*/
{
if ( tok != tok_number
return tok_error;
return tok_error;
return rcp_get_token(parser);
}
/**
* domainexpr ::= 'domain' string
*/
{
/**
* It's nowhere specified how resolver should react on dublicats
* of 'domain' declarations, let's assume that resolv.conf is broken.
*/
return tok_error;
/**
* We initialize this pointer in place, just make single pointer check
* in 'domain'-less resolv.conf.
*/
return rcp_get_token(parser);
}
/**
* searchexpr ::= 'search' (string)+
* @note: resolver (5) Mac OSX:
* "The search list is currently limited to six domains with a total of 256 characters."
* @note: resolv.conf (5) Linux:
* "The search list is currently limited to six domains with a total of 256 characters."
* @note: 'search' parameter could contains numbers only hex or decimal, 1c1e or 111
*/
{
char *ptr;
return tok_error;
/* just ignore "too many search list" */
return rcp_get_token(parser);
/* we don't want accept keywords */
if (tok <= tok_nameserver)
return tok;
/* if there're several entries of "search" we compose them together */
i = st->rcps_num_searchlist;
if ( i == 0)
else
{
}
while (1)
{
break; /* not enough room for new entry */
if (i >= RCPS_MAX_SEARCHLIST)
break; /* not enought free entries for 'search' items */
/* token filter */
|| tok <= tok_nameserver)
break;
}
st->rcps_num_searchlist = i;
return tok;
}
/**
* expr ::= nameserverexpr | expr
* ::= portexpr | expr
* ::= domainexpr | expr
* ::= searchexpr | expr
* ::= searchlistexpr | expr
* ::= search_orderexpr | expr
* ::= timeoutexpr | expr
* ::= optionsexpr | expr
*/
{
{
switch (tok)
{
case tok_nameserver:
break;
case tok_port:
break;
case tok_domain:
break;
case tok_search:
break;
default:
}
}
return -1;
return 0;
}
{
unsigned i;
int rc;
struct rcp_parser parser;
/**
* for debugging need: with RCP_STANDALONE it's possible
* to run simplefied scenarious like
*
* # cat /etc/resolv.conf | rcp-test-0
* or in lldb
* # process launch -i /etc/resolv.conf
*/
#ifdef RCP_STANDALONE
#else
return -1;
#endif
else
{
}
if (rc == -1)
return -1;
#ifdef RT_OS_DARWIN
/**
* port recolv.conf's option and IP.port are Mac OSX extentions, there're no need to care on
* other hosts.
*/
&& i != RCPS_MAX_NAMESERVERS; ++i)
{
}
#endif
return 0;
}