]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
- Pull up 3.0 changes.
authorTed Lemon <source@isc.org>
Tue, 25 Jan 2000 01:13:21 +0000 (01:13 +0000)
committerTed Lemon <source@isc.org>
Tue, 25 Jan 2000 01:13:21 +0000 (01:13 +0000)
- Support malloc debug.
- Parse ganged events, let, unset, parenthesized if statements, eval.
- Part of backwards compatibility for BCTEL (doesn't work yet)

common/parse.c

index ffd3d6ad76071e8dfc4b02fb57ff5570f33d24e2..742f4ceffd421313213c0a3e008dc972ff2f38a5 100644 (file)
@@ -22,7 +22,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: parse.c,v 1.58 2000/01/08 01:36:39 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: parse.c,v 1.59 2000/01/25 01:13:21 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -112,7 +112,7 @@ char *parse_string (cfile)
                skip_to_semi (cfile);
                return (char *)0;
        }
-       s = (char *)malloc (strlen (val) + 1);
+       s = (char *)dmalloc (strlen (val) + 1, MDL);
        if (!s)
                log_fatal ("no memory for string %s.", val);
        strcpy (s, val);
@@ -147,7 +147,7 @@ char *parse_host_name (cfile)
                token = next_token (&val, cfile);
 
                /* Store this identifier... */
-               if (!(s = (char *)malloc (strlen (val) + 1)))
+               if (!(s = (char *)dmalloc (strlen (val) + 1, MDL)))
                        log_fatal ("can't allocate temp space for hostname.");
                strcpy (s, val);
                c = cons ((caddr_t)s, c);
@@ -160,7 +160,7 @@ char *parse_host_name (cfile)
        } while (token == DOT);
 
        /* Assemble the hostname together into a string. */
-       if (!(s = (char *)malloc (len)))
+       if (!(s = (char *)dmalloc (len, MDL)))
                log_fatal ("can't allocate space for hostname.");
        t = s + len;
        *--t = 0;
@@ -170,8 +170,8 @@ char *parse_host_name (cfile)
                t -= l;
                memcpy (t, (char *)(c -> car), l);
                /* Free up temp space. */
-               free (c -> car);
-               free (c);
+               dfree (c -> car, MDL);
+               dfree (c, MDL);
                c = cdr;
                if (t != s)
                        *--t = '.';
@@ -291,7 +291,7 @@ void parse_hardware_param (cfile, hardware)
        if (!t)
                return;
        if (hlen + 1 > sizeof hardware -> hbuf) {
-               free (t);
+               dfree (t, MDL);
                parse_warn (cfile, "hardware address too long");
        } else {
                hardware -> hlen = hlen + 1;
@@ -299,7 +299,7 @@ void parse_hardware_param (cfile, hardware)
                if (hlen + 1 < sizeof hardware -> hbuf)
                        memset (&hardware -> hbuf [hlen + 1], 0,
                                (sizeof hardware -> hbuf) - hlen - 1);
-               free (t);
+               dfree (t, MDL);
        }
        
        token = next_token (&val, cfile);
