2
0
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:
Shane Kerr 2007-05-23 15:29:49 +00:00
parent 6d7bdffcbd
commit 66eaae186e
3 changed files with 84 additions and 67 deletions

View File

@ -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;
} }

View File

@ -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);

View File

@ -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. */