mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-28 12:57:42 +00:00
Handle IPv6 parsing better. Adds generic whitespace handling to
parser. See RT ticket #16862 for more.
This commit is contained in:
parent
9b21e73e3c
commit
bda3316935
2
RELNOTES
2
RELNOTES
@ -54,6 +54,8 @@ suggested fixes to <dhcp-users@isc.org>.
|
|||||||
|
|
||||||
Changes since 4.0.0a1
|
Changes since 4.0.0a1
|
||||||
|
|
||||||
|
- Fix for parsing error on some IPv6 addresses.
|
||||||
|
|
||||||
- Invalid CIDR representation for IPv6 subnets or ranges now checked
|
- Invalid CIDR representation for IPv6 subnets or ranges now checked
|
||||||
for when loading configuration.
|
for when loading configuration.
|
||||||
|
|
||||||
|
286
common/conflex.c
286
common/conflex.c
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char copyright[] =
|
static char copyright[] =
|
||||||
"$Id: conflex.c,v 1.110 2007/06/08 14:58:20 dhankins Exp $ Copyright (c) 2004-2007 Internet Systems Consortium. All rights reserved.\n";
|
"$Id: conflex.c,v 1.111 2007/06/20 10:38:55 shane Exp $ Copyright (c) 2004-2007 Internet Systems Consortium. All rights reserved.\n";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include "dhcpd.h"
|
#include "dhcpd.h"
|
||||||
@ -43,6 +43,7 @@ static char copyright[] =
|
|||||||
static int get_char PROTO ((struct parse *));
|
static int get_char PROTO ((struct parse *));
|
||||||
static enum dhcp_token get_token PROTO ((struct parse *));
|
static enum dhcp_token get_token PROTO ((struct parse *));
|
||||||
static void skip_to_eol PROTO ((struct parse *));
|
static void skip_to_eol PROTO ((struct parse *));
|
||||||
|
static enum dhcp_token read_whitespace(int c, struct parse *cfile);
|
||||||
static enum dhcp_token read_string PROTO ((struct parse *));
|
static enum dhcp_token read_string PROTO ((struct parse *));
|
||||||
static enum dhcp_token read_number PROTO ((int, struct parse *));
|
static enum dhcp_token read_number PROTO ((int, struct parse *));
|
||||||
static enum dhcp_token read_num_or_name PROTO ((int, struct parse *));
|
static enum dhcp_token read_num_or_name PROTO ((int, struct parse *));
|
||||||
@ -58,25 +59,29 @@ isc_result_t new_parse (cfile, file, inbuf, buflen, name, eolp)
|
|||||||
{
|
{
|
||||||
struct parse *tmp;
|
struct parse *tmp;
|
||||||
|
|
||||||
tmp = dmalloc (sizeof (struct parse), MDL);
|
tmp = dmalloc(sizeof(struct parse), MDL);
|
||||||
if (!tmp)
|
if (tmp == NULL) {
|
||||||
return ISC_R_NOMEMORY;
|
return ISC_R_NOMEMORY;
|
||||||
memset (tmp, 0, sizeof *tmp);
|
}
|
||||||
|
|
||||||
tmp->token = 0;
|
/*
|
||||||
|
* We don't need to initialize things to zero here, since
|
||||||
|
* dmalloc() returns memory that is set to zero.
|
||||||
|
*/
|
||||||
|
/* tmp->token = 0; */
|
||||||
|
/* tmp->warnings_occurred = 0; */
|
||||||
|
/* tmp->bufix = 0; */
|
||||||
|
/* tmp->saved_state = NULL; */
|
||||||
tmp->tlname = name;
|
tmp->tlname = name;
|
||||||
tmp->lpos = tmp -> line = 1;
|
tmp->lpos = tmp -> line = 1;
|
||||||
tmp->cur_line = tmp -> line1;
|
tmp->cur_line = tmp->line1;
|
||||||
tmp->prev_line = tmp -> line2;
|
tmp->prev_line = tmp->line2;
|
||||||
tmp->token_line = tmp -> cur_line;
|
tmp->token_line = tmp->cur_line;
|
||||||
tmp->cur_line [0] = tmp -> prev_line [0] = 0;
|
tmp->cur_line[0] = tmp->prev_line[0] = 0;
|
||||||
tmp->warnings_occurred = 0;
|
|
||||||
tmp->file = file;
|
tmp->file = file;
|
||||||
tmp->eol_token = eolp;
|
tmp->eol_token = eolp;
|
||||||
|
|
||||||
tmp->bufix = 0;
|
if (inbuf != NULL) {
|
||||||
|
|
||||||
if (inbuf) {
|
|
||||||
tmp->inbuf = inbuf;
|
tmp->inbuf = inbuf;
|
||||||
tmp->buflen = buflen;
|
tmp->buflen = buflen;
|
||||||
tmp->bufsiz = 0;
|
tmp->bufsiz = 0;
|
||||||
@ -86,7 +91,7 @@ isc_result_t new_parse (cfile, file, inbuf, buflen, name, eolp)
|
|||||||
if (fstat(file, &sb) < 0)
|
if (fstat(file, &sb) < 0)
|
||||||
return ISC_R_IOERROR;
|
return ISC_R_IOERROR;
|
||||||
|
|
||||||
tmp->bufsiz = tmp->buflen = (size_t) sb.st_size;
|
tmp->bufsiz = tmp->buflen = (size_t)sb.st_size;
|
||||||
tmp->inbuf = mmap(NULL, tmp->bufsiz, PROT_READ, MAP_SHARED,
|
tmp->inbuf = mmap(NULL, tmp->bufsiz, PROT_READ, MAP_SHARED,
|
||||||
file, 0);
|
file, 0);
|
||||||
|
|
||||||
@ -107,12 +112,63 @@ isc_result_t end_parse (cfile)
|
|||||||
munmap((*cfile)->inbuf, (*cfile)->bufsiz);
|
munmap((*cfile)->inbuf, (*cfile)->bufsiz);
|
||||||
close((*cfile)->file);
|
close((*cfile)->file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((*cfile)->saved_state != NULL) {
|
||||||
|
dfree((*cfile)->saved_state, MDL);
|
||||||
|
}
|
||||||
|
|
||||||
dfree(*cfile, MDL);
|
dfree(*cfile, MDL);
|
||||||
*cfile = NULL;
|
*cfile = NULL;
|
||||||
return ISC_R_SUCCESS;
|
return ISC_R_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save the current state of the parser.
|
||||||
|
*
|
||||||
|
* Only one state may be saved. Any previous saved state is
|
||||||
|
* lost.
|
||||||
|
*/
|
||||||
|
isc_result_t
|
||||||
|
save_parse_state(struct parse *cfile) {
|
||||||
|
/*
|
||||||
|
* Free any previous saved state.
|
||||||
|
*/
|
||||||
|
if (cfile->saved_state != NULL) {
|
||||||
|
dfree(cfile->saved_state, MDL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save our current state.
|
||||||
|
*/
|
||||||
|
cfile->saved_state = dmalloc(sizeof(struct parse), MDL);
|
||||||
|
if (cfile->saved_state == NULL) {
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
}
|
||||||
|
memcpy(cfile->saved_state, cfile, sizeof(*cfile));
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the parser to the previous saved state.
|
||||||
|
*
|
||||||
|
* You must call save_parse_state() before calling
|
||||||
|
* restore_parse_state(), but you can call restore_parse_state() any
|
||||||
|
* number of times after that.
|
||||||
|
*/
|
||||||
|
isc_result_t
|
||||||
|
restore_parse_state(struct parse *cfile) {
|
||||||
|
struct parse *saved_state;
|
||||||
|
|
||||||
|
if (cfile->saved_state == NULL) {
|
||||||
|
return ISC_R_NOTYET;
|
||||||
|
}
|
||||||
|
|
||||||
|
saved_state = cfile->saved_state;
|
||||||
|
memcpy(cfile, saved_state, sizeof(*cfile));
|
||||||
|
cfile->saved_state = saved_state;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int get_char (cfile)
|
static int get_char (cfile)
|
||||||
struct parse *cfile;
|
struct parse *cfile;
|
||||||
{
|
{
|
||||||
@ -150,9 +206,29 @@ static int get_char (cfile)
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum dhcp_token get_token (cfile)
|
/*
|
||||||
struct parse *cfile;
|
* GENERAL NOTE ABOUT TOKENS
|
||||||
{
|
*
|
||||||
|
* We normally only want non-whitespace tokens. There are some
|
||||||
|
* circumstances where we *do* want to see whitespace (for example
|
||||||
|
* when parsing IPv6 addresses).
|
||||||
|
*
|
||||||
|
* Generally we use the next_token() function to read tokens. This
|
||||||
|
* in turn calls get_token, which does *not* return tokens for
|
||||||
|
* whitespace. Rather, it skips these.
|
||||||
|
*
|
||||||
|
* When we need to see whitespace, we us next_raw_token(), which also
|
||||||
|
* returns the WHITESPACE token.
|
||||||
|
*
|
||||||
|
* The peek_token() and peek_raw_token() functions work as expected.
|
||||||
|
*
|
||||||
|
* Warning: if you invoke peek_token(), then if there is a whitespace
|
||||||
|
* token, it will be lost, and subsequent use of next_raw_token() or
|
||||||
|
* peek_raw_token() will NOT see it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static enum dhcp_token
|
||||||
|
get_raw_token(struct parse *cfile) {
|
||||||
int c;
|
int c;
|
||||||
enum dhcp_token ttok;
|
enum dhcp_token ttok;
|
||||||
static char tb [2];
|
static char tb [2];
|
||||||
@ -164,20 +240,12 @@ static enum dhcp_token get_token (cfile)
|
|||||||
u = cfile -> ugflag;
|
u = cfile -> ugflag;
|
||||||
|
|
||||||
c = get_char (cfile);
|
c = get_char (cfile);
|
||||||
#ifdef OLD_LEXER
|
if (!((c == '\n') && cfile->eol_token) &&
|
||||||
if (c == '\n' && p == 1 && !u
|
isascii(c) && isspace(c)) {
|
||||||
&& cfile -> comment_index < sizeof cfile -> comments)
|
ttok = read_whitespace(c, cfile);
|
||||||
cfile -> comments [cfile -> comment_index++] = '\n';
|
break;
|
||||||
#endif
|
}
|
||||||
|
|
||||||
if (!(c == '\n' && cfile -> eol_token)
|
|
||||||
&& isascii (c) && isspace (c))
|
|
||||||
continue;
|
|
||||||
if (c == '#') {
|
if (c == '#') {
|
||||||
#ifdef OLD_LEXER
|
|
||||||
if (cfile -> comment_index < sizeof cfile -> comments)
|
|
||||||
cfile -> comments [cfile -> comment_index++] = '#';
|
|
||||||
#endif
|
|
||||||
skip_to_eol (cfile);
|
skip_to_eol (cfile);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -215,11 +283,17 @@ static enum dhcp_token get_token (cfile)
|
|||||||
return ttok;
|
return ttok;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum dhcp_token next_token (rval, rlen, cfile)
|
/*
|
||||||
const char **rval;
|
* The get_next_token() function consumes the next token and
|
||||||
unsigned *rlen;
|
* returns it to the caller.
|
||||||
struct parse *cfile;
|
*
|
||||||
{
|
* Since the code is almost the same for "normal" and "raw"
|
||||||
|
* input, we pass a flag to alter the way it works.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static enum dhcp_token
|
||||||
|
get_next_token(const char **rval, unsigned *rlen,
|
||||||
|
struct parse *cfile, isc_boolean_t raw) {
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
if (cfile -> token) {
|
if (cfile -> token) {
|
||||||
@ -230,9 +304,17 @@ enum dhcp_token next_token (rval, rlen, cfile)
|
|||||||
rv = cfile -> token;
|
rv = cfile -> token;
|
||||||
cfile -> token = 0;
|
cfile -> token = 0;
|
||||||
} else {
|
} else {
|
||||||
rv = get_token (cfile);
|
rv = get_raw_token(cfile);
|
||||||
cfile -> token_line = cfile -> cur_line;
|
cfile -> token_line = cfile -> cur_line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!raw) {
|
||||||
|
while (rv == WHITESPACE) {
|
||||||
|
rv = get_raw_token(cfile);
|
||||||
|
cfile->token_line = cfile->cur_line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (rval)
|
if (rval)
|
||||||
*rval = cfile -> tval;
|
*rval = cfile -> tval;
|
||||||
if (rlen)
|
if (rlen)
|
||||||
@ -243,17 +325,56 @@ enum dhcp_token next_token (rval, rlen, cfile)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum dhcp_token peek_token (rval, rlen, cfile)
|
|
||||||
const char **rval;
|
/*
|
||||||
unsigned int *rlen;
|
* Get the next token from cfile and return it.
|
||||||
struct parse *cfile;
|
*
|
||||||
{
|
* If rval is non-NULL, set the pointer it contains to
|
||||||
|
* the contents of the token.
|
||||||
|
*
|
||||||
|
* If rlen is non-NULL, set the integer it contains to
|
||||||
|
* the length of the token.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum dhcp_token
|
||||||
|
next_token(const char **rval, unsigned *rlen, struct parse *cfile) {
|
||||||
|
return get_next_token(rval, rlen, cfile, ISC_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The same as the next_token() function above, but will return space
|
||||||
|
* as the WHITESPACE token.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum dhcp_token
|
||||||
|
next_raw_token(const char **rval, unsigned *rlen, struct parse *cfile) {
|
||||||
|
return get_next_token(rval, rlen, cfile, ISC_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The do_peek_token() function checks the next token without
|
||||||
|
* consuming it, and returns it to the caller.
|
||||||
|
*
|
||||||
|
* Since the code is almost the same for "normal" and "raw"
|
||||||
|
* input, we pass a flag to alter the way it works. (See the
|
||||||
|
* warning in the GENERAL NOTES ABOUT TOKENS above though.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum dhcp_token
|
||||||
|
do_peek_token(const char **rval, unsigned int *rlen,
|
||||||
|
struct parse *cfile, isc_boolean_t raw) {
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
if (!cfile -> token) {
|
if (!cfile->token || (!raw && (cfile->token == WHITESPACE))) {
|
||||||
cfile -> tlpos = cfile -> lexchar;
|
cfile -> tlpos = cfile -> lexchar;
|
||||||
cfile -> tline = cfile -> lexline;
|
cfile -> tline = cfile -> lexline;
|
||||||
cfile -> token = get_token (cfile);
|
|
||||||
|
do {
|
||||||
|
cfile->token = get_raw_token(cfile);
|
||||||
|
} while (!raw && (cfile->token == WHITESPACE));
|
||||||
|
|
||||||
if (cfile -> lexline != cfile -> tline)
|
if (cfile -> lexline != cfile -> tline)
|
||||||
cfile -> token_line = cfile -> prev_line;
|
cfile -> token_line = cfile -> prev_line;
|
||||||
|
|
||||||
@ -275,6 +396,36 @@ enum dhcp_token peek_token (rval, rlen, cfile)
|
|||||||
return cfile -> token;
|
return cfile -> token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the next token from cfile and return it, leaving it for a
|
||||||
|
* subsequent call to next_token().
|
||||||
|
*
|
||||||
|
* Note that it WILL consume whitespace tokens.
|
||||||
|
*
|
||||||
|
* If rval is non-NULL, set the pointer it contains to
|
||||||
|
* the contents of the token.
|
||||||
|
*
|
||||||
|
* If rlen is non-NULL, set the integer it contains to
|
||||||
|
* the length of the token.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum dhcp_token
|
||||||
|
peek_token(const char **rval, unsigned *rlen, struct parse *cfile) {
|
||||||
|
return do_peek_token(rval, rlen, cfile, ISC_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The same as the peek_token() function above, but will return space
|
||||||
|
* as the WHITESPACE token.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum dhcp_token
|
||||||
|
peek_raw_token(const char **rval, unsigned *rlen, struct parse *cfile) {
|
||||||
|
return do_peek_token(rval, rlen, cfile, ISC_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
static void skip_to_eol (cfile)
|
static void skip_to_eol (cfile)
|
||||||
struct parse *cfile;
|
struct parse *cfile;
|
||||||
{
|
{
|
||||||
@ -283,16 +434,42 @@ static void skip_to_eol (cfile)
|
|||||||
c = get_char (cfile);
|
c = get_char (cfile);
|
||||||
if (c == EOF)
|
if (c == EOF)
|
||||||
return;
|
return;
|
||||||
#ifdef OLD_LEXER
|
|
||||||
if (cfile -> comment_index < sizeof (cfile -> comments))
|
|
||||||
comments [cfile -> comment_index++] = c;
|
|
||||||
#endif
|
|
||||||
if (c == EOL) {
|
if (c == EOL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} while (1);
|
} while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum dhcp_token
|
||||||
|
read_whitespace(int c, struct parse *cfile) {
|
||||||
|
int ofs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read as much whitespace as we have available.
|
||||||
|
*/
|
||||||
|
ofs = 0;
|
||||||
|
do {
|
||||||
|
cfile->tokbuf[ofs++] = c;
|
||||||
|
c = get_char(cfile);
|
||||||
|
} while (!((c == '\n') && cfile->eol_token) &&
|
||||||
|
isascii(c) && isspace(c));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Put the last (non-whitespace) character back.
|
||||||
|
*/
|
||||||
|
if (c != EOF) {
|
||||||
|
cfile->bufix--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return our token.
|
||||||
|
*/
|
||||||
|
cfile->tokbuf[ofs] = '\0';
|
||||||
|
cfile->tlen = ofs;
|
||||||
|
cfile->tval = cfile->tokbuf;
|
||||||
|
return WHITESPACE;
|
||||||
|
}
|
||||||
|
|
||||||
static enum dhcp_token read_string (cfile)
|
static enum dhcp_token read_string (cfile)
|
||||||
struct parse *cfile;
|
struct parse *cfile;
|
||||||
{
|
{
|
||||||
@ -406,9 +583,6 @@ static enum dhcp_token read_number (c, cfile)
|
|||||||
int c;
|
int c;
|
||||||
struct parse *cfile;
|
struct parse *cfile;
|
||||||
{
|
{
|
||||||
#ifdef OLD_LEXER
|
|
||||||
int seenx = 0;
|
|
||||||
#endif
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int token = NUMBER;
|
int token = NUMBER;
|
||||||
|
|
||||||
@ -416,7 +590,6 @@ static enum dhcp_token read_number (c, cfile)
|
|||||||
for (; i < sizeof cfile -> tokbuf; i++) {
|
for (; i < sizeof cfile -> tokbuf; i++) {
|
||||||
c = get_char (cfile);
|
c = get_char (cfile);
|
||||||
|
|
||||||
#ifndef OLD_LEXER
|
|
||||||
/* Promote NUMBER -> NUMBER_OR_NAME -> NAME, never demote.
|
/* Promote NUMBER -> NUMBER_OR_NAME -> NAME, never demote.
|
||||||
* Except in the case of '0x' syntax hex, which gets called
|
* Except in the case of '0x' syntax hex, which gets called
|
||||||
* a NAME at '0x', and returned to NUMBER_OR_NAME once it's
|
* a NAME at '0x', and returned to NUMBER_OR_NAME once it's
|
||||||
@ -459,17 +632,6 @@ static enum dhcp_token read_number (c, cfile)
|
|||||||
default:
|
default:
|
||||||
log_fatal("read_number():%s:%d: impossible case", MDL);
|
log_fatal("read_number():%s:%d: impossible case", MDL);
|
||||||
}
|
}
|
||||||
#else /* OLD_LEXER */
|
|
||||||
if (!seenx && (c == 'x')) {
|
|
||||||
seenx = 1;
|
|
||||||
} else if (!isascii (c) || !isxdigit (c)) {
|
|
||||||
if (c != EOF) {
|
|
||||||
cfile -> bufix--;
|
|
||||||
cfile -> ugflag = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif /* OLD_LEXER */
|
|
||||||
|
|
||||||
cfile -> tokbuf [i] = c;
|
cfile -> tokbuf [i] = c;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char copyright[] =
|
static char copyright[] =
|
||||||
"$Id: parse.c,v 1.127 2007/06/07 15:52:29 dhankins Exp $ Copyright (c) 2004-2007 Internet Systems Consortium. All rights reserved.\n";
|
"$Id: parse.c,v 1.128 2007/06/20 10:38:55 shane Exp $ Copyright (c) 2004-2007 Internet Systems Consortium. All rights reserved.\n";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include "dhcpd.h"
|
#include "dhcpd.h"
|
||||||
@ -274,7 +274,6 @@ int parse_ip_addr_or_hostname (expr, cfile, uniform)
|
|||||||
unsigned len = sizeof addr;
|
unsigned len = sizeof addr;
|
||||||
char *name;
|
char *name;
|
||||||
struct expression *x = (struct expression *)0;
|
struct expression *x = (struct expression *)0;
|
||||||
struct parse cfile0;
|
|
||||||
int ipaddr = 0;
|
int ipaddr = 0;
|
||||||
|
|
||||||
token = peek_token (&val, (unsigned *)0, cfile);
|
token = peek_token (&val, (unsigned *)0, cfile);
|
||||||
@ -287,12 +286,12 @@ int parse_ip_addr_or_hostname (expr, cfile, uniform)
|
|||||||
* context first, and restore it after we know what
|
* context first, and restore it after we know what
|
||||||
* we're dealing with.
|
* we're dealing with.
|
||||||
*/
|
*/
|
||||||
memcpy(&cfile0, cfile, sizeof(struct parse));
|
save_parse_state(cfile);
|
||||||
(void) next_token(NULL, NULL, cfile);
|
(void) next_token(NULL, NULL, cfile);
|
||||||
if (next_token(NULL, NULL, cfile) == DOT &&
|
if (next_token(NULL, NULL, cfile) == DOT &&
|
||||||
next_token(NULL, NULL, cfile) == NUMBER)
|
next_token(NULL, NULL, cfile) == NUMBER)
|
||||||
ipaddr = 1;
|
ipaddr = 1;
|
||||||
memcpy(cfile, &cfile0, sizeof(struct parse));
|
restore_parse_state(cfile);
|
||||||
|
|
||||||
if (ipaddr &&
|
if (ipaddr &&
|
||||||
parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
|
parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
|
||||||
@ -379,16 +378,24 @@ parse_ip6_addr(struct parse *cfile, struct iaddr *addr) {
|
|||||||
char v6[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
|
char v6[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
|
||||||
int v6_len;
|
int v6_len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First token is non-raw. This way we eat any whitespace before
|
||||||
|
* our IPv6 address begins, like one would expect.
|
||||||
|
*/
|
||||||
|
token = peek_token(&val, NULL, cfile);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gather symbols.
|
||||||
|
*/
|
||||||
v6_len = 0;
|
v6_len = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
token = peek_token(&val, NULL, cfile);
|
|
||||||
if ((((token == NAME) || (token == NUMBER_OR_NAME)) &&
|
if ((((token == NAME) || (token == NUMBER_OR_NAME)) &&
|
||||||
is_hex_string(val)) ||
|
is_hex_string(val)) ||
|
||||||
(token == NUMBER) ||
|
(token == NUMBER) ||
|
||||||
(token == DOT) ||
|
(token == DOT) ||
|
||||||
(token == COLON)) {
|
(token == COLON)) {
|
||||||
|
|
||||||
next_token(&val, NULL, cfile);
|
next_raw_token(&val, NULL, cfile);
|
||||||
val_len = strlen(val);
|
val_len = strlen(val);
|
||||||
if ((v6_len + val_len) >= sizeof(v6)) {
|
if ((v6_len + val_len) >= sizeof(v6)) {
|
||||||
parse_warn(cfile, "Invalid IPv6 address.");
|
parse_warn(cfile, "Invalid IPv6 address.");
|
||||||
@ -401,9 +408,13 @@ parse_ip6_addr(struct parse *cfile, struct iaddr *addr) {
|
|||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
token = peek_raw_token(&val, NULL, cfile);
|
||||||
}
|
}
|
||||||
v6[v6_len] = '\0';
|
v6[v6_len] = '\0';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use inet_pton() for actual work.
|
||||||
|
*/
|
||||||
if (inet_pton(AF_INET6, v6, addr->iabuf) <= 0) {
|
if (inet_pton(AF_INET6, v6, addr->iabuf) <= 0) {
|
||||||
parse_warn(cfile, "Invalid IPv6 address.");
|
parse_warn(cfile, "Invalid IPv6 address.");
|
||||||
skip_to_semi(cfile);
|
skip_to_semi(cfile);
|
||||||
|
@ -266,15 +266,13 @@ struct parse {
|
|||||||
int tlen;
|
int tlen;
|
||||||
char tokbuf [1500];
|
char tokbuf [1500];
|
||||||
|
|
||||||
#ifdef OLD_LEXER
|
|
||||||
char comments [4096];
|
|
||||||
int comment_index;
|
|
||||||
#endif
|
|
||||||
int warnings_occurred;
|
int warnings_occurred;
|
||||||
int file;
|
int file;
|
||||||
char *inbuf;
|
char *inbuf;
|
||||||
size_t bufix, buflen;
|
size_t bufix, buflen;
|
||||||
size_t bufsiz;
|
size_t bufsiz;
|
||||||
|
|
||||||
|
struct parse *saved_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Variable-length array of data. */
|
/* Variable-length array of data. */
|
||||||
@ -1577,8 +1575,14 @@ isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
|
|||||||
isc_result_t new_parse PROTO ((struct parse **, int,
|
isc_result_t new_parse PROTO ((struct parse **, int,
|
||||||
char *, unsigned, const char *, int));
|
char *, unsigned, const char *, int));
|
||||||
isc_result_t end_parse PROTO ((struct parse **));
|
isc_result_t end_parse PROTO ((struct parse **));
|
||||||
|
isc_result_t save_parse_state(struct parse *cfile);
|
||||||
|
isc_result_t restore_parse_state(struct parse *cfile);
|
||||||
enum dhcp_token next_token PROTO ((const char **, unsigned *, struct parse *));
|
enum dhcp_token next_token PROTO ((const char **, unsigned *, struct parse *));
|
||||||
enum dhcp_token peek_token PROTO ((const char **, unsigned *, struct parse *));
|
enum dhcp_token peek_token PROTO ((const char **, unsigned *, struct parse *));
|
||||||
|
enum dhcp_token next_raw_token(const char **rval, unsigned *rlen,
|
||||||
|
struct parse *cfile);
|
||||||
|
enum dhcp_token peek_raw_token(const char **rval, unsigned *rlen,
|
||||||
|
struct parse *cfile);
|
||||||
|
|
||||||
/* confpars.c */
|
/* confpars.c */
|
||||||
void parse_trace_setup (void);
|
void parse_trace_setup (void);
|
||||||
|
@ -342,7 +342,8 @@ enum dhcp_token {
|
|||||||
LLT = 645,
|
LLT = 645,
|
||||||
EN = 646,
|
EN = 646,
|
||||||
LL = 647,
|
LL = 647,
|
||||||
RANGE6 = 648
|
RANGE6 = 648,
|
||||||
|
WHITESPACE = 649
|
||||||
};
|
};
|
||||||
|
|
||||||
#define is_identifier(x) ((x) >= FIRST_TOKEN && \
|
#define is_identifier(x) ((x) >= FIRST_TOKEN && \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user