@@ -354,7 +354,7 @@ unsigned char *parse_numeric_aggregate (cfile, buf,
        pair c = (pair)0;
 
        if (!bufp && *max) {
-               bufp = (unsigned char *)malloc (*max * size / 8);
+               bufp = (unsigned char *)dmalloc (*max * size / 8, MDL);
                if (!bufp)
                        log_fatal ("no space for numeric aggregate");
                s = 0;
@@ -396,7 +396,7 @@ unsigned char *parse_numeric_aggregate (cfile, buf,
                        convert_num (cfile, s, val, base, size);
                        s += size / 8;
                } else {
-                       t = (unsigned char *)malloc (strlen (val) + 1);
+                       t = (unsigned char *)dmalloc (strlen (val) + 1, MDL);
                        if (!t)
                                log_fatal ("no temp space for number.");
                        strcpy ((char *)t, val);
@@ -406,7 +406,7 @@ unsigned char *parse_numeric_aggregate (cfile, buf,
 
        /* If we had to cons up a list, convert it now. */
        if (c) {
-               bufp = (unsigned char *)malloc (count * size / 8);
+               bufp = (unsigned char *)dmalloc (count * size / 8, MDL);
                if (!bufp)
                        log_fatal ("no space for numeric aggregate.");
                s = bufp + count - size / 8;
@@ -417,8 +417,8 @@ unsigned char *parse_numeric_aggregate (cfile, buf,
                convert_num (cfile, s, (char *)(c -> car), base, size);
                s -= size / 8;
                /* Free up temp space. */
-               free (c -> car);
-               free (c);
+               dfree (c -> car, MDL);
+               dfree (c, MDL);
                c = cdr;
        }
        return bufp;
@@ -749,7 +749,7 @@ struct option *parse_option_name (cfile, allocate, known)
                        skip_to_semi (cfile);
                return (struct option *)0;
        }
-       uname = malloc (strlen (val) + 1);
+       uname = dmalloc (strlen (val) + 1, MDL);
        if (!uname)
                log_fatal ("no memory for uname information.");
        strcpy (uname, val);
@@ -803,9 +803,8 @@ struct option *parse_option_name (cfile, allocate, known)
                                option -> name = val;
                        else {
                                char *s;
-                               free (uname);
-                               s = dmalloc (strlen (val) + 1,
-                                            "parse_option_name");
+                               dfree (uname, MDL);
+                               s = dmalloc (strlen (val) + 1, MDL);
                                if (!s)
                                    log_fatal ("no memory for option %s.%s",
                                               universe -> name, val);
@@ -826,7 +825,7 @@ struct option *parse_option_name (cfile, allocate, known)
        }
 
        /* Free the initial identifier token. */
-       free (uname);
+       dfree (uname, MDL);
        return option;
 }
 
@@ -853,7 +852,7 @@ void parse_option_space_decl (cfile)
                log_fatal ("No memory for new option space.");
 
        /* Set up the server option universe... */
-       s = dmalloc (strlen (val) + 1, "parse_option_space_decl");
+       s = dmalloc (strlen (val) + 1, MDL);
        if (!s)
                log_fatal ("No memory for new option space name.");
        strcpy (s, val);
@@ -872,13 +871,12 @@ void parse_option_space_decl (cfile)
        nu -> store_length = putUChar;
        nu -> index = universe_count++;
        if (nu -> index >= universe_max) {
-               ua = dmalloc (universe_max * 2 * sizeof *ua,
-                             "parse_option_space_decl");
+               ua = dmalloc (universe_max * 2 * sizeof *ua, MDL);
                if (!ua)
                        log_fatal ("No memory to expand option space array.");
                memcpy (ua, universes, universe_max * sizeof *ua);
                universe_max *= 2;
-               dfree (universes, "parse_option_space_decl");
+               dfree (universes, MDL);
                universes = ua;
        }
        universes [nu -> index] = nu;
@@ -1084,7 +1082,7 @@ int parse_option_code_definition (cfile, option)
                        skip_to_semi (cfile);
                return 0;
        }
-       s = dmalloc (tokix + arrayp + 1, "parse_option_code_definition");
+       s = dmalloc (tokix + arrayp + 1, MDL);
        if (!s)
                log_fatal ("no memory for option format.");
        memcpy (s, tokbuf, tokix);
@@ -1128,15 +1126,14 @@ int parse_cshl (data, cfile)
                        skip_to_semi (cfile);
                        for (; sl; sl = next) {
                                next = sl -> next;
-                               dfree (sl, "parse_cshl");
+                               dfree (sl, MDL);
                        }
                        return 0;
                }
                if (ilen == sizeof ibuf) {
                        next = (struct option_tag *)
                                dmalloc (ilen - 1 +
-                                        sizeof (struct option_tag),
-                                        "parse_cshl");
+                                        sizeof (struct option_tag), MDL);
                        if (!next)
                                log_fatal ("no memory for string list.");
                        memcpy (next -> data, ibuf, ilen);
@@ -1164,7 +1161,7 @@ int parse_cshl (data, cfile)
                next = sl -> next;
                memcpy (rvp, sl -> data, sizeof ibuf);
                rvp += sizeof ibuf;
-               dfree (sl, "parse_cshl");
+               dfree (sl, MDL);
                sl = next;
        }
        
@@ -1375,7 +1372,6 @@ int parse_executable_statement (result, cfile, lose, case_context)
                        
              case TOKEN_SET:
                token = next_token (&val, cfile);
-               token = next_token (&val, cfile);
 
                token = next_token (&val, cfile);
                if (token != NAME && token != NUMBER_OR_NAME) {
@@ -1391,9 +1387,8 @@ int parse_executable_statement (result, cfile, lose, case_context)
                    (result,
                     "parse_executable_statement"))
                        log_fatal ("no memory for set statement.");
