summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
author/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org </C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org>2008-03-25 14:34:24 +0000
committer/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org </C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org>2008-03-25 14:34:24 +0000
commitb935efce01e351b8fdfd8f3999e505d5e1fc6bf3 (patch)
tree66073b69fe77ec09543e3d04822326f7fb4aa69e
parent845dc5b01cefe918597061f3b0534fd2a7b4ee1d (diff)
This patch adds invmap support and duplicate code/id for reply direction,
so inserted conntracks get proper type, code and id. Without this fix "type", "code" and "id" in reply direction were always set to 0. It "automagically" worked for ICMP and ICMP_ECHOREPLY (ICMP_ECHOREPLY==8 -> ICMP_ECHO==*0*), but not with with other ICMP codes nor with ICMPv6. Signed-off-by: Krzysztof Oledzki <ole@ans.pl>
-rw-r--r--src/conntrack/setter.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/src/conntrack/setter.c b/src/conntrack/setter.c
index 5ba8e40..62be3e6 100644
--- a/src/conntrack/setter.c
+++ b/src/conntrack/setter.c
@@ -6,6 +6,26 @@
*/
#include "internal.h"
+#include <linux/icmp.h>
+#include <linux/icmpv6.h>
+
+static const u_int8_t invmap_icmp[] = {
+ [ICMP_ECHO] = ICMP_ECHOREPLY + 1,
+ [ICMP_ECHOREPLY] = ICMP_ECHO + 1,
+ [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1,
+ [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1,
+ [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1,
+ [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1,
+ [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1,
+ [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1
+};
+
+static u_int8_t invmap_icmpv6[] = {
+ [ICMPV6_ECHO_REQUEST - 128] = ICMPV6_ECHO_REPLY + 1,
+ [ICMPV6_ECHO_REPLY - 128] = ICMPV6_ECHO_REQUEST + 1,
+ [ICMPV6_NI_QUERY - 128] = ICMPV6_NI_QUERY + 1,
+ [ICMPV6_NI_REPLY - 128] = ICMPV6_NI_REPLY + 1
+};
static void set_attr_orig_ipv4_src(struct nf_conntrack *ct, const void *value)
{
@@ -69,17 +89,40 @@ static void set_attr_repl_port_dst(struct nf_conntrack *ct, const void *value)
static void set_attr_icmp_type(struct nf_conntrack *ct, const void *value)
{
+ u_int8_t rtype;
+
ct->tuple[__DIR_ORIG].l4dst.icmp.type = *((u_int8_t *) value);
+
+ switch(ct->tuple[__DIR_ORIG].l3protonum) {
+ case AF_INET:
+ rtype = invmap_icmp[*((u_int8_t *) value)];
+ break;
+
+ case AF_INET6:
+ rtype = invmap_icmpv6[*((u_int8_t *) value) - 128];
+ break;
+
+ default:
+ rtype = 0; /* not found */
+ }
+
+ if (rtype)
+ ct->tuple[__DIR_REPL].l4dst.icmp.type = rtype - 1;
+ else
+ ct->tuple[__DIR_REPL].l4dst.icmp.type = 255; /* will fail with -EINVAL */
+
}
static void set_attr_icmp_code(struct nf_conntrack *ct, const void *value)
{
ct->tuple[__DIR_ORIG].l4dst.icmp.code = *((u_int8_t *) value);
+ ct->tuple[__DIR_REPL].l4dst.icmp.code = *((u_int8_t *) value);
}
static void set_attr_icmp_id(struct nf_conntrack *ct, const void *value)
{
ct->tuple[__DIR_ORIG].l4src.icmp.id = *((u_int16_t *) value);
+ ct->tuple[__DIR_REPL].l4src.icmp.id = *((u_int16_t *) value);
}
static void set_attr_orig_l3proto(struct nf_conntrack *ct, const void *value)