diff options
Diffstat (limited to 'netinet/sctp_indata.c')
-rwxr-xr-x | netinet/sctp_indata.c | 80 |
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 |