diff --git a/include/common/defaults.h b/include/common/defaults.h index 5000d9c3d..874d2e273 100644 --- a/include/common/defaults.h +++ b/include/common/defaults.h @@ -73,6 +73,13 @@ #define MAX_HDR_HISTORY 10 #endif +// max # of stick counters per session (at least 3 for sc0..sc2) +// Some changes are needed in TCP_ACT_TRK_SC* and SN_BE_TRACK_SC* if more +// values are required. +#ifndef MAX_SESS_STKCTR +#define MAX_SESS_STKCTR 3 +#endif + // max # of loops we can perform around a read() which succeeds. // It's very frequent that the system returns a few TCP segments at a time. #ifndef MAX_READ_POLL_LOOPS diff --git a/include/proto/session.h b/include/proto/session.h index cc1242daa..f597d5977 100644 --- a/include/proto/session.h +++ b/include/proto/session.h @@ -59,7 +59,7 @@ static inline void session_store_counters(struct session *s) void *ptr; int i; - for (i = 0; i < sizeof(s->stkctr) / sizeof(s->stkctr[0]); i++) { + for (i = 0; i < MAX_SESS_STKCTR; i++) { if (!s->stkctr[i].entry) continue; ptr = stktable_data_ptr(s->stkctr[i].table, s->stkctr[i].entry, STKTABLE_DT_CONN_CUR); @@ -83,7 +83,7 @@ static inline void session_stop_backend_counters(struct session *s) if (likely(!(s->flags & SN_BE_TRACK_ANY))) return; - for (i = 0; i < sizeof(s->stkctr) / sizeof(s->stkctr[0]); i++) { + for (i = 0; i < MAX_SESS_STKCTR; i++) { if (!s->stkctr[i].entry) continue; @@ -145,7 +145,7 @@ static void inline session_inc_http_req_ctr(struct session *s) void *ptr; int i; - for (i = 0; i < sizeof(s->stkctr) / sizeof(s->stkctr[0]); i++) { + for (i = 0; i < MAX_SESS_STKCTR; i++) { if (!s->stkctr[i].entry) continue; @@ -169,7 +169,7 @@ static void inline session_inc_be_http_req_ctr(struct session *s) if (likely(!(s->flags & SN_BE_TRACK_ANY))) return; - for (i = 0; i < sizeof(s->stkctr) / sizeof(s->stkctr[0]); i++) { + for (i = 0; i < MAX_SESS_STKCTR; i++) { if (!s->stkctr[i].entry) continue; @@ -198,7 +198,7 @@ static void inline session_inc_http_err_ctr(struct session *s) void *ptr; int i; - for (i = 0; i < sizeof(s->stkctr) / sizeof(s->stkctr[0]); i++) { + for (i = 0; i < MAX_SESS_STKCTR; i++) { if (!s->stkctr[i].entry) continue; diff --git a/include/types/proto_tcp.h b/include/types/proto_tcp.h index a820462cf..662cde495 100644 --- a/include/types/proto_tcp.h +++ b/include/types/proto_tcp.h @@ -33,9 +33,10 @@ enum { TCP_ACT_ACCEPT = 1, TCP_ACT_REJECT = 2, TCP_ACT_EXPECT_PX = 3, - TCP_ACT_TRK_SC0 = 4, /* TCP request tracking : must be contiguous */ + TCP_ACT_TRK_SC0 = 4, /* TCP request tracking : must be contiguous and cover up to MAX_SESS_STKCTR values */ TCP_ACT_TRK_SC1 = 5, TCP_ACT_TRK_SC2 = 6, + TCP_ACT_TRK_SCMAX = TCP_ACT_TRK_SC0 + MAX_SESS_STKCTR - 1, }; struct tcp_rule { diff --git a/include/types/session.h b/include/types/session.h index 42d37dbed..8f731ddee 100644 --- a/include/types/session.h +++ b/include/types/session.h @@ -90,7 +90,9 @@ #define SN_COMP_READY 0x00100000 /* the compression is initialized */ -/* session tracking flags: these ones must absolutely be contiguous. See also s->stkctr */ +/* session tracking flags: these ones must absolutely be contiguous and cover + * at least MAX_SESS_STKCTR flags. + */ #define SN_BE_TRACK_SC0 0x00200000 /* backend tracks stick-counter 0 */ #define SN_BE_TRACK_SC1 0x00400000 /* backend tracks stick-counter 1 */ #define SN_BE_TRACK_SC2 0x00800000 /* backend tracks stick-counter 2 */ @@ -146,7 +148,7 @@ struct session { } store[8]; /* tracked stickiness values to store */ int store_count; - struct stkctr stkctr[3]; /* stick counters */ + struct stkctr stkctr[MAX_SESS_STKCTR]; /* stick counters */ struct stream_interface si[2]; /* client and server stream interfaces */ struct { diff --git a/src/cfgparse.c b/src/cfgparse.c index a85bbedf0..d51e1b6da 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -6367,7 +6367,7 @@ int check_config_validity() list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) { struct proxy *target; - if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SC2) + if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX) continue; if (trule->act_prm.trk_ctr.table.n) @@ -6406,7 +6406,7 @@ int check_config_validity() list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) { struct proxy *target; - if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SC2) + if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX) continue; if (trule->act_prm.trk_ctr.table.n) diff --git a/src/proto_tcp.c b/src/proto_tcp.c index fe4a0d2b5..797f3357e 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -938,7 +938,7 @@ int tcp_inspect_request(struct session *s, struct channel *req, int an_bit) s->flags |= SN_FINST_R; return 0; } - else if ((rule->action >= TCP_ACT_TRK_SC0 && rule->action <= TCP_ACT_TRK_SC2) && + else if ((rule->action >= TCP_ACT_TRK_SC0 && rule->action <= TCP_ACT_TRK_SCMAX) && !s->stkctr[tcp_trk_idx(rule->action)].entry) { /* Note: only the first valid tracking parameter of each * applies. @@ -1092,7 +1092,7 @@ int tcp_exec_req_rules(struct session *s) result = 0; break; } - else if ((rule->action >= TCP_ACT_TRK_SC0 && rule->action <= TCP_ACT_TRK_SC2) && + else if ((rule->action >= TCP_ACT_TRK_SC0 && rule->action <= TCP_ACT_TRK_SCMAX) && !s->stkctr[tcp_trk_idx(rule->action)].entry) { /* Note: only the first valid tracking parameter of each * applies. @@ -1184,7 +1184,9 @@ static int tcp_parse_request_rule(char **args, int arg, int section_type, arg++; rule->action = TCP_ACT_REJECT; } - else if (strcmp(args[arg], "track-sc0") == 0 || strcmp(args[arg], "track-sc1") == 0 || strcmp(args[arg], "track-sc2") == 0) { + else if (strncmp(args[arg], "track-sc", 8) == 0 && + args[arg][9] == '\0' && args[arg][8] >= '0' && + args[arg][8] <= '0' + MAX_SESS_STKCTR) { /* track-sc 0..9 */ struct sample_expr *expr; int kw = arg; @@ -1246,9 +1248,9 @@ static int tcp_parse_request_rule(char **args, int arg, int section_type, } else { memprintf(err, - "'%s %s' expects 'accept', 'reject', 'track-sc0', 'track-sc1' " - " or 'track-sc2' in %s '%s' (got '%s')", - args[0], args[1], proxy_type_str(curpx), curpx->id, args[arg]); + "'%s %s' expects 'accept', 'reject', 'track-sc0' ... 'track-sc%d' " + " in %s '%s' (got '%s')", + args[0], args[1], MAX_SESS_STKCTR, proxy_type_str(curpx), curpx->id, args[arg]); return -1; } diff --git a/src/session.c b/src/session.c index 9be5faa21..ec78be1b3 100644 --- a/src/session.c +++ b/src/session.c @@ -420,7 +420,7 @@ int session_complete(struct session *s) /* Let's count a session now */ proxy_inc_fe_sess_ctr(l, p); - for (i = 0; i < sizeof(s->stkctr) / sizeof(s->stkctr[0]); i++) { + for (i = 0; i < MAX_SESS_STKCTR; i++) { void *ptr; if (!s->stkctr[i].entry) @@ -707,7 +707,7 @@ void session_process_counters(struct session *s) if (s->listener->counters) s->listener->counters->bytes_in += bytes; - for (i = 0; i < sizeof(s->stkctr) / sizeof(s->stkctr[0]); i++) { + for (i = 0; i < MAX_SESS_STKCTR; i++) { if (!s->stkctr[i].entry) continue; @@ -741,7 +741,7 @@ void session_process_counters(struct session *s) if (s->listener->counters) s->listener->counters->bytes_out += bytes; - for (i = 0; i < sizeof(s->stkctr) / sizeof(s->stkctr[0]); i++) { + for (i = 0; i < MAX_SESS_STKCTR; i++) { if (!s->stkctr[i].entry) continue;