summaryrefslogtreecommitdiff
path: root/netinet/sctp_indata.c
diff options
context:
space:
mode:
Diffstat (limited to 'netinet/sctp_indata.c')
-rwxr-xr-xnetinet/sctp_indata.c80
1 files changed, 73 insertions, 7 deletions
diff --git a/netinet/sctp_indata.c b/netinet/sctp_indata.c
index 2801704..125c82f 100755
--- a/netinet/sctp_indata.c
+++ b/netinet/sctp_indata.c
@@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.c 263237 2014-03-16 12:32:16Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.c 264838 2014-04-23 21:20:55Z tuexen $");
#endif
#include <netinet/sctp_os.h>
@@ -844,7 +844,6 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
{
struct mbuf *op_err;
char msg[SCTP_DIAG_INFO_LEN];
-
uint32_t cum_ackp1, prev_tsn, post_tsn;
struct sctp_tmit_chunk *at, *prev, *next;
@@ -1018,9 +1017,9 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
* Huh, need the correct STR here,
* they must be the same.
*/
- SCTP_PRINTF("Prev check - Gak, Evil plot, sid:%d not the same as at:%d\n",
- chk->rec.data.stream_number,
- prev->rec.data.stream_number);
+ SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - Gak, Evil plot, sid:%d not the same as at:%d\n",
+ chk->rec.data.stream_number,
+ prev->rec.data.stream_number);
snprintf(msg, sizeof(msg),
"Expect SID=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
prev->rec.data.stream_number,
@@ -1033,6 +1032,24 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
*abort_flag = 1;
return;
}
+ if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) !=
+ (prev->rec.data.rcv_flags & SCTP_DATA_UNORDERED)) {
+ /*
+ * Huh, need the same ordering here,
+ * they must be the same.
+ */
+ SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - Gak, Evil plot, U-bit not constant\n");
+ snprintf(msg, sizeof(msg),
+ "Expect U-bit=%d for TSN=%8.8x, got U-bit=%d",
+ (prev->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0,
+ chk->rec.data.TSN_seq,
+ (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0);
+ op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
+ stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_7;
+ sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
+ *abort_flag = 1;
+ return;
+ }
if ((prev->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == 0 &&
chk->rec.data.stream_seq !=
prev->rec.data.stream_seq) {
@@ -1143,6 +1160,24 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
*abort_flag = 1;
return;
}
+ if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) !=
+ (next->rec.data.rcv_flags & SCTP_DATA_UNORDERED)) {
+ /*
+ * Huh, need the same ordering here,
+ * they must be the same.
+ */
+ SCTPDBG(SCTP_DEBUG_INDATA1, "Next check - Gak, Evil plot, U-bit not constant\n");
+ snprintf(msg, sizeof(msg),
+ "Expect U-bit=%d for TSN=%8.8x, got U-bit=%d",
+ (next->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0,
+ chk->rec.data.TSN_seq,
+ (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0);
+ op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
+ stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_12;
+ sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
+ *abort_flag = 1;
+ return;
+ }
if ((next->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == 0 &&
chk->rec.data.stream_seq !=
next->rec.data.stream_seq) {
@@ -1694,6 +1729,9 @@ failed_express_del:
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_15;
sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
+ if (last_chunk) {
+ *m = NULL;
+ }
return (0);
} else {
if (sctp_does_tsn_belong_to_reasm(asoc, control->sinfo_tsn)) {
@@ -1710,6 +1748,9 @@ failed_express_del:
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_16;
sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
+ if (last_chunk) {
+ *m = NULL;
+ }
return (0);
}
}
@@ -1736,6 +1777,9 @@ failed_express_del:
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_17;
sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
+ if (last_chunk) {
+ *m = NULL;
+ }
return (0);
}
}
@@ -1798,6 +1842,9 @@ failed_express_del:
} else {
sctp_queue_data_to_stream(stcb, asoc, control, abort_flag);
if (*abort_flag) {
+ if (last_chunk) {
+ *m = NULL;
+ }
return (0);
}
}
@@ -1810,7 +1857,9 @@ failed_express_del:
* the assoc is now gone and chk was put onto the
* reasm queue, which has all been freed.
*/
- *m = NULL;
+ if (last_chunk) {
+ *m = NULL;
+ }
return (0);
}
}
@@ -2339,7 +2388,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
continue;
}
if (ch->ch.chunk_type == SCTP_DATA) {
- if ((size_t)chk_length < sizeof(struct sctp_data_chunk) + 1) {
+ if ((size_t)chk_length < sizeof(struct sctp_data_chunk)) {
/*
* Need to send an abort since we had a
* invalid data chunk.
@@ -2359,6 +2408,23 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
vrf_id, port);
return (2);
}
+ if ((size_t)chk_length == sizeof(struct sctp_data_chunk)) {
+ /*
+ * Need to send an abort since we had an
+ * empty data chunk.
+ */
+ struct mbuf *op_err;
+
+ op_err = sctp_generate_no_user_data_cause(ch->dp.tsn);
+ stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_19;
+ sctp_abort_association(inp, stcb, m, iphlen,
+ src, dst, sh, op_err,
+#if defined(__FreeBSD__)
+ use_mflowid, mflowid,
+#endif
+ vrf_id, port);
+ return (2);
+ }
#ifdef SCTP_AUDITING_ENABLED
sctp_audit_log(0xB1, 0);
#endif