]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
Handle hostnames that start with numbers.
authorShane Kerr <shane@isc.org>
Wed, 23 May 2007 15:29:49 +0000 (15:29 +0000)
committerShane Kerr <shane@isc.org>
Wed, 23 May 2007 15:29:49 +0000 (15:29 +0000)
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.

common/conflex.c
common/parse.c
includes/dhcpd.h

index 52b7e43fdd44bc37426215fab0acf655f6f679d6..89a4f4651c0941a68b044efa53116f0210e56408 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 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 */
 
 #include "dhcpd.h"
@@ -63,29 +63,36 @@ isc_result_t new_parse (cfile, file, inbuf, buflen, name, eolp)
                return ISC_R_NOMEMORY;
        memset (tmp, 0, sizeof *tmp);
 
-       tmp -> token = 0;
-       tmp -> tlname = name;
-       tmp -> lpos = tmp -> line = 1;
-       tmp -> cur_line = tmp -> line1;
-       tmp -> prev_line = tmp -> line2;
-       tmp -> token_line = tmp -> cur_line;
-       tmp -> cur_line [0] = tmp -> prev_line [0] = 0;
-       tmp -> warnings_occurred = 0;
-       tmp -> file = file;
-       tmp -> eol_token = eolp;
+       tmp->token = 0;
+       tmp->tlname = name;
+       tmp->lpos = tmp -> line = 1;
+       tmp->cur_line = tmp -> line1;
+       tmp->prev_line = tmp -> line2;
+       tmp->token_line = tmp -> cur_line;
+       tmp->cur_line [0] = tmp -> prev_line [0] = 0;
+       tmp->warnings_occurred = 0;
+       tmp->file = file;
+       tmp->eol_token = eolp;
+
+       tmp->bufix = 0;
 
-       tmp -> bufix = 0;
-       tmp -> buflen = buflen;
        if (inbuf) {
-               tmp -> bufsiz = 0;
-               tmp -> inbuf = inbuf;
+               tmp->inbuf = inbuf;
+               tmp->buflen = buflen;
+               tmp->bufsiz = 0;
        } else {
-               tmp -> inbuf = dmalloc (8192, MDL);
-               if (!tmp -> inbuf) {
-                       dfree (tmp, MDL);
-                       return ISC_R_NOMEMORY;
+               struct stat sb;
+
+               if (fstat(file, &sb) < 0)
+                       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;
@@ -96,11 +103,11 @@ isc_result_t end_parse (cfile)
        struct parse **cfile;
 {
        /* "Memory" config files have no file. */
-       if ((*cfile)->file != -1)
+       if ((*cfile)->file != -1) {
+               munmap((*cfile)->inbuf, (*cfile)->bufsiz);
                close((*cfile)->file);
-
-       if ((*cfile)->bufsiz)
-               dfree((*cfile)->inbuf, MDL);
+       }
+               
        dfree(*cfile, MDL);
        *cfile = NULL;
        return ISC_R_SUCCESS;
@@ -112,49 +119,34 @@ static int get_char (cfile)
        /* My kingdom for WITH... */
        int c;
 
-       if (cfile -> bufix == cfile -> buflen) {
-               if (cfile -> file != -1) {
-                       cfile -> buflen =
-                               read (cfile -> file,
-                                     cfile -> inbuf, cfile -> bufsiz);
-                       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->bufix == cfile->buflen)
+               c = EOF;
+       else {
+               c = cfile->inbuf [cfile->bufix];
+               cfile->bufix++;
        }
 
-       if (!cfile -> ugflag) {
+       if (!cfile->ugflag) {
                if (c == EOL) {
-                       if (cfile -> cur_line == cfile -> line1) {      
-                               cfile -> cur_line = cfile -> line2;
-                               cfile -> prev_line = cfile -> line1;
+                       if (cfile->cur_line == cfile->line1) {  
+                               cfile->cur_line = cfile->line2;
+                               cfile->prev_line = cfile->line1;
                        } else {
-                               cfile -> cur_line = cfile -> line1;
-                               cfile -> prev_line = cfile -> line2;
+                               cfile->cur_line = cfile->line1;
+                               cfile->prev_line = cfile->line2;
                        }
-                       cfile -> line++;
-                       cfile -> lpos = 1;
-                       cfile -> cur_line [0] = 0;
+                       cfile->line++;
+                       cfile->lpos = 1;
+                       cfile->cur_line [0] = 0;
                } else if (c != EOF) {
-                       if (cfile -> lpos <= 80) {
-                               cfile -> cur_line [cfile -> lpos - 1] = c;
-                               cfile -> cur_line [cfile -> lpos] = 0;
+                       if (cfile->lpos <= 80) {
+                               cfile->cur_line [cfile->lpos - 1] = c;
+                               cfile->cur_line [cfile->lpos] = 0;
                        }
-                       cfile -> lpos++;
+                       cfile->lpos++;
                }
        } else
-               cfile -> ugflag = 0;
+               cfile->ugflag = 0;
        return c;               
 }
 
index 3d123a34bc63e770d553f7a066f878b8c131ef6e..6287193f69ffdc4ab82d6a32244580756e27183d 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 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 */
 
 #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
    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)
        struct expression **expr;
@@ -270,9 +274,33 @@ int parse_ip_addr_or_hostname (expr, cfile, uniform)
        unsigned len = sizeof addr;
        char *name;
        struct expression *x = (struct expression *)0;
+       struct parse cfile0;
+       int ipaddr = 0;
 
        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);
                if (!name)
                        return 0;
@@ -287,10 +315,6 @@ int parse_ip_addr_or_hostname (expr, cfile, uniform)
                        expression_dereference (expr, MDL);
                        *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 {
                if (token != RBRACE && token != LBRACE)
                        token = next_token (&val, (unsigned *)0, cfile);
index 69feb44cf0bd9ede704456d39caeafe6cedfef1d..2fade44e5fd2e46174c53ed7050ccb0d494944dc 100644 (file)
@@ -52,6 +52,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <sys/stat.h>
+#include <sys/mman.h>
 #include <ctype.h>
 #include <time.h>
 
@@ -272,8 +273,8 @@ struct parse {
        int warnings_occurred;
        int file;
        char *inbuf;
-       unsigned bufix, buflen;
-       unsigned bufsiz;
+       size_t bufix, buflen;
+       size_t bufsiz;
 };
 
 /* Variable-length array of data. */