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