mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-22 01:49:35 +00:00
- Two new operators, ~= and ~~, have been integrated to implement
boolean matches by regular expression (such as may be used in class matching statements). Thanks to a patch by Alexandr S. Agranovsky, which underwent slight modification. [ISC-Bugs #8155]
This commit is contained in:
parent
a546f2a714
commit
dd3282251e
5
RELNOTES
5
RELNOTES
@ -54,6 +54,11 @@ suggested fixes to <dhcp-users@isc.org>.
|
||||
|
||||
Changes since 4.0.0a1
|
||||
|
||||
- Two new operators, ~= and ~~, have been integrated to implement
|
||||
boolean matches by regular expression (such as may be used in
|
||||
class matching statements). Thanks to a patch by Alexandr S.
|
||||
Agranovsky, which underwent slight modification.
|
||||
|
||||
- Fix for icmp packets on 64-bit systems (bug introduced in 4.0).
|
||||
|
||||
- A bug was fixed in interface discovery wherein an error identifying
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $Id: dhcp-eval.5,v 1.26 2007/05/19 19:16:24 dhankins Exp $
|
||||
.\" $Id: dhcp-eval.5,v 1.27 2007/06/07 15:52:29 dhankins Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2004,2007 by Internet Systems Consortium, Inc. ("ISC")
|
||||
.\" Copyright (c) 1996-2003 by Internet Software Consortium
|
||||
@ -114,7 +114,7 @@ treated as false in conditionals.
|
||||
The following is the current list of boolean expressions that are
|
||||
supported by the DHCP distribution.
|
||||
.PP
|
||||
.I data-expression-1 \fB=\fI data-expression-2\fR
|
||||
.I data-expression-1 \fB=\fR \fIdata-expression-2\fR
|
||||
.RS 0.25i
|
||||
.PP
|
||||
The \fB=\fR operator compares the values of two data expressions,
|
||||
@ -123,7 +123,20 @@ either the left-hand side or the right-hand side are null, the
|
||||
result is also null.
|
||||
.RE
|
||||
.PP
|
||||
.I boolean-expression-1 \fBand\fI boolean-expression-2\fR
|
||||
.I data-expression-1 \fB~=\fR \fIdata-expression-2\fR
|
||||
.I data-expression-1 \fB~~\fR \fIdata-expression-2\fR
|
||||
.RS 0.25i
|
||||
.PP
|
||||
The \fB~=\fR and \fB~~\fR operators (not available on all systems) perform
|
||||
extended regex(7) matching of the values of two data expressions, returning
|
||||
true if \fIdata-expression-1\fR matches against the regular expression
|
||||
evaluated by \fIdata-expression-2\fR, or false if it does not match or
|
||||
encounters some error. If either the left-hand side or the right-hand side
|
||||
are null, the result is also false. The \fB~~\fR operator differs from the
|
||||
\fB~=\fR operator in that it is case-insensitive.
|
||||
.RE
|
||||
.PP
|
||||
.I boolean-expression-1 \fBand\fR \fIboolean-expression-2\fR
|
||||
.PP
|
||||
.RS 0.25i
|
||||
The \fBand\fR operator evaluates to true if the boolean expression on
|
||||
@ -133,7 +146,7 @@ the expression on the left-hand side or the expression on the
|
||||
right-hand side are null, the result is null.
|
||||
.RE
|
||||
.PP
|
||||
.I boolean-expression-1 \fBor\fI boolean-expression-2\fR
|
||||
.I boolean-expression-1 \fBor\fR \fIboolean-expression-2\fR
|
||||
.PP
|
||||
.RS 0.25i
|
||||
The \fBor\fR operator evaluates to true if either the boolean
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"$Id: parse.c,v 1.126 2007/05/29 18:11:55 each Exp $ Copyright (c) 2004-2007 Internet Systems Consortium. All rights reserved.\n";
|
||||
"$Id: parse.c,v 1.127 2007/06/07 15:52:29 dhankins Exp $ Copyright (c) 2004-2007 Internet Systems Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
@ -3195,6 +3195,7 @@ int parse_if_statement (result, cfile, lose)
|
||||
* NOT boolean-expression |
|
||||
* data-expression EQUAL data-expression |
|
||||
* data-expression BANG EQUAL data-expression |
|
||||
* data-expression REGEX_MATCH data-expression |
|
||||
* boolean-expression AND boolean-expression |
|
||||
* boolean-expression OR boolean-expression
|
||||
* EXISTS OPTION-NAME
|
||||
@ -4559,6 +4560,35 @@ int parse_expression (expr, cfile, lose, context, plhs, binop)
|
||||
context = expression_context (rhs);
|
||||
break;
|
||||
|
||||
case TILDE:
|
||||
#ifdef HAVE_REGEX_H
|
||||
token = next_token(&val, NULL, cfile);
|
||||
token = peek_token(&val, NULL, cfile);
|
||||
|
||||
if (token == TILDE)
|
||||
next_op = expr_iregex_match;
|
||||
else if (token == EQUAL)
|
||||
next_op = expr_regex_match;
|
||||
else {
|
||||
parse_warn(cfile, "expecting ~= or ~~ operator");
|
||||
*lose = 1;
|
||||
skip_to_semi(cfile);
|
||||
if (lhs)
|
||||
expression_dereference(&lhs, MDL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
context = expression_context(rhs);
|
||||
#else
|
||||
parse_warn(cfile, "No support for regex operator.");
|
||||
*lose = 1;
|
||||
skip_to_semi(cfile);
|
||||
if (lhs != NULL)
|
||||
expression_dereference(&lhs, MDL);
|
||||
return 0;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case AND:
|
||||
next_op = expr_and;
|
||||
context = expression_context (rhs);
|
||||
@ -4685,6 +4715,23 @@ int parse_expression (expr, cfile, lose, context, plhs, binop)
|
||||
}
|
||||
break;
|
||||
|
||||
case expr_regex_match:
|
||||
#ifdef HAVE_REGEX_H
|
||||
if (expression_context(rhs) != context_data) {
|
||||
parse_warn(cfile, "expecting data expression");
|
||||
skip_to_semi(cfile);
|
||||
expression_dereference(&rhs, MDL);
|
||||
*lose = 1;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
/* It should not be possible to attempt to parse the right
|
||||
* hand side of an operator there is no support for.
|
||||
*/
|
||||
log_fatal("Impossible condition at %s:%d.", MDL);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case expr_and:
|
||||
case expr_or:
|
||||
if ((rhs_context != context_boolean) &&
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"$Id: print.c,v 1.66 2007/05/29 18:11:55 each Exp $ Copyright (c) 2004-2007 Internet Systems Consortium. All rights reserved.\n";
|
||||
"$Id: print.c,v 1.67 2007/06/07 15:52:29 dhankins Exp $ Copyright (c) 2004-2007 Internet Systems Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
@ -517,6 +517,21 @@ static unsigned print_subexpression (expr, buf, len)
|
||||
}
|
||||
break;
|
||||
|
||||
case expr_regex_match:
|
||||
if (len > 10) {
|
||||
rv = 4;
|
||||
strcpy(buf, "(regex ");
|
||||
rv += print_subexpression(expr->data.equal[0],
|
||||
buf + rv, len - rv - 2);
|
||||
buf[rv++] = ' ';
|
||||
rv += print_subexpression(expr->data.equal[1],
|
||||
buf + rv, len - rv - 1);
|
||||
buf[rv++] = ')';
|
||||
buf[rv] = 0;
|
||||
return rv;
|
||||
}
|
||||
break;
|
||||
|
||||
case expr_substring:
|
||||
if (len > 11) {
|
||||
rv = 8;
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"$Id: tree.c,v 1.115 2007/05/19 19:16:24 dhankins Exp $ Copyright (c) 2004-2007 Internet Systems Consortium. All rights reserved.\n";
|
||||
"$Id: tree.c,v 1.116 2007/06/07 15:52:29 dhankins Exp $ Copyright (c) 2004-2007 Internet Systems Consortium. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "dhcpd.h"
|
||||
@ -42,6 +42,10 @@ static char copyright[] =
|
||||
#include <ctype.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#ifdef HAVE_REGEX_H
|
||||
# include <regex.h>
|
||||
#endif
|
||||
|
||||
struct binding_scope *global_scope;
|
||||
|
||||
static int do_host_lookup PROTO ((struct data_string *,
|
||||
@ -968,6 +972,8 @@ int evaluate_dns_expression (result, packet, lease, client_state, in_options,
|
||||
case expr_check:
|
||||
case expr_equal:
|
||||
case expr_not_equal:
|
||||
case expr_regex_match:
|
||||
case expr_iregex_match:
|
||||
case expr_and:
|
||||
case expr_or:
|
||||
case expr_not:
|
||||
@ -1061,6 +1067,10 @@ int evaluate_boolean_expression (result, packet, lease, client_state,
|
||||
int sleft, sright;
|
||||
struct binding *binding;
|
||||
struct binding_value *bv, *obv;
|
||||
#ifdef HAVE_REGEX_H
|
||||
int reg_st, regflags = REG_EXTENDED | REG_NOSUB;
|
||||
regex_t re;
|
||||
#endif
|
||||
|
||||
switch (expr -> op) {
|
||||
case expr_check:
|
||||
@ -1153,6 +1163,57 @@ int evaluate_boolean_expression (result, packet, lease, client_state,
|
||||
binding_value_dereference (&obv, MDL);
|
||||
return 1;
|
||||
|
||||
case expr_iregex_match:
|
||||
#ifdef HAVE_REGEX_H
|
||||
regflags |= REG_ICASE;
|
||||
#endif
|
||||
/* FALL THROUGH */
|
||||
case expr_regex_match:
|
||||
#ifdef HAVE_REGEX_H
|
||||
memset(&left, 0, sizeof left);
|
||||
bleft = evaluate_data_expression(&left, packet, lease,
|
||||
client_state,
|
||||
in_options, cfg_options,
|
||||
scope,
|
||||
expr->data.equal[0], MDL);
|
||||
memset(&right, 0, sizeof right);
|
||||
bright = evaluate_data_expression(&right, packet, lease,
|
||||
client_state,
|
||||
in_options, cfg_options,
|
||||
scope,
|
||||
expr->data.equal[1], MDL);
|
||||
|
||||
*result = 0;
|
||||
memset(&re, 0, sizeof(re));
|
||||
if (bleft && bright &&
|
||||
(regcomp(&re, right.data, regflags) == 0) &&
|
||||
(regexec(&re, left.data, (size_t)0, NULL, 0) == 0))
|
||||
*result = 1;
|
||||
|
||||
#if defined (DEBUG_EXPRESSIONS)
|
||||
log_debug("bool: %s ~= %s yields %s",
|
||||
bleft ? print_hex_1(left.len, left.data, 20)
|
||||
: "NULL",
|
||||
bright ? print_hex_2 (right.len, right.data, 20)
|
||||
: "NULL",
|
||||
*result ? "true" : "false");
|
||||
#endif
|
||||
|
||||
if (bleft)
|
||||
data_string_forget(&left, MDL);
|
||||
if (bright)
|
||||
data_string_forget(&right, MDL);
|
||||
|
||||
regfree(&re);
|
||||
return reg_st;
|
||||
#else
|
||||
/* It shouldn't be possible to configure a regex operator
|
||||
* when there's no support.
|
||||
*/
|
||||
log_fatal("Impossible condition at %s:%d.", MDL);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case expr_and:
|
||||
sleft = evaluate_boolean_expression (&bleft, packet, lease,
|
||||
client_state,
|
||||
@ -2296,6 +2357,8 @@ int evaluate_data_expression (result, packet, lease, client_state,
|
||||
case expr_check:
|
||||
case expr_equal:
|
||||
case expr_not_equal:
|
||||
case expr_regex_match:
|
||||
case expr_iregex_match:
|
||||
case expr_and:
|
||||
case expr_or:
|
||||
case expr_not:
|
||||
@ -2374,6 +2437,8 @@ int evaluate_numeric_expression (result, packet, lease, client_state,
|
||||
case expr_check:
|
||||
case expr_equal:
|
||||
case expr_not_equal:
|
||||
case expr_regex_match:
|
||||
case expr_iregex_match:
|
||||
case expr_and:
|
||||
case expr_or:
|
||||
case expr_not:
|
||||
@ -2990,6 +3055,8 @@ void expression_dereference (eptr, file, line)
|
||||
/* All the binary operators can be handled the same way. */
|
||||
case expr_equal:
|
||||
case expr_not_equal:
|
||||
case expr_regex_match:
|
||||
case expr_iregex_match:
|
||||
case expr_concat:
|
||||
case expr_and:
|
||||
case expr_or:
|
||||
@ -3211,6 +3278,8 @@ int is_boolean_expression (expr)
|
||||
expr -> op == expr_variable_exists ||
|
||||
expr -> op == expr_equal ||
|
||||
expr -> op == expr_not_equal ||
|
||||
expr->op == expr_regex_match ||
|
||||
expr->op == expr_iregex_match ||
|
||||
expr -> op == expr_and ||
|
||||
expr -> op == expr_or ||
|
||||
expr -> op == expr_not ||
|
||||
@ -3350,6 +3419,8 @@ static int op_val (op)
|
||||
|
||||
case expr_equal:
|
||||
case expr_not_equal:
|
||||
case expr_regex_match:
|
||||
case expr_iregex_match:
|
||||
return 4;
|
||||
|
||||
case expr_or:
|
||||
@ -3443,6 +3514,8 @@ enum expression_context op_context (op)
|
||||
|
||||
case expr_equal:
|
||||
case expr_not_equal:
|
||||
case expr_regex_match:
|
||||
case expr_iregex_match:
|
||||
return context_data;
|
||||
|
||||
case expr_and:
|
||||
@ -3498,6 +3571,14 @@ int write_expression (file, expr, col, indent, firstp)
|
||||
"\"", (char *)0);
|
||||
break;
|
||||
|
||||
case expr_regex_match:
|
||||
s = "~=";
|
||||
goto binary;
|
||||
|
||||
case expr_iregex_match:
|
||||
s = "~~";
|
||||
goto binary;
|
||||
|
||||
case expr_not_equal:
|
||||
s = "!=";
|
||||
goto binary;
|
||||
@ -4179,6 +4260,8 @@ int data_subexpression_length (int *rv,
|
||||
case expr_match:
|
||||
case expr_check:
|
||||
case expr_equal:
|
||||
case expr_regex_match:
|
||||
case expr_iregex_match:
|
||||
case expr_and:
|
||||
case expr_or:
|
||||
case expr_not:
|
||||
|
@ -86,9 +86,7 @@ else
|
||||
fi
|
||||
|
||||
# Look for optional headers.
|
||||
AC_CHECK_HEADER(net/if_dl.h,
|
||||
AC_DEFINE([HAVE_IF_DL], [1],
|
||||
[Define to 1 if the system has a net/if_dl.h header.]))
|
||||
AC_CHECK_HEADERS(net/if_dl.h regex.h)
|
||||
|
||||
# find an MD5 library
|
||||
AC_SEARCH_LIBS(MD5_Init, [crypto])
|
||||
@ -102,6 +100,9 @@ AC_SEARCH_LIBS(inet_aton, [socket nsl], ,
|
||||
AC_DEFINE([NEED_INET_ATON], [1],
|
||||
[Define to 1 if the inet_aton() function is missing.]))
|
||||
|
||||
# Check for a standalone regex library.
|
||||
AC_SEARCH_LIBS(regcomp, [regex])
|
||||
|
||||
# check for /dev/random (declares HAVE_DEV_RANDOM)
|
||||
AC_CHECK_FILE(/dev/random,
|
||||
AC_DEFINE([HAVE_DEV_RANDOM], [1],
|
||||
|
@ -59,7 +59,7 @@
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
#include <net/if_arp.h>
|
||||
#if HAVE_IF_DL
|
||||
#if HAVE_IF_DL_H
|
||||
# include <net/if_dl.h>
|
||||
#endif
|
||||
|
||||
|
@ -43,6 +43,7 @@ enum dhcp_token {
|
||||
LPAREN = '(',
|
||||
RPAREN = ')',
|
||||
EQUAL = '=',
|
||||
TILDE = '~',
|
||||
BANG = '!',
|
||||
PERCENT = '%',
|
||||
PLUS = '+',
|
||||
|
@ -193,7 +193,9 @@ enum expr_op {
|
||||
expr_binary_xor,
|
||||
expr_client_state,
|
||||
expr_ucase,
|
||||
expr_lcase
|
||||
expr_lcase,
|
||||
expr_regex_match,
|
||||
expr_iregex_match
|
||||
};
|
||||
|
||||
struct expression {
|
||||
|
Loading…
x
Reference in New Issue
Block a user