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);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to