Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[sfrench/cifs-2.6.git] / net / sctp / associola.c
index 039fdb862b1797686bf7e5e911379b5b47ea58f7..5d5a16204d50516eca7d5322a60aac6511178c38 100644 (file)
@@ -986,8 +986,9 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
        struct sctp_endpoint *ep;
        struct sctp_chunk *chunk;
        struct sctp_inq *inqueue;
-       int state;
+       int first_time = 1;     /* is this the first time through the loop */
        int error = 0;
+       int state;
 
        /* The association should be held so we should be safe. */
        ep = asoc->ep;
@@ -998,6 +999,30 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
                state = asoc->state;
                subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type);
 
+               /* If the first chunk in the packet is AUTH, do special
+                * processing specified in Section 6.3 of SCTP-AUTH spec
+                */
+               if (first_time && subtype.chunk == SCTP_CID_AUTH) {
+                       struct sctp_chunkhdr *next_hdr;
+
+                       next_hdr = sctp_inq_peek(inqueue);
+                       if (!next_hdr)
+                               goto normal;
+
+                       /* If the next chunk is COOKIE-ECHO, skip the AUTH
+                        * chunk while saving a pointer to it so we can do
+                        * Authentication later (during cookie-echo
+                        * processing).
+                        */
+                       if (next_hdr->type == SCTP_CID_COOKIE_ECHO) {
+                               chunk->auth_chunk = skb_clone(chunk->skb,
+                                                             GFP_ATOMIC);
+                               chunk->auth = 1;
+                               continue;
+                       }
+               }
+
+normal:
                /* SCTP-AUTH, Section 6.3:
                 *    The receiver has a list of chunk types which it expects
                 *    to be received only after an AUTH-chunk.  This list has
@@ -1036,6 +1061,9 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
                /* If there is an error on chunk, discard this packet. */
                if (error && chunk)
                        chunk->pdiscard = 1;
+
+               if (first_time)
+                       first_time = 0;
        }
        sctp_association_put(asoc);
 }