]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
- Add client-state expression.
authorTed Lemon <source@isc.org>
Tue, 28 Nov 2000 23:23:13 +0000 (23:23 +0000)
committerTed Lemon <source@isc.org>
Tue, 28 Nov 2000 23:23:13 +0000 (23:23 +0000)
- Fix debugging printf formats.
- Pass client state to eval functions.

common/tree.c

index b62a9da7f46d15718e48e0d82eac82733a5588fd..8fcee12cdec2836975aa9c2d50f236a012c6ba43 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: tree.c,v 1.91 2000/11/24 04:08:31 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: tree.c,v 1.92 2000/11/28 23:23:13 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -423,11 +423,12 @@ static int do_host_lookup (result, dns)
        return 1;
 }
 
-int evaluate_expression (result, packet, lease,
+int evaluate_expression (result, packet, lease, client_state,
                         in_options, cfg_options, scope, expr)
        struct binding_value **result;
        struct packet *packet;
        struct lease *lease;
+       struct client_state *client_state;
        struct option_state *in_options;
        struct option_state *cfg_options;
        struct binding_scope **scope;
@@ -508,6 +509,7 @@ int evaluate_expression (result, packet, lease,
                                }
                        }
                        evaluate_expression (&nb -> value, packet, lease,
+                                            client_state,
                                             in_options, cfg_options, scope,
                                             arg -> data.arg.val);
                        nb -> next = ns -> bindings;
@@ -532,7 +534,8 @@ int evaluate_expression (result, packet, lease,
                        binding_scope_reference (&ns -> outer, *scope, MDL);
 
                status = (execute_statements
-                         (&bv, packet, lease, in_options, cfg_options, &ns,
+                         (&bv, packet,
+                          lease, client_state, in_options, cfg_options, &ns,
                           binding -> value -> value.fundef -> statements));
                binding_scope_dereference (&ns, MDL);
 
@@ -543,37 +546,37 @@ int evaluate_expression (result, packet, lease,
                        return 0;
                bv -> type = binding_boolean;
                status = (evaluate_boolean_expression
-                         (&bv -> value.boolean, packet, lease, in_options,
-                          cfg_options, scope, expr));
+                         (&bv -> value.boolean, packet, lease, client_state,
+                          in_options, cfg_options, scope, expr));
        } else if (is_numeric_expression (expr)) {
                if (!binding_value_allocate (&bv, MDL))
                        return 0;
                bv -> type = binding_numeric;
                status = (evaluate_numeric_expression
-                         (&bv -> value.intval, packet, lease, in_options,
-                          cfg_options, scope, expr));
+                         (&bv -> value.intval, packet, lease, client_state,
+                          in_options, cfg_options, scope, expr));
        } else if (is_data_expression  (expr)) {
                if (!binding_value_allocate (&bv, MDL))
                        return 0;
                bv -> type = binding_data;
                status = (evaluate_data_expression
-                         (&bv -> value.data, packet, lease, in_options,
-                          cfg_options, scope, expr));
+                         (&bv -> value.data, packet, lease, client_state,
+                          in_options, cfg_options, scope, expr));
        } else if (is_dns_expression (expr)) {
 #if defined (NSUPDATE)
                if (!binding_value_allocate (&bv, MDL))
                        return 0;
                bv -> type = binding_dns;
                status = (evaluate_dns_expression
-                         (&bv -> value.dns, packet, lease, in_options,
-                          cfg_options, scope, expr));
+                         (&bv -> value.dns, packet, lease, client_state,
+                          in_options, cfg_options, scope, expr));
 #endif
        } else {
                log_error ("%s: invalid expression type: %d",
                           "evaluate_expression", expr -> op);
                return 0;
        }
-       if (result)
+       if (result && status)
                binding_value_reference (result, bv, MDL);
        binding_value_dereference (&bv, MDL);
 
@@ -634,11 +637,12 @@ int binding_value_dereference (struct binding_value **v,
 }
 
 #if defined (NSUPDATE)
