]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
- lcase() and ucase() configuration expressions have been added which adjust
authorDavid Hankins <dhankins@isc.org>
Thu, 11 May 2006 16:31:29 +0000 (16:31 +0000)
committerDavid Hankins <dhankins@isc.org>
Thu, 11 May 2006 16:31:29 +0000 (16:31 +0000)
  their arguments from upper to lower and lower to upper cases respectively.
  [ISC-Bugs #1597]

RELNOTES
common/conflex.c
common/dhcp-eval.5
common/parse.c
common/print.c
common/tree.c
includes/dhctoken.h
includes/tree.h

index 1b82d7f3f79c74ff615219f626d5bb44150b5b4f..f5773e6c87a38864b61e0a5bfed06de31024033d 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -99,6 +99,9 @@ and for prodding me into improving it.
 - The Load Balance Algorithm was misimplemented.  The current implementation
   matches RFC 3074.
 
+- lcase() and ucase() configuration expressions have been added which adjust
+  their arguments from upper to lower and lower to upper cases respectively.
+
                        Changes since 3.0.4b2
 
 - Null-termination sensing for certain clients that unfortunatley require
index 55b8facef50f8b56854a531bb274eca090170b52..2dd8b897c36f0ec763166a81c9a19bee0856835c 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: conflex.c,v 1.96 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: conflex.c,v 1.97 2006/05/11 16:31:29 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -805,6 +805,8 @@ static enum dhcp_token intern (atom, dfv)
                        return KEY;
                break;
              case 'l':
+               if (!strcasecmp (atom + 1, "case"))
+                       return LCASE;
                if (!strcasecmp (atom + 1, "ease"))
                        return LEASE;
                if (!strcasecmp (atom + 1, "eased-address"))
@@ -1071,6 +1073,8 @@ static enum dhcp_token intern (atom, dfv)
                        return TRANSMISSION;
                break;
              case 'u':
+               if (!strcasecmp (atom + 1, "case"))
+                       return UCASE;
                if (!strcasecmp (atom + 1, "nset"))
                        return UNSET;
                if (!strcasecmp (atom + 1, "nsigned"))
index 14c9e65081c73ed76ce5c772342350273b32c2f8..f7c0fde5d1300a6197804955c2868778b186a418 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: dhcp-eval.5,v 1.20 2006/05/05 20:32:30 dhankins Exp $
+.\"    $Id: dhcp-eval.5,v 1.21 2006/05/11 16:31:29 dhankins Exp $
 .\"
 .\" Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
 .\" Copyright (c) 1996-2003 by Internet Software Consortium
@@ -204,6 +204,22 @@ number greater than the length of the evaluated data, then the
 evaluated data is returned.
 .RE
 .PP
+.B lcase (\fIdata-expr\fB)\fR
+.PP
+.RS 0.25i
+The \fBlcase\fR function returns the result of evaluating
+\fIdata-expr\fR converted to lower case.   If \fIdata-expr\fR evaluates
+to null, then the result is also null.
+.RE
+.PP
+.B ucase (\fIdata-expr\fB)\fR
+.PP
+.RS 0.25i
+The \fBucase\fR function returns the result of evaluating
+\fIdata-expr\fR converted to upper case.   If \fIdata-expr\fR evaluates
+to null, then the result is also null.
+.RE
+.PP
 .B option \fIoption-name\fR
 .PP
 .RS 0.25i
@@ -310,6 +326,7 @@ client, one could write the following expression:
                 ".in-addr.arpa.");
 
 .fi
+.RE
 .PP
 .B encode-int (\fInumeric-expr\fB, \fIwidth\fB)\fR
 .RS 0.25i
index 9882c150f9db94365afe5fa91925d319ddeea4bf..8aefd5d6d6adbfbd36397e8ab1fed4a569286991 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: parse.c,v 1.107 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: parse.c,v 1.108 2006/05/11 16:31:29 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -2684,9 +2684,11 @@ int parse_boolean_expression (expr, cfile, lose)
  *                                     numeric-expression COMMA
  *                                     numeric-expression RPAREN |
  *                    CONCAT LPAREN data-expression COMMA 
                                      data-expression RPAREN
*                                     data-expression RPAREN
  *                    SUFFIX LPAREN data_expression COMMA
  *                                  numeric-expression RPAREN |
+ *                    LCASE LPAREN data_expression RPAREN |
+ *                    UCASE LPAREN data_expression RPAREN |
  *                    OPTION option_name |
  *                    HARDWARE |
  *                    PACKET LPAREN numeric-expression COMMA
@@ -3002,6 +3004,43 @@ int parse_non_binary (expr, cfile, lose, context)
                        goto norparen;
                break;
 
+             case LCASE:
+               token = next_token(&val, (unsigned *)0, cfile);
+               if (!expression_allocate(expr, MDL))
+                       log_fatal ("can't allocate expression");
+               (*expr)->op = expr_lcase;
+
+               token = next_token(&val, (unsigned *)0, cfile);
+               if (token != LPAREN)
+                       goto nolparen;
+
+               if (!parse_data_expression(&(*expr)->data.lcase, cfile, lose))
+                       goto nodata;
+
+               token = next_token(&val, (unsigned *)0, cfile);
+               if (token != RPAREN)
+                       goto norparen;
+               break;
+
+             case UCASE:
+               token = next_token(&val, (unsigned *)0, cfile);
+               if (!expression_allocate(expr, MDL))
+                       log_fatal ("can't allocate expression");
+               (*expr)->op = expr_ucase;
+
+               token = next_token (&val, (unsigned *)0, cfile);
+               if (token != LPAREN)
+                       goto nolparen;
+
+               if (!parse_data_expression(&(*expr)->data.ucase,
+                                          cfile, lose))
+                       goto nodata;
+
+               token = next_token(&val, (unsigned *)0, cfile);
+               if (token != RPAREN)
+                       goto norparen;
+               break;
+
              case CONCAT:
                token = next_token (&val, (unsigned *)0, cfile);
                if (!expression_allocate (expr, MDL))
index 60e029b7ec716ff0e7086c06cbcfea994039c074..67f2283793eb9de7a089266d8d3c8dc940ea518d 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: print.c,v 1.58 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: print.c,v 1.59 2006/05/11 16:31:29 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -550,6 +550,30 @@ static unsigned print_subexpression (expr, buf, len)
                }
                break;
 
+             case expr_lcase:
+               if (len > 9) {
+                       rv = 7;
+                       strcpy(buf, "(lcase ");
+                       rv += print_subexpression(expr->data.lcase,
+                                                 buf + rv, len - rv - 1);
+                       buf[rv++] = ')';
+                       buf[rv] = 0;
+                       return rv;
+               }
+               break;
+
+             case expr_ucase:
+               if (len > 9) {
+                       rv = 7;
+                       strcpy(buf, "(ucase ");
+                       rv += print_subexpression(expr->data.ucase,
+                                                 buf + rv, len - rv - 1);
+                       buf[rv++] = ')';
+                       buf[rv] = 0;
+                       return rv;
+               }
+               break;
+
              case expr_concat:
                if (len > 10) {
                        rv = 8;
index e19886415cb35f0b313861941598e80ce65cb6ac..a572b8d9a8feb173d2b35226e7c00ad5d57834f5 100644 (file)
 
 #ifndef lint
 static char copyright[] =
-"$Id: tree.c,v 1.104 2006/02/24 23:16:29 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: tree.c,v 1.105 2006/05/11 16:31:29 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
 #include <omapip/omapip_p.h>
+#include <ctype.h>
 
 struct binding_scope *global_scope;
 
@@ -835,6 +836,8 @@ int evaluate_dns_expression (result, packet, lease, client_state, in_options,
              case expr_none:
              case expr_substring:
              case expr_suffix:
+             case expr_lcase:
+             case expr_ucase:
              case expr_option:
              case expr_hardware:
              case expr_const_data:
@@ -1198,6 +1201,8 @@ int evaluate_boolean_expression (result, packet, lease, client_state,
              case expr_match:
              case expr_substring:
              case expr_suffix:
+             case expr_lcase:
+             case expr_ucase:
              case expr_option:
              case expr_hardware:
              case expr_const_data:
@@ -1279,7 +1284,7 @@ int evaluate_data_expression (result, packet, lease, client_state,
        int s0, s1, s2, s3;
        int status;
        struct binding *binding;
-       char *s;
+       unsigned char *s;
        struct binding_value *bv;
 
        switch (expr -> op) {
@@ -1333,7 +1338,6 @@ int evaluate_data_expression (result, packet, lease, client_state,
                        return 1;
                return 0;
 
-
                /* Extract the last N bytes of a data string. */
              case expr_suffix:
                memset (&data, 0, sizeof data);
@@ -1372,6 +1376,78 @@ int evaluate_data_expression (result, packet, lease, client_state,
 #endif
                return s0 && s1;
 
+               /* Convert string to lowercase. */
+             case expr_lcase:
+               memset(&data, 0, sizeof data);
+               s0 = evaluate_data_expression(&data, packet, lease,
+                                             client_state,
+                                             in_options, cfg_options, scope,
+                                             expr->data.lcase, MDL);
+               s1 = 0;
+               if (s0) {
+                       result->len = data.len;
+                       if (buffer_allocate(&result->buffer,
+                                           result->len + data.terminated,
+                                           MDL)) {
+                               result->data = &result->buffer->data[0];
+                               memcpy(result->buffer->data, data.data,
+                                      data.len + data.terminated);
+                               result->terminated = data.terminated;
+                               s = (unsigned char *)result->data;
+                               for (i = 0; i < result->len; i++, s++)
+                                       *s = tolower(*s);
+                               s1 = 1;
+                       } else {
+                               log_error("data: lcase: no buffer memory.");
+                       }
+               }
+
+#if defined (DEBUG_EXPRESSIONS)
+               log_debug("data: lcase (%s) = %s",
+                         s0 ? print_hex_1(data.len, data.data, 30) : "NULL",
+                         s1 ? print_hex_2(result->len, result->data, 30)
+                            : "NULL");
+#endif
+               if (s0)
+                       data_string_forget(&data, MDL);
+               return s1;
+
+               /* Convert string to uppercase. */
+             case expr_ucase:
+               memset(&data, 0, sizeof data);
+               s0 = evaluate_data_expression(&data, packet, lease,
+                                             client_state,
+                                             in_options, cfg_options, scope,
+                                             expr->data.lcase, MDL);
+               s1 = 0;
+               if (s0) {
+                       result->len = data.len;
+                       if (buffer_allocate(&result->buffer,
+                                           result->len + data.terminated,
+                                           file, line)) {
+                               result->data = &result->buffer->data[0];
+                               memcpy(result->buffer->data, data.data,
+                                      data.len + data.terminated);
+                               result->terminated = data.terminated;
+                               s = (unsigned char *)result->data;
+                               for (i = 0; i < result->len; i++, s++)
+                                       *s = toupper(*s);
+                               s1 = 1;
+                       } else {
+                               log_error("data: lcase: no buffer memory.");
+                       }
+               }
+
+#if defined (DEBUG_EXPRESSIONS)
+               log_debug("data: ucase (%s) = %s",
+                         s0 ? print_hex_1(data.len, data.data, 30) : "NULL",
+                         s1 ? print_hex_2(result->len, result->data, 30)
+                            : "NULL");
+#endif
+                if (s0)
+                       data_string_forget(&data, MDL);
+                return s1;
+
                /* Extract an option. */
              case expr_option:
                if (in_options)
@@ -2164,6 +2240,8 @@ int evaluate_numeric_expression (result, packet, lease, client_state,
 
              case expr_substring:
              case expr_suffix:
+             case expr_lcase:
+             case expr_ucase:
              case expr_option:
              case expr_hardware:
              case expr_const_data:
@@ -2799,6 +2877,16 @@ void expression_dereference (eptr, file, line)
                                                file, line);
                break;
 
+             case expr_lcase:
+               if (expr->data.lcase)
+                       expression_dereference(&expr->data.lcase, MDL);
+               break;
+
+             case expr_ucase:
+               if (expr->data.ucase)
+                       expression_dereference(&expr->data.ucase, MDL);
+               break;
+
              case expr_not:
                if (expr -> data.not)
                        expression_dereference (&expr -> data.not, file, line);
@@ -2979,27 +3067,29 @@ int is_boolean_expression (expr)
 int is_data_expression (expr)
        struct expression *expr;
 {
-       return (expr -> op == expr_substring ||
-               expr -> op == expr_suffix ||
-               expr -> op == expr_option ||
-               expr -> op == expr_hardware ||
-               expr -> op == expr_const_data ||
-               expr -> op == expr_packet ||
-               expr -> op == expr_concat ||
-               expr -> op == expr_encapsulate ||
-               expr -> op == expr_encode_int8 ||
-               expr -> op == expr_encode_int16 ||
-               expr -> op == expr_encode_int32 ||
-               expr -> op == expr_host_lookup ||
-               expr -> op == expr_binary_to_ascii ||
-               expr -> op == expr_filename ||
-               expr -> op == expr_sname ||
-               expr -> op == expr_reverse ||
-               expr -> op == expr_pick_first_value ||
-               expr -> op == expr_host_decl_name ||
-               expr -> op == expr_leased_address ||
-               expr -> op == expr_config_option ||
-               expr -> op == expr_null);
+       return (expr->op == expr_substring ||
+               expr->op == expr_suffix ||
+               expr->op == expr_lcase ||
+               expr->op == expr_ucase ||
+               expr->op == expr_option ||
+               expr->op == expr_hardware ||
+               expr->op == expr_const_data ||
+               expr->op == expr_packet ||
+               expr->op == expr_concat ||
+               expr->op == expr_encapsulate ||
+               expr->op == expr_encode_int8 ||
+               expr->op == expr_encode_int16 ||
+               expr->op == expr_encode_int32 ||
+               expr->op == expr_host_lookup ||
+               expr->op == expr_binary_to_ascii ||
+               expr->op == expr_filename ||
+               expr->op == expr_sname ||
+               expr->op == expr_reverse ||
+               expr->op == expr_pick_first_value ||
+               expr->op == expr_host_decl_name ||
+               expr->op == expr_leased_address ||
+               expr->op == expr_config_option ||
+               expr->op == expr_null);
 }
 
 int is_numeric_expression (expr)
@@ -3058,6 +3148,8 @@ static int op_val (op)
              case expr_check:
              case expr_substring:
              case expr_suffix:
+             case expr_lcase:
+             case expr_ucase:
              case expr_concat:
              case expr_encapsulate:
              case expr_host_lookup:
@@ -3154,6 +3246,8 @@ enum expression_context op_context (op)
              case expr_check:
              case expr_substring:
              case expr_suffix:
+             case expr_lcase:
+             case expr_ucase:
              case expr_concat:
              case expr_encapsulate:
              case expr_host_lookup:
@@ -3289,6 +3383,21 @@ int write_expression (file, expr, col, indent, firstp)
                col = write_expression (file, expr -> data.suffix.len,
                                        col, scol, 0);
                col = token_print_indent (file, col, indent, "", "", ")");
+
+             case expr_lcase:
+               col = token_print_indent(file, col, indent, "", "", "lcase");
+               col = token_print_indent(file, col, indent, " ", "", "(");
+               scol = col;
+               col = write_expression(file, expr->data.lcase, col, scol, 1);
+               col = token_print_indent(file, col, indent, "", "", ")");
+               break;
+
+             case expr_ucase:
+               col = token_print_indent(file, col, indent, "", "", "ucase");
+               col = token_print_indent(file, col, indent, " ", "", "(");
+               scol = col;
+               col = write_expression(file, expr->data.ucase, col, scol, 1);
+               col = token_print_indent(file, col, indent, "", "", ")");
                break;
 
              case expr_concat:
@@ -3857,6 +3966,12 @@ int data_subexpression_length (int *rv,
                }
                return 0;
 
+             case expr_lcase:
+               return data_subexpression_length(rv, expr->data.lcase);
+
+             case expr_ucase:
+               return data_subexpression_length(rv, expr->data.ucase);
+
              case expr_concat:
                clhs = data_subexpression_length (&llhs,
                                                  expr -> data.concat [0]);
index da8da3d429adc33517b31e49862d4f8a896af08b..88bf0264f0cfadd06b389c7ee223d05b12333985 100644 (file)
@@ -309,7 +309,9 @@ enum dhcp_token {
        DOMAIN_NAME = 613,
        DO_FORWARD_UPDATE = 614,
        KNOWN_CLIENTS = 615,
-       ATSFP = 616
+       ATSFP = 616,
+       LCASE = 617,
+       UCASE = 618
 };
 
 #define is_identifier(x)       ((x) >= FIRST_TOKEN &&  \
index 64f4397766d791c07b2b1fbd84f2fa9e5b86feb3..b12bc9ec93788f556b16ce6108b050a176633940 100644 (file)
@@ -190,13 +190,15 @@ enum expr_op {
        expr_binary_and,
        expr_binary_or,
        expr_binary_xor,
-       expr_client_state
+       expr_client_state,
+       expr_ucase,
+       expr_lcase
 };
 
 struct expression {
        int refcnt;
        enum expr_op op;
-       union {
+       union expr_union {
                struct {
                        struct expression *expr;
                        struct expression *offset;
@@ -216,6 +218,8 @@ struct expression {
                        struct expression *expr;
                        struct expression *len;
                } suffix;
+               struct expression *lcase;
+               struct expression *ucase;
                struct option *option;
                struct option *config_option;
                struct {