Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net...
[safe/jmp/linux-2.6] / net / netfilter / nf_conntrack_proto_dccp.c
index aee0d6b..1b816a2 100644 (file)
@@ -25,8 +25,6 @@
 #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:
@@ -492,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;
@@ -536,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 ");
@@ -552,7 +550,7 @@ 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);
@@ -621,36 +619,39 @@ 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;
        NLA_PUT_U8(skb, CTA_PROTOINFO_DCCP_STATE, ct->proto.dccp.state);
        NLA_PUT_U8(skb, CTA_PROTOINFO_DCCP_ROLE,
                   ct->proto.dccp.role[IP_CT_DIR_ORIGINAL]);
+       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;
 }
 
 static const struct nla_policy dccp_nla_policy[CTA_PROTOINFO_DCCP_MAX + 1] = {
        [CTA_PROTOINFO_DCCP_STATE]      = { .type = NLA_U8 },
        [CTA_PROTOINFO_DCCP_ROLE]       = { .type = NLA_U8 },
+       [CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ] = { .type = NLA_U64 },
 };
 
 static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct)
@@ -674,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;
@@ -683,7 +684,11 @@ static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct)
                ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_SERVER;
                ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_CLIENT;
        }
-       write_unlock_bh(&dccp_lock);
+       if (tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ]) {
+               ct->proto.dccp.handshake_seq =
+               be64_to_cpu(nla_get_be64(tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ]));
+       }
+       spin_unlock_bh(&ct->lock);
        return 0;
 }