]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] IPv6 support for stick-tables
authorDavid du Colombier <dducolombier@exceliance.fr>
Thu, 24 Mar 2011 10:09:31 +0000 (11:09 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 28 Mar 2011 23:09:14 +0000 (01:09 +0200)
Since IPv6 is a different type than IPv4, the pattern fetch functions
src6 and dst6 were added. IPv6 stick-tables can also fetch IPv4 addresses
with src and dst. In this case, the IPv4 addresses are mapped to their
IPv6 counterpart, according to RFC 4291.

include/common/standard.h
include/proto/proto_tcp.h
include/types/pattern.h
include/types/stick_table.h
src/dumpstats.c
src/pattern.c
src/proto_tcp.c
src/session.c
src/standard.c
src/stick_table.c

index e20eb77545d524d8d6209abd23010e94ca2cd279..e7a1052841528b4e1005b5ea9680759fa05e9817 100644 (file)
@@ -549,4 +549,18 @@ static inline int set_host_port(struct sockaddr_storage *addr, int port)
        return 0;
 }
 
+/* Return true if IPv4 address is part of the network */
+extern int in_net_ipv4(struct in_addr *addr, struct in_addr *mask, struct in_addr *net);
+
+/* Return true if IPv6 address is part of the network */
+extern int in_net_ipv6(struct in6_addr *addr, struct in6_addr *mask, struct in6_addr *net);
+
+/* Map IPv4 adress on IPv6 address, as specified in RFC 3513. */
+extern void v4tov6(struct in6_addr *sin6_addr, struct in_addr *sin_addr);
+
+/* Map IPv6 adress on IPv4 address, as specified in RFC 3513.
+ * Return true if conversion is possible and false otherwise.
+ */
+extern int v6tov4(struct in_addr *sin_addr, struct in6_addr *sin6_addr);
+
 #endif /* _COMMON_STANDARD_H */
index 26e06df8cc70d7d2879e460c1a249cce1eb71a09..c7aef6a89c45b501420b19dee42e11035fbd7e55 100644 (file)
@@ -36,18 +36,19 @@ int tcp_inspect_response(struct session *s, struct buffer *rep, int an_bit);
 int tcp_persist_rdp_cookie(struct session *s, struct buffer *req, int an_bit);
 int tcp_exec_req_rules(struct session *s);
 
-/* Converts the TCPv4 source address to a stick_table key usable for table
+/* Converts the TCP source address to a stick_table key usable for table
  * lookups. Returns either NULL if the source cannot be converted (eg: not
  * IPv4) or a pointer to the converted result in static_table_key in the
  * appropriate format (IP).
  */
-static inline struct stktable_key *tcpv4_src_to_stktable_key(struct session *s)
+static inline struct stktable_key *tcp_src_to_stktable_key(struct session *s)
 {
-       /* right now we only support IPv4 */
-       if (s->si[0].addr.c.from.ss_family != AF_INET)
-               return NULL;
-
-       static_table_key.key = (void *)&((struct sockaddr_in *)&s->si[0].addr.c.from)->sin_addr;
+       switch (s->si[0].addr.c.from.ss_family) {
+       case AF_INET:
+               static_table_key.key = (void *)&((struct sockaddr_in *)&s->si[0].addr.c.from)->sin_addr;
+       case AF_INET6:
+               static_table_key.key = (void *)&((struct sockaddr_in6 *)&s->si[0].addr.c.from)->sin6_addr;
+       }
        return &static_table_key;
 }
 
index a3d5c3673b38cd448606fd9eb827886f88ecc27c..9b4e3405d97e026d1b802c60ae98a1fbc1683d15 100644 (file)
@@ -29,6 +29,7 @@
 /* pattern in and out types */
 enum {
        PATTERN_TYPE_IP = 0,      /* ipv4 type */
+       PATTERN_TYPE_IPV6,        /* ipv6 type */
        PATTERN_TYPE_INTEGER,     /* unsigned 32bits integer type */
        PATTERN_TYPE_STRING,      /* char string type */
        PATTERN_TYPE_DATA,        /* buffer type */
@@ -41,6 +42,7 @@ enum {
 /* pattern arg types */
 enum {
        PATTERN_ARG_TYPE_IP = 0,      /* ipv4 type */
+       PATTERN_ARG_TYPE_IPV6,        /* ipv6 type */
        PATTERN_ARG_TYPE_INTEGER,     /* unsigned 32bits integer type */
        PATTERN_ARG_TYPE_SINTEGER,    /* signed 32bits integer type */
        PATTERN_ARG_TYPE_STRING       /* string type */
@@ -53,6 +55,7 @@ enum {
 
 union pattern_arg_data {
        struct in_addr ip;        /* used for ipv4 type */
+       struct in6_addr ipv6;     /* used for ipv6 type */
        uint32_t integer;         /* used for unsigned 32bits integer type */
        int sinteger;             /* used for signed 32bits integer type */
        struct chunk str;
@@ -66,6 +69,7 @@ struct pattern_arg {
 /* pattern result data */
 union pattern_data {
        struct in_addr ip;        /* used for ipv4 type */
+       struct in6_addr ipv6;     /* used for ipv6 type */
        uint32_t integer;         /* used for unsigned 32bits integer type */
        struct chunk str;         /* used for char string type or buffers*/
 };
index e519f490e35903409978f35fd61301f8dff986d9..cccf9fbecd9b91a341c01fd04ba8ef7973bf26fe 100644 (file)
@@ -35,6 +35,7 @@
 /* stick table key types */
 enum {
        STKTABLE_TYPE_IP = 0,     /* table key is ipv4 */
+       STKTABLE_TYPE_IPV6,       /* table key is ipv6 */
        STKTABLE_TYPE_INTEGER,    /* table key is unsigned 32bit integer */
        STKTABLE_TYPE_STRING,     /* table key is a null terminated string */
        STKTABLE_TYPE_BINARY,     /* table key is a buffer of data  */
@@ -172,7 +173,8 @@ extern struct stktable_data_type stktable_data_types[STKTABLE_DATA_TYPES];
 
 /* stick table key data */
 union stktable_key_data {
-       struct in_addr ip;        /* used to store an ip key */
+       struct in_addr ip;        /* used to store an ipv4 key */
+       struct in6_addr ipv6;     /* used to store an ipv6 key */
        uint32_t integer;         /* used to store an integer key */
        char buf[BUFSIZE];        /* used to store a null terminated string key or a buffer of data */
 };
index 8b8c3fc3208061970ab80c989234d19133dd1057..75baadb06d4c083efa03e571589aa5c4efc5eccc 100644 (file)
@@ -3312,12 +3312,19 @@ int stats_dump_table_to_buffer(struct stream_interface *si)
                        chunk_printf(&msg, "%p:", si->applet.ctx.table.entry);
 
                        if (si->applet.ctx.table.proxy->table.type == STKTABLE_TYPE_IP) {
-                               char addr[16];
+                               char addr[INET_ADDRSTRLEN];
                                inet_ntop(AF_INET,
                                          (const void *)&si->applet.ctx.table.entry->key.key,
                                          addr, sizeof(addr));
                                chunk_printf(&msg, " key=%s", addr);
                        }
+                       else if (si->applet.ctx.table.proxy->table.type == STKTABLE_TYPE_IPV6) {
+                               char addr[INET6_ADDRSTRLEN];
+                               inet_ntop(AF_INET6,
+                                         (const void *)&si->applet.ctx.table.entry->key.key,
+                                         addr, sizeof(addr));
+                               chunk_printf(&msg, " key=%s", addr);
+                       }
                        else if (si->applet.ctx.table.proxy->table.type == STKTABLE_TYPE_INTEGER) {
                                chunk_printf(&msg, " key=%u", *(unsigned int *)si->applet.ctx.table.entry->key.key);
                        }
index ba8d5a01e9ce52d7471223aa058ef6e567239e31..e705f00c31aa5ea225b2dbeb5cd808924c909eb2 100644 (file)
@@ -146,6 +146,32 @@ static int c_ip2str(union pattern_data *data)
        return 1;
 }
 
+static int c_ip2ipv6(union pattern_data *data)
+{
+       v4tov6(&data->ipv6, &data->ip);
+       return 1;
+}
+
+static int c_ipv62str(union pattern_data *data)
+{
+       struct chunk *trash = get_trash_chunk();
+
+       if (!inet_ntop(AF_INET6, (void *)&data->ipv6, trash->str, trash->size))
+               return 0;
+
+       trash->len = strlen(trash->str);
+       pattern_data_setstring(data, trash);
+
+       return 1;
+}
+
+/*
+static int c_ipv62ip(union pattern_data *data)
+{
+       return v6tov4(&data->ip, &data->ipv6);
+}
+*/
+
 static int c_int2ip(union pattern_data *data)
 {
        data->ip.s_addr = htonl(data->integer);
@@ -159,6 +185,11 @@ static int c_str2ip(union pattern_data *data)
        return 1;
 }
 
+static int c_str2ipv6(union pattern_data *data)
+{
+       return inet_pton(AF_INET6, data->str.str, &data->ipv6);
+}
+
 static int c_int2str(union pattern_data *data)
 {
        struct chunk *trash = get_trash_chunk();
@@ -222,13 +253,14 @@ static int c_str2int(union pattern_data *data)
 
 typedef int (*pattern_cast_fct)(union pattern_data *data);
 static pattern_cast_fct pattern_casts[PATTERN_TYPES][PATTERN_TYPES] = {
-/*            to:   IP           INTEGER      STRING       DATA         CONSTSTRING  CONSTDATA */
-/* from:    IP */ { c_donothing, c_ip2int,    c_ip2str,    NULL,        c_ip2str,    NULL        },
-/*     INTEGER */ { c_int2ip,    c_donothing, c_int2str,   NULL,        c_int2str,   NULL        },
-/*      STRING */ { c_str2ip,    c_str2int,   c_donothing, c_donothing, c_donothing, c_donothing },
-/*        DATA */ { NULL,        NULL,        NULL,        c_donothing, NULL,        c_donothing },
-/* CONSTSTRING */ { c_str2ip,    c_str2int,   c_datadup,   c_datadup,   c_donothing, c_donothing },
-/*   CONSTDATA */ { NULL,        NULL,        NULL,        c_datadup,   NULL,       NULL        },
+/*            to:   IP           IPV6         INTEGER      STRING       DATA         CONSTSTRING  CONSTDATA */
+/* from:    IP */ { c_donothing, c_ip2ipv6,   c_ip2int,    c_ip2str,    NULL,        c_ip2str,    NULL        },
+/*        IPV6 */ { NULL,        c_donothing, NULL,        c_ipv62str,  NULL,        c_ipv62str,  NULL        },
+/*     INTEGER */ { c_int2ip,    NULL,        c_donothing, c_int2str,   NULL,        c_int2str,   NULL        },
+/*      STRING */ { c_str2ip,    c_str2ipv6,  c_str2int,   c_donothing, c_donothing, c_donothing, c_donothing },
+/*        DATA */ { NULL,        NULL,        NULL,        NULL,        c_donothing, NULL,        c_donothing },
+/* CONSTSTRING */ { c_str2ip,    c_str2ipv6,  c_str2int,   c_datadup,   c_datadup,   c_donothing, c_donothing },
+/*   CONSTDATA */ { NULL,        NULL,        NULL,        NULL,        c_datadup,   NULL,           c_donothing },
 };
 
 
index 3c8a04f71776ab35da62d16e7a2772a6ae6618c2..ca993a6fc35afbeffb2d57f5f2eb24c6c4a7fe50 100644 (file)
@@ -745,7 +745,7 @@ int tcp_inspect_request(struct session *s, struct buffer *req, int an_bit)
                                         * to consider rule->act_prm->trk_ctr.type.
                                         */
                                        t = rule->act_prm.trk_ctr.table.t;
-                                       ts = stktable_get_entry(t, tcpv4_src_to_stktable_key(s));
+                                       ts = stktable_get_entry(t, tcp_src_to_stktable_key(s));
                                        if (ts) {
                                                session_track_stkctr1(s, t, ts);
                                                if (s->fe != s->be)
@@ -761,7 +761,7 @@ int tcp_inspect_request(struct session *s, struct buffer *req, int an_bit)
                                         * to consider rule->act_prm->trk_ctr.type.
                                         */
                                        t = rule->act_prm.trk_ctr.table.t;
-                                       ts = stktable_get_entry(t, tcpv4_src_to_stktable_key(s));
+                                       ts = stktable_get_entry(t, tcp_src_to_stktable_key(s));
                                        if (ts) {
                                                session_track_stkctr2(s, t, ts);
                                                if (s->fe != s->be)
@@ -915,7 +915,7 @@ int tcp_exec_req_rules(struct session *s)
                                         * to consider rule->act_prm->trk_ctr.type.
                                         */
                                        t = rule->act_prm.trk_ctr.table.t;
-                                       ts = stktable_get_entry(t, tcpv4_src_to_stktable_key(s));
+                                       ts = stktable_get_entry(t, tcp_src_to_stktable_key(s));
                                        if (ts)
                                                session_track_stkctr1(s, t, ts);
                                }
@@ -928,7 +928,7 @@ int tcp_exec_req_rules(struct session *s)
                                         * to consider rule->act_prm->trk_ctr.type.
                                         */
                                        t = rule->act_prm.trk_ctr.table.t;
-                                       ts = stktable_get_entry(t, tcpv4_src_to_stktable_key(s));
+                                       ts = stktable_get_entry(t, tcp_src_to_stktable_key(s));
                                        if (ts)
                                                session_track_stkctr2(s, t, ts);
                                }
@@ -1275,7 +1275,7 @@ acl_fetch_src(struct proxy *px, struct session *l4, void *l7, int dir,
        return 1;
 }
 
-/* extract the connection's source address */
+/* extract the connection's source ipv4 address */
 static int
 pattern_fetch_src(struct proxy *px, struct session *l4, void *l7, int dir,
                   const struct pattern_arg *arg_p, int arg_i, union pattern_data *data)
@@ -1287,6 +1287,17 @@ pattern_fetch_src(struct proxy *px, struct session *l4, void *l7, int dir,
        return 1;
 }
 
+/* extract the connection's source ipv6 address */
+static int
+pattern_fetch_src6(struct proxy *px, struct session *l4, void *l7, int dir,
+                  const struct pattern_arg *arg_p, int arg_i, union pattern_data *data)
+{
+       if (l4->si[0].addr.c.from.ss_family != AF_INET6)
+               return 0;
+
+       memcpy(data->ipv6.s6_addr, ((struct sockaddr_in6 *)&l4->si[0].addr.c.from)->sin6_addr.s6_addr, sizeof(data->ipv6.s6_addr));
+       return 1;
+}
 
 /* set test->i to the connection's source port */
 static int
@@ -1326,7 +1337,7 @@ acl_fetch_dst(struct proxy *px, struct session *l4, void *l7, int dir,
 }
 
 
-/* extract the connection's destination address */
+/* extract the connection's destination ipv4 address */
 static int
 pattern_fetch_dst(struct proxy *px, struct session *l4, void *l7, int dir,
                   const struct pattern_arg *arg_p, int arg_i, union pattern_data *data)
@@ -1341,6 +1352,21 @@ pattern_fetch_dst(struct proxy *px, struct session *l4, void *l7, int dir,
        return 1;
 }
 
+/* extract the connection's destination ipv6 address */
+static int
+pattern_fetch_dst6(struct proxy *px, struct session *l4, void *l7, int dir,
+                  const struct pattern_arg *arg_p, int arg_i, union pattern_data *data)
+{
+       if (!(l4->flags & SN_FRT_ADDR_SET))
+               get_frt_addr(l4);
+
+       if (l4->si[0].addr.c.to.ss_family != AF_INET6)
+               return 0;
+
+       memcpy(data->ipv6.s6_addr, ((struct sockaddr_in6 *)&l4->si[0].addr.c.to)->sin6_addr.s6_addr, sizeof(data->ipv6.s6_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,
@@ -1367,10 +1393,13 @@ pattern_fetch_dport(struct proxy *px, struct session *l4, void *l7, int dir,
        if (!(l4->flags & SN_FRT_ADDR_SET))
                get_frt_addr(l4);
 
-       if (l4->si[0].addr.c.to.ss_family != AF_INET)
+       if (l4->si[0].addr.c.to.ss_family == AF_INET)
+               data->integer = ntohs(((struct sockaddr_in *)&l4->si[0].addr.c.to)->sin_port);
+       else if (l4->si[0].addr.c.to.ss_family == AF_INET6)
+               data->integer = ntohs(((struct sockaddr_in6 *)&l4->si[0].addr.c.to)->sin6_port);
+       else
                return 0;
 
-       data->integer = ntohs(((struct sockaddr_in *)&l4->si[0].addr.c.to)->sin_port);
        return 1;
 }
 
@@ -1566,7 +1595,9 @@ static struct acl_kw_list acl_kws = {{ },{
 /* Note: must not be declared <const> as its list will be overwritten */
 static struct pattern_fetch_kw_list pattern_fetch_keywords = {{ },{
        { "src",         pattern_fetch_src,       NULL,                         PATTERN_TYPE_IP,        PATTERN_FETCH_REQ },
+       { "src6",        pattern_fetch_src6,      NULL,                         PATTERN_TYPE_IPV6,      PATTERN_FETCH_REQ },
        { "dst",         pattern_fetch_dst,       NULL,                         PATTERN_TYPE_IP,        PATTERN_FETCH_REQ },
+       { "dst6",        pattern_fetch_dst6,      NULL,                         PATTERN_TYPE_IPV6,      PATTERN_FETCH_REQ },
        { "dst_port",    pattern_fetch_dport,     NULL,                         PATTERN_TYPE_INTEGER,   PATTERN_FETCH_REQ },
        { "payload",     pattern_fetch_payload,   pattern_arg_fetch_payload,    PATTERN_TYPE_CONSTDATA, PATTERN_FETCH_REQ|PATTERN_FETCH_RTR },
        { "payload_lv",  pattern_fetch_payloadlv, pattern_arg_fetch_payloadlv,  PATTERN_TYPE_CONSTDATA, PATTERN_FETCH_REQ|PATTERN_FETCH_RTR },
index b7914d030b5d02818a263b36ad04119425f6cb4d..27f4fbd1c6e89c608c982c783db5e2ea51973d20 100644 (file)
@@ -2244,9 +2244,9 @@ acl_fetch_src_get_gpc0(struct proxy *px, struct session *l4, void *l7, int dir,
 {
        struct stktable_key *key;
 
-       key = tcpv4_src_to_stktable_key(l4);
+       key = tcp_src_to_stktable_key(l4);
        if (!key)
-               return 0; /* only TCPv4 is supported right now */
+               return 0;
 
        if (expr->arg_len)
                px = find_stktable(expr->arg.str);
@@ -2307,9 +2307,9 @@ acl_fetch_src_inc_gpc0(struct proxy *px, struct session *l4, void *l7, int dir,
 {
        struct stktable_key *key;
 
-       key = tcpv4_src_to_stktable_key(l4);
+       key = tcp_src_to_stktable_key(l4);
        if (!key)
-               return 0; /* only TCPv4 is supported right now */
+               return 0;
 
        if (expr->arg_len)
                px = find_stktable(expr->arg.str);
@@ -2366,9 +2366,9 @@ acl_fetch_src_conn_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
 {
        struct stktable_key *key;
 
-       key = tcpv4_src_to_stktable_key(l4);
+       key = tcp_src_to_stktable_key(l4);
        if (!key)
-               return 0; /* only TCPv4 is supported right now */
+               return 0;
 
        if (expr->arg_len)
                px = find_stktable(expr->arg.str);
@@ -2430,9 +2430,9 @@ acl_fetch_src_conn_rate(struct proxy *px, struct session *l4, void *l7, int dir,
 {
        struct stktable_key *key;
 
-       key = tcpv4_src_to_stktable_key(l4);
+       key = tcp_src_to_stktable_key(l4);
        if (!key)
-               return 0; /* only TCPv4 is supported right now */
+               return 0;
 
        if (expr->arg_len)
                px = find_stktable(expr->arg.str);
@@ -2454,9 +2454,9 @@ acl_fetch_src_updt_conn_cnt(struct proxy *px, struct session *l4, void *l7, int
        struct stktable_key *key;
        void *ptr;
 
-       key = tcpv4_src_to_stktable_key(l4);
+       key = tcp_src_to_stktable_key(l4);
        if (!key)
-               return 0; /* only TCPv4 is supported right now */
+               return 0;
 
        if (expr->arg_len)
                px = find_stktable(expr->arg.str);
@@ -2524,9 +2524,9 @@ acl_fetch_src_conn_cur(struct proxy *px, struct session *l4, void *l7, int dir,
 {
        struct stktable_key *key;
 
-       key = tcpv4_src_to_stktable_key(l4);
+       key = tcp_src_to_stktable_key(l4);
        if (!key)
-               return 0; /* only TCPv4 is supported right now */
+               return 0;
 
        if (expr->arg_len)
                px = find_stktable(expr->arg.str);
@@ -2583,9 +2583,9 @@ acl_fetch_src_sess_cnt(struct proxy *px, struct session *l4, void *l7, int dir,
 {
        struct stktable_key *key;
 
-       key = tcpv4_src_to_stktable_key(l4);
+       key = tcp_src_to_stktable_key(l4);
        if (!key)
-               return 0; /* only TCPv4 is supported right now */
+               return 0;
 
        if (expr->arg_len)
                px = find_stktable(expr->arg.str);
@@ -2647,9 +2647,9 @@ acl_fetch_src_sess_rate(struct proxy *px, struct session *l4, void *l7, int dir,
 {
        struct stktable_key *key;
 
-       key = tcpv4_src_to_stktable_key(l4);
+       key = tcp_src_to_stktable_key(l4);
        if (!key)
-               return 0; /* only TCPv4 is supported right now */
+               return 0;
 
        if (expr->arg_len)
                px = find_stktable(expr->arg.str);
@@ -2706,9 +2706,9 @@ acl_fetch_src_http_req_cnt(struct proxy *px, struct session *l4, void *l7, int d
 {
        struct stktable_key *key;
 
-       key = tcpv4_src_to_stktable_key(l4);
+       key = tcp_src_to_stktable_key(l4);
        if (!key)
-               return 0; /* only TCPv4 is supported right now */
+               return 0;
 
        if (expr->arg_len)
                px = find_stktable(expr->arg.str);
@@ -2770,9 +2770,9 @@ acl_fetch_src_http_req_rate(struct proxy *px, struct session *l4, void *l7, int
 {
        struct stktable_key *key;
 
-       key = tcpv4_src_to_stktable_key(l4);
+       key = tcp_src_to_stktable_key(l4);
        if (!key)
-               return 0; /* only TCPv4 is supported right now */
+               return 0;
 
        if (expr->arg_len)
                px = find_stktable(expr->arg.str);
@@ -2829,9 +2829,9 @@ acl_fetch_src_http_err_cnt(struct proxy *px, struct session *l4, void *l7, int d
 {
        struct stktable_key *key;
 
-       key = tcpv4_src_to_stktable_key(l4);
+       key = tcp_src_to_stktable_key(l4);
        if (!key)
-               return 0; /* only TCPv4 is supported right now */
+               return 0;
 
        if (expr->arg_len)
                px = find_stktable(expr->arg.str);
@@ -2893,9 +2893,9 @@ acl_fetch_src_http_err_rate(struct proxy *px, struct session *l4, void *l7, int
 {
        struct stktable_key *key;
 
-       key = tcpv4_src_to_stktable_key(l4);
+       key = tcp_src_to_stktable_key(l4);
        if (!key)
-               return 0; /* only TCPv4 is supported right now */
+               return 0;
 
        if (expr->arg_len)
                px = find_stktable(expr->arg.str);
@@ -2957,9 +2957,9 @@ acl_fetch_src_kbytes_in(struct proxy *px, struct session *l4, void *l7, int dir,
 {
        struct stktable_key *key;
 
-       key = tcpv4_src_to_stktable_key(l4);
+       key = tcp_src_to_stktable_key(l4);
        if (!key)
-               return 0; /* only TCPv4 is supported right now */
+               return 0;
 
        if (expr->arg_len)
                px = find_stktable(expr->arg.str);
@@ -3023,9 +3023,9 @@ acl_fetch_src_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, int
 {
        struct stktable_key *key;
 
-       key = tcpv4_src_to_stktable_key(l4);
+       key = tcp_src_to_stktable_key(l4);
        if (!key)
-               return 0; /* only TCPv4 is supported right now */
+               return 0;
 
        if (expr->arg_len)
                px = find_stktable(expr->arg.str);
@@ -3087,9 +3087,9 @@ acl_fetch_src_kbytes_out(struct proxy *px, struct session *l4, void *l7, int dir
 {
        struct stktable_key *key;
 
-       key = tcpv4_src_to_stktable_key(l4);
+       key = tcp_src_to_stktable_key(l4);
        if (!key)
-               return 0; /* only TCPv4 is supported right now */
+               return 0;
 
        if (expr->arg_len)
                px = find_stktable(expr->arg.str);
@@ -3153,9 +3153,9 @@ acl_fetch_src_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, int
 {
        struct stktable_key *key;
 
-       key = tcpv4_src_to_stktable_key(l4);
+       key = tcp_src_to_stktable_key(l4);
        if (!key)
-               return 0; /* only TCPv4 is supported right now */
+               return 0;
 
        if (expr->arg_len)
                px = find_stktable(expr->arg.str);
index 0e5c71ea36731e4419b2449ab2f111b7308460db..d3b9ef714322035871dd1b0b0340367ece08d900 100644 (file)
@@ -1199,6 +1199,54 @@ unsigned int full_hash(unsigned int a)
        return __full_hash(a);
 }
 
+/* Return non-zero if IPv4 address is part of the network,
+ * otherwise zero.
+ */
+int in_net_ipv4(struct in_addr *addr, struct in_addr *mask, struct in_addr *net)
+{
+       return((addr->s_addr & mask->s_addr) == (net->s_addr & mask->s_addr));
+}
+
+/* Return non-zero if IPv6 address is part of the network,
+ * otherwise zero.
+ */
+int in_net_ipv6(struct in6_addr *addr, struct in6_addr *mask, struct in6_addr *net)
+{
+       int i;
+
+       for (i = 0; i < sizeof(struct in6_addr) / sizeof(int); i++)
+               if (((((int *)addr)[i] & ((int *)mask)[i])) !=
+                   (((int *)net)[i] & ((int *)mask)[i]))
+                       return 0;
+       return 1;
+}
+
+/* RFC 4291 prefix */
+const char rfc4291_pfx[] = { 0x00, 0x00, 0x00, 0x00,
+                            0x00, 0x00, 0x00, 0x00,
+                            0x00, 0x00, 0xFF, 0xFF };
+
+/* Map IPv4 adress on IPv6 address, as specified in RFC 3513. */
+void v4tov6(struct in6_addr *sin6_addr, struct in_addr *sin_addr)
+{
+       memcpy(sin6_addr->s6_addr, rfc4291_pfx, sizeof(rfc4291_pfx));
+       memcpy(sin6_addr->s6_addr+12, &sin_addr->s_addr, 4);
+}
+
+/* Map IPv6 adress on IPv4 address, as specified in RFC 3513.
+ * Return true if conversion is possible and false otherwise.
+ */
+int v6tov4(struct in_addr *sin_addr, struct in6_addr *sin6_addr)
+{
+       if (memcmp(sin6_addr->s6_addr, rfc4291_pfx, sizeof(rfc4291_pfx)) == 0) {
+               memcpy(&(sin_addr->s_addr), &(sin6_addr->s6_addr[12]),
+                       sizeof(struct in_addr));
+               return 1;
+       }
+
+       return 0;
+}
+
 /*
  * Local variables:
  *  c-indent-level: 8
index 7c9ad8da0dfadd135a7fa02c2ea57564c0d45d0b..5e9aa35718d18445699122c076cff0304e197d12 100644 (file)
@@ -406,9 +406,10 @@ int stktable_init(struct stktable *t)
  * Configuration keywords of known table types
  */
 struct stktable_type stktable_types[STKTABLE_TYPES] =  {{ "ip", 0, 4 },
+                                                       { "ipv6", 0, 16 },
                                                        { "integer", 0, 4 },
                                                        { "string", STK_F_CUSTOM_KEYSIZE, 32 },
-                                                       { "binary", STK_F_CUSTOM_KEYSIZE, 32 } };
+                                                       { "binary", STK_F_CUSTOM_KEYSIZE, 32 } };
 
 
 /*
@@ -457,6 +458,25 @@ static void *k_ip2ip(union pattern_data *pdata, union stktable_key_data *kdata,
        return (void *)&pdata->ip.s_addr;
 }
 
+static void *k_ip2ipv6(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len)
+{
+       v4tov6(&pdata->ipv6, &pdata->ip);
+       return (void *)&pdata->ipv6.s6_addr;
+}
+
+static void *k_ipv62ipv6(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len)
+{
+       return (void *)&pdata->ipv6.s6_addr;
+}
+
+/*
+static void *k_ipv62ip(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len)
+{
+       v6tov4(&pdata->ip, &pdata->ipv6);
+       return (void *)&pdata->ip.s_addr;
+}
+*/
+
 static void *k_ip2int(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len)
 {
        kdata->integer = ntohl(pdata->ip.s_addr);
@@ -484,6 +504,15 @@ static void *k_ip2str(union pattern_data *pdata, union stktable_key_data *kdata,
        return (void *)kdata->buf;
 }
 
+static void *k_ipv62str(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len)
+{
+       if (!inet_ntop(AF_INET6, &pdata->ipv6, kdata->buf, sizeof(kdata->buf)))
+               return NULL;
+
+       *len = strlen((const char *)kdata->buf);
+       return (void *)kdata->buf;
+}
+
 static void *k_int2str(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len)
 {
        void *key;
@@ -504,6 +533,13 @@ static void *k_str2ip(union pattern_data *pdata, union stktable_key_data *kdata,
        return (void *)&kdata->ip.s_addr;
 }
 
+static void *k_str2ipv6(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len)
+{
+       if (!inet_pton(AF_INET6, pdata->str.str, &kdata->ipv6))
+               return NULL;
+
+       return (void *)&kdata->ipv6.s6_addr;
+}
 
 static void *k_str2int(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len)
 {
@@ -527,15 +563,22 @@ static void *k_str2int(union pattern_data *pdata, union stktable_key_data *kdata
 /*         NULL pointer used for impossible pattern casts        */
 /*****************************************************************/
 
+/*
+ * Conversions from IPv6 to IPv4 are available, but we haven't
+ * added them to the table since they doesn't seem sufficely
+ * relevant and could cause confusion in configuration.
+ */
+
 typedef void *(*pattern_to_key_fct)(union pattern_data *pdata, union stktable_key_data *kdata, size_t *len);
 static pattern_to_key_fct pattern_to_key[PATTERN_TYPES][STKTABLE_TYPES] = {
-/*         table type:   IP        INTEGER    STRING     BINARY    */
-/* pattern type: IP */ { k_ip2ip,  k_ip2int,  k_ip2str,  NULL      },
-/*          INTEGER */ { k_int2ip, k_int2int, k_int2str, NULL      },
-/*           STRING */ { k_str2ip, k_str2int, k_str2str, k_str2str },
-/*             DATA */ { NULL,     NULL,      NULL,      k_str2str },
-/*      CONSTSTRING */ { k_str2ip, k_str2int, k_str2str, k_str2str },
-/*        CONSTDATA */ { NULL,     NULL,      NULL,      k_str2str },
+/*       table type:   IP          IPV6         INTEGER    STRING      BINARY    */
+/* pattern type: IP */ { k_ip2ip,  k_ip2ipv6,   k_ip2int,  k_ip2str,   NULL      },
+/*             IPV6 */ { NULL,     k_ipv62ipv6, NULL,      k_ipv62str, NULL      },
+/*          INTEGER */ { k_int2ip, NULL,        k_int2int, k_int2str,  NULL      },
+/*           STRING */ { k_str2ip, k_str2ipv6,  k_str2int, k_str2str,  k_str2str },
+/*             DATA */ { NULL,     NULL,        NULL,      NULL,       k_str2str },
+/*      CONSTSTRING */ { k_str2ip, k_str2ipv6,  k_str2int, k_str2str,  k_str2str },
+
 };