http_date([offset[,unit]]) integer string
iif(true,false) boolean string
in_table([table]) any boolean
+ip.data binary binary
+ip.df binary integer
+ip.dst binary address
+ip.hdr binary binary
+ip.proto binary integer
+ip.src binary address
+ip.tos binary integer
+ip.ttl binary integer
+ip.ver binary integer
ipmask(mask4[,mask6]) address address
json([input-code]) string string
json_query(json_path[,output_type]) string _outtype_
elements (e.g. whether or not a source IP address or an Authorization header
was already seen).
+ip.data
+ This is used with an input sample representing a binary Ethernet frame, as
+ returned by "fc_saved_syn" combined with the "tcp-ss" bind option set to "1",
+ or with the output of "eth.data". It skips the IP header and any optional
+ options or extensions, and returns a block of binary data starting at the
+ transport protocol (usually TCP or UDP). See also "fc_saved_syn", "tcp-ss",
+ and "eth.data".
+
+ip.df
+ This is used with an input sample representing a binary Ethernet frame, as
+ returned by "fc_saved_syn" combined with the "tcp-ss" bind option set to "1",
+ or with the output of "eth.data". It returns integer value 1 if the DF (don't
+ fragment) flag is set in the IP header, 0 otherwise. IPv6 does not have a DF
+ flag, and doesn't fragment by default so it always returns 1. See also
+ "fc_saved_syn", "tcp-ss", and "eth.data".
+
+ip.dst
+ This is used with an input sample representing a binary Ethernet frame, as
+ returned by "fc_saved_syn" combined with the "tcp-ss" bind option set to "1",
+ or with the output of "eth.data". It returns the IPv4 or IPv6 destination
+ address from the IPv4/v6 header. See also "fc_saved_syn", "tcp-ss", and
+ "eth.data".
+
+ip.hdr
+ This is used with an input sample representing a binary Ethernet frame, as
+ returned by "fc_saved_syn" combined with the "tcp-ss" bind option set to "1",
+ or with the output of "eth.data". It returns a block of binary data starting
+ with the IP header and stopping after the last option or extension, and
+ before the transport protocol header. See also "fc_saved_syn", "tcp-ss", and
+ "eth.data".
+
+ip.proto
+ This is used with an input sample representing a binary Ethernet frame, as
+ returned by "fc_saved_syn" combined with the "tcp-ss" bind option set to "1",
+ or with the output of "eth.data". It returns the transport protocol number,
+ usually 6 for TCP or 17 for UDP. See also "fc_saved_syn", "tcp-ss", and
+ "eth.data".
+
+ip.src
+ This is used with an input sample representing a binary Ethernet frame, as
+ returned by "fc_saved_syn" combined with the "tcp-ss" bind option set to "1",
+ or with the output of "eth.data". It returns the IPv4 or IPv6 source address
+ from the IPv4/v6 header. See also "fc_saved_syn", "tcp-ss", and "eth.data".
+
+ip.tos
+ This is used with an input sample representing a binary Ethernet frame, as
+ returned by "fc_saved_syn" combined with the "tcp-ss" bind option set to "1",
+ or with the output of "eth.data". It returns an integer corresponding to the
+ value of the type-of-service (TOS) field in the IPv4 header or traffic class
+ (TC) field in the IPv6 header. Note that in the modern internet, this field
+ most often contains a DSCP (Differentiated Services Codepoint) value in the
+ 6 upper bits and the two lower are either not used, or used by IP ECN. Please
+ refer to RFC2474 and RFC8436 for DSCP values, and RFC3168 for IP ECN fields.
+ See also "fc_saved_syn", "tcp-ss", and "eth.data".
+
+ip.ttl
+ This is used with an input sample representing a binary Ethernet frame, as
+ returned by "fc_saved_syn" combined with the "tcp-ss" bind option set to "1",
+ or with the output of "eth.data". This returns an integer corresponding to
+ the TTL (Time To Live) or HL (Hop Limit) field in the IPv4/IPv6 header. This
+ value is usually preset to a fixed value and decremented by each router that
+ the packet crosses. It can help infer how far a client connects from when the
+ initial value is known. Note that most modern operating systems start with an
+ initial value of 64. See also "fc_saved_syn", "tcp-ss", and "eth.data".
+
+ip.ver
+ This is used with an input sample representing a binary Ethernet frame, as
+ returned by "fc_saved_syn" combined with the "tcp-ss" bind option set to "1",
+ or with the output of "eth.data". This returns the IP version from the IP
+ header, normally either 4 or 6. Note that this doesn't check whether the
+ protocol number in the upper layer Ethernet frame matches, but since this is
+ expected to be used with valid packets, it is expected that the operating
+ system has already verified this. See also "fc_saved_syn", "tcp-ss", and
+ "eth.data".
+
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
mac_src=%[var(sess.syn),eth.src,hex] \
proto=%[var(sess.syn),eth.proto,bytes(6),be2hex(,2)] \
ipv4h=%[var(sess.syn),eth.data,bytes(0,12),hex] \
- ipv4_src=%[var(sess.syn),bytes(26,4),be2dec(.,1)] \
- ipv4_dst=%[var(sess.syn),bytes(30,4),be2dec(.,1)] \
+ ipv4_src=%[var(sess.syn),eth.data,ip.src] \
+ ipv4_dst=%[var(sess.syn),eth.data,ip.dst] \
tcp_spt=%[var(sess.syn),bytes(34,2),be2dec(,2)] \
tcp_dpt=%[var(sess.syn),bytes(36,2),be2dec(,2)] \
tcp_win=%[var(sess.syn),bytes(48,2),be2dec(,2)] \
tcp_spt=43970 tcp_dpt=4445 tcp_win=65495 \
tcp_opt=0204FFD70402080A01DC0D410000000001030307
- See also the "set-var" action, the "be2dec", "bytes", "hex", and
- "eth.XXX" converters.
+ See also the "set-var" action, the "be2dec", "bytes", "hex", "eth.XXX" and
+ "ip.XXX" converters.
fc_settings_streams_limit : integer
Returns the maximum number of streams allowed on the frontend connection. For
return 0;
}
+/*******************************************************/
+/* Converters used to process IPv4/IPv6 packet headers */
+/*******************************************************/
+
+/* returns the total header length for the input IP packet header (v4 or v6),
+ * including all extensions if any. It corresponds to the length to skip to
+ * find the TCP or UDP header. If data are missing or unparsable, it returns
+ * 0.
+ */
+static size_t ip_header_length(const struct sample *smp)
+{
+ size_t len;
+ uchar next;
+ uchar ver;
+
+ if (smp->data.u.str.data < 1)
+ return 0;
+
+ ver = (uchar)smp->data.u.str.area[0] >> 4;
+ if (ver == 4) {
+ len = (smp->data.u.str.area[0] & 0xF) * 4;
+ if (smp->data.u.str.data < len)
+ return 0;
+ }
+ else if (ver == 6) {
+ if (smp->data.u.str.data < 40)
+ return 0;
+
+ len = 40;
+ next = smp->data.u.str.area[6];
+
+ while (next != 6 && next != 17) {
+ if (smp->data.u.str.data < len + 2)
+ return 0;
+ next = smp->data.u.str.area[len];
+ len += (uchar)smp->data.u.str.area[len + 1] * 8 + 8;
+ }
+
+ if (smp->data.u.str.data < len)
+ return 0;
+ }
+ else {
+ return 0;
+ }
+
+ return len;
+}
+
+/* returns the payload following the input IP packet header (v4 or v6) skipping
+ * all extensions if any. For IPv6, it returns the TCP or UDP next header.
+ */
+static int sample_conv_ip_data(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ size_t len;
+
+ len = ip_header_length(smp);
+ if (!len)
+ return 0;
+
+ /* advance buffer by <len> */
+ smp->data.u.str.area += len;
+ smp->data.u.str.data -= len;
+ return 1;
+}
+
+/* returns the DF (don't fragment) flag from an IPv4 header, as 0 or 1. The
+ * value is always one for IPv6 since DF is implicit.
+ */
+static int sample_conv_ip_df(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ uchar ver;
+ uchar df;
+
+ if (smp->data.u.str.data < 1)
+ return 0;
+
+ ver = (uchar)smp->data.u.str.area[0] >> 4;
+ if (ver == 4) {
+ if (smp->data.u.str.data < 6)
+ return 0;
+ df = !!(smp->data.u.str.area[6] & 0x40);
+ }
+ else if (ver == 6) {
+ df = 1;
+ }
+ else {
+ return 0;
+ }
+
+ smp->data.u.sint = df;
+ smp->data.type = SMP_T_SINT;
+ smp->flags &= ~SMP_F_CONST;
+ return 1;
+}
+
+/* returns the IP DST address found in an input IP packet header (v4 or v6). */
+static int sample_conv_ip_dst(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ uchar ver;
+
+ if (smp->data.u.str.data < 1)
+ return 0;
+
+ ver = (uchar)smp->data.u.str.area[0] >> 4;
+ if (ver == 4) {
+ if (smp->data.u.str.data < 20)
+ return 0;
+
+ smp->data.u.ipv4.s_addr = read_u32(smp->data.u.str.area + 16);
+ smp->data.type = SMP_T_IPV4;
+ }
+ else if (ver == 6) {
+ if (smp->data.u.str.data < 40)
+ return 0;
+
+ memcpy(&smp->data.u.ipv6, smp->data.u.str.area + 24, 16);
+ smp->data.type = SMP_T_IPV6;
+ }
+ else {
+ return 0;
+ }
+
+ smp->flags &= ~SMP_F_CONST;
+ return 1;
+}
+
+/* returns the IP header only for an input IP packet header (v4 or v6), including
+ * all extensions if any. For IPv6, it includes every extension before TCP/UDP.
+ */
+static int sample_conv_ip_hdr(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ size_t len;
+
+ len = ip_header_length(smp);
+ if (!len)
+ return 0;
+
+ /* truncate buffer to <len> */
+ smp->data.u.str.data = len;
+ return 1;
+}
+
+/* returns the upper layer protocol number (TCP/UDP) for an input IP packet
+ * header (v4 or v6).
+ */
+static int sample_conv_ip_proto(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ size_t len;
+ uchar next;
+ uchar ver;
+
+ if (smp->data.u.str.data < 1)
+ return 0;
+
+ ver = (uchar)smp->data.u.str.area[0] >> 4;
+ if (ver == 4) {
+ if (smp->data.u.str.data < 10)
+ return 0;
+ next = smp->data.u.str.area[9];
+ }
+ else if (ver == 6) {
+ /* skip all extensions */
+ if (smp->data.u.str.data < 40)
+ return 0;
+
+ len = 40;
+ next = smp->data.u.str.area[6];
+
+ while (next != 6 && next != 17) {
+ if (smp->data.u.str.data < len + 2)
+ return 0;
+ next = smp->data.u.str.area[len];
+ len += (uchar)smp->data.u.str.area[len + 1] * 8 + 8;
+ }
+
+ if (smp->data.u.str.data < len)
+ return 0;
+ }
+ else {
+ return 0;
+ }
+
+ /* protocol number is in <next> */
+ smp->data.u.sint = next;
+ smp->data.type = SMP_T_SINT;
+ smp->flags &= ~SMP_F_CONST;
+ return 1;
+}
+
+/* returns the IP SRC address found in an input IP packet header (v4 or v6). */
+static int sample_conv_ip_src(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ uchar ver;
+
+ if (smp->data.u.str.data < 1)
+ return 0;
+
+ ver = (uchar)smp->data.u.str.area[0] >> 4;
+ if (ver == 4) {
+ if (smp->data.u.str.data < 20)
+ return 0;
+
+ smp->data.u.ipv4.s_addr = read_u32(smp->data.u.str.area + 12);
+ smp->data.type = SMP_T_IPV4;
+ }
+ else if (ver == 6) {
+ if (smp->data.u.str.data < 40)
+ return 0;
+
+ memcpy(&smp->data.u.ipv6, smp->data.u.str.area + 8, 16);
+ smp->data.type = SMP_T_IPV6;
+ }
+ else {
+ return 0;
+ }
+
+ smp->flags &= ~SMP_F_CONST;
+ return 1;
+}
+
+/* returns the IP TOS/TC field found in an input IP packet header (v4 or v6). */
+static int sample_conv_ip_tos(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ uchar ver;
+
+ if (smp->data.u.str.data < 1)
+ return 0;
+
+ ver = (uchar)smp->data.u.str.area[0] >> 4;
+ if (ver == 4) {
+ /* TOS field is at offset 1 */
+ if (smp->data.u.str.data < 2)
+ return 0;
+
+ smp->data.u.sint = (uchar)smp->data.u.str.area[1];
+ }
+ else if (ver == 6) {
+ /* TOS field is between offset 0 and 1 */
+ if (smp->data.u.str.data < 2)
+ return 0;
+
+ smp->data.u.sint = (uchar)(read_n16(smp->data.u.str.area) >> 4);
+ }
+ else {
+ return 0;
+ }
+
+ /* OK we have the value in data.u.sint */
+ smp->data.type = SMP_T_SINT;
+ smp->flags &= ~SMP_F_CONST;
+ return 1;
+}
+
+/* returns the IP TTL/HL field found in an input IP packet header (v4 or v6). */
+static int sample_conv_ip_ttl(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ uchar ver;
+
+ if (smp->data.u.str.data < 1)
+ return 0;
+
+ ver = (uchar)smp->data.u.str.area[0] >> 4;
+ if (ver == 4) {
+ if (smp->data.u.str.data < 20)
+ return 0;
+
+ smp->data.u.sint = (uchar)smp->data.u.str.area[8];
+ }
+ else if (ver == 6) {
+ if (smp->data.u.str.data < 40)
+ return 0;
+
+ smp->data.u.sint = (uchar)smp->data.u.str.area[7];
+ }
+ else {
+ return 0;
+ }
+
+ /* OK we have the value in data.u.sint */
+ smp->data.type = SMP_T_SINT;
+ smp->flags &= ~SMP_F_CONST;
+ return 1;
+}
+
+/* returns the IP version found in an input IP packet header (v4 or v6). */
+static int sample_conv_ip_ver(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ if (smp->data.u.str.data < 1)
+ return 0;
+
+ smp->data.u.sint = (uchar)smp->data.u.str.area[0] >> 4;
+ smp->data.type = SMP_T_SINT;
+ 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, {
{ "eth.data", sample_conv_eth_data, 0, NULL, SMP_T_BIN, SMP_T_BIN },
{ "eth.src", sample_conv_eth_src, 0, NULL, SMP_T_BIN, SMP_T_BIN },
{ "eth.vlan", sample_conv_eth_vlan, 0, NULL, SMP_T_BIN, SMP_T_SINT },
+ { "ip.data", sample_conv_ip_data, 0, NULL, SMP_T_BIN, SMP_T_BIN },
+ { "ip.df", sample_conv_ip_df, 0, NULL, SMP_T_BIN, SMP_T_SINT },
+ { "ip.dst", sample_conv_ip_dst, 0, NULL, SMP_T_BIN, SMP_T_ADDR },
+ { "ip.hdr", sample_conv_ip_hdr, 0, NULL, SMP_T_BIN, SMP_T_BIN },
+ { "ip.proto", sample_conv_ip_proto, 0, NULL, SMP_T_BIN, SMP_T_SINT },
+ { "ip.src", sample_conv_ip_src, 0, NULL, SMP_T_BIN, SMP_T_ADDR },
+ { "ip.tos", sample_conv_ip_tos, 0, NULL, SMP_T_BIN, SMP_T_SINT },
+ { "ip.ttl", sample_conv_ip_ttl, 0, NULL, SMP_T_BIN, SMP_T_SINT },
+ { "ip.ver", sample_conv_ip_ver, 0, NULL, SMP_T_BIN, SMP_T_SINT },
+
{ NULL, NULL, 0, 0, 0 },
}};