mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-30 05:47:45 +00:00
Handle hostnames that start with numbers.
This involved needing to look at more than one token at a time, so this patch moves from read() to mmap() of files, as a way to gracefully rewind. See RT ticket #16516 for (a lot) more.
This commit is contained in:
parent
6d7bdffcbd
commit
66eaae186e
108
common/conflex.c
108
common/conflex.c
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char copyright[] =
|
static char copyright[] =
|
||||||
"$Id: conflex.c,v 1.107 2007/05/19 19:16:24 dhankins Exp $ Copyright (c) 2004-2007 Internet Systems Consortium. All rights reserved.\n";
|
"$Id: conflex.c,v 1.108 2007/05/23 15:29:49 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"
|
||||||
@ -63,29 +63,36 @@ isc_result_t new_parse (cfile, file, inbuf, buflen, name, eolp)
|
|||||||
return ISC_R_NOMEMORY;
|
return ISC_R_NOMEMORY;
|
||||||
memset (tmp, 0, sizeof *tmp);
|
memset (tmp, 0, sizeof *tmp);
|
||||||
|
|
||||||
tmp -> token = 0;
|
tmp->token = 0;
|
||||||
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->warnings_occurred = 0;
|
||||||
tmp -> file = file;
|
tmp->file = file;
|
||||||
tmp -> eol_token = eolp;
|
tmp->eol_token = eolp;
|
||||||
|
|
||||||
|
tmp->bufix = 0;
|
||||||
|
|
||||||
tmp -> bufix = 0;
|
|
||||||
tmp -> buflen = buflen;
|
|
||||||
if (inbuf) {
|
if (inbuf) {
|
||||||
tmp -> bufsiz = 0;
|
tmp->inbuf = inbuf;
|
||||||
tmp -> inbuf = inbuf;
|
tmp->buflen = buflen;
|
||||||
|
tmp->bufsiz = 0;
|
||||||
} else {
|
} else {
|
||||||
tmp -> inbuf = dmalloc (8192, MDL);
|
struct stat sb;
|
||||||
if (!tmp -> inbuf) {
|
|
||||||
dfree (tmp, MDL);
|
if (fstat(file, &sb) < 0)
|
||||||
return ISC_R_NOMEMORY;
|
return ISC_R_IOERROR;
|
||||||
|
|
||||||
|
tmp->bufsiz = tmp->buflen = (size_t) sb.st_size;
|
||||||
|
tmp->inbuf = mmap(NULL, tmp->bufsiz, PROT_READ, MAP_SHARED,
|
||||||
|
file, 0);
|
||||||
|
|
||||||
|
if (tmp->inbuf == MAP_FAILED) {
|
||||||
|
return ISC_R_IOERROR;
|
||||||
}
|
}
|
||||||
tmp -> bufsiz = 8192;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*cfile = tmp;
|
*cfile = tmp;
|
||||||
@ -96,11 +103,11 @@ isc_result_t end_parse (cfile)
|
|||||||
struct parse **cfile;
|
struct parse **cfile;
|
||||||
{
|
{
|
||||||
/* "Memory" config files have no file. */
|
/* "Memory" config files have no file. */
|
||||||
if ((*cfile)->file != -1)
|
if ((*cfile)->file != -1) {
|
||||||
|
munmap((*cfile)->inbuf, (*cfile)->bufsiz);
|
||||||
close((*cfile)->file);
|
close((*cfile)->file);
|
||||||
|
}
|
||||||
if ((*cfile)->bufsiz)
|
|
||||||
dfree((*cfile)->inbuf, MDL);
|
|
||||||
dfree(*cfile, MDL);
|
dfree(*cfile, MDL);
|
||||||
*cfile = NULL;
|
*cfile = NULL;
|
||||||
return ISC_R_SUCCESS;
|
return ISC_R_SUCCESS;
|
||||||
@ -112,49 +119,34 @@ static int get_char (cfile)
|
|||||||
/* My kingdom for WITH... */
|
/* My kingdom for WITH... */
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
if (cfile -> bufix == cfile -> buflen) {
|
if (cfile->bufix == cfile->buflen)
|
||||||
if (cfile -> file != -1) {
|
c = EOF;
|
||||||
cfile -> buflen =
|
else {
|
||||||
read (cfile -> file,
|
c = cfile->inbuf [cfile->bufix];
|
||||||
cfile -> inbuf, cfile -> bufsiz);
|
cfile->bufix++;
|
||||||
if (cfile -> buflen == 0) {
|
|
||||||
c = EOF;
|
|
||||||
cfile -> bufix = 0;
|
|
||||||
} else if (cfile -> buflen < 0) {
|
|
||||||
c = EOF;
|
|
||||||
cfile -> bufix = cfile -> buflen = 0;
|
|
||||||
} else {
|
|
||||||
c = cfile -> inbuf [0];
|
|
||||||
cfile -> bufix = 1;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
c = EOF;
|
|
||||||
} else {
|
|
||||||
c = cfile -> inbuf [cfile -> bufix];
|
|
||||||
cfile -> bufix++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cfile -> ugflag) {
|
if (!cfile->ugflag) {
|
||||||
if (c == EOL) {
|
if (c == EOL) {
|
||||||
if (cfile -> cur_line == cfile -> line1) {
|
if (cfile->cur_line == cfile->line1) {
|
||||||
cfile -> cur_line = cfile -> line2;
|
cfile->cur_line = cfile->line2;
|
||||||
cfile -> prev_line = cfile -> line1;
|
cfile->prev_line = cfile->line1;
|
||||||
} else {
|
} else {
|
||||||
cfile -> cur_line = cfile -> line1;
|
cfile->cur_line = cfile->line1;
|
||||||
cfile -> prev_line = cfile -> line2;
|
cfile->prev_line = cfile->line2;
|
||||||
}
|
}
|
||||||
cfile -> line++;
|
cfile->line++;
|
||||||
cfile -> lpos = 1;
|
cfile->lpos = 1;
|
||||||
cfile -> cur_line [0] = 0;
|
cfile->cur_line [0] = 0;
|
||||||
} else if (c != EOF) {
|
} else if (c != EOF) {
|
||||||
if (cfile -> lpos <= 80) {
|
if (cfile->lpos <= 80) {
|
||||||
cfile -> cur_line [cfile -> lpos - 1] = c;
|
cfile->cur_line [cfile->lpos - 1] = c;
|
||||||
cfile -> cur_line [cfile -> lpos] = 0;
|
cfile->cur_line [cfile->lpos] = 0;
|
||||||
}
|
}
|
||||||
cfile -> lpos++;
|
cfile->lpos++;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
cfile -> ugflag = 0;
|
cfile->ugflag = 0;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char copyright[] =
|
static char copyright[] =
|
||||||
"$Id: parse.c,v 1.124 2007/05/19 19:16:24 dhankins Exp $ Copyright (c) 2004-2007 Internet Systems Consortium. All rights reserved.\n";
|
"$Id: parse.c,v 1.125 2007/05/23 15:29:49 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"
|
||||||
@ -257,7 +257,11 @@ char *parse_host_name (cfile)
|
|||||||
|
|
||||||
Parse an ip address or a hostname. If uniform is zero, put in
|
Parse an ip address or a hostname. If uniform is zero, put in
|
||||||
an expr_substring node to limit hostnames that evaluate to more
|
an expr_substring node to limit hostnames that evaluate to more
|
||||||
than one IP address. */
|
than one IP address.
|
||||||
|
|
||||||
|
Note that RFC1123 permits hostnames to consist of all digits,
|
||||||
|
making it difficult to quickly disambiguate them from ip addresses.
|
||||||
|
*/
|
||||||
|
|
||||||
int parse_ip_addr_or_hostname (expr, cfile, uniform)
|
int parse_ip_addr_or_hostname (expr, cfile, uniform)
|
||||||
struct expression **expr;
|
struct expression **expr;
|
||||||
@ -270,9 +274,33 @@ 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;
|
||||||
|
|
||||||
token = peek_token (&val, (unsigned *)0, cfile);
|
token = peek_token (&val, (unsigned *)0, cfile);
|
||||||
if (is_identifier (token)) {
|
|
||||||
|
if (token == NUMBER) {
|
||||||
|
/*
|
||||||
|
* a hostname may be numeric, but domain names must
|
||||||
|
* start with a letter, so we can disambiguate by
|
||||||
|
* looking ahead a few tokens. we save the parse
|
||||||
|
* context first, and restore it after we know what
|
||||||
|
* we're dealing with.
|
||||||
|
*/
|
||||||
|
memcpy(&cfile0, cfile, sizeof(struct parse));
|
||||||
|
(void) next_token(NULL, NULL, cfile);
|
||||||
|
if (next_token(NULL, NULL, cfile) == DOT &&
|
||||||
|
next_token(NULL, NULL, cfile) == NUMBER)
|
||||||
|
ipaddr = 1;
|
||||||
|
memcpy(cfile, &cfile0, sizeof(struct parse));
|
||||||
|
|
||||||
|
if (ipaddr &&
|
||||||
|
parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
|
||||||
|
return make_const_data (expr, addr, len, 0, 1, MDL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_identifier (token) || token == NUMBER) {
|
||||||
name = parse_host_name (cfile);
|
name = parse_host_name (cfile);
|
||||||
if (!name)
|
if (!name)
|
||||||
return 0;
|
return 0;
|
||||||
@ -287,10 +315,6 @@ int parse_ip_addr_or_hostname (expr, cfile, uniform)
|
|||||||
expression_dereference (expr, MDL);
|
expression_dereference (expr, MDL);
|
||||||
*expr = x;
|
*expr = x;
|
||||||
}
|
}
|
||||||
} else if (token == NUMBER) {
|
|
||||||
if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
|
|
||||||
return 0;
|
|
||||||
return make_const_data (expr, addr, len, 0, 1, MDL);
|
|
||||||
} else {
|
} else {
|
||||||
if (token != RBRACE && token != LBRACE)
|
if (token != RBRACE && token != LBRACE)
|
||||||
token = next_token (&val, (unsigned *)0, cfile);
|
token = next_token (&val, (unsigned *)0, cfile);
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
@ -272,8 +273,8 @@ struct parse {
|
|||||||
int warnings_occurred;
|
int warnings_occurred;
|
||||||
int file;
|
int file;
|
||||||
char *inbuf;
|
char *inbuf;
|
||||||
unsigned bufix, buflen;
|
size_t bufix, buflen;
|
||||||
unsigned bufsiz;
|
size_t bufsiz;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Variable-length array of data. */
|
/* Variable-length array of data. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user