Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / net / ipv4 / netfilter / ip_conntrack_proto_sctp.c
index 52a9bb7..2d3612c 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
+#include <linux/interrupt.h>
 #include <linux/netfilter.h>
 #include <linux/module.h>
 #include <linux/in.h>
@@ -26,7 +27,6 @@
 
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
-#include <linux/netfilter_ipv4/lockhelp.h>
 
 #if 0
 #define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
@@ -35,7 +35,7 @@
 #endif
 
 /* Protects conntrack->proto.sctp */
-static DECLARE_RWLOCK(sctp_lock);
+static DEFINE_RWLOCK(sctp_lock);
 
 /* FIXME: Examine ipfilter's timeouts and conntrack transitions more
    closely.  They're more complex. --RR 
@@ -58,15 +58,15 @@ static const char *sctp_conntrack_names[] = {
 #define HOURS * 60 MINS
 #define DAYS  * 24 HOURS
 
-static unsigned long ip_ct_sctp_timeout_closed            =  10 SECS;
-static unsigned long ip_ct_sctp_timeout_cookie_wait       =   3 SECS;
-static unsigned long ip_ct_sctp_timeout_cookie_echoed     =   3 SECS;
-static unsigned long ip_ct_sctp_timeout_established       =   2 DAYS;
-static unsigned long ip_ct_sctp_timeout_shutdown_sent     = 300 SECS / 1000;
-static unsigned long ip_ct_sctp_timeout_shutdown_recd     = 300 SECS / 1000;
-static unsigned long ip_ct_sctp_timeout_shutdown_ack_sent =   3 SECS;
+static unsigned int ip_ct_sctp_timeout_closed            =  10 SECS;
+static unsigned int ip_ct_sctp_timeout_cookie_wait       =   3 SECS;
+static unsigned int ip_ct_sctp_timeout_cookie_echoed     =   3 SECS;
+static unsigned int ip_ct_sctp_timeout_established       =   5 DAYS;
+static unsigned int ip_ct_sctp_timeout_shutdown_sent     = 300 SECS / 1000;
+static unsigned int ip_ct_sctp_timeout_shutdown_recd     = 300 SECS / 1000;
+static unsigned int ip_ct_sctp_timeout_shutdown_ack_sent =   3 SECS;
 
-static unsigned long * sctp_timeouts[]
+static const unsigned int * sctp_timeouts[]
 = { NULL,                                  /* SCTP_CONNTRACK_NONE  */
     &ip_ct_sctp_timeout_closed,                   /* SCTP_CONNTRACK_CLOSED */
     &ip_ct_sctp_timeout_cookie_wait,       /* SCTP_CONNTRACK_COOKIE_WAIT */
@@ -119,7 +119,7 @@ cookie echoed to closed.
 */
 
 /* SCTP conntrack state transitions */
-static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
+static const enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
        {
 /*     ORIGINAL        */
 /*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
@@ -199,9 +199,9 @@ static int sctp_print_conntrack(struct seq_file *s,
        DEBUGP(__FUNCTION__);
        DEBUGP("\n");
 
-       READ_LOCK(&sctp_lock);
+       read_lock_bh(&sctp_lock);
        state = conntrack->proto.sctp.state;
-       READ_UNLOCK(&sctp_lock);
+       read_unlock_bh(&sctp_lock);
 
        return seq_printf(s, "%s ", sctp_conntrack_names[state]);
 }
@@ -235,12 +235,15 @@ static int do_basic_checks(struct ip_conntrack *conntrack,
                        flag = 1;
                }
 
-               /* Cookie Ack/Echo chunks not the first OR 
-                  Init / Init Ack / Shutdown compl chunks not the only chunks */
-               if ((sch->type == SCTP_CID_COOKIE_ACK 
+               /*
+                * Cookie Ack/Echo chunks not the first OR
+                * Init / Init Ack / Shutdown compl chunks not the only chunks
+                * OR zero-length.
+                */
+               if (((sch->type == SCTP_CID_COOKIE_ACK
                        || sch->type == SCTP_CID_COOKIE_ECHO
                        || flag)
-                    && count !=0 ) {
+                     && count !=0) || !sch->length) {
                        DEBUGP("Basic checks failed\n");
                        return 1;
                }
@@ -251,7 +254,7 @@ static int do_basic_checks(struct ip_conntrack *conntrack,
        }
 
        DEBUGP("Basic checks passed\n");
-       return 0;
+       return count == 0;
 }
 
 static int new_state(enum ip_conntrack_dir dir,
@@ -343,13 +346,13 @@ static int sctp_packet(struct ip_conntrack *conntrack,
 
        oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
        for_each_sctp_chunk (skb, sch, _sch, offset, count) {
-               WRITE_LOCK(&sctp_lock);
+               write_lock_bh(&sctp_lock);
 
                /* Special cases of Verification tag check (Sec 8.5.1) */
                if (sch->type == SCTP_CID_INIT) {
                        /* Sec 8.5.1 (A) */
                        if (sh->vtag != 0) {
-                               WRITE_UNLOCK(&sctp_lock);
+                               write_unlock_bh(&sctp_lock);
                                return -1;
                        }
                } else if (sch->type == SCTP_CID_ABORT) {
@@ -357,7 +360,7 @@ static int sctp_packet(struct ip_conntrack *conntrack,
                        if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
                                && !(sh->vtag == conntrack->proto.sctp.vtag
                                                        [1 - CTINFO2DIR(ctinfo)])) {
-                               WRITE_UNLOCK(&sctp_lock);
+                               write_unlock_bh(&sctp_lock);
                                return -1;
                        }
                } else if (sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
@@ -366,13 +369,13 @@ static int sctp_packet(struct ip_conntrack *conntrack,
                                && !(sh->vtag == conntrack->proto.sctp.vtag
                                                        [1 - CTINFO2DIR(ctinfo)] 
                                        && (sch->flags & 1))) {
-                               WRITE_UNLOCK(&sctp_lock);
+                               write_unlock_bh(&sctp_lock);
                                return -1;
                        }
                } else if (sch->type == SCTP_CID_COOKIE_ECHO) {
                        /* Sec 8.5.1 (D) */
                        if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
-                               WRITE_UNLOCK(&sctp_lock);
+                               write_unlock_bh(&sctp_lock);
                                return -1;
                        }
                }
@@ -384,7 +387,7 @@ static int sctp_packet(struct ip_conntrack *conntrack,
                if (newconntrack == SCTP_CONNTRACK_MAX) {
                        DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
                               CTINFO2DIR(ctinfo), sch->type, oldsctpstate);
-                       WRITE_UNLOCK(&sctp_lock);
+                       write_unlock_bh(&sctp_lock);
                        return -1;
                }
 
@@ -396,7 +399,7 @@ static int sctp_packet(struct ip_conntrack *conntrack,
                        ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
                                                sizeof(_inithdr), &_inithdr);
                        if (ih == NULL) {
-                                       WRITE_UNLOCK(&sctp_lock);
+                                       write_unlock_bh(&sctp_lock);
                                        return -1;
                        }
                        DEBUGP("Setting vtag %x for dir %d\n", 
@@ -405,7 +408,9 @@ static int sctp_packet(struct ip_conntrack *conntrack,
                }
 
                conntrack->proto.sctp.state = newconntrack;
-               WRITE_UNLOCK(&sctp_lock);
+               if (oldsctpstate != newconntrack)
+                       ip_conntrack_event_cache(IPCT_PROTOINFO, skb);
+               write_unlock_bh(&sctp_lock);
        }
 
        ip_ct_refresh_acct(conntrack, ctinfo, skb, *sctp_timeouts[newconntrack]);
@@ -415,6 +420,7 @@ static int sctp_packet(struct ip_conntrack *conntrack,
                && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
                DEBUGP("Setting assured bit\n");
                set_bit(IPS_ASSURED_BIT, &conntrack->status);
+               ip_conntrack_event_cache(IPCT_STATUS, skb);
        }
 
        return NF_ACCEPT;
@@ -504,7 +510,12 @@ static struct ip_conntrack_protocol ip_conntrack_protocol_sctp = {
        .packet          = sctp_packet, 
        .new             = sctp_new, 
        .destroy         = NULL, 
-       .me              = THIS_MODULE 
+       .me              = THIS_MODULE,
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+    defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+       .tuple_to_nfattr = ip_ct_port_tuple_to_nfattr,
+       .nfattr_to_tuple = ip_ct_port_nfattr_to_tuple,
+#endif
 };
 
 #ifdef CONFIG_SYSCTL
@@ -601,7 +612,7 @@ static ctl_table ip_ct_net_table[] = {
 static struct ctl_table_header *ip_ct_sysctl_header;
 #endif
 
-static int __init init(void)
+static int __init ip_conntrack_proto_sctp_init(void)
 {
        int ret;
 
@@ -632,7 +643,7 @@ static int __init init(void)
        return ret;
 }
 
-static void __exit fini(void)
+static void __exit ip_conntrack_proto_sctp_fini(void)
 {
        ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
 #ifdef CONFIG_SYSCTL
@@ -641,8 +652,8 @@ static void __exit fini(void)
        DEBUGP("SCTP conntrack module unloaded\n");
 }
 
-module_init(init);
-module_exit(fini);
+module_init(ip_conntrack_proto_sctp_init);
+module_exit(ip_conntrack_proto_sctp_fini);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Kiran Kumar Immidi");