Merge git://oss.sgi.com:8090/xfs/xfs-2.6
[linux-drm-fsl-dcu.git] / net / sctp / input.c
index 42b66e74bbb504cf38b7ea088895ab49a7446280..71db66873695ffadeed4ac18cc68454dfbc7ab44 100644 (file)
@@ -135,6 +135,9 @@ int sctp_rcv(struct sk_buff *skb)
 
        SCTP_INC_STATS_BH(SCTP_MIB_INSCTPPACKS);
 
+       if (skb_linearize(skb))
+               goto discard_it;
+
        sh = (struct sctphdr *) skb->h.raw;
 
        /* Pull up the IP and SCTP headers. */
@@ -218,18 +221,12 @@ int sctp_rcv(struct sk_buff *skb)
                }
        }
 
-       /* SCTP seems to always need a timestamp right now (FIXME) */
-       if (skb->tstamp.off_sec == 0) {
-               __net_timestamp(skb);
-               sock_enable_timestamp(sk); 
-       }
-
        if (!xfrm_policy_check(sk, XFRM_POLICY_IN, skb, family))
                goto discard_release;
        nf_reset(skb);
 
-       if (sk_filter(sk, skb, 1))
-                goto discard_release;
+       if (sk_filter(sk, skb))
+               goto discard_release;
 
        /* Create an SCTP packet structure. */
        chunk = sctp_chunkify(skb, asoc, sk);
@@ -255,10 +252,13 @@ int sctp_rcv(struct sk_buff *skb)
         */
        sctp_bh_lock_sock(sk);
 
-       if (sock_owned_by_user(sk))
+       if (sock_owned_by_user(sk)) {
+               SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_BACKLOG);
                sctp_add_backlog(sk, skb);
-       else
+       } else {
+               SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_SOFTIRQ);
                sctp_inq_push(&chunk->rcvr->inqueue, chunk);
+       }
 
        sctp_bh_unlock_sock(sk);
 
@@ -271,6 +271,7 @@ int sctp_rcv(struct sk_buff *skb)
        return 0;
 
 discard_it:
+       SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_DISCARDS);
        kfree_skb(skb);
        return 0;
 
@@ -292,11 +293,11 @@ discard_release:
 int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 {
        struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
-       struct sctp_inq *inqueue = &chunk->rcvr->inqueue;
-       struct sctp_ep_common *rcvr = NULL;
+       struct sctp_inq *inqueue = &chunk->rcvr->inqueue;
+       struct sctp_ep_common *rcvr = NULL;
        int backloged = 0;
 
-       rcvr = chunk->rcvr;
+       rcvr = chunk->rcvr;
 
        /* If the rcvr is dead then the association or endpoint
         * has been deleted and we can safely drop the chunk
@@ -346,7 +347,7 @@ done:
        else
                BUG();
 
-        return 0;
+       return 0;
 }
 
 static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
@@ -384,7 +385,7 @@ void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
                         * pmtu discovery on this transport.
                         */
                        t->pathmtu = SCTP_DEFAULT_MINSEGMENT;
-                       t->param_flags = (t->param_flags & ~SPP_HB) |
+                       t->param_flags = (t->param_flags & ~SPP_PMTUD) |
                                SPP_PMTUD_DISABLE;
                } else {
                        t->pathmtu = pmtu;
@@ -398,7 +399,7 @@ void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
         * Normally, if PMTU discovery is disabled, an ICMP Fragmentation
         * Needed will never be sent, but if a message was sent before
         * PMTU discovery was disabled that was larger than the PMTU, it
-        * would not be fragmented, so it must be re-transmitted fragmented.     
+        * would not be fragmented, so it must be re-transmitted fragmented.
         */
        sctp_retransmit(&asoc->outqueue, t, SCTP_RTXR_PMTUD);
 }
@@ -415,8 +416,8 @@ void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
  *
  */
 void sctp_icmp_proto_unreachable(struct sock *sk,
-                           struct sctp_association *asoc,
-                           struct sctp_transport *t)
+                          struct sctp_association *asoc,
+                          struct sctp_transport *t)
 {
        SCTP_DEBUG_PRINTK("%s\n",  __FUNCTION__);
 
@@ -725,7 +726,7 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l
        struct sctp_endpoint *ep;
        int hash;
 
-       hash = sctp_ep_hashfn(laddr->v4.sin_port);
+       hash = sctp_ep_hashfn(ntohs(laddr->v4.sin_port));
        head = &sctp_ep_hashtable[hash];
        read_lock(&head->lock);
        for (epb = head->chain; epb; epb = epb->next) {
@@ -770,6 +771,9 @@ static void __sctp_hash_established(struct sctp_association *asoc)
 /* Add an association to the hash. Local BH-safe. */
 void sctp_hash_established(struct sctp_association *asoc)
 {
+       if (asoc->temp)
+               return;
+
        sctp_local_bh_disable();
        __sctp_hash_established(asoc);
        sctp_local_bh_enable();
@@ -803,6 +807,9 @@ static void __sctp_unhash_established(struct sctp_association *asoc)
 /* Remove association from the hash table.  Local BH-safe. */
 void sctp_unhash_established(struct sctp_association *asoc)
 {
+       if (asoc->temp)
+               return;
+
        sctp_local_bh_disable();
        __sctp_unhash_established(asoc);
        sctp_local_bh_enable();
@@ -823,7 +830,7 @@ static struct sctp_association *__sctp_lookup_association(
        /* Optimize here for direct hit, only listening connections can
         * have wildcards anyways.
         */
-       hash = sctp_assoc_hashfn(local->v4.sin_port, peer->v4.sin_port);
+       hash = sctp_assoc_hashfn(ntohs(local->v4.sin_port), ntohs(peer->v4.sin_port));
        head = &sctp_assoc_hashtable[hash];
        read_lock(&head->lock);
        for (epb = head->chain; epb; epb = epb->next) {
@@ -950,7 +957,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
                if (!af)
                        continue;
 
-               af->from_addr_param(paddr, params.addr, ntohs(sh->source), 0);
+               af->from_addr_param(paddr, params.addr, sh->source, 0);
 
                asoc = __sctp_lookup_association(laddr, paddr, &transport);
                if (asoc)