]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/netfilter/nf_conntrack_proto_dccp.c
Merge branch 'for-2.6.32' of git://linux-nfs.org/~bfields/linux
[karo-tx-linux.git] / net / netfilter / nf_conntrack_proto_dccp.c
index 11801c43c8cfbdf870c3fe7ad35826aaee017165..1b816a2ea813b9c2383aaf2bc5978692deee40f3 100644 (file)
 #include <linux/netfilter/nfnetlink_conntrack.h>
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
 #include <net/netfilter/nf_log.h>
 
-static DEFINE_RWLOCK(dccp_lock);
-
 /* Timeouts are based on values from RFC4340:
  *
  * - REQUEST:
@@ -491,7 +490,7 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
                return NF_ACCEPT;
        }
 
-       write_lock_bh(&dccp_lock);
+       spin_lock_bh(&ct->lock);
 
        role = ct->proto.dccp.role[dir];
        old_state = ct->proto.dccp.state;
@@ -535,13 +534,13 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
                ct->proto.dccp.last_dir = dir;
                ct->proto.dccp.last_pkt = type;
 
-               write_unlock_bh(&dccp_lock);
+               spin_unlock_bh(&ct->lock);
                if (LOG_INVALID(net, 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);
+               spin_unlock_bh(&ct->lock);
                if (LOG_INVALID(net, IPPROTO_DCCP))
                        nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
                                      "nf_ct_dccp: invalid state transition ");
@@ -551,7 +550,10 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
        ct->proto.dccp.last_dir = dir;
        ct->proto.dccp.last_pkt = type;
        ct->proto.dccp.state = new_state;
-       write_unlock_bh(&dccp_lock);
+       spin_unlock_bh(&ct->lock);
+
+       if (new_state != old_state)
+               nf_conntrack_event_cache(IPCT_PROTOINFO, ct);
 
        dn = dccp_pernet(net);
        nf_ct_refresh_acct(ct, ctinfo, skb, dn->dccp_timeout[new_state]);
@@ -617,18 +619,18 @@ static int dccp_print_tuple(struct seq_file *s,
                          ntohs(tuple->dst.u.dccp.port));
 }
 
-static int dccp_print_conntrack(struct seq_file *s, const struct nf_conn *ct)
+static int dccp_print_conntrack(struct seq_file *s, 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 nf_conn *ct)
 {
        struct nlattr *nest_parms;
 
-       read_lock_bh(&dccp_lock);
+       spin_lock_bh(&ct->lock);
        nest_parms = nla_nest_start(skb, CTA_PROTOINFO_DCCP | NLA_F_NESTED);
        if (!nest_parms)
                goto nla_put_failure;
@@ -638,11 +640,11 @@ static int dccp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
        NLA_PUT_BE64(skb, CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ,
                     cpu_to_be64(ct->proto.dccp.handshake_seq));
        nla_nest_end(skb, nest_parms);
-       read_unlock_bh(&dccp_lock);
+       spin_unlock_bh(&ct->lock);
        return 0;
 
 nla_put_failure:
-       read_unlock_bh(&dccp_lock);
+       spin_unlock_bh(&ct->lock);
        return -1;
 }
 
@@ -673,7 +675,7 @@ static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct)
                return -EINVAL;
        }
 
-       write_lock_bh(&dccp_lock);
+       spin_lock_bh(&ct->lock);
        ct->proto.dccp.state = nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]);
        if (nla_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]) == CT_DCCP_ROLE_CLIENT) {
                ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_CLIENT;
@@ -686,7 +688,7 @@ static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct)
                ct->proto.dccp.handshake_seq =
                be64_to_cpu(nla_get_be64(tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ]));
        }
-       write_unlock_bh(&dccp_lock);
+       spin_unlock_bh(&ct->lock);
        return 0;
 }