1 /* SCTP kernel implementation 2 * (C) Copyright IBM Corp. 2001, 2004 3 * Copyright (c) 1999-2000 Cisco, Inc. 4 * Copyright (c) 1999-2001 Motorola, Inc. 5 * Copyright (c) 2001 Intel Corp. 6 * 7 * This file is part of the SCTP kernel implementation 8 * 9 * These functions manipulate sctp tsn mapping array. 10 * 11 * This SCTP implementation is free software; 12 * you can redistribute it and/or modify it under the terms of 13 * the GNU General Public License as published by 14 * the Free Software Foundation; either version 2, or (at your option) 15 * any later version. 16 * 17 * This SCTP implementation is distributed in the hope that it 18 * will be useful, but WITHOUT ANY WARRANTY; without even the implied 19 * ************************ 20 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 21 * See the GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with GNU CC; see the file COPYING. If not, see 25 * <http://www.gnu.org/licenses/>. 26 * 27 * Please send any bug reports or fixes you make to the 28 * email address(es): 29 * lksctp developers <linux-sctp@vger.kernel.org> 30 * 31 * Written or modified by: 32 * Xin Long <lucien.xin@gmail.com> 33 */ 34 35 #include <net/sctp/sctp.h> 36 #include <net/sctp/sm.h> 37 38 int sctp_stream_new(struct sctp_association *asoc, gfp_t gfp) 39 { 40 struct sctp_stream *stream; 41 int i; 42 43 stream = kzalloc(sizeof(*stream), gfp); 44 if (!stream) 45 return -ENOMEM; 46 47 stream->outcnt = asoc->c.sinit_num_ostreams; 48 stream->out = kcalloc(stream->outcnt, sizeof(*stream->out), gfp); 49 if (!stream->out) { 50 kfree(stream); 51 return -ENOMEM; 52 } 53 for (i = 0; i < stream->outcnt; i++) 54 stream->out[i].state = SCTP_STREAM_OPEN; 55 56 asoc->stream = stream; 57 58 return 0; 59 } 60 61 int sctp_stream_init(struct sctp_association *asoc, gfp_t gfp) 62 { 63 struct sctp_stream *stream = asoc->stream; 64 int i; 65 66 /* Initial stream->out size may be very big, so free it and alloc 67 * a new one with new outcnt to save memory. 68 */ 69 kfree(stream->out); 70 stream->outcnt = asoc->c.sinit_num_ostreams; 71 stream->out = kcalloc(stream->outcnt, sizeof(*stream->out), gfp); 72 if (!stream->out) 73 goto nomem; 74 75 for (i = 0; i < stream->outcnt; i++) 76 stream->out[i].state = SCTP_STREAM_OPEN; 77 78 stream->incnt = asoc->c.sinit_max_instreams; 79 stream->in = kcalloc(stream->incnt, sizeof(*stream->in), gfp); 80 if (!stream->in) { 81 kfree(stream->out); 82 goto nomem; 83 } 84 85 return 0; 86 87 nomem: 88 asoc->stream = NULL; 89 kfree(stream); 90 91 return -ENOMEM; 92 } 93 94 void sctp_stream_free(struct sctp_stream *stream) 95 { 96 if (unlikely(!stream)) 97 return; 98 99 kfree(stream->out); 100 kfree(stream->in); 101 kfree(stream); 102 } 103 104 void sctp_stream_clear(struct sctp_stream *stream) 105 { 106 int i; 107 108 for (i = 0; i < stream->outcnt; i++) 109 stream->out[i].ssn = 0; 110 111 for (i = 0; i < stream->incnt; i++) 112 stream->in[i].ssn = 0; 113 } 114 115 static int sctp_send_reconf(struct sctp_association *asoc, 116 struct sctp_chunk *chunk) 117 { 118 struct net *net = sock_net(asoc->base.sk); 119 int retval = 0; 120 121 retval = sctp_primitive_RECONF(net, asoc, chunk); 122 if (retval) 123 sctp_chunk_free(chunk); 124 125 return retval; 126 } 127 128 int sctp_send_reset_streams(struct sctp_association *asoc, 129 struct sctp_reset_streams *params) 130 { 131 struct sctp_stream *stream = asoc->stream; 132 __u16 i, str_nums, *str_list; 133 struct sctp_chunk *chunk; 134 int retval = -EINVAL; 135 bool out, in; 136 137 if (!asoc->peer.reconf_capable || 138 !(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ)) { 139 retval = -ENOPROTOOPT; 140 goto out; 141 } 142 143 if (asoc->strreset_outstanding) { 144 retval = -EINPROGRESS; 145 goto out; 146 } 147 148 out = params->srs_flags & SCTP_STREAM_RESET_OUTGOING; 149 in = params->srs_flags & SCTP_STREAM_RESET_INCOMING; 150 if (!out && !in) 151 goto out; 152 153 str_nums = params->srs_number_streams; 154 str_list = params->srs_stream_list; 155 if (out && str_nums) 156 for (i = 0; i < str_nums; i++) 157 if (str_list[i] >= stream->outcnt) 158 goto out; 159 160 if (in && str_nums) 161 for (i = 0; i < str_nums; i++) 162 if (str_list[i] >= stream->incnt) 163 goto out; 164 165 for (i = 0; i < str_nums; i++) 166 str_list[i] = htons(str_list[i]); 167 168 chunk = sctp_make_strreset_req(asoc, str_nums, str_list, out, in); 169 170 for (i = 0; i < str_nums; i++) 171 str_list[i] = ntohs(str_list[i]); 172 173 if (!chunk) { 174 retval = -ENOMEM; 175 goto out; 176 } 177 178 if (out) { 179 if (str_nums) 180 for (i = 0; i < str_nums; i++) 181 stream->out[str_list[i]].state = 182 SCTP_STREAM_CLOSED; 183 else 184 for (i = 0; i < stream->outcnt; i++) 185 stream->out[i].state = SCTP_STREAM_CLOSED; 186 } 187 188 asoc->strreset_chunk = chunk; 189 sctp_chunk_hold(asoc->strreset_chunk); 190 191 retval = sctp_send_reconf(asoc, chunk); 192 if (retval) { 193 sctp_chunk_put(asoc->strreset_chunk); 194 asoc->strreset_chunk = NULL; 195 if (!out) 196 goto out; 197 198 if (str_nums) 199 for (i = 0; i < str_nums; i++) 200 stream->out[str_list[i]].state = 201 SCTP_STREAM_OPEN; 202 else 203 for (i = 0; i < stream->outcnt; i++) 204 stream->out[i].state = SCTP_STREAM_OPEN; 205 206 goto out; 207 } 208 209 asoc->strreset_outstanding = out + in; 210 211 out: 212 return retval; 213 } 214 215 int sctp_send_reset_assoc(struct sctp_association *asoc) 216 { 217 struct sctp_chunk *chunk = NULL; 218 int retval; 219 __u16 i; 220 221 if (!asoc->peer.reconf_capable || 222 !(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ)) 223 return -ENOPROTOOPT; 224 225 if (asoc->strreset_outstanding) 226 return -EINPROGRESS; 227 228 chunk = sctp_make_strreset_tsnreq(asoc); 229 if (!chunk) 230 return -ENOMEM; 231 232 /* Block further xmit of data until this request is completed */ 233 for (i = 0; i < asoc->stream->outcnt; i++) 234 asoc->stream->out[i].state = SCTP_STREAM_CLOSED; 235 236 asoc->strreset_chunk = chunk; 237 sctp_chunk_hold(asoc->strreset_chunk); 238 239 retval = sctp_send_reconf(asoc, chunk); 240 if (retval) { 241 sctp_chunk_put(asoc->strreset_chunk); 242 asoc->strreset_chunk = NULL; 243 244 for (i = 0; i < asoc->stream->outcnt; i++) 245 asoc->stream->out[i].state = SCTP_STREAM_OPEN; 246 247 return retval; 248 } 249 250 asoc->strreset_outstanding = 1; 251 252 return 0; 253 } 254 255 int sctp_send_add_streams(struct sctp_association *asoc, 256 struct sctp_add_streams *params) 257 { 258 struct sctp_stream *stream = asoc->stream; 259 struct sctp_chunk *chunk = NULL; 260 int retval = -ENOMEM; 261 __u32 outcnt, incnt; 262 __u16 out, in; 263 264 if (!asoc->peer.reconf_capable || 265 !(asoc->strreset_enable & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { 266 retval = -ENOPROTOOPT; 267 goto out; 268 } 269 270 if (asoc->strreset_outstanding) { 271 retval = -EINPROGRESS; 272 goto out; 273 } 274 275 out = params->sas_outstrms; 276 in = params->sas_instrms; 277 outcnt = stream->outcnt + out; 278 incnt = stream->incnt + in; 279 if (outcnt > SCTP_MAX_STREAM || incnt > SCTP_MAX_STREAM || 280 (!out && !in)) { 281 retval = -EINVAL; 282 goto out; 283 } 284 285 if (out) { 286 struct sctp_stream_out *streamout; 287 288 streamout = krealloc(stream->out, outcnt * sizeof(*streamout), 289 GFP_KERNEL); 290 if (!streamout) 291 goto out; 292 293 memset(streamout + stream->outcnt, 0, out * sizeof(*streamout)); 294 stream->out = streamout; 295 } 296 297 chunk = sctp_make_strreset_addstrm(asoc, out, in); 298 if (!chunk) 299 goto out; 300 301 asoc->strreset_chunk = chunk; 302 sctp_chunk_hold(asoc->strreset_chunk); 303 304 retval = sctp_send_reconf(asoc, chunk); 305 if (retval) { 306 sctp_chunk_put(asoc->strreset_chunk); 307 asoc->strreset_chunk = NULL; 308 goto out; 309 } 310 311 stream->incnt = incnt; 312 stream->outcnt = outcnt; 313 314 asoc->strreset_outstanding = !!out + !!in; 315 316 out: 317 return retval; 318 } 319 320 static sctp_paramhdr_t *sctp_chunk_lookup_strreset_param( 321 struct sctp_association *asoc, __u32 resp_seq, 322 __be16 type) 323 { 324 struct sctp_chunk *chunk = asoc->strreset_chunk; 325 struct sctp_reconf_chunk *hdr; 326 union sctp_params param; 327 328 if (!chunk) 329 return NULL; 330 331 hdr = (struct sctp_reconf_chunk *)chunk->chunk_hdr; 332 sctp_walk_params(param, hdr, params) { 333 /* sctp_strreset_tsnreq is actually the basic structure 334 * of all stream reconf params, so it's safe to use it 335 * to access request_seq. 336 */ 337 struct sctp_strreset_tsnreq *req = param.v; 338 339 if ((!resp_seq || req->request_seq == resp_seq) && 340 (!type || type == req->param_hdr.type)) 341 return param.v; 342 } 343 344 return NULL; 345 } 346 347 struct sctp_chunk *sctp_process_strreset_outreq( 348 struct sctp_association *asoc, 349 union sctp_params param, 350 struct sctp_ulpevent **evp) 351 { 352 struct sctp_strreset_outreq *outreq = param.v; 353 struct sctp_stream *stream = asoc->stream; 354 __u16 i, nums, flags = 0, *str_p = NULL; 355 __u32 result = SCTP_STRRESET_DENIED; 356 __u32 request_seq; 357 358 request_seq = ntohl(outreq->request_seq); 359 360 if (ntohl(outreq->send_reset_at_tsn) > 361 sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map)) { 362 result = SCTP_STRRESET_IN_PROGRESS; 363 goto out; 364 } 365 366 if (request_seq > asoc->strreset_inseq) { 367 result = SCTP_STRRESET_ERR_BAD_SEQNO; 368 goto out; 369 } else if (request_seq == asoc->strreset_inseq) { 370 asoc->strreset_inseq++; 371 } 372 373 /* Check strreset_enable after inseq inc, as sender cannot tell 374 * the peer doesn't enable strreset after receiving response with 375 * result denied, as well as to keep consistent with bsd. 376 */ 377 if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ)) 378 goto out; 379 380 if (asoc->strreset_chunk) { 381 if (!sctp_chunk_lookup_strreset_param( 382 asoc, outreq->response_seq, 383 SCTP_PARAM_RESET_IN_REQUEST)) { 384 /* same process with outstanding isn't 0 */ 385 result = SCTP_STRRESET_ERR_IN_PROGRESS; 386 goto out; 387 } 388 389 asoc->strreset_outstanding--; 390 asoc->strreset_outseq++; 391 392 if (!asoc->strreset_outstanding) { 393 struct sctp_transport *t; 394 395 t = asoc->strreset_chunk->transport; 396 if (del_timer(&t->reconf_timer)) 397 sctp_transport_put(t); 398 399 sctp_chunk_put(asoc->strreset_chunk); 400 asoc->strreset_chunk = NULL; 401 } 402 403 flags = SCTP_STREAM_RESET_INCOMING_SSN; 404 } 405 406 nums = (ntohs(param.p->length) - sizeof(*outreq)) / 2; 407 if (nums) { 408 str_p = outreq->list_of_streams; 409 for (i = 0; i < nums; i++) { 410 if (ntohs(str_p[i]) >= stream->incnt) { 411 result = SCTP_STRRESET_ERR_WRONG_SSN; 412 goto out; 413 } 414 } 415 416 for (i = 0; i < nums; i++) 417 stream->in[ntohs(str_p[i])].ssn = 0; 418 } else { 419 for (i = 0; i < stream->incnt; i++) 420 stream->in[i].ssn = 0; 421 } 422 423 result = SCTP_STRRESET_PERFORMED; 424 425 *evp = sctp_ulpevent_make_stream_reset_event(asoc, 426 flags | SCTP_STREAM_RESET_OUTGOING_SSN, nums, str_p, 427 GFP_ATOMIC); 428 429 out: 430 return sctp_make_strreset_resp(asoc, result, request_seq); 431 } 432 433 struct sctp_chunk *sctp_process_strreset_inreq( 434 struct sctp_association *asoc, 435 union sctp_params param, 436 struct sctp_ulpevent **evp) 437 { 438 struct sctp_strreset_inreq *inreq = param.v; 439 struct sctp_stream *stream = asoc->stream; 440 __u32 result = SCTP_STRRESET_DENIED; 441 struct sctp_chunk *chunk = NULL; 442 __u16 i, nums, *str_p; 443 __u32 request_seq; 444 445 request_seq = ntohl(inreq->request_seq); 446 if (request_seq > asoc->strreset_inseq) { 447 result = SCTP_STRRESET_ERR_BAD_SEQNO; 448 goto out; 449 } else if (request_seq == asoc->strreset_inseq) { 450 asoc->strreset_inseq++; 451 } 452 453 if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ)) 454 goto out; 455 456 if (asoc->strreset_outstanding) { 457 result = SCTP_STRRESET_ERR_IN_PROGRESS; 458 goto out; 459 } 460 461 nums = (ntohs(param.p->length) - sizeof(*inreq)) / 2; 462 str_p = inreq->list_of_streams; 463 for (i = 0; i < nums; i++) { 464 if (ntohs(str_p[i]) >= stream->outcnt) { 465 result = SCTP_STRRESET_ERR_WRONG_SSN; 466 goto out; 467 } 468 } 469 470 chunk = sctp_make_strreset_req(asoc, nums, str_p, 1, 0); 471 if (!chunk) 472 goto out; 473 474 if (nums) 475 for (i = 0; i < nums; i++) 476 stream->out[ntohs(str_p[i])].state = 477 SCTP_STREAM_CLOSED; 478 else 479 for (i = 0; i < stream->outcnt; i++) 480 stream->out[i].state = SCTP_STREAM_CLOSED; 481 482 asoc->strreset_chunk = chunk; 483 asoc->strreset_outstanding = 1; 484 sctp_chunk_hold(asoc->strreset_chunk); 485 486 *evp = sctp_ulpevent_make_stream_reset_event(asoc, 487 SCTP_STREAM_RESET_INCOMING_SSN, nums, str_p, GFP_ATOMIC); 488 489 out: 490 if (!chunk) 491 chunk = sctp_make_strreset_resp(asoc, result, request_seq); 492 493 return chunk; 494 } 495 496 struct sctp_chunk *sctp_process_strreset_tsnreq( 497 struct sctp_association *asoc, 498 union sctp_params param, 499 struct sctp_ulpevent **evp) 500 { 501 __u32 init_tsn = 0, next_tsn = 0, max_tsn_seen; 502 struct sctp_strreset_tsnreq *tsnreq = param.v; 503 struct sctp_stream *stream = asoc->stream; 504 __u32 result = SCTP_STRRESET_DENIED; 505 __u32 request_seq; 506 __u16 i; 507 508 request_seq = ntohl(tsnreq->request_seq); 509 if (request_seq > asoc->strreset_inseq) { 510 result = SCTP_STRRESET_ERR_BAD_SEQNO; 511 goto out; 512 } else if (request_seq == asoc->strreset_inseq) { 513 asoc->strreset_inseq++; 514 } 515 516 if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ)) 517 goto out; 518 519 if (asoc->strreset_outstanding) { 520 result = SCTP_STRRESET_ERR_IN_PROGRESS; 521 goto out; 522 } 523 524 /* G3: The same processing as though a SACK chunk with no gap report 525 * and a cumulative TSN ACK of the Sender's Next TSN minus 1 were 526 * received MUST be performed. 527 */ 528 max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map); 529 sctp_ulpq_reasm_flushtsn(&asoc->ulpq, max_tsn_seen); 530 sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC); 531 532 /* G1: Compute an appropriate value for the Receiver's Next TSN -- the 533 * TSN that the peer should use to send the next DATA chunk. The 534 * value SHOULD be the smallest TSN not acknowledged by the 535 * receiver of the request plus 2^31. 536 */ 537 init_tsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + (1 << 31); 538 sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL, 539 init_tsn, GFP_ATOMIC); 540 541 /* G4: The same processing as though a FWD-TSN chunk (as defined in 542 * [RFC3758]) with all streams affected and a new cumulative TSN 543 * ACK of the Receiver's Next TSN minus 1 were received MUST be 544 * performed. 545 */ 546 sctp_outq_free(&asoc->outqueue); 547 548 /* G2: Compute an appropriate value for the local endpoint's next TSN, 549 * i.e., the next TSN assigned by the receiver of the SSN/TSN reset 550 * chunk. The value SHOULD be the highest TSN sent by the receiver 551 * of the request plus 1. 552 */ 553 next_tsn = asoc->next_tsn; 554 asoc->ctsn_ack_point = next_tsn - 1; 555 asoc->adv_peer_ack_point = asoc->ctsn_ack_point; 556 557 /* G5: The next expected and outgoing SSNs MUST be reset to 0 for all 558 * incoming and outgoing streams. 559 */ 560 for (i = 0; i < stream->outcnt; i++) 561 stream->out[i].ssn = 0; 562 for (i = 0; i < stream->incnt; i++) 563 stream->in[i].ssn = 0; 564 565 result = SCTP_STRRESET_PERFORMED; 566 567 *evp = sctp_ulpevent_make_assoc_reset_event(asoc, 0, init_tsn, 568 next_tsn, GFP_ATOMIC); 569 570 out: 571 return sctp_make_strreset_tsnresp(asoc, result, request_seq, 572 next_tsn, init_tsn); 573 } 574 575 struct sctp_chunk *sctp_process_strreset_addstrm_out( 576 struct sctp_association *asoc, 577 union sctp_params param, 578 struct sctp_ulpevent **evp) 579 { 580 struct sctp_strreset_addstrm *addstrm = param.v; 581 struct sctp_stream *stream = asoc->stream; 582 __u32 result = SCTP_STRRESET_DENIED; 583 struct sctp_stream_in *streamin; 584 __u32 request_seq, incnt; 585 __u16 in; 586 587 request_seq = ntohl(addstrm->request_seq); 588 if (request_seq > asoc->strreset_inseq) { 589 result = SCTP_STRRESET_ERR_BAD_SEQNO; 590 goto out; 591 } else if (request_seq == asoc->strreset_inseq) { 592 asoc->strreset_inseq++; 593 } 594 595 if (!(asoc->strreset_enable & SCTP_ENABLE_CHANGE_ASSOC_REQ)) 596 goto out; 597 598 if (asoc->strreset_chunk) { 599 if (!sctp_chunk_lookup_strreset_param( 600 asoc, 0, SCTP_PARAM_RESET_ADD_IN_STREAMS)) { 601 /* same process with outstanding isn't 0 */ 602 result = SCTP_STRRESET_ERR_IN_PROGRESS; 603 goto out; 604 } 605 606 asoc->strreset_outstanding--; 607 asoc->strreset_outseq++; 608 609 if (!asoc->strreset_outstanding) { 610 struct sctp_transport *t; 611 612 t = asoc->strreset_chunk->transport; 613 if (del_timer(&t->reconf_timer)) 614 sctp_transport_put(t); 615 616 sctp_chunk_put(asoc->strreset_chunk); 617 asoc->strreset_chunk = NULL; 618 } 619 } 620 621 in = ntohs(addstrm->number_of_streams); 622 incnt = stream->incnt + in; 623 if (!in || incnt > SCTP_MAX_STREAM) 624 goto out; 625 626 streamin = krealloc(stream->in, incnt * sizeof(*streamin), 627 GFP_ATOMIC); 628 if (!streamin) 629 goto out; 630 631 memset(streamin + stream->incnt, 0, in * sizeof(*streamin)); 632 stream->in = streamin; 633 stream->incnt = incnt; 634 635 result = SCTP_STRRESET_PERFORMED; 636 637 *evp = sctp_ulpevent_make_stream_change_event(asoc, 638 0, ntohs(addstrm->number_of_streams), 0, GFP_ATOMIC); 639 640 out: 641 return sctp_make_strreset_resp(asoc, result, request_seq); 642 } 643 644 struct sctp_chunk *sctp_process_strreset_addstrm_in( 645 struct sctp_association *asoc, 646 union sctp_params param, 647 struct sctp_ulpevent **evp) 648 { 649 struct sctp_strreset_addstrm *addstrm = param.v; 650 struct sctp_stream *stream = asoc->stream; 651 __u32 result = SCTP_STRRESET_DENIED; 652 struct sctp_stream_out *streamout; 653 struct sctp_chunk *chunk = NULL; 654 __u32 request_seq, outcnt; 655 __u16 out; 656 657 request_seq = ntohl(addstrm->request_seq); 658 if (request_seq > asoc->strreset_inseq) { 659 result = SCTP_STRRESET_ERR_BAD_SEQNO; 660 goto out; 661 } else if (request_seq == asoc->strreset_inseq) { 662 asoc->strreset_inseq++; 663 } 664 665 if (!(asoc->strreset_enable & SCTP_ENABLE_CHANGE_ASSOC_REQ)) 666 goto out; 667 668 if (asoc->strreset_outstanding) { 669 result = SCTP_STRRESET_ERR_IN_PROGRESS; 670 goto out; 671 } 672 673 out = ntohs(addstrm->number_of_streams); 674 outcnt = stream->outcnt + out; 675 if (!out || outcnt > SCTP_MAX_STREAM) 676 goto out; 677 678 streamout = krealloc(stream->out, outcnt * sizeof(*streamout), 679 GFP_ATOMIC); 680 if (!streamout) 681 goto out; 682 683 memset(streamout + stream->outcnt, 0, out * sizeof(*streamout)); 684 stream->out = streamout; 685 686 chunk = sctp_make_strreset_addstrm(asoc, out, 0); 687 if (!chunk) 688 goto out; 689 690 asoc->strreset_chunk = chunk; 691 asoc->strreset_outstanding = 1; 692 sctp_chunk_hold(asoc->strreset_chunk); 693 694 stream->outcnt = outcnt; 695 696 *evp = sctp_ulpevent_make_stream_change_event(asoc, 697 0, 0, ntohs(addstrm->number_of_streams), GFP_ATOMIC); 698 699 out: 700 if (!chunk) 701 chunk = sctp_make_strreset_resp(asoc, result, request_seq); 702 703 return chunk; 704 } 705 706 struct sctp_chunk *sctp_process_strreset_resp( 707 struct sctp_association *asoc, 708 union sctp_params param, 709 struct sctp_ulpevent **evp) 710 { 711 struct sctp_strreset_resp *resp = param.v; 712 struct sctp_stream *stream = asoc->stream; 713 struct sctp_transport *t; 714 __u16 i, nums, flags = 0; 715 sctp_paramhdr_t *req; 716 __u32 result; 717 718 req = sctp_chunk_lookup_strreset_param(asoc, resp->response_seq, 0); 719 if (!req) 720 return NULL; 721 722 result = ntohl(resp->result); 723 if (result != SCTP_STRRESET_PERFORMED) { 724 /* if in progress, do nothing but retransmit */ 725 if (result == SCTP_STRRESET_IN_PROGRESS) 726 return NULL; 727 else if (result == SCTP_STRRESET_DENIED) 728 flags = SCTP_STREAM_RESET_DENIED; 729 else 730 flags = SCTP_STREAM_RESET_FAILED; 731 } 732 733 if (req->type == SCTP_PARAM_RESET_OUT_REQUEST) { 734 struct sctp_strreset_outreq *outreq; 735 __u16 *str_p = NULL; 736 737 outreq = (struct sctp_strreset_outreq *)req; 738 nums = (ntohs(outreq->param_hdr.length) - sizeof(*outreq)) / 2; 739 740 if (result == SCTP_STRRESET_PERFORMED) { 741 if (nums) { 742 str_p = outreq->list_of_streams; 743 for (i = 0; i < nums; i++) 744 stream->out[ntohs(str_p[i])].ssn = 0; 745 } else { 746 for (i = 0; i < stream->outcnt; i++) 747 stream->out[i].ssn = 0; 748 } 749 750 flags = SCTP_STREAM_RESET_OUTGOING_SSN; 751 } 752 753 for (i = 0; i < stream->outcnt; i++) 754 stream->out[i].state = SCTP_STREAM_OPEN; 755 756 *evp = sctp_ulpevent_make_stream_reset_event(asoc, flags, 757 nums, str_p, GFP_ATOMIC); 758 } else if (req->type == SCTP_PARAM_RESET_IN_REQUEST) { 759 struct sctp_strreset_inreq *inreq; 760 __u16 *str_p = NULL; 761 762 /* if the result is performed, it's impossible for inreq */ 763 if (result == SCTP_STRRESET_PERFORMED) 764 return NULL; 765 766 inreq = (struct sctp_strreset_inreq *)req; 767 nums = (ntohs(inreq->param_hdr.length) - sizeof(*inreq)) / 2; 768 769 str_p = inreq->list_of_streams; 770 *evp = sctp_ulpevent_make_stream_reset_event(asoc, flags, 771 nums, str_p, GFP_ATOMIC); 772 } else if (req->type == SCTP_PARAM_RESET_TSN_REQUEST) { 773 struct sctp_strreset_resptsn *resptsn; 774 __u32 stsn, rtsn; 775 776 /* check for resptsn, as sctp_verify_reconf didn't do it*/ 777 if (ntohs(param.p->length) != sizeof(*resptsn)) 778 return NULL; 779 780 resptsn = (struct sctp_strreset_resptsn *)resp; 781 stsn = ntohl(resptsn->senders_next_tsn); 782 rtsn = ntohl(resptsn->receivers_next_tsn); 783 784 if (result == SCTP_STRRESET_PERFORMED) { 785 __u32 mtsn = sctp_tsnmap_get_max_tsn_seen( 786 &asoc->peer.tsn_map); 787 788 sctp_ulpq_reasm_flushtsn(&asoc->ulpq, mtsn); 789 sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC); 790 791 sctp_tsnmap_init(&asoc->peer.tsn_map, 792 SCTP_TSN_MAP_INITIAL, 793 stsn, GFP_ATOMIC); 794 795 sctp_outq_free(&asoc->outqueue); 796 797 asoc->next_tsn = rtsn; 798 asoc->ctsn_ack_point = asoc->next_tsn - 1; 799 asoc->adv_peer_ack_point = asoc->ctsn_ack_point; 800 801 for (i = 0; i < stream->outcnt; i++) 802 stream->out[i].ssn = 0; 803 for (i = 0; i < stream->incnt; i++) 804 stream->in[i].ssn = 0; 805 } 806 807 for (i = 0; i < stream->outcnt; i++) 808 stream->out[i].state = SCTP_STREAM_OPEN; 809 810 *evp = sctp_ulpevent_make_assoc_reset_event(asoc, flags, 811 stsn, rtsn, GFP_ATOMIC); 812 } else if (req->type == SCTP_PARAM_RESET_ADD_OUT_STREAMS) { 813 struct sctp_strreset_addstrm *addstrm; 814 __u16 number; 815 816 addstrm = (struct sctp_strreset_addstrm *)req; 817 nums = ntohs(addstrm->number_of_streams); 818 number = stream->outcnt - nums; 819 820 if (result == SCTP_STRRESET_PERFORMED) 821 for (i = number; i < stream->outcnt; i++) 822 stream->out[i].state = SCTP_STREAM_OPEN; 823 else 824 stream->outcnt = number; 825 826 *evp = sctp_ulpevent_make_stream_change_event(asoc, flags, 827 0, nums, GFP_ATOMIC); 828 } else if (req->type == SCTP_PARAM_RESET_ADD_IN_STREAMS) { 829 struct sctp_strreset_addstrm *addstrm; 830 831 /* if the result is performed, it's impossible for addstrm in 832 * request. 833 */ 834 if (result == SCTP_STRRESET_PERFORMED) 835 return NULL; 836 837 addstrm = (struct sctp_strreset_addstrm *)req; 838 nums = ntohs(addstrm->number_of_streams); 839 840 *evp = sctp_ulpevent_make_stream_change_event(asoc, flags, 841 nums, 0, GFP_ATOMIC); 842 } 843 844 asoc->strreset_outstanding--; 845 asoc->strreset_outseq++; 846 847 /* remove everything for this reconf request */ 848 if (!asoc->strreset_outstanding) { 849 t = asoc->strreset_chunk->transport; 850 if (del_timer(&t->reconf_timer)) 851 sctp_transport_put(t); 852 853 sctp_chunk_put(asoc->strreset_chunk); 854 asoc->strreset_chunk = NULL; 855 } 856 857 return NULL; 858 } 859