Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 66621
b: refs/heads/master
c: bbd0d59
h: refs/heads/master
i:
  66619: 619d491
v: v3
  • Loading branch information
Vlad Yasevich authored and David S. Miller committed Oct 10, 2007
1 parent 76610a6 commit 57e7fbb
Show file tree
Hide file tree
Showing 10 changed files with 375 additions and 14 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4cd57c8078fae0a4b1bf421191e94626d0cba92a
refs/heads/master: bbd0d59809f923ea2b540cbd781b32110e249f6e
4 changes: 3 additions & 1 deletion trunk/include/net/sctp/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,9 @@ typedef enum {
SCTP_IERROR_NO_DATA,
SCTP_IERROR_BAD_STREAM,
SCTP_IERROR_BAD_PORTS,

SCTP_IERROR_AUTH_BAD_HMAC,
SCTP_IERROR_AUTH_BAD_KEYID,
SCTP_IERROR_PROTO_VIOLATION,
} sctp_ierror_t;


Expand Down
1 change: 1 addition & 0 deletions trunk/include/net/sctp/sm.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ sctp_state_fn_t sctp_sf_do_asconf_ack;
sctp_state_fn_t sctp_sf_do_9_2_reshutack;
sctp_state_fn_t sctp_sf_eat_fwd_tsn;
sctp_state_fn_t sctp_sf_eat_fwd_tsn_fast;
sctp_state_fn_t sctp_sf_eat_auth;

/* Prototypes for primitive event state functions. */
sctp_state_fn_t sctp_sf_do_prm_asoc;
Expand Down
8 changes: 8 additions & 0 deletions trunk/include/net/sctp/structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,13 @@ struct sctp_chunk {
*/
struct sctp_transport *transport;

/* SCTP-AUTH: For the special case inbound processing of COOKIE-ECHO
* we need save a pointer to the AUTH chunk, since the SCTP-AUTH
* spec violates the principle premis that all chunks are processed
* in order.
*/
struct sk_buff *auth_chunk;

__u8 rtt_in_progress; /* Is this chunk used for RTT calculation? */
__u8 resent; /* Has this chunk ever been retransmitted. */
__u8 has_tsn; /* Does this chunk have a TSN yet? */
Expand Down Expand Up @@ -1067,6 +1074,7 @@ void sctp_inq_init(struct sctp_inq *);
void sctp_inq_free(struct sctp_inq *);
void sctp_inq_push(struct sctp_inq *, struct sctp_chunk *packet);
struct sctp_chunk *sctp_inq_pop(struct sctp_inq *);
struct sctp_chunkhdr *sctp_inq_peek(struct sctp_inq *);
void sctp_inq_set_th_handler(struct sctp_inq *, work_func_t);

/* This is the structure we use to hold outbound chunks. You push
Expand Down
10 changes: 10 additions & 0 deletions trunk/net/sctp/associola.c
Original file line number Diff line number Diff line change
Expand Up @@ -1011,6 +1011,16 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
state = asoc->state;
subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type);

/* 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
* been sent to the peer during the association setup. It
* MUST silently discard these chunks if they are not placed
* after an AUTH chunk in the packet.
*/
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.
*/
Expand Down
29 changes: 29 additions & 0 deletions trunk/net/sctp/endpointola.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
*
Expand All @@ -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.
Expand All @@ -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;
}
}
65 changes: 55 additions & 10 deletions trunk/net/sctp/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -911,15 +911,6 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,

ch = (sctp_chunkhdr_t *) skb->data;

/* If this is INIT/INIT-ACK look inside the chunk too. */
switch (ch->type) {
case SCTP_CID_INIT:
case SCTP_CID_INIT_ACK:
break;
default:
return NULL;
}

/* The code below will attempt to walk the chunk and extract
* parameter information. Before we do that, we need to verify
* that the chunk length doesn't cause overflow. Otherwise, we'll
Expand Down Expand Up @@ -964,6 +955,60 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
return NULL;
}

/* SCTP-AUTH, Section 6.3:
* If the receiver does not find a STCB for a packet containing an AUTH
* chunk as the first chunk and not a COOKIE-ECHO chunk as the second
* chunk, it MUST use the chunks after the AUTH chunk to look up an existing
* association.
*
* This means that any chunks that can help us identify the association need
* to be looked at to find this assocation.
*
* TODO: The only chunk currently defined that can do that is ASCONF, but we
* don't support that functionality yet.
*/
static struct sctp_association *__sctp_rcv_auth_lookup(struct sk_buff *skb,
const union sctp_addr *paddr,
const union sctp_addr *laddr,
struct sctp_transport **transportp)
{
/* XXX - walk through the chunks looking for something that can
* help us find the association. INIT, and INIT-ACK are not permitted.
* That leaves ASCONF, but we don't support that yet.
*/
return NULL;
}

/*
* There are circumstances when we need to look inside the SCTP packet
* for information to help us find the association. Examples
* include looking inside of INIT/INIT-ACK chunks or after the AUTH
* chunks.
*/
static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
const union sctp_addr *paddr,
const union sctp_addr *laddr,
struct sctp_transport **transportp)
{
sctp_chunkhdr_t *ch;

ch = (sctp_chunkhdr_t *) skb->data;

/* If this is INIT/INIT-ACK look inside the chunk too. */
switch (ch->type) {
case SCTP_CID_INIT:
case SCTP_CID_INIT_ACK:
return __sctp_rcv_init_lookup(skb, laddr, transportp);
break;

case SCTP_CID_AUTH:
return __sctp_rcv_auth_lookup(skb, paddr, laddr, transportp);
break;
}

return NULL;
}

/* Lookup an association for an inbound skb. */
static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
const union sctp_addr *paddr,
Expand All @@ -979,7 +1024,7 @@ static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
* parameters within the INIT or INIT-ACK.
*/
if (!asoc)
asoc = __sctp_rcv_init_lookup(skb, laddr, transportp);
asoc = __sctp_rcv_lookup_harder(skb, paddr, laddr, transportp);

return asoc;
}
19 changes: 19 additions & 0 deletions trunk/net/sctp/inqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,25 @@ void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *chunk)
q->immediate.func(&q->immediate);
}

/* Peek at the next chunk on the inqeue. */
struct sctp_chunkhdr *sctp_inq_peek(struct sctp_inq *queue)
{
struct sctp_chunk *chunk;
sctp_chunkhdr_t *ch = NULL;

chunk = queue->in_progress;
/* If there is no more chunks in this packet, say so */
if (chunk->singleton ||
chunk->end_of_packet ||
chunk->pdiscard)
return NULL;

ch = (sctp_chunkhdr_t *)chunk->chunk_end;

return ch;
}


/* Extract a chunk from an SCTP inqueue.
*
* WARNING: If you need to put the chunk on another queue, you need to
Expand Down
Loading

0 comments on commit 57e7fbb

Please sign in to comment.