Commit 686ed0a0 authored by David S. Miller's avatar David S. Miller

Merge http://linux-lksctp.bkbits.net/lksctp-2.5.work

into nuts.davemloft.net:/disk1/BK/net-2.6
parents 6781fdec e343efc8
......@@ -93,6 +93,7 @@ typedef enum {
SCTP_CMD_PROCESS_OPERR, /* Process an ERROR chunk. */
SCTP_CMD_REPORT_FWDTSN, /* Report new cumulative TSN Ack. */
SCTP_CMD_PROCESS_FWDTSN, /* Skips were reported, so process further. */
SCTP_CMD_CLEAR_INIT_TAG, /* Clears association peer's inittag. */
SCTP_CMD_LAST
} sctp_verb_t;
......
......@@ -440,6 +440,23 @@ static inline void sctp_add_cmd_sf(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_a
BUG();
}
/* Check VTAG of the packet matches the sender's own tag. */
static inline int
sctp_vtag_verify(const struct sctp_chunk *chunk,
const struct sctp_association *asoc)
{
/* RFC 2960 Sec 8.5 When receiving an SCTP packet, the endpoint
* MUST ensure that the value in the Verification Tag field of
* the received SCTP packet matches its own Tag. If the received
* Verification Tag value does not match the receiver's own
* tag value, the receiver shall silently discard the packet...
*/
if (ntohl(chunk->sctp_hdr->vtag) == asoc->c.my_vtag)
return 1;
return 0;
}
/* Check VTAG of the packet matches the sender's own tag OR its peer's
* tag and the T bit is set in the Chunk Flags.
*/
......
......@@ -429,6 +429,9 @@ static void sctp_cmd_init_failed(sctp_cmd_seq_t *commands,
sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
SCTP_ULPEVENT(event));
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
/* SEND_FAILED sent later when cleaning up the association. */
asoc->outqueue.error = error;
sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
......@@ -457,6 +460,10 @@ static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *commands,
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
/* Set sk_err to ECONNRESET on a 1-1 style socket. */
if (!sctp_style(asoc->base.sk, UDP))
asoc->base.sk->sk_err = ECONNRESET;
/* SEND_FAILED sent later when cleaning up the association. */
asoc->outqueue.error = error;
sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
......@@ -1272,6 +1279,9 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
case SCTP_CMD_PROCESS_OPERR:
sctp_cmd_process_operr(commands, asoc, chunk);
break;
case SCTP_CMD_CLEAR_INIT_TAG:
asoc->peer.i.init_tag = 0;
break;
default:
printk(KERN_WARNING "Impossible command: %u, %p\n",
cmd->verb, cmd->obj.ptr);
......
......@@ -171,7 +171,7 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep,
* Verification Tag field to Tag_A, and also provide its own
* Verification Tag (Tag_Z) in the Initiate Tag field.
*
* Verification Tag: No checking.
* Verification Tag: Must be 0.
*
* Inputs
* (endpoint, asoc, chunk)
......@@ -219,6 +219,12 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
(sk->sk_ack_backlog >= sk->sk_max_ack_backlog)))
return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
/* 3.1 A packet containing an INIT chunk MUST have a zero Verification
* Tag.
*/
if (chunk->sctp_hdr->vtag != 0)
return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
/* Verify the INIT chunk before processing it. */
err_chunk = NULL;
if (!sctp_verify_init(asoc, chunk->chunk_hdr->type,
......@@ -377,6 +383,9 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
if (!chunk->singleton)
return SCTP_DISPOSITION_VIOLATION;
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
/* Grab the INIT header. */
chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;
......@@ -659,8 +668,12 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
const sctp_subtype_t type, void *arg,
sctp_cmd_seq_t *commands)
{
struct sctp_chunk *chunk = arg;
struct sctp_ulpevent *ev;
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
/* RFC 2960 5.1 Normal Establishment of an Association
*
* E) Upon reception of the COOKIE ACK, endpoint "A" will move
......@@ -807,13 +820,7 @@ sctp_disposition_t sctp_sf_beat_8_3(const struct sctp_endpoint *ep,
struct sctp_chunk *reply;
size_t paylen = 0;
/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
* that the value in the Verification Tag field of the
* received SCTP packet matches its own Tag. If the received
* Verification Tag value does not match the receiver's own
* tag value, the receiver shall silently discard the packet...
*/
if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
/* 8.3 The receiver of the HEARTBEAT should immediately
......@@ -876,11 +883,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
sctp_sender_hb_info_t *hbinfo;
unsigned long max_interval;
/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
* that the value in the Verification Tag field of the
* received SCTP packet matches its own Tag. ...
*/
if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data;
......@@ -1130,6 +1133,12 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
if (!chunk->singleton)
return SCTP_DISPOSITION_VIOLATION;
/* 3.1 A packet containing an INIT chunk MUST have a zero Verification
* Tag.
*/
if (chunk->sctp_hdr->vtag != 0)
return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
/* Grab the INIT header. */
chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;
......@@ -1386,6 +1395,8 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep,
sctp_init_chunk_t *peer_init;
struct sctp_ulpevent *ev;
struct sctp_chunk *repl;
struct sctp_chunk *err;
sctp_disposition_t disposition;
/* new_asoc is a brand-new association, so these are not yet
* side effects--it is safe to run them here.
......@@ -1405,6 +1416,29 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep,
return SCTP_DISPOSITION_CONSUME;
}
/* If the endpoint is in the SHUTDOWN-ACK-SENT state and recognizes
* the peer has restarted (Action A), it MUST NOT setup a new
* association but instead resend the SHUTDOWN ACK and send an ERROR
* chunk with a "Cookie Received while Shutting Down" error cause to
* its peer.
*/
if (sctp_state(asoc, SHUTDOWN_ACK_SENT)) {
disposition = sctp_sf_do_9_2_reshutack(ep, asoc,
SCTP_ST_CHUNK(chunk->chunk_hdr->type),
chunk, commands);
if (SCTP_DISPOSITION_NOMEM == disposition)
goto nomem;
err = sctp_make_op_error(asoc, chunk,
SCTP_ERROR_COOKIE_IN_SHUTDOWN,
NULL, 0);
if (err)
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(err));
return SCTP_DISPOSITION_CONSUME;
}
/* For now, fail any unsent/unacked data. Consider the optional
* choice of resending of this data.
*/
......@@ -1883,6 +1917,9 @@ sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
sctp_addto_chunk(reply, sizeof(bht), &bht);
/* Clear peer's init_tag cached in assoc as we are sending a new INIT */
sctp_add_cmd_sf(commands, SCTP_CMD_CLEAR_INIT_TAG, SCTP_NULL());
/* Cast away the const modifier, as we want to just
* rerun it through as a sideffect.
*/
......@@ -2071,13 +2108,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
skb_pull(chunk->skb, sizeof(sctp_shutdownhdr_t));
chunk->subh.shutdown_hdr = sdh;
/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
* that the value in the Verification Tag field of the
* received SCTP packet matches its own Tag. If the received
* Verification Tag value does not match the receiver's own
* tag value, the receiver shall silently discard the packet...
*/
if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
/* Upon the reception of the SHUTDOWN, the peer endpoint shall
......@@ -2190,13 +2221,7 @@ sctp_disposition_t sctp_sf_do_ecn_cwr(const struct sctp_endpoint *ep,
sctp_cwrhdr_t *cwr;
struct sctp_chunk *chunk = arg;
/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
* that the value in the Verification Tag field of the
* received SCTP packet matches its own Tag. If the received
* Verification Tag value does not match the receiver's own
* tag value, the receiver shall silently discard the packet...
*/
if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
cwr = (sctp_cwrhdr_t *) chunk->skb->data;
......@@ -2246,13 +2271,7 @@ sctp_disposition_t sctp_sf_do_ecne(const struct sctp_endpoint *ep,
sctp_ecnehdr_t *ecne;
struct sctp_chunk *chunk = arg;
/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
* that the value in the Verification Tag field of the
* received SCTP packet matches its own Tag. If the received
* Verification Tag value does not match the receiver's own
* tag value, the receiver shall silently discard the packet...
*/
if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
ecne = (sctp_ecnehdr_t *) chunk->skb->data;
......@@ -2309,13 +2328,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
int tmp;
__u32 tsn;
/* RFC 2960 8.5 Verification Tag
*
* When receiving an SCTP packet, the endpoint MUST ensure
* that the value in the Verification Tag field of the
* received SCTP packet matches its own Tag.
*/
if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag) {
if (!sctp_vtag_verify(chunk, asoc)) {
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
SCTP_NULL());
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
......@@ -2569,13 +2582,7 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const struct sctp_endpoint *ep,
int tmp;
__u32 tsn;
/* RFC 2960 8.5 Verification Tag
*
* When receiving an SCTP packet, the endpoint MUST ensure
* that the value in the Verification Tag field of the
* received SCTP packet matches its own Tag.
*/
if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag) {
if (!sctp_vtag_verify(chunk, asoc)) {
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
SCTP_NULL());
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
......@@ -2745,11 +2752,7 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep,
sctp_sackhdr_t *sackh;
__u32 ctsn;
/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
* that the value in the Verification Tag field of the
* received SCTP packet matches its own Tag. ...
*/
if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
/* Pull the SACK chunk from the data buffer */
......@@ -2895,6 +2898,9 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep,
struct sctp_chunk *reply;
struct sctp_ulpevent *ev;
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
/* 10.2 H) SHUTDOWN COMPLETE notification
*
* When SCTP completes the shutdown procedures (section 9.2) this
......@@ -3229,13 +3235,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(const struct sctp_endpoint *ep,
__u16 len;
__u32 tsn;
/* RFC 2960 8.5 Verification Tag
*
* When receiving an SCTP packet, the endpoint MUST ensure
* that the value in the Verification Tag field of the
* received SCTP packet matches its own Tag.
*/
if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag) {
if (!sctp_vtag_verify(chunk, asoc)) {
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
SCTP_NULL());
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
......@@ -3293,13 +3293,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn_fast(
__u16 len;
__u32 tsn;
/* RFC 2960 8.5 Verification Tag
*
* When receiving an SCTP packet, the endpoint MUST ensure
* that the value in the Verification Tag field of the
* received SCTP packet matches its own Tag.
*/
if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag) {
if (!sctp_vtag_verify(chunk, asoc)) {
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
SCTP_NULL());
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
......@@ -3376,13 +3370,7 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep,
SCTP_DEBUG_PRINTK("Processing the unknown chunk id %d.\n", type.chunk);
/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
* that the value in the Verification Tag field of the
* received SCTP packet matches its own Tag. If the received
* Verification Tag value does not match the receiver's own
* tag value, the receiver shall silently discard the packet.
*/
if (ntohl(unk_chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
if (!sctp_vtag_verify(unk_chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
switch (type.chunk & SCTP_CID_ACTION_MASK) {
......
......@@ -1164,6 +1164,11 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
if (!asoc) {
SCTP_DEBUG_PRINTK("There is no association yet.\n");
if (sinfo_flags & (MSG_EOF | MSG_ABORT)) {
err = -EINVAL;
goto out_unlock;
}
/* Check for invalid stream against the stream counts,
* either the default or the user specified stream counts.
*/
......@@ -4388,6 +4393,10 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p)
return err;
do_error:
if (asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1 >=
asoc->max_init_attempts)
err = -ETIMEDOUT;
else
err = -ECONNREFUSED;
goto out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment