]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: sample: Add strcmp sample converter
authorTim Duesterhus <tim@bastelstu.be>
Fri, 27 Apr 2018 19:18:45 +0000 (21:18 +0200)
committerWilly Tarreau <w@1wt.eu>
Sat, 28 Apr 2018 05:03:39 +0000 (07:03 +0200)
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

doc/configuration.txt
src/sample.c

index dcc87fdc09ea5a86c99ae2e1155b7d06cd82e3b3..b865b33b4f7d14cc2fd7c152f7e5c9a36cb07d6d 100644 (file)
@@ -13242,6 +13242,21 @@ sha1
   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
index b1c01484fbc680ec68beacb858973c2ad5a79fd1..3f72266b90223c25ec204169ae834787ea7bfc3a 100644 (file)
@@ -2684,6 +2684,54 @@ static int smp_check_concat(struct arg *args, struct sample_conv *conv,
        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 @@ static struct sample_conv_kw_list sample_conv_kws = {ILH, {
        { "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  },