the presence of a certain key in a table tracking some elements (e.g. whether
or not a source IP address or an Authorization header was already seen).
-ipmask(<mask>)
- Apply a mask to an IPv4 address, and use the result for lookups and storage.
+ipmask(<mask4>, [<mask6>])
+ Apply a mask to an IP address, and use the result for lookups and storage.
This can be used to make all hosts within a certain mask to share the same
- table entries and as such use the same server. The mask can be passed in
- dotted form (e.g. 255.255.255.0) or in CIDR form (e.g. 24).
+ table entries and as such use the same server. The mask4 can be passed in
+ dotted form (e.g. 255.255.255.0) or in CIDR form (e.g. 24). The mask6 can
+ be passed in quadruplet form (e.g. ffff:ffff::) or in CIDR form (e.g. 64).
+ If no mask6 is given IPv6 addresses will fail to convert for backwards
+ compatibility reasons.
json([<input-code>])
Escapes the input string and produces an ASCII output string ready to use as a
return 1;
}
-/* takes the netmask in arg_p */
-static int sample_conv_ipmask(const struct arg *arg_p, struct sample *smp, void *private)
+/* takes the IPv4 mask in args[0] and an optional IPv6 mask in args[1] */
+static int sample_conv_ipmask(const struct arg *args, struct sample *smp, void *private)
{
- smp->data.u.ipv4.s_addr &= arg_p->data.ipv4.s_addr;
- smp->data.type = SMP_T_IPV4;
+ /* Attempt to convert to IPv4 to apply the correct mask. */
+ c_ipv62ip(smp);
+
+ if (smp->data.type == SMP_T_IPV4) {
+ smp->data.u.ipv4.s_addr &= args[0].data.ipv4.s_addr;
+ smp->data.type = SMP_T_IPV4;
+ }
+ else if (smp->data.type == SMP_T_IPV6) {
+ /* IPv6 cannot be converted without an IPv6 mask. */
+ if (args[1].type != ARGT_IPV6)
+ return 0;
+
+ *(uint32_t*)&smp->data.u.ipv6.s6_addr[0] &= *(uint32_t*)&args[1].data.ipv6.s6_addr[0];
+ *(uint32_t*)&smp->data.u.ipv6.s6_addr[4] &= *(uint32_t*)&args[1].data.ipv6.s6_addr[4];
+ *(uint32_t*)&smp->data.u.ipv6.s6_addr[8] &= *(uint32_t*)&args[1].data.ipv6.s6_addr[8];
+ *(uint32_t*)&smp->data.u.ipv6.s6_addr[12] &= *(uint32_t*)&args[1].data.ipv6.s6_addr[12];
+ smp->data.type = SMP_T_IPV6;
+ }
+
return 1;
}
{ "length", sample_conv_length, 0, NULL, SMP_T_STR, SMP_T_SINT },
{ "hex", sample_conv_bin2hex, 0, NULL, SMP_T_BIN, SMP_T_STR },
{ "hex2i", sample_conv_hex2int, 0, NULL, SMP_T_STR, SMP_T_SINT },
- { "ipmask", sample_conv_ipmask, ARG1(1,MSK4), NULL, SMP_T_IPV4, SMP_T_IPV4 },
+ { "ipmask", sample_conv_ipmask, ARG2(1,MSK4,MSK6), NULL, SMP_T_ADDR, SMP_T_IPV4 },
{ "ltime", sample_conv_ltime, ARG2(1,STR,SINT), NULL, SMP_T_SINT, SMP_T_STR },
{ "utime", sample_conv_utime, ARG2(1,STR,SINT), NULL, SMP_T_SINT, SMP_T_STR },
{ "crc32", sample_conv_crc32, ARG1(0,SINT), NULL, SMP_T_BIN, SMP_T_SINT },