diff --git a/src/backend.c b/src/backend.c index b51c27677..a1d9c37df 100644 --- a/src/backend.c +++ b/src/backend.c @@ -1353,25 +1353,6 @@ acl_fetch_connslots(struct proxy *px, struct session *l4, void *l7, int dir, return 1; } -/* set test->i to the number of connections per second reaching the frontend */ -static int -acl_fetch_fe_sess_rate(struct proxy *px, struct session *l4, void *l7, int dir, - struct acl_expr *expr, struct acl_test *test) -{ - test->flags = ACL_TEST_F_VOL_TEST; - if (expr->arg_len) { - /* another proxy was designated, we must look for it */ - for (px = proxy; px; px = px->next) - if ((px->cap & PR_CAP_FE) && !strcmp(px->id, expr->arg.str)) - break; - } - if (!px) - return 0; - - test->i = read_freq_ctr(&px->fe_sess_per_sec); - return 1; -} - /* set test->i to the number of connections per second reaching the backend */ static int acl_fetch_be_sess_rate(struct proxy *px, struct session *l4, void *l7, int dir, @@ -1391,25 +1372,6 @@ acl_fetch_be_sess_rate(struct proxy *px, struct session *l4, void *l7, int dir, return 1; } -/* set test->i to the number of concurrent connections on the frontend */ -static int -acl_fetch_fe_conn(struct proxy *px, struct session *l4, void *l7, int dir, - struct acl_expr *expr, struct acl_test *test) -{ - test->flags = ACL_TEST_F_VOL_TEST; - if (expr->arg_len) { - /* another proxy was designated, we must look for it */ - for (px = proxy; px; px = px->next) - if ((px->cap & PR_CAP_FE) && !strcmp(px->id, expr->arg.str)) - break; - } - if (!px) - return 0; - - test->i = px->feconn; - return 1; -} - /* set test->i to the number of concurrent connections on the backend */ static int acl_fetch_be_conn(struct proxy *px, struct session *l4, void *l7, int dir, @@ -1489,9 +1451,7 @@ acl_fetch_avg_queue_size(struct proxy *px, struct session *l4, void *l7, int dir static struct acl_kw_list acl_kws = {{ },{ { "nbsrv", acl_parse_int, acl_fetch_nbsrv, acl_match_int, ACL_USE_NOTHING }, { "connslots", acl_parse_int, acl_fetch_connslots, acl_match_int, ACL_USE_NOTHING }, - { "fe_sess_rate", acl_parse_int, acl_fetch_fe_sess_rate, acl_match_int, ACL_USE_NOTHING }, { "be_sess_rate", acl_parse_int, acl_fetch_be_sess_rate, acl_match_int, ACL_USE_NOTHING }, - { "fe_conn", acl_parse_int, acl_fetch_fe_conn, acl_match_int, ACL_USE_NOTHING }, { "be_conn", acl_parse_int, acl_fetch_be_conn, acl_match_int, ACL_USE_NOTHING }, { "queue", acl_parse_int, acl_fetch_queue_size, acl_match_int, ACL_USE_NOTHING }, { "avg_queue", acl_parse_int, acl_fetch_avg_queue_size, acl_match_int, ACL_USE_NOTHING }, diff --git a/src/client.c b/src/client.c index 4126ee481..a9bf76922 100644 --- a/src/client.c +++ b/src/client.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -512,111 +511,6 @@ int event_accept(int fd) { return 0; } - - -/************************************************************************/ -/* All supported keywords must be declared here. */ -/************************************************************************/ - -/* set test->ptr to point to the source IPv4/IPv6 address and test->i to the family */ -static int -acl_fetch_src(struct proxy *px, struct session *l4, void *l7, int dir, - struct acl_expr *expr, struct acl_test *test) -{ - test->i = l4->cli_addr.ss_family; - if (test->i == AF_INET) - test->ptr = (void *)&((struct sockaddr_in *)&l4->cli_addr)->sin_addr; - else - test->ptr = (void *)&((struct sockaddr_in6 *)(&l4->cli_addr))->sin6_addr; - test->flags = ACL_TEST_F_READ_ONLY; - return 1; -} - -/* extract the connection's source address */ -static int -pattern_fetch_src(struct proxy *px, struct session *l4, void *l7, int dir, - const char *arg, int arg_len, union pattern_data *data) -{ - data->ip.s_addr = ((struct sockaddr_in *)&l4->cli_addr)->sin_addr.s_addr; - return 1; -} - - -/* set test->i to the connection's source port */ -static int -acl_fetch_sport(struct proxy *px, struct session *l4, void *l7, int dir, - struct acl_expr *expr, struct acl_test *test) -{ - if (l4->cli_addr.ss_family == AF_INET) - test->i = ntohs(((struct sockaddr_in *)&l4->cli_addr)->sin_port); - else - test->i = ntohs(((struct sockaddr_in6 *)(&l4->cli_addr))->sin6_port); - test->flags = 0; - return 1; -} - - -/* set test->ptr to point to the frontend's IPv4/IPv6 address and test->i to the family */ -static int -acl_fetch_dst(struct proxy *px, struct session *l4, void *l7, int dir, - struct acl_expr *expr, struct acl_test *test) -{ - if (!(l4->flags & SN_FRT_ADDR_SET)) - get_frt_addr(l4); - - test->i = l4->frt_addr.ss_family; - if (test->i == AF_INET) - test->ptr = (void *)&((struct sockaddr_in *)&l4->frt_addr)->sin_addr; - else - test->ptr = (void *)&((struct sockaddr_in6 *)(&l4->frt_addr))->sin6_addr; - test->flags = ACL_TEST_F_READ_ONLY; - return 1; -} - - -/* extract the connection's destination address */ -static int -pattern_fetch_dst(struct proxy *px, struct session *l4, void *l7, int dir, - const char *arg, int arg_len, union pattern_data *data) -{ - data->ip.s_addr = ((struct sockaddr_in *)&l4->frt_addr)->sin_addr.s_addr; - return 1; -} - -/* set test->i to the frontend connexion's destination port */ -static int -acl_fetch_dport(struct proxy *px, struct session *l4, void *l7, int dir, - struct acl_expr *expr, struct acl_test *test) -{ - if (!(l4->flags & SN_FRT_ADDR_SET)) - get_frt_addr(l4); - - if (l4->frt_addr.ss_family == AF_INET) - test->i = ntohs(((struct sockaddr_in *)&l4->frt_addr)->sin_port); - else - test->i = ntohs(((struct sockaddr_in6 *)(&l4->frt_addr))->sin6_port); - test->flags = 0; - return 1; -} - -static int -pattern_fetch_dport(struct proxy *px, struct session *l4, void *l7, int dir, - const char *arg, int arg_len, union pattern_data *data) - -{ - data->integer = ntohs(((struct sockaddr_in *)&l4->frt_addr)->sin_port); - return 1; -} - -/* set test->i to the number of connexions to the same listening socket */ -static int -acl_fetch_dconn(struct proxy *px, struct session *l4, void *l7, int dir, - struct acl_expr *expr, struct acl_test *test) -{ - test->i = l4->listener->nbconn; - return 1; -} - /* set test->i to the id of the frontend */ static int acl_fetch_fe_id(struct proxy *px, struct session *l4, void *l7, int dir, @@ -629,49 +523,58 @@ acl_fetch_fe_id(struct proxy *px, struct session *l4, void *l7, int dir, return 1; } -/* set test->i to the id of the socket (listener) */ +/* set test->i to the number of connections per second reaching the frontend */ static int -acl_fetch_so_id(struct proxy *px, struct session *l4, void *l7, int dir, - struct acl_expr *expr, struct acl_test *test) { +acl_fetch_fe_sess_rate(struct proxy *px, struct session *l4, void *l7, int dir, + struct acl_expr *expr, struct acl_test *test) +{ + test->flags = ACL_TEST_F_VOL_TEST; + if (expr->arg_len) { + /* another proxy was designated, we must look for it */ + for (px = proxy; px; px = px->next) + if ((px->cap & PR_CAP_FE) && !strcmp(px->id, expr->arg.str)) + break; + } + if (!px) + return 0; - test->flags = ACL_TEST_F_READ_ONLY; + test->i = read_freq_ctr(&px->fe_sess_per_sec); + return 1; +} - test->i = l4->listener->luid; +/* set test->i to the number of concurrent connections on the frontend */ +static int +acl_fetch_fe_conn(struct proxy *px, struct session *l4, void *l7, int dir, + struct acl_expr *expr, struct acl_test *test) +{ + test->flags = ACL_TEST_F_VOL_TEST; + if (expr->arg_len) { + /* another proxy was designated, we must look for it */ + for (px = proxy; px; px = px->next) + if ((px->cap & PR_CAP_FE) && !strcmp(px->id, expr->arg.str)) + break; + } + if (!px) + return 0; + test->i = px->feconn; return 1; } /* Note: must not be declared as its list will be overwritten */ static struct acl_kw_list acl_kws = {{ },{ - { "src_port", acl_parse_int, acl_fetch_sport, acl_match_int, ACL_USE_TCP_PERMANENT }, - { "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 }, -#if 0 - { "src_limit", acl_parse_int, acl_fetch_sconn, acl_match_int }, -#endif - { "dst_conn", acl_parse_int, acl_fetch_dconn, acl_match_int, ACL_USE_NOTHING }, - { "fe_id", acl_parse_int, acl_fetch_fe_id, acl_match_int, ACL_USE_NOTHING }, - { "so_id", acl_parse_int, acl_fetch_so_id, acl_match_int, ACL_USE_NOTHING }, + { "fe_id", acl_parse_int, acl_fetch_fe_id, acl_match_int, ACL_USE_NOTHING }, + { "fe_sess_rate", acl_parse_int, acl_fetch_fe_sess_rate, acl_match_int, ACL_USE_NOTHING }, + { "fe_conn", acl_parse_int, acl_fetch_fe_conn, acl_match_int, ACL_USE_NOTHING }, { NULL, NULL, NULL, NULL }, }}; -/* Note: must not be declared as its list will be overwritten */ -static struct pattern_fetch_kw_list pattern_fetch_keywords = {{ },{ - { "src", pattern_fetch_src, PATTERN_TYPE_IP, PATTERN_FETCH_REQ }, - { "dst", pattern_fetch_dst, PATTERN_TYPE_IP, PATTERN_FETCH_REQ }, - { "dst_port", pattern_fetch_dport, PATTERN_TYPE_INTEGER, PATTERN_FETCH_REQ }, - { NULL, NULL, 0, 0 }, -}}; - - __attribute__((constructor)) static void __client_init(void) { acl_register_keywords(&acl_kws); - pattern_register_fetches(&pattern_fetch_keywords); } diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 4a8311505..d336ed1cc 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -39,7 +39,9 @@ #include #include +#include #include +#include #include #include #include @@ -822,20 +824,130 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx, return -1; } + +/************************************************************************/ +/* All supported ACL keywords must be declared here. */ +/************************************************************************/ + +/* set test->ptr to point to the source IPv4/IPv6 address and test->i to the family */ +static int +acl_fetch_src(struct proxy *px, struct session *l4, void *l7, int dir, + struct acl_expr *expr, struct acl_test *test) +{ + test->i = l4->cli_addr.ss_family; + if (test->i == AF_INET) + test->ptr = (void *)&((struct sockaddr_in *)&l4->cli_addr)->sin_addr; + else + test->ptr = (void *)&((struct sockaddr_in6 *)(&l4->cli_addr))->sin6_addr; + test->flags = ACL_TEST_F_READ_ONLY; + return 1; +} + +/* extract the connection's source address */ +static int +pattern_fetch_src(struct proxy *px, struct session *l4, void *l7, int dir, + const char *arg, int arg_len, union pattern_data *data) +{ + data->ip.s_addr = ((struct sockaddr_in *)&l4->cli_addr)->sin_addr.s_addr; + return 1; +} + + +/* set test->i to the connection's source port */ +static int +acl_fetch_sport(struct proxy *px, struct session *l4, void *l7, int dir, + struct acl_expr *expr, struct acl_test *test) +{ + if (l4->cli_addr.ss_family == AF_INET) + test->i = ntohs(((struct sockaddr_in *)&l4->cli_addr)->sin_port); + else + test->i = ntohs(((struct sockaddr_in6 *)(&l4->cli_addr))->sin6_port); + test->flags = 0; + return 1; +} + + +/* set test->ptr to point to the frontend's IPv4/IPv6 address and test->i to the family */ +static int +acl_fetch_dst(struct proxy *px, struct session *l4, void *l7, int dir, + struct acl_expr *expr, struct acl_test *test) +{ + if (!(l4->flags & SN_FRT_ADDR_SET)) + get_frt_addr(l4); + + test->i = l4->frt_addr.ss_family; + if (test->i == AF_INET) + test->ptr = (void *)&((struct sockaddr_in *)&l4->frt_addr)->sin_addr; + else + test->ptr = (void *)&((struct sockaddr_in6 *)(&l4->frt_addr))->sin6_addr; + test->flags = ACL_TEST_F_READ_ONLY; + return 1; +} + + +/* extract the connection's destination address */ +static int +pattern_fetch_dst(struct proxy *px, struct session *l4, void *l7, int dir, + const char *arg, int arg_len, union pattern_data *data) +{ + data->ip.s_addr = ((struct sockaddr_in *)&l4->frt_addr)->sin_addr.s_addr; + return 1; +} + +/* set test->i to the frontend connexion's destination port */ +static int +acl_fetch_dport(struct proxy *px, struct session *l4, void *l7, int dir, + struct acl_expr *expr, struct acl_test *test) +{ + if (!(l4->flags & SN_FRT_ADDR_SET)) + get_frt_addr(l4); + + if (l4->frt_addr.ss_family == AF_INET) + test->i = ntohs(((struct sockaddr_in *)&l4->frt_addr)->sin_port); + else + test->i = ntohs(((struct sockaddr_in6 *)(&l4->frt_addr))->sin6_port); + test->flags = 0; + return 1; +} + +static int +pattern_fetch_dport(struct proxy *px, struct session *l4, void *l7, int dir, + const char *arg, int arg_len, union pattern_data *data) + +{ + data->integer = ntohs(((struct sockaddr_in *)&l4->frt_addr)->sin_port); + return 1; +} + + static struct cfg_kw_list cfg_kws = {{ },{ { CFG_LISTEN, "tcp-request", tcp_parse_tcp_req }, { 0, NULL, NULL }, }}; +/* Note: must not be declared as its list will be overwritten */ static struct acl_kw_list acl_kws = {{ },{ + { "src_port", acl_parse_int, acl_fetch_sport, acl_match_int, ACL_USE_TCP_PERMANENT }, + { "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 }, { NULL, NULL, NULL, NULL }, }}; +/* Note: must not be declared as its list will be overwritten */ +static struct pattern_fetch_kw_list pattern_fetch_keywords = {{ },{ + { "src", pattern_fetch_src, PATTERN_TYPE_IP, PATTERN_FETCH_REQ }, + { "dst", pattern_fetch_dst, PATTERN_TYPE_IP, PATTERN_FETCH_REQ }, + { "dst_port", pattern_fetch_dport, PATTERN_TYPE_INTEGER, PATTERN_FETCH_REQ }, + { NULL, NULL, 0, 0 }, +}}; + __attribute__((constructor)) static void __tcp_protocol_init(void) { protocol_register(&proto_tcpv4); protocol_register(&proto_tcpv6); + pattern_register_fetches(&pattern_fetch_keywords); cfg_register_keywords(&cfg_kws); acl_register_keywords(&acl_kws); } diff --git a/src/protocols.c b/src/protocols.c index 735c38443..a32272d73 100644 --- a/src/protocols.c +++ b/src/protocols.c @@ -1,7 +1,7 @@ /* - * Protocol registration functions. + * Protocol registration and listener management functions. * - * Copyright 2000-2008 Willy Tarreau + * Copyright 2000-2010 Willy Tarreau * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,6 +18,7 @@ #include #include +#include #include /* List head of all registered protocols */ @@ -208,3 +209,47 @@ int protocol_disable_all(void) return err; } +/************************************************************************/ +/* All supported ACL keywords must be declared here. */ +/************************************************************************/ + +/* set test->i to the number of connexions to the same listening socket */ +static int +acl_fetch_dconn(struct proxy *px, struct session *l4, void *l7, int dir, + struct acl_expr *expr, struct acl_test *test) +{ + test->i = l4->listener->nbconn; + return 1; +} + +/* set test->i to the id of the socket (listener) */ +static int +acl_fetch_so_id(struct proxy *px, struct session *l4, void *l7, int dir, + struct acl_expr *expr, struct acl_test *test) { + + test->flags = ACL_TEST_F_READ_ONLY; + + test->i = l4->listener->luid; + + return 1; +} + +/* Note: must not be declared as its list will be overwritten */ +static struct acl_kw_list acl_kws = {{ },{ + { "dst_conn", acl_parse_int, acl_fetch_dconn, acl_match_int, ACL_USE_NOTHING }, + { "so_id", acl_parse_int, acl_fetch_so_id, acl_match_int, ACL_USE_NOTHING }, + { NULL, NULL, NULL, NULL }, +}}; + +__attribute__((constructor)) +static void __protocols_init(void) +{ + acl_register_keywords(&acl_kws); +} + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * End: + */