-               (*result) -> op = default_statement;
-               (*result) -> data.set.name = dmalloc (strlen (val) + 1,
-                                                     "parse_executable_stmt");
+               (*result) -> op = set_statement;
+               (*result) -> data.set.name = dmalloc (strlen (val) + 1, MDL);
                if (!(*result)->data.set.name)
                        log_fatal ("can't allocate variable name");
                strcpy ((*result) -> data.set.name, val);
@@ -1419,6 +1414,56 @@ int parse_executable_statement (result, cfile, lose, case_context)
                parse_semi (cfile);
                break;
 
+             case UNSET:
+               token = next_token (&val, cfile);
+
+               token = next_token (&val, cfile);
+               if (token != NAME && token != NUMBER_OR_NAME) {
+                       parse_warn (cfile,
+                                   "%s can't be a variable name", val);
+                     badunset:
+                       skip_to_semi (cfile);
+                       *lose = 1;
+                       return 0;
+               }
+
+               if (!executable_statement_allocate
+                   (result,
+                    "parse_executable_statement"))
+                       log_fatal ("no memory for set statement.");
+               (*result) -> op = unset_statement;
+               (*result) -> data.unset = dmalloc (strlen (val) + 1, MDL);
+               if (!(*result)->data.unset)
+                       log_fatal ("can't allocate variable name");
+               strcpy ((*result) -> data.unset, val);
+               parse_semi (cfile);
+               break;
+
+             case EVAL:
+               token = next_token (&val, cfile);
+
+               if (!executable_statement_allocate
+                   (result,
+                    "parse_executable_statement"))
+                       log_fatal ("no memory for eval statement.");
+               (*result) -> op = eval_statement;
+
+               if (!parse_expression (&(*result) -> data.eval,
+                                      cfile, lose, context_data, /* XXX */
+                                      (struct expression **)0, expr_none)) {
+                       if (!*lose)
+                               parse_warn (cfile,
+                                           "expecting data expression.");
+                       else
+                               *lose = 1;
+                       skip_to_semi (cfile);
+                       executable_statement_dereference
+                               (result, "parse_executable_statement");
+                       return 0;
+               }
+               parse_semi (cfile);
+               break;
+
              default:
                *lose = 0;
                return 0;
@@ -1455,11 +1500,11 @@ int parse_on_statement (result, cfile, lose)
                        break;
                
                      case COMMIT:
-                       (*result) -> data.on.evtypes = ON_COMMIT;
+                       (*result) -> data.on.evtypes |= ON_COMMIT;
                        break;
                        
                      case RELEASE:
-                       (*result) -> data.on.evtypes = ON_RELEASE;
+                       (*result) -> data.on.evtypes |= ON_RELEASE;
                        break;
                        
                      default:
@@ -1468,7 +1513,7 @@ int parse_on_statement (result, cfile, lose)
                        *lose = 1;
                        executable_statement_dereference
                                (result, "parse_on_statement");
-                       break;
+                       return 0;
                }
                token = next_token (&val, cfile);
        } while (token == OR);
@@ -1641,12 +1686,21 @@ int parse_if_statement (result, cfile, lose)
 {
        enum dhcp_token token;
        const char *val;
+       int parenp;
 
        if (!executable_statement_allocate (result, "parse_if_statement"))
                log_fatal ("no memory for if statement.");
 
        (*result) -> op = if_statement;
 
+       token = peek_token (&val, cfile);
+       if (token == LPAREN) {
+               parenp = 1;
+               next_token (&val, cfile);
+       } else
+               parenp = 0;
+
+
        if (!parse_boolean_expression (&(*result) -> data.ie.expr,
                                       cfile, lose)) {
                if (!*lose)
@@ -1659,6 +1713,16 @@ int parse_if_statement (result, cfile, lose)
 #if defined (DEBUG_EXPRESSION_PARSE)
        print_expression ("if condition", if_condition);
 #endif
+       if (parenp) {
+               token = next_token (&val, cfile);
+               if (token != RPAREN) {
+                       parse_warn (cfile, "expecting right paren.");
+                       *lose = 1;
+                       executable_statement_dereference
+                               (result, "parse_if_statement");
+                       return 0;
+               }
+       }
        token = next_token (&val, cfile);
        if (token != LBRACE) {
                parse_warn (cfile, "left brace expected.");
@@ -1884,6 +1948,8 @@ int parse_non_binary (expr, cfile, lose, context)
        int known;
        enum expr_op opcode;
        const char *s;
+       struct executable_statement *stmt;
+       int i;
 
        token = peek_token (&val, cfile);
 
@@ -2176,7 +2242,7 @@ int parse_non_binary (expr, cfile, lose, context)
                        goto norparen;
                break;
 
-             case PICK_FIRST_VALUE:
+             case PICK:
                /* pick (a, b, c) actually produces an internal representation
                   that looks like pick (a, pick (b, pick (c, nil))). */
                token = next_token (&val, cfile);
@@ -2220,70 +2286,75 @@ int parse_non_binary (expr, cfile, lose, context)
                parse_warn (cfile,
                            "Please rebuild dhcpd with --with-nsupdate.");
 #endif
+               token = next_token (&val, cfile);
                if (token == DNS_UPDATE)
                        opcode = expr_ns_add;
                else
                        opcode = expr_ns_delete;
 
-               token = next_token (&val, cfile);
-               if (!expression_allocate (expr,
-                                         "parse_expression: DNS_UPDATE"))
-                       log_fatal ("can't allocate expression");
-               (*expr) -> op = expr_dns_transaction;
-
                token = next_token (&val, cfile);
                if (token != LPAREN)
                        goto nolparen;
 
-               nexp = (struct expression *)0;
-               if (!expression_allocate (&nexp,
-                                         "parse_expression: DNS_UPDATE1"))
-                       log_fatal ("can't allocate expression");
-               nexp -> op = opcode;
-               (*expr) -> data.dns_transaction.car = nexp;
-
                token = next_token (&val, cfile);
                if (token != STRING) {
                        parse_warn (cfile,
                                    "parse_expression: expecting string.");
                      badnsupdate:
-                       expression_dereference
-                               (expr, "parse_expression");
                        skip_to_semi (cfile);
                        *lose = 1;
                        return 0;
                }
                        
                if (!strcasecmp (val, "a"))
-                       nexp -> data.ns_add.rrtype = T_A;
+                       i = T_A;
                else if (!strcasecmp (val, "ptr"))
-                       nexp -> data.ns_add.rrtype = T_PTR;
+                       i = T_PTR;
                else if (!strcasecmp (val, "mx"))
-                       nexp -> data.ns_add.rrtype = T_MX;
+                       i = T_MX;
                else if (!strcasecmp (val, "cname"))
-                       nexp -> data.ns_add.rrtype = T_CNAME;
+                       i = T_CNAME;
                else if (!strcasecmp (val, "TXT"))
-                       nexp -> data.ns_add.rrtype = T_TXT;
+                       i = T_TXT;
                else {
                        parse_warn (cfile, "unexpected rrtype: %s", val);
                        goto badnsupdate;
                }
-               nexp -> data.ns_add.rrclass = C_IN;
+
+               if (!expression_allocate (expr,
+                                         "parse_expression: DNS_UPDATE"))
+                       log_fatal ("can't allocate expression");
+#if 0
+               (*expr) -> op = expr_funcall;
+               (*expr) -> data.funcall.context = context_boolean;
+               (*expr) -> data.funcall.name = 
+
+               if (!make_let (&(*expr) -> data.funcall.statements, "rrtype"))
+                       log_fatal ("can't allocate rrtype let.");
+               stmt = (*expr) -> data.funcall.statements;
+               if (!make_const_int (stmt -> data.let.value, i))
+                       log_fatal ("can't allocate rrtype value.");
 
                token = next_token (&val, cfile);
                if (token != COMMA)
                        goto nocomma;
 
-               if (!(parse_data_expression
-                     (&nexp -> data.ns_add.rrname, cfile, lose)))
+               if (!make_let (&stmt -> data.let.statements, "rrname"))
+                       log_fatal ("can't allocate rrname let.");
+               stmt = stmt -> data.let.statements;
+               if (!(parse_data_expression (&stmt -> data.let.expr,
+                                            cfile, lose)))
                        goto nodata;
 
                token = next_token (&val, cfile);
                if (token != COMMA)
                        goto nocomma;
 
-               if (!(parse_data_expression
-                     (&nexp -> data.ns_add.rrdata, cfile, lose)))
+               if (!make_let (&stmt -> data.let.statements, "rrdata"))
+                       log_fatal ("can't allocate rrname let.");
+               stmt = stmt -> data.let.statements;
+               if (!(parse_data_expression (&stmt -> data.let.expr,
+                                            cfile, lose)))
                        goto nodata;
 
                if (opcode == expr_ns_add) {
@@ -2291,14 +2362,18 @@ int parse_non_binary (expr, cfile, lose, context)
                        if (token != COMMA)
                                goto nocomma;
                        
+                       if (!make_let (&stmt -> data.let.statements, "ttl"))
+                               log_fatal ("can't allocate rrname let.");
+                       stmt = stmt -> data.let.statements;
+
                        if (!(parse_numeric_expression
-                             (&nexp -> data.ns_add.ttl, cfile, lose))) {
+                             (&stmt -> data.let.expr, cfile, lose))) {
                                parse_warn (cfile,
-                                           "expecting data expression.");
+                                           "expecting numeric expression.");
                                goto badnsupdate;
                        }
                }
-
+#endif
                token = next_token (&val, cfile);
                if (token != RPAREN)
                        goto norparen;
@@ -2354,7 +2429,12 @@ int parse_non_binary (expr, cfile, lose, context)
 
                /* NOT EXISTS is special cased above... */
              not_exists:
-               token = next_token (&val, cfile);
+               token = peek_token (&val, cfile);
+               if (token != EXISTS) {
+                       parse_warn (cfile, "expecting DNS prerequisite.");
+                       *lose = 1;
+                       return 0;
+               }
                opcode = expr_ns_not_exists;
                goto nsupdatecode;
              case TOKEN_ADD:
@@ -2498,6 +2578,22 @@ int parse_non_binary (expr, cfile, lose, context)
                (*expr) -> op = expr_leased_address;
                break;
 
+             case FILENAME:
+               token = next_token (&val, cfile);
+               if (!expression_allocate (expr,
+                                         "parse_expression: FILENAME"))
+                       log_fatal ("can't allocate expression");
+               (*expr) -> op = expr_filename;
+               break;
+
+             case SERVER_NAME:
+               token = next_token (&val, cfile);
+               if (!expression_allocate (expr,
+                                         "parse_expression: SERVER_NAME"))
+                       log_fatal ("can't allocate expression");
+               (*expr) -> op = expr_sname;
+               break;
+
              case LEASE_TIME:
                token = next_token (&val, cfile);
                if (!expression_allocate (expr,
@@ -2552,7 +2648,7 @@ int parse_non_binary (expr, cfile, lose, context)
                        log_fatal ("can't allocate expression");
                (*expr) -> op = expr_variable_reference;
                (*expr) -> data.variable =
-                       dmalloc (strlen (s) + 1, "parse_expression");
+                       dmalloc (strlen (s) + 1, MDL);
                if (!(*expr) -> data.variable)
                        log_fatal ("can't allocate variable name.");
                strcpy ((*expr) -> data.variable, s);
@@ -2832,8 +2928,7 @@ int parse_non_binary (expr, cfile, lose, context)
                if (!expression_allocate (expr, "parse_expression"))
                        log_fatal ("can't allocate expression");
                (*expr) -> op = expr_variable_exists;
-               (*expr) -> data.variable = dmalloc (strlen (val) + 1,
-                                                   "parse_expression");
+               (*expr) -> data.variable = dmalloc (strlen (val) + 1, MDL);
                if (!(*expr)->data.variable)
                        log_fatal ("can't allocate variable name");
                strcpy ((*expr) -> data.variable, val);
@@ -2851,8 +2946,7 @@ int parse_non_binary (expr, cfile, lose, context)
                if (!expression_allocate (expr, "parse_expression"))
                        log_fatal ("can't allocate expression");
                (*expr) -> op = expr_variable_reference;
-               (*expr) -> data.variable = dmalloc (strlen (val) + 1,
-                                                   "parse_expression");
+               (*expr) -> data.variable = dmalloc (strlen (val) + 1, MDL);
                if (!(*expr)->data.variable)
                        log_fatal ("can't allocate variable name");
                strcpy ((*expr) -> data.variable, val);
@@ -3131,6 +3225,7 @@ int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
        int len;
        unsigned char *ob;
        struct iaddr addr;
+       int num;
 
        switch (*fmt) {
              case 'U':
@@ -3194,9 +3289,19 @@ int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
                }
                break;
                
+             case 'T': /* Lease interval. */
+               token = next_token (&val, cfile);
+               if (token != INFINITE)
+                       goto check_number;
+               putLong (buf, -1);
+               if (!make_const_data (&t, buf, 4, 0, 1))
+                       return 0;
+               break;
+
              case 'L': /* Unsigned 32-bit integer... */
              case 'l': /* Signed 32-bit integer... */
                token = next_token (&val, cfile);
+             check_number:
                if (token != NUMBER) {
                      need_number:
                        parse_warn (cfile, "expecting number.");