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 static void sctp_update_strreset_result(struct sctp_association *asoc, 348 __u32 result) 349 { 350 asoc->strreset_result[1] = asoc->strreset_result[0]; 351 asoc->strreset_result[0] = result; 352 } 353 354 struct sctp_chunk *sctp_process_strreset_outreq( 355 struct sctp_association *asoc, 356 union sctp_params param, 357 struct sctp_ulpevent **evp) 358 { 359 struct sctp_strreset_outreq *outreq = param.v; 360 struct sctp_stream *stream = asoc->stream; 361 __u16 i, nums, flags = 0, *str_p = NULL; 362 __u32 result = SCTP_STRRESET_DENIED; 363 __u32 request_seq; 364 365 request_seq = ntohl(outreq->request_seq); 366 367 if (ntohl(outreq->send_reset_at_tsn) > 368 sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map)) { 369 result = SCTP_STRRESET_IN_PROGRESS; 370 goto err; 371 } 372 373 if (TSN_lt(asoc->strreset_inseq, request_seq) || 374 TSN_lt(request_seq, asoc->strreset_inseq - 2)) { 375 result = SCTP_STRRESET_ERR_BAD_SEQNO; 376 goto err; 377 } else if (TSN_lt(request_seq, asoc->strreset_inseq)) { 378 i = asoc->strreset_inseq - request_seq - 1; 379 result = asoc->strreset_result[i]; 380 goto err; 381 } 382 asoc->strreset_inseq++; 383 384 /* Check strreset_enable after inseq inc, as sender cannot tell 385 * the peer doesn't enable strreset after receiving response with 386 * result denied, as well as to keep consistent with bsd. 387 */ 388 if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ)) 389 goto out; 390 391 if (asoc->strreset_chunk) { 392 if (!sctp_chunk_lookup_strreset_param( 393 asoc, outreq->response_seq, 394 SCTP_PARAM_RESET_IN_REQUEST)) { 395 /* same process with outstanding isn't 0 */ 396 result = SCTP_STRRESET_ERR_IN_PROGRESS; 397 goto out; 398 } 399 400 asoc->strreset_outstanding--; 401 asoc->strreset_outseq++; 402 403 if (!asoc->strreset_outstanding) { 404 struct sctp_transport *t; 405 406 t = asoc->strreset_chunk->transport; 407 if (del_timer(&t->reconf_timer)) 408 sctp_transport_put(t); 409 410 sctp_chunk_put(asoc->strreset_chunk); 411 asoc->strreset_chunk = NULL; 412 } 413 414 flags = SCTP_STREAM_RESET_INCOMING_SSN; 415 } 416 417 nums = (ntohs(param.p->length) - sizeof(*outreq)) / 2; 418 if (nums) { 419 str_p = outreq->list_of_streams; 420 for (i = 0; i < nums; i++) { 421 if (ntohs(str_p[i]) >= stream->incnt) { 422 result = SCTP_STRRESET_ERR_WRONG_SSN; 423 goto out; 424 } 425 } 426 427 for (i = 0; i < nums; i++) 428 stream->in[ntohs(str_p[i])].ssn = 0; 429 } else { 430 for (i = 0; i < stream->incnt; i++) 431 stream->in[i].ssn = 0; 432 } 433 434 result = SCTP_STRRESET_PERFORMED; 435 436 *evp = sctp_ulpevent_make_stream_reset_event(asoc, 437 flags | SCTP_STREAM_RESET_OUTGOING_SSN, nums, str_p, 438 GFP_ATOMIC); 439 440 out: 441 sctp_update_strreset_result(asoc, result); 442 err: 443 return sctp_make_strreset_resp(asoc, result, request_seq); 444 } 445 446 struct sctp_chunk *sctp_process_strreset_inreq( 447 struct sctp_association *asoc, 448 union sctp_params param, 449 struct sctp_ulpevent **evp) 450 { 451 struct sctp_strreset_inreq *inreq = param.v; 452 struct sctp_stream *stream = asoc->stream; 453 __u32 result = SCTP_STRRESET_DENIED; 454 struct sctp_chunk *chunk = NULL; 455 __u16 i, nums, *str_p; 456 __u32 request_seq; 457 458 request_seq = ntohl(inreq->request_seq); 459 if (TSN_lt(asoc->strreset_inseq, request_seq) || 460 TSN_lt(request_seq, asoc->strreset_inseq - 2)) { 461 result = SCTP_STRRESET_ERR_BAD_SEQNO; 462 goto err; 463 } else if (TSN_lt(request_seq, asoc->strreset_inseq)) { 464 i = asoc->strreset_inseq - request_seq - 1; 465 result = asoc->strreset_result[i]; 466 if (result == SCTP_STRRESET_PERFORMED) 467 return NULL; 468 goto err; 469 } 470 asoc->strreset_inseq++; 471 472 if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ)) 473 goto out; 474 475 if (asoc->strreset_outstanding) { 476 result = SCTP_STRRESET_ERR_IN_PROGRESS; 477 goto out; 478 } 479 480 nums = (ntohs(param.p->length) - sizeof(*inreq)) / 2; 481 str_p = inreq->list_of_streams; 482 for (i = 0; i < nums; i++) { 483 if (ntohs(str_p[i]) >= stream->outcnt) { 484 result = SCTP_STRRESET_ERR_WRONG_SSN; 485 goto out; 486 } 487 } 488 489 chunk = sctp_make_strreset_req(asoc, nums, str_p, 1, 0); 490 if (!chunk) 491 goto out; 492 493 if (nums) 494 for (i = 0; i < nums; i++) 495 stream->out[ntohs(str_p[i])].state = 496 SCTP_STREAM_CLOSED; 497 else 498 for (i = 0; i < stream->outcnt; i++) 499 stream->out[i].state = SCTP_STREAM_CLOSED; 500 501 asoc->strreset_chunk = chunk; 502 asoc->strreset_outstanding = 1; 503 sctp_chunk_hold(asoc->strreset_chunk); 504 505 result = SCTP_STRRESET_PERFORMED; 506 507 *evp = sctp_ulpevent_make_stream_reset_event(asoc, 508 SCTP_STREAM_RESET_INCOMING_SSN, nums, str_p, GFP_ATOMIC); 509 510 out: 511 sctp_update_strreset_result(asoc, result); 512 err: 513 if (!chunk) 514 chunk = sctp_make_strreset_resp(asoc, result, request_seq); 515 516 return chunk; 517 } 518 519 struct sctp_chunk *sctp_process_strreset_tsnreq( 520 struct sctp_association *asoc, 521 union sctp_params param, 522 struct sctp_ulpevent **evp) 523 { 524 __u32 init_tsn = 0, next_tsn = 0, max_tsn_seen; 525 struct sctp_strreset_tsnreq *tsnreq = param.v; 526 struct sctp_stream *stream = asoc->stream; 527 __u32 result = SCTP_STRRESET_DENIED; 528 __u32 request_seq; 529 __u16 i; 530 531 request_seq = ntohl(tsnreq->request_seq); 532 if (TSN_lt(asoc->strreset_inseq, request_seq) || 533 TSN_lt(request_seq, asoc->strreset_inseq - 2)) { 534 result = SCTP_STRRESET_ERR_BAD_SEQNO; 535 goto err; 536 } else if (TSN_lt(request_seq, asoc->strreset_inseq)) { 537 i = asoc->strreset_inseq - request_seq - 1; 538 result = asoc->strreset_result[i]; 539 if (result == SCTP_STRRESET_PERFORMED) { 540 next_tsn = asoc->next_tsn; 541 init_tsn = 542 sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + 1; 543 } 544 goto err; 545 } 546 asoc->strreset_inseq++; 547 548 if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ)) 549 goto out; 550 551 if (asoc->strreset_outstanding) { 552 result = SCTP_STRRESET_ERR_IN_PROGRESS; 553 goto out; 554 } 555 556 /* G3: The same processing as though a SACK chunk with no gap report 557 * and a cumulative TSN ACK of the Sender's Next TSN minus 1 were 558 * received MUST be performed. 559 */ 560 max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map); 561 sctp_ulpq_reasm_flushtsn(&asoc->ulpq, max_tsn_seen); 562 sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC); 563 564 /* G1: Compute an appropriate value for the Receiver's Next TSN -- the 565 * TSN that the peer should use to send the next DATA chunk. The 566 * value SHOULD be the smallest TSN not acknowledged by the 567 * receiver of the request plus 2^31. 568 */ 569 init_tsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + (1 << 31); 570 sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL, 571 init_tsn, GFP_ATOMIC); 572 573 /* G4: The same processing as though a FWD-TSN chunk (as defined in 574 * [RFC3758]) with all streams affected and a new cumulative TSN 575 * ACK of the Receiver's Next TSN minus 1 were received MUST be 576 * performed. 577 */ 578 sctp_outq_free(&asoc->outqueue); 579 580 /* G2: Compute an appropriate value for the local endpoint's next TSN, 581 * i.e., the next TSN assigned by the receiver of the SSN/TSN reset 582 * chunk. The value SHOULD be the highest TSN sent by the receiver 583 * of the request plus 1. 584 */ 585 next_tsn = asoc->next_tsn; 586 asoc->ctsn_ack_point = next_tsn - 1; 587 asoc->adv_peer_ack_point = asoc->ctsn_ack_point; 588 589 /* G5: The next expected and outgoing SSNs MUST be reset to 0 for all 590 * incoming and outgoing streams. 591 */ 592 for (i = 0; i < stream->outcnt; i++) 593 stream->out[i].ssn = 0; 594 for (i = 0; i < stream->incnt; i++) 595 stream->in[i].ssn = 0; 596 597 result = SCTP_STRRESET_PERFORMED; 598 599 *evp = sctp_ulpevent_make_assoc_reset_event(asoc, 0, init_tsn, 600 next_tsn, GFP_ATOMIC); 601 602 out: 603 sctp_update_strreset_result(asoc, result); 604 err: 605 return sctp_make_strreset_tsnresp(asoc, result, request_seq, 606 next_tsn, init_tsn); 607 } 608 609 struct sctp_chunk *sctp_process_strreset_addstrm_out( 610 struct sctp_association *asoc, 611 union sctp_params param, 612 struct sctp_ulpevent **evp) 613 { 614 struct sctp_strreset_addstrm *addstrm = param.v; 615 struct sctp_stream *stream = asoc->stream; 616 __u32 result = SCTP_STRRESET_DENIED; 617 struct sctp_stream_in *streamin; 618 __u32 request_seq, incnt; 619 __u16 in, i; 620 621 request_seq = ntohl(addstrm->request_seq); 622 if (TSN_lt(asoc->strreset_inseq, request_seq) || 623 TSN_lt(request_seq, asoc->strreset_inseq - 2)) { 624 result = SCTP_STRRESET_ERR_BAD_SEQNO; 625 goto err; 626 } else if (TSN_lt(request_seq, asoc->strreset_inseq)) { 627 i = asoc->strreset_inseq - request_seq - 1; 628 result = asoc->strreset_result[i]; 629 goto err; 630 } 631 asoc->strreset_inseq++; 632 633 if (!(asoc->strreset_enable & SCTP_ENABLE_CHANGE_ASSOC_REQ)) 634 goto out; 635 636 if (asoc->strreset_chunk) { 637 if (!sctp_chunk_lookup_strreset_param( 638 asoc, 0, SCTP_PARAM_RESET_ADD_IN_STREAMS)) { 639 /* same process with outstanding isn't 0 */ 640 result = SCTP_STRRESET_ERR_IN_PROGRESS; 641 goto out; 642 } 643 644 asoc->strreset_outstanding--; 645 asoc->strreset_outseq++; 646 647 if (!asoc->strreset_outstanding) { 648 struct sctp_transport *t; 649 650 t = asoc->strreset_chunk->transport; 651 if (del_timer(&t->reconf_timer)) 652 sctp_transport_put(t); 653 654 sctp_chunk_put(asoc->strreset_chunk); 655 asoc->strreset_chunk = NULL; 656 } 657 } 658 659 in = ntohs(addstrm->number_of_streams); 660 incnt = stream->incnt + in; 661 if (!in || incnt > SCTP_MAX_STREAM) 662 goto out; 663 664 streamin = krealloc(stream->in, incnt * sizeof(*streamin), 665 GFP_ATOMIC); 666 if (!streamin) 667 goto out; 668 669 memset(streamin + stream->incnt, 0, in * sizeof(*streamin)); 670 stream->in = streamin; 671 stream->incnt = incnt; 672 673 result = SCTP_STRRESET_PERFORMED; 674 675 *evp = sctp_ulpevent_make_stream_change_event(asoc, 676 0, ntohs(addstrm->number_of_streams), 0, GFP_ATOMIC); 677 678 out: 679 sctp_update_strreset_result(asoc, result); 680 err: 681 return sctp_make_strreset_resp(asoc, result, request_seq); 682 } 683 684 struct sctp_chunk *sctp_process_strreset_addstrm_in( 685 struct sctp_association *asoc, 686 union sctp_params param, 687 struct sctp_ulpevent **evp) 688 { 689 struct sctp_strreset_addstrm *addstrm = param.v; 690 struct sctp_stream *stream = asoc->stream; 691 __u32 result = SCTP_STRRESET_DENIED; 692 struct sctp_stream_out *streamout; 693 struct sctp_chunk *chunk = NULL; 694 __u32 request_seq, outcnt; 695 __u16 out, i; 696 697 request_seq = ntohl(addstrm->request_seq); 698 if (TSN_lt(asoc->strreset_inseq, request_seq) || 699 TSN_lt(request_seq, asoc->strreset_inseq - 2)) { 700 result = SCTP_STRRESET_ERR_BAD_SEQNO; 701 goto err; 702 } else if (TSN_lt(request_seq, asoc->strreset_inseq)) { 703 i = asoc->strreset_inseq - request_seq - 1; 704 result = asoc->strreset_result[i]; 705 if (result == SCTP_STRRESET_PERFORMED) 706 return NULL; 707 goto err; 708 } 709 asoc->strreset_inseq++; 710 711 if (!(asoc->strreset_enable & SCTP_ENABLE_CHANGE_ASSOC_REQ)) 712 goto out; 713 714 if (asoc->strreset_outstanding) { 715 result = SCTP_STRRESET_ERR_IN_PROGRESS; 716 goto out; 717 } 718 719 out = ntohs(addstrm->number_of_streams); 720 outcnt = stream->outcnt + out; 721 if (!out || outcnt > SCTP_MAX_STREAM) 722 goto out; 723 724 streamout = krealloc(stream->out, outcnt * sizeof(*streamout), 725 GFP_ATOMIC); 726 if (!streamout) 727 goto out; 728 729 memset(streamout + stream->outcnt, 0, out * sizeof(*streamout)); 730 stream->out = streamout; 731 732 chunk = sctp_make_strreset_addstrm(asoc, out, 0); 733 if (!chunk) 734 goto out; 735 736 asoc->strreset_chunk = chunk; 737 asoc->strreset_outstanding = 1; 738 sctp_chunk_hold(asoc->strreset_chunk); 739 740 stream->outcnt = outcnt; 741 742 result = SCTP_STRRESET_PERFORMED; 743 744 *evp = sctp_ulpevent_make_stream_change_event(asoc, 745 0, 0, ntohs(addstrm->number_of_streams), GFP_ATOMIC); 746 747 out: 748 sctp_update_strreset_result(asoc, result); 749 err: 750 if (!chunk) 751 chunk = sctp_make_strreset_resp(asoc, result, request_seq); 752 753 return chunk; 754 } 755 756 struct sctp_chunk *sctp_process_strreset_resp( 757 struct sctp_association *asoc, 758 union sctp_params param, 759 struct sctp_ulpevent **evp) 760 { 761 struct sctp_strreset_resp *resp = param.v; 762 struct sctp_stream *stream = asoc->stream; 763 struct sctp_transport *t; 764 __u16 i, nums, flags = 0; 765 sctp_paramhdr_t *req; 766 __u32 result; 767 768 req = sctp_chunk_lookup_strreset_param(asoc, resp->response_seq, 0); 769 if (!req) 770 return NULL; 771 772 result = ntohl(resp->result); 773 if (result != SCTP_STRRESET_PERFORMED) { 774 /* if in progress, do nothing but retransmit */ 775 if (result == SCTP_STRRESET_IN_PROGRESS) 776 return NULL; 777 else if (result == SCTP_STRRESET_DENIED) 778 flags = SCTP_STREAM_RESET_DENIED; 779 else 780 flags = SCTP_STREAM_RESET_FAILED; 781 } 782 783 if (req->type == SCTP_PARAM_RESET_OUT_REQUEST) { 784 struct sctp_strreset_outreq *outreq; 785 __u16 *str_p; 786 787 outreq = (struct sctp_strreset_outreq *)req; 788 str_p = outreq->list_of_streams; 789 nums = (ntohs(outreq->param_hdr.length) - sizeof(*outreq)) / 2; 790 791 if (result == SCTP_STRRESET_PERFORMED) { 792 if (nums) { 793 for (i = 0; i < nums; i++) 794 stream->out[ntohs(str_p[i])].ssn = 0; 795 } else { 796 for (i = 0; i < stream->outcnt; i++) 797 stream->out[i].ssn = 0; 798 } 799 800 flags = SCTP_STREAM_RESET_OUTGOING_SSN; 801 } 802 803 for (i = 0; i < stream->outcnt; i++) 804 stream->out[i].state = SCTP_STREAM_OPEN; 805 806 *evp = sctp_ulpevent_make_stream_reset_event(asoc, flags, 807 nums, str_p, GFP_ATOMIC); 808 } else if (req->type == SCTP_PARAM_RESET_IN_REQUEST) { 809 struct sctp_strreset_inreq *inreq; 810 __u16 *str_p; 811 812 /* if the result is performed, it's impossible for inreq */ 813 if (result == SCTP_STRRESET_PERFORMED) 814 return NULL; 815 816 inreq = (struct sctp_strreset_inreq *)req; 817 str_p = inreq->list_of_streams; 818 nums = (ntohs(inreq->param_hdr.length) - sizeof(*inreq)) / 2; 819 820 *evp = sctp_ulpevent_make_stream_reset_event(asoc, flags, 821 nums, str_p, GFP_ATOMIC); 822 } else if (req->type == SCTP_PARAM_RESET_TSN_REQUEST) { 823 struct sctp_strreset_resptsn *resptsn; 824 __u32 stsn, rtsn; 825 826 /* check for resptsn, as sctp_verify_reconf didn't do it*/ 827 if (ntohs(param.p->length) != sizeof(*resptsn)) 828 return NULL; 829 830 resptsn = (struct sctp_strreset_resptsn *)resp; 831 stsn = ntohl(resptsn->senders_next_tsn); 832 rtsn = ntohl(resptsn->receivers_next_tsn); 833 834 if (result == SCTP_STRRESET_PERFORMED) { 835 __u32 mtsn = sctp_tsnmap_get_max_tsn_seen( 836 &asoc->peer.tsn_map); 837 838 sctp_ulpq_reasm_flushtsn(&asoc->ulpq, mtsn); 839 sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC); 840 841 sctp_tsnmap_init(&asoc->peer.tsn_map, 842 SCTP_TSN_MAP_INITIAL, 843 stsn, GFP_ATOMIC); 844 845 sctp_outq_free(&asoc->outqueue); 846 847 asoc->next_tsn = rtsn; 848 asoc->ctsn_ack_point = asoc->next_tsn - 1; 849 asoc->adv_peer_ack_point = asoc->ctsn_ack_point; 850 851 for (i = 0; i < stream->outcnt; i++) 852 stream->out[i].ssn = 0; 853 for (i = 0; i < stream->incnt; i++) 854 stream->in[i].ssn = 0; 855 } 856 857 for (i = 0; i < stream->outcnt; i++) 858 stream->out[i].state = SCTP_STREAM_OPEN; 859 860 *evp = sctp_ulpevent_make_assoc_reset_event(asoc, flags, 861 stsn, rtsn, GFP_ATOMIC); 862 } else if (req->type == SCTP_PARAM_RESET_ADD_OUT_STREAMS) { 863 struct sctp_strreset_addstrm *addstrm; 864 __u16 number; 865 866 addstrm = (struct sctp_strreset_addstrm *)req; 867 nums = ntohs(addstrm->number_of_streams); 868 number = stream->outcnt - nums; 869 870 if (result == SCTP_STRRESET_PERFORMED) 871 for (i = number; i < stream->outcnt; i++) 872 stream->out[i].state = SCTP_STREAM_OPEN; 873 else 874 stream->outcnt = number; 875 876 *evp = sctp_ulpevent_make_stream_change_event(asoc, flags, 877 0, nums, GFP_ATOMIC); 878 } else if (req->type == SCTP_PARAM_RESET_ADD_IN_STREAMS) { 879 struct sctp_strreset_addstrm *addstrm; 880 881 /* if the result is performed, it's impossible for addstrm in 882 * request. 883 */ 884 if (result == SCTP_STRRESET_PERFORMED) 885 return NULL; 886 887 addstrm = (struct sctp_strreset_addstrm *)req; 888 nums = ntohs(addstrm->number_of_streams); 889 890 *evp = sctp_ulpevent_make_stream_change_event(asoc, flags, 891 nums, 0, GFP_ATOMIC); 892 } 893 894 asoc->strreset_outstanding--; 895 asoc->strreset_outseq++; 896 897 /* remove everything for this reconf request */ 898 if (!asoc->strreset_outstanding) { 899 t = asoc->strreset_chunk->transport; 900 if (del_timer(&t->reconf_timer)) 901 sctp_transport_put(t); 902 903 sctp_chunk_put(asoc->strreset_chunk); 904 asoc->strreset_chunk = NULL; 905 } 906 907 return NULL; 908 } 909