]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
Pervasive changes to support leased_address, reverse and binary_to_ascii.
authorTed Lemon <source@isc.org>
Fri, 2 Jul 1999 20:58:48 +0000 (20:58 +0000)
committerTed Lemon <source@isc.org>
Fri, 2 Jul 1999 20:58:48 +0000 (20:58 +0000)
13 files changed:
client/dhclient.c
common/convert.c
common/execute.c
common/memory.c
common/options.c
common/parse.c
common/tree.c
includes/dhcpd.h
includes/dhctoken.h
includes/tree.h
server/bootp.c
server/class.c
server/dhcp.c

index 1000b03d3668e86d96221ee4f3610f1ac2a2a551..7a9d01d25ea76d662706a90ceb30bb07f3172ffc 100644 (file)
@@ -22,7 +22,7 @@
 
 #ifndef lint
 static char ocopyright[] =
-"$Id: dhclient.c,v 1.77 1999/05/07 17:32:37 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: dhclient.c,v 1.78 1999/07/02 20:57:06 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -267,8 +267,9 @@ struct class *find_class (s)
        return (struct class *)0;
 }
 
-int check_collection (packet, collection)
+int check_collection (packet, lease, collection)
        struct packet *packet;
+       struct lease *lease;
        struct collection *collection;
 {
        return 0;
@@ -511,7 +512,8 @@ void dhcpack (packet)
        memset (&ds, 0, sizeof ds);
        if (oc &&
            evaluate_option_cache (&ds, packet,
-                                  client -> new -> options, oc)) {
+                                  client -> new -> options,
+                                  (struct lease *)0, oc)) {
                if (ds.len > 3)
                        client -> new -> expiry = getULong (ds.data);
                else
@@ -539,8 +541,8 @@ void dhcpack (packet)
        oc = lookup_option (&dhcp_universe, client -> new -> options,
                            DHO_DHCP_RENEWAL_TIME);
        if (oc &&
-           evaluate_option_cache (&ds, packet,
-                                  client -> new -> options, oc)) {
+           evaluate_option_cache (&ds, packet, client -> new -> options,
+                                  (struct lease *)0, oc)) {
                if (ds.len > 3)
                        client -> new -> renewal = getULong (ds.data);
                else
@@ -559,7 +561,8 @@ void dhcpack (packet)
                            DHO_DHCP_REBINDING_TIME);
        if (oc &&
            evaluate_option_cache (&ds, packet,
-                                  client -> new -> options, oc)) {
+                                  client -> new -> options,
+                                  (struct lease *)0, oc)) {
                if (ds.len > 3)
                        client -> new -> rebind = getULong (ds.data);
                else
@@ -667,7 +670,9 @@ void state_bound (cpp)
                            DHO_DHCP_SERVER_IDENTIFIER);
        if (oc &&
            evaluate_option_cache (&ds, (struct packet *)0,
-                                  client -> active -> options, oc)) {
+                                  client -> active -> options,
+                                  (struct lease *)0,
+                                  oc)) {
                if (ds.len > 3) {
                        memcpy (client -> destination.iabuf, ds.data, 4);
                        client -> destination.len = 4;
@@ -906,7 +911,8 @@ struct client_lease *packet_to_lease (packet)
                            DHO_DHCP_OPTION_OVERLOAD);
        memset (&data, 0, sizeof data);
        if (oc &&
-           evaluate_option_cache (&data, packet, lease -> options, oc)) {
+           evaluate_option_cache (&data, packet, lease -> options,
+                                  (struct lease *)0, oc)) {
                if (data.len > 0)
                        i = data.data [0];
                else
@@ -1482,10 +1488,9 @@ void make_client_options (client, lease, type, sid, rip, prl, op)
        /* Run statements that need to be run on transmission. */
        if (client -> config -> on_transmission)
                execute_statements_in_scope
-                       ((struct packet *)0, (lease
-                                             ? lease -> options
-                                             : (struct option_state *)0), *op,
-                        client -> config -> on_transmission,
+                       ((struct packet *)0, (struct lease *)0,
+                        (lease ? lease -> options : (struct option_state *)0),
+                        *op, client -> config -> on_transmission,
                         (struct group *)0);
 }
 
@@ -1508,7 +1513,8 @@ void make_discover (client, lease)
 
        /* Set up the option buffer... */
        client -> packet_length =
-               cons_options ((struct packet *)0, &client -> packet, 0,
+               cons_options ((struct packet *)0, &client -> packet,
+                             (struct lease *)0, 0,
                              options, 0, 0, 0, (struct data_string *)0);
        if (client -> packet_length < BOOTP_MIN_LEN)
                client -> packet_length = BOOTP_MIN_LEN;
@@ -1574,7 +1580,8 @@ void make_request (client, lease)
 
        /* Set up the option buffer... */
        client -> packet_length =
-               cons_options ((struct packet *)0, &client -> packet, 0,
+               cons_options ((struct packet *)0, &client -> packet,
+                             (struct lease *)0, 0,
                              options, 0, 0, 0, (struct data_string *)0);
        if (client -> packet_length < BOOTP_MIN_LEN)
                client -> packet_length = BOOTP_MIN_LEN;
@@ -1637,7 +1644,8 @@ void make_decline (client, lease)
        /* Set up the option buffer... */
        memset (&client -> packet, 0, sizeof (client -> packet));
        client -> packet_length =
-               cons_options ((struct packet *)0, &client -> packet, 0,
+               cons_options ((struct packet *)0, &client -> packet,
+                             (struct lease *)0, 0,
                              options, 0, 0, 0, (struct data_string *)0);
        if (client -> packet_length < BOOTP_MIN_LEN)
                client -> packet_length = BOOTP_MIN_LEN;
@@ -1693,7 +1701,8 @@ void make_release (client, lease)
 
        /* Set up the option buffer... */
        client -> packet_length =
-               cons_options ((struct packet *)0, &client -> packet, 0,
+               cons_options ((struct packet *)0, &client -> packet,
+                             (struct lease *)0, 0,
                              options, 0, 0, 0, (struct data_string *)0);
        if (client -> packet_length < BOOTP_MIN_LEN)
                client -> packet_length = BOOTP_MIN_LEN;
@@ -1838,7 +1847,8 @@ void write_client_lease (client, lease, rewrite)
                for (p = hash [i]; p; p = p -> cdr) {
                        oc = (struct option_cache *)p -> car;
                        if (evaluate_option_cache (&ds, (struct packet *)0,
-                                                  lease -> options, oc)) {
+                                                  lease -> options,
+                                                  (struct lease *)0, oc)) {
                                fprintf (leaseFile,
                                         "  option %s %s;\n",
                                         oc -> option -> name,
@@ -1950,7 +1960,8 @@ void script_write_params (client, prefix, lease)
        memset (&data, 0, sizeof data);
        oc = lookup_option (&dhcp_universe, lease -> options, DHO_SUBNET_MASK);
        if (oc && evaluate_option_cache (&data, (struct packet *)0,
-                                        lease -> options, oc)) {
+                                        lease -> options,
+                                        (struct lease *)0, oc)) {
                if (data.len > 3) {
                        struct iaddr netmask, subnet, broadcast;
 
@@ -1973,6 +1984,7 @@ void script_write_params (client, prefix, lease)
                                    !evaluate_option_cache (&data,
                                                            (struct packet *)0,
                                                            lease -> options,
+                                                           (struct lease *)0,
                                                            oc)) {
                                        broadcast = broadcast_addr (subnet,
                                                                    netmask);
@@ -2004,7 +2016,8 @@ void script_write_params (client, prefix, lease)
                fprintf (scriptFile, "export %sserver_name\n", prefix);
        }
 
-       execute_statements_in_scope ((struct packet *)0, lease -> options,
+       execute_statements_in_scope ((struct packet *)0,
+                                    (struct lease *)0, lease -> options,
                                     lease -> options,
                                     client -> config -> on_receipt,
                                     (struct group *)0);
@@ -2017,7 +2030,8 @@ void script_write_params (client, prefix, lease)
                        oc = (struct option_cache *)hp -> car;
 
                        if (evaluate_option_cache (&data, (struct packet *)0,
-                                                  lease -> options, oc)) {
+                                                  lease -> options,
+                                                  (struct lease *)0, oc)) {
 
                                if (data.len) {
                                        char *s = (dhcp_option_ev_name
index 88f335f1e64c4c00b091095c5fa15e0cfd7e4e88..a1206648c8f74c8b86d2910b529cd72e26a5bd94 100644 (file)
@@ -23,7 +23,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: convert.c,v 1.7 1999/04/05 15:33:52 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: convert.c,v 1.8 1999/07/02 20:57:24 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -108,3 +108,65 @@ u_int32_t getUChar (obuf)
 {
        return obuf [0];
 }
+
+int converted_length (buf, base, width)
+       unsigned char *buf;
+       unsigned int base;
+       unsigned int width;
+{
+       u_int32_t number;
+       int column;
+       int power = 1;
+       int newcolumn = base;
+
+       if (base > 16)
+               return 0;
+
+       if (width == 1)
+               number = getUChar (buf);
+       else if (width == 2)
+               number = getUShort (buf);
+       else if (width == 4)
+               number = getULong (buf);
+
+       do {
+               column = newcolumn;
+
+               if (number < column)
+                       return power;
+               power++;
+               newcolumn = column * base;
+               /* If we wrap around, it must be the next power of two up. */
+       } while (column > newcolumn);
+
+       return power;
+}
+
+int binary_to_ascii (outbuf, inbuf, base, width)
+       unsigned char *outbuf;
+       unsigned char *inbuf;
+       unsigned int base;
+       unsigned int width;
+{
+       u_int32_t number;
+       static char h2a [] = "0123456789abcdef";
+       int power = 0;
+       int i, j;
+
+       if (base > 16)
+               return 0;
+
+       if (width == 1)
+               number = getUChar (inbuf);
+       else if (width == 2)
+               number = getUShort (inbuf);
+       else if (width == 4)
+               number = getULong (inbuf);
+
+       for (i = 0; number; i++) {
+               outbuf [i] = h2a [number % base];
+               number /= base;
+               power++;
+       }
+       return power;
+}
index de1e94a44db0a74d8143faf8c1b2476731609c17..2c4eb8c4b65cb531c97532bd4754efc3a4aeec32 100644 (file)
 
 #ifndef lint
 static char copyright[] =
-"$Id: execute.c,v 1.9 1999/04/05 15:35:54 mellon Exp $ Copyright (c) 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: execute.c,v 1.10 1999/07/02 20:57:24 mellon Exp $ Copyright (c) 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
 
-int execute_statements (packet, in_options, out_options, statements)
+int execute_statements (packet, lease, in_options, out_options, statements)
        struct packet *packet;
+       struct lease *lease;
        struct option_state *in_options;
        struct option_state *out_options;
        struct executable_statement *statements;
@@ -45,7 +46,7 @@ int execute_statements (packet, in_options, out_options, statements)
                      case if_statement:
                        status = evaluate_boolean_expression
                                (&result, packet,
-                                in_options, r -> data.ie.expr);
+                                in_options, lease, r -> data.ie.expr);
                        
 #if defined (DEBUG_EXPRESSIONS)
                        log_info ("exec: if %s", (status
@@ -56,7 +57,7 @@ int execute_statements (packet, in_options, out_options, statements)
                        if (!status)
                                result = 0;
                        if (!execute_statements
-                           (packet, in_options, out_options,
+                           (packet, lease, in_options, out_options,
                             result ? r -> data.ie.true : r -> data.ie.false))
                                return 0;
                        break;
@@ -64,7 +65,7 @@ int execute_statements (packet, in_options, out_options, statements)
                      case eval_statement:
                        status = evaluate_boolean_expression
                                (&result,
-                                packet, in_options, r -> data.eval);
+                                packet, in_options, lease, r -> data.eval);
 #if defined (DEBUG_EXPRESSIONS)
                        log_info ("exec: evaluate: %s",
                              (status
@@ -138,9 +139,10 @@ int execute_statements (packet, in_options, out_options, statements)
    specific scopes, so we recursively traverse the scope list, executing
    the most outer scope first. */
 
-void execute_statements_in_scope (packet, in_options, out_options,
+void execute_statements_in_scope (packet, lease, in_options, out_options,
                                  group, limiting_group)
        struct packet *packet;
+       struct lease *lease;
        struct option_state *in_options;
        struct option_state *out_options;
        struct group *group;
@@ -182,8 +184,9 @@ void execute_statements_in_scope (packet, in_options, out_options,
        }
 
        if (group -> next)
-               execute_statements_in_scope (packet, in_options, out_options,
+               execute_statements_in_scope (packet, lease,
+                                            in_options, out_options,
                                             group -> next, limiting_group);
-       execute_statements (packet,
+       execute_statements (packet, lease,
                            in_options, out_options, group -> statements);
 }
index fc1c09bb5b651abbc59480151bf043798abe9c29..cd506c6b5b386e2bf2164b597be9b5ea42dd3a10 100644 (file)
@@ -22,7 +22,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: memory.c,v 1.51 1999/07/01 18:45:28 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: memory.c,v 1.52 1999/07/02 20:57:24 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -87,6 +87,7 @@ void enter_host (hd)
                                (&hd -> client_identifier,
                                 (struct packet *)0,
                                 (struct option_state *)0,
+                                (struct lease *)0,
                                 esp -> data.option);
                        break;
                }
@@ -176,6 +177,7 @@ struct subnet *find_host_for_network (host, addr, share)
                        continue;
                if (!evaluate_data_expression (&fixed_addr, (struct packet *)0,
                                               (struct option_state *)0,
+                                              (struct lease *)0,
                                               hp -> fixed_addr -> expression))
                        continue;
                for (i = 0; i < fixed_addr.len; i += 4) {
index 246b983be8ed42bd5d01fe863aee8e8f273e8ff2..591181c1d9d9418aab1b4013aed9ebec7e7b17cb 100644 (file)
@@ -22,7 +22,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: options.c,v 1.42 1999/05/07 17:36:36 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: options.c,v 1.43 1999/07/02 20:57:25 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #define DHCP_OPTION_DATA
@@ -233,10 +233,11 @@ int parse_agent_information_option (packet, len, data)
    three seperate buffers if needed.  This allows us to cons up a set
    of vendor options using the same routine. */
 
-int cons_options (inpacket, outpacket,
+int cons_options (inpacket, outpacket, lease,
                  mms, options, overload, terminate, bootpp, prl)
        struct packet *inpacket;
        struct dhcp_packet *outpacket;
+       struct lease *lease;
        int mms;
        struct option_state *options;
        int overload;   /* Overload flags that may be set. */
@@ -267,7 +268,7 @@ int cons_options (inpacket, outpacket,
            (op = lookup_option (&dhcp_universe, inpacket -> options,
                                 DHO_DHCP_MAX_MESSAGE_SIZE))) {
                evaluate_option_cache (&ds, inpacket,
-                                      inpacket -> options, op);
+                                      inpacket -> options, lease, op);
                if (ds.len >= sizeof (u_int16_t))
                        mms = getUShort (ds.data);
                data_string_forget (&ds, "cons_options");
@@ -363,6 +364,7 @@ int cons_options (inpacket, outpacket,
                                     (main_buffer_size - 7 +
                                      ((overload & 1) ? DHCP_FILE_LEN : 0) +
                                      ((overload & 2) ? DHCP_SNAME_LEN : 0)),
+                                    lease,
                                     options,
                                     priority_list, priority_len,
                                     main_buffer_size,
@@ -472,10 +474,11 @@ int cons_options (inpacket, outpacket,
 
 /* Store all the requested options into the requested buffer. */
 
-int store_options (buffer, buflen, options, priority_list, priority_len,
+int store_options (buffer, buflen, lease, options, priority_list, priority_len,
                   first_cutoff, second_cutoff, terminate)
        unsigned char *buffer;
        int buflen;
+       struct lease *lease;
        struct option_state *options;
        int *priority_list;
        int priority_len;
@@ -534,7 +537,8 @@ int store_options (buffer, buflen, options, priority_list, priority_len,
                }
 
                /* Find the value of the option... */
-               evaluate_option_cache (&od, (struct packet *)0, options, oc);
+               evaluate_option_cache (&od, (struct packet *)0,
+                                      options, lease, oc);
                if (!od.len) {
                        continue;
                }
@@ -805,7 +809,8 @@ void do_packet (interface, packet, len, from_port, from, hfrom)
                                 DHO_DHCP_MESSAGE_TYPE))) {
                struct data_string dp;
                memset (&dp, 0, sizeof dp);
-               evaluate_option_cache (&dp, &tp, tp.options, op);
+               evaluate_option_cache (&dp, &tp, tp.options,
+                                      (struct lease *)0, op);
                if (dp.len > 0)
                        tp.packet_type = dp.data [0];
                else
@@ -821,9 +826,11 @@ void do_packet (interface, packet, len, from_port, from, hfrom)
        option_state_dereference (&tp.options, "do_packet");
 }
 
-int hashed_option_get (result, universe, options, code)
+int hashed_option_get (result, universe, packet, lease, options, code)
        struct data_string *result;
        struct universe *universe;
+       struct packet *packet;
+       struct lease *lease;
        struct option_state *options;
        int code;
 {
@@ -834,14 +841,17 @@ int hashed_option_get (result, universe, options, code)
        oc = ((*universe -> lookup_func) (universe, options, code));
        if (!oc)
                return 0;
-       if (!evaluate_option_cache (result, (struct packet *)0, options, oc))
+       if (!evaluate_option_cache (result, packet,
+                                   options, lease, oc))
                return 0;
        return 1;
 }
 
-int agent_option_get (result, universe, options, code)
+int agent_option_get (result, universe, packet, lease, options, code)
        struct data_string *result;
        struct universe *universe;
+       struct packet *packet;
+       struct lease *lease;
        struct option_state *options;
        int code;
 {
@@ -1204,9 +1214,10 @@ int agent_option_state_dereference (universe, state)
        return 1;
 }
 
-int store_option (result, universe, oc)
+int store_option (result, universe, lease, oc)
        struct data_string *result;
        struct universe *universe;
+       struct lease *lease;
        struct option_cache *oc;
 {
        struct data_string d1, d2;
@@ -1215,7 +1226,7 @@ int store_option (result, universe, oc)
        memset (&d2, 0, sizeof d2);
 
        if (evaluate_option_cache (&d2, (struct packet *)0,
-                                  (struct option_state *)0, oc)) {
+                                  (struct option_state *)0, lease, oc)) {
                if (!buffer_allocate (&d1.buffer,
                                      (result -> len +
                                       universe -> length_size +
@@ -1245,9 +1256,10 @@ int store_option (result, universe, oc)
        return 0;
 }
        
-int option_space_encapsulate (result, options, name)
+int option_space_encapsulate (result, options, lease, name)
        struct data_string *result;
        struct option_state *options;
+       struct lease *lease;
        struct data_string *name;
 {
        struct universe *u;
@@ -1260,15 +1272,16 @@ int option_space_encapsulate (result, options, name)
        }
 
        if (u -> encapsulate)
-               return (*u -> encapsulate) (result, options, u);
+               return (*u -> encapsulate) (result, options, lease, u);
        log_error ("encapsulation requested for %s with no support.",
                   name -> data);
        return 0;
 }
 
-int hashed_option_space_encapsulate (result, options, universe)
+int hashed_option_space_encapsulate (result, options, lease, universe)
        struct data_string *result;
        struct option_state *options;
+       struct lease *lease;
        struct universe *universe;
 {
        pair p, *hash;
@@ -1285,7 +1298,7 @@ int hashed_option_space_encapsulate (result, options, universe)
        status = 0;
        for (i = 0; i < OPTION_HASH_SIZE; i++) {
                for (p = hash [i]; p; p = p -> cdr) {
-                       if (store_option (result, universe,
+                       if (store_option (result, universe, lease,
                                          (struct option_cache *)p -> car))
                                status = 1;
                }
index ab44c8f930553c01391ba3e40a9f38d1b7f1dc0e..19ae0d7eb74a1944315c33245dbf709d65f2e033 100644 (file)
@@ -22,7 +22,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: parse.c,v 1.25 1999/07/01 18:53:46 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: parse.c,v 1.26 1999/07/02 20:57:25 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -1676,6 +1676,76 @@ int parse_non_binary (expr, cfile, lose, context)
                        goto norparen;
                break;
 
+             case BINARY_TO_ASCII:
+               token = next_token (&val, cfile);
+               if (!expression_allocate (expr, "parse_expression: B2A"))
+                       log_fatal ("can't allocate expression");
+               (*expr) -> op = expr_concat;
+
+               token = next_token (&val, cfile);
+               if (token != LPAREN)
+                       goto nolparen;
+
+               if (!parse_numeric_expression (&(*expr) -> data.b2a.base,
+                                              cfile, lose))
+                       goto nodata;
+
+               token = next_token (&val, cfile);
+               if (token != COMMA)
+                       goto nocomma;
+
+               if (!parse_numeric_expression (&(*expr) -> data.b2a.width,
+                                              cfile, lose))
+                       goto nodata;
+
+               token = next_token (&val, cfile);
+               if (token != COMMA)
+                       goto nocomma;
+
+               if (!parse_data_expression (&(*expr) -> data.b2a.seperator,
+                                           cfile, lose))
+                       goto nodata;
+
+               token = next_token (&val, cfile);
+               if (token != COMMA)
+                       goto nocomma;
+
+               if (!parse_data_expression (&(*expr) -> data.b2a.buffer,
+                                           cfile, lose))
+                       goto nodata;
+
+               token = next_token (&val, cfile);
+               if (token != RPAREN)
+                       goto norparen;
+               break;
+
+             case REVERSE:
+               token = next_token (&val, cfile);
+               if (!expression_allocate (expr, "parse_expression: REVERSE"))
+                       log_fatal ("can't allocate expression");
+               (*expr) -> op = expr_concat;
+
+               token = next_token (&val, cfile);
+               if (token != LPAREN)
+                       goto nolparen;
+
+               if (!(parse_numeric_expression
+                     (&(*expr) -> data.reverse.width, cfile, lose)))
+                       goto nodata;
+
+               token = next_token (&val, cfile);
+               if (token != COMMA)
+                       goto nocomma;
+
+               if (!(parse_data_expression
+                     (&(*expr) -> data.reverse.buffer, cfile, lose)))
+                       goto nodata;
+
+               token = next_token (&val, cfile);
+               if (token != RPAREN)
+                       goto norparen;
+               break;
+
              case OPTION:
                token = next_token (&val, cfile);
                if (!expression_allocate (expr, "parse_expression: OPTION"))
@@ -1697,6 +1767,14 @@ int parse_non_binary (expr, cfile, lose, context)
                (*expr) -> op = expr_hardware;
                break;
 
+             case LEASED_ADDRESS:
+               token = next_token (&val, cfile);
+               if (!expression_allocate (expr,
+                                         "parse_expression: LEASED_ADDRESS"))
+                       log_fatal ("can't allocate expression");
+               (*expr) -> op = expr_leased_address;
+               break;
+
              case PACKET:
                token = next_token (&val, cfile);
                if (!expression_allocate (expr, "parse_expression: PACKET"))
index ae6a28416f28c5e74e66a165322efb85c3074ce6..618ea80304ca36a66518bfa1abae56d9ad00e9a6 100644 (file)
@@ -22,7 +22,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: tree.c,v 1.29 1999/05/27 14:30:00 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: tree.c,v 1.30 1999/07/02 20:57:26 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -378,10 +378,11 @@ int do_host_lookup (result, dns)
        return 1;
 }
 
-int evaluate_boolean_expression (result, packet, options, expr)
+int evaluate_boolean_expression (result, packet, options, lease, expr)
        int *result;
        struct packet *packet;
        struct option_state *options;
+       struct lease *lease;
        struct expression *expr;
 {
        struct data_string left, right;
@@ -390,7 +391,8 @@ int evaluate_boolean_expression (result, packet, options, expr)
 
        switch (expr -> op) {
              case expr_check:
-               *result = check_collection (packet, expr -> data.check);
+               *result = check_collection (packet, lease,
+                                           expr -> data.check);
 #if defined (DEBUG_EXPRESSIONS)
                log_info ("bool: check (%s) returns %s",
                      expr -> data.check -> name, *result ? "true" : "false");
@@ -400,9 +402,11 @@ int evaluate_boolean_expression (result, packet, options, expr)
              case expr_equal:
                memset (&left, 0, sizeof left);
                sleft = evaluate_data_expression (&left, packet, options,
+                                                 lease,
                                                  expr -> data.equal [0]);
                memset (&right, 0, sizeof right);
                sright = evaluate_data_expression (&right, packet, options,
+                                                  lease,
                                                   expr -> data.equal [1]);
                if (sleft && sright) {
                        if (left.len == right.len &&
@@ -431,8 +435,10 @@ int evaluate_boolean_expression (result, packet, options, expr)
 
              case expr_and:
                sleft = evaluate_boolean_expression (&bleft, packet, options,
+                                                    lease,
                                                     expr -> data.and [0]);
                sright = evaluate_boolean_expression (&bright, packet, options,
+                                                     lease,
                                                      expr -> data.and [1]);
 
 #if defined (DEBUG_EXPRESSIONS)
@@ -450,8 +456,10 @@ int evaluate_boolean_expression (result, packet, options, expr)
 
              case expr_or:
                sleft = evaluate_boolean_expression (&bleft, packet, options,
+                                                    lease,
                                                     expr -> data.or [0]);
                sright = evaluate_boolean_expression (&bright, packet, options,
+                                                     lease,
                                                      expr -> data.or [1]);
 #if defined (DEBUG_EXPRESSIONS)
                log_info ("bool: or (%s, %s) = %s",
@@ -468,6 +476,7 @@ int evaluate_boolean_expression (result, packet, options, expr)
 
              case expr_not:
                sleft = evaluate_boolean_expression (&bleft, packet, options,
+                                                    lease,
                                                     expr -> data.not);
 #if defined (DEBUG_EXPRESSIONS)
                log_info ("bool: not (%s) = %s",
@@ -487,7 +496,7 @@ int evaluate_boolean_expression (result, packet, options, expr)
                if (!options ||
                    !((*expr -> data.option -> universe -> get_func)
                      (&left, expr -> data.exists -> universe,
-                      options, expr -> data.exists -> code)))
+                      packet, lease, options, expr -> data.exists -> code)))
                        *result = 0;
                else {
                        *result = 1;
@@ -527,6 +536,9 @@ int evaluate_boolean_expression (result, packet, options, expr)
              case expr_encode_int8:
              case expr_encode_int16:
              case expr_encode_int32:
+             case expr_binary_to_ascii:
+             case expr_reverse:
+             case expr_leased_address:
                log_error ("Data opcode in evaluate_boolean_expression: %d",
                      expr -> op);
                return 0;
@@ -545,28 +557,31 @@ int evaluate_boolean_expression (result, packet, options, expr)
        return 0;
 }
 
-int evaluate_data_expression (result, packet, options, expr)
+int evaluate_data_expression (result, packet, options, lease, expr)
        struct data_string *result;
        struct packet *packet;
        struct option_state *options;
+       struct lease *lease;
        struct expression *expr;
 {
        struct data_string data, other;
        unsigned long offset, len;
        int s0, s1, s2, s3;
+       int status;
 
        switch (expr -> op) {
                /* Extract N bytes starting at byte M of a data string. */
              case expr_substring:
                memset (&data, 0, sizeof data);
                s0 = evaluate_data_expression (&data, packet, options,
+                                              lease,
                                               expr -> data.substring.expr);
 
                /* Evaluate the offset and length. */
                s1 = evaluate_numeric_expression
-                       (&offset,
-                        packet, options, expr -> data.substring.offset);
-               s2 = evaluate_numeric_expression (&len, packet, options,
+                       (&offset, packet, options, lease,
+                        expr -> data.substring.offset);
+               s2 = evaluate_numeric_expression (&len, packet, options, lease,
                                                  expr -> data.substring.len);
 
                if (s0 && s1 && s2) {
@@ -604,10 +619,10 @@ int evaluate_data_expression (result, packet, options, expr)
                /* Extract the last N bytes of a data string. */
              case expr_suffix:
                memset (&data, 0, sizeof data);
-               s0 = evaluate_data_expression (&data, packet, options,
+               s0 = evaluate_data_expression (&data, packet, options, lease,
                                               expr -> data.suffix.expr);
                /* Evaluate the length. */
-               s1 = evaluate_numeric_expression (&len, packet, options,
+               s1 = evaluate_numeric_expression (&len, packet, options, lease,
                                                  expr -> data.substring.len);
                if (s0 && s1) {
                        data_string_copy (result, &data,
@@ -639,7 +654,8 @@ int evaluate_data_expression (result, packet, options, expr)
                if (options)
                        s0 = ((*expr -> data.option -> universe -> get_func)
                              (result, expr -> data.option -> universe,
-                              options, expr -> data.option -> code));
+                              packet, lease, options,
+                              expr -> data.option -> code));
                else
                        s0 = 0;
 
@@ -688,9 +704,10 @@ int evaluate_data_expression (result, packet, options, expr)
                        return 0;
                }
 
-               s0 = evaluate_numeric_expression (&len, packet, options,
+               s0 = evaluate_numeric_expression (&len, packet, options, lease,
                                                  expr -> data.packet.len);
-               s1 = evaluate_numeric_expression (&offset, packet, options,
+               s1 = evaluate_numeric_expression (&offset,
+                                                 packet, options, lease,
                                                  expr -> data.packet.len);
                if (s0 && s1 && offset < packet -> packet_length) {
                        if (offset + len > packet -> packet_length)
@@ -725,7 +742,8 @@ int evaluate_data_expression (result, packet, options, expr)
              case expr_encapsulate:
                if (options)
                        s0 = option_space_encapsulate
-                               (result, options, &expr -> data.encapsulate);
+                               (result, options, lease,
+                                &expr -> data.encapsulate);
                else
                        s0 = 0;
 
@@ -764,10 +782,10 @@ int evaluate_data_expression (result, packet, options, expr)
                /* Concatenation... */
              case expr_concat:
                memset (&data, 0, sizeof data);
-               s0 = evaluate_data_expression (&data, packet, options,
+               s0 = evaluate_data_expression (&data, packet, options, lease,
                                               expr -> data.concat [0]);
                memset (&other, 0, sizeof other);
-               s1 = evaluate_data_expression (&other, packet, options,
+               s1 = evaluate_data_expression (&other, packet, options, lease,
                                               expr -> data.concat [1]);
 
                if (s0 && s1) {
@@ -801,7 +819,7 @@ int evaluate_data_expression (result, packet, options, expr)
                return s0 || s1;
 
              case expr_encode_int8:
-               s0 = evaluate_numeric_expression (&len, packet, options,
+               s0 = evaluate_numeric_expression (&len, packet, options, lease,
                                                  expr -> data.packet.len);
                if (s0) {
                        result -> len = 1;
@@ -829,7 +847,7 @@ int evaluate_data_expression (result, packet, options, expr)
                        
                
              case expr_encode_int16:
-               s0 = evaluate_numeric_expression (&len, packet, options,
+               s0 = evaluate_numeric_expression (&len, packet, options, lease,
                                                  expr -> data.packet.len);
                if (s0) {
                        result -> len = 2;
@@ -856,7 +874,7 @@ int evaluate_data_expression (result, packet, options, expr)
                return s0;
 
              case expr_encode_int32:
-               s0 = evaluate_numeric_expression (&len, packet, options,
+               s0 = evaluate_numeric_expression (&len, packet, options, lease,
                                                  expr -> data.packet.len);
                if (s0) {
                        result -> len = 4;
@@ -882,6 +900,212 @@ int evaluate_data_expression (result, packet, options, expr)
 #endif
                return s0;
 
+             case expr_binary_to_ascii:
+               /* Evaluate the base (offset) and width (len): */
+               s0 = evaluate_numeric_expression
+                       (&offset, packet, options, lease,
+                        expr -> data.substring.offset);
+               s1 = evaluate_numeric_expression (&len, packet, options, lease,
+                                                 expr -> data.substring.len);
+
+               /* Evaluate the seperator string. */
+               memset (&data, 0, sizeof data);
+               s2 = evaluate_data_expression (&data, packet, options, lease,
+                                              expr -> data.b2a.seperator);
+
+               /* Evaluate the data to be converted. */
+               memset (&other, 0, sizeof other);
+               s3 = evaluate_data_expression (&data, packet, options, lease,
+                                              expr -> data.b2a.buffer);
+
+               if (s0 && s1 && s2 && s3) {
+                       int buflen, i;
+
+                       if (len != 8 && len != 16 && len != 32) {
+                               log_info ("binary_to_ascii: %s %d!",
+                                         "invalid width", len);
+                               goto b2a_out;
+                       }
+                       len /= 8;
+
+                       /* The buffer must be a multiple of the number's
+                          width. */
+                       if (other.len % len) {
+                               log_info ("binary-to-ascii: %s %d %s %d!",
+                                         "length of buffer", other.len,
+                                         "not a multiple of width", len);
+                               status = 0;
+                               goto b2a_out;
+                       }
+
+                       /* Count the width of the output. */
+                       buflen = 0;
+                       for (i = 0; i < other.len; i += len) {
+                               if (len == 1) {
+                                       if (offset == 8) {
+                                               if (other.data [i] < 8)
+                                                       buflen++;
+                                               else if (other.data [i] < 64)
+                                                       buflen += 2;
+                                               else
+                                                       buflen += 3;
+                                       } else if (offset == 10) {
+                                               if (other.data [i] < 10)
+                                                       buflen++;
+                                               else if (other.data [i] < 100)
+                                                       buflen += 2;
+                                               else
+                                                       buflen += 3;
+                                       } else if (offset == 10) {
+                                               if (other.data [i] < 16)
+                                                       buflen++;
+                                               else
+                                                       buflen += 2;
+                                       } else
+                                               buflen += (converted_length
+                                                          (&other.data [i],
+                                                           offset, 1));
+                               } else
+                                       buflen += (converted_length
+                                                  (&other.data [i],
+                                                   offset, len));
+                               if (i + len != other.len)
+                                       buflen += data.len;
+                       }
+
+                       if (!buffer_allocate (&result -> buffer, buflen + 1,
+                                             "binary-to-ascii")) {
+                               log_error ("data: binary-to-ascii: no memory");
+                               status = 0;
+                               goto b2a_out;
+                       }
+                       result -> data = &result -> buffer -> data [0];
+                       result -> len = buflen;
+                       result -> terminated = 1;
+
+                       buflen = 0;
+                       for (i = 0; i < other.len; i += len) {
+                               buflen += (binary_to_ascii
+                                          (&result -> data [buflen],
+                                           &other.data [i], offset, len));
+                               if (i + len != other.len) {
+                                       memcpy (&result -> data [buflen],
+                                               data.data, data.len);
+                                       buflen += data.len;
+                               }
+                       }
+                       /* NUL terminate. */
+                       result -> data [buflen] = 0;
+                       status = 1;
+               } else
+                       status = 0;
+
+             b2a_out:
+#if defined (DEBUG_EXPRESSIONS)
+               log_info ("data: binary-to-ascii (%s, %s, %s, %s) = %s",
+                     s0 ? print_dec_1 (offset) : "NULL",
+                     s1 ? print_dec_2 (len) : "NULL",
+                     s2 ? print_hex_1 (data.len, data.data, 30) : "NULL",
+                     s3 ? print_hex_2 (other.len, other.data, 30) : "NULL",
+                     (status ? print_hex_3 (result -> len, result -> data, 30)
+                         : "NULL"));
+#endif
+               if (s2)
+                       data_string_forget (&data, "binary-to-ascii");
+               if (s3)
+                       data_string_forget (&other, "binary-to-ascii");
+               if (status)
+                       return 1;
+               return 0;
+
+             case expr_reverse:
+               /* Evaluate the width (len): */
+               s0 = evaluate_numeric_expression
+                       (&len, packet, options, lease,
+                        expr -> data.substring.offset);
+
+               /* Evaluate the data. */
+               memset (&data, 0, sizeof data);
+               s1 = evaluate_data_expression (&data, packet, options, lease,
+                                              expr -> data.b2a.seperator);
+
+               if (len != 8 && len != 16 && len != 32) {
+                       log_info ("reverse: invalid width %d!", len);
+                       goto b2a_out;
+               }
+               len /= 8;
+
+               if (s0 && s1) {
+                       char *upper;
+                       int i;
+
+                       /* The buffer must be a multiple of the number's
+                          width. */
+                       if (other.len % len) {
+                               log_info ("binary-to-ascii: %s %d %s %d!",
+                                         "length of buffer", other.len,
+                                         "not a multiple of width", len);
+                               status = 0;
+                               goto reverse_out;
+                       }
+
+                       /* XXX reverse in place?   I don't think we can. */
+                       if (!buffer_allocate (&result -> buffer, data.len,
+                                             "reverse")) {
+                               log_error ("data: reverse: no memory");
+                               status = 0;
+                               goto reverse_out;
+                       }
+                       result -> data = &result -> buffer -> data [0];
+                       result -> len = data.len;
+                       result -> terminated = 0;
+
+                       for (i = 0; i < data.len; i += len) {
+                               memcpy (&result -> data [i],
+                                       &data.data [data.len - i - len], len);
+                       }
+                       status = 1;
+               } else
+                       status = 0;
+
+             reverse_out:
+#if defined (DEBUG_EXPRESSIONS)
+               log_info ("data: reverse (%s, %s) = %s",
+                     s0 ? print_dec_1 (offset) : "NULL",
+                     s1 ? print_hex_1 (data.len, data.data, 30) : "NULL",
+                     (status ? print_hex_3 (result -> len, result -> data, 30)
+                         : "NULL"));
+#endif
+               if (s0)
+                       data_string_forget (&data, "evaluate_data_expression");
+               if (status)
+                       return 1;
+               return 0;
+
+             case expr_leased_address:
+               if (!lease) {
+                       log_error ("data: leased_address: not available");
+                       return 0;
+               }
+               result -> len = lease -> ip_addr.len;
+               if (buffer_allocate (&result -> buffer, result -> len,
+                                    "leased-address")) {
+                       result -> data = &result -> buffer -> data [0];
+                       memcpy (&result -> data [0],
+                               lease -> ip_addr.iabuf, lease -> ip_addr.len);
+                       result -> terminated = 0;
+               } else {
+                       log_error ("data: leased-address: no memory.");
+                       return 0;
+               }
+#if defined (DEBUG_EXPRESSIONS)
+               log_info ("data: leased-address = %s",
+                     print_hex_1 (result -> len, result -> data, 60));
+#endif
+               return 1;
+
+               
+
              case expr_check:
              case expr_equal:
              case expr_and:
@@ -906,10 +1130,11 @@ int evaluate_data_expression (result, packet, options, expr)
        return 0;
 }      
 
-int evaluate_numeric_expression (result, packet, options, expr)
+int evaluate_numeric_expression (result, packet, options, lease, expr)
        unsigned long *result;
        struct packet *packet;
        struct option_state *options;
+       struct lease *lease;
        struct expression *expr;
 {
        struct data_string data;
@@ -939,6 +1164,9 @@ int evaluate_numeric_expression (result, packet, options, expr)
              case expr_encode_int8:
              case expr_encode_int16:
              case expr_encode_int32:
+             case expr_binary_to_ascii:
+             case expr_reverse:
+             case expr_leased_address:
                log_error ("Data opcode in evaluate_numeric_expression: %d",
                      expr -> op);
                return 0;
@@ -947,7 +1175,7 @@ int evaluate_numeric_expression (result, packet, options, expr)
                memset (&data, 0, sizeof data);
                status = evaluate_data_expression
                        (&data, packet,
-                        options, expr -> data.extract_int);
+                        options, lease, expr -> data.extract_int);
                if (status)
                        *result = data.data [0];
 #if defined (DEBUG_EXPRESSIONS)
@@ -962,7 +1190,7 @@ int evaluate_numeric_expression (result, packet, options, expr)
              case expr_extract_int16:
                memset (&data, 0, sizeof data);
                status = (evaluate_data_expression
-                         (&data, packet, options,
+                         (&data, packet, options, lease,
                           expr -> data.extract_int));
                if (status && data.len >= 2)
                        *result = getUShort (data.data);
@@ -979,7 +1207,7 @@ int evaluate_numeric_expression (result, packet, options, expr)
              case expr_extract_int32:
                memset (&data, 0, sizeof data);
                status = (evaluate_data_expression
-                         (&data, packet, options,
+                         (&data, packet, options, lease,
                           expr -> data.extract_int));
                if (status && data.len >= 4)
                        *result = getULong (data.data);
@@ -1007,10 +1235,11 @@ int evaluate_numeric_expression (result, packet, options, expr)
    result of that evaluation.   There should never be both an expression
    and a valid data_string. */
 
-int evaluate_option_cache (result, packet, options, oc)
+int evaluate_option_cache (result, packet, options, lease, oc)
        struct data_string *result;
        struct packet *packet;
        struct option_state *options;
+       struct lease *lease;
        struct option_cache *oc;
 {
        if (oc -> data.len) {
@@ -1020,16 +1249,17 @@ int evaluate_option_cache (result, packet, options, oc)
        }
        if (!oc -> expression)
                return 0;
-       return evaluate_data_expression (result,
-                                        packet, options, oc -> expression);
+       return evaluate_data_expression (result, packet, options, lease,
+                                        oc -> expression);
 }
 
 /* Evaluate an option cache and extract a boolean from the result,
    returning the boolean.   Return false if there is no data. */
 
-int evaluate_boolean_option_cache (packet, options, oc)
+int evaluate_boolean_option_cache (packet, options, lease, oc)
        struct packet *packet;
        struct option_state *options;
+       struct lease *lease;
        struct option_cache *oc;
 {
        struct data_string ds;
@@ -1040,7 +1270,7 @@ int evaluate_boolean_option_cache (packet, options, oc)
                return 0;
        
        memset (&ds, 0, sizeof ds);
-       if (!evaluate_option_cache (&ds, packet, options, oc))
+       if (!evaluate_option_cache (&ds, packet, options, lease, oc))
                return 0;
 
        if (ds.len && ds.data [0])
@@ -1055,9 +1285,10 @@ int evaluate_boolean_option_cache (packet, options, oc)
 /* Evaluate a boolean expression and return the result of the evaluation,
    or FALSE if it failed. */
 
-int evaluate_boolean_expression_result (packet, options, expr)
+int evaluate_boolean_expression_result (packet, options, lease, expr)
        struct packet *packet;
        struct option_state *options;
+       struct lease *lease;
        struct expression *expr;
 {
        int result;
@@ -1066,7 +1297,8 @@ int evaluate_boolean_expression_result (packet, options, expr)
        if (!expr)
                return 0;
        
-       if (!evaluate_boolean_expression (&result, packet, options, expr))
+       if (!evaluate_boolean_expression (&result,
+                                         packet, options, lease, expr))
                return 0;
 
        return result;
@@ -1172,7 +1404,30 @@ void expression_dereference (eptr, name)
                                                    name);
                break;
 
+             case expr_binary_to_ascii:
+               if (expr -> data.b2a.base)
+                       expression_dereference (&expr -> data.b2a.base, name);
+               if (expr -> data.b2a.width)
+                       expression_dereference (&expr -> data.b2a.width, name);
+               if (expr -> data.b2a.seperator)
+                       expression_dereference (&expr -> data.b2a.seperator,
+                                               name);
+               if (expr -> data.b2a.buffer)
+                       expression_dereference (&expr -> data.b2a.buffer,
+                                               name);
+               break;
+
+             case expr_reverse:
+               if (expr -> data.reverse.width)
+                       expression_dereference (&expr -> data.reverse.width,
+                                               name);
+               if (expr -> data.reverse.buffer)
+                       expression_dereference
+                               (&expr -> data.reverse.buffer, name);
+               break;
+
                /* No subexpressions. */
+             case expr_leased_address:
              case expr_const_int:
              case expr_check:
              case expr_option:
@@ -1253,7 +1508,10 @@ int is_data_expression (expr)
                expr -> op == expr_encode_int8 ||
                expr -> op == expr_encode_int16 ||
                expr -> op == expr_encode_int32 ||
-               expr -> op == expr_host_lookup);
+               expr -> op == expr_host_lookup ||
+               expr -> op == expr_binary_to_ascii ||
+               expr -> op == expr_reverse ||
+               expr -> op == expr_leased_address);
 }
 
 int is_numeric_expression (expr)
@@ -1293,6 +1551,9 @@ static int op_val (op)
              case expr_const_int:
              case expr_exists:
              case expr_known:
+             case expr_binary_to_ascii:
+             case expr_reverse:
+             case expr_leased_address:
                return 100;
 
              case expr_equal:
@@ -1319,6 +1580,7 @@ enum expression_context op_context (op)
        enum expr_op op;
 {
        switch (op) {
+/* XXX Why aren't these specific? */
              case expr_none:
              case expr_match:
              case expr_check:
@@ -1341,6 +1603,9 @@ enum expression_context op_context (op)
              case expr_const_int:
              case expr_exists:
              case expr_known:
+             case expr_binary_to_ascii:
+             case expr_reverse:
+             case expr_leased_address:
                return context_any;
 
              case expr_equal:
index 741b80f8f5640006a85a5dedac890476e37c5d25..ebb19ccb21065c6fbe04ca992f640add9bad979b 100644 (file)
@@ -773,20 +773,23 @@ typedef unsigned char option_mask [16];
 int parse_options PROTO ((struct packet *));
 int parse_option_buffer PROTO ((struct packet *, unsigned char *, int));
 int parse_agent_information_option PROTO ((struct packet *, int, u_int8_t *));
-int cons_options PROTO ((struct packet *, struct dhcp_packet *, int,
-                        struct option_state *,
+int cons_options PROTO ((struct packet *, struct dhcp_packet *, struct lease *,
+                        int, struct option_state *,
                         int, int, int, struct data_string *));
-int store_options PROTO ((unsigned char *, int, struct option_state *,
-                          int *, int, int, int, int));
+int store_options PROTO ((unsigned char *, int,
+                         struct lease *, struct option_state *,
+                         int *, int, int, int, int));
 char *pretty_print_option PROTO ((unsigned int,
                                  unsigned char *, int, int, int));
 void do_packet PROTO ((struct interface_info *,
                       struct dhcp_packet *, int,
                       unsigned int, struct iaddr, struct hardware *));
-int hashed_option_get PROTO ((struct data_string *,
-                             struct universe *, struct option_state *, int));
+int hashed_option_get PROTO ((struct data_string *, struct universe *,
+                             struct packet *, struct lease *,
+                             struct option_state *, int));
 int agent_option_get PROTO ((struct data_string *, struct universe *,
-                               struct option_state *, int));
+                             struct packet *, struct lease *,
+                            struct option_state *, int));
 void hashed_option_set PROTO ((struct universe *, struct option_state *,
                               struct option_cache *,
                               enum statement_op));
@@ -807,15 +810,19 @@ int hashed_option_state_dereference PROTO ((struct universe *,
 int agent_option_state_dereference PROTO ((struct universe *,
                                           struct option_state *));
 int store_option PROTO ((struct data_string *,
-                 struct universe *, struct option_cache *));
+                        struct universe *, struct lease *,
+                        struct option_cache *));
 int option_space_encapsulate PROTO ((struct data_string *,
                                     struct option_state *,
+                                    struct lease *,
                                     struct data_string *));
 int hashed_option_space_encapsulate PROTO ((struct data_string *,
                                            struct option_state *,
+                                           struct lease *,
                                            struct universe *));
 int agent_option_space_encapsulate PROTO ((struct data_string *,
                                           struct option_state *,
+                                          struct lease *,
                                           struct universe *));
 
 /* errwarn.c */
@@ -934,22 +941,27 @@ int option_cache PROTO ((struct option_cache **, struct data_string *,
                         struct expression *, struct option *));
 int evaluate_boolean_expression PROTO ((int *,
                                        struct packet *, struct option_state *,
+                                       struct lease *,
                                        struct expression *));
 int evaluate_data_expression PROTO ((struct data_string *,
                                     struct packet *, struct option_state *,
+                                    struct lease *,
                                     struct expression *));
 int evaluate_numeric_expression PROTO
        ((unsigned long *, struct packet *,
-         struct option_state *, struct expression *));
+         struct option_state *, struct lease *, struct expression *));
 int evaluate_option_cache PROTO ((struct data_string *,
                                  struct packet *,
                                  struct option_state *,
+                                 struct lease *,
                                  struct option_cache *));
 int evaluate_boolean_option_cache PROTO ((struct packet *,
                                          struct option_state *,
+                                         struct lease *,
                                          struct option_cache *));
 int evaluate_boolean_expression_result PROTO ((struct packet *,
                                               struct option_state *,
+                                              struct lease *,
                                               struct expression *));
 void expression_dereference PROTO ((struct expression **, char *));
 void data_string_copy PROTO ((struct data_string *,
@@ -1302,6 +1314,9 @@ void putLong PROTO ((unsigned char *, int32_t));
 void putUShort PROTO ((unsigned char *, u_int32_t));
 void putShort PROTO ((unsigned char *, int32_t));
 void putUChar PROTO ((unsigned char *, u_int32_t));
+int converted_length PROTO ((unsigned char *, unsigned int, unsigned int));
+int binary_to_ascii PROTO ((unsigned char *, unsigned char *,
+                           unsigned int, unsigned int));
 
 /* inet.c */
 struct iaddr subnet_number PROTO ((struct iaddr, struct iaddr));
@@ -1511,7 +1526,8 @@ struct executable_statement *default_classification_rules;
 
 void classification_setup PROTO ((void));
 void classify_client PROTO ((struct packet *));
-int check_collection PROTO ((struct packet *, struct collection *));
+int check_collection PROTO ((struct packet *, struct lease *,
+                            struct collection *));
 void classify PROTO ((struct packet *, struct class *));
 struct class *find_class PROTO ((char *));
 int unbill_class PROTO ((struct lease *, struct class *));
@@ -1519,9 +1535,11 @@ int bill_class PROTO ((struct lease *, struct class *));
 
 /* execute.c */
 int execute_statements PROTO ((struct packet *,
+                              struct lease *,
                               struct option_state *, struct option_state *,
                               struct executable_statement *));
 void execute_statements_in_scope PROTO ((struct packet *,
+                                        struct lease *,
                                         struct option_state *,
                                         struct option_state *,
                                         struct group *, struct group *));
index b9892497c664258ae92cf3173bac2ed3c23a5f22..0dcf2b65aca8bc27d91d333eed9fdf5c34433f4b 100644 (file)
@@ -179,6 +179,9 @@ enum dhcp_token {
        ENCODE_INT = 399,
        DDNS_FWD_NAME = 400,
        DDNS_REV_NAME = 401,
+       REVERSE = 402,
+       LEASED_ADDRESS = 403,
+       BINARY_TO_ASCII = 404,
 };
 
 #define is_identifier(x)       ((x) >= FIRST_TOKEN &&  \
index f8589f9747370006fc7af2b1d8d5c8685bac3df6..5a44e1f36f7b2bdece41185883d48f13d24c4457 100644 (file)
@@ -83,6 +83,9 @@ enum expr_op {
        expr_exists,
        expr_encapsulate,
        expr_known,
+       expr_reverse,
+       expr_leased_address,
+       expr_binary_to_ascii,
 };
 
 struct expression {
@@ -116,6 +119,16 @@ struct expression {
                struct dns_host_entry *host_lookup;
                struct option *exists;
                struct data_string encapsulate;
+               struct {
+                       struct expression *base;
+                       struct expression *width;
+                       struct expression *seperator;
+                       struct expression *buffer;
+               } b2a;
+               struct {
+                       struct expression *width;
+                       struct expression *buffer;
+               } reverse;
        } data;
        int flags;
 #      define EXPR_EPHEMERAL   1
@@ -134,6 +147,7 @@ struct data_string; /* forward */
 struct packet; /* forward */
 struct option_state; /* forward */
 struct decoded_option_state; /* forward */
+struct lease; /* forward */
 
 struct universe {
        char *name;
@@ -143,6 +157,7 @@ struct universe {
        void (*save_func) PROTO ((struct universe *, struct option_state *,
                                  struct option_cache *));
        int (*get_func) PROTO ((struct data_string *, struct universe *,
+                               struct packet *, struct lease *,
                                struct option_state *, int));
        void (*set_func) PROTO ((struct universe *, struct option_state *,
                                 struct option_cache *, enum statement_op));
@@ -152,7 +167,7 @@ struct universe {
        int (*option_state_dereference) PROTO ((struct universe *,
                                                struct option_state *));
        int (*encapsulate) PROTO ((struct data_string *, struct option_state *,
-                                  struct universe *));
+                                  struct lease *, struct universe *));
        void (*store_tag) PROTO ((unsigned char *, u_int32_t));
        void (*store_length) PROTO ((unsigned char *, u_int32_t));
        int tag_size, length_size;
index 18612cc06a48098bcfbc0c51fd035bb58f4acd89..5bb62968f3d27e45fd2430f378d15e5f12a31013 100644 (file)
@@ -22,7 +22,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: bootp.c,v 1.49 1999/07/01 20:02:58 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: bootp.c,v 1.50 1999/07/02 20:58:48 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -117,24 +117,24 @@ void bootp (packet)
        option_state_allocate (&options, "bootrequest");
        
        /* Execute the subnet statements. */
-       execute_statements_in_scope (packet, packet -> options, options,
+       execute_statements_in_scope (packet, lease, packet -> options, options,
                                     lease -> subnet -> group,
                                     (struct group *)0);
        
        /* Execute statements from class scopes. */
        for (i = packet -> class_count; i > 0; i--) {
                execute_statements_in_scope
-                       (packet, packet -> options, options,
+                       (packet, lease, packet -> options, options,
                         packet -> classes [i - 1] -> group,
                         lease -> subnet -> group);
        }
 
        /* Execute the host statements. */
-       execute_statements_in_scope (packet, packet -> options, options,
+       execute_statements_in_scope (packet, lease, packet -> options, options,
                                     hp -> group, subnet -> group);
        
        /* Drop the request if it's not allowed for this client. */
-       if (evaluate_boolean_option_cache (packet, options,
+       if (evaluate_boolean_option_cache (packet, options, lease,
                                           lookup_option (&server_universe,
                                                          options,
                                                          SV_ALLOW_BOOTP))) {
@@ -143,7 +143,7 @@ void bootp (packet)
                return;
        } 
 
-       if (evaluate_boolean_option_cache (packet, options,
+       if (evaluate_boolean_option_cache (packet, options, lease,
                                           lookup_option (&server_universe,
                                                          options,
                                                          SV_ALLOW_BOOTING))) {
@@ -161,7 +161,7 @@ void bootp (packet)
           just copy the input options to the output. */
        if (!packet -> options_valid &&
            !(evaluate_boolean_option_cache
-             (packet, options,
+             (packet, options, lease,
               lookup_option (&server_universe, options,
                              SV_ALWAYS_REPLY_RFC1048)))) {
                memcpy (outgoing.raw -> options,
@@ -194,7 +194,7 @@ void bootp (packet)
                   name buffers. */
 
                outgoing.packet_length =
-                       cons_options (packet, outgoing.raw, 0, options,
+                       cons_options (packet, outgoing.raw, lease, 0, options,
                                      0, 0, 1, (struct data_string *)0);
                if (outgoing.packet_length < BOOTP_MIN_LEN)
                        outgoing.packet_length = BOOTP_MIN_LEN;
@@ -216,14 +216,15 @@ void bootp (packet)
           the broadcast bit in the bootp flags field. */
        if ((oc = lookup_option (&server_universe,
                                options, SV_ALWAYS_BROADCAST)) &&
-           evaluate_boolean_option_cache (packet, packet -> options, oc))
+           evaluate_boolean_option_cache (packet, packet -> options,
+                                          lease, oc))
                raw.flags |= htons (BOOTP_BROADCAST);
 
        /* Figure out the address of the next server. */
        memset (&d1, 0, sizeof d1);
        oc = lookup_option (&server_universe, options, SV_NEXT_SERVER);
        if (oc &&
-           evaluate_option_cache (&d1, packet, options, oc)) {
+           evaluate_option_cache (&d1, packet, options, lease, oc)) {
                /* If there was more than one answer, take the first. */
                if (d1.len >= 4 && d1.data)
                        memcpy (&raw.siaddr, d1.data, 4);
@@ -241,7 +242,7 @@ void bootp (packet)
        /* Figure out the filename. */
        oc = lookup_option (&server_universe, options, SV_FILENAME);
        if (oc &&
-           evaluate_option_cache (&d1, packet, options, oc)) {
+           evaluate_option_cache (&d1, packet, options, lease, oc)) {
                memcpy (raw.file, d1.data,
                        d1.len > sizeof raw.file ? sizeof raw.file : d1.len);
                if (sizeof raw.file > d1.len)
@@ -254,7 +255,7 @@ void bootp (packet)
        /* Choose a server name as above. */
        oc = lookup_option (&server_universe, options, SV_SERVER_NAME);
        if (oc &&
-           evaluate_option_cache (&d1, packet, options, oc)) {
+           evaluate_option_cache (&d1, packet, options, lease, oc)) {
                memcpy (raw.sname, d1.data,
                        d1.len > sizeof raw.sname ? sizeof raw.sname : d1.len);
                if (sizeof raw.sname > d1.len)
index d63de40fb8e661aca9213d164e264988f3442080..90cdc4d02e785d9074904423d5c444c738cb4327 100644 (file)
@@ -22,7 +22,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: class.c,v 1.11 1999/04/05 16:34:33 mellon Exp $ Copyright (c) 1998 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: class.c,v 1.12 1999/07/02 20:58:48 mellon Exp $ Copyright (c) 1998 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -70,13 +70,14 @@ void classification_setup ()
 void classify_client (packet)
        struct packet *packet;
 {
-       execute_statements (packet, packet -> options,
+       execute_statements (packet, (struct lease *)0, packet -> options,
                            (struct option_state *)0,
                            default_classification_rules);
 }
 
-int check_collection (packet, collection)
+int check_collection (packet, lease, collection)
        struct packet *packet;
+       struct lease *lease;
        struct collection *collection;
 {
        struct class *class, *nc;
@@ -92,8 +93,10 @@ int check_collection (packet, collection)
                /* If a class is for billing, don't put the client in the
                   class if we've already billed it to a different class. */
                if (class -> submatch) {
-                       status = evaluate_data_expression (&data, packet,
+                       status = evaluate_data_expression (&data,
+                                                          packet,
                                                           packet -> options,
+                                                          lease,
                                                           class -> submatch);
                        if (status) {
                                if ((nc = ((struct class *)
@@ -159,7 +162,7 @@ int check_collection (packet, collection)
                }
 
                status = (evaluate_boolean_expression_result
-                         (packet, packet -> options, class -> expr));
+                         (packet, packet -> options, lease, class -> expr));
                if (status) {
                        matched = 1;
 #if defined (DEBUG_CLASS_MATCHING)
index 466490a7fb8a6d10ba3dc09daf28c9d6edded37e..f0a0bb29367423c1573bf28c4bd09934334ad354 100644 (file)
@@ -22,7 +22,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: dhcp.c,v 1.97 1999/07/02 17:47:42 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: dhcp.c,v 1.98 1999/07/02 20:58:48 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -122,7 +122,8 @@ void dhcprequest (packet)
                            DHO_DHCP_REQUESTED_ADDRESS);
        memset (&data, 0, sizeof data);
        if (oc &&
-           evaluate_option_cache (&data, packet, packet -> options, oc)) {
+           evaluate_option_cache (&data, packet, packet -> options,
+                                  (struct lease *)0, oc)) {
                cip.len = 4;
                memcpy (cip.iabuf, data.data, 4);
                data_string_forget (&data, "dhcprequest");
@@ -264,7 +265,8 @@ void dhcprelease (packet)
                            DHO_DHCP_CLIENT_IDENTIFIER);
        memset (&data, 0, sizeof data);
        if (oc &&
-           evaluate_option_cache (&data, packet, packet -> options, oc)) {
+           evaluate_option_cache (&data, packet, packet -> options, 
+                                  (struct lease *)0, oc)) {
                lease = find_lease_by_uid (data.data, data.len);
                data_string_forget (&data, "dhcprelease");
        } else
@@ -312,7 +314,8 @@ void dhcpdecline (packet)
                                  DHO_DHCP_REQUESTED_ADDRESS)))
                return;
        memset (&data, 0, sizeof data);
-       if (!evaluate_option_cache (&data, packet, packet -> options, oc))
+       if (!evaluate_option_cache (&data, packet, packet -> options,
+                                   (struct lease *)0, oc))
                return;
 
        cip.len = 4;
@@ -390,14 +393,15 @@ void dhcpinform (packet)
 
        /* Execute statements in scope starting with the subnet scope. */
        if (subnet)
-               execute_statements_in_scope (packet, packet -> options,
+               execute_statements_in_scope (packet, (struct lease *)0,
+                                            packet -> options,
                                             options, subnet -> group,
                                             (struct group *)0);
 
        /* Execute statements in the class scopes. */
        for (i = packet -> class_count; i > 0; i--) {
                execute_statements_in_scope
-                       (packet, packet -> options,
+                       (packet, (struct lease *)0, packet -> options,
                         options, packet -> classes [i - 1] -> group,
                         subnet ? subnet -> group : (struct group *)0);
        }
@@ -405,7 +409,8 @@ void dhcpinform (packet)
        /* Figure out the filename. */
        memset (&d1, 0, sizeof d1);
        oc = lookup_option (&server_universe, options, SV_FILENAME);
-       if (oc && evaluate_option_cache (&d1, packet, packet -> options, oc)) {
+       if (oc && evaluate_option_cache (&d1, packet, packet -> options,
+                                        (struct lease *)0, oc)) {
                i = d1.len;
                if (i > sizeof raw.file)
                        i = sizeof raw.file;
@@ -417,7 +422,8 @@ void dhcpinform (packet)
 
        /* Choose a server name as above. */
        oc = lookup_option (&server_universe, options, SV_SERVER_NAME);
-       if (oc && evaluate_option_cache (&d1, packet, packet -> options, oc)) {
+       if (oc && evaluate_option_cache (&d1, packet, packet -> options,
+                                        (struct lease *)0, oc)) {
                i = d1.len;
                if (i > sizeof raw.sname)
                        i = sizeof raw.sname;
@@ -432,8 +438,8 @@ void dhcpinform (packet)
        nulltp = 0;
        if ((oc = lookup_option (&dhcp_universe, packet -> options,
                                 DHO_HOST_NAME))) {
-               if (evaluate_option_cache (&d1, packet,
-                                          packet -> options, oc)) {
+               if (evaluate_option_cache (&d1, packet, packet -> options,
+                                          (struct lease *)0, oc)) {
                        if (d1.data [d1.len - 1] == '\0')
                                nulltp = 1;
                        data_string_forget (&d1, "dhcpinform");
@@ -471,8 +477,8 @@ void dhcpinform (packet)
                }
                from = packet -> interface -> primary_address;
        } else {
-               if (evaluate_option_cache (&d1, packet,
-                                          packet -> options, oc)) {
+               if (evaluate_option_cache (&d1, packet, packet -> options,
+                                          (struct lease *)0, oc)) {
                        if (!d1.len || d1.len != sizeof from) {
                                data_string_forget (&d1, "dhcpinform");
                                goto use_primary;
@@ -506,7 +512,8 @@ void dhcpinform (packet)
        j = SV_VENDOR_OPTION_SPACE;
        if (!lookup_option (&dhcp_universe, options, i) &&
            (oc = lookup_option (&server_universe, options, j)) &&
-           evaluate_option_cache (&d1, packet, packet -> options, oc)) {
+           evaluate_option_cache (&d1, packet, packet -> options,
+                                  (struct lease *)0, oc)) {
                oc = (struct option_cache *)0;
                if (option_cache_allocate (&oc, "dhcpinform")) {
                        if (make_encapsulation (&oc -> expression, &d1)) {
@@ -522,7 +529,8 @@ void dhcpinform (packet)
           site option codes. */
        i = SV_SITE_OPTION_SPACE;
        if ((oc = lookup_option (&server_universe, options, i)) &&
-           evaluate_option_cache (&d1, packet, packet -> options, oc)) {
+           evaluate_option_cache (&d1, packet,
+                                  packet -> options, (struct lease *)0, oc)) {
                struct universe *u;
                
                u = ((struct universe *)
@@ -555,7 +563,8 @@ void dhcpinform (packet)
                                    DHO_DHCP_PARAMETER_REQUEST_LIST);
 
        if (oc)
-               evaluate_option_cache (&prl, packet, packet -> options, oc);
+               evaluate_option_cache (&prl, packet, packet -> options,
+                                      (struct lease *)0, oc);
 
 #ifdef DEBUG_PACKET
        dump_packet (packet);
@@ -568,8 +577,8 @@ void dhcpinform (packet)
        raw.siaddr = from;
        if ((oc =
             lookup_option (&server_universe, options, SV_NEXT_SERVER))) {
-               if (evaluate_option_cache (&d1, packet,
-                                          packet -> options, oc)) {
+               if (evaluate_option_cache (&d1, packet, packet -> options,
+                                          (struct lease *)0, oc)) {
                        /* If there was more than one answer,
                           take the first. */
                        if (d1.len >= 4 && d1.data)
@@ -580,8 +589,8 @@ void dhcpinform (packet)
 
        /* Set up the option buffer... */
        outgoing.packet_length =
-               cons_options (packet, outgoing.raw, 0, options,
-                             0, nulltp, 0,
+               cons_options (packet, outgoing.raw, (struct lease *)0,
+                             0, options, 0, nulltp, 0,
                              prl.len ? &prl : (struct data_string *)0);
        option_state_dereference (&options, "dhcpinform");
        data_string_forget (&prl, "dhcpinform");
@@ -690,8 +699,8 @@ void nak_lease (packet, cip)
 
        /* Set up the option buffer... */
        outgoing.packet_length =
-               cons_options (packet, outgoing.raw, 0, options,
-                             0, 0, 0,
+               cons_options (packet, outgoing.raw, (struct lease *)0,
+                             0, options, 0, 0, 0,
                              (struct data_string *)0);
        option_state_dereference (&options, "nak_lease");
 
@@ -810,8 +819,8 @@ void ack_lease (packet, lease, offer, when, msg)
        oc = lookup_option (&dhcp_universe, packet -> options, DHO_HOST_NAME);
        memset (&d1, 0, sizeof d1);
        if (oc)
-               s1 = evaluate_option_cache (&d1, packet,
-                                           packet -> options, oc);
+               s1 = evaluate_option_cache (&d1, packet, packet -> options,
+                                           (struct lease *)0, oc);
        if (oc && status &&
            lease -> client_hostname &&
            strlen (lease -> client_hostname) == d1.len &&
@@ -844,14 +853,16 @@ void ack_lease (packet, lease, offer, when, msg)
        }
 
        /* Execute statements in scope starting with the subnet scope. */
-       execute_statements_in_scope (packet, packet -> options,
+       execute_statements_in_scope (packet, lease,
+                                    packet -> options,
                                     state -> options,
                                     lease -> subnet -> group,
                                     (struct group *)0);
 
        /* If the lease is from a pool, run the pool scope. */
        if (lease -> pool)
-               execute_statements_in_scope (packet, packet -> options,
+               execute_statements_in_scope (packet, lease,
+                                            packet -> options,
                                             state -> options,
                                             lease -> pool -> group,
                                             lease -> subnet -> group);
@@ -859,7 +870,7 @@ void ack_lease (packet, lease, offer, when, msg)
        /* Execute statements from class scopes. */
        for (i = packet -> class_count; i > 0; i--) {
                execute_statements_in_scope
-                       (packet, packet -> options, state -> options,
+                       (packet, lease, packet -> options, state -> options,
                         packet -> classes [i - 1] -> group,
                         (lease -> pool
                          ? lease -> pool -> group
@@ -869,7 +880,7 @@ void ack_lease (packet, lease, offer, when, msg)
        /* If we have a host_decl structure, run the options associated
           with its group. */
        if (lease -> host)
-               execute_statements_in_scope (packet, packet -> options,
+               execute_statements_in_scope (packet, lease, packet -> options,
                                             state -> options,
                                             lease -> host -> group,
                                             (lease -> pool
@@ -888,7 +899,8 @@ void ack_lease (packet, lease, offer, when, msg)
        if (offer == DHCPREQUEST &&
            (oc = lookup_option (&server_universe, state -> options,
                                 SV_ONE_LEASE_PER_CLIENT)) &&
-           evaluate_boolean_option_cache (packet, packet -> options, oc)) {
+           evaluate_boolean_option_cache (packet,
+                                          packet -> options, lease, oc)) {
                struct lease *seek;
                if (lease -> uid_len) {
                        do {
@@ -931,7 +943,7 @@ void ack_lease (packet, lease, offer, when, msg)
            (oc = lookup_option (&server_universe, state -> options,
                                 SV_MIN_SECS))) {
                if (evaluate_option_cache (&d1, packet,
-                                          packet -> options, oc)) {
+                                          packet -> options, lease, oc)) {
                        if (d1.len && packet -> raw -> secs < d1.data [0]) {
                                data_string_forget (&d1, "ack_lease");
                                log_info ("%s: %d secs < %d",
@@ -956,7 +968,7 @@ void ack_lease (packet, lease, offer, when, msg)
                                    DHO_DHCP_CLIENT_IDENTIFIER);
                if (oc &&
                    evaluate_option_cache (&d1, packet,
-                                          packet -> options, oc)) {
+                                          packet -> options, lease, oc)) {
                        hp = find_hosts_by_uid (d1.data, d1.len);
                        data_string_forget (&d1, "dhcpdiscover");
                        if (!hp)
@@ -978,7 +990,7 @@ void ack_lease (packet, lease, offer, when, msg)
            (oc = lookup_option (&server_universe, state -> options,
                                 SV_BOOT_UNKNOWN_CLIENTS))) {
                if (evaluate_option_cache (&d1, packet,
-                                          packet -> options, oc)) {
+                                          packet -> options, lease, oc)) {
                        if (d1.len && !d1.data [0]) {
                                log_info ("%s: unknown", msg);
                                data_string_forget (&d1, "ack_lease");
@@ -994,7 +1006,7 @@ void ack_lease (packet, lease, offer, when, msg)
            (oc = lookup_option (&server_universe, state -> options,
                                 SV_ALLOW_BOOTP))) {
                if (evaluate_option_cache (&d1, packet,
-                                          packet -> options, oc)) {
+                                          packet -> options, lease, oc)) {
                        if (d1.len && !d1.data [0]) {
                                data_string_forget (&d1, "ack_lease");
                                log_info ("%s: bootp disallowed", msg);
@@ -1009,7 +1021,8 @@ void ack_lease (packet, lease, offer, when, msg)
        oc = lookup_option (&server_universe, state -> options,
                            SV_ALLOW_BOOTING);
        if (oc &&
-           evaluate_option_cache (&d1, packet, packet -> options, oc)) {
+           evaluate_option_cache (&d1, packet, packet -> options,
+                                  lease, oc)) {
                if (d1.len && !d1.data [0]) {
                        log_info ("%s: booting disallowed", msg);
                        data_string_forget (&d1, "ack_lease");
@@ -1062,14 +1075,14 @@ void ack_lease (packet, lease, offer, when, msg)
        oc = lookup_option (&server_universe, state -> options, SV_FILENAME);
        if (oc)
                evaluate_option_cache (&state -> filename,
-                                      packet, packet -> options, oc);
+                                      packet, packet -> options, lease, oc);
 
        /* Choose a server name as above. */
        oc = lookup_option (&server_universe, state -> options,
                            SV_SERVER_NAME);
        if (oc)
                evaluate_option_cache (&state -> server_name, packet,
-                                      packet -> options, oc);
+                                      packet -> options, lease, oc);
 
        /* At this point, we have a lease that we can offer the client.
           Now we construct a lease structure that contains what we want,
@@ -1090,7 +1103,8 @@ void ack_lease (packet, lease, offer, when, msg)
                if ((oc = lookup_option (&server_universe, state -> options,
                                         SV_DEFAULT_LEASE_TIME))) {
                        if (evaluate_option_cache (&d1, packet,
-                                                  packet -> options, oc)) {
+                                                  packet -> options,
+                                                  lease, oc)) {
                                if (d1.len == sizeof (u_int32_t))
                                        default_lease_time =
                                                getULong (d1.data);
@@ -1101,7 +1115,8 @@ void ack_lease (packet, lease, offer, when, msg)
                if ((oc = lookup_option (&dhcp_universe, packet -> options,
                                         DHO_DHCP_LEASE_TIME)))
                        s1 = evaluate_option_cache (&d1, packet,
-                                                   packet -> options, oc);
+                                                   packet -> options,
+                                                   lease, oc);
                else
                        s1 = 0;
                if (s1 && d1.len == sizeof (u_int32_t)) {
@@ -1113,7 +1128,7 @@ void ack_lease (packet, lease, offer, when, msg)
                                                 SV_MAX_LEASE_TIME))) {
                                if (evaluate_option_cache (&d1, packet,
                                                           packet -> options,
-                                                          oc)) {
+                                                          lease, oc)) {
                                        if (d1.len == sizeof (u_int32_t))
                                                max_lease_time =
                                                        getULong (d1.data);
@@ -1133,7 +1148,8 @@ void ack_lease (packet, lease, offer, when, msg)
                if ((oc = lookup_option (&server_universe, state -> options,
                                         SV_MIN_LEASE_TIME))) {
                        if (evaluate_option_cache (&d1, packet,
-                                                  packet -> options, oc)) {
+                                                  packet -> options,
+                                                  lease, oc)) {
                                if (d1.len == sizeof (u_int32_t))
                                        min_lease_time = getULong (d1.data);
                                data_string_forget (&d1, "ack_lease");
@@ -1158,7 +1174,8 @@ void ack_lease (packet, lease, offer, when, msg)
                if ((oc = lookup_option (&server_universe, state -> options,
                                         SV_BOOTP_LEASE_LENGTH))) {
                        if (evaluate_option_cache (&d1, packet,
-                                                  packet -> options, oc)) {
+                                                  packet -> options, lease,
+                                                  oc)) {
                                if (d1.len == sizeof (u_int32_t))
                                        lease_time = getULong (d1.data);
                                data_string_forget (&d1, "ack_lease");
@@ -1168,7 +1185,8 @@ void ack_lease (packet, lease, offer, when, msg)
                if ((oc = lookup_option (&server_universe, state -> options,
                                         SV_BOOTP_LEASE_CUTOFF))) {
                        if (evaluate_option_cache (&d1, packet,
-                                                  packet -> options, oc)) {
+                                                  packet -> options,
+                                                  lease, oc)) {
                                if (d1.len == sizeof (u_int32_t))
                                        lease_time = (getULong (d1.data) -
                                                      cur_time);
@@ -1186,7 +1204,8 @@ void ack_lease (packet, lease, offer, when, msg)
        oc = lookup_option (&dhcp_universe, packet -> options,
                            DHO_DHCP_CLIENT_IDENTIFIER);
        if (oc &&
-           evaluate_option_cache (&d1, packet, packet -> options, oc)) {
+           evaluate_option_cache (&d1, packet, packet -> options,
+                                  lease, oc)) {
                if (d1.len <= sizeof lt.uid_buf) {
                        memcpy (lt.uid_buf, d1.data, d1.len);
                        lt.uid = lt.uid_buf;
@@ -1258,7 +1277,7 @@ void ack_lease (packet, lease, offer, when, msg)
        if ((oc = lookup_option (&dhcp_universe, packet -> options,
                                 DHO_HOST_NAME))) {
                if (evaluate_option_cache (&d1, packet,
-                                          packet -> options, oc)) {
+                                          packet -> options, lease, oc)) {
                        if (d1.data [d1.len - 1] == '\0')
                                lease -> flags |= MS_NULL_TERMINATION;
                        data_string_forget (&d1, "ack_lease");
@@ -1278,7 +1297,8 @@ void ack_lease (packet, lease, offer, when, msg)
           the broadcast bit in the bootp flags field. */
        if ((oc = lookup_option (&server_universe, state -> options,
                                SV_ALWAYS_BROADCAST)) &&
-           evaluate_boolean_option_cache (packet, packet -> options, oc))
+           evaluate_boolean_option_cache (packet, packet -> options,
+                                          lease, oc))
                state -> bootp_flags |= htons (BOOTP_BROADCAST);
 
        /* Get the Maximum Message Size option from the packet, if one
@@ -1286,7 +1306,8 @@ void ack_lease (packet, lease, offer, when, msg)
        oc = lookup_option (&dhcp_universe, packet -> options,
                            DHO_DHCP_MAX_MESSAGE_SIZE);
        if (oc &&
-           evaluate_option_cache (&d1, packet, packet -> options, oc)) {
+           evaluate_option_cache (&d1, packet, packet -> options,
+                                  lease, oc)) {
                if (d1.len == sizeof (u_int16_t))
                        state -> max_message_size = getUShort (d1.data);
                data_string_forget (&d1, "ack_lease");
@@ -1333,7 +1354,8 @@ void ack_lease (packet, lease, offer, when, msg)
                                state -> from.len);
                } else {
                        if (evaluate_option_cache (&d1, packet,
-                                                  packet -> options, oc)) {
+                                                  packet -> options,
+                                                  lease, oc)) {
                                if (!d1.len ||
                                    d1.len > sizeof state -> from.iabuf) {
                                        data_string_forget (&d1, "ack_lease");
@@ -1422,7 +1444,7 @@ void ack_lease (packet, lease, offer, when, msg)
             lookup_option (&server_universe,
                            state -> options, SV_NEXT_SERVER))) {
                if (evaluate_option_cache (&d1, packet,
-                                          packet -> options, oc)) {
+                                          packet -> options, lease, oc)) {
                        /* If there was more than one answer,
                           take the first. */
                        if (d1.len >= 4 && d1.data)
@@ -1456,7 +1478,7 @@ void ack_lease (packet, lease, offer, when, msg)
        if (!lookup_option (&dhcp_universe, state -> options, i) &&
            lease -> host && lease -> host -> name &&
            (evaluate_boolean_option_cache
-            (packet, packet -> options,
+            (packet, packet -> options, lease, 
              (lookup_option
               (&server_universe, state -> options, j))))) {
                oc = (struct option_cache *)0;
@@ -1479,7 +1501,7 @@ void ack_lease (packet, lease, offer, when, msg)
        j = SV_GET_LEASE_HOSTNAMES;
        if (!lookup_option (&server_universe, state -> options, i) &&
            (evaluate_boolean_option_cache
-            (packet, packet -> options,
+            (packet, packet -> options, lease,
              lookup_option (&server_universe, state -> options, j)))) {
                struct in_addr ia;
                struct hostent *h;
@@ -1512,7 +1534,7 @@ void ack_lease (packet, lease, offer, when, msg)
           so if the local router does proxy arp, you win. */
 
        if (evaluate_boolean_option_cache
-           (packet, state -> options,
+           (packet, state -> options, lease,
             lookup_option (&server_universe, state -> options,
                            SV_USE_LEASE_ADDR_FOR_DEFAULT_ROUTE))) {
                i = DHO_ROUTERS;
@@ -1543,7 +1565,7 @@ void ack_lease (packet, lease, offer, when, msg)
        if (!lookup_option (&dhcp_universe, state -> options, i) &&
            (oc = lookup_option (&server_universe, state -> options, j)) &&
            evaluate_option_cache (&d1,
-                                  packet, state -> options, oc)) {
+                                  packet, state -> options, lease, oc)) {
                oc = (struct option_cache *)0;
                if (option_cache_allocate (&oc, "ack_lease")) {
                        if (make_encapsulation (&oc -> expression, &d1)) {
@@ -1560,7 +1582,7 @@ void ack_lease (packet, lease, offer, when, msg)
           site option codes. */
        i = SV_SITE_OPTION_SPACE;
        if ((oc = lookup_option (&server_universe, state -> options, i)) &&
-           evaluate_option_cache (&d1, packet, state -> options, oc)) {
+           evaluate_option_cache (&d1, packet, state -> options, lease, oc)) {
                struct universe *u;
                
                u = ((struct universe *)
@@ -1591,7 +1613,7 @@ void ack_lease (packet, lease, offer, when, msg)
                                    DHO_DHCP_PARAMETER_REQUEST_LIST);
        if (oc)
                evaluate_option_cache (&state -> parameter_request_list,
-                                      packet, packet -> options, oc);
+                                      packet, packet -> options, lease, oc);
 
 #ifdef DEBUG_PACKET
        dump_packet (packet);
@@ -1685,7 +1707,7 @@ void dhcp_reply (lease)
                bootpp = 1;
 
        /* Insert such options as will fit into the buffer. */
-       packet_length = cons_options ((struct packet *)0, &raw,
+       packet_length = cons_options ((struct packet *)0, &raw, lease,
                                      state -> max_message_size,
                                      state -> options,
                                      bufs, nulltp, bootpp,
@@ -1839,7 +1861,8 @@ struct lease *find_lease (packet, share, ours)
                            DHO_DHCP_REQUESTED_ADDRESS);
        memset (&d1, 0, sizeof d1);
        if (oc &&
-           evaluate_option_cache (&d1, packet, packet -> options, oc)) {
+           evaluate_option_cache (&d1, packet, packet -> options,
+                                  (struct lease *)0, oc)) {
                packet -> got_requested_address = 1;
                cip.len = 4;
                memcpy (cip.iabuf, d1.data, cip.len);
@@ -1857,7 +1880,8 @@ struct lease *find_lease (packet, share, ours)
        memset (&client_identifier, 0, sizeof client_identifier);
        if (oc &&
            evaluate_option_cache (&client_identifier,
-                                  packet, packet -> options, oc)) {
+                                  packet, packet -> options,
+                                  (struct lease *)0, oc)) {
                /* Remember this for later. */
                have_client_identifier = 1;