blob: 572a6a84ea8ad2688ddc7618c7347d69c7c42a5e [file] [log] [blame]
Willy Tarreau8987e7a2020-08-28 11:37:21 +02001/*
2 * AF_INET/AF_INET6 SOCK_STREAM protocol layer (tcp)
3 *
4 * Copyright 2000-2013 Willy Tarreau <w@1wt.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13/* this is to have tcp_info defined on systems using musl
14 * library, such as Alpine Linux.
15 */
16#define _GNU_SOURCE
17
18#include <ctype.h>
19#include <errno.h>
20#include <fcntl.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <time.h>
25
26#include <sys/param.h>
27#include <sys/socket.h>
28#include <sys/types.h>
29
30#include <netinet/tcp.h>
31#include <netinet/in.h>
32
33#include <haproxy/api.h>
34#include <haproxy/arg.h>
35#include <haproxy/connection.h>
Christopher Faulet8da67aa2022-03-29 17:53:09 +020036#include <haproxy/cs_utils.h>
Willy Tarreau6cd007d2021-10-06 19:01:21 +020037#include <haproxy/errors.h>
Willy Tarreau8987e7a2020-08-28 11:37:21 +020038#include <haproxy/global.h>
39#include <haproxy/listener-t.h>
40#include <haproxy/namespace.h>
41#include <haproxy/proxy-t.h>
42#include <haproxy/sample.h>
Christopher Fauletc03be1a2021-10-25 08:01:20 +020043#include <haproxy/session.h>
Willy Tarreau8987e7a2020-08-28 11:37:21 +020044#include <haproxy/tools.h>
45
Christopher Faulet7d081f02021-04-15 09:38:37 +020046/* Fetch the connection's source IPv4/IPv6 address. Depending on the keyword, it
47 * may be the frontend or the backend connection.
Willy Tarreau8987e7a2020-08-28 11:37:21 +020048 */
49static int
50smp_fetch_src(const struct arg *args, struct sample *smp, const char *kw, void *private)
51{
Christopher Fauletc03be1a2021-10-25 08:01:20 +020052 const struct sockaddr_storage *src = NULL;
Christopher Faulet003df1c2021-04-15 09:39:38 +020053
Christopher Faulet888cd702021-10-25 16:58:50 +020054 if (kw[0] == 'b') { /* bc_src */
Christopher Fauletc03be1a2021-10-25 08:01:20 +020055 struct connection *conn = ((obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
56 ? cs_conn(__objt_check(smp->sess->origin)->cs)
Christopher Faulet95a61e82021-12-22 14:22:03 +010057 : (smp->strm ? cs_conn(smp->strm->csb): NULL));
Christopher Fauletc03be1a2021-10-25 08:01:20 +020058 if (conn && conn_get_src(conn))
59 src = conn_src(conn);
60 }
Christopher Faulet888cd702021-10-25 16:58:50 +020061 else if (kw[0] == 'f') { /* fc_src */
62 struct connection *conn = objt_conn(smp->sess->origin);
63
64 if (conn && conn_get_src(conn))
65 src = conn_src(conn);
66 }
67 else /* src */
Christopher Faulet8da67aa2022-03-29 17:53:09 +020068 src = (smp->strm ? cs_src(smp->strm->csf) : sess_src(smp->sess));
Willy Tarreau8987e7a2020-08-28 11:37:21 +020069
Christopher Fauletc03be1a2021-10-25 08:01:20 +020070 if (!src)
Willy Tarreau8987e7a2020-08-28 11:37:21 +020071 return 0;
72
Christopher Fauletc03be1a2021-10-25 08:01:20 +020073 switch (src->ss_family) {
Willy Tarreau8987e7a2020-08-28 11:37:21 +020074 case AF_INET:
Christopher Fauletc03be1a2021-10-25 08:01:20 +020075 smp->data.u.ipv4 = ((struct sockaddr_in *)src)->sin_addr;
Willy Tarreau8987e7a2020-08-28 11:37:21 +020076 smp->data.type = SMP_T_IPV4;
77 break;
78 case AF_INET6:
Christopher Fauletc03be1a2021-10-25 08:01:20 +020079 smp->data.u.ipv6 = ((struct sockaddr_in6 *)src)->sin6_addr;
Willy Tarreau8987e7a2020-08-28 11:37:21 +020080 smp->data.type = SMP_T_IPV6;
81 break;
82 default:
83 return 0;
84 }
85
86 smp->flags = 0;
87 return 1;
88}
89
Christopher Faulet7d081f02021-04-15 09:38:37 +020090/* set temp integer to the connection's source port. Depending on the
91 * keyword, it may be the frontend or the backend connection.
92 */
Willy Tarreau8987e7a2020-08-28 11:37:21 +020093static int
Christopher Faulet7d081f02021-04-15 09:38:37 +020094smp_fetch_sport(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8987e7a2020-08-28 11:37:21 +020095{
Christopher Fauletc03be1a2021-10-25 08:01:20 +020096 const struct sockaddr_storage *src = NULL;
Christopher Faulet003df1c2021-04-15 09:39:38 +020097
Christopher Faulet888cd702021-10-25 16:58:50 +020098 if (kw[0] == 'b') { /* bc_src_port */
Christopher Fauletc03be1a2021-10-25 08:01:20 +020099 struct connection *conn = ((obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
100 ? cs_conn(__objt_check(smp->sess->origin)->cs)
Christopher Faulet95a61e82021-12-22 14:22:03 +0100101 : (smp->strm ? cs_conn(smp->strm->csb): NULL));
Christopher Fauletc03be1a2021-10-25 08:01:20 +0200102 if (conn && conn_get_src(conn))
103 src = conn_src(conn);
104 }
Christopher Faulet888cd702021-10-25 16:58:50 +0200105 else if (kw[0] == 'f') { /* fc_src_port */
106 struct connection *conn = objt_conn(smp->sess->origin);
107
108 if (conn && conn_get_src(conn))
109 src = conn_src(conn);
110 }
111 else /* src_port */
Christopher Faulet8da67aa2022-03-29 17:53:09 +0200112 src = (smp->strm ? cs_src(smp->strm->csf) : sess_src(smp->sess));
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200113
Christopher Fauletc03be1a2021-10-25 08:01:20 +0200114 if (!src)
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200115 return 0;
116
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200117 smp->data.type = SMP_T_SINT;
Christopher Fauletc03be1a2021-10-25 08:01:20 +0200118 if (!(smp->data.u.sint = get_host_port(src)))
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200119 return 0;
120
121 smp->flags = 0;
122 return 1;
123}
124
Christopher Faulet7d081f02021-04-15 09:38:37 +0200125/* fetch the connection's destination IPv4/IPv6 address. Depending on the
126 * keyword, it may be the frontend or the backend connection.
127 */
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200128static int
129smp_fetch_dst(const struct arg *args, struct sample *smp, const char *kw, void *private)
130{
Christopher Fauletc03be1a2021-10-25 08:01:20 +0200131 const struct sockaddr_storage *dst = NULL;
Christopher Faulet003df1c2021-04-15 09:39:38 +0200132
Christopher Faulet888cd702021-10-25 16:58:50 +0200133 if (kw[0] == 'b') { /* bc_dst */
Christopher Fauletc03be1a2021-10-25 08:01:20 +0200134 struct connection *conn = ((obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
135 ? cs_conn(__objt_check(smp->sess->origin)->cs)
Christopher Faulet95a61e82021-12-22 14:22:03 +0100136 : (smp->strm ? cs_conn(smp->strm->csb): NULL));
Christopher Fauletc03be1a2021-10-25 08:01:20 +0200137 if (conn && conn_get_dst(conn))
138 dst = conn_dst(conn);
139 }
Christopher Faulet888cd702021-10-25 16:58:50 +0200140 else if (kw[0] == 'f') { /* fc_dst */
141 struct connection *conn = objt_conn(smp->sess->origin);
142
143 if (conn && conn_get_dst(conn))
144 dst = conn_dst(conn);
145 }
146 else /* dst */
Christopher Faulet8da67aa2022-03-29 17:53:09 +0200147 dst = (smp->strm ? cs_dst(smp->strm->csf) : sess_dst(smp->sess));
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200148
Christopher Fauletc03be1a2021-10-25 08:01:20 +0200149 if (!dst)
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200150 return 0;
151
Christopher Fauletc03be1a2021-10-25 08:01:20 +0200152 switch (dst->ss_family) {
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200153 case AF_INET:
Christopher Fauletc03be1a2021-10-25 08:01:20 +0200154 smp->data.u.ipv4 = ((struct sockaddr_in *)dst)->sin_addr;
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200155 smp->data.type = SMP_T_IPV4;
156 break;
157 case AF_INET6:
Christopher Fauletc03be1a2021-10-25 08:01:20 +0200158 smp->data.u.ipv6 = ((struct sockaddr_in6 *)dst)->sin6_addr;
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200159 smp->data.type = SMP_T_IPV6;
160 break;
161 default:
162 return 0;
163 }
164
165 smp->flags = 0;
166 return 1;
167}
168
169/* check if the destination address of the front connection is local to the
170 * system or if it was intercepted.
171 */
172int smp_fetch_dst_is_local(const struct arg *args, struct sample *smp, const char *kw, void *private)
173{
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200174 struct listener *li = smp->sess->listener;
Christopher Faulet888cd702021-10-25 16:58:50 +0200175 const struct sockaddr_storage *dst = NULL;
176
177 if (kw[0] == 'f') { /* fc_dst_is_local */
178 struct connection *conn = objt_conn(smp->sess->origin);
179
180 if (conn && conn_get_src(conn))
181 dst = conn_dst(conn);
182 }
183 else /* dst_is_local */
Christopher Faulet8da67aa2022-03-29 17:53:09 +0200184 dst = (smp->strm ? cs_dst(smp->strm->csf) : sess_dst(smp->sess));
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200185
Christopher Fauletc03be1a2021-10-25 08:01:20 +0200186 if (!dst)
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200187 return 0;
188
189 smp->data.type = SMP_T_BOOL;
190 smp->flags = 0;
Christopher Fauletc03be1a2021-10-25 08:01:20 +0200191 smp->data.u.sint = addr_is_local(li->rx.settings->netns, dst);
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200192 return smp->data.u.sint >= 0;
193}
194
195/* check if the source address of the front connection is local to the system
196 * or not.
197 */
198int smp_fetch_src_is_local(const struct arg *args, struct sample *smp, const char *kw, void *private)
199{
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200200 struct listener *li = smp->sess->listener;
Christopher Faulet888cd702021-10-25 16:58:50 +0200201 const struct sockaddr_storage *src = NULL;
202
203 if (kw[0] == 'f') { /* fc_src_is_local */
204 struct connection *conn = objt_conn(smp->sess->origin);
205
206 if (conn && conn_get_src(conn))
207 src = conn_src(conn);
208 }
209 else /* src_is_local */
Christopher Faulet8da67aa2022-03-29 17:53:09 +0200210 src = (smp->strm ? cs_src(smp->strm->csf) : sess_src(smp->sess));
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200211
Christopher Fauletc03be1a2021-10-25 08:01:20 +0200212 if (!src)
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200213 return 0;
214
215 smp->data.type = SMP_T_BOOL;
216 smp->flags = 0;
Christopher Fauletc03be1a2021-10-25 08:01:20 +0200217 smp->data.u.sint = addr_is_local(li->rx.settings->netns, src);
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200218 return smp->data.u.sint >= 0;
219}
220
Christopher Faulet7d081f02021-04-15 09:38:37 +0200221/* set temp integer to the connexion's destination port. Depending on the
222 * keyword, it may be the frontend or the backend connection.
223 */
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200224static int
225smp_fetch_dport(const struct arg *args, struct sample *smp, const char *kw, void *private)
226{
Christopher Fauletc03be1a2021-10-25 08:01:20 +0200227 const struct sockaddr_storage *dst = NULL;
Christopher Faulet003df1c2021-04-15 09:39:38 +0200228
Christopher Faulet888cd702021-10-25 16:58:50 +0200229 if (kw[0] == 'b') { /* bc_dst_port */
Christopher Fauletc03be1a2021-10-25 08:01:20 +0200230 struct connection *conn = ((obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
231 ? cs_conn(__objt_check(smp->sess->origin)->cs)
Christopher Faulet95a61e82021-12-22 14:22:03 +0100232 : (smp->strm ? cs_conn(smp->strm->csb): NULL));
Christopher Fauletc03be1a2021-10-25 08:01:20 +0200233 if (conn && conn_get_dst(conn))
234 dst = conn_dst(conn);
235 }
Christopher Faulet888cd702021-10-25 16:58:50 +0200236 else if (kw[0] == 'f') { /* fc_dst_post */
237 struct connection *conn = objt_conn(smp->sess->origin);
238
239 if (conn && conn_get_src(conn))
240 dst = conn_dst(conn);
241 }
242 else /* dst_port */
Christopher Faulet8da67aa2022-03-29 17:53:09 +0200243 dst = (smp->strm ? cs_dst(smp->strm->csf) : sess_dst(smp->sess));
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200244
Christopher Fauletc03be1a2021-10-25 08:01:20 +0200245 if (!dst)
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200246 return 0;
247
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200248 smp->data.type = SMP_T_SINT;
Christopher Fauletc03be1a2021-10-25 08:01:20 +0200249 if (!(smp->data.u.sint = get_host_port(dst)))
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200250 return 0;
251
252 smp->flags = 0;
253 return 1;
254}
255
256#ifdef TCP_INFO
257
258
259/* Validates the arguments passed to "fc_*" fetch keywords returning a time
260 * value. These keywords support an optional string representing the unit of the
261 * result: "us" for microseconds and "ms" for milliseconds". Returns 0 on error
262 * and non-zero if OK.
263 */
264static int val_fc_time_value(struct arg *args, char **err)
265{
266 if (args[0].type == ARGT_STR) {
267 if (strcmp(args[0].data.str.area, "us") == 0) {
268 chunk_destroy(&args[0].data.str);
269 args[0].type = ARGT_SINT;
270 args[0].data.sint = TIME_UNIT_US;
271 }
272 else if (strcmp(args[0].data.str.area, "ms") == 0) {
273 chunk_destroy(&args[0].data.str);
274 args[0].type = ARGT_SINT;
275 args[0].data.sint = TIME_UNIT_MS;
276 }
277 else {
278 memprintf(err, "expects 'us' or 'ms', got '%s'",
279 args[0].data.str.area);
280 return 0;
281 }
282 }
283 else {
284 memprintf(err, "Unexpected arg type");
285 return 0;
286 }
287
288 return 1;
289}
290
291/* Validates the arguments passed to "fc_*" fetch keywords returning a
292 * counter. These keywords should be used without any keyword, but because of a
293 * bug in previous versions, an optional string argument may be passed. In such
294 * case, the argument is ignored and a warning is emitted. Returns 0 on error
295 * and non-zero if OK.
296 */
297static int var_fc_counter(struct arg *args, char **err)
298{
299 if (args[0].type != ARGT_STOP) {
300 ha_warning("no argument supported for 'fc_*' sample expressions returning counters.\n");
301 if (args[0].type == ARGT_STR)
302 chunk_destroy(&args[0].data.str);
303 args[0].type = ARGT_STOP;
304 }
305
306 return 1;
307}
308
309/* Returns some tcp_info data if it's available. "dir" must be set to 0 if
310 * the client connection is required, otherwise it is set to 1. "val" represents
311 * the required value.
312 * If the function fails it returns 0, otherwise it returns 1 and "result" is filled.
313 */
314static inline int get_tcp_info(const struct arg *args, struct sample *smp,
315 int dir, int val)
316{
317 struct connection *conn;
318 struct tcp_info info;
319 socklen_t optlen;
320
321 /* strm can be null. */
322 if (!smp->strm)
323 return 0;
324
Christopher Faulet6b0a0fb2022-04-04 11:29:28 +0200325 /* get the object associated with the conn-stream.The
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200326 * object can be other thing than a connection. For example,
327 * it be a appctx. */
Christopher Faulet95a61e82021-12-22 14:22:03 +0100328 conn = (dir == 0 ? cs_conn(smp->strm->csf) : cs_conn(smp->strm->csb));
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200329 if (!conn)
330 return 0;
331
332 /* The fd may not be available for the tcp_info struct, and the
333 syscal can fail. */
334 optlen = sizeof(info);
Willy Tarreaue2226792022-04-11 18:04:33 +0200335 if ((conn->flags & CO_FL_FDLESS) ||
336 getsockopt(conn->handle.fd, IPPROTO_TCP, TCP_INFO, &info, &optlen) == -1)
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200337 return 0;
338
339 /* extract the value. */
340 smp->data.type = SMP_T_SINT;
341 switch (val) {
342 case 0: smp->data.u.sint = info.tcpi_rtt; break;
343 case 1: smp->data.u.sint = info.tcpi_rttvar; break;
344#if defined(__linux__)
345 /* these ones are common to all Linux versions */
346 case 2: smp->data.u.sint = info.tcpi_unacked; break;
347 case 3: smp->data.u.sint = info.tcpi_sacked; break;
348 case 4: smp->data.u.sint = info.tcpi_lost; break;
349 case 5: smp->data.u.sint = info.tcpi_retrans; break;
350 case 6: smp->data.u.sint = info.tcpi_fackets; break;
351 case 7: smp->data.u.sint = info.tcpi_reordering; break;
352#elif defined(__FreeBSD__) || defined(__NetBSD__)
353 /* the ones are found on FreeBSD and NetBSD featuring TCP_INFO */
354 case 2: smp->data.u.sint = info.__tcpi_unacked; break;
355 case 3: smp->data.u.sint = info.__tcpi_sacked; break;
356 case 4: smp->data.u.sint = info.__tcpi_lost; break;
357 case 5: smp->data.u.sint = info.__tcpi_retrans; break;
358 case 6: smp->data.u.sint = info.__tcpi_fackets; break;
359 case 7: smp->data.u.sint = info.__tcpi_reordering; break;
360#endif
361 default: return 0;
362 }
363
364 return 1;
365}
366
367/* get the mean rtt of a client connection */
368static int
369smp_fetch_fc_rtt(const struct arg *args, struct sample *smp, const char *kw, void *private)
370{
371 if (!get_tcp_info(args, smp, 0, 0))
372 return 0;
373
374 /* By default or if explicitly specified, convert rtt to ms */
375 if (!args || args[0].type == ARGT_STOP || args[0].data.sint == TIME_UNIT_MS)
376 smp->data.u.sint = (smp->data.u.sint + 500) / 1000;
377
378 return 1;
379}
380
381/* get the variance of the mean rtt of a client connection */
382static int
383smp_fetch_fc_rttvar(const struct arg *args, struct sample *smp, const char *kw, void *private)
384{
385 if (!get_tcp_info(args, smp, 0, 1))
386 return 0;
387
388 /* By default or if explicitly specified, convert rttvar to ms */
389 if (!args || args[0].type == ARGT_STOP || args[0].data.sint == TIME_UNIT_MS)
390 smp->data.u.sint = (smp->data.u.sint + 500) / 1000;
391
392 return 1;
393}
394
395#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
396
397/* get the unacked counter on a client connection */
398static int
399smp_fetch_fc_unacked(const struct arg *args, struct sample *smp, const char *kw, void *private)
400{
401 if (!get_tcp_info(args, smp, 0, 2))
402 return 0;
403 return 1;
404}
405
406/* get the sacked counter on a client connection */
407static int
408smp_fetch_fc_sacked(const struct arg *args, struct sample *smp, const char *kw, void *private)
409{
410 if (!get_tcp_info(args, smp, 0, 3))
411 return 0;
412 return 1;
413}
414
415/* get the lost counter on a client connection */
416static int
417smp_fetch_fc_lost(const struct arg *args, struct sample *smp, const char *kw, void *private)
418{
419 if (!get_tcp_info(args, smp, 0, 4))
420 return 0;
421 return 1;
422}
423
424/* get the retrans counter on a client connection */
425static int
426smp_fetch_fc_retrans(const struct arg *args, struct sample *smp, const char *kw, void *private)
427{
428 if (!get_tcp_info(args, smp, 0, 5))
429 return 0;
430 return 1;
431}
432
433/* get the fackets counter on a client connection */
434static int
435smp_fetch_fc_fackets(const struct arg *args, struct sample *smp, const char *kw, void *private)
436{
437 if (!get_tcp_info(args, smp, 0, 6))
438 return 0;
439 return 1;
440}
441
442/* get the reordering counter on a client connection */
443static int
444smp_fetch_fc_reordering(const struct arg *args, struct sample *smp, const char *kw, void *private)
445{
446 if (!get_tcp_info(args, smp, 0, 7))
447 return 0;
448 return 1;
449}
450#endif // linux || freebsd || netbsd
451#endif // TCP_INFO
452
453/* Note: must not be declared <const> as its list will be overwritten.
454 * Note: fetches that may return multiple types must be declared as the lowest
455 * common denominator, the type that can be casted into all other ones. For
456 * instance v4/v6 must be declared v4.
457 */
458static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Christopher Faulet7d081f02021-04-15 09:38:37 +0200459 { "bc_dst", smp_fetch_dst, 0, NULL, SMP_T_SINT, SMP_USE_L4SRV },
460 { "bc_dst_port", smp_fetch_dport, 0, NULL, SMP_T_SINT, SMP_USE_L4SRV },
461 { "bc_src", smp_fetch_src, 0, NULL, SMP_T_SINT, SMP_USE_L4SRV },
462 { "bc_src_port", smp_fetch_sport, 0, NULL, SMP_T_SINT, SMP_USE_L4SRV },
463
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200464 { "dst", smp_fetch_dst, 0, NULL, SMP_T_IPV4, SMP_USE_L4CLI },
465 { "dst_is_local", smp_fetch_dst_is_local, 0, NULL, SMP_T_BOOL, SMP_USE_L4CLI },
466 { "dst_port", smp_fetch_dport, 0, NULL, SMP_T_SINT, SMP_USE_L4CLI },
Christopher Faulet888cd702021-10-25 16:58:50 +0200467
468 { "fc_dst", smp_fetch_dst, 0, NULL, SMP_T_IPV4, SMP_USE_L4CLI },
469 { "fc_dst_is_local", smp_fetch_dst_is_local, 0, NULL, SMP_T_BOOL, SMP_USE_L4CLI },
470 { "fc_dst_port", smp_fetch_dport, 0, NULL, SMP_T_SINT, SMP_USE_L4CLI },
471
472 { "fc_src", smp_fetch_src, 0, NULL, SMP_T_IPV4, SMP_USE_L4CLI },
473 { "fc_src_is_local", smp_fetch_src_is_local, 0, NULL, SMP_T_BOOL, SMP_USE_L4CLI },
474 { "fc_src_port", smp_fetch_sport, 0, NULL, SMP_T_SINT, SMP_USE_L4CLI },
475
Willy Tarreau8987e7a2020-08-28 11:37:21 +0200476 { "src", smp_fetch_src, 0, NULL, SMP_T_IPV4, SMP_USE_L4CLI },
477 { "src_is_local", smp_fetch_src_is_local, 0, NULL, SMP_T_BOOL, SMP_USE_L4CLI },
478 { "src_port", smp_fetch_sport, 0, NULL, SMP_T_SINT, SMP_USE_L4CLI },
479#ifdef TCP_INFO
480 { "fc_rtt", smp_fetch_fc_rtt, ARG1(0,STR), val_fc_time_value, SMP_T_SINT, SMP_USE_L4CLI },
481 { "fc_rttvar", smp_fetch_fc_rttvar, ARG1(0,STR), val_fc_time_value, SMP_T_SINT, SMP_USE_L4CLI },
482#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
483 { "fc_unacked", smp_fetch_fc_unacked, ARG1(0,STR), var_fc_counter, SMP_T_SINT, SMP_USE_L4CLI },
484 { "fc_sacked", smp_fetch_fc_sacked, ARG1(0,STR), var_fc_counter, SMP_T_SINT, SMP_USE_L4CLI },
485 { "fc_retrans", smp_fetch_fc_retrans, ARG1(0,STR), var_fc_counter, SMP_T_SINT, SMP_USE_L4CLI },
486 { "fc_fackets", smp_fetch_fc_fackets, ARG1(0,STR), var_fc_counter, SMP_T_SINT, SMP_USE_L4CLI },
487 { "fc_lost", smp_fetch_fc_lost, ARG1(0,STR), var_fc_counter, SMP_T_SINT, SMP_USE_L4CLI },
488 { "fc_reordering", smp_fetch_fc_reordering, ARG1(0,STR), var_fc_counter, SMP_T_SINT, SMP_USE_L4CLI },
489#endif // linux || freebsd || netbsd
490#endif // TCP_INFO
491 { /* END */ },
492}};
493
494INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
495
496
497/*
498 * Local variables:
499 * c-indent-level: 8
500 * c-basic-offset: 8
501 * End:
502 */