From owner-svn-src-all@FreeBSD.ORG Sat May 5 20:07:33 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id DDAFB106566C; Sat, 5 May 2012 20:07:33 +0000 (UTC) (envelope-from tuexen@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id C58AF8FC08; Sat, 5 May 2012 20:07:33 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q45K7XXI073528; Sat, 5 May 2012 20:07:33 GMT (envelope-from tuexen@svn.freebsd.org) Received: (from tuexen@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q45K7X4e073525; Sat, 5 May 2012 20:07:33 GMT (envelope-from tuexen@svn.freebsd.org) Message-Id: <201205052007.q45K7X4e073525@svn.freebsd.org> From: Michael Tuexen Date: Sat, 5 May 2012 20:07:33 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r235064 - head/sys/netinet X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 05 May 2012 20:07:34 -0000 Author: tuexen Date: Sat May 5 20:07:33 2012 New Revision: 235064 URL: http://svn.freebsd.org/changeset/base/235064 Log: Honor SCTP_ENABLE_STREAM_RESET socket option when processing incoming requests. Fix also the provided result in the response and use names as specified in RFC 6525. MFC after: 3 days Modified: head/sys/netinet/sctp_header.h head/sys/netinet/sctp_input.c Modified: head/sys/netinet/sctp_header.h ============================================================================== --- head/sys/netinet/sctp_header.h Sat May 5 19:42:38 2012 (r235063) +++ head/sys/netinet/sctp_header.h Sat May 5 20:07:33 2012 (r235064) @@ -499,12 +499,13 @@ struct sctp_stream_reset_add_strm { uint16_t reserved; } SCTP_PACKED; -#define SCTP_STREAM_RESET_NOTHING 0x00000000 /* Nothing for me to do */ -#define SCTP_STREAM_RESET_PERFORMED 0x00000001 /* Did it */ -#define SCTP_STREAM_RESET_REJECT 0x00000002 /* refused to do it */ -#define SCTP_STREAM_RESET_ERROR_STR 0x00000003 /* bad Stream no */ -#define SCTP_STREAM_RESET_TRY_LATER 0x00000004 /* collision, try again */ -#define SCTP_STREAM_RESET_BAD_SEQNO 0x00000005 /* bad str-reset seq no */ +#define SCTP_STREAM_RESET_RESULT_NOTHING_TO_DO 0x00000000 /* XXX: unused */ +#define SCTP_STREAM_RESET_RESULT_PERFORMED 0x00000001 +#define SCTP_STREAM_RESET_RESULT_DENIED 0x00000002 +#define SCTP_STREAM_RESET_RESULT_ERR__WRONG_SSN 0x00000003 /* XXX: unused */ +#define SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS 0x00000004 +#define SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO 0x00000005 +#define SCTP_STREAM_RESET_RESULT_IN_PROGRESS 0x00000006 /* XXX: unused */ /* * convience structures, note that if you are making a request for specific Modified: head/sys/netinet/sctp_input.c ============================================================================== --- head/sys/netinet/sctp_input.c Sat May 5 19:42:38 2012 (r235063) +++ head/sys/netinet/sctp_input.c Sat May 5 20:07:33 2012 (r235064) @@ -3599,7 +3599,7 @@ sctp_handle_stream_reset_response(struct asoc->stream_reset_out_is_outstanding = 0; if (asoc->stream_reset_outstanding) asoc->stream_reset_outstanding--; - if (action == SCTP_STREAM_RESET_PERFORMED) { + if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { /* do it */ sctp_reset_out_streams(stcb, number_entries, srparam->list_of_streams); } else { @@ -3610,7 +3610,7 @@ sctp_handle_stream_reset_response(struct number_entries = (lparm_len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t); if (asoc->stream_reset_outstanding) asoc->stream_reset_outstanding--; - if (action != SCTP_STREAM_RESET_PERFORMED) { + if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) { sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_IN, stcb, number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED); } @@ -3626,7 +3626,7 @@ sctp_handle_stream_reset_response(struct stcb->asoc.strm_pending_add_size = 0; if (asoc->stream_reset_outstanding) asoc->stream_reset_outstanding--; - if (action == SCTP_STREAM_RESET_PERFORMED) { + if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { /* Put the new streams into effect */ stcb->asoc.streamoutcnt += num_stream; sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0); @@ -3637,7 +3637,7 @@ sctp_handle_stream_reset_response(struct } else if (type == SCTP_STR_RESET_ADD_IN_STREAMS) { if (asoc->stream_reset_outstanding) asoc->stream_reset_outstanding--; - if (action != SCTP_STREAM_RESET_PERFORMED) { + if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) { sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, SCTP_STREAM_CHANGED_DENIED); } @@ -3655,7 +3655,7 @@ sctp_handle_stream_reset_response(struct /* huh ? */ return (0); } - if (action == SCTP_STREAM_RESET_PERFORMED) { + if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { resp = (struct sctp_stream_reset_response_tsn *)respin; asoc->stream_reset_outstanding--; fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk)); @@ -3714,10 +3714,12 @@ sctp_handle_str_reset_request_in(struct seq = ntohl(req->request_seq); if (asoc->str_reset_seq_in == seq) { - if (trunc) { + asoc->last_reset_action[1] = asoc->last_reset_action[0]; + if (!(asoc->local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) { + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; + } else if (trunc) { /* Can't do it, since they exceeded our buffer size */ - asoc->last_reset_action[1] = asoc->last_reset_action[0]; - asoc->last_reset_action[0] = SCTP_STREAM_RESET_REJECT; + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; } else if (stcb->asoc.stream_reset_out_is_outstanding == 0) { len = ntohs(req->ph.param_length); number_entries = ((len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t)); @@ -3725,9 +3727,7 @@ sctp_handle_str_reset_request_in(struct temp = ntohs(req->list_of_streams[i]); req->list_of_streams[i] = temp; } - /* move the reset action back one */ - asoc->last_reset_action[1] = asoc->last_reset_action[0]; - asoc->last_reset_action[0] = SCTP_STREAM_RESET_PERFORMED; + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; sctp_add_stream_reset_out(chk, number_entries, req->list_of_streams, asoc->str_reset_seq_out, seq, (asoc->sending_seq - 1)); @@ -3737,8 +3737,7 @@ sctp_handle_str_reset_request_in(struct stcb->asoc.stream_reset_outstanding++; } else { /* Can't do it, since we have sent one out */ - asoc->last_reset_action[1] = asoc->last_reset_action[0]; - asoc->last_reset_action[0] = SCTP_STREAM_RESET_TRY_LATER; + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS; } sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); asoc->str_reset_seq_in++; @@ -3747,7 +3746,7 @@ sctp_handle_str_reset_request_in(struct } else if (asoc->str_reset_seq_in - 2 == seq) { sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); } else { - sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_BAD_SEQNO); + sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); } } @@ -3769,7 +3768,13 @@ sctp_handle_str_reset_request_tsn(struct seq = ntohl(req->request_seq); if (asoc->str_reset_seq_in == seq) { - fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk)); + if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { + stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; + stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; + + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; + } else + fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk)); fwdtsn.ch.chunk_type = SCTP_FORWARD_CUM_TSN; fwdtsn.ch.chunk_flags = 0; fwdtsn.new_cumulative_tsn = htonl(stcb->asoc.highest_tsn_inside_map + 1); @@ -3777,45 +3782,41 @@ sctp_handle_str_reset_request_tsn(struct if (abort_flag) { return (1); } - stcb->asoc.highest_tsn_inside_map += SCTP_STREAM_RESET_TSN_DELTA; + asoc->highest_tsn_inside_map += SCTP_STREAM_RESET_TSN_DELTA; if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { sctp_log_map(0, 10, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); } - stcb->asoc.tsn_last_delivered = stcb->asoc.cumulative_tsn = stcb->asoc.highest_tsn_inside_map; - stcb->asoc.mapping_array_base_tsn = stcb->asoc.highest_tsn_inside_map + 1; - memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size); - stcb->asoc.highest_tsn_inside_nr_map = stcb->asoc.highest_tsn_inside_map; - memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.mapping_array_size); - atomic_add_int(&stcb->asoc.sending_seq, 1); + asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->highest_tsn_inside_map; + asoc->mapping_array_base_tsn = asoc->highest_tsn_inside_map + 1; + memset(asoc->mapping_array, 0, asoc->mapping_array_size); + asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map; + memset(asoc->nr_mapping_array, 0, asoc->mapping_array_size); + atomic_add_int(&asoc->sending_seq, 1); /* save off historical data for retrans */ - stcb->asoc.last_sending_seq[1] = stcb->asoc.last_sending_seq[0]; - stcb->asoc.last_sending_seq[0] = stcb->asoc.sending_seq; - stcb->asoc.last_base_tsnsent[1] = stcb->asoc.last_base_tsnsent[0]; - stcb->asoc.last_base_tsnsent[0] = stcb->asoc.mapping_array_base_tsn; + asoc->last_sending_seq[1] = asoc->last_sending_seq[0]; + asoc->last_sending_seq[0] = asoc->sending_seq; + asoc->last_base_tsnsent[1] = asoc->last_base_tsnsent[0]; + asoc->last_base_tsnsent[0] = asoc->mapping_array_base_tsn; sctp_add_stream_reset_result_tsn(chk, ntohl(req->request_seq), - SCTP_STREAM_RESET_PERFORMED, - stcb->asoc.sending_seq, - stcb->asoc.mapping_array_base_tsn); + SCTP_STREAM_RESET_RESULT_PERFORMED, + asoc->sending_seq, + asoc->mapping_array_base_tsn); sctp_reset_out_streams(stcb, 0, (uint16_t *) NULL); sctp_reset_in_stream(stcb, 0, (uint16_t *) NULL); - stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; - stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_PERFORMED; - sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 0); + asoc->last_reset_action[1] = asoc->last_reset_action[0]; + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; + sctp_notify_stream_reset_tsn(stcb, asoc->sending_seq, (asoc->mapping_array_base_tsn + 1), 0); asoc->str_reset_seq_in++; } else if (asoc->str_reset_seq_in - 1 == seq) { sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[0], - stcb->asoc.last_sending_seq[0], - stcb->asoc.last_base_tsnsent[0] - ); + asoc->last_sending_seq[0], asoc->last_base_tsnsent[0]); } else if (asoc->str_reset_seq_in - 2 == seq) { sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[1], - stcb->asoc.last_sending_seq[1], - stcb->asoc.last_base_tsnsent[1] - ); + asoc->last_sending_seq[1], asoc->last_base_tsnsent[1]); } else { - sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_BAD_SEQNO); + sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); } return (0); } @@ -3846,12 +3847,14 @@ sctp_handle_str_reset_request_out(struct /* move the reset action back one */ asoc->last_reset_action[1] = asoc->last_reset_action[0]; - if (trunc) { - asoc->last_reset_action[0] = SCTP_STREAM_RESET_REJECT; + if (!(asoc->local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) { + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; + } else if (trunc) { + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; } else if (SCTP_TSN_GE(asoc->cumulative_tsn, tsn)) { /* we can do it now */ sctp_reset_in_stream(stcb, number_entries, req->list_of_streams); - asoc->last_reset_action[0] = SCTP_STREAM_RESET_PERFORMED; + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; } else { /* * we must queue it up and thus wait for the TSN's @@ -3865,8 +3868,8 @@ sctp_handle_str_reset_request_out(struct siz, SCTP_M_STRESET); if (liste == NULL) { /* gak out of memory */ - sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_REJECT); - asoc->last_reset_action[0] = SCTP_STREAM_RESET_REJECT; + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; + sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); return; } liste->tsn = tsn; @@ -3874,7 +3877,7 @@ sctp_handle_str_reset_request_out(struct memcpy(&liste->req, req, (sizeof(struct sctp_stream_reset_out_request) + (number_entries * sizeof(uint16_t)))); TAILQ_INSERT_TAIL(&asoc->resetHead, liste, next_resp); - asoc->last_reset_action[0] = SCTP_STREAM_RESET_PERFORMED; + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; } sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); asoc->str_reset_seq_in++; @@ -3891,7 +3894,7 @@ sctp_handle_str_reset_request_out(struct */ sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); } else { - sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_BAD_SEQNO); + sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); } } @@ -3914,12 +3917,14 @@ sctp_handle_str_reset_add_strm(struct sc /* Now what would be the new total? */ if (asoc->str_reset_seq_in == seq) { num_stream += stcb->asoc.streamincnt; - if ((num_stream > stcb->asoc.max_inbound_streams) || + stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; + if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; + } else if ((num_stream > stcb->asoc.max_inbound_streams) || (num_stream > 0xffff)) { /* We must reject it they ask for to many */ denied: - stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; - stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_REJECT; + stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; } else { /* Ok, we can do that :-) */ struct sctp_stream_in *oldstrm; @@ -3955,8 +3960,7 @@ sctp_handle_str_reset_add_strm(struct sc SCTP_FREE(oldstrm, SCTP_M_STRMI); /* update the size */ stcb->asoc.streamincnt = num_stream; - stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; - stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_PERFORMED; + stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0); } sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); @@ -3974,7 +3978,7 @@ sctp_handle_str_reset_add_strm(struct sc */ sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); } else { - sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_BAD_SEQNO); + sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); } } @@ -3996,10 +4000,12 @@ sctp_handle_str_reset_add_out_strm(struc num_stream = ntohs(str_add->number_of_streams); /* Now what would be the new total? */ if (asoc->str_reset_seq_in == seq) { - if (stcb->asoc.stream_reset_outstanding) { + stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; + if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; + } else if (stcb->asoc.stream_reset_outstanding) { /* We must reject it we have something pending */ - stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; - stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_REJECT; + stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS; } else { /* Ok, we can do that :-) */ int mychk; @@ -4007,14 +4013,12 @@ sctp_handle_str_reset_add_out_strm(struc mychk = stcb->asoc.streamoutcnt; mychk += num_stream; if (mychk < 0x10000) { - stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; - stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_PERFORMED; + stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; if (sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, 1, num_stream, 0, 1)) { - stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_REJECT; + stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; } } else { - stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; - stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_REJECT; + stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; } } sctp_add_stream_reset_result(chk, seq, stcb->asoc.last_reset_action[0]); @@ -4032,7 +4036,7 @@ sctp_handle_str_reset_add_out_strm(struc */ sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); } else { - sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_BAD_SEQNO); + sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); } } @@ -4046,7 +4050,6 @@ __attribute__((noinline)) int chk_length, param_len, ptype; struct sctp_paramhdr pstore; uint8_t cstore[SCTP_CHUNK_BUFFER_SIZE]; - uint32_t seq = 0; int num_req = 0; int trunc = 0; @@ -4124,7 +4127,7 @@ strres_nochunk: seq = ntohl(req_out->response_seq); if (seq == stcb->asoc.str_reset_seq_out) { /* implicit ack */ - (void)sctp_handle_stream_reset_response(stcb, seq, SCTP_STREAM_RESET_PERFORMED, NULL); + (void)sctp_handle_stream_reset_response(stcb, seq, SCTP_STREAM_RESET_RESULT_PERFORMED, NULL); } } sctp_handle_str_reset_request_out(stcb, chk, req_out, trunc);