diff options
Diffstat (limited to 'net/sctp/stream.c')
-rw-r--r-- | net/sctp/stream.c | 68 |
1 files changed, 33 insertions, 35 deletions
diff --git a/net/sctp/stream.c b/net/sctp/stream.c index dda53a293986..af6b49850344 100644 --- a/net/sctp/stream.c +++ b/net/sctp/stream.c | |||
@@ -37,30 +37,23 @@ | |||
37 | 37 | ||
38 | int sctp_stream_new(struct sctp_association *asoc, gfp_t gfp) | 38 | int sctp_stream_new(struct sctp_association *asoc, gfp_t gfp) |
39 | { | 39 | { |
40 | struct sctp_stream *stream; | 40 | struct sctp_stream *stream = &asoc->stream; |
41 | int i; | 41 | int i; |
42 | 42 | ||
43 | stream = kzalloc(sizeof(*stream), gfp); | ||
44 | if (!stream) | ||
45 | return -ENOMEM; | ||
46 | |||
47 | stream->outcnt = asoc->c.sinit_num_ostreams; | 43 | stream->outcnt = asoc->c.sinit_num_ostreams; |
48 | stream->out = kcalloc(stream->outcnt, sizeof(*stream->out), gfp); | 44 | stream->out = kcalloc(stream->outcnt, sizeof(*stream->out), gfp); |
49 | if (!stream->out) { | 45 | if (!stream->out) |
50 | kfree(stream); | ||
51 | return -ENOMEM; | 46 | return -ENOMEM; |
52 | } | 47 | |
53 | for (i = 0; i < stream->outcnt; i++) | 48 | for (i = 0; i < stream->outcnt; i++) |
54 | stream->out[i].state = SCTP_STREAM_OPEN; | 49 | stream->out[i].state = SCTP_STREAM_OPEN; |
55 | 50 | ||
56 | asoc->stream = stream; | ||
57 | |||
58 | return 0; | 51 | return 0; |
59 | } | 52 | } |
60 | 53 | ||
61 | int sctp_stream_init(struct sctp_association *asoc, gfp_t gfp) | 54 | int sctp_stream_init(struct sctp_association *asoc, gfp_t gfp) |
62 | { | 55 | { |
63 | struct sctp_stream *stream = asoc->stream; | 56 | struct sctp_stream *stream = &asoc->stream; |
64 | int i; | 57 | int i; |
65 | 58 | ||
66 | /* Initial stream->out size may be very big, so free it and alloc | 59 | /* Initial stream->out size may be very big, so free it and alloc |
@@ -70,7 +63,7 @@ int sctp_stream_init(struct sctp_association *asoc, gfp_t gfp) | |||
70 | stream->outcnt = asoc->c.sinit_num_ostreams; | 63 | stream->outcnt = asoc->c.sinit_num_ostreams; |
71 | stream->out = kcalloc(stream->outcnt, sizeof(*stream->out), gfp); | 64 | stream->out = kcalloc(stream->outcnt, sizeof(*stream->out), gfp); |
72 | if (!stream->out) | 65 | if (!stream->out) |
73 | goto nomem; | 66 | return -ENOMEM; |
74 | 67 | ||
75 | for (i = 0; i < stream->outcnt; i++) | 68 | for (i = 0; i < stream->outcnt; i++) |
76 | stream->out[i].state = SCTP_STREAM_OPEN; | 69 | stream->out[i].state = SCTP_STREAM_OPEN; |
@@ -79,26 +72,17 @@ int sctp_stream_init(struct sctp_association *asoc, gfp_t gfp) | |||
79 | stream->in = kcalloc(stream->incnt, sizeof(*stream->in), gfp); | 72 | stream->in = kcalloc(stream->incnt, sizeof(*stream->in), gfp); |
80 | if (!stream->in) { | 73 | if (!stream->in) { |
81 | kfree(stream->out); | 74 | kfree(stream->out); |
82 | goto nomem; | 75 | stream->out = NULL; |
76 | return -ENOMEM; | ||
83 | } | 77 | } |
84 | 78 | ||
85 | return 0; | 79 | return 0; |
86 | |||
87 | nomem: | ||
88 | asoc->stream = NULL; | ||
89 | kfree(stream); | ||
90 | |||
91 | return -ENOMEM; | ||
92 | } | 80 | } |
93 | 81 | ||
94 | void sctp_stream_free(struct sctp_stream *stream) | 82 | void sctp_stream_free(struct sctp_stream *stream) |
95 | { | 83 | { |
96 | if (unlikely(!stream)) | ||
97 | return; | ||
98 | |||
99 | kfree(stream->out); | 84 | kfree(stream->out); |
100 | kfree(stream->in); | 85 | kfree(stream->in); |
101 | kfree(stream); | ||
102 | } | 86 | } |
103 | 87 | ||
104 | void sctp_stream_clear(struct sctp_stream *stream) | 88 | void sctp_stream_clear(struct sctp_stream *stream) |
@@ -112,6 +96,19 @@ void sctp_stream_clear(struct sctp_stream *stream) | |||
112 | stream->in[i].ssn = 0; | 96 | stream->in[i].ssn = 0; |
113 | } | 97 | } |
114 | 98 | ||
99 | void sctp_stream_update(struct sctp_stream *stream, struct sctp_stream *new) | ||
100 | { | ||
101 | sctp_stream_free(stream); | ||
102 | |||
103 | stream->out = new->out; | ||
104 | stream->in = new->in; | ||
105 | stream->outcnt = new->outcnt; | ||
106 | stream->incnt = new->incnt; | ||
107 | |||
108 | new->out = NULL; | ||
109 | new->in = NULL; | ||
110 | } | ||
111 | |||
115 | static int sctp_send_reconf(struct sctp_association *asoc, | 112 | static int sctp_send_reconf(struct sctp_association *asoc, |
116 | struct sctp_chunk *chunk) | 113 | struct sctp_chunk *chunk) |
117 | { | 114 | { |
@@ -128,7 +125,7 @@ static int sctp_send_reconf(struct sctp_association *asoc, | |||
128 | int sctp_send_reset_streams(struct sctp_association *asoc, | 125 | int sctp_send_reset_streams(struct sctp_association *asoc, |
129 | struct sctp_reset_streams *params) | 126 | struct sctp_reset_streams *params) |
130 | { | 127 | { |
131 | struct sctp_stream *stream = asoc->stream; | 128 | struct sctp_stream *stream = &asoc->stream; |
132 | __u16 i, str_nums, *str_list; | 129 | __u16 i, str_nums, *str_list; |
133 | struct sctp_chunk *chunk; | 130 | struct sctp_chunk *chunk; |
134 | int retval = -EINVAL; | 131 | int retval = -EINVAL; |
@@ -214,6 +211,7 @@ out: | |||
214 | 211 | ||
215 | int sctp_send_reset_assoc(struct sctp_association *asoc) | 212 | int sctp_send_reset_assoc(struct sctp_association *asoc) |
216 | { | 213 | { |
214 | struct sctp_stream *stream = &asoc->stream; | ||
217 | struct sctp_chunk *chunk = NULL; | 215 | struct sctp_chunk *chunk = NULL; |
218 | int retval; | 216 | int retval; |
219 | __u16 i; | 217 | __u16 i; |
@@ -230,8 +228,8 @@ int sctp_send_reset_assoc(struct sctp_association *asoc) | |||
230 | return -ENOMEM; | 228 | return -ENOMEM; |
231 | 229 | ||
232 | /* Block further xmit of data until this request is completed */ | 230 | /* Block further xmit of data until this request is completed */ |
233 | for (i = 0; i < asoc->stream->outcnt; i++) | 231 | for (i = 0; i < stream->outcnt; i++) |
234 | asoc->stream->out[i].state = SCTP_STREAM_CLOSED; | 232 | stream->out[i].state = SCTP_STREAM_CLOSED; |
235 | 233 | ||
236 | asoc->strreset_chunk = chunk; | 234 | asoc->strreset_chunk = chunk; |
237 | sctp_chunk_hold(asoc->strreset_chunk); | 235 | sctp_chunk_hold(asoc->strreset_chunk); |
@@ -241,8 +239,8 @@ int sctp_send_reset_assoc(struct sctp_association *asoc) | |||
241 | sctp_chunk_put(asoc->strreset_chunk); | 239 | sctp_chunk_put(asoc->strreset_chunk); |
242 | asoc->strreset_chunk = NULL; | 240 | asoc->strreset_chunk = NULL; |
243 | 241 | ||
244 | for (i = 0; i < asoc->stream->outcnt; i++) | 242 | for (i = 0; i < stream->outcnt; i++) |
245 | asoc->stream->out[i].state = SCTP_STREAM_OPEN; | 243 | stream->out[i].state = SCTP_STREAM_OPEN; |
246 | 244 | ||
247 | return retval; | 245 | return retval; |
248 | } | 246 | } |
@@ -255,7 +253,7 @@ int sctp_send_reset_assoc(struct sctp_association *asoc) | |||
255 | int sctp_send_add_streams(struct sctp_association *asoc, | 253 | int sctp_send_add_streams(struct sctp_association *asoc, |
256 | struct sctp_add_streams *params) | 254 | struct sctp_add_streams *params) |
257 | { | 255 | { |
258 | struct sctp_stream *stream = asoc->stream; | 256 | struct sctp_stream *stream = &asoc->stream; |
259 | struct sctp_chunk *chunk = NULL; | 257 | struct sctp_chunk *chunk = NULL; |
260 | int retval = -ENOMEM; | 258 | int retval = -ENOMEM; |
261 | __u32 outcnt, incnt; | 259 | __u32 outcnt, incnt; |
@@ -357,7 +355,7 @@ struct sctp_chunk *sctp_process_strreset_outreq( | |||
357 | struct sctp_ulpevent **evp) | 355 | struct sctp_ulpevent **evp) |
358 | { | 356 | { |
359 | struct sctp_strreset_outreq *outreq = param.v; | 357 | struct sctp_strreset_outreq *outreq = param.v; |
360 | struct sctp_stream *stream = asoc->stream; | 358 | struct sctp_stream *stream = &asoc->stream; |
361 | __u16 i, nums, flags = 0, *str_p = NULL; | 359 | __u16 i, nums, flags = 0, *str_p = NULL; |
362 | __u32 result = SCTP_STRRESET_DENIED; | 360 | __u32 result = SCTP_STRRESET_DENIED; |
363 | __u32 request_seq; | 361 | __u32 request_seq; |
@@ -449,7 +447,7 @@ struct sctp_chunk *sctp_process_strreset_inreq( | |||
449 | struct sctp_ulpevent **evp) | 447 | struct sctp_ulpevent **evp) |
450 | { | 448 | { |
451 | struct sctp_strreset_inreq *inreq = param.v; | 449 | struct sctp_strreset_inreq *inreq = param.v; |
452 | struct sctp_stream *stream = asoc->stream; | 450 | struct sctp_stream *stream = &asoc->stream; |
453 | __u32 result = SCTP_STRRESET_DENIED; | 451 | __u32 result = SCTP_STRRESET_DENIED; |
454 | struct sctp_chunk *chunk = NULL; | 452 | struct sctp_chunk *chunk = NULL; |
455 | __u16 i, nums, *str_p; | 453 | __u16 i, nums, *str_p; |
@@ -523,7 +521,7 @@ struct sctp_chunk *sctp_process_strreset_tsnreq( | |||
523 | { | 521 | { |
524 | __u32 init_tsn = 0, next_tsn = 0, max_tsn_seen; | 522 | __u32 init_tsn = 0, next_tsn = 0, max_tsn_seen; |
525 | struct sctp_strreset_tsnreq *tsnreq = param.v; | 523 | struct sctp_strreset_tsnreq *tsnreq = param.v; |
526 | struct sctp_stream *stream = asoc->stream; | 524 | struct sctp_stream *stream = &asoc->stream; |
527 | __u32 result = SCTP_STRRESET_DENIED; | 525 | __u32 result = SCTP_STRRESET_DENIED; |
528 | __u32 request_seq; | 526 | __u32 request_seq; |
529 | __u16 i; | 527 | __u16 i; |
@@ -612,7 +610,7 @@ struct sctp_chunk *sctp_process_strreset_addstrm_out( | |||
612 | struct sctp_ulpevent **evp) | 610 | struct sctp_ulpevent **evp) |
613 | { | 611 | { |
614 | struct sctp_strreset_addstrm *addstrm = param.v; | 612 | struct sctp_strreset_addstrm *addstrm = param.v; |
615 | struct sctp_stream *stream = asoc->stream; | 613 | struct sctp_stream *stream = &asoc->stream; |
616 | __u32 result = SCTP_STRRESET_DENIED; | 614 | __u32 result = SCTP_STRRESET_DENIED; |
617 | struct sctp_stream_in *streamin; | 615 | struct sctp_stream_in *streamin; |
618 | __u32 request_seq, incnt; | 616 | __u32 request_seq, incnt; |
@@ -687,7 +685,7 @@ struct sctp_chunk *sctp_process_strreset_addstrm_in( | |||
687 | struct sctp_ulpevent **evp) | 685 | struct sctp_ulpevent **evp) |
688 | { | 686 | { |
689 | struct sctp_strreset_addstrm *addstrm = param.v; | 687 | struct sctp_strreset_addstrm *addstrm = param.v; |
690 | struct sctp_stream *stream = asoc->stream; | 688 | struct sctp_stream *stream = &asoc->stream; |
691 | __u32 result = SCTP_STRRESET_DENIED; | 689 | __u32 result = SCTP_STRRESET_DENIED; |
692 | struct sctp_stream_out *streamout; | 690 | struct sctp_stream_out *streamout; |
693 | struct sctp_chunk *chunk = NULL; | 691 | struct sctp_chunk *chunk = NULL; |
@@ -758,8 +756,8 @@ struct sctp_chunk *sctp_process_strreset_resp( | |||
758 | union sctp_params param, | 756 | union sctp_params param, |
759 | struct sctp_ulpevent **evp) | 757 | struct sctp_ulpevent **evp) |
760 | { | 758 | { |
759 | struct sctp_stream *stream = &asoc->stream; | ||
761 | struct sctp_strreset_resp *resp = param.v; | 760 | struct sctp_strreset_resp *resp = param.v; |
762 | struct sctp_stream *stream = asoc->stream; | ||
763 | struct sctp_transport *t; | 761 | struct sctp_transport *t; |
764 | __u16 i, nums, flags = 0; | 762 | __u16 i, nums, flags = 0; |
765 | sctp_paramhdr_t *req; | 763 | sctp_paramhdr_t *req; |