summaryrefslogtreecommitdiff
path: root/net/netfilter
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-04-14 03:50:43 -0700
committerDavid S. Miller <davem@davemloft.net>2008-04-14 03:50:43 -0700
commit334f8b2afd9652e20f67ddee4fec483ed860425b (patch)
tree35d4fb46a9dc145e831fe5da026f2bfd9ee6657c /net/netfilter
parent7477fd2e6b676fcd15861c2a96a7172f71afe0a5 (diff)
parentef1a5a50bbd509b8697dcd4d13017e9e0053867b (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-2.6.26
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/Kconfig10
-rw-r--r--net/netfilter/Makefile1
-rw-r--r--net/netfilter/nf_conntrack_amanda.c6
-rw-r--r--net/netfilter/nf_conntrack_core.c29
-rw-r--r--net/netfilter/nf_conntrack_extend.c3
-rw-r--r--net/netfilter/nf_conntrack_ftp.c9
-rw-r--r--net/netfilter/nf_conntrack_h323_main.c65
-rw-r--r--net/netfilter/nf_conntrack_helper.c2
-rw-r--r--net/netfilter/nf_conntrack_irc.c14
-rw-r--r--net/netfilter/nf_conntrack_l3proto_generic.c12
-rw-r--r--net/netfilter/nf_conntrack_netlink.c34
-rw-r--r--net/netfilter/nf_conntrack_pptp.c8
-rw-r--r--net/netfilter/nf_conntrack_proto.c9
-rw-r--r--net/netfilter/nf_conntrack_proto_dccp.c815
-rw-r--r--net/netfilter/nf_conntrack_proto_generic.c20
-rw-r--r--net/netfilter/nf_conntrack_proto_gre.c31
-rw-r--r--net/netfilter/nf_conntrack_proto_sctp.c50
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c64
-rw-r--r--net/netfilter/nf_conntrack_proto_udp.c18
-rw-r--r--net/netfilter/nf_conntrack_proto_udplite.c55
-rw-r--r--net/netfilter/nf_conntrack_sane.c5
-rw-r--r--net/netfilter/nf_conntrack_sip.c21
-rw-r--r--net/netfilter/nf_conntrack_standalone.c131
-rw-r--r--net/netfilter/nf_conntrack_tftp.c10
-rw-r--r--net/netfilter/x_tables.c18
-rw-r--r--net/netfilter/xt_CONNSECMARK.c2
-rw-r--r--net/netfilter/xt_RATEEST.c2
-rw-r--r--net/netfilter/xt_connlimit.c10
-rw-r--r--net/netfilter/xt_conntrack.c4
-rw-r--r--net/netfilter/xt_dccp.c3
-rw-r--r--net/netfilter/xt_esp.c3
-rw-r--r--net/netfilter/xt_multiport.c6
-rw-r--r--net/netfilter/xt_policy.c2
-rw-r--r--net/netfilter/xt_rateest.c4
-rw-r--r--net/netfilter/xt_sctp.c6
-rw-r--r--net/netfilter/xt_tcpmss.c6
-rw-r--r--net/netfilter/xt_tcpudp.c9
-rw-r--r--net/netfilter/xt_time.c2
38 files changed, 1159 insertions, 340 deletions
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index daf5b881064..c1fc0f1a641 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -86,6 +86,16 @@ config NF_CONNTRACK_EVENTS
If unsure, say `N'.
+config NF_CT_PROTO_DCCP
+ tristate 'DCCP protocol connection tracking support (EXPERIMENTAL)'
+ depends on EXPERIMENTAL && NF_CONNTRACK
+ depends on NETFILTER_ADVANCED
+ help
+ With this option enabled, the layer 3 independent connection
+ tracking code will be able to do state tracking on DCCP connections.
+
+ If unsure, say 'N'.
+
config NF_CT_PROTO_GRE
tristate
depends on NF_CONNTRACK
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index ea7508387f9..5c4b183f642 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o
# SCTP protocol connection tracking
+obj-$(CONFIG_NF_CT_PROTO_DCCP) += nf_conntrack_proto_dccp.o
obj-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o
obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
obj-$(CONFIG_NF_CT_PROTO_UDPLITE) += nf_conntrack_proto_udplite.o
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c
index d14585a19b7..38aedeeaf4e 100644
--- a/net/netfilter/nf_conntrack_amanda.c
+++ b/net/netfilter/nf_conntrack_amanda.c
@@ -53,7 +53,7 @@ enum amanda_strings {
};
static struct {
- char *string;
+ const char *string;
size_t len;
struct ts_config *ts;
} search[] __read_mostly = {
@@ -91,7 +91,6 @@ static int amanda_help(struct sk_buff *skb,
char pbuf[sizeof("65535")], *tmp;
u_int16_t len;
__be16 port;
- int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
int ret = NF_ACCEPT;
typeof(nf_nat_amanda_hook) nf_nat_amanda;
@@ -148,7 +147,8 @@ static int amanda_help(struct sk_buff *skb,
goto out;
}
tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
- nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, family,
+ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
+ nf_ct_l3num(ct),
&tuple->src.u3, &tuple->dst.u3,
IPPROTO_TCP, NULL, &port);
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index b77eb56a87e..4eac65c74ed 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -94,7 +94,7 @@ static inline u_int32_t hash_conntrack(const struct nf_conntrack_tuple *tuple)
nf_conntrack_hash_rnd);
}
-int
+bool
nf_ct_get_tuple(const struct sk_buff *skb,
unsigned int nhoff,
unsigned int dataoff,
@@ -108,7 +108,7 @@ nf_ct_get_tuple(const struct sk_buff *skb,
tuple->src.l3num = l3num;
if (l3proto->pkt_to_tuple(skb, nhoff, tuple) == 0)
- return 0;
+ return false;
tuple->dst.protonum = protonum;
tuple->dst.dir = IP_CT_DIR_ORIGINAL;
@@ -117,10 +117,8 @@ nf_ct_get_tuple(const struct sk_buff *skb,
}
EXPORT_SYMBOL_GPL(nf_ct_get_tuple);
-int nf_ct_get_tuplepr(const struct sk_buff *skb,
- unsigned int nhoff,
- u_int16_t l3num,
- struct nf_conntrack_tuple *tuple)
+bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff,
+ u_int16_t l3num, struct nf_conntrack_tuple *tuple)
{
struct nf_conntrack_l3proto *l3proto;
struct nf_conntrack_l4proto *l4proto;
@@ -134,7 +132,7 @@ int nf_ct_get_tuplepr(const struct sk_buff *skb,
ret = l3proto->get_l4proto(skb, nhoff, &protoff, &protonum);
if (ret != NF_ACCEPT) {
rcu_read_unlock();
- return 0;
+ return false;
}
l4proto = __nf_ct_l4proto_find(l3num, protonum);
@@ -147,7 +145,7 @@ int nf_ct_get_tuplepr(const struct sk_buff *skb,
}
EXPORT_SYMBOL_GPL(nf_ct_get_tuplepr);
-int
+bool
nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig,
const struct nf_conntrack_l3proto *l3proto,
@@ -157,7 +155,7 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
inverse->src.l3num = orig->src.l3num;
if (l3proto->invert_tuple(inverse, orig) == 0)
- return 0;
+ return false;
inverse->dst.dir = !orig->dst.dir;
@@ -194,8 +192,7 @@ destroy_conntrack(struct nf_conntrack *nfct)
* destroy_conntrack() MUST NOT be called with a write lock
* to nf_conntrack_lock!!! -HW */
rcu_read_lock();
- l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num,
- ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
+ l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
if (l4proto && l4proto->destroy)
l4proto->destroy(ct);
@@ -739,10 +736,10 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff *skb)
}
EXPORT_SYMBOL_GPL(nf_conntrack_in);
-int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
- const struct nf_conntrack_tuple *orig)
+bool nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
+ const struct nf_conntrack_tuple *orig)
{
- int ret;
+ bool ret;
rcu_read_lock();
ret = nf_ct_invert_tuple(inverse, orig,
@@ -766,10 +763,10 @@ void nf_conntrack_alter_reply(struct nf_conn *ct,
NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
pr_debug("Altering reply tuple of %p to ", ct);
- NF_CT_DUMP_TUPLE(newreply);
+ nf_ct_dump_tuple(newreply);
ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
- if (ct->master || (help && help->expecting != 0))
+ if (ct->master || (help && !hlist_empty(&help->expectations)))
return;
rcu_read_lock();
diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c
index 2bd9963b5b3..bcc19fa4ed1 100644
--- a/net/netfilter/nf_conntrack_extend.c
+++ b/net/netfilter/nf_conntrack_extend.c
@@ -71,6 +71,9 @@ void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
int i, newlen, newoff;
struct nf_ct_ext_type *t;
+ /* Conntrack must not be confirmed to avoid races on reallocation. */
+ NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
+
if (!ct->ext)
return nf_ct_ext_create(&ct->ext, id, gfp);
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index 7eff876bb8b..bb20672fe03 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -350,8 +350,9 @@ static int help(struct sk_buff *skb,
enum ip_conntrack_info ctinfo)
{
unsigned int dataoff, datalen;
- struct tcphdr _tcph, *th;
- char *fb_ptr;
+ const struct tcphdr *th;
+ struct tcphdr _tcph;
+ const char *fb_ptr;
int ret;
u32 seq;
int dir = CTINFO2DIR(ctinfo);
@@ -405,7 +406,7 @@ static int help(struct sk_buff *skb,
/* Initialize IP/IPv6 addr to expected address (it's not mentioned
in EPSV responses) */
- cmd.l3num = ct->tuplehash[dir].tuple.src.l3num;
+ cmd.l3num = nf_ct_l3num(ct);
memcpy(cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all,
sizeof(cmd.u3.all));
@@ -452,7 +453,7 @@ static int help(struct sk_buff *skb,
daddr = &ct->tuplehash[!dir].tuple.dst.u3;
/* Update the ftp info */
- if ((cmd.l3num == ct->tuplehash[dir].tuple.src.l3num) &&
+ if ((cmd.l3num == nf_ct_l3num(ct)) &&
memcmp(&cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all,
sizeof(cmd.u3.all))) {
/* Enrico Scholz's passive FTP to partially RNAT'd ftp
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index 505052d495c..95da1a24aab 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -218,7 +218,6 @@ static int get_h245_addr(struct nf_conn *ct, const unsigned char *data,
union nf_inet_addr *addr, __be16 *port)
{
const unsigned char *p;
- int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
int len;
if (taddr->choice != eH245_TransportAddress_unicastAddress)
@@ -226,13 +225,13 @@ static int get_h245_addr(struct nf_conn *ct, const unsigned char *data,
switch (taddr->unicastAddress.choice) {
case eUnicastAddress_iPAddress:
- if (family != AF_INET)
+ if (nf_ct_l3num(ct) != AF_INET)
return 0;
p = data + taddr->unicastAddress.iPAddress.network;
len = 4;
break;
case eUnicastAddress_iP6Address:
- if (family != AF_INET6)
+ if (nf_ct_l3num(ct) != AF_INET6)
return 0;
p = data + taddr->unicastAddress.iP6Address.network;
len = 16;
@@ -277,8 +276,7 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
/* Create expect for RTP */
if ((rtp_exp = nf_ct_expect_alloc(ct)) == NULL)
return -1;
- nf_ct_expect_init(rtp_exp, NF_CT_EXPECT_CLASS_DEFAULT,
- ct->tuplehash[!dir].tuple.src.l3num,
+ nf_ct_expect_init(rtp_exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
&ct->tuplehash[!dir].tuple.src.u3,
&ct->tuplehash[!dir].tuple.dst.u3,
IPPROTO_UDP, NULL, &rtp_port);
@@ -288,8 +286,7 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
nf_ct_expect_put(rtp_exp);
return -1;
}
- nf_ct_expect_init(rtcp_exp, NF_CT_EXPECT_CLASS_DEFAULT,
- ct->tuplehash[!dir].tuple.src.l3num,
+ nf_ct_expect_init(rtcp_exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
&ct->tuplehash[!dir].tuple.src.u3,
&ct->tuplehash[!dir].tuple.dst.u3,
IPPROTO_UDP, NULL, &rtcp_port);
@@ -306,9 +303,9 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
if (nf_ct_expect_related(rtp_exp) == 0) {
if (nf_ct_expect_related(rtcp_exp) == 0) {
pr_debug("nf_ct_h323: expect RTP ");
- NF_CT_DUMP_TUPLE(&rtp_exp->tuple);
+ nf_ct_dump_tuple(&rtp_exp->tuple);
pr_debug("nf_ct_h323: expect RTCP ");
- NF_CT_DUMP_TUPLE(&rtcp_exp->tuple);
+ nf_ct_dump_tuple(&rtcp_exp->tuple);
} else {
nf_ct_unexpect_related(rtp_exp);
ret = -1;
@@ -346,8 +343,7 @@ static int expect_t120(struct sk_buff *skb,
/* Create expect for T.120 connections */
if ((exp = nf_ct_expect_alloc(ct)) == NULL)
return -1;
- nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
- ct->tuplehash[!dir].tuple.src.l3num,
+ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
&ct->tuplehash[!dir].tuple.src.u3,
&ct->tuplehash[!dir].tuple.dst.u3,
IPPROTO_TCP, NULL, &port);
@@ -364,7 +360,7 @@ static int expect_t120(struct sk_buff *skb,
} else { /* Conntrack only */
if (nf_ct_expect_related(exp) == 0) {
pr_debug("nf_ct_h323: expect T.120 ");
- NF_CT_DUMP_TUPLE(&exp->tuple);
+ nf_ct_dump_tuple(&exp->tuple);
} else
ret = -1;
}
@@ -586,7 +582,7 @@ static int h245_help(struct sk_buff *skb, unsigned int protoff,
while (get_tpkt_data(skb, protoff, ct, ctinfo,
&data, &datalen, &dataoff)) {
pr_debug("nf_ct_h245: TPKT len=%d ", datalen);
- NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
+ nf_ct_dump_tuple(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
/* Decode H.245 signal */
ret = DecodeMultimediaSystemControlMessage(data, datalen,
@@ -634,18 +630,17 @@ int get_h225_addr(struct nf_conn *ct, unsigned char *data,
union nf_inet_addr *addr, __be16 *port)
{
const unsigned char *p;
- int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
int len;
switch (taddr->choice) {
case eTransportAddress_ipAddress:
- if (family != AF_INET)
+ if (nf_ct_l3num(ct) != AF_INET)
return 0;
p = data + taddr->ipAddress.ip;
len = 4;
break;
case eTransportAddress_ip6Address:
- if (family != AF_INET6)
+ if (nf_ct_l3num(ct) != AF_INET6)
return 0;
p = data + taddr->ip6Address.ip;
len = 16;
@@ -683,8 +678,7 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
/* Create expect for h245 connection */
if ((exp = nf_ct_expect_alloc(ct)) == NULL)
return -1;
- nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
- ct->tuplehash[!dir].tuple.src.l3num,
+ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
&ct->tuplehash[!dir].tuple.src.u3,
&ct->tuplehash[!dir].tuple.dst.u3,
IPPROTO_TCP, NULL, &port);
@@ -701,7 +695,7 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
} else { /* Conntrack only */
if (nf_ct_expect_related(exp) == 0) {
pr_debug("nf_ct_q931: expect H.245 ");
- NF_CT_DUMP_TUPLE(&exp->tuple);
+ nf_ct_dump_tuple(&exp->tuple);
} else
ret = -1;
}
@@ -792,7 +786,7 @@ static int expect_callforwarding(struct sk_buff *skb,
* we don't need to track the second call */
if (callforward_filter &&
callforward_do_filter(&addr, &ct->tuplehash[!dir].tuple.src.u3,
- ct->tuplehash[!dir].tuple.src.l3num)) {
+ nf_ct_l3num(ct))) {
pr_debug("nf_ct_q931: Call Forwarding not tracked\n");
return 0;
}
@@ -800,8 +794,7 @@ static int expect_callforwarding(struct sk_buff *skb,
/* Create expect for the second call leg */
if ((exp = nf_ct_expect_alloc(ct)) == NULL)
return -1;
- nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
- ct->tuplehash[!dir].tuple.src.l3num,
+ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
&ct->tuplehash[!dir].tuple.src.u3, &addr,
IPPROTO_TCP, NULL, &port);
exp->helper = nf_conntrack_helper_q931;
@@ -817,7 +810,7 @@ static int expect_callforwarding(struct sk_buff *skb,
} else { /* Conntrack only */
if (nf_ct_expect_related(exp) == 0) {
pr_debug("nf_ct_q931: expect Call Forwarding ");
- NF_CT_DUMP_TUPLE(&exp->tuple);
+ nf_ct_dump_tuple(&exp->tuple);
} else
ret = -1;
}
@@ -1137,7 +1130,7 @@ static int q931_help(struct sk_buff *skb, unsigned int protoff,
while (get_tpkt_data(skb, protoff, ct, ctinfo,
&data, &datalen, &dataoff)) {
pr_debug("nf_ct_q931: TPKT len=%d ", datalen);
- NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
+ nf_ct_dump_tuple(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
/* Decode Q.931 signal */
ret = DecodeQ931(data, datalen, &q931);
@@ -1272,8 +1265,7 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
/* Create expect for Q.931 */
if ((exp = nf_ct_expect_alloc(ct)) == NULL)
return -1;
- nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
- ct->tuplehash[!dir].tuple.src.l3num,
+ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
gkrouted_only ? /* only accept calls from GK? */
&ct->tuplehash[!dir].tuple.src.u3 : NULL,
&ct->tuplehash[!dir].tuple.dst.u3,
@@ -1287,7 +1279,7 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
} else { /* Conntrack only */
if (nf_ct_expect_related(exp) == 0) {
pr_debug("nf_ct_ras: expect Q.931 ");
- NF_CT_DUMP_TUPLE(&exp->tuple);
+ nf_ct_dump_tuple(&exp->tuple);
/* Save port for looking up expect in processing RCF */
info->sig_port[dir] = port;
@@ -1344,15 +1336,14 @@ static int process_gcf(struct sk_buff *skb, struct nf_conn *ct,
/* Need new expect */
if ((exp = nf_ct_expect_alloc(ct)) == NULL)
return -1;
- nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
- ct->tuplehash[!dir].tuple.src.l3num,
+ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
&ct->tuplehash[!dir].tuple.src.u3, &addr,
IPPROTO_UDP, NULL, &port);
exp->helper = nf_conntrack_helper_ras;
if (nf_ct_expect_related(exp) == 0) {
pr_debug("nf_ct_ras: expect RAS ");
- NF_CT_DUMP_TUPLE(&exp->tuple);
+ nf_ct_dump_tuple(&exp->tuple);
} else
ret = -1;
@@ -1436,7 +1427,7 @@ static int process_rcf(struct sk_buff *skb, struct nf_conn *ct,
pr_debug("nf_ct_ras: set Q.931 expect "
"timeout to %u seconds for",
info->timeout);
- NF_CT_DUMP_TUPLE(&exp->tuple);
+ nf_ct_dump_tuple(&exp->tuple);
set_expect_timeout(exp, info->timeout);
}
spin_unlock_bh(&nf_conntrack_lock);
@@ -1549,8 +1540,7 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
/* Need new expect */
if ((exp = nf_ct_expect_alloc(ct)) == NULL)
return -1;
- nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
- ct->tuplehash[!dir].tuple.src.l3num,
+ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
&ct->tuplehash[!dir].tuple.src.u3, &addr,
IPPROTO_TCP, NULL, &port);
exp->flags = NF_CT_EXPECT_PERMANENT;
@@ -1558,7 +1548,7 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
if (nf_ct_expect_related(exp) == 0) {
pr_debug("nf_ct_ras: expect Q.931 ");
- NF_CT_DUMP_TUPLE(&exp->tuple);
+ nf_ct_dump_tuple(&exp->tuple);
} else
ret = -1;
@@ -1603,8 +1593,7 @@ static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,
/* Need new expect for call signal */
if ((exp = nf_ct_expect_alloc(ct)) == NULL)
return -1;
- nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
- ct->tuplehash[!dir].tuple.src.l3num,
+ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
&ct->tuplehash[!dir].tuple.src.u3, &addr,
IPPROTO_TCP, NULL, &port);
exp->flags = NF_CT_EXPECT_PERMANENT;
@@ -1612,7 +1601,7 @@ static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,
if (nf_ct_expect_related(exp) == 0) {
pr_debug("nf_ct_ras: expect Q.931 ");
- NF_CT_DUMP_TUPLE(&exp->tuple);
+ nf_ct_dump_tuple(&exp->tuple);
} else
ret = -1;
@@ -1716,7 +1705,7 @@ static int ras_help(struct sk_buff *skb, unsigned int protoff,
if (data == NULL)
goto accept;
pr_debug("nf_ct_ras: RAS message len=%d ", datalen);
- NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
+ nf_ct_dump_tuple(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
/* Decode RAS message */
ret = DecodeRasMessage(data, datalen, &ras);
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index e350f56d43c..7d1b1170374 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -126,7 +126,7 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
{
struct nf_conntrack_tuple_hash *h;
struct nf_conntrack_expect *exp;
- struct hlist_node *n, *next;
+ const struct hlist_node *n, *next;
unsigned int i;
mutex_lock(&nf_ct_helper_mutex);
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
index 02f21cbe5ae..1b1226d6653 100644
--- a/net/netfilter/nf_conntrack_irc.c
+++ b/net/netfilter/nf_conntrack_irc.c
@@ -50,7 +50,7 @@ MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per "
module_param(dcc_timeout, uint, 0400);
MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels");
-static const char *dccprotos[] = {
+static const char *const dccprotos[] = {
"SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT "
};
@@ -65,7 +65,7 @@ static const char *dccprotos[] = {
* ad_beg_p returns pointer to first byte of addr data
* ad_end_p returns pointer to last byte of addr data
*/
-static int parse_dcc(char *data, char *data_end, u_int32_t *ip,
+static int parse_dcc(char *data, const char *data_end, u_int32_t *ip,
u_int16_t *port, char **ad_beg_p, char **ad_end_p)
{
/* at least 12: "AAAAAAAA P\1\n" */
@@ -93,9 +93,11 @@ static int help(struct sk_buff *skb, unsigned int protoff,
struct nf_conn *ct, enum ip_conntrack_info ctinfo)
{
unsigned int dataoff;
- struct iphdr *iph;
- struct tcphdr _tcph, *th;
- char *data, *data_limit, *ib_ptr;
+ const struct iphdr *iph;
+ const struct tcphdr *th;
+ struct tcphdr _tcph;
+ const char *data_limit;
+ char *data, *ib_ptr;
int dir = CTINFO2DIR(ctinfo);
struct nf_conntrack_expect *exp;
struct nf_conntrack_tuple *tuple;
@@ -159,7 +161,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
/* we have at least
* (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid
* data left (== 14/13 bytes) */
- if (parse_dcc((char *)data, data_limit, &dcc_ip,
+ if (parse_dcc(data, data_limit, &dcc_ip,
&dcc_port, &addr_beg_p, &addr_end_p)) {
pr_debug("unable to parse dcc command\n");
continue;
diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c
index 8e914e5ffea..e7eb807fe07 100644
--- a/net/netfilter/nf_conntrack_l3proto_generic.c
+++ b/net/netfilter/nf_conntrack_l3proto_generic.c
@@ -31,22 +31,22 @@
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
-static int generic_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
- struct nf_conntrack_tuple *tuple)
+static bool generic_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
+ struct nf_conntrack_tuple *tuple)
{
memset(&tuple->src.u3, 0, sizeof(tuple->src.u3));
memset(&tuple->dst.u3, 0, sizeof(tuple->dst.u3));
- return 1;
+ return true;
}
-static int generic_invert_tuple(struct nf_conntrack_tuple *tuple,
- const struct nf_conntrack_tuple *orig)
+static bool generic_invert_tuple(struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_tuple *orig)
{
memset(&tuple->src.u3, 0, sizeof(tuple->src.u3));
memset(&tuple->dst.u3, 0, sizeof(tuple->dst.u3));
- return 1;
+ return true;
}
static int generic_print_tuple(struct seq_file *s,
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 4a1b42b2b7a..16774ecd1c4 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -145,10 +145,11 @@ nla_put_failure:
static inline int
ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct nf_conn *ct)
{
- struct nf_conntrack_l4proto *l4proto = nf_ct_l4proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
+ struct nf_conntrack_l4proto *l4proto;
struct nlattr *nest_proto;
int ret;
+ l4proto = nf_ct_l4proto_find_get(nf_ct_l3num(ct), nf_ct_protonum(ct));
if (!l4proto->to_nlattr) {
nf_ct_l4proto_put(l4proto);
return 0;
@@ -368,8 +369,7 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
nfmsg = NLMSG_DATA(nlh);
nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;
- nfmsg->nfgen_family =
- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ nfmsg->nfgen_family = nf_ct_l3num(ct);
nfmsg->version = NFNETLINK_V0;
nfmsg->res_id = 0;
@@ -454,7 +454,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
nfmsg = NLMSG_DATA(nlh);
nlh->nlmsg_flags = flags;
- nfmsg->nfgen_family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ nfmsg->nfgen_family = nf_ct_l3num(ct);
nfmsg->version = NFNETLINK_V0;
nfmsg->res_id = 0;
@@ -535,8 +535,6 @@ static int ctnetlink_done(struct netlink_callback *cb)
return 0;
}
-#define L3PROTO(ct) (ct)->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num
-
static int
ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
{
@@ -558,7 +556,7 @@ restart:
/* Dump entries of a given L3 protocol number.
* If it is not specified, ie. l3proto == 0,
* then dump everything. */
- if (l3proto && L3PROTO(ct) != l3proto)
+ if (l3proto && nf_ct_l3num(ct) != l3proto)
continue;
if (cb->args[1]) {
if (ct != last)
@@ -704,20 +702,11 @@ static int nfnetlink_parse_nat_proto(struct nlattr *attr,
if (err < 0)
return err;
- npt = nf_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
-
- if (!npt->nlattr_to_range) {
- nf_nat_proto_put(npt);
- return 0;
- }
-
- /* nlattr_to_range returns 1 if it parsed, 0 if not, neg. on error */
- if (npt->nlattr_to_range(tb, range) > 0)
- range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
-
+ npt = nf_nat_proto_find_get(nf_ct_protonum(ct));
+ if (npt->nlattr_to_range)
+ err = npt->nlattr_to_range(tb, range);
nf_nat_proto_put(npt);
-
- return 0;
+ return err;
}
static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = {
@@ -1010,14 +999,11 @@ ctnetlink_change_protoinfo(struct nf_conn *ct, struct nlattr *cda[])
{
struct nlattr *tb[CTA_PROTOINFO_MAX+1], *attr = cda[CTA_PROTOINFO];
struct nf_conntrack_l4proto *l4proto;
- u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
- u_int16_t l3num = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
int err = 0;
nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, NULL);
- l4proto = nf_ct_l4proto_find_get(l3num, npt);
-
+ l4proto = nf_ct_l4proto_find_get(nf_ct_l3num(ct), nf_ct_protonum(ct));
if (l4proto->from_nlattr)
err = l4proto->from_nlattr(tb, ct);
nf_ct_l4proto_put(l4proto);
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index 8fd83470d1b..97e54b0e43a 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -119,7 +119,7 @@ static void pptp_expectfn(struct nf_conn *ct,
/* obviously this tuple inversion only works until you do NAT */
nf_ct_invert_tuplepr(&inv_t, &exp->tuple);
pr_debug("trying to unexpect other dir: ");
- NF_CT_DUMP_TUPLE(&inv_t);
+ nf_ct_dump_tuple(&inv_t);
exp_other = nf_ct_expect_find_get(&inv_t);
if (exp_other) {
@@ -141,7 +141,7 @@ static int destroy_sibling_or_exp(const struct nf_conntrack_tuple *t)
struct nf_conn *sibling;
pr_debug("trying to timeout ct or exp for tuple ");
- NF_CT_DUMP_TUPLE(t);
+ nf_ct_dump_tuple(t);
h = nf_conntrack_find_get(t);
if (h) {
@@ -209,7 +209,7 @@ static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid)
/* original direction, PNS->PAC */
dir = IP_CT_DIR_ORIGINAL;
nf_ct_expect_init(exp_orig, NF_CT_EXPECT_CLASS_DEFAULT,
- ct->tuplehash[dir].tuple.src.l3num,
+ nf_ct_l3num(ct),
&ct->tuplehash[dir].tuple.src.u3,
&ct->tuplehash[dir].tuple.dst.u3,
IPPROTO_GRE, &peer_callid, &callid);
@@ -218,7 +218,7 @@ static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid)
/* reply direction, PAC->PNS */
dir = IP_CT_DIR_REPLY;
nf_ct_expect_init(exp_reply, NF_CT_EXPECT_CLASS_DEFAULT,
- ct->tuplehash[dir].tuple.src.l3num,
+ nf_ct_l3num(ct),
&ct->tuplehash[dir].tuple.src.u3,
&ct->tuplehash[dir].tuple.dst.u3,
IPPROTO_GRE, &callid, &peer_callid);
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index 8595b5946ac..a49fc932629 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -146,18 +146,15 @@ EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put);
static int kill_l3proto(struct nf_conn *i, void *data)
{
- return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num ==
- ((struct nf_conntrack_l3proto *)data)->l3proto);
+ return nf_ct_l3num(i) == ((struct nf_conntrack_l3proto *)data)->l3proto;
}
static int kill_l4proto(struct nf_conn *i, void *data)
{
struct nf_conntrack_l4proto *l4proto;
l4proto = (struct nf_conntrack_l4proto *)data;
- return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
- l4proto->l4proto) &&
- (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num ==
- l4proto->l3proto);
+ return nf_ct_protonum(i) == l4proto->l4proto &&
+ nf_ct_l3num(i) == l4proto->l3proto;
}
static int nf_ct_l3proto_register_sysctl(struct nf_conntrack_l3proto *l3proto)
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c
new file mode 100644
index 00000000000..afb4a1861d2
--- /dev/null
+++ b/net/netfilter/nf_conntrack_proto_dccp.c
@@ -0,0 +1,815 @@
+/*
+ * DCCP connection tracking protocol helper
+ *
+ * Copyright (c) 2005, 2006, 2008 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sysctl.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.h>
+#include <linux/dccp.h>
+
+#include <linux/netfilter/nfnetlink_conntrack.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_log.h>
+
+static DEFINE_RWLOCK(dccp_lock);
+
+static int nf_ct_dccp_loose __read_mostly = 1;
+
+/* Timeouts are based on values from RFC4340:
+ *
+ * - REQUEST:
+ *
+ * 8.1.2. Client Request
+ *
+ * A client MAY give up on its DCCP-Requests after some time
+ * (3 minutes, for example).
+ *
+ * - RESPOND:
+ *
+ * 8.1.3. Server Response
+ *
+ * It MAY also leave the RESPOND state for CLOSED after a timeout of
+ * not less than 4MSL (8 minutes);
+ *
+ * - PARTOPEN:
+ *
+ * 8.1.5. Handshake Completion
+ *
+ * If the client remains in PARTOPEN for more than 4MSL (8 minutes),
+ * it SHOULD reset the connection with Reset Code 2, "Aborted".
+ *
+ * - OPEN:
+ *
+ * The DCCP timestamp overflows after 11.9 hours. If the connection
+ * stays idle this long the sequence number won't be recognized
+ * as valid anymore.
+ *
+ * - CLOSEREQ/CLOSING:
+ *
+ * 8.3. Termination
+ *
+ * The retransmission timer should initially be set to go off in two
+ * round-trip times and should back off to not less than once every
+ * 64 seconds ...
+ *
+ * - TIMEWAIT:
+ *
+ * 4.3. States
+ *
+ * A server or client socket remains in this state for 2MSL (4 minutes)
+ * after the connection has been town down, ...
+ */
+
+#define DCCP_MSL (2 * 60 * HZ)
+
+static unsigned int dccp_timeout[CT_DCCP_MAX + 1] __read_mostly = {
+ [CT_DCCP_REQUEST] = 2 * DCCP_MSL,
+ [CT_DCCP_RESPOND] = 4 * DCCP_MSL,
+ [CT_DCCP_PARTOPEN] = 4 * DCCP_MSL,
+ [CT_DCCP_OPEN] = 12 * 3600 * HZ,
+ [CT_DCCP_CLOSEREQ] = 64 * HZ,
+ [CT_DCCP_CLOSING] = 64 * HZ,
+ [CT_DCCP_TIMEWAIT] = 2 * DCCP_MSL,
+};
+
+static const char * const dccp_state_names[] = {
+ [CT_DCCP_NONE] = "NONE",
+ [CT_DCCP_REQUEST] = "REQUEST",
+ [CT_DCCP_RESPOND] = "RESPOND",
+ [CT_DCCP_PARTOPEN] = "PARTOPEN",
+ [CT_DCCP_OPEN] = "OPEN",
+ [CT_DCCP_CLOSEREQ] = "CLOSEREQ",
+ [CT_DCCP_CLOSING] = "CLOSING",
+ [CT_DCCP_TIMEWAIT] = "TIMEWAIT",
+ [CT_DCCP_IGNORE] = "IGNORE",
+ [CT_DCCP_INVALID] = "INVALID",
+};
+
+#define sNO CT_DCCP_NONE
+#define sRQ CT_DCCP_REQUEST
+#define sRS CT_DCCP_RESPOND
+#define sPO CT_DCCP_PARTOPEN
+#define sOP CT_DCCP_OPEN
+#define sCR CT_DCCP_CLOSEREQ
+#define sCG CT_DCCP_CLOSING
+#define sTW CT_DCCP_TIMEWAIT
+#define sIG CT_DCCP_IGNORE
+#define sIV CT_DCCP_INVALID
+
+/*
+ * DCCP state transistion table
+ *
+ * The assumption is the same as for TCP tracking:
+ *
+ * We are the man in the middle. All the packets go through us but might
+ * get lost in transit to the destination. It is assumed that the destination
+ * can't receive segments we haven't seen.
+ *
+ * The following states exist:
+ *
+ * NONE: Initial state, expecting Request
+ * REQUEST: Request seen, waiting for Response from server
+ * RESPOND: Response from server seen, waiting for Ack from client
+ * PARTOPEN: Ack after Response seen, waiting for packet other than Response,
+ * Reset or Sync from server
+ * OPEN: Packet other than Response, Reset or Sync seen
+ * CLOSEREQ: CloseReq from server seen, expecting Close from client
+ * CLOSING: Close seen, expecting Reset
+ * TIMEWAIT: Reset seen
+ * IGNORE: Not determinable whether packet is valid
+ *
+ * Some states exist only on one side of the connection: REQUEST, RESPOND,
+ * PARTOPEN, CLOSEREQ. For the other side these states are equivalent to
+ * the one it was in before.
+ *
+ * Packets are marked as ignored (sIG) if we don't know if they're valid
+ * (for example a reincarnation of a connection we didn't notice is dead
+ * already) and the server may send back a connection closing Reset or a
+ * Response. They're also used for Sync/SyncAck packets, which we don't
+ * care about.
+ */
+static const u_int8_t
+dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] = {
+ [CT_DCCP_ROLE_CLIENT] = {
+ [DCCP_PKT_REQUEST] = {
+ /*
+ * sNO -> sRQ Regular Request
+ * sRQ -> sRQ Retransmitted Request or reincarnation
+ * sRS -> sRS Retransmitted Request (apparently Response
+ * got lost after we saw it) or reincarnation
+ * sPO -> sIG Ignore, conntrack might be out of sync
+ * sOP -> sIG Ignore, conntrack might be out of sync
+ * sCR -> sIG Ignore, conntrack might be out of sync
+ * sCG -> sIG Ignore, conntrack might be out of sync
+ * sTW -> sRQ Reincarnation
+ *
+ * sNO, sRQ, sRS, sPO. sOP, sCR, sCG, sTW, */
+ sRQ, sRQ, sRS, sIG, sIG, sIG, sIG, sRQ,
+ },
+ [DCCP_PKT_RESPONSE] = {
+ /*
+ * sNO -> sIV Invalid
+ * sRQ -> sIG Ignore, might be response to ignored Request
+ * sRS -> sIG Ignore, might be response to ignored Request
+ * sPO -> sIG Ignore, might be response to ignored Request
+ * sOP -> sIG Ignore, might be response to ignored Request
+ * sCR -> sIG Ignore, might be response to ignored Request
+ * sCG -> sIG Ignore, might be response to ignored Request
+ * sTW -> sIV Invalid, reincarnation in reverse direction
+ * goes through sRQ
+ *
+ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
+ sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIV,
+ },
+ [DCCP_PKT_ACK] = {
+ /*
+ * sNO -> sIV No connection
+ * sRQ -> sIV No connection
+ * sRS -> sPO Ack for Response, move to PARTOPEN (8.1.5.)
+ * sPO -> sPO Retransmitted Ack for Response, remain in PARTOPEN
+ * sOP -> sOP Regular ACK, remain in OPEN
+ * sCR -> sCR Ack in CLOSEREQ MAY be processed (8.3.)
+ * sCG -> sCG Ack in CLOSING MAY be processed (8.3.)
+ * sTW -> sIV
+ *
+ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
+ sIV, sIV, sPO, sPO, sOP, sCR, sCG, sIV
+ },
+ [DCCP_PKT_DATA] = {
+ /*
+ * sNO -> sIV No connection
+ * sRQ -> sIV No connection
+ * sRS -> sIV No connection
+ * sPO -> sIV MUST use DataAck in PARTOPEN state (8.1.5.)
+ * sOP -> sOP Regular Data packet
+ * sCR -> sCR Data in CLOSEREQ MAY be processed (8.3.)
+ * sCG -> sCG Data in CLOSING MAY be processed (8.3.)
+ * sTW -> sIV
+ *
+ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
+ sIV, sIV, sIV, sIV, sOP, sCR, sCG, sIV,
+ },
+ [DCCP_PKT_DATAACK] = {
+ /*
+ * sNO -> sIV No connection
+ * sRQ -> sIV No connection
+ * sRS -> sPO Ack for Response, move to PARTOPEN (8.1.5.)
+ * sPO -> sPO Remain in PARTOPEN state
+ * sOP -> sOP Regular DataAck packet in OPEN state
+ * sCR -> sCR DataAck in CLOSEREQ MAY be processed (8.3.)
+ * sCG -> sCG DataAck in CLOSING MAY be processed (8.3.)
+ * sTW -> sIV
+ *
+ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
+ sIV, sIV, sPO, sPO, sOP, sCR, sCG, sIV
+ },
+ [DCCP_PKT_CLOSEREQ] = {
+ /*
+ * CLOSEREQ may only be sent by the server.
+ *
+ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
+ sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV
+ },
+ [DCCP_PKT_CLOSE] = {
+ /*
+ * sNO -> sIV No connection
+ * sRQ -> sIV No connection
+ * sRS -> sIV No connection
+ * sPO -> sCG Client-initiated close
+ * sOP -> sCG Client-initiated close
+ * sCR -> sCG Close in response to CloseReq (8.3.)
+ * sCG -> sCG Retransmit
+ * sTW -> sIV Late retransmit, already in TIME_WAIT
+ *
+ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
+ sIV, sIV, sIV, sCG, sCG, sCG, sIV, sIV
+ },
+ [DCCP_PKT_RESET] = {
+ /*
+ * sNO -> sIV No connection
+ * sRQ -> sTW Sync received or timeout, SHOULD send Reset (8.1.1.)
+ * sRS -> sTW Response received without Request
+ * sPO -> sTW Timeout, SHOULD send Reset (8.1.5.)
+ * sOP -> sTW Connection reset
+ * sCR -> sTW Connection reset
+ * sCG -> sTW Connection reset
+ * sTW -> sIG Ignore (don't refresh timer)
+ *
+ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
+ sIV, sTW, sTW, sTW, sTW, sTW, sTW, sIG
+ },
+ [DCCP_PKT_SYNC] = {
+ /*
+ * We currently ignore Sync packets
+ *
+ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
+ sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG,
+ },
+ [DCCP_PKT_SYNCACK] = {
+ /*
+ * We currently ignore SyncAck packets
+ *
+ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
+ sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG,
+ },
+ },
+ [CT_DCCP_ROLE_SERVER] = {
+ [DCCP_PKT_REQUEST] = {
+ /*
+ * sNO -> sIV Invalid
+ * sRQ -> sIG Ignore, conntrack might be out of sync
+ * sRS -> sIG Ignore, conntrack might be out of sync
+ * sPO -> sIG Ignore, conntrack might be out of sync
+ * sOP -> sIG Ignore, conntrack might be out of sync
+ * sCR -> sIG Ignore, conntrack might be out of sync
+ * sCG -> sIG Ignore, conntrack might be out of sync
+ * sTW -> sRQ Reincarnation, must reverse roles
+ *
+ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
+ sIV, sIG, sIG, sIG, sIG, sIG, sIG, sRQ
+ },
+ [DCCP_PKT_RESPONSE] = {
+ /*
+ * sNO -> sIV Response without Request
+ * sRQ -> sRS Response to clients Request
+ * sRS -> sRS Retransmitted Response (8.1.3. SHOULD NOT)
+ * sPO -> sIG Response to an ignored Request or late retransmit
+ * sOP -> sIG Ignore, might be response to ignored Request
+ * sCR -> sIG Ignore, might be response to ignored Request
+ * sCG -> sIG Ignore, might be response to ignored Request
+ * sTW -> sIV Invalid, Request from client in sTW moves to sRQ
+ *
+ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
+ sIV, sRS, sRS, sIG, sIG, sIG, sIG, sIV
+ },
+ [DCCP_PKT_ACK] = {
+ /*
+ * sNO -> sIV No connection
+ * sRQ -> sIV No connection
+ * sRS -> sIV No connection
+ * sPO -> sOP Enter OPEN state (8.1.5.)
+ * sOP -> sOP Regular Ack in OPEN state
+ * sCR -> sIV Waiting for Close from client
+ * sCG -> sCG Ack in CLOSING MAY be processed (8.3.)
+ * sTW -> sIV
+ *
+ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
+ sIV, sIV, sIV, sOP, sOP, sIV, sCG, sIV
+ },
+ [DCCP_PKT_DATA] = {
+ /*
+ * sNO -> sIV No connection
+ * sRQ -> sIV No connection
+ * sRS -> sIV No connection
+ * sPO -> sOP Enter OPEN state (8.1.5.)
+ * sOP -> sOP Regular Data packet in OPEN state
+ * sCR -> sIV Waiting for Close from client
+ * sCG -> sCG Data in CLOSING MAY be processed (8.3.)
+ * sTW -> sIV
+ *
+ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
+ sIV, sIV, sIV, sOP, sOP, sIV, sCG, sIV
+ },
+ [DCCP_PKT_DATAACK] = {
+ /*
+ * sNO -> sIV No connection
+ * sRQ -> sIV No connection
+ * sRS -> sIV No connection
+ * sPO -> sOP Enter OPEN state (8.1.5.)
+ * sOP -> sOP Regular DataAck in OPEN state
+ * sCR -> sIV Waiting for Close from client
+ * sCG -> sCG Data in CLOSING MAY be processed (8.3.)
+ * sTW -> sIV
+ *
+ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
+ sIV, sIV, sIV, sOP, sOP, sIV, sCG, sIV
+ },
+ [DCCP_PKT_CLOSEREQ] = {
+ /*
+ * sNO -> sIV No connection
+ * sRQ -> sIV No connection
+ * sRS -> sIV No connection
+ * sPO -> sOP -> sCR Move directly to CLOSEREQ (8.1.5.)
+ * sOP -> sCR CloseReq in OPEN state
+ * sCR -> sCR Retransmit
+ * sCG -> sCR Simultaneous close, client sends another Close
+ * sTW -> sIV Already closed
+ *
+ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
+ sIV, sIV, sIV, sCR, sCR, sCR, sCR, sIV
+ },
+ [DCCP_PKT_CLOSE] = {
+ /*
+ * sNO -> sIV No connection
+ * sRQ -> sIV No connection
+ * sRS -> sIV No connection
+ * sPO -> sOP -> sCG Move direcly to CLOSING
+ * sOP -> sCG Move to CLOSING
+ * sCR -> sIV Close after CloseReq is invalid
+ * sCG -> sCG Retransmit
+ * sTW -> sIV Already closed
+ *
+ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
+ sIV, sIV, sIV, sCG, sCG, sIV, sCG, sIV
+ },
+ [DCCP_PKT_RESET] = {
+ /*
+ * sNO -> sIV No connection
+ * sRQ -> sTW Reset in response to Request
+ * sRS -> sTW Timeout, SHOULD send Reset (8.1.3.)
+ * sPO -> sTW Timeout, SHOULD send Reset (8.1.3.)
+ * sOP -> sTW
+ * sCR -> sTW
+ * sCG -> sTW
+ * sTW -> sIG Ignore (don't refresh timer)
+ *
+ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW, sTW */
+ sIV, sTW, sTW, sTW, sTW, sTW, sTW, sTW, sIG
+ },
+ [DCCP_PKT_SYNC] = {
+ /*
+ * We currently ignore Sync packets
+ *
+ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
+ sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG,
+ },
+ [DCCP_PKT_SYNCACK] = {
+ /*
+ * We currently ignore SyncAck packets
+ *
+ * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */
+ sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG,
+ },
+ },
+};
+
+static bool dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
+ struct nf_conntrack_tuple *tuple)
+{
+ struct dccp_hdr _hdr, *dh;
+
+ dh = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
+ if (dh == NULL)
+ return false;
+
+ tuple->src.u.dccp.port = dh->dccph_sport;
+ tuple->dst.u.dccp.port = dh->dccph_dport;
+ return true;
+}
+
+static bool dccp_invert_tuple(struct nf_conntrack_tuple *inv,
+ const struct nf_conntrack_tuple *tuple)
+{
+ inv->src.u.dccp.port = tuple->dst.u.dccp.port;
+ inv->dst.u.dccp.port = tuple->src.u.dccp.port;
+ return true;
+}
+
+static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
+ unsigned int dataoff)
+{
+ struct dccp_hdr _dh, *dh;
+ const char *msg;
+ u_int8_t state;
+
+ dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh);
+ BUG_ON(dh == NULL);
+
+ state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE];
+ switch (state) {
+ default:
+ if (nf_ct_dccp_loose == 0) {
+ msg = "nf_ct_dccp: not picking up existing connection ";
+ goto out_invalid;
+ }
+ case CT_DCCP_REQUEST:
+ break;
+ case CT_DCCP_INVALID:
+ msg = "nf_ct_dccp: invalid state transition ";
+ goto out_invalid;
+ }
+
+ ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_CLIENT;
+ ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_SERVER;
+ ct->proto.dccp.state = CT_DCCP_NONE;
+ return true;
+
+out_invalid:
+ if (LOG_INVALID(IPPROTO_DCCP))
+ nf_log_packet(nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL, msg);
+ return false;
+}
+
+static u64 dccp_ack_seq(const struct dccp_hdr *dh)
+{
+ const struct dccp_hdr_ack_bits *dhack;
+
+ dhack = (void *)dh + __dccp_basic_hdr_len(dh);
+ return ((u64)ntohs(dhack->dccph_ack_nr_high) << 32) +
+ ntohl(dhack->dccph_ack_nr_low);
+}
+
+static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
+ unsigned int dataoff, enum ip_conntrack_info ctinfo,
+ int pf, unsigned int hooknum)
+{
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+ struct dccp_hdr _dh, *dh;
+ u_int8_t type, old_state, new_state;
+ enum ct_dccp_roles role;
+
+ dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh);
+ BUG_ON(dh == NULL);
+ type = dh->dccph_type;
+
+ if (type == DCCP_PKT_RESET &&
+ !test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
+ /* Tear down connection immediately if only reply is a RESET */
+ if (del_timer(&ct->timeout))
+ ct->timeout.function((unsigned long)ct);
+ return NF_ACCEPT;
+ }
+
+ write_lock_bh(&dccp_lock);
+
+ role = ct->proto.dccp.role[dir];
+ old_state = ct->proto.dccp.state;
+ new_state = dccp_state_table[role][type][old_state];
+
+ switch (new_state) {
+ case CT_DCCP_REQUEST:
+ if (old_state == CT_DCCP_TIMEWAIT &&
+ role == CT_DCCP_ROLE_SERVER) {
+ /* Reincarnation in the reverse direction: reopen and
+ * reverse client/server roles. */
+ ct->proto.dccp.role[dir] = CT_DCCP_ROLE_CLIENT;
+ ct->proto.dccp.role[!dir] = CT_DCCP_ROLE_SERVER;
+ }
+ break;
+ case CT_DCCP_RESPOND:
+ if (old_state == CT_DCCP_REQUEST)
+ ct->proto.dccp.handshake_seq = dccp_hdr_seq(dh);
+ break;
+ case CT_DCCP_PARTOPEN:
+ if (old_state == CT_DCCP_RESPOND &&
+ type == DCCP_PKT_ACK &&
+ dccp_ack_seq(dh) == ct->proto.dccp.handshake_seq)
+ set_bit(IPS_ASSURED_BIT, &ct->status);
+ break;
+ case CT_DCCP_IGNORE:
+ /*
+ * Connection tracking might be out of sync, so we ignore
+ * packets that might establish a new connection and resync
+ * if the server responds with a valid Response.
+ */
+ if (ct->proto.dccp.last_dir == !dir &&
+ ct->proto.dccp.last_pkt == DCCP_PKT_REQUEST &&
+ type == DCCP_PKT_RESPONSE) {
+ ct->proto.dccp.role[!dir] = CT_DCCP_ROLE_CLIENT;
+ ct->proto.dccp.role[dir] = CT_DCCP_ROLE_SERVER;
+ ct->proto.dccp.handshake_seq = dccp_hdr_seq(dh);
+ new_state = CT_DCCP_RESPOND;
+ break;
+ }
+ ct->proto.dccp.last_dir = dir;
+ ct->proto.dccp.last_pkt = type;
+
+ write_unlock_bh(&dccp_lock);
+ if (LOG_INVALID(IPPROTO_DCCP))
+ nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+ "nf_ct_dccp: invalid packet ignored ");
+ return NF_ACCEPT;
+ case CT_DCCP_INVALID:
+ write_unlock_bh(&dccp_lock);
+ if (LOG_INVALID(IPPROTO_DCCP))
+ nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+ "nf_ct_dccp: invalid state transition ");
+ return -NF_ACCEPT;
+ }
+
+ ct->proto.dccp.last_dir = dir;
+ ct->proto.dccp.last_pkt = type;
+ ct->proto.dccp.state = new_state;
+ write_unlock_bh(&dccp_lock);
+ nf_ct_refresh_acct(ct, ctinfo, skb, dccp_timeout[new_state]);
+
+ return NF_ACCEPT;
+}
+
+static int dccp_error(struct sk_buff *skb, unsigned int dataoff,
+ enum ip_conntrack_info *ctinfo, int pf,
+ unsigned int hooknum)
+{
+ struct dccp_hdr _dh, *dh;
+ unsigned int dccp_len = skb->len - dataoff;
+ unsigned int cscov;
+ const char *msg;
+
+ dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh);
+ if (dh == NULL) {
+ msg = "nf_ct_dccp: short packet ";
+ goto out_invalid;
+ }
+
+ if (dh->dccph_doff * 4 < sizeof(struct dccp_hdr) ||
+ dh->dccph_doff * 4 > dccp_len) {
+ msg = "nf_ct_dccp: truncated/malformed packet ";
+ goto out_invalid;
+ }
+
+ cscov = dccp_len;
+ if (dh->dccph_cscov) {
+ cscov = (dh->dccph_cscov - 1) * 4;
+ if (cscov > dccp_len) {
+ msg = "nf_ct_dccp: bad checksum coverage ";
+ goto out_invalid;
+ }
+ }
+
+ if (nf_conntrack_checksum && hooknum == NF_INET_PRE_ROUTING &&
+ nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_DCCP,
+ pf)) {
+ msg = "nf_ct_dccp: bad checksum ";
+ goto out_invalid;
+ }
+
+ if (dh->dccph_type >= DCCP_PKT_INVALID) {
+ msg = "nf_ct_dccp: reserved packet type ";
+ goto out_invalid;
+ }
+
+ return NF_ACCEPT;
+
+out_invalid:
+ if (LOG_INVALID(IPPROTO_DCCP))
+ nf_log_packet(pf, 0, skb, NULL, NULL, NULL, msg);
+ return -NF_ACCEPT;
+}
+
+static int dccp_print_tuple(struct seq_file *s,
+ const struct nf_conntrack_tuple *tuple)
+{
+ return seq_printf(s, "sport=%hu dport=%hu ",
+ ntohs(tuple->src.u.dccp.port),
+ ntohs(tuple->dst.u.dccp.port));
+}
+
+static int dccp_print_conntrack(struct seq_file *s, const struct nf_conn *ct)
+{
+ return seq_printf(s, "%s ", dccp_state_names[ct->proto.dccp.state]);
+}
+
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+static int dccp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
+ const struct nf_conn *ct)
+{
+ struct nlattr *nest_parms;
+
+ read_lock_bh(&dccp_lock);
+ nest_parms = nla_nest_start(skb, CTA_PROTOINFO_DCCP | NLA_F_NESTED);
+ if (!nest_parms)
+ goto nla_put_failure;
+ NLA_PUT_U8(skb, CTA_PROTOINFO_DCCP_STATE, ct->proto.dccp.state);
+ nla_nest_end(skb, nest_parms);
+ read_unlock_bh(&dccp_lock);
+ return 0;
+
+nla_put_failure:
+ read_unlock_bh(&dccp_lock);
+ return -1;
+}
+
+static const struct nla_policy dccp_nla_policy[CTA_PROTOINFO_DCCP_MAX + 1] = {
+ [CTA_PROTOINFO_DCCP_STATE] = { .type = NLA_U8 },
+};
+
+static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct)
+{
+ struct nlattr *attr = cda[CTA_PROTOINFO_DCCP];
+ struct nlattr *tb[CTA_PROTOINFO_DCCP_MAX + 1];
+ int err;
+
+ if (!attr)
+ return 0;
+
+ err = nla_parse_nested(tb, CTA_PROTOINFO_DCCP_MAX, attr,
+ dccp_nla_policy);
+ if (err < 0)
+ return err;
+
+ if (!tb[CTA_PROTOINFO_DCCP_STATE] ||
+ nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]) >= CT_DCCP_IGNORE)
+ return -EINVAL;
+
+ write_lock_bh(&dccp_lock);
+ ct->proto.dccp.state = nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]);
+ write_unlock_bh(&dccp_lock);
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_SYSCTL
+static unsigned int dccp_sysctl_table_users;
+static struct ctl_table_header *dccp_sysctl_header;
+static ctl_table dccp_sysctl_table[] = {
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "nf_conntrack_dccp_timeout_request",
+ .data = &dccp_timeout[CT_DCCP_REQUEST],
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "nf_conntrack_dccp_timeout_respond",
+ .data = &dccp_timeout[CT_DCCP_RESPOND],
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "nf_conntrack_dccp_timeout_partopen",
+ .data = &dccp_timeout[CT_DCCP_PARTOPEN],
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "nf_conntrack_dccp_timeout_open",
+ .data = &dccp_timeout[CT_DCCP_OPEN],
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "nf_conntrack_dccp_timeout_closereq",
+ .data = &dccp_timeout[CT_DCCP_CLOSEREQ],
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "nf_conntrack_dccp_timeout_closing",
+ .data = &dccp_timeout[CT_DCCP_CLOSING],
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "nf_conntrack_dccp_timeout_timewait",
+ .data = &dccp_timeout[CT_DCCP_TIMEWAIT],
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "nf_conntrack_dccp_loose",
+ .data = &nf_ct_dccp_loose,
+ .maxlen = sizeof(nf_ct_dccp_loose),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ {
+ .ctl_name = 0,
+ }
+};
+#endif /* CONFIG_SYSCTL */
+
+static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = {
+ .l3proto = AF_INET,
+ .l4proto = IPPROTO_DCCP,
+ .name = "dccp",
+ .pkt_to_tuple = dccp_pkt_to_tuple,
+ .invert_tuple = dccp_invert_tuple,
+ .new = dccp_new,
+ .packet = dccp_packet,
+ .error = dccp_error,
+ .print_tuple = dccp_print_tuple,
+ .print_conntrack = dccp_print_conntrack,
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+ .to_nlattr = dccp_to_nlattr,
+ .from_nlattr = nlattr_to_dccp,
+ .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
+ .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
+ .nla_policy = nf_ct_port_nla_policy,
+#endif
+#ifdef CONFIG_SYSCTL
+ .ctl_table_users = &dccp_sysctl_table_users,
+ .ctl_table_header = &dccp_sysctl_header,
+ .ctl_table = dccp_sysctl_table,
+#endif
+};
+
+static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = {
+ .l3proto = AF_INET6,
+ .l4proto = IPPROTO_DCCP,
+ .name = "dccp",
+ .pkt_to_tuple = dccp_pkt_to_tuple,
+ .invert_tuple = dccp_invert_tuple,
+ .new = dccp_new,
+ .packet = dccp_packet,
+ .error = dccp_error,
+ .print_tuple = dccp_print_tuple,
+ .print_conntrack = dccp_print_conntrack,
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+ .to_nlattr = dccp_to_nlattr,
+ .from_nlattr = nlattr_to_dccp,
+ .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
+ .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
+ .nla_policy = nf_ct_port_nla_policy,
+#endif
+#ifdef CONFIG_SYSCTL
+ .ctl_table_users = &dccp_sysctl_table_users,
+ .ctl_table_header = &dccp_sysctl_header,
+ .ctl_table = dccp_sysctl_table,
+#endif
+};
+
+static int __init nf_conntrack_proto_dccp_init(void)
+{
+ int err;
+
+ err = nf_conntrack_l4proto_register(&dccp_proto4);
+ if (err < 0)
+ goto err1;
+
+ err = nf_conntrack_l4proto_register(&dccp_proto6);
+ if (err < 0)
+ goto err2;
+ return 0;
+
+err2:
+ nf_conntrack_l4proto_unregister(&dccp_proto4);
+err1:
+ return err;
+}
+
+static void __exit nf_conntrack_proto_dccp_fini(void)
+{
+ nf_conntrack_l4proto_unregister(&dccp_proto6);
+ nf_conntrack_l4proto_unregister(&dccp_proto4);
+}
+
+module_init(nf_conntrack_proto_dccp_init);
+module_exit(nf_conntrack_proto_dccp_fini);
+
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("DCCP connection tracking protocol helper");
+MODULE_LICENSE("GPL");
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c
index 55458915575..e31b0e7bd0b 100644
--- a/net/netfilter/nf_conntrack_proto_generic.c
+++ b/net/netfilter/nf_conntrack_proto_generic.c
@@ -14,23 +14,23 @@
static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ;
-static int generic_pkt_to_tuple(const struct sk_buff *skb,
- unsigned int dataoff,
- struct nf_conntrack_tuple *tuple)
+static bool generic_pkt_to_tuple(const struct sk_buff *skb,
+ unsigned int dataoff,
+ struct nf_conntrack_tuple *tuple)
{
tuple->src.u.all = 0;
tuple->dst.u.all = 0;
- return 1;
+ return true;
}
-static int generic_invert_tuple(struct nf_conntrack_tuple *tuple,
- const struct nf_conntrack_tuple *orig)
+static bool generic_invert_tuple(struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_tuple *orig)
{
tuple->src.u.all = 0;
tuple->dst.u.all = 0;
- return 1;
+ return true;
}
/* Print out the per-protocol part of the tuple. */
@@ -53,10 +53,10 @@ static int packet(struct nf_conn *ct,
}
/* Called when a new connection for this protocol found. */
-static int new(struct nf_conn *ct, const struct sk_buff *skb,
- unsigned int dataoff)
+static bool new(struct nf_conn *ct, const struct sk_buff *skb,
+ unsigned int dataoff)
{
- return 1;
+ return true;
}
#ifdef CONFIG_SYSCTL
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
index e10024a1b66..654a4f7f12c 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -82,7 +82,7 @@ static __be16 gre_keymap_lookup(struct nf_conntrack_tuple *t)
read_unlock_bh(&nf_ct_gre_lock);
pr_debug("lookup src key 0x%x for ", key);
- NF_CT_DUMP_TUPLE(t);
+ nf_ct_dump_tuple(t);
return key;
}
@@ -113,7 +113,7 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
*kmp = km;
pr_debug("adding new entry %p: ", km);
- NF_CT_DUMP_TUPLE(&km->tuple);
+ nf_ct_dump_tuple(&km->tuple);
write_lock_bh(&nf_ct_gre_lock);
list_add_tail(&km->list, &gre_keymap_list);
@@ -148,18 +148,17 @@ EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_destroy);
/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */
/* invert gre part of tuple */
-static int gre_invert_tuple(struct nf_conntrack_tuple *tuple,
- const struct nf_conntrack_tuple *orig)
+static bool gre_invert_tuple(struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_tuple *orig)
{
tuple->dst.u.gre.key = orig->src.u.gre.key;
tuple->src.u.gre.key = orig->dst.u.gre.key;
- return 1;
+ return true;
}
/* gre hdr info to tuple */
-static int gre_pkt_to_tuple(const struct sk_buff *skb,
- unsigned int dataoff,
- struct nf_conntrack_tuple *tuple)
+static bool gre_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
+ struct nf_conntrack_tuple *tuple)
{
const struct gre_hdr_pptp *pgrehdr;
struct gre_hdr_pptp _pgrehdr;
@@ -173,24 +172,24 @@ static int gre_pkt_to_tuple(const struct sk_buff *skb,
/* try to behave like "nf_conntrack_proto_generic" */
tuple->src.u.all = 0;
tuple->dst.u.all = 0;
- return 1;
+ return true;
}
/* PPTP header is variable length, only need up to the call_id field */
pgrehdr = skb_header_pointer(skb, dataoff, 8, &_pgrehdr);
if (!pgrehdr)
- return 1;
+ return true;
if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) {
pr_debug("GRE_VERSION_PPTP but unknown proto\n");
- return 0;
+ return false;
}
tuple->dst.u.gre.key = pgrehdr->call_id;
srckey = gre_keymap_lookup(tuple);
tuple->src.u.gre.key = srckey;
- return 1;
+ return true;
}
/* print gre part of tuple */
@@ -235,18 +234,18 @@ static int gre_packet(struct nf_conn *ct,
}
/* Called when a new connection for this protocol found. */
-static int gre_new(struct nf_conn *ct, const struct sk_buff *skb,
- unsigned int dataoff)
+static bool gre_new(struct nf_conn *ct, const struct sk_buff *skb,
+ unsigned int dataoff)
{
pr_debug(": ");
- NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+ nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
/* initialize to sane value. Ideally a conntrack helper
* (e.g. in case of pptp) is increasing them */
ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT;
ct->proto.gre.timeout = GRE_TIMEOUT;
- return 1;
+ return true;
}
/* Called when a conntrack entry has already been removed from the hashes
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index f9a08370dbb..cbf2e27a22b 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -33,7 +33,7 @@ static DEFINE_RWLOCK(sctp_lock);
And so for me for SCTP :D -Kiran */
-static const char *sctp_conntrack_names[] = {
+static const char *const sctp_conntrack_names[] = {
"NONE",
"CLOSED",
"COOKIE_WAIT",
@@ -130,28 +130,28 @@ static const u8 sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
}
};
-static int sctp_pkt_to_tuple(const struct sk_buff *skb,
- unsigned int dataoff,
- struct nf_conntrack_tuple *tuple)
+static bool sctp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
+ struct nf_conntrack_tuple *tuple)
{
- sctp_sctphdr_t _hdr, *hp;
+ const struct sctphdr *hp;
+ struct sctphdr _hdr;
/* Actually only need first 8 bytes. */
hp = skb_header_pointer(skb, dataoff, 8, &_hdr);
if (hp == NULL)
- return 0;
+ return false;
tuple->src.u.sctp.port = hp->source;
tuple->dst.u.sctp.port = hp->dest;
- return 1;
+ return true;
}
-static int sctp_invert_tuple(struct nf_conntrack_tuple *tuple,
- const struct nf_conntrack_tuple *orig)
+static bool sctp_invert_tuple(struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_tuple *orig)
{
tuple->src.u.sctp.port = orig->dst.u.sctp.port;
tuple->dst.u.sctp.port = orig->src.u.sctp.port;
- return 1;
+ return true;
}
/* Print out the per-protocol part of the tuple. */
@@ -292,8 +292,10 @@ static int sctp_packet(struct nf_conn *ct,
{
enum sctp_conntrack new_state, old_state;
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
- sctp_sctphdr_t _sctph, *sh;
- sctp_chunkhdr_t _sch, *sch;
+ const struct sctphdr *sh;
+ struct sctphdr _sctph;
+ const struct sctp_chunkhdr *sch;
+ struct sctp_chunkhdr _sch;
u_int32_t offset, count;
unsigned long map[256 / sizeof(unsigned long)] = { 0 };
@@ -390,27 +392,29 @@ out:
}
/* Called when a new connection for this protocol found. */
-static int sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
- unsigned int dataoff)
+static bool sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
+ unsigned int dataoff)
{
enum sctp_conntrack new_state;
- sctp_sctphdr_t _sctph, *sh;
- sctp_chunkhdr_t _sch, *sch;
+ const struct sctphdr *sh;
+ struct sctphdr _sctph;
+ const struct sctp_chunkhdr *sch;
+ struct sctp_chunkhdr _sch;
u_int32_t offset, count;
unsigned long map[256 / sizeof(unsigned long)] = { 0 };
sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
if (sh == NULL)
- return 0;
+ return false;
if (do_basic_checks(ct, skb, dataoff, map) != 0)
- return 0;
+ return false;
/* If an OOTB packet has any of these chunks discard (Sec 8.4) */
if (test_bit(SCTP_CID_ABORT, map) ||
test_bit(SCTP_CID_SHUTDOWN_COMPLETE, map) ||
test_bit(SCTP_CID_COOKIE_ACK, map))
- return 0;
+ return false;
new_state = SCTP_CONNTRACK_MAX;
for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
@@ -422,7 +426,7 @@ static int sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
if (new_state == SCTP_CONNTRACK_NONE ||
new_state == SCTP_CONNTRACK_MAX) {
pr_debug("nf_conntrack_sctp: invalid new deleting.\n");
- return 0;
+ return false;
}
/* Copy the vtag into the state info */
@@ -433,7 +437,7 @@ static int sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
sizeof(_inithdr), &_inithdr);
if (ih == NULL)
- return 0;
+ return false;
pr_debug("Setting vtag %x for new conn\n",
ih->init_tag);
@@ -442,7 +446,7 @@ static int sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
ih->init_tag;
} else {
/* Sec 8.5.1 (A) */
- return 0;
+ return false;
}
}
/* If it is a shutdown ack OOTB packet, we expect a return
@@ -456,7 +460,7 @@ static int sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
ct->proto.sctp.state = new_state;
}
- return 1;
+ return true;
}
#ifdef CONFIG_SYSCTL
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 62567959b66..ba94004fe32 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -257,9 +257,8 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
}
};
-static int tcp_pkt_to_tuple(const struct sk_buff *skb,
- unsigned int dataoff,
- struct nf_conntrack_tuple *tuple)
+static bool tcp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
+ struct nf_conntrack_tuple *tuple)
{
const struct tcphdr *hp;
struct tcphdr _hdr;
@@ -267,20 +266,20 @@ static int tcp_pkt_to_tuple(const struct sk_buff *skb,
/* Actually only need first 8 bytes. */
hp = skb_header_pointer(skb, dataoff, 8, &_hdr);
if (hp == NULL)
- return 0;
+ return false;
tuple->src.u.tcp.port = hp->source;
tuple->dst.u.tcp.port = hp->dest;
- return 1;
+ return true;
}
-static int tcp_invert_tuple(struct nf_conntrack_tuple *tuple,
- const struct nf_conntrack_tuple *orig)
+static bool tcp_invert_tuple(struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_tuple *orig)
{
tuple->src.u.tcp.port = orig->dst.u.tcp.port;
tuple->dst.u.tcp.port = orig->src.u.tcp.port;
- return 1;
+ return true;
}
/* Print out the per-protocol part of the tuple. */
@@ -478,20 +477,20 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff,
}
}
-static int tcp_in_window(const struct nf_conn *ct,
- struct ip_ct_tcp *state,
- enum ip_conntrack_dir dir,
- unsigned int index,
- const struct sk_buff *skb,
- unsigned int dataoff,
- const struct tcphdr *tcph,
- int pf)
+static bool tcp_in_window(const struct nf_conn *ct,
+ struct ip_ct_tcp *state,
+ enum ip_conntrack_dir dir,
+ unsigned int index,
+ const struct sk_buff *skb,
+ unsigned int dataoff,
+ const struct tcphdr *tcph,
+ int pf)
{
struct ip_ct_tcp_state *sender = &state->seen[dir];
struct ip_ct_tcp_state *receiver = &state->seen[!dir];
const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple;
__u32 seq, ack, sack, end, win, swin;
- int res;
+ bool res;
/*
* Get the required data from the packet.
@@ -506,7 +505,7 @@ static int tcp_in_window(const struct nf_conn *ct,
pr_debug("tcp_in_window: START\n");
pr_debug("tcp_in_window: ");
- NF_CT_DUMP_TUPLE(tuple);
+ nf_ct_dump_tuple(tuple);
pr_debug("seq=%u ack=%u sack=%u win=%u end=%u\n",
seq, ack, sack, win, end);
pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
@@ -593,7 +592,7 @@ static int tcp_in_window(const struct nf_conn *ct,
seq = end = sender->td_end;
pr_debug("tcp_in_window: ");
- NF_CT_DUMP_TUPLE(tuple);
+ nf_ct_dump_tuple(tuple);
pr_debug("seq=%u ack=%u sack =%u win=%u end=%u\n",
seq, ack, sack, win, end);
pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
@@ -657,12 +656,12 @@ static int tcp_in_window(const struct nf_conn *ct,
state->retrans = 0;
}
}
- res = 1;
+ res = true;
} else {
- res = 0;
+ res = false;
if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL ||
nf_ct_tcp_be_liberal)
- res = 1;
+ res = true;
if (!res && LOG_INVALID(IPPROTO_TCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_tcp: %s ",
@@ -676,7 +675,7 @@ static int tcp_in_window(const struct nf_conn *ct,
: "SEQ is over the upper bound (over the window of the receiver)");
}
- pr_debug("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
+ pr_debug("tcp_in_window: res=%u sender end=%u maxend=%u maxwin=%u "
"receiver end=%u maxend=%u maxwin=%u\n",
res, sender->td_end, sender->td_maxend, sender->td_maxwin,
receiver->td_end, receiver->td_maxend, receiver->td_maxwin);
@@ -937,7 +936,7 @@ static int tcp_packet(struct nf_conn *ct,
ct->proto.tcp.last_dir = dir;
pr_debug("tcp_conntracks: ");
- NF_CT_DUMP_TUPLE(tuple);
+ nf_ct_dump_tuple(tuple);
pr_debug("syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
(th->syn ? 1 : 0), (th->ack ? 1 : 0),
(th->fin ? 1 : 0), (th->rst ? 1 : 0),
@@ -982,9 +981,8 @@ static int tcp_packet(struct nf_conn *ct,
}
/* Called when a new connection for this protocol found. */
-static int tcp_new(struct nf_conn *ct,
- const struct sk_buff *skb,
- unsigned int dataoff)
+static bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb,
+ unsigned int dataoff)
{
enum tcp_conntrack new_state;
const struct tcphdr *th;
@@ -1003,7 +1001,7 @@ static int tcp_new(struct nf_conn *ct,
/* Invalid: delete conntrack */
if (new_state >= TCP_CONNTRACK_MAX) {
pr_debug("nf_ct_tcp: invalid new deleting.\n");
- return 0;
+ return false;
}
if (new_state == TCP_CONNTRACK_SYN_SENT) {
@@ -1021,7 +1019,7 @@ static int tcp_new(struct nf_conn *ct,
ct->proto.tcp.seen[1].flags = 0;
} else if (nf_ct_tcp_loose == 0) {
/* Don't try to pick up connections. */
- return 0;
+ return false;
} else {
/*
* We are in the middle of a connection,
@@ -1061,7 +1059,7 @@ static int tcp_new(struct nf_conn *ct,
sender->td_scale,
receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
receiver->td_scale);
- return 1;
+ return true;
}
#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
@@ -1129,11 +1127,13 @@ static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct)
if (err < 0)
return err;
- if (!tb[CTA_PROTOINFO_TCP_STATE])
+ if (tb[CTA_PROTOINFO_TCP_STATE] &&
+ nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]) >= TCP_CONNTRACK_MAX)
return -EINVAL;
write_lock_bh(&tcp_lock);
- ct->proto.tcp.state = nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]);
+ if (tb[CTA_PROTOINFO_TCP_STATE])
+ ct->proto.tcp.state = nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]);
if (tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL]) {
struct nf_ct_tcp_flags *attr =
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index b8a35cc0641..8b21762e65d 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -26,7 +26,7 @@
static unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ;
static unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ;
-static int udp_pkt_to_tuple(const struct sk_buff *skb,
+static bool udp_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff,
struct nf_conntrack_tuple *tuple)
{
@@ -36,20 +36,20 @@ static int udp_pkt_to_tuple(const struct sk_buff *skb,
/* Actually only need first 8 bytes. */
hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
if (hp == NULL)
- return 0;
+ return false;
tuple->src.u.udp.port = hp->source;
tuple->dst.u.udp.port = hp->dest;
- return 1;
+ return true;
}
-static int udp_invert_tuple(struct nf_conntrack_tuple *tuple,
- const struct nf_conntrack_tuple *orig)
+static bool udp_invert_tuple(struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_tuple *orig)
{
tuple->src.u.udp.port = orig->dst.u.udp.port;
tuple->dst.u.udp.port = orig->src.u.udp.port;
- return 1;
+ return true;
}
/* Print out the per-protocol part of the tuple. */
@@ -83,10 +83,10 @@ static int udp_packet(struct nf_conn *ct,
}
/* Called when a new connection for this protocol found. */
-static int udp_new(struct nf_conn *ct, const struct sk_buff *skb,
- unsigned int dataoff)
+static bool udp_new(struct nf_conn *ct, const struct sk_buff *skb,
+ unsigned int dataoff)
{
- return 1;
+ return true;
}
static int udp_error(struct sk_buff *skb, unsigned int dataoff,
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c
index 9dd03c7aeac..1fa62f3c24f 100644
--- a/net/netfilter/nf_conntrack_proto_udplite.c
+++ b/net/netfilter/nf_conntrack_proto_udplite.c
@@ -27,28 +27,28 @@
static unsigned int nf_ct_udplite_timeout __read_mostly = 30*HZ;
static unsigned int nf_ct_udplite_timeout_stream __read_mostly = 180*HZ;
-static int udplite_pkt_to_tuple(const struct sk_buff *skb,
- unsigned int dataoff,
- struct nf_conntrack_tuple *tuple)
+static bool udplite_pkt_to_tuple(const struct sk_buff *skb,
+ unsigned int dataoff,
+ struct nf_conntrack_tuple *tuple)
{
const struct udphdr *hp;
struct udphdr _hdr;
hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
if (hp == NULL)
- return 0;
+ return false;
tuple->src.u.udp.port = hp->source;
tuple->dst.u.udp.port = hp->dest;
- return 1;
+ return true;
}
-static int udplite_invert_tuple(struct nf_conntrack_tuple *tuple,
- const struct nf_conntrack_tuple *orig)
+static bool udplite_invert_tuple(struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_tuple *orig)
{
tuple->src.u.udp.port = orig->dst.u.udp.port;
tuple->dst.u.udp.port = orig->src.u.udp.port;
- return 1;
+ return true;
}
/* Print out the per-protocol part of the tuple. */
@@ -83,10 +83,10 @@ static int udplite_packet(struct nf_conn *ct,
}
/* Called when a new connection for this protocol found. */
-static int udplite_new(struct nf_conn *ct, const struct sk_buff *skb,
- unsigned int dataoff)
+static bool udplite_new(struct nf_conn *ct, const struct sk_buff *skb,
+ unsigned int dataoff)
{
- return 1;
+ return true;
}
static int udplite_error(struct sk_buff *skb, unsigned int dataoff,
@@ -127,32 +127,13 @@ static int udplite_error(struct sk_buff *skb, unsigned int dataoff,
}
/* Checksum invalid? Ignore. */
- if (nf_conntrack_checksum && !skb_csum_unnecessary(skb) &&
- hooknum == NF_INET_PRE_ROUTING) {
- if (pf == PF_INET) {
- struct iphdr *iph = ip_hdr(skb);
-
- skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
- udplen, IPPROTO_UDPLITE, 0);
- } else {
- struct ipv6hdr *ipv6h = ipv6_hdr(skb);
- __wsum hsum = skb_checksum(skb, 0, dataoff, 0);
-
- skb->csum = ~csum_unfold(
- csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr,
- udplen, IPPROTO_UDPLITE,
- csum_sub(0, hsum)));
- }
-
- skb->ip_summed = CHECKSUM_NONE;
- if (__skb_checksum_complete_head(skb, dataoff + cscov)) {
- if (LOG_INVALID(IPPROTO_UDPLITE))
- nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
- "nf_ct_udplite: bad UDPLite "
- "checksum ");
- return -NF_ACCEPT;
- }
- skb->ip_summed = CHECKSUM_UNNECESSARY;
+ if (nf_conntrack_checksum && hooknum == NF_INET_PRE_ROUTING &&
+ nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_UDP,
+ pf)) {
+ if (LOG_INVALID(IPPROTO_UDPLITE))
+ nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+ "nf_ct_udplite: bad UDPLite checksum ");
+ return -NF_ACCEPT;
}
return NF_ACCEPT;
diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c
index 7542e25eede..a94294b2b23 100644
--- a/net/netfilter/nf_conntrack_sane.c
+++ b/net/netfilter/nf_conntrack_sane.c
@@ -72,7 +72,6 @@ static int help(struct sk_buff *skb,
struct nf_conntrack_tuple *tuple;
struct sane_request *req;
struct sane_reply_net_start *reply;
- int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
ct_sane_info = &nfct_help(ct)->help.ct_sane_info;
/* Until there's been traffic both ways, don't look in packets. */
@@ -143,12 +142,12 @@ static int help(struct sk_buff *skb,
}
tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
- nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, family,
+ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
&tuple->src.u3, &tuple->dst.u3,
IPPROTO_TCP, NULL, &reply->port);
pr_debug("nf_ct_sane: expect: ");
- NF_CT_DUMP_TUPLE(&exp->tuple);
+ nf_ct_dump_tuple(&exp->tuple);
/* Can't expect this? Best to drop packet now. */
if (nf_ct_expect_related(exp) != 0)
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index da5dec6e615..65b3ba57a3b 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -142,10 +142,10 @@ static int parse_addr(const struct nf_conn *ct, const char *cp,
const char *limit)
{
const char *end;
- int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
int ret = 0;
- switch (family) {
+ memset(addr, 0, sizeof(*addr));
+ switch (nf_ct_l3num(ct)) {
case AF_INET:
ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end);
break;
@@ -739,7 +739,6 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb,
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
union nf_inet_addr *saddr;
struct nf_conntrack_tuple tuple;
- int family = ct->tuplehash[!dir].tuple.src.l3num;
int direct_rtp = 0, skip_expect = 0, ret = NF_DROP;
u_int16_t base_port;
__be16 rtp_port, rtcp_port;
@@ -769,7 +768,7 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb,
memset(&tuple, 0, sizeof(tuple));
if (saddr)
tuple.src.u3 = *saddr;
- tuple.src.l3num = family;
+ tuple.src.l3num = nf_ct_l3num(ct);
tuple.dst.protonum = IPPROTO_UDP;
tuple.dst.u3 = *daddr;
tuple.dst.u.udp.port = port;
@@ -814,13 +813,13 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb,
rtp_exp = nf_ct_expect_alloc(ct);
if (rtp_exp == NULL)
goto err1;
- nf_ct_expect_init(rtp_exp, class, family, saddr, daddr,
+ nf_ct_expect_init(rtp_exp, class, nf_ct_l3num(ct), saddr, daddr,
IPPROTO_UDP, NULL, &rtp_port);
rtcp_exp = nf_ct_expect_alloc(ct);
if (rtcp_exp == NULL)
goto err2;
- nf_ct_expect_init(rtcp_exp, class, family, saddr, daddr,
+ nf_ct_expect_init(rtcp_exp, class, nf_ct_l3num(ct), saddr, daddr,
IPPROTO_UDP, NULL, &rtcp_port);
nf_nat_sdp_media = rcu_dereference(nf_nat_sdp_media_hook);
@@ -870,7 +869,6 @@ static int process_sdp(struct sk_buff *skb,
{
enum ip_conntrack_info ctinfo;
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
- int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
unsigned int matchoff, matchlen;
unsigned int mediaoff, medialen;
unsigned int sdpoff;
@@ -885,8 +883,8 @@ static int process_sdp(struct sk_buff *skb,
typeof(nf_nat_sdp_session_hook) nf_nat_sdp_session;
nf_nat_sdp_addr = rcu_dereference(nf_nat_sdp_addr_hook);
- c_hdr = family == AF_INET ? SDP_HDR_CONNECTION_IP4 :
- SDP_HDR_CONNECTION_IP6;
+ c_hdr = nf_ct_l3num(ct) == AF_INET ? SDP_HDR_CONNECTION_IP4 :
+ SDP_HDR_CONNECTION_IP6;
/* Find beginning of session description */
if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen,
@@ -1033,7 +1031,6 @@ static int process_register_request(struct sk_buff *skb,
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
struct nf_conn_help *help = nfct_help(ct);
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
- int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
unsigned int matchoff, matchlen;
struct nf_conntrack_expect *exp;
union nf_inet_addr *saddr, daddr;
@@ -1088,8 +1085,8 @@ static int process_register_request(struct sk_buff *skb,
if (sip_direct_signalling)
saddr = &ct->tuplehash[!dir].tuple.src.u3;
- nf_ct_expect_init(exp, SIP_EXPECT_SIGNALLING, family, saddr, &daddr,
- IPPROTO_UDP, NULL, &port);
+ nf_ct_expect_init(exp, SIP_EXPECT_SIGNALLING, nf_ct_l3num(ct),
+ saddr, &daddr, IPPROTO_UDP, NULL, &port);
exp->timeout.expires = sip_timeout * HZ;
exp->helper = nfct_help(ct)->helper;
exp->flags = NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE;
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 9d0b8bb4113..b59871f6bdd 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -127,21 +127,14 @@ static int ct_seq_show(struct seq_file *s, void *v)
if (NF_CT_DIRECTION(hash))
return 0;
- l3proto = __nf_ct_l3proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL]
- .tuple.src.l3num);
-
+ l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct));
NF_CT_ASSERT(l3proto);
- l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL]
- .tuple.src.l3num,
- ct->tuplehash[IP_CT_DIR_ORIGINAL]
- .tuple.dst.protonum);
+ l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
NF_CT_ASSERT(l4proto);
if (seq_printf(s, "%-8s %u %-8s %u %ld ",
- l3proto->name,
- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num,
- l4proto->name,
- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
+ l3proto->name, nf_ct_l3num(ct),
+ l4proto->name, nf_ct_protonum(ct),
timer_pending(&ct->timeout)
? (long)(ct->timeout.expires - jiffies)/HZ : 0) != 0)
return -ENOSPC;
@@ -295,6 +288,41 @@ static const struct file_operations ct_cpu_seq_fops = {
.llseek = seq_lseek,
.release = seq_release,
};
+
+static int nf_conntrack_standalone_init_proc(void)
+{
+ struct proc_dir_entry *pde;
+
+ pde = proc_net_fops_create(&init_net, "nf_conntrack", 0440, &ct_file_ops);
+ if (!pde)
+ goto out_nf_conntrack;
+ pde = create_proc_entry("nf_conntrack", S_IRUGO, init_net.proc_net_stat);
+ if (!pde)
+ goto out_stat_nf_conntrack;
+ pde->proc_fops = &ct_cpu_seq_fops;
+ pde->owner = THIS_MODULE;
+ return 0;
+
+out_stat_nf_conntrack:
+ proc_net_remove(&init_net, "nf_conntrack");
+out_nf_conntrack:
+ return -ENOMEM;
+}
+
+static void nf_conntrack_standalone_fini_proc(void)
+{
+ remove_proc_entry("nf_conntrack", init_net.proc_net_stat);
+ proc_net_remove(&init_net, "nf_conntrack");
+}
+#else
+static int nf_conntrack_standalone_init_proc(void)
+{
+ return 0;
+}
+
+static void nf_conntrack_standalone_fini_proc(void)
+{
+}
#endif /* CONFIG_PROC_FS */
/* Sysctl support */
@@ -390,60 +418,61 @@ static struct ctl_path nf_ct_path[] = {
};
EXPORT_SYMBOL_GPL(nf_ct_log_invalid);
+
+static int nf_conntrack_standalone_init_sysctl(void)
+{
+ nf_ct_sysctl_header =
+ register_sysctl_paths(nf_ct_path, nf_ct_netfilter_table);
+ if (nf_ct_sysctl_header == NULL) {
+ printk("nf_conntrack: can't register to sysctl.\n");
+ return -ENOMEM;
+ }
+ return 0;
+
+}
+
+static void nf_conntrack_standalone_fini_sysctl(void)
+{
+ unregister_sysctl_table(nf_ct_sysctl_header);
+}
+#else
+static int nf_conntrack_standalone_init_sysctl(void)
+{
+ return 0;
+}
+
+static void nf_conntrack_standalone_fini_sysctl(void)
+{
+}
#endif /* CONFIG_SYSCTL */
static int __init nf_conntrack_standalone_init(void)
{
-#ifdef CONFIG_PROC_FS
- struct proc_dir_entry *proc;
-#endif
- int ret = 0;
+ int ret;
ret = nf_conntrack_init();
if (ret < 0)
- return ret;
-
-#ifdef CONFIG_PROC_FS
- proc = proc_net_fops_create(&init_net, "nf_conntrack", 0440, &ct_file_ops);
- if (!proc) goto cleanup_init;
-
- if (!proc_create("nf_conntrack", S_IRUGO,
- init_net.proc_net_stat, &ct_cpu_seq_fops))
- goto cleanup_proc;
-#endif
-#ifdef CONFIG_SYSCTL
- nf_ct_sysctl_header = register_sysctl_paths(nf_ct_path,
- nf_ct_netfilter_table);
- if (nf_ct_sysctl_header == NULL) {
- printk("nf_conntrack: can't register to sysctl.\n");
- ret = -ENOMEM;
- goto cleanup_proc_stat;
- }
-#endif
- return ret;
+ goto out;
+ ret = nf_conntrack_standalone_init_proc();
+ if (ret < 0)
+ goto out_proc;
+ ret = nf_conntrack_standalone_init_sysctl();
+ if (ret < 0)
+ goto out_sysctl;
+ return 0;
-#ifdef CONFIG_SYSCTL
- cleanup_proc_stat:
-#endif
-#ifdef CONFIG_PROC_FS
- remove_proc_entry("nf_conntrack", init_net. proc_net_stat);
- cleanup_proc:
- proc_net_remove(&init_net, "nf_conntrack");
- cleanup_init:
-#endif /* CNFIG_PROC_FS */
+out_sysctl:
+ nf_conntrack_standalone_fini_proc();
+out_proc:
nf_conntrack_cleanup();
+out:
return ret;
}
static void __exit nf_conntrack_standalone_fini(void)
{
-#ifdef CONFIG_SYSCTL
- unregister_sysctl_table(nf_ct_sysctl_header);
-#endif
-#ifdef CONFIG_PROC_FS
- remove_proc_entry("nf_conntrack", init_net.proc_net_stat);
- proc_net_remove(&init_net, "nf_conntrack");
-#endif /* CNFIG_PROC_FS */
+ nf_conntrack_standalone_fini_sysctl();
+ nf_conntrack_standalone_fini_proc();
nf_conntrack_cleanup();
}
diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c
index a28341b30f2..f57f6e7a71e 100644
--- a/net/netfilter/nf_conntrack_tftp.c
+++ b/net/netfilter/nf_conntrack_tftp.c
@@ -44,7 +44,6 @@ static int tftp_help(struct sk_buff *skb,
struct nf_conntrack_expect *exp;
struct nf_conntrack_tuple *tuple;
unsigned int ret = NF_ACCEPT;
- int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
typeof(nf_nat_tftp_hook) nf_nat_tftp;
tfh = skb_header_pointer(skb, protoff + sizeof(struct udphdr),
@@ -56,19 +55,20 @@ static int tftp_help(struct sk_buff *skb,
case TFTP_OPCODE_READ:
case TFTP_OPCODE_WRITE:
/* RRQ and WRQ works the same way */
- NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
- NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+ nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+ nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
exp = nf_ct_expect_alloc(ct);
if (exp == NULL)
return NF_DROP;
tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
- nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, family,
+ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
+ nf_ct_l3num(ct),
&tuple->src.u3, &tuple->dst.u3,
IPPROTO_UDP, NULL, &tuple->dst.u.udp.port);
pr_debug("expect: ");
- NF_CT_DUMP_TUPLE(&exp->tuple);
+ nf_ct_dump_tuple(&exp->tuple);
nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook);
if (nf_nat_tftp && ct->status & IPS_NAT_MASK)
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 0bd95680a49..f52f7f810ac 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -58,7 +58,7 @@ static struct xt_af *xt;
#define duprintf(format, args...)
#endif
-static const char *xt_prefix[NPROTO] = {
+static const char *const xt_prefix[NPROTO] = {
[AF_INET] = "ip",
[AF_INET6] = "ip6",
[NF_ARP] = "arp",
@@ -248,7 +248,7 @@ EXPORT_SYMBOL_GPL(xt_request_find_target);
static int match_revfn(int af, const char *name, u8 revision, int *bestp)
{
- struct xt_match *m;
+ const struct xt_match *m;
int have_rev = 0;
list_for_each_entry(m, &xt[af].match, list) {
@@ -264,7 +264,7 @@ static int match_revfn(int af, const char *name, u8 revision, int *bestp)
static int target_revfn(int af, const char *name, u8 revision, int *bestp)
{
- struct xt_target *t;
+ const struct xt_target *t;
int have_rev = 0;
list_for_each_entry(t, &xt[af].target, list) {
@@ -385,7 +385,7 @@ short xt_compat_calc_jump(int af, unsigned int offset)
}
EXPORT_SYMBOL_GPL(xt_compat_calc_jump);
-int xt_compat_match_offset(struct xt_match *match)
+int xt_compat_match_offset(const struct xt_match *match)
{
u_int16_t csize = match->compatsize ? : match->matchsize;
return XT_ALIGN(match->matchsize) - COMPAT_XT_ALIGN(csize);
@@ -395,7 +395,7 @@ EXPORT_SYMBOL_GPL(xt_compat_match_offset);
int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
unsigned int *size)
{
- struct xt_match *match = m->u.kernel.match;
+ const struct xt_match *match = m->u.kernel.match;
struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
int pad, off = xt_compat_match_offset(match);
u_int16_t msize = cm->u.user.match_size;
@@ -422,7 +422,7 @@ EXPORT_SYMBOL_GPL(xt_compat_match_from_user);
int xt_compat_match_to_user(struct xt_entry_match *m, void __user **dstptr,
unsigned int *size)
{
- struct xt_match *match = m->u.kernel.match;
+ const struct xt_match *match = m->u.kernel.match;
struct compat_xt_entry_match __user *cm = *dstptr;
int off = xt_compat_match_offset(match);
u_int16_t msize = m->u.user.match_size - off;
@@ -479,7 +479,7 @@ int xt_check_target(const struct xt_target *target, unsigned short family,
EXPORT_SYMBOL_GPL(xt_check_target);
#ifdef CONFIG_COMPAT
-int xt_compat_target_offset(struct xt_target *target)
+int xt_compat_target_offset(const struct xt_target *target)
{
u_int16_t csize = target->compatsize ? : target->targetsize;
return XT_ALIGN(target->targetsize) - COMPAT_XT_ALIGN(csize);
@@ -489,7 +489,7 @@ EXPORT_SYMBOL_GPL(xt_compat_target_offset);
void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
unsigned int *size)
{
- struct xt_target *target = t->u.kernel.target;
+ const struct xt_target *target = t->u.kernel.target;
struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
int pad, off = xt_compat_target_offset(target);
u_int16_t tsize = ct->u.user.target_size;
@@ -515,7 +515,7 @@ EXPORT_SYMBOL_GPL(xt_compat_target_from_user);
int xt_compat_target_to_user(struct xt_entry_target *t, void __user **dstptr,
unsigned int *size)
{
- struct xt_target *target = t->u.kernel.target;
+ const struct xt_target *target = t->u.kernel.target;
struct compat_xt_entry_target __user *ct = *dstptr;
int off = xt_compat_target_offset(target);
u_int16_t tsize = t->u.user.target_size - off;
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
index 1faa9136195..211189eb2b6 100644
--- a/net/netfilter/xt_CONNSECMARK.c
+++ b/net/netfilter/xt_CONNSECMARK.c
@@ -55,7 +55,7 @@ static void secmark_save(const struct sk_buff *skb)
static void secmark_restore(struct sk_buff *skb)
{
if (!skb->secmark) {
- struct nf_conn *ct;
+ const struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
ct = nf_ct_get(skb, &ctinfo);
diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c
index 24c73ba31ea..64d6ad38029 100644
--- a/net/netfilter/xt_RATEEST.c
+++ b/net/netfilter/xt_RATEEST.c
@@ -96,7 +96,7 @@ xt_rateest_tg_checkentry(const char *tablename,
void *targinfo,
unsigned int hook_mask)
{
- struct xt_rateest_target_info *info = (void *)targinfo;
+ struct xt_rateest_target_info *info = targinfo;
struct xt_rateest *est;
struct {
struct nlattr opt;
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
index 3b0111933f6..2e89a00df92 100644
--- a/net/netfilter/xt_connlimit.c
+++ b/net/netfilter/xt_connlimit.c
@@ -72,9 +72,7 @@ connlimit_iphash6(const union nf_inet_addr *addr,
static inline bool already_closed(const struct nf_conn *conn)
{
- u_int16_t proto = conn->tuplehash[0].tuple.dst.protonum;
-
- if (proto == IPPROTO_TCP)
+ if (nf_ct_protonum(conn) == IPPROTO_TCP)
return conn->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT;
else
return 0;
@@ -106,10 +104,10 @@ static int count_them(struct xt_connlimit_data *data,
const union nf_inet_addr *mask,
const struct xt_match *match)
{
- struct nf_conntrack_tuple_hash *found;
+ const struct nf_conntrack_tuple_hash *found;
struct xt_connlimit_conn *conn;
struct xt_connlimit_conn *tmp;
- struct nf_conn *found_ct;
+ const struct nf_conn *found_ct;
struct list_head *hash;
bool addit = true;
int matches = 0;
@@ -256,7 +254,7 @@ connlimit_mt_check(const char *tablename, const void *ip,
static void
connlimit_mt_destroy(const struct xt_match *match, void *matchinfo)
{
- struct xt_connlimit_info *info = matchinfo;
+ const struct xt_connlimit_info *info = matchinfo;
struct xt_connlimit_conn *conn;
struct xt_connlimit_conn *tmp;
struct list_head *hash = info->data->iphash;
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index 0c50b289405..d61412f58ef 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -65,7 +65,7 @@ conntrack_mt_v0(const struct sk_buff *skb, const struct net_device *in,
}
if (sinfo->flags & XT_CONNTRACK_PROTO &&
- FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum !=
+ FWINV(nf_ct_protonum(ct) !=
sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum,
XT_CONNTRACK_PROTO))
return false;
@@ -174,7 +174,7 @@ ct_proto_port_check(const struct xt_conntrack_mtinfo1 *info,
tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
if ((info->match_flags & XT_CONNTRACK_PROTO) &&
- (tuple->dst.protonum == info->l4proto) ^
+ (nf_ct_protonum(ct) == info->l4proto) ^
!(info->invert_flags & XT_CONNTRACK_PROTO))
return false;
diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c
index 667f45e72cd..8b6522186d9 100644
--- a/net/netfilter/xt_dccp.c
+++ b/net/netfilter/xt_dccp.c
@@ -98,7 +98,8 @@ dccp_mt(const struct sk_buff *skb, const struct net_device *in,
const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
{
const struct xt_dccp_info *info = matchinfo;
- struct dccp_hdr _dh, *dh;
+ const struct dccp_hdr *dh;
+ struct dccp_hdr _dh;
if (offset)
return false;
diff --git a/net/netfilter/xt_esp.c b/net/netfilter/xt_esp.c
index 71c7c378526..a133eb9b23e 100644
--- a/net/netfilter/xt_esp.c
+++ b/net/netfilter/xt_esp.c
@@ -47,7 +47,8 @@ esp_mt(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct xt_match *match,
const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
{
- struct ip_esp_hdr _esp, *eh;
+ const struct ip_esp_hdr *eh;
+ struct ip_esp_hdr _esp;
const struct xt_esp *espinfo = matchinfo;
/* Must not be a fragment. */
diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c
index 31daa819242..fd88c489b70 100644
--- a/net/netfilter/xt_multiport.c
+++ b/net/netfilter/xt_multiport.c
@@ -100,7 +100,8 @@ multiport_mt_v0(const struct sk_buff *skb, const struct net_device *in,
const void *matchinfo, int offset, unsigned int protoff,
bool *hotdrop)
{
- __be16 _ports[2], *pptr;
+ const __be16 *pptr;
+ __be16 _ports[2];
const struct xt_multiport *multiinfo = matchinfo;
if (offset)
@@ -126,7 +127,8 @@ multiport_mt(const struct sk_buff *skb, const struct net_device *in,
const void *matchinfo, int offset, unsigned int protoff,
bool *hotdrop)
{
- __be16 _ports[2], *pptr;
+ const __be16 *pptr;
+ __be16 _ports[2];
const struct xt_multiport_v1 *multiinfo = matchinfo;
if (offset)
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
index 9e918add228..d351582b2a3 100644
--- a/net/netfilter/xt_policy.c
+++ b/net/netfilter/xt_policy.c
@@ -136,7 +136,7 @@ policy_mt_check(const char *tablename, const void *ip_void,
const struct xt_match *match, void *matchinfo,
unsigned int hook_mask)
{
- struct xt_policy_info *info = matchinfo;
+ const struct xt_policy_info *info = matchinfo;
if (!(info->flags & (XT_POLICY_MATCH_IN|XT_POLICY_MATCH_OUT))) {
printk(KERN_ERR "xt_policy: neither incoming nor "
diff --git a/net/netfilter/xt_rateest.c b/net/netfilter/xt_rateest.c
index fdb86a51514..ebd84f1b4f6 100644
--- a/net/netfilter/xt_rateest.c
+++ b/net/netfilter/xt_rateest.c
@@ -86,7 +86,7 @@ static bool xt_rateest_mt_checkentry(const char *tablename,
void *matchinfo,
unsigned int hook_mask)
{
- struct xt_rateest_match_info *info = (void *)matchinfo;
+ struct xt_rateest_match_info *info = matchinfo;
struct xt_rateest *est1, *est2;
if (hweight32(info->flags & (XT_RATEEST_MATCH_ABS |
@@ -130,7 +130,7 @@ err1:
static void xt_rateest_mt_destroy(const struct xt_match *match,
void *matchinfo)
{
- struct xt_rateest_match_info *info = (void *)matchinfo;
+ struct xt_rateest_match_info *info = matchinfo;
xt_rateest_put(info->est1);
if (info->est2)
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
index b718ec64333..e6e4681fa04 100644
--- a/net/netfilter/xt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -46,7 +46,8 @@ match_packet(const struct sk_buff *skb,
bool *hotdrop)
{
u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
- sctp_chunkhdr_t _sch, *sch;
+ const sctp_chunkhdr_t *sch;
+ sctp_chunkhdr_t _sch;
int chunk_match_type = info->chunk_match_type;
const struct xt_sctp_flag_info *flag_info = info->flag_info;
int flag_count = info->flag_count;
@@ -121,7 +122,8 @@ sctp_mt(const struct sk_buff *skb, const struct net_device *in,
const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
{
const struct xt_sctp_info *info = matchinfo;
- sctp_sctphdr_t _sh, *sh;
+ const sctp_sctphdr_t *sh;
+ sctp_sctphdr_t _sh;
if (offset) {
duprintf("Dropping non-first fragment.. FIXME\n");
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index d7a5b27fe81..6771bf01275 100644
--- a/net/netfilter/xt_tcpmss.c
+++ b/net/netfilter/xt_tcpmss.c
@@ -31,9 +31,11 @@ tcpmss_mt(const struct sk_buff *skb, const struct net_device *in,
bool *hotdrop)
{
const struct xt_tcpmss_match_info *info = matchinfo;
- struct tcphdr _tcph, *th;
+ const struct tcphdr *th;
+ struct tcphdr _tcph;
/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
- u8 _opt[15 * 4 - sizeof(_tcph)], *op;
+ const u_int8_t *op;
+ u8 _opt[15 * 4 - sizeof(_tcph)];
unsigned int i, optlen;
/* If we don't have the whole header, drop packet. */
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
index 4fa3b669f69..951b06b8d70 100644
--- a/net/netfilter/xt_tcpudp.c
+++ b/net/netfilter/xt_tcpudp.c
@@ -42,7 +42,8 @@ tcp_find_option(u_int8_t option,
bool *hotdrop)
{
/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
- u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
+ const u_int8_t *op;
+ u_int8_t _opt[60 - sizeof(struct tcphdr)];
unsigned int i;
duprintf("tcp_match: finding option\n");
@@ -72,7 +73,8 @@ tcp_mt(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct xt_match *match,
const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
{
- struct tcphdr _tcph, *th;
+ const struct tcphdr *th;
+ struct tcphdr _tcph;
const struct xt_tcp *tcpinfo = matchinfo;
if (offset) {
@@ -144,7 +146,8 @@ udp_mt(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct xt_match *match,
const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
{
- struct udphdr _udph, *uh;
+ const struct udphdr *uh;
+ struct udphdr _udph;
const struct xt_udp *udpinfo = matchinfo;
/* Must not be a fragment. */
diff --git a/net/netfilter/xt_time.c b/net/netfilter/xt_time.c
index 9fa2e082470..ed76baab473 100644
--- a/net/netfilter/xt_time.c
+++ b/net/netfilter/xt_time.c
@@ -223,7 +223,7 @@ time_mt_check(const char *tablename, const void *ip,
const struct xt_match *match, void *matchinfo,
unsigned int hook_mask)
{
- struct xt_time_info *info = matchinfo;
+ const struct xt_time_info *info = matchinfo;
if (info->daytime_start > XT_TIME_MAX_DAYTIME ||
info->daytime_stop > XT_TIME_MAX_DAYTIME) {