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