Reported long ago by matthieu@. Also Jacob Berkman via the lists.
Tests and suggestions from Jacob and Matthieu.
-/* $OpenBSD: clparse.c,v 1.91 2015/02/01 18:43:39 krw Exp $ */
+/* $OpenBSD: clparse.c,v 1.92 2015/05/18 17:51:21 krw Exp $ */
/* Parser for dhclient config and lease files. */
int len;
token = peek_token(&val, cfile);
- if (token == TOK_NUMBER_OR_NAME || token == TOK_NUMBER) {
+ if (token == TOK_NUMBER_OR_NAME) {
len = 0;
for (token = ':'; token == ':';
token = next_token(NULL, cfile)) {
-/* $OpenBSD: conflex.c,v 1.31 2015/05/02 14:29:32 krw Exp $ */
+/* $OpenBSD: conflex.c,v 1.32 2015/05/18 17:51:21 krw Exp $ */
/* Lexical scanner for dhclient config file. */
static int get_token(FILE *);
static void skip_to_eol(FILE *);
static int read_string(FILE *);
-static int read_number(int, FILE *);
static int read_num_or_name(int, FILE *);
static int intern(char *, int);
if (c == '"') {
ttok = read_string(cfile);
break;
- }
- if ((isascii(c) && isdigit(c)) || c == '-') {
- ttok = read_number(c, cfile);
- break;
- } else if (isascii(c) && isalpha(c)) {
+ } else if (c == '-' || (isascii(c) && isalnum(c))) {
ttok = read_num_or_name(c, cfile);
break;
} else {
return (TOK_STRING);
}
-static int
-read_number(int c, FILE *cfile)
-{
- int seenx = 0, i = 0, token = TOK_NUMBER;
-
- tokbuf[i++] = c;
- for (; i < sizeof(tokbuf); i++) {
- c = get_char(cfile);
- if (!seenx && c == 'x')
- seenx = 1;
- else if (!isascii(c) || !isxdigit(c)) {
- ungetc(c, cfile);
- ugflag = 1;
- break;
- }
- tokbuf[i] = c;
- }
- if (i == sizeof(tokbuf)) {
- parse_warn("numeric token larger than internal buffer");
- i--;
- }
- tokbuf[i] = 0;
- tval = tokbuf;
-
- return (token);
-}
-
static int
read_num_or_name(int c, FILE *cfile)
{
- int i = 0;
- int rv = TOK_NUMBER_OR_NAME;
+ int i, rv, xdigits;
+
+ xdigits = isxdigit(c) ? 1 : 0;
- tokbuf[i++] = c;
- for (; i < sizeof(tokbuf); i++) {
+ tokbuf[0] = c;
+ for (i = 1; i < sizeof(tokbuf); i++) {
c = get_char(cfile);
if (!isascii(c) || (c != '-' && c != '_' && !isalnum(c))) {
ungetc(c, cfile);
ugflag = 1;
break;
}
- if (!isxdigit(c))
- rv = TOK_NAME;
+ if (isxdigit(c))
+ xdigits++;
tokbuf[i] = c;
}
if (i == sizeof(tokbuf)) {
parse_warn("token larger than internal buffer");
i--;
+ c = tokbuf[i];
+ if (isxdigit(c))
+ xdigits--;
}
tokbuf[i] = 0;
tval = tokbuf;
- return (intern(tval, rv));
+ c = (unsigned int)tokbuf[0];
+
+ if (c == '-')
+ rv = TOK_NUMBER;
+ else
+ rv = intern(tval, TOK_NUMBER_OR_NAME);
+
+ if (rv == TOK_NUMBER_OR_NAME && xdigits != i)
+ rv = TOK_NAME;
+
+ return (rv);
}
static const struct keywords {
-/* $OpenBSD: parse.c,v 1.38 2014/05/05 18:02:49 krw Exp $ */
+/* $OpenBSD: parse.c,v 1.39 2015/05/18 17:51:21 krw Exp $ */
/* Common parser code for dhcpd and dhclient. */
switch (token) {
case TOK_NAME:
case TOK_NUMBER:
+ case TOK_NUMBER_OR_NAME:
case '/':
case ':':
token = next_token(&val, cfile);
-/* $OpenBSD: conflex.c,v 1.14 2015/05/02 14:29:32 krw Exp $ */
+/* $OpenBSD: conflex.c,v 1.15 2015/05/18 17:51:21 krw Exp $ */
/* Lexical scanner for dhcpd config file... */
static int get_token(FILE *);
static void skip_to_eol(FILE *);
static int read_string(FILE *);
-static int read_number(int, FILE *);
static int read_num_or_name(int, FILE *);
static int intern(char *, int);
if (c == '"') {
ttok = read_string(cfile);
break;
- }
- if ((isascii(c) && isdigit(c)) || c == '-') {
- ttok = read_number(c, cfile);
- break;
- } else if (isascii(c) && isalpha(c)) {
+ } else if (c == '-' || (isascii(c) && isalnum(c))) {
ttok = read_num_or_name(c, cfile);
break;
} else {
return (TOK_STRING);
}
-static int
-read_number(int c, FILE *cfile)
-{
- int seenx = 0, i = 0, token = TOK_NUMBER;
-
- tokbuf[i++] = c;
- for (; i < sizeof(tokbuf); i++) {
- c = get_char(cfile);
- if (!seenx && c == 'x')
- seenx = 1;
- else if (!isascii(c) || !isxdigit(c)) {
- ungetc(c, cfile);
- ugflag = 1;
- break;
- }
- tokbuf[i] = c;
- }
- if (i == sizeof(tokbuf)) {
- parse_warn("numeric token larger than internal buffer");
- i--;
- }
- tokbuf[i] = 0;
- tval = tokbuf;
-
- return (token);
-}
-
static int
read_num_or_name(int c, FILE *cfile)
{
- int i = 0;
- int rv = TOK_NUMBER_OR_NAME;
+ int i, rv, xdigits;
+
+ xdigits = isxdigit(c) ? 1 : 0;
- tokbuf[i++] = c;
- for (; i < sizeof(tokbuf); i++) {
+ tokbuf[0] = c;
+ for (i = 1; i < sizeof(tokbuf); i++) {
c = get_char(cfile);
if (!isascii(c) || (c != '-' && c != '_' && !isalnum(c))) {
ungetc(c, cfile);
ugflag = 1;
break;
}
- if (!isxdigit(c))
- rv = TOK_NAME;
+ if (isxdigit(c))
+ xdigits++;
tokbuf[i] = c;
}
if (i == sizeof(tokbuf)) {
parse_warn("token larger than internal buffer");
i--;
+ c = tokbuf[i];
+ if (isxdigit(c))
+ xdigits--;
}
tokbuf[i] = 0;
tval = tokbuf;
- return (intern(tval, rv));
+ c = (unsigned int)tokbuf[0];
+
+ if (c == '-')
+ rv = TOK_NUMBER;
+ else
+ rv = intern(tval, TOK_NUMBER_OR_NAME);
+
+ if (rv == TOK_NUMBER_OR_NAME && xdigits != i)
+ rv = TOK_NAME;
+
+ return (rv);
}
static const struct keywords {
-/* $OpenBSD: confpars.c,v 1.23 2014/07/09 13:42:24 yasuoka Exp $ */
+/* $OpenBSD: confpars.c,v 1.24 2015/05/18 17:51:21 krw Exp $ */
/*
* Copyright (c) 1995, 1996, 1997 The Internet Software Consortium.
int
parse_cidr(FILE *cfile, unsigned char *addr, unsigned char *prefix)
{
+ const char *errstr;
char *val;
int token;
int len = 4;
goto nocidr;
}
- *prefix = 0;
token = next_token(&val, cfile);
- if (token == TOK_NUMBER)
- convert_num(prefix, val, 10, 8);
+ if (token == TOK_NUMBER_OR_NAME)
+ *prefix = strtonum(val, 0, 32, &errstr);
- if (token != TOK_NUMBER || *prefix > 32) {
+ if (token != TOK_NUMBER_OR_NAME || errstr) {
+ *prefix = 0;
parse_warn("Expecting CIDR prefix length, got '%s'", val);
goto nocidr;
}
struct tree *rv;
struct hostent *h;
+ name = NULL;
+ h = NULL;
+
token = peek_token(&val, cfile);
if (is_identifier(token)) {
name = parse_host_name(cfile);
- if (!name)
- return NULL;
- h = gethostbyname(name);
- if (h == NULL) {
- parse_warn("%s (%d): could not resolve hostname",
- val, token);
- return NULL;
+ if (name)
+ h = gethostbyname(name);
+ if (name && h) {
+ rv = tree_const(h->h_addr_list[0], h->h_length);
+ if (!uniform)
+ rv = tree_limit(rv, 4);
+ return rv;
}
- rv = tree_const(h->h_addr_list[0], h->h_length);
- if (!uniform)
- rv = tree_limit(rv, 4);
- } else if (token == TOK_NUMBER) {
- if (!parse_numeric_aggregate(cfile, addr, &len, '.', 10, 8))
+ }
+
+ if (token == TOK_NUMBER_OR_NAME) {
+ if (!parse_numeric_aggregate(cfile, addr, &len, '.', 10, 8)) {
+ parse_warn("%s (%d): expecting IP address or hostname",
+ val, token);
return NULL;
+ }
rv = tree_const(addr, len);
} else {
if (token != '{' && token != '}')
switch (*fmt) {
case 'X':
token = peek_token(&val, cfile);
- if (token == TOK_NUMBER_OR_NAME ||
- token == TOK_NUMBER) {
+ if (token == TOK_NUMBER_OR_NAME) {
do {
token = next_token
(&val, cfile);
- if (token != TOK_NUMBER &&
- token != TOK_NUMBER_OR_NAME) {
+ if (token != TOK_NUMBER_OR_NAME) {
parse_warn("expecting "
- "number.");
+ "hex number.");
if (token != ';')
skip_to_semi(
cfile);
case 'L': /* Unsigned 32-bit integer... */
case 'l': /* Signed 32-bit integer... */
token = next_token(&val, cfile);
- if (token != TOK_NUMBER) {
+ if (token != TOK_NUMBER && token !=
+ TOK_NUMBER_OR_NAME) {
parse_warn("expecting number.");
if (token != ';')
skip_to_semi(cfile);
case 's': /* Signed 16-bit integer. */
case 'S': /* Unsigned 16-bit integer. */
token = next_token(&val, cfile);
- if (token != TOK_NUMBER) {
+ if (token != TOK_NUMBER && token !=
+ TOK_NUMBER_OR_NAME) {
parse_warn("expecting number.");
if (token != ';')
skip_to_semi(cfile);
case 'b': /* Signed 8-bit integer. */
case 'B': /* Unsigned 8-bit integer. */
token = next_token(&val, cfile);
- if (token != TOK_NUMBER) {
+ if (token != TOK_NUMBER && token !=
+ TOK_NUMBER_OR_NAME) {
parse_warn("expecting number.");
if (token != ';')
skip_to_semi(cfile);
-/* $OpenBSD: parse.c,v 1.17 2013/12/18 20:37:04 krw Exp $ */
+/* $OpenBSD: parse.c,v 1.18 2015/05/18 17:51:21 krw Exp $ */
/* Common parser code for dhcpd and dhclient. */
* Enterprises, see ``http://www.vix.com''.
*/
+#include <stdint.h>
+
#include "dhcpd.h"
#include "dhctoken.h"
do {
/* Read a token, which should be an identifier. */
token = next_token(&val, cfile);
- if (!is_identifier(token) && token != TOK_NUMBER) {
+ if (!is_identifier(token)) {
parse_warn("expecting an identifier in hostname");
skip_to_semi(cfile);
return (NULL);
void
parse_lease_time(FILE *cfile, time_t *timep)
{
+ const char *errstr;
char *val;
uint32_t value;
int token;
token = next_token(&val, cfile);
- if (token != TOK_NUMBER) {
- parse_warn("Expecting numeric lease time");
+
+ value = strtonum(val, 0, UINT32_MAX, &errstr);
+ if (errstr) {
+ parse_warn("lease time is %s: %s", errstr, val);
skip_to_semi(cfile);
return;
}
- convert_num((unsigned char *)&value, val, 10, 32);
- /* Unswap the number - convert_num returns stuff in NBO. */
- *timep = ntohl(value); /* XXX */
parse_semi(cfile);
}
parse_warn("unexpected end of file");
break;
}
- /* Allow NUMBER_OR_NAME if base is 16. */
- if (token != TOK_NUMBER &&
- (base != 16 || token != TOK_NUMBER_OR_NAME)) {
+ if (token != TOK_NUMBER && token != TOK_NUMBER_OR_NAME) {
parse_warn("expecting numeric value.");
skip_to_semi(cfile);
return (NULL);
switch (token) {
case TOK_NAME:
case TOK_NUMBER:
+ case TOK_NUMBER_OR_NAME:
case '/':
case ':':
token = next_token(&val, cfile);