MINOR: sample: Add strcmp sample converter
This converter supplements the existing string matching by allowing
strings to be converted to a variable.
Example usage:
http-request set-var(txn.host) hdr(host)
# Check whether the client is attempting domain fronting.
acl ssl_sni_http_host_match ssl_fc_sni,strcmp(txn.host) eq 0
diff --git a/doc/configuration.txt b/doc/configuration.txt
index dcc87fd..b865b33 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -13242,6 +13242,21 @@
Converts a binary input sample to a SHA1 digest. The result is a binary
sample with length of 20 bytes.
+strcmp(<var>)
+ Compares the contents of <var> with the input value of type string. Returns
+ the result as a signed integer compatible with strcmp(3): 0 if both strings
+ are identical. A value less than 0 if the left string is lexicographically
+ smaller than the right string or if the left string is shorter. A value greater
+ than 0 otherwise (right string greater than left string or the right string is
+ shorter).
+
+ Example :
+
+ http-request set-var(txn.host) hdr(host)
+ # Check whether the client is attempting domain fronting.
+ acl ssl_sni_http_host_match ssl_fc_sni,strcmp(txn.host) eq 0
+
+
sub(<value>)
Subtracts <value> from the input value of type signed integer, and returns
the result as an signed integer. Note: in order to subtract the input from
diff --git a/src/sample.c b/src/sample.c
index b1c0148..3f72266 100644
--- a/src/sample.c
+++ b/src/sample.c
@@ -2684,6 +2684,54 @@
return 1;
}
+/* compares string with a variable containing a string. Return value
+ * is compatible with strcmp(3)'s return value.
+ */
+static int sample_conv_strcmp(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ struct sample tmp;
+ int max, result;
+
+ smp_set_owner(&tmp, smp->px, smp->sess, smp->strm, smp->opt);
+ if (arg_p[0].type != ARGT_VAR)
+ return 0;
+ if (!vars_get_by_desc(&arg_p[0].data.var, &tmp))
+ return 0;
+ if (!sample_casts[tmp.data.type][SMP_T_STR](&tmp))
+ return 0;
+
+ max = MIN(smp->data.u.str.len, tmp.data.u.str.len);
+ result = strncmp(smp->data.u.str.str, tmp.data.u.str.str, max);
+ if (result == 0) {
+ if (smp->data.u.str.len != tmp.data.u.str.len) {
+ if (smp->data.u.str.len < tmp.data.u.str.len) {
+ result = -1;
+ }
+ else {
+ result = 1;
+ }
+ }
+ }
+
+ smp->data.u.sint = result;
+ smp->data.type = SMP_T_SINT;
+ return 1;
+}
+
+/* This function checks the "strcmp" converter's arguments and extracts the
+ * variable name and its scope.
+ */
+static int smp_check_strcmp(struct arg *args, struct sample_conv *conv,
+ const char *file, int line, char **err)
+{
+ /* Try to decode a variable. */
+ if (vars_check_arg(&args[0], NULL))
+ return 1;
+
+ memprintf(err, "failed to register variable name '%s'", args[0].data.str.str);
+ return 0;
+}
+
/************************************************************************/
/* All supported sample fetch functions must be declared here */
/************************************************************************/
@@ -2999,6 +3047,7 @@
{ "regsub", sample_conv_regsub, ARG3(2,REG,STR,STR), sample_conv_regsub_check, SMP_T_STR, SMP_T_STR },
{ "sha1", sample_conv_sha1, 0, NULL, SMP_T_BIN, SMP_T_BIN },
{ "concat", sample_conv_concat, ARG3(1,STR,STR,STR), smp_check_concat, SMP_T_STR, SMP_T_STR },
+ { "strcmp", sample_conv_strcmp, ARG1(1,STR), smp_check_strcmp, SMP_T_STR, SMP_T_SINT },
{ "and", sample_conv_binary_and, ARG1(1,STR), check_operator, SMP_T_SINT, SMP_T_SINT },
{ "or", sample_conv_binary_or, ARG1(1,STR), check_operator, SMP_T_SINT, SMP_T_SINT },