-int evaluate_dns_expression (result, packet, lease, in_options,
+int evaluate_dns_expression (result, packet, lease, client_state, in_options,
                             cfg_options, scope, expr)
        ns_updrec **result;
        struct packet *packet;
        struct lease *lease;
+       struct client_state *client_state;
        struct option_state *in_options;
        struct option_state *cfg_options;
        struct binding_scope **scope;
@@ -664,6 +668,7 @@ int evaluate_dns_expression (result, packet, lease, in_options,
 #if defined (NSUPDATE)
              case expr_ns_add:
                r0 = evaluate_numeric_expression (&ttl, packet, lease,
+                                                 client_state,
                                                  in_options, cfg_options,
                                                  scope,
                                                  expr -> data.ns_add.ttl);
@@ -678,6 +683,7 @@ int evaluate_dns_expression (result, packet, lease, in_options,
              nsfinish:
                memset (&name, 0, sizeof name);
                r1 = evaluate_data_expression (&name, packet, lease,
+                                              client_state,
                                               in_options, cfg_options, scope,
                                               expr -> data.ns_add.rrname);
                if (r1) {
@@ -695,8 +701,8 @@ int evaluate_dns_expression (result, packet, lease, in_options,
                                tname [name.len] = 0;
                                memset (&data, 0, sizeof data);
                                r2 = evaluate_data_expression
-                                       (&data, packet, lease, in_options,
-                                        cfg_options, scope,
+                                       (&data, packet, lease, client_state,
+                                        in_options, cfg_options, scope,
                                         expr -> data.ns_add.rrdata);
                        }
                } else
@@ -859,6 +865,7 @@ int evaluate_dns_expression (result, packet, lease, in_options,
              case expr_binary_and:
              case expr_binary_or:
              case expr_binary_xor:
+             case expr_client_state:
                log_error ("Numeric opcode in evaluate_dns_expression: %d",
                      expr -> op);
                return 0;
@@ -878,11 +885,12 @@ int evaluate_dns_expression (result, packet, lease, in_options,
 }
 #endif /* defined (NSUPDATE) */
 
-int evaluate_boolean_expression (result, packet, lease, in_options,
-                                cfg_options, scope, expr)
+int evaluate_boolean_expression (result, packet, lease, client_state,
+                                in_options, cfg_options, scope, expr)
        int *result;
        struct packet *packet;
        struct lease *lease;
+       struct client_state *client_state;
        struct option_state *in_options;
        struct option_state *cfg_options;
        struct binding_scope **scope;
@@ -911,11 +919,13 @@ int evaluate_boolean_expression (result, packet, lease, in_options,
              case expr_not_equal:
                memset (&left, 0, sizeof left);
                sleft = evaluate_data_expression (&left, packet, lease,
+                                                 client_state,
                                                  in_options, cfg_options,
                                                  scope,
                                                  expr -> data.equal [0]);
                memset (&right, 0, sizeof right);
                sright = evaluate_data_expression (&right, packet, lease,
+                                                  client_state,
                                                   in_options, cfg_options,
                                                   scope,
                                                   expr -> data.equal [1]);
@@ -925,9 +935,10 @@ int evaluate_boolean_expression (result, packet, lease, in_options,
                                *result = expr -> op == expr_equal;
                        else
                                *result = expr -> op == expr_not_equal;
-               }
-               if (!sleft && !sright)
+               } else if (!sleft && !sright)
                        *result = expr -> op == expr_equal;
+               else
+                       *result = expr -> op == expr_not_equal;
 
 #if defined (DEBUG_EXPRESSIONS)
                log_debug ("bool: %sequal (%s, %s) = %s",
@@ -938,24 +949,23 @@ int evaluate_boolean_expression (result, packet, lease, in_options,
                           (sright
                            ? print_hex_2 (right.len, right.data, 30)
                            : "NULL"),
-                          ((sleft && sright)
-                           ? (*result ? "true" : "false")
-                           : "NULL"));
+                          (*result ? "true" : "false"));
 #endif
                if (sleft)
                        data_string_forget (&left, MDL);
                if (sright)
                        data_string_forget (&right, MDL);
-               return (sleft && sright) || (!sleft && !sright);
+               return 1;
 
              case expr_and:
                sleft = evaluate_boolean_expression (&bleft, packet, lease,
+                                                    client_state,
                                                     in_options, cfg_options,
                                                     scope,
                                                     expr -> data.and [0]);
                if (sleft && bleft)
                        sright = evaluate_boolean_expression
-                               (&bright, packet, lease,
+                               (&bright, packet, lease, client_state,
                                 in_options, cfg_options,
                                 scope, expr -> data.and [1]);
                else
@@ -977,12 +987,13 @@ int evaluate_boolean_expression (result, packet, lease, in_options,
              case expr_or:
                bleft = bright = 0;
                sleft = evaluate_boolean_expression (&bleft, packet, lease,
+                                                    client_state,
                                                     in_options, cfg_options,
                                                     scope,
                                                     expr -> data.or [0]);
                if (!sleft || !bleft)
                        sright = evaluate_boolean_expression
-                               (&bright, packet, lease,
+                               (&bright, packet, lease, client_state,
                                 in_options, cfg_options,
                                 scope, expr -> data.or [1]);
                else
@@ -1002,6 +1013,7 @@ int evaluate_boolean_expression (result, packet, lease, in_options,
 
              case expr_not:
                sleft = evaluate_boolean_expression (&bleft, packet, lease,
+                                                    client_state,
                                                     in_options, cfg_options,
                                                     scope,
                                                     expr -> data.not);
@@ -1022,8 +1034,8 @@ int evaluate_boolean_expression (result, packet, lease, in_options,
                memset (&left, 0, sizeof left);
                if (!in_options ||
                    !get_option (&left, expr -> data.exists -> universe,
-                                packet, lease, in_options, cfg_options,
-                                in_options,
+                                packet, lease, client_state,
+                                in_options, cfg_options, in_options,
                                 scope, expr -> data.exists -> code))
                        *result = 0;
                else {
@@ -1034,7 +1046,7 @@ int evaluate_boolean_expression (result, packet, lease, in_options,
                log_debug ("bool: exists %s.%s = %s",
                           expr -> data.option -> universe -> name,
                           expr -> data.option -> name,
-                          *result ? "true" : MDL);
+                          *result ? "true" : "false");
 #endif
                return 1;
 
@@ -1081,7 +1093,7 @@ int evaluate_boolean_expression (result, packet, lease, in_options,
                        *result = 0;
 #if defined (DEBUG_EXPRESSIONS)
                log_debug ("boolean: %s? = %s", expr -> data.variable,
-                          sleft ? "true" : "false");
+                          *result ? "true" : "false");
 #endif
                return 1;
 
@@ -1112,7 +1124,7 @@ int evaluate_boolean_expression (result, packet, lease, in_options,
 
              case expr_funcall:
                bv = (struct binding_value *)0;
-               sleft = evaluate_expression (&bv, packet, lease,
+               sleft = evaluate_expression (&bv, packet, lease, client_state,
                                          in_options, cfg_options,
                                          scope, expr);
                if (sleft) {
@@ -1172,6 +1184,7 @@ int evaluate_boolean_expression (result, packet, lease, in_options,
              case expr_binary_and:
              case expr_binary_or:
              case expr_binary_xor:
+             case expr_client_state:
                log_error ("Numeric opcode in evaluate_boolean_expression: %d",
                      expr -> op);
                return 0;
@@ -1197,11 +1210,12 @@ int evaluate_boolean_expression (result, packet, lease, in_options,
        return 0;
 }
 
-int evaluate_data_expression (result, packet, lease,
+int evaluate_data_expression (result, packet, lease, client_state,
                              in_options, cfg_options, scope, expr)
        struct data_string *result;
        struct packet *packet;
        struct lease *lease;
+       struct client_state *client_state;
        struct option_state *in_options;
        struct option_state *cfg_options;
        struct binding_scope **scope;
@@ -1220,14 +1234,16 @@ int evaluate_data_expression (result, packet, lease,
              case expr_substring:
                memset (&data, 0, sizeof data);
                s0 = evaluate_data_expression (&data, packet, lease,
+                                              client_state,
                                               in_options, cfg_options, scope,
                                               expr -> data.substring.expr);
 
                /* Evaluate the offset and length. */
                s1 = evaluate_numeric_expression
-                       (&offset, packet, lease, in_options, cfg_options,
-                        scope, expr -> data.substring.offset);
+                       (&offset, packet, lease, client_state, in_options,
+                        cfg_options, scope, expr -> data.substring.offset);
                s2 = evaluate_numeric_expression (&len, packet, lease,
+                                                 client_state,
                                                  in_options, cfg_options,
                                                  scope,
                                                  expr -> data.substring.len);
@@ -1268,10 +1284,12 @@ int evaluate_data_expression (result, packet, lease,
              case expr_suffix:
                memset (&data, 0, sizeof data);
                s0 = evaluate_data_expression (&data, packet, lease,
+                                              client_state,
                                               in_options, cfg_options, scope,
                                               expr -> data.suffix.expr);
                /* Evaluate the length. */
                s1 = evaluate_numeric_expression (&len, packet, lease,
+                                                 client_state,
                                                  in_options, cfg_options,
                                                  scope,
                                                  expr -> data.suffix.len);
@@ -1304,7 +1322,7 @@ int evaluate_data_expression (result, packet, lease,
                if (in_options)
                        s0 = get_option (result,
                                         expr -> data.option -> universe,
-                                        packet, lease,
+                                        packet, lease, client_state,
                                         in_options, cfg_options, in_options,
                                         scope, expr -> data.option -> code);
                else
@@ -1323,7 +1341,7 @@ int evaluate_data_expression (result, packet, lease,
                if (cfg_options)
                        s0 = get_option (result,
                                         expr -> data.option -> universe,
-                                        packet, lease,
+                                        packet, lease, client_state,
                                         in_options, cfg_options, cfg_options,
                                         scope, expr -> data.option -> code);
                else
@@ -1375,11 +1393,12 @@ int evaluate_data_expression (result, packet, lease,
                }
 
                s0 = evaluate_numeric_expression (&offset, packet, lease,
+                                                 client_state,
                                                  in_options, cfg_options,
                                                  scope,
                                                  expr -> data.packet.offset);
                s1 = evaluate_numeric_expression (&len,
-                                                 packet, lease,
+                                                 packet, lease, client_state,
                                                  in_options, cfg_options,
                                                  scope,
                                                  expr -> data.packet.len);
@@ -1416,7 +1435,7 @@ int evaluate_data_expression (result, packet, lease,
              case expr_encapsulate:
                if (cfg_options)
                        s0 = option_space_encapsulate
-                               (result, packet, lease,
+                               (result, packet, lease, client_state,
                                 in_options, cfg_options, scope,
                                 &expr -> data.encapsulate);
                else
@@ -1457,10 +1476,12 @@ int evaluate_data_expression (result, packet, lease,
              case expr_concat:
                memset (&data, 0, sizeof data);
                s0 = evaluate_data_expression (&data, packet, lease,
+                                              client_state,
                                               in_options, cfg_options, scope,
                                               expr -> data.concat [0]);
                memset (&other, 0, sizeof other);
                s1 = evaluate_data_expression (&other, packet, lease,
+                                              client_state,
                                               in_options, cfg_options, scope,
                                               expr -> data.concat [1]);
 
@@ -1495,6 +1516,7 @@ int evaluate_data_expression (result, packet, lease,
 
              case expr_encode_int8:
                s0 = evaluate_numeric_expression (&len, packet, lease,
+                                                 client_state,
                                                  in_options, cfg_options,
                                                  scope,
                                                  expr -> data.encode_int);
@@ -1524,6 +1546,7 @@ int evaluate_data_expression (result, packet, lease,
                
              case expr_encode_int16:
                s0 = evaluate_numeric_expression (&len, packet, lease,
+                                                 client_state,
                                                  in_options, cfg_options,
                                                  scope,
                                                  expr -> data.encode_int);
@@ -1552,6 +1575,7 @@ int evaluate_data_expression (result, packet, lease,
 
              case expr_encode_int32:
                s0 = evaluate_numeric_expression (&len, packet, lease,
+                                                 client_state,
                                                  in_options, cfg_options,
                                                  scope,
                                                  expr -> data.encode_int);
@@ -1581,9 +1605,10 @@ int evaluate_data_expression (result, packet, lease,
              case expr_binary_to_ascii:
                /* Evaluate the base (offset) and width (len): */
                s0 = evaluate_numeric_expression
-                       (&offset, packet, lease, in_options, cfg_options,
-                        scope, expr -> data.b2a.base);
+                       (&offset, packet, lease, client_state, in_options,
+                        cfg_options, scope, expr -> data.b2a.base);
                s1 = evaluate_numeric_expression (&len, packet, lease,
+                                                 client_state,
                                                  in_options, cfg_options,
                                                  scope,
                                                  expr -> data.b2a.width);
@@ -1591,12 +1616,14 @@ int evaluate_data_expression (result, packet, lease,
                /* Evaluate the seperator string. */
                memset (&data, 0, sizeof data);
                s2 = evaluate_data_expression (&data, packet, lease,
+                                              client_state,
                                               in_options, cfg_options, scope,
                                               expr -> data.b2a.seperator);
 
                /* Evaluate the data to be converted. */
                memset (&other, 0, sizeof other);
                s3 = evaluate_data_expression (&other, packet, lease,
+                                              client_state,
                                               in_options, cfg_options, scope,
                                               expr -> data.b2a.buffer);
 
@@ -1704,12 +1731,13 @@ int evaluate_data_expression (result, packet, lease,
              case expr_reverse:
                /* Evaluate the width (len): */
                s0 = evaluate_numeric_expression
-                       (&len, packet, lease, in_options, cfg_options,
-                        scope, expr -> data.reverse.width);
+                       (&len, packet, lease, client_state, in_options,
+                        cfg_options, scope, expr -> data.reverse.width);
 
                /* Evaluate the data. */
                memset (&data, 0, sizeof data);
                s1 = evaluate_data_expression (&data, packet, lease,
+                                              client_state,
                                               in_options, cfg_options, scope,
                                               expr -> data.reverse.buffer);
 
@@ -1784,8 +1812,9 @@ int evaluate_data_expression (result, packet, lease,
              case expr_pick_first_value:
                memset (&data, 0, sizeof data);
                if ((evaluate_data_expression
-                    (result, packet, lease, in_options, cfg_options, scope,
-                     expr -> data.pick_first_value.car))) {
+                    (result, packet,
+                     lease, client_state, in_options, cfg_options,
+                     scope, expr -> data.pick_first_value.car))) {
 #if defined (DEBUG_EXPRESSIONS)
                        log_debug ("data: pick_first_value (%s, ???)",
                                   print_hex_1 (result -> len,
@@ -1796,8 +1825,9 @@ int evaluate_data_expression (result, packet, lease,
 
                if (expr -> data.pick_first_value.cdr &&
                    (evaluate_data_expression
-                    (result, packet, lease, in_options, cfg_options, scope,
-                     expr -> data.pick_first_value.cdr))) {
+                    (result, packet,
+                     lease, client_state, in_options, cfg_options,
+                     scope, expr -> data.pick_first_value.cdr))) {
 #if defined (DEBUG_EXPRESSIONS)
                        log_debug ("data: pick_first_value (NULL, %s)",
                                   print_hex_1 (result -> len,
@@ -1868,7 +1898,7 @@ int evaluate_data_expression (result, packet, lease,
 
              case expr_funcall:
                bv = (struct binding_value *)0;
-               s0 = evaluate_expression (&bv, packet, lease,
+               s0 = evaluate_expression (&bv, packet, lease, client_state,
                                          in_options, cfg_options,
                                          scope, expr);
                if (s0) {
@@ -1917,7 +1947,7 @@ int evaluate_data_expression (result, packet, lease,
 
 #if defined (DEBUG_EXPRESSIONS)
                log_info ("data: filename = \"%s\"",
-                         s0 ? (char *)(result -> data) : "NULL");
+                         s0 ? (const char *)(result -> data) : "NULL");
 #endif
                return s0;
 
@@ -1949,7 +1979,7 @@ int evaluate_data_expression (result, packet, lease,
 
 #if defined (DEBUG_EXPRESSIONS)
                log_info ("data: sname = \"%s\"",
-                         s0 ? (char *)(result -> data) : "NULL");
+                         s0 ? (const char *)(result -> data) : "NULL");
 #endif
                return s0;
 
@@ -1983,6 +2013,7 @@ int evaluate_data_expression (result, packet, lease,
              case expr_binary_and:
              case expr_binary_or:
              case expr_binary_xor:
+             case expr_client_state:
                log_error ("Numeric opcode in evaluate_data_expression: %d",
                      expr -> op);
                return 0;
@@ -2007,11 +2038,12 @@ int evaluate_data_expression (result, packet, lease,
        return 0;
 }      
 
-int evaluate_numeric_expression (result, packet, lease,
+int evaluate_numeric_expression (result, packet, lease, client_state,
                                 in_options, cfg_options, scope, expr)
        unsigned long *result;
        struct packet *packet;
        struct lease *lease;
+       struct client_state *client_state;
        struct option_state *in_options;
        struct option_state *cfg_options;
        struct binding_scope **scope;
@@ -2075,8 +2107,8 @@ int evaluate_numeric_expression (result, packet, lease,
              case expr_extract_int8:
                memset (&data, 0, sizeof data);
                status = evaluate_data_expression
-                       (&data, packet, lease, in_options, cfg_options,
-                        scope, expr -> data.extract_int);
+                       (&data, packet, lease, client_state, in_options,
+                        cfg_options, scope, expr -> data.extract_int);
                if (status)
                        *result = data.data [0];
 #if defined (DEBUG_EXPRESSIONS)
@@ -2090,8 +2122,8 @@ int evaluate_numeric_expression (result, packet, lease,
              case expr_extract_int16:
                memset (&data, 0, sizeof data);
                status = (evaluate_data_expression
-                         (&data, packet, lease, in_options, cfg_options,
-                          scope, expr -> data.extract_int));
+                         (&data, packet, lease, client_state, in_options,
+                          cfg_options, scope, expr -> data.extract_int));
                if (status && data.len >= 2)
                        *result = getUShort (data.data);
 #if defined (DEBUG_EXPRESSIONS)
@@ -2106,8 +2138,8 @@ int evaluate_numeric_expression (result, packet, lease,
              case expr_extract_int32:
                memset (&data, 0, sizeof data);
                status = (evaluate_data_expression
-                         (&data, packet, lease, in_options, cfg_options,
-                          scope, expr -> data.extract_int));
+                         (&data, packet, lease, client_state, in_options,
+                          cfg_options, scope, expr -> data.extract_int));
                if (status && data.len >= 4)
                        *result = getULong (data.data);
 #if defined (DEBUG_EXPRESSIONS)
@@ -2159,7 +2191,8 @@ int evaluate_numeric_expression (result, packet, lease,
                    next = cur -> data.dns_transaction.cdr;
                    nut = 0;
                    status = (evaluate_dns_expression
-                             (&nut, packet, lease, in_options, cfg_options,
+                             (&nut, packet,
+                              lease, client_state, in_options, cfg_options,
                               scope, cur -> data.dns_transaction.car));
                    if (!status)
                            goto dns_bad;
@@ -2206,14 +2239,19 @@ int evaluate_numeric_expression (result, packet, lease,
                } else
                    status = 0;
 #if defined (DEBUG_EXPRESSIONS)
-               log_debug ("numeric: %s = %s", expr -> data.variable,
-                          status ? *result : 0);
+               if (status)
+                       log_debug ("numeric: %s = %ld",
+                                  expr -> data.variable, *result);
+               else
+                       log_debug ("numeric: %s = NULL",
+                                  expr -> data.variable);
 #endif
                return status;
 
              case expr_funcall:
                bv = (struct binding_value *)0;
                status = evaluate_expression (&bv, packet, lease,
+                                             client_state,
                                              in_options, cfg_options,
                                              scope, expr);
                if (status) {
@@ -2227,25 +2265,31 @@ int evaluate_numeric_expression (result, packet, lease,
                        binding_value_dereference (&bv, MDL);
                }
 #if defined (DEBUG_EXPRESSIONS)
-               log_debug ("data: %s = %d", expr -> data.funcall.name,
+               log_debug ("data: %s = %ld", expr -> data.funcall.name,
                           status ? *result : 0);
 #endif
                break;
 
              case expr_add:
                sleft = evaluate_numeric_expression (&ileft, packet, lease,
+                                                    client_state,
                                                     in_options, cfg_options,
                                                     scope,
                                                     expr -> data.and [0]);
                sright = evaluate_numeric_expression (&iright, packet, lease,
+                                                     client_state,
                                                      in_options, cfg_options,
                                                      scope,
                                                      expr -> data.and [1]);
 
 #if defined (DEBUG_EXPRESSIONS)
-               log_debug ("num: %d + %d = %d",
-                     ileft, iright,
-                     ((sleft && sright) ? (ileft + iright) : 0));
+               if (sleft && sright)
+                       log_debug ("num: %ld + %ld = %ld",
+                                  ileft, iright, ileft + iright);
+               else if (sleft)
+                       log_debug ("num: %ld + NULL = NULL", ileft);
+               else
+                       log_debug ("num: NULL + %ld = NULL", iright);
 #endif
                if (sleft && sright) {
                        *result = ileft + iright;
@@ -2255,18 +2299,24 @@ int evaluate_numeric_expression (result, packet, lease,
 
              case expr_subtract:
                sleft = evaluate_numeric_expression (&ileft, packet, lease,
+                                                    client_state,
                                                     in_options, cfg_options,
                                                     scope,
                                                     expr -> data.and [0]);
                sright = evaluate_numeric_expression (&iright, packet, lease,
+                                                     client_state,
                                                      in_options, cfg_options,
                                                      scope,
                                                      expr -> data.and [1]);
 
 #if defined (DEBUG_EXPRESSIONS)
-               log_debug ("num: %d - %d = %d",
-                     ileft, iright,
-                     ((sleft && sright) ? (ileft - iright) : 0));
+               if (sleft && sright)
+                       log_debug ("num: %ld - %ld = %ld",
+                                  ileft, iright, ileft - iright);
+               else if (sleft)
+                       log_debug ("num: %ld - NULL = NULL", ileft);
+               else
+                       log_debug ("num: NULL - %ld = NULL", iright);
 #endif
                if (sleft && sright) {
                        *result = ileft - iright;
@@ -2276,18 +2326,24 @@ int evaluate_numeric_expression (result, packet, lease,
 
              case expr_multiply:
                sleft = evaluate_numeric_expression (&ileft, packet, lease,
+                                                    client_state,
                                                     in_options, cfg_options,
                                                     scope,
                                                     expr -> data.and [0]);
                sright = evaluate_numeric_expression (&iright, packet, lease,
+                                                     client_state,
                                                      in_options, cfg_options,
                                                      scope,
                                                      expr -> data.and [1]);
 
 #if defined (DEBUG_EXPRESSIONS)
-               log_debug ("num: %d * %d = %d",
-                     ileft, iright,
-                     ((sleft && sright) ? (ileft * iright) : 0));
+               if (sleft && sright)
+                       log_debug ("num: %ld * %ld = %ld",
+                                  ileft, iright, ileft * iright);
+               else if (sleft)
+                       log_debug ("num: %ld * NULL = NULL", ileft);
+               else
+                       log_debug ("num: NULL * %ld = NULL", iright);
 #endif
                if (sleft && sright) {
                        *result = ileft * iright;
@@ -2297,18 +2353,28 @@ int evaluate_numeric_expression (result, packet, lease,
 
              case expr_divide:
                sleft = evaluate_numeric_expression (&ileft, packet, lease,
+                                                    client_state,
                                                     in_options, cfg_options,
                                                     scope,
                                                     expr -> data.and [0]);
                sright = evaluate_numeric_expression (&iright, packet, lease,
+                                                     client_state,
                                                      in_options, cfg_options,
                                                      scope,
                                                      expr -> data.and [1]);
 
 #if defined (DEBUG_EXPRESSIONS)
-               log_debug ("num: %d / %d = %d",
-                     ileft, iright,
-                     ((sleft && sright && iright) ? (ileft / iright) : 0));
+               if (sleft && sright) {
+                       if (iright != 0)
+                               log_debug ("num: %ld / %ld = %ld",
+                                          ileft, iright, ileft / iright);
+                       else
+                               log_debug ("num: %ld / %ld = NULL",
+                                          ileft, iright);
+               } else if (sleft)
+                       log_debug ("num: %ld / NULL = NULL", ileft);
+               else
+                       log_debug ("num: NULL / %ld = NULL", iright);
 #endif
                if (sleft && sright && iright) {
                        *result = ileft / iright;
@@ -2318,18 +2384,28 @@ int evaluate_numeric_expression (result, packet, lease,
 
              case expr_remainder:
                sleft = evaluate_numeric_expression (&ileft, packet, lease,
+                                                    client_state,
                                                     in_options, cfg_options,
                                                     scope,
                                                     expr -> data.and [0]);
                sright = evaluate_numeric_expression (&iright, packet, lease,
+                                                     client_state,
                                                      in_options, cfg_options,
                                                      scope,
                                                      expr -> data.and [1]);
 
 #if defined (DEBUG_EXPRESSIONS)
-               log_debug ("num: %d %% %d = %d",
-                     ileft, iright,
-                     ((sleft && sright && iright) ? (ileft % iright) : 0));
+               if (sleft && sright) {
+                       if (iright != 0)
+                               log_debug ("num: %ld %% %ld = %ld",
+                                          ileft, iright, ileft % iright);
+                       else
+                               log_debug ("num: %ld %% %ld = NULL",
+                                          ileft, iright);
+               } else if (sleft)
+                       log_debug ("num: %ld %% NULL = NULL", ileft);
+               else
+                       log_debug ("num: NULL %% %ld = NULL", iright);
 #endif
                if (sleft && sright && iright) {
                        *result = ileft % iright;
@@ -2339,18 +2415,24 @@ int evaluate_numeric_expression (result, packet, lease,
 
              case expr_binary_and:
                sleft = evaluate_numeric_expression (&ileft, packet, lease,
+                                                    client_state,
                                                     in_options, cfg_options,
                                                     scope,
                                                     expr -> data.and [0]);
                sright = evaluate_numeric_expression (&iright, packet, lease,
+                                                     client_state,
                                                      in_options, cfg_options,
                                                      scope,
                                                      expr -> data.and [1]);
 
 #if defined (DEBUG_EXPRESSIONS)
-               log_debug ("num: %d & %d = %d",
-                     ileft, iright,
-                     ((sleft && sright) ? (ileft & iright) : 0));
+               if (sleft && sright)
+                       log_debug ("num: %ld | %ld = %ld",
+                                  ileft, iright, ileft & iright);
+               else if (sleft)
+                       log_debug ("num: %ld & NULL = NULL", ileft);
+               else
+                       log_debug ("num: NULL & %ld = NULL", iright);
 #endif
                if (sleft && sright) {
                        *result = ileft & iright;
@@ -2360,18 +2442,24 @@ int evaluate_numeric_expression (result, packet, lease,
 
              case expr_binary_or:
                sleft = evaluate_numeric_expression (&ileft, packet, lease,
+                                                    client_state,
                                                     in_options, cfg_options,
                                                     scope,
                                                     expr -> data.and [0]);
                sright = evaluate_numeric_expression (&iright, packet, lease,
+                                                     client_state,
                                                      in_options, cfg_options,
                                                      scope,
                                                      expr -> data.and [1]);
 
 #if defined (DEBUG_EXPRESSIONS)
-               log_debug ("num: %d | %d = %d",
-                     ileft, iright,
-                     ((sleft && sright) ? (ileft | iright) : 0));
+               if (sleft && sright)
+                       log_debug ("num: %ld | %ld = %ld",
+                                  ileft, iright, ileft | iright);
+               else if (sleft)
+                       log_debug ("num: %ld | NULL = NULL", ileft);
+               else
+                       log_debug ("num: NULL | %ld = NULL", iright);
 #endif
                if (sleft && sright) {
                        *result = ileft | iright;
@@ -2381,18 +2469,24 @@ int evaluate_numeric_expression (result, packet, lease,
 
              case expr_binary_xor:
                sleft = evaluate_numeric_expression (&ileft, packet, lease,
+                                                    client_state,
                                                     in_options, cfg_options,
                                                     scope,
                                                     expr -> data.and [0]);
                sright = evaluate_numeric_expression (&iright, packet, lease,
+                                                     client_state,
                                                      in_options, cfg_options,
                                                      scope,
                                                      expr -> data.and [1]);
 
 #if defined (DEBUG_EXPRESSIONS)
-               log_debug ("num: %d ^ %d = %d",
-                     ileft, iright,
-                     ((sleft && sright) ? (ileft ^ iright) : 0));
+               if (sleft && sright)
+                       log_debug ("num: %ld ^ %ld = %ld",
+                                  ileft, iright, ileft ^ iright);
+               else if (sleft)
+                       log_debug ("num: %ld ^ NULL = NULL", ileft);
+               else
+                       log_debug ("num: NULL ^ %ld = NULL", iright);
 #endif
                if (sleft && sright) {
                        *result = ileft ^ iright;
@@ -2400,6 +2494,21 @@ int evaluate_numeric_expression (result, packet, lease,
                }
                return 0;
 
+             case expr_client_state:
+               if (client_state) {
+#if defined (DEBUG_EXPRESSIONS)
+                       log_debug ("num: client-state = %d",
+                                  client_state -> state);
+#endif
+                       *result = client_state -> state;
+                       return 1;
+               } else {
+#if defined (DEBUG_EXPRESSIONS)
+                       log_debug ("num: client-state = NULL");
+#endif
+                       return 0;
+               }
+
              case expr_ns_add:
              case expr_ns_delete:
              case expr_ns_exists:
@@ -2425,11 +2534,12 @@ int evaluate_numeric_expression (result, packet, lease,
    result of that evaluation.   There should never be both an expression
    and a valid data_string. */
 
-int evaluate_option_cache (result, packet, lease,
+int evaluate_option_cache (result, packet, lease, client_state,
                           in_options, cfg_options, scope, oc, file, line)
        struct data_string *result;
        struct packet *packet;
        struct lease *lease;
+       struct client_state *client_state;
        struct option_state *in_options;
        struct option_state *cfg_options;
        struct binding_scope **scope;
@@ -2443,7 +2553,7 @@ int evaluate_option_cache (result, packet, lease,
        }
        if (!oc -> expression)
                return 0;
-       return evaluate_data_expression (result, packet, lease,
+       return evaluate_data_expression (result, packet, lease, client_state,
                                         in_options, cfg_options, scope,
                                         oc -> expression);
 }
@@ -2451,11 +2561,13 @@ int evaluate_option_cache (result, packet, lease,
 /* 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 (ignorep, packet, lease, in_options,
+int evaluate_boolean_option_cache (ignorep, packet,
+                                  lease, client_state, in_options,
                                   cfg_options, scope, oc, file, line)
        int *ignorep;
        struct packet *packet;
        struct lease *lease;
+       struct client_state *client_state;
        struct option_state *in_options;
        struct option_state *cfg_options;
        struct binding_scope **scope;
@@ -2471,7 +2583,8 @@ int evaluate_boolean_option_cache (ignorep, packet, lease, in_options,
                return 0;
        
        memset (&ds, 0, sizeof ds);
-       if (!evaluate_option_cache (&ds, packet, lease, in_options,
+       if (!evaluate_option_cache (&ds, packet,
+                                   lease, client_state, in_options,
                                    cfg_options, scope, oc, file, line))
                return 0;
 
@@ -2491,11 +2604,12 @@ int evaluate_boolean_option_cache (ignorep, packet, lease, in_options,
 /* Evaluate a boolean expression and return the result of the evaluation,
    or FALSE if it failed. */
 
-int evaluate_boolean_expression_result (ignorep, packet, lease, in_options,
-                                       cfg_options, scope, expr)
+int evaluate_boolean_expression_result (ignorep, packet, lease, client_state,
+                                       in_options, cfg_options, scope, expr)
        int *ignorep;
        struct packet *packet;
        struct lease *lease;
+       struct client_state *client_state;
        struct option_state *in_options;
        struct option_state *cfg_options;
        struct binding_scope **scope;
@@ -2507,7 +2621,7 @@ int evaluate_boolean_expression_result (ignorep, packet, lease, in_options,
        if (!expr)
                return 0;
        
-       if (!evaluate_boolean_expression (&result, packet, lease,
+       if (!evaluate_boolean_expression (&result, packet, lease, client_state,
                                          in_options, cfg_options,
                                          scope, expr))
                return 0;
@@ -2567,6 +2681,7 @@ void expression_dereference (eptr, file, line)
              case expr_binary_and:
              case expr_binary_or:
              case expr_binary_xor:
+             case expr_client_state:
                if (expr -> data.equal [0])
                        expression_dereference (&expr -> data.equal [0],
                                                file, line);
@@ -2815,7 +2930,8 @@ int is_numeric_expression (expr)
                expr -> op == expr_remainder ||
                expr -> op == expr_binary_and ||
                expr -> op == expr_binary_or ||
-               expr -> op == expr_binary_xor);
+               expr -> op == expr_binary_xor ||
+               expr -> op == expr_client_state);
 }
 
 int is_compound_expression (expr)
@@ -2895,6 +3011,7 @@ static int op_val (op)
              case expr_binary_and:
              case expr_binary_or:
              case expr_binary_xor:
+             case expr_client_state:
                return 100;
 
              case expr_equal:
@@ -2991,6 +3108,7 @@ enum expression_context op_context (op)
              case expr_binary_and:
              case expr_binary_or:
              case expr_binary_xor:
+             case expr_client_state:
                return context_numeric;
        }
        return context_any;
@@ -3281,6 +3399,11 @@ int write_expression (file, expr, col, indent, firstp)
                                          "leased-address");
                break;
 
+             case expr_client_state:
+               col = token_print_indent (file, col, indent, "", "",
+                                         "client-state");
+               break;
+
              case expr_binary_to_ascii:
                col = token_print_indent (file, col, indent, "", "",
                                          "binary-to-ascii");
@@ -3715,6 +3838,7 @@ int data_subexpression_length (int *rv,
              case expr_binary_and:
              case expr_binary_or:
              case expr_binary_xor:
+             case expr_client_state:
                return 0;
        }
        return 0;