summaryrefslogtreecommitdiffstats
path: root/net/sctp/endpointola.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/endpointola.c')
-rw-r--r--net/sctp/endpointola.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index c8d5023606a..2d2d81ef4a6 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -400,6 +400,7 @@ static void sctp_endpoint_bh_rcv(struct work_struct *work)
sctp_subtype_t subtype;
sctp_state_t state;
int error = 0;
+ int first_time = 1; /* is this the first time through the looop */
if (ep->base.dead)
return;
@@ -411,6 +412,29 @@ static void sctp_endpoint_bh_rcv(struct work_struct *work)
while (NULL != (chunk = sctp_inq_pop(inqueue))) {
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:
/* We might have grown an association since last we
* looked, so try again.
*
@@ -426,6 +450,8 @@ static void sctp_endpoint_bh_rcv(struct work_struct *work)
}
state = asoc ? asoc->state : SCTP_STATE_CLOSED;
+ if (sctp_auth_recv_cid(subtype.chunk, asoc) && !chunk->auth)
+ continue;
/* Remember where the last DATA chunk came from so we
* know where to send the SACK.
@@ -449,5 +475,8 @@ static void sctp_endpoint_bh_rcv(struct work_struct *work)
*/
if (!sctp_sk(sk)->ep)
break;
+
+ if (first_time)
+ first_time = 0;
}
}