table_sess_cnt([table]) any integer
table_sess_rate([table]) any integer
table_trackers([table]) any integer
+tcp.dst binary integer
+tcp.flags binary integer
+tcp.options.mss binary integer
+tcp.options.sack binary integer
+tcp.options.tsopt binary integer
+tcp.options.tsval binary integer
+tcp.options.wscale binary integer
+tcp.options.wsopt binary integer
+tcp.options_list binary binary
+tcp.seq binary integer
+tcp.src binary integer
+tcp.win binary integer
ub64dec string string
ub64enc string string
ungrpc(field_number[,field_type]) binary binary / int
concurrent connections there are from a given address for example. See also
the sc_trackers sample fetch keyword.
+tcp.dst
+ This is used with an input sample representing a binary TCP header, as
+ returned by "ip.data". It returns an integer representing the destination
+ port present in the TCP header. See also "fc_saved_syn", "tcp-ss", and
+ "ip.data".
+
+tcp.flags
+ This is used with an input sample representing a binary TCP header, as
+ returned by "ip.data". It returns an integer representing the TCP flags
+ from this TCP header. All 8 flags from FIN to CWR are retrieved. Each flag
+ may be tested using the "and()" converter. Please refer to RFC9293 for the
+ value of each flag. See also "fc_saved_syn", "tcp-ss", and "ip.data".
+
+tcp.options.mss
+ This is used with an input sample representing a binary TCP header, as
+ returned by "ip.data". It looks for a TCP option of kind "MSS", and if found,
+ it returns an integer value corresponding to the advertised value in that
+ option, otherwise zero. The MSS is the Maximum Segment Size and indicates the
+ largest segment the peer may receive, in bytes. See also "fc_saved_syn",
+ "tcp-ss", and "ip.data".
+
+tcp.options.sack
+ This is used with an input sample representing a binary TCP header, as
+ returned by "ip.data". It looks for a TCP option of kind "Sack-Permitted",
+ and if found, returns 1, otherwise zero. See also "fc_saved_syn", "tcp-ss",
+ and "ip.data".
+
+tcp.options.tsopt
+ This is used with an input sample representing a binary TCP header, as
+ returned by "ip.data". It looks for a TCP option of kind "Timestamp", and if
+ found, returns 1, otherwise zero. See also "fc_saved_syn", "tcp-ss", and
+ "ip.data".
+
+tcp.options.tsval
+ This is used with an input sample representing a binary TCP header, as
+ returned by "ip.data". It looks for a TCP option of kind "Timestamp", and if
+ found, returns the timestamp value emitted by the peer, otherwise does not
+ return anything. Note that timestamps are 32-bit unsigned values with no
+ particular unit that only the peer decides on, and timestamps are expected to
+ be independent between different connections. See also "fc_saved_syn",
+ "tcp-ss", and "ip.data".
+
+tcp.options.wscale
+ This is used with an input sample representing a binary TCP header, as
+ returned by "ip.data". It looks for a TCP option of kind "Window Scale", and
+ if found, returns the window scaling value emitted by the peer, otherwise
+ zero. Note that values are not expected to be beyond 14 though no technical
+ limitation prevents them from being sent. In order to detect if the window
+ scale option was used, please use "tcp.options.wsopt". See also "tcp-ss",
+ "fc_saved_syn", "ip.data", and "tcp.options.wsopt".
+
+tcp.options.wsopt
+ This is used with an input sample representing a binary TCP header, as
+ returned by "ip.data". It looks for a TCP option of kind "Window Scale", and
+ if found, returns 1 otherwise 0. See also "fc_saved_syn", "tcp-ss", "ip.data"
+ "tcp.options.wscale".
+
+tcp.options_list
+ This is used with an input sample representing a binary TCP header, as
+ returned by "ip.data". It builds a binary sequence of all TCP option kinds in
+ the same order as they appear in the TCP header. It can produce from 0 to 60
+ bytes (in the worst case). The End-of-options is not emitted. See also
+ "fc_saved_syn", "tcp-ss", and "ip.data".
+
+tcp.seq
+ This is used with an input sample representing a binary TCP header, as
+ returned by "ip.data". It returns an integer representing the sequence number
+ used by the peer in the TCP header. Sequence numbers are 32-bit unsigned
+ values. See also "fc_saved_syn", "tcp-ss", and "ip.data".
+
+tcp.src
+ This is used with an input sample representing a binary TCP header, as
+ returned by "ip.data". It returns an integer representing the source port
+ present in the TCP header. See also "fc_saved_syn", "tcp-ss", and "ip.data".
+
+tcp.win
+ This is used with an input sample representing a binary TCP header, as
+ returned by "ip.data". It returns an integer representing the window size
+ advertised by the peer in the TCP header. The value is provided as-is, as a
+ 16-bit unsigned quantity, without applying the window scaling factor. See
+ also "fc_saved_syn", "tcp-ss", and "ip.data".
+
ub64dec
This converter is the base64url variant of b64dec converter. base64url
encoding is the "URL and Filename Safe Alphabet" variant of base64 encoding.
ipv4h=%[var(sess.syn),eth.data,bytes(0,12),hex] \
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_opt=%[var(sess.syn),bytes(54),hex]\n"
+ tcp_spt=%[var(sess.syn),eth.data,ip.data,tcp.src] \
+ tcp_dpt=%[var(sess.syn),eth.data,ip.data,tcp.dst] \
+ tcp_win=%[var(sess.syn),eth.data,ip.data,tcp.win] \
+ tcp_opt=%[var(sess.syn),eth.data,ip.data,bytes(20),hex]\n"
$ curl '0:4445'
mac_dst=000000000000 mac_src=000000000000 proto=0800 \
tcp_spt=43970 tcp_dpt=4445 tcp_win=65495 \
tcp_opt=0204FFD70402080A01DC0D410000000001030307
- See also the "set-var" action, the "be2dec", "bytes", "hex", "eth.XXX" and
- "ip.XXX" converters.
+ See also the "set-var" action, the "be2dec", "bytes", "hex", "eth.XXX",
+ "ip.XXX", and "tcp.XXX" converters.
fc_settings_streams_limit : integer
Returns the maximum number of streams allowed on the frontend connection. For
return 1;
}
+/******************************************/
+/* Converters used to process TCP headers */
+/******************************************/
+
+/* returns the TCP header length in bytes if complete, otherwise zero */
+static int tcp_fullhdr_length(const struct sample *smp)
+{
+ size_t ofs;
+
+ if (smp->data.u.str.data < 20)
+ return 0;
+
+ /* check that header is complete */
+ ofs = ((uchar)smp->data.u.str.area[12] >> 4) * 4;
+ if (ofs < 20 || smp->data.u.str.data < ofs)
+ return 0;
+ return ofs;
+}
+
+/* returns the offset in the input TCP header where option kind <opt> is first
+ * seen, otherwise 0 if not found. NOP and END cannot be searched.
+ */
+static size_t tcp_fullhdr_find_opt(const struct sample *smp, uint8_t opt)
+{
+ size_t len = tcp_fullhdr_length(smp);
+ size_t next = 20, curr;
+
+ while ((curr = next) < len) {
+ if (smp->data.u.str.area[next] == 0) // kind0=end of options
+ break;
+ /* kind1 = NOP and is a single byte, others have a length field */
+ next += (smp->data.u.str.area[next] == 1) ? 1 : smp->data.u.str.area[next + 1];
+ if (smp->data.u.str.area[curr] == opt && next <= len)
+ return curr;
+ }
+
+ return 0;
+}
+
+/* returns the destination port field found in an input TCP header */
+static int sample_conv_tcp_dst(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ if (smp->data.u.str.data < 20)
+ return 0;
+
+ smp->data.u.sint = read_n16(smp->data.u.str.area + 2);
+ smp->data.type = SMP_T_SINT;
+ smp->flags &= ~SMP_F_CONST;
+ return 1;
+}
+
+/* returns the flags field found in an input TCP header */
+static int sample_conv_tcp_flags(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ if (smp->data.u.str.data < 20)
+ return 0;
+
+ smp->data.u.sint = (uchar)smp->data.u.str.area[13];
+ smp->data.type = SMP_T_SINT;
+ smp->flags &= ~SMP_F_CONST;
+ return 1;
+}
+
+/* returns the MSS value of an input TCP header, or 0 if absent. Returns
+ * nothing if the header is incomplete.
+ */
+static int sample_conv_tcp_options_mss(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ size_t len = tcp_fullhdr_length(smp);
+ size_t ofs = tcp_fullhdr_find_opt(smp, 2 /* MSS */);
+
+ if (!len)
+ return 0;
+
+ smp->data.u.sint = ofs ? read_n16(smp->data.u.str.area + ofs + 2) : 0;
+ smp->data.type = SMP_T_SINT;
+ smp->flags &= ~SMP_F_CONST;
+ return 1;
+}
+
+/* returns 1 if the SackPerm option is present in an input TCP header,
+ * otherwise 0. Returns nothing if the header is incomplete.
+ */
+static int sample_conv_tcp_options_sack(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ size_t len = tcp_fullhdr_length(smp);
+ size_t ofs = tcp_fullhdr_find_opt(smp, 4 /* sackperm */);
+
+ if (!len)
+ return 0;
+
+ smp->data.u.sint = !!ofs;
+ smp->data.type = SMP_T_SINT;
+ smp->flags &= ~SMP_F_CONST;
+ return 1;
+}
+
+/* returns 1 if the TimeStamp option is present in an input TCP header,
+ * otherwise 0. Returns nothing if the header is incomplete.
+ */
+static int sample_conv_tcp_options_tsopt(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ size_t len = tcp_fullhdr_length(smp);
+ size_t ofs = tcp_fullhdr_find_opt(smp, 8 /* TS */);
+
+ if (!len)
+ return 0;
+
+ smp->data.u.sint = !!ofs;
+ smp->data.type = SMP_T_SINT;
+ smp->flags &= ~SMP_F_CONST;
+ return 1;
+}
+
+/* returns the TSval value in the TimeStamp option found in an input TCP
+ * header, if found, otherwise 0. Returns nothing if the header is incomplete
+ * (see also tsopt).
+ */
+static int sample_conv_tcp_options_tsval(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ size_t len = tcp_fullhdr_length(smp);
+ size_t ofs = tcp_fullhdr_find_opt(smp, 8 /* TS */);
+
+ if (!len)
+ return 0;
+
+ smp->data.u.sint = ofs ? read_n32(smp->data.u.str.area + ofs + 2) : 0;
+ smp->data.type = SMP_T_SINT;
+ smp->flags &= ~SMP_F_CONST;
+ return 1;
+}
+
+/* returns the window scaling shift count from an input TCP header, otherwise 0
+ * if option not found (see also wsopt). Returns nothing if the header is
+ * incomplete.
+ */
+static int sample_conv_tcp_options_wscale(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ size_t len = tcp_fullhdr_length(smp);
+ size_t ofs = tcp_fullhdr_find_opt(smp, 3 /* wscale */);
+
+ if (!len)
+ return 0;
+
+ smp->data.u.sint = ofs ? (uchar)smp->data.u.str.area[ofs + 2] : 0;
+ smp->data.type = SMP_T_SINT;
+ smp->flags &= ~SMP_F_CONST;
+ return 1;
+}
+
+/* returns 1 if the WScale option is present in an input TCP header,
+ * otherwise 0. Returns nothing if the header is incomplete.
+ */
+static int sample_conv_tcp_options_wsopt(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ size_t len = tcp_fullhdr_length(smp);
+ size_t ofs = tcp_fullhdr_find_opt(smp, 3 /* wscale */);
+
+ if (!len)
+ return 0;
+
+ smp->data.u.sint = !!ofs;
+ smp->data.type = SMP_T_SINT;
+ smp->flags &= ~SMP_F_CONST;
+ return 1;
+}
+
+/* returns only the TCP options kinds of an input TCP header, as a binary
+ * block of one byte per option.
+ */
+static int sample_conv_tcp_options_list(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ struct buffer *trash = get_trash_chunk();
+ size_t len = tcp_fullhdr_length(smp);
+ size_t ofs = 20;
+
+ if (!len)
+ return 0;
+
+ while (ofs < len) {
+ if (smp->data.u.str.area[ofs] == 0) // kind0=end of options
+ break;
+ trash->area[trash->data++] = smp->data.u.str.area[ofs];
+ /* kind1 = NOP and is a single byte, others have a length field */
+ if (smp->data.u.str.area[ofs] == 1)
+ ofs++;
+ else if (ofs + 1 <= len)
+ ofs += smp->data.u.str.area[ofs + 1];
+ else
+ break;
+ }
+
+ /* returns a binary block of 1 byte per option */
+ smp->data.u.str = *trash;
+ smp->flags &= ~SMP_F_CONST;
+ return 1;
+}
+
+/* returns the sequence number field found in an input TCP header */
+static int sample_conv_tcp_seq(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ if (smp->data.u.str.data < 20)
+ return 0;
+
+ smp->data.u.sint = read_n32(smp->data.u.str.area + 4);
+ smp->data.type = SMP_T_SINT;
+ smp->flags &= ~SMP_F_CONST;
+ return 1;
+}
+
+/* returns the source port field found in an input TCP header */
+static int sample_conv_tcp_src(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ if (smp->data.u.str.data < 20)
+ return 0;
+
+ smp->data.u.sint = read_n16(smp->data.u.str.area);
+ smp->data.type = SMP_T_SINT;
+ smp->flags &= ~SMP_F_CONST;
+ return 1;
+}
+
+/* returns the window field found in an input TCP header */
+static int sample_conv_tcp_win(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ if (smp->data.u.str.data < 20)
+ return 0;
+
+ smp->data.u.sint = read_n16(smp->data.u.str.area + 14);
+ 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, {
{ "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 },
+ { "tcp.dst", sample_conv_tcp_dst, 0, NULL, SMP_T_BIN, SMP_T_SINT },
+ { "tcp.flags", sample_conv_tcp_flags, 0, NULL, SMP_T_BIN, SMP_T_SINT },
+ { "tcp.options.mss", sample_conv_tcp_options_mss, 0, NULL, SMP_T_BIN, SMP_T_SINT },
+ { "tcp.options.sack", sample_conv_tcp_options_sack, 0, NULL, SMP_T_BIN, SMP_T_SINT },
+ { "tcp.options.tsopt", sample_conv_tcp_options_tsopt, 0, NULL, SMP_T_BIN, SMP_T_SINT },
+ { "tcp.options.tsval", sample_conv_tcp_options_tsval, 0, NULL, SMP_T_BIN, SMP_T_SINT },
+ { "tcp.options.wscale", sample_conv_tcp_options_wscale, 0, NULL, SMP_T_BIN, SMP_T_SINT },
+ { "tcp.options.wsopt", sample_conv_tcp_options_wsopt, 0, NULL, SMP_T_BIN, SMP_T_SINT },
+ { "tcp.options_list", sample_conv_tcp_options_list, 0, NULL, SMP_T_BIN, SMP_T_BIN },
+ { "tcp.seq", sample_conv_tcp_seq, 0, NULL, SMP_T_BIN, SMP_T_SINT },
+ { "tcp.src", sample_conv_tcp_src, 0, NULL, SMP_T_BIN, SMP_T_SINT },
+ { "tcp.win", sample_conv_tcp_win, 0, NULL, SMP_T_BIN, SMP_T_SINT },
+
{ NULL, NULL, 0, 0, 0 },
}};