stream.c 28 KB

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