diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 7adb0f999..20fcd6aa7 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -1034,84 +1034,6 @@ pattern_fetch_dport(struct proxy *px, struct session *l4, void *l7, int dir, return 1; } -/* set test->i to the number of connections from the session's source address - * in the table pointed to by expr. - */ -static int -acl_fetch_src_count(struct proxy *px, struct session *l4, void *l7, int dir, - struct acl_expr *expr, struct acl_test *test) -{ - struct stksess *ts; - - /* right now we only support IPv4 */ - if (l4->cli_addr.ss_family != AF_INET) - return 0; - - if (expr->arg_len) { - /* another table was designated, we must look for it */ - for (px = proxy; px; px = px->next) - if (strcmp(px->id, expr->arg.str) == 0) - break; - } - if (!px) - return 0; /* table not found */ - - static_table_key.key = (void *)&((struct sockaddr_in *)&l4->frt_addr)->sin_addr; - test->flags = ACL_TEST_F_VOL_TEST; - test->i = 0; - if ((ts = stktable_lookup_key(&px->table, &static_table_key)) != NULL) { - void *ptr = stktable_data_ptr(&px->table, ts, STKTABLE_DT_CONN_CUM); - if (!ptr) - return 0; /* parameter not stored */ - test->i = stktable_data_cast(ptr, conn_cum); - } - - return 1; -} - -/* set test->i to the number of connections from the session's source address - * in the table pointed to by expr, after updating it. - */ -static int -acl_fetch_src_update_count(struct proxy *px, struct session *l4, void *l7, int dir, - struct acl_expr *expr, struct acl_test *test) -{ - struct stksess *ts; - void *ptr; - - /* right now we only support IPv4 */ - if (l4->cli_addr.ss_family != AF_INET) - return 0; - - if (expr->arg_len) { - /* another table was designated, we must look for it */ - for (px = proxy; px; px = px->next) - if (strcmp(px->id, expr->arg.str) == 0) - break; - } - if (!px) - return 0; - - static_table_key.key = (void *)&((struct sockaddr_in *)&l4->frt_addr)->sin_addr; - if ((ts = stktable_lookup_key(&px->table, &static_table_key)) == NULL) { - /* entry does not exist, initialize a new one */ - ts = stksess_new(&px->table, &static_table_key); - if (!ts) - return 0; - stktable_store(&px->table, ts); - } - else - stktable_touch(&px->table, ts); - - ptr = stktable_data_ptr(&px->table, ts, STKTABLE_DT_CONN_CUM); - if (!ptr) - return 0; /* parameter not stored in this table */ - - test->i = ++stktable_data_cast(ptr, conn_cum); - test->flags = ACL_TEST_F_VOL_TEST; - return 1; -} - static struct cfg_kw_list cfg_kws = {{ },{ { CFG_LISTEN, "tcp-request", tcp_parse_tcp_req }, { 0, NULL, NULL }, @@ -1123,8 +1045,6 @@ static struct acl_kw_list acl_kws = {{ },{ { "src", acl_parse_ip, acl_fetch_src, acl_match_ip, ACL_USE_TCP4_PERMANENT|ACL_MAY_LOOKUP }, { "dst", acl_parse_ip, acl_fetch_dst, acl_match_ip, ACL_USE_TCP4_PERMANENT|ACL_MAY_LOOKUP }, { "dst_port", acl_parse_int, acl_fetch_dport, acl_match_int, ACL_USE_TCP_PERMANENT }, - { "src_count", acl_parse_int, acl_fetch_src_count,acl_match_int, ACL_USE_TCP4_VOLATILE }, - { "src_update_count", acl_parse_int, acl_fetch_src_update_count, acl_match_int, ACL_USE_TCP4_VOLATILE }, { NULL, NULL, NULL, NULL }, }}; diff --git a/src/session.c b/src/session.c index 4e2bedd65..9d583b5f0 100644 --- a/src/session.c +++ b/src/session.c @@ -2051,6 +2051,91 @@ void default_srv_error(struct session *s, struct stream_interface *si) } +/************************************************************************/ +/* All supported ACL keywords must be declared here. */ +/************************************************************************/ + +/* set test->i to the number of connections from the session's source address + * in the table pointed to by expr. + */ +static int +acl_fetch_src_conn_cnt(struct proxy *px, struct session *l4, void *l7, int dir, + struct acl_expr *expr, struct acl_test *test) +{ + struct stksess *ts; + struct stktable_key *key; + + key = tcpv4_src_to_stktable_key(l4); + if (!key) + return 0; /* only TCPv4 is supported right now */ + + if (expr->arg_len) + px = find_stktable(expr->arg.str); + + if (!px) + return 0; /* table not found */ + + test->flags = ACL_TEST_F_VOL_TEST; + test->i = 0; + if ((ts = stktable_lookup_key(&px->table, key)) != NULL) { + void *ptr = stktable_data_ptr(&px->table, ts, STKTABLE_DT_CONN_CNT); + if (!ptr) + return 0; /* parameter not stored */ + test->i = stktable_data_cast(ptr, conn_cnt); + } + + return 1; +} + +/* set test->i to the number of connections from the session's source address + * in the table pointed to by expr, after updating it. + */ +static int +acl_fetch_src_updt_conn_cnt(struct proxy *px, struct session *l4, void *l7, int dir, + struct acl_expr *expr, struct acl_test *test) +{ + struct stksess *ts; + struct stktable_key *key; + void *ptr; + + key = tcpv4_src_to_stktable_key(l4); + if (!key) + return 0; /* only TCPv4 is supported right now */ + + if (expr->arg_len) + px = find_stktable(expr->arg.str); + + if (!px) + return 0; /* table not found */ + + if ((ts = stktable_lookup_key(&px->table, key)) == NULL) { + /* entry does not exist, initialize a new one */ + ts = stksess_new(&px->table, key); + if (!ts) + return 0; + stktable_store(&px->table, ts); + } + else + stktable_touch(&px->table, ts); + + ptr = stktable_data_ptr(&px->table, ts, STKTABLE_DT_CONN_CNT); + if (!ptr) + return 0; /* parameter not stored in this table */ + + test->i = ++stktable_data_cast(ptr, conn_cnt); + test->flags = ACL_TEST_F_VOL_TEST; + return 1; +} + + +/* Note: must not be declared as its list will be overwritten */ +static struct acl_kw_list acl_kws = {{ },{ + { "src_conn_cnt", acl_parse_int, acl_fetch_src_conn_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE }, + { "src_updt_conn_cnt", acl_parse_int, acl_fetch_src_updt_conn_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE }, + { NULL, NULL, NULL, NULL }, +}}; + + /* Parse a "track-counters" line starting with "track-counters" in args[arg-1]. * Returns the number of warnings emitted, or -1 in case of fatal errors. The * struct is fed with the table name if any. If unspecified, the caller @@ -2100,6 +2185,12 @@ int parse_track_counters(char **args, int *arg, return 0; } +__attribute__((constructor)) +static void __session_init(void) +{ + acl_register_keywords(&acl_kws); +} + /* * Local variables: * c-indent-level: 8