rfc7239_is_valid string boolean
rfc7239_n2nn string address / str
rfc7239_n2np string integer / str
+rfc7239_nn address/str string
+rfc7239_np integer/str string
rtrim(chars) string string
sdbm([avalanche]) binary integer
secure_memcmp(var) string boolean
#input: "_name:_port"
# output: "_port" (string)
+rfc7239_nn
+ Converts provided address / string input into RFC7239-compliant node name.
+ It may be used to manually build 'for' or 'by' 7239 header fields.
+
+ When provided input is string, it will be automatically prefixed with '_'
+ char to represent obfuscated identifier. String must comply with RFC7239
+ charset. If string is empty, it will be converter to "unknown" identifier.
+
+ Example:
+ #input: ipv6(ab:cd:ff:ff:ff:ff:ff:ff)
+ # output: "[ab:cd:ff:ff:ff:ff:ff:ff]"
+ #input: str(test)
+ # output: "_test"
+ #input: str()
+ # output: "unknown"
+
+ See also: "rfc7239_np"
+
+rfc7239_np
+ Converts provided unsigned integer / string input into RFC7239-compliant node
+ port. It may be used to manually build 'for' or 'by' 7239 header fields.
+
+ When provided input is string, it will be automatically prefixed with '_'
+ char to represent obfuscated identifier. String must comply with RFC7239
+ charset and cannot be empty.
+
+ Example:
+ #input: int(12)
+ # output: "12"
+ #input: str(test)
+ # output: "_test"
+
+ # build 'for' forwarded header field
+ http-request set-var-fmt(txn.test) "for=\"%[ipv6(::1),rfc7239_nn]:%[int(8080),rfc7239_np]\";"
+ # output: "for=\"[::1]:8080\";"
+
+ # build RFC-compliant 7239 header:
+ http-request set-var-fmt(txn.forwarded) "for=\"%[ipv6(::1),rfc7239_nn]:%[str(8888),rfc7239_np]\";host=\"haproxy.org\";proto=http"
+ # check RFC-compliancy:
+ http-request set-var(txn.test) "var(txn.forwarded),debug(test,stderr),rfc7239_is_valid,debug(test,stderr)"
+ # stderr output:
+ # [debug] test: type=str <for="[::1]:_8888";host="haproxy.org";proto=http>
+ # [debug] test: type=bool <1>
+
+ See also: "rfc7239_nn"
+
rtrim(<chars>)
Skips any characters from <chars> from the end of the string representation
of the input sample.
return 1;
}
+/*
+ * input: ipv4 address, ipv6 address or str (empty string will result in
+ * "unknown" indentifier, else string will be translated to _obfs
+ * indentifier, prefixed by '_'. Must comply with RFC7239 charset)
+ *
+ * output: rfc7239-compliant forwarded header nodename
+ */
+static int sample_conv_7239_nn(const struct arg *args, struct sample *smp, void *private)
+{
+ struct buffer *trash = get_trash_chunk();
+
+ switch (smp->data.type) {
+ case SMP_T_IPV4:
+ {
+ unsigned char *pn = (unsigned char *)&(smp->data.u.ipv4);
+
+ chunk_printf(trash, "%d.%d.%d.%d", pn[0], pn[1], pn[2], pn[3]);
+ break;
+ }
+ case SMP_T_IPV6:
+ _7239_print_ip6(trash, &smp->data.u.ipv6, 1);
+ break;
+ case SMP_T_STR:
+ case_str:
+ {
+ struct ist validate_n = ist2(smp->data.u.str.area, smp->data.u.str.data);
+
+ if (!istlen(validate_n)) {
+ // empty -> unknown
+ chunk_printf(trash, "unknown");
+ break;
+ }
+
+ if (!(http_7239_extract_obfs(&validate_n, NULL) && !istlen(validate_n)))
+ return 0; /* invalid input */
+ // output with '_' prefix
+ chunk_printf(trash, "_%.*s", (int)smp->data.u.str.data, smp->data.u.str.area);
+ break;
+ }
+ default:
+ {
+ if (sample_casts[smp->data.type][SMP_T_STR] &&
+ sample_casts[smp->data.type][SMP_T_STR](smp))
+ goto case_str;
+ return 0; /* unexpected */
+ }
+
+ }
+
+ smp->data.u.str = *trash;
+ smp->data.type = SMP_T_STR;
+ smp->flags &= ~SMP_F_CONST;
+
+ return 1;
+}
+
+/*
+ * input: unsigned integer or str (string will be translated to _obfs
+ * indentifier, prefixed by '_'. Must comply with RFC7239 charset)
+ *
+ * output: rfc7239-compliant forwarded header nodeport
+ */
+static int sample_conv_7239_np(const struct arg *args, struct sample *smp, void *private)
+{
+ struct buffer *trash = get_trash_chunk();
+
+ switch (smp->data.type) {
+ case SMP_T_SINT:
+ {
+ chunk_printf(trash, "%u", (unsigned int)smp->data.u.sint);
+ break;
+ }
+ case SMP_T_STR:
+ case_str:
+ {
+ struct ist validate_n = ist2(smp->data.u.str.area, smp->data.u.str.data);
+
+ if (!istlen(validate_n))
+ return 0;
+
+ if (!(http_7239_extract_obfs(&validate_n, NULL) && !istlen(validate_n)))
+ return 0; /* invalid input */
+ // output with '_' prefix
+ chunk_printf(trash, "_%.*s", (int)smp->data.u.str.data, smp->data.u.str.area);
+ break;
+ }
+ default:
+ {
+ if (sample_casts[smp->data.type][SMP_T_STR] &&
+ sample_casts[smp->data.type][SMP_T_STR](smp))
+ goto case_str;
+ return 0; /* unexpected */
+ }
+
+ }
+
+ smp->data.u.str = *trash;
+ smp->data.type = SMP_T_STR;
+ smp->flags &= ~SMP_F_CONST;
+
+ return 1;
+
+}
+
/* Note: must not be declared <const> as its list will be overwritten */
static struct sample_conv_kw_list sample_conv_kws = {ILH, {
{ "rfc7239_is_valid", sample_conv_7239_valid, 0, NULL, SMP_T_STR, SMP_T_BOOL},
{ "rfc7239_field", sample_conv_7239_field, ARG1(1,STR), NULL, SMP_T_STR, SMP_T_STR},
{ "rfc7239_n2nn", sample_conv_7239_n2nn, 0, NULL, SMP_T_STR, SMP_T_ANY},
{ "rfc7239_n2np", sample_conv_7239_n2np, 0, NULL, SMP_T_STR, SMP_T_ANY},
+ { "rfc7239_nn", sample_conv_7239_nn, 0, NULL, SMP_T_ANY, SMP_T_STR},
+ { "rfc7239_np", sample_conv_7239_np, 0, NULL, SMP_T_ANY, SMP_T_STR},
{ NULL, NULL, 0, 0, 0 },
}};