diff --git a/doc/configuration.txt b/doc/configuration.txt index 229574424..128447dc0 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -10155,18 +10155,42 @@ sample fetch method. These keywords may equally be appended immediately after the fetch keyword's argument, delimited by a comma. These keywords can also support some arguments (eg: a netmask) which must be passed in parenthesis. +A certain category of converters are bitwise and arithmetic operators which +support performing basic operations on integers. Some bitwise operations are +supported (and, or, xor, cpl) and some arithmetic operations are supported +(add, sub, mul, div, mod, neg). Some comparators are provided (odd, even, not, +bool) which make it possible to report a match without having to write an ACL. + The currently available list of transformation keywords include : +add() + Adds to the input value of type unsigned integer, and returns the + result as an unsigned integer. + +and() + Performs a bitwise "AND" between and the input value of type unsigned + integer, and returns the result as an unsigned integer. + base64 Converts a binary input sample to a base64 string. It is used to log or transfer binary content in a way that can be reliably transferred (eg: an SSL ID can be copied in a header). +bool + Returns a boolean TRUE if the input value of type unsigned integer is + non-null, otherwise returns FALSE. Used in conjunction with and(), it can be + used to report true/false for bit testing on input values (eg: verify the + presence of a flag). + bytes([,]) Extracts some bytes from an input binary sample. The result is a binary sample starting at an offset (in bytes) of the original sample and optionnaly truncated at the given length. +cpl + Takes the input value of type unsigned integer, applies a twos-complement + (flips all bits) and returns the result as an unsigned integer. + crc32([]) Hashes a binary input sample into an unsigned 32-bit quantity using the CRC32 hash function. Optionally, it is possible to apply a full avalanche hash @@ -10180,6 +10204,11 @@ crc32([]) not be used for security purposes as a 32-bit hash is trivial to break. See also "djb2", "sdbm", "wt6" and the "hash-type" directive. +div() + Divides the input value of type unsigned integer by , and returns the + result as an unsigned integer. If is null, the largest unsigned + integer is returned (typically 2^32-1). + djb2([]) Hashes a binary input sample into an unsigned 32-bit quantity using the DJB2 hash function. Optionally, it is possible to apply a full avalanche hash @@ -10191,6 +10220,10 @@ djb2([]) 32-bit hash is trivial to break. See also "crc32", "sdbm", "wt6" and the "hash-type" directive. +even + Returns a boolean TRUE if the input value of type unsigned integer is even + otherwise returns FALSE. It is functionally equivalent to "not,and(1),bool". + field(,) Extracts the substring at the given index considering given delimiters from an input string. Indexes start at 1 and delimiters are a string formatted @@ -10366,6 +10399,35 @@ map__([,]) | `---------------------------- key `------------------------------------ leading spaces ignored +mod() + Divides the input value of type unsigned integer by , and returns the + remainder as an unsigned integer. If is null, then zero is returned. + +mul() + Multiplies the input value of type unsigned integer by , and returns + the product as an unsigned integer. In case of overflow, the higher bits are + lost, leading to seemingly strange values. + +neg + Takes the input value of type unsigned integer, computes the opposite value, + and returns the remainder as an unsigned integer. 0 is identity. This + operator is provided for reversed subtracts : in order to subtract the input + from a constant, simply perform a "neg,add(value)". + +not + Returns a boolean FALSE if the input value of type unsigned integer is + non-null, otherwise returns TRUE. Used in conjunction with and(), it can be + used to report true/false for bit testing on input values (eg: verify the + absence of a flag). + +odd + Returns a boolean TRUE if the input value of type unsigned integer is odd + otherwise returns FALSE. It is functionally equivalent to "and(1),bool". + +or() + Performs a bitwise "OR" between and the input value of type unsigned + integer, and returns the result as an unsigned integer. + regsub(,[,]) Applies a regex-based substitution to the input string. It does the same operation as the well-known "sed" utility with "s///". By @@ -10399,6 +10461,11 @@ sdbm([]) 32-bit hash is trivial to break. See also "crc32", "djb2", "wt6" and the "hash-type" directive. +sub() + Subtracts from the input value of type unsigned integer, and returns + the result as an unsigned integer. Note: in order to subtract the input from + a constant, simply perform a "neg,add(value)". + table_bytes_in_rate() Uses the string representation of the input sample to perform a look up in the specified table. If the key is not found in the table, integer value zero @@ -10572,6 +10639,10 @@ wt6([]) 32-bit hash is trivial to break. See also "crc32", "djb2", "sdbm", and the "hash-type" directive. +xor() + Performs a bitwise "XOR" (exclusive OR) between and the input value + of type unsigned integer, and returns the result as an unsigned integer. + 7.3.2. Fetching samples from internal states -------------------------------------------- diff --git a/src/sample.c b/src/sample.c index a1c6b4606..57b2c003a 100644 --- a/src/sample.c +++ b/src/sample.c @@ -1888,6 +1888,144 @@ static int sample_conv_regsub(const struct arg *arg_p, struct sample *smp) return 1; } +/* Takes a UINT on input, applies a binary twos complement and returns the UINT + * result. + */ +static int sample_conv_binary_cpl(const struct arg *arg_p, struct sample *smp) +{ + smp->data.uint = ~smp->data.uint; + return 1; +} + +/* Takes a UINT on input, applies a binary "and" with the UINT in arg_p, and + * returns the UINT result. + */ +static int sample_conv_binary_and(const struct arg *arg_p, struct sample *smp) +{ + smp->data.uint &= arg_p->data.uint; + return 1; +} + +/* Takes a UINT on input, applies a binary "or" with the UINT in arg_p, and + * returns the UINT result. + */ +static int sample_conv_binary_or(const struct arg *arg_p, struct sample *smp) +{ + smp->data.uint |= arg_p->data.uint; + return 1; +} + +/* Takes a UINT on input, applies a binary "xor" with the UINT in arg_p, and + * returns the UINT result. + */ +static int sample_conv_binary_xor(const struct arg *arg_p, struct sample *smp) +{ + smp->data.uint ^= arg_p->data.uint; + return 1; +} + +/* Takes a UINT on input, applies an arithmetic "add" with the UINT in arg_p, + * and returns the UINT result. + */ +static int sample_conv_arith_add(const struct arg *arg_p, struct sample *smp) +{ + smp->data.uint += arg_p->data.uint; + return 1; +} + +/* Takes a UINT on input, applies an arithmetic "sub" with the UINT in arg_p, + * and returns the UINT result. + */ +static int sample_conv_arith_sub(const struct arg *arg_p, struct sample *smp) +{ + smp->data.uint -= arg_p->data.uint; + return 1; +} + +/* Takes a UINT on input, applies an arithmetic "mul" with the UINT in arg_p, + * and returns the UINT result. + */ +static int sample_conv_arith_mul(const struct arg *arg_p, struct sample *smp) +{ + smp->data.uint *= arg_p->data.uint; + return 1; +} + +/* Takes a UINT on input, applies an arithmetic "div" with the UINT in arg_p, + * and returns the UINT result. If arg_p makes the result overflow, then the + * largest possible quantity is returned. + */ +static int sample_conv_arith_div(const struct arg *arg_p, struct sample *smp) +{ + if (arg_p->data.uint) + smp->data.uint /= arg_p->data.uint; + else + smp->data.uint = ~0; + return 1; +} + +/* Takes a UINT on input, applies an arithmetic "mod" with the UINT in arg_p, + * and returns the UINT result. If arg_p makes the result overflow, then zero + * is returned. + */ +static int sample_conv_arith_mod(const struct arg *arg_p, struct sample *smp) +{ + if (arg_p->data.uint) + smp->data.uint %= arg_p->data.uint; + else + smp->data.uint = 0; + return 1; +} + +/* Takes an UINT on input, applies an arithmetic "neg" and returns the UINT + * result. + */ +static int sample_conv_arith_neg(const struct arg *arg_p, struct sample *smp) +{ + smp->data.uint = -smp->data.uint; + return 1; +} + +/* Takes a UINT on input, returns true is the value is non-null, otherwise + * false. The output is a BOOL. + */ +static int sample_conv_arith_bool(const struct arg *arg_p, struct sample *smp) +{ + smp->data.uint = !!smp->data.uint; + smp->type = SMP_T_BOOL; + return 1; +} + +/* Takes a UINT on input, returns false is the value is non-null, otherwise + * truee. The output is a BOOL. + */ +static int sample_conv_arith_not(const struct arg *arg_p, struct sample *smp) +{ + smp->data.uint = !smp->data.uint; + smp->type = SMP_T_BOOL; + return 1; +} + +/* Takes a UINT on input, returns true is the value is odd, otherwise false. + * The output is a BOOL. + */ +static int sample_conv_arith_odd(const struct arg *arg_p, struct sample *smp) +{ + smp->data.uint = smp->data.uint & 1; + smp->type = SMP_T_BOOL; + return 1; +} + +/* Takes a UINT on input, returns true is the value is even, otherwise false. + * The output is a BOOL. + */ +static int sample_conv_arith_even(const struct arg *arg_p, struct sample *smp) +{ + smp->data.uint = !(smp->data.uint & 1); + smp->type = SMP_T_BOOL; + return 1; +} + /************************************************************************/ /* All supported sample fetch functions must be declared here */ /************************************************************************/ @@ -2034,6 +2172,22 @@ static struct sample_conv_kw_list sample_conv_kws = {ILH, { { "field", sample_conv_field, ARG2(2,UINT,STR), sample_conv_field_check, SMP_T_STR, SMP_T_STR }, { "word", sample_conv_word, ARG2(2,UINT,STR), sample_conv_field_check, SMP_T_STR, SMP_T_STR }, { "regsub", sample_conv_regsub, ARG3(2,REG,STR,STR), sample_conv_regsub_check, SMP_T_STR, SMP_T_STR }, + + { "and", sample_conv_binary_and, ARG1(1,UINT), NULL, SMP_T_UINT, SMP_T_UINT }, + { "or", sample_conv_binary_or, ARG1(1,UINT), NULL, SMP_T_UINT, SMP_T_UINT }, + { "xor", sample_conv_binary_xor, ARG1(1,UINT), NULL, SMP_T_UINT, SMP_T_UINT }, + { "cpl", sample_conv_binary_cpl, 0, NULL, SMP_T_UINT, SMP_T_UINT }, + { "bool", sample_conv_arith_bool, 0, NULL, SMP_T_UINT, SMP_T_BOOL }, + { "not", sample_conv_arith_not, 0, NULL, SMP_T_UINT, SMP_T_BOOL }, + { "odd", sample_conv_arith_odd, 0, NULL, SMP_T_UINT, SMP_T_BOOL }, + { "even", sample_conv_arith_even, 0, NULL, SMP_T_UINT, SMP_T_BOOL }, + { "add", sample_conv_arith_add, ARG1(1,UINT), NULL, SMP_T_UINT, SMP_T_UINT }, + { "sub", sample_conv_arith_sub, ARG1(1,UINT), NULL, SMP_T_UINT, SMP_T_UINT }, + { "mul", sample_conv_arith_mul, ARG1(1,UINT), NULL, SMP_T_UINT, SMP_T_UINT }, + { "div", sample_conv_arith_div, ARG1(1,UINT), NULL, SMP_T_UINT, SMP_T_UINT }, + { "mod", sample_conv_arith_mod, ARG1(1,UINT), NULL, SMP_T_UINT, SMP_T_UINT }, + { "neg", sample_conv_arith_neg, 0, NULL, SMP_T_UINT, SMP_T_UINT }, + { NULL, NULL, 0, 0, 0 }, }};