From: Willy Tarreau Date: Sun, 9 Dec 2012 13:53:32 +0000 (+0100) Subject: MINOR: http: add the "base32+src" fetch method. X-Git-Tag: v1.5-dev15~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4a55060aa631a4296adba15a4a4ababee5856ef1;p=thirdparty%2Fhaproxy.git MINOR: http: add the "base32+src" fetch method. This returns the concatenation of the base32 fetch and the src fetch. The resulting type is of type binary, with a size of 8 or 20 bytes depending on the source address family. This can be used to track per-IP, per-URL counters. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index 8adc3f2e95..fcbb9ee2ab 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -9322,6 +9322,11 @@ The list of currently supported pattern fetch functions is the following : shorter hash is stored, saving a lot of memory. The output type is an unsigned integer. + base32+src This returns the concatenation of the base32 fetch above and the + src fetch below. The resulting type is of type binary, with a + size of 8 or 20 bytes depending on the source address family. + This can be used to track per-IP, per-URL counters. + src This is the source IPv4 address of the client of the session. It is of type IPv4 and works on both IPv4 and IPv6 tables. On IPv6 tables, IPv4 address is mapped to its IPv6 equivalent, diff --git a/src/proto_http.c b/src/proto_http.c index b3481aff9e..89b55b3006 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -8538,6 +8538,43 @@ smp_fetch_base32(struct proxy *px, struct session *l4, void *l7, unsigned int op return 1; } +/* This concatenates the source address with the 32-bit hash of the Host and + * URL as returned by smp_fetch_base32(). The idea is to have per-source and + * per-url counters. The result is a binary block from 8 to 20 bytes depending + * on the source address length. The URL hash is stored before the address so + * that in environments where IPv6 is insignificant, truncating the output to + * 8 bytes would still work. + */ +static int +smp_fetch_base32_src(struct proxy *px, struct session *l4, void *l7, unsigned int opt, + const struct arg *args, struct sample *smp) +{ + struct chunk *temp = sample_get_trash_chunk(); + + if (!smp_fetch_base32(px, l4, l7, opt, args, smp)) + return 0; + + memcpy(temp->str + temp->len, &smp->data.uint, sizeof(smp->data.uint)); + temp->len += sizeof(smp->data.uint); + + switch (l4->si[0].conn->addr.from.ss_family) { + case AF_INET: + memcpy(temp->str + temp->len, &((struct sockaddr_in *)&l4->si[0].conn->addr.from)->sin_addr, 4); + temp->len += 4; + break; + case AF_INET6: + memcpy(temp->str + temp->len, &((struct sockaddr_in6 *)(&l4->si[0].conn->addr.from))->sin6_addr, 16); + temp->len += 16; + break; + default: + return 0; + } + + smp->data.str = *temp; + smp->type = SMP_T_BIN; + return 1; +} + static int acl_fetch_proto_http(struct proxy *px, struct session *l4, void *l7, unsigned int opt, const struct arg *args, struct sample *smp) @@ -9160,6 +9197,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{ { "hdr", smp_fetch_hdr, ARG2(1,STR,SINT), val_hdr, SMP_T_CSTR, SMP_CAP_L7|SMP_CAP_REQ }, { "base", smp_fetch_base, 0, NULL, SMP_T_CSTR, SMP_CAP_L7|SMP_CAP_REQ }, { "base32", smp_fetch_base32, 0, NULL, SMP_T_UINT, SMP_CAP_L7|SMP_CAP_REQ }, + { "base32+src", smp_fetch_base32_src, 0, NULL, SMP_T_BIN, SMP_CAP_L7|SMP_CAP_REQ }, { "path", smp_fetch_path, 0, NULL, SMP_T_CSTR, SMP_CAP_L7|SMP_CAP_REQ }, { "url", smp_fetch_url, 0, NULL, SMP_T_CSTR, SMP_CAP_L7|SMP_CAP_REQ }, { "url_ip", smp_fetch_url_ip, 0, NULL, SMP_T_IPV4, SMP_CAP_L7|SMP_CAP_REQ },