@@ -303,13 +303,14 @@ int sctp_send_add_streams(struct sctp_association *asoc,
303303}
304304
305305static sctp_paramhdr_t * sctp_chunk_lookup_strreset_param (
306- struct sctp_association * asoc , __u32 resp_seq )
306+ struct sctp_association * asoc , __u32 resp_seq ,
307+ __be16 type )
307308{
308309 struct sctp_chunk * chunk = asoc -> strreset_chunk ;
309310 struct sctp_reconf_chunk * hdr ;
310311 union sctp_params param ;
311312
312- if (ntohl ( resp_seq ) != asoc -> strreset_outseq || !chunk )
313+ if (!chunk )
313314 return NULL ;
314315
315316 hdr = (struct sctp_reconf_chunk * )chunk -> chunk_hdr ;
@@ -320,7 +321,8 @@ static sctp_paramhdr_t *sctp_chunk_lookup_strreset_param(
320321 */
321322 struct sctp_strreset_tsnreq * req = param .v ;
322323
323- if (req -> request_seq == resp_seq )
324+ if ((!resp_seq || req -> request_seq == resp_seq ) &&
325+ (!type || type == req -> param_hdr .type ))
324326 return param .v ;
325327 }
326328
@@ -361,13 +363,9 @@ struct sctp_chunk *sctp_process_strreset_outreq(
361363 goto out ;
362364
363365 if (asoc -> strreset_chunk ) {
364- sctp_paramhdr_t * param_hdr ;
365- struct sctp_transport * t ;
366-
367- param_hdr = sctp_chunk_lookup_strreset_param (
368- asoc , outreq -> response_seq );
369- if (!param_hdr || param_hdr -> type !=
370- SCTP_PARAM_RESET_IN_REQUEST ) {
366+ if (!sctp_chunk_lookup_strreset_param (
367+ asoc , outreq -> response_seq ,
368+ SCTP_PARAM_RESET_IN_REQUEST )) {
371369 /* same process with outstanding isn't 0 */
372370 result = SCTP_STRRESET_ERR_IN_PROGRESS ;
373371 goto out ;
@@ -377,6 +375,8 @@ struct sctp_chunk *sctp_process_strreset_outreq(
377375 asoc -> strreset_outseq ++ ;
378376
379377 if (!asoc -> strreset_outstanding ) {
378+ struct sctp_transport * t ;
379+
380380 t = asoc -> strreset_chunk -> transport ;
381381 if (del_timer (& t -> reconf_timer ))
382382 sctp_transport_put (t );
@@ -556,3 +556,72 @@ struct sctp_chunk *sctp_process_strreset_tsnreq(
556556 return sctp_make_strreset_tsnresp (asoc , result , request_seq ,
557557 next_tsn , init_tsn );
558558}
559+
560+ struct sctp_chunk * sctp_process_strreset_addstrm_out (
561+ struct sctp_association * asoc ,
562+ union sctp_params param ,
563+ struct sctp_ulpevent * * evp )
564+ {
565+ struct sctp_strreset_addstrm * addstrm = param .v ;
566+ struct sctp_stream * stream = asoc -> stream ;
567+ __u32 result = SCTP_STRRESET_DENIED ;
568+ struct sctp_stream_in * streamin ;
569+ __u32 request_seq , incnt ;
570+ __u16 in ;
571+
572+ request_seq = ntohl (addstrm -> request_seq );
573+ if (request_seq > asoc -> strreset_inseq ) {
574+ result = SCTP_STRRESET_ERR_BAD_SEQNO ;
575+ goto out ;
576+ } else if (request_seq == asoc -> strreset_inseq ) {
577+ asoc -> strreset_inseq ++ ;
578+ }
579+
580+ if (!(asoc -> strreset_enable & SCTP_ENABLE_CHANGE_ASSOC_REQ ))
581+ goto out ;
582+
583+ if (asoc -> strreset_chunk ) {
584+ if (!sctp_chunk_lookup_strreset_param (
585+ asoc , 0 , SCTP_PARAM_RESET_ADD_IN_STREAMS )) {
586+ /* same process with outstanding isn't 0 */
587+ result = SCTP_STRRESET_ERR_IN_PROGRESS ;
588+ goto out ;
589+ }
590+
591+ asoc -> strreset_outstanding -- ;
592+ asoc -> strreset_outseq ++ ;
593+
594+ if (!asoc -> strreset_outstanding ) {
595+ struct sctp_transport * t ;
596+
597+ t = asoc -> strreset_chunk -> transport ;
598+ if (del_timer (& t -> reconf_timer ))
599+ sctp_transport_put (t );
600+
601+ sctp_chunk_put (asoc -> strreset_chunk );
602+ asoc -> strreset_chunk = NULL ;
603+ }
604+ }
605+
606+ in = ntohs (addstrm -> number_of_streams );
607+ incnt = stream -> incnt + in ;
608+ if (!in || incnt > SCTP_MAX_STREAM )
609+ goto out ;
610+
611+ streamin = krealloc (stream -> in , incnt * sizeof (* streamin ),
612+ GFP_ATOMIC );
613+ if (!streamin )
614+ goto out ;
615+
616+ memset (streamin + stream -> incnt , 0 , in * sizeof (* streamin ));
617+ stream -> in = streamin ;
618+ stream -> incnt = incnt ;
619+
620+ result = SCTP_STRRESET_PERFORMED ;
621+
622+ * evp = sctp_ulpevent_make_stream_change_event (asoc ,
623+ 0 , ntohs (addstrm -> number_of_streams ), 0 , GFP_ATOMIC );
624+
625+ out :
626+ return sctp_make_strreset_resp (asoc , result , request_seq );
627+ }
0 commit comments