@@ -675,3 +675,157 @@ struct sctp_chunk *sctp_process_strreset_addstrm_in(
675675
676676 return chunk ;
677677}
678+
679+ struct sctp_chunk * sctp_process_strreset_resp (
680+ struct sctp_association * asoc ,
681+ union sctp_params param ,
682+ struct sctp_ulpevent * * evp )
683+ {
684+ struct sctp_strreset_resp * resp = param .v ;
685+ struct sctp_stream * stream = asoc -> stream ;
686+ struct sctp_transport * t ;
687+ __u16 i , nums , flags = 0 ;
688+ sctp_paramhdr_t * req ;
689+ __u32 result ;
690+
691+ req = sctp_chunk_lookup_strreset_param (asoc , resp -> response_seq , 0 );
692+ if (!req )
693+ return NULL ;
694+
695+ result = ntohl (resp -> result );
696+ if (result != SCTP_STRRESET_PERFORMED ) {
697+ /* if in progress, do nothing but retransmit */
698+ if (result == SCTP_STRRESET_IN_PROGRESS )
699+ return NULL ;
700+ else if (result == SCTP_STRRESET_DENIED )
701+ flags = SCTP_STREAM_RESET_DENIED ;
702+ else
703+ flags = SCTP_STREAM_RESET_FAILED ;
704+ }
705+
706+ if (req -> type == SCTP_PARAM_RESET_OUT_REQUEST ) {
707+ struct sctp_strreset_outreq * outreq ;
708+ __u16 * str_p = NULL ;
709+
710+ outreq = (struct sctp_strreset_outreq * )req ;
711+ nums = (ntohs (outreq -> param_hdr .length ) - sizeof (* outreq )) / 2 ;
712+
713+ if (result == SCTP_STRRESET_PERFORMED ) {
714+ if (nums ) {
715+ str_p = outreq -> list_of_streams ;
716+ for (i = 0 ; i < nums ; i ++ )
717+ stream -> out [ntohs (str_p [i ])].ssn = 0 ;
718+ } else {
719+ for (i = 0 ; i < stream -> outcnt ; i ++ )
720+ stream -> out [i ].ssn = 0 ;
721+ }
722+
723+ flags = SCTP_STREAM_RESET_OUTGOING_SSN ;
724+ }
725+
726+ for (i = 0 ; i < stream -> outcnt ; i ++ )
727+ stream -> out [i ].state = SCTP_STREAM_OPEN ;
728+
729+ * evp = sctp_ulpevent_make_stream_reset_event (asoc , flags ,
730+ nums , str_p , GFP_ATOMIC );
731+ } else if (req -> type == SCTP_PARAM_RESET_IN_REQUEST ) {
732+ struct sctp_strreset_inreq * inreq ;
733+ __u16 * str_p = NULL ;
734+
735+ /* if the result is performed, it's impossible for inreq */
736+ if (result == SCTP_STRRESET_PERFORMED )
737+ return NULL ;
738+
739+ inreq = (struct sctp_strreset_inreq * )req ;
740+ nums = (ntohs (inreq -> param_hdr .length ) - sizeof (* inreq )) / 2 ;
741+
742+ str_p = inreq -> list_of_streams ;
743+ * evp = sctp_ulpevent_make_stream_reset_event (asoc , flags ,
744+ nums , str_p , GFP_ATOMIC );
745+ } else if (req -> type == SCTP_PARAM_RESET_TSN_REQUEST ) {
746+ struct sctp_strreset_resptsn * resptsn ;
747+ __u32 stsn , rtsn ;
748+
749+ /* check for resptsn, as sctp_verify_reconf didn't do it*/
750+ if (ntohs (param .p -> length ) != sizeof (* resptsn ))
751+ return NULL ;
752+
753+ resptsn = (struct sctp_strreset_resptsn * )resp ;
754+ stsn = ntohl (resptsn -> senders_next_tsn );
755+ rtsn = ntohl (resptsn -> receivers_next_tsn );
756+
757+ if (result == SCTP_STRRESET_PERFORMED ) {
758+ __u32 mtsn = sctp_tsnmap_get_max_tsn_seen (
759+ & asoc -> peer .tsn_map );
760+
761+ sctp_ulpq_reasm_flushtsn (& asoc -> ulpq , mtsn );
762+ sctp_ulpq_abort_pd (& asoc -> ulpq , GFP_ATOMIC );
763+
764+ sctp_tsnmap_init (& asoc -> peer .tsn_map ,
765+ SCTP_TSN_MAP_INITIAL ,
766+ stsn , GFP_ATOMIC );
767+
768+ sctp_outq_free (& asoc -> outqueue );
769+
770+ asoc -> next_tsn = rtsn ;
771+ asoc -> ctsn_ack_point = asoc -> next_tsn - 1 ;
772+ asoc -> adv_peer_ack_point = asoc -> ctsn_ack_point ;
773+
774+ for (i = 0 ; i < stream -> outcnt ; i ++ )
775+ stream -> out [i ].ssn = 0 ;
776+ for (i = 0 ; i < stream -> incnt ; i ++ )
777+ stream -> in [i ].ssn = 0 ;
778+ }
779+
780+ for (i = 0 ; i < stream -> outcnt ; i ++ )
781+ stream -> out [i ].state = SCTP_STREAM_OPEN ;
782+
783+ * evp = sctp_ulpevent_make_assoc_reset_event (asoc , flags ,
784+ stsn , rtsn , GFP_ATOMIC );
785+ } else if (req -> type == SCTP_PARAM_RESET_ADD_OUT_STREAMS ) {
786+ struct sctp_strreset_addstrm * addstrm ;
787+ __u16 number ;
788+
789+ addstrm = (struct sctp_strreset_addstrm * )req ;
790+ nums = ntohs (addstrm -> number_of_streams );
791+ number = stream -> outcnt - nums ;
792+
793+ if (result == SCTP_STRRESET_PERFORMED )
794+ for (i = number ; i < stream -> outcnt ; i ++ )
795+ stream -> out [i ].state = SCTP_STREAM_OPEN ;
796+ else
797+ stream -> outcnt = number ;
798+
799+ * evp = sctp_ulpevent_make_stream_change_event (asoc , flags ,
800+ 0 , nums , GFP_ATOMIC );
801+ } else if (req -> type == SCTP_PARAM_RESET_ADD_IN_STREAMS ) {
802+ struct sctp_strreset_addstrm * addstrm ;
803+
804+ /* if the result is performed, it's impossible for addstrm in
805+ * request.
806+ */
807+ if (result == SCTP_STRRESET_PERFORMED )
808+ return NULL ;
809+
810+ addstrm = (struct sctp_strreset_addstrm * )req ;
811+ nums = ntohs (addstrm -> number_of_streams );
812+
813+ * evp = sctp_ulpevent_make_stream_change_event (asoc , flags ,
814+ nums , 0 , GFP_ATOMIC );
815+ }
816+
817+ asoc -> strreset_outstanding -- ;
818+ asoc -> strreset_outseq ++ ;
819+
820+ /* remove everything for this reconf request */
821+ if (!asoc -> strreset_outstanding ) {
822+ t = asoc -> strreset_chunk -> transport ;
823+ if (del_timer (& t -> reconf_timer ))
824+ sctp_transport_put (t );
825+
826+ sctp_chunk_put (asoc -> strreset_chunk );
827+ asoc -> strreset_chunk = NULL ;
828+ }
829+
830+ return NULL ;
831+ }
0 commit comments