Commit ac40e41f4ddec8882d3f7bc8fa98a4fce8796aff
Committed by
David S. Miller
1 parent
70b57b814e
Exists in
master
and in
7 other branches
[SCTP]: Do not include ABORT chunk header in the notification.
The socket API draft is unclear about whether to include the chunk header or not. Recent discussion on the sctp implementors mailing list clarified that the chunk header shouldn't be included, but the error parameter header still needs to be there. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 1 changed file with 2 additions and 9 deletions Inline Diff
net/sctp/ulpevent.c
1 | /* SCTP kernel reference Implementation | 1 | /* SCTP kernel reference Implementation |
2 | * (C) Copyright IBM Corp. 2001, 2004 | 2 | * (C) Copyright IBM Corp. 2001, 2004 |
3 | * Copyright (c) 1999-2000 Cisco, Inc. | 3 | * Copyright (c) 1999-2000 Cisco, Inc. |
4 | * Copyright (c) 1999-2001 Motorola, Inc. | 4 | * Copyright (c) 1999-2001 Motorola, Inc. |
5 | * Copyright (c) 2001 Intel Corp. | 5 | * Copyright (c) 2001 Intel Corp. |
6 | * Copyright (c) 2001 Nokia, Inc. | 6 | * Copyright (c) 2001 Nokia, Inc. |
7 | * Copyright (c) 2001 La Monte H.P. Yarroll | 7 | * Copyright (c) 2001 La Monte H.P. Yarroll |
8 | * | 8 | * |
9 | * These functions manipulate an sctp event. The struct ulpevent is used | 9 | * These functions manipulate an sctp event. The struct ulpevent is used |
10 | * to carry notifications and data to the ULP (sockets). | 10 | * to carry notifications and data to the ULP (sockets). |
11 | * The SCTP reference implementation is free software; | 11 | * The SCTP reference implementation is free software; |
12 | * you can redistribute it and/or modify it under the terms of | 12 | * you can redistribute it and/or modify it under the terms of |
13 | * the GNU General Public License as published by | 13 | * the GNU General Public License as published by |
14 | * the Free Software Foundation; either version 2, or (at your option) | 14 | * the Free Software Foundation; either version 2, or (at your option) |
15 | * any later version. | 15 | * any later version. |
16 | * | 16 | * |
17 | * The SCTP reference implementation is distributed in the hope that it | 17 | * The SCTP reference implementation is distributed in the hope that it |
18 | * will be useful, but WITHOUT ANY WARRANTY; without even the implied | 18 | * will be useful, but WITHOUT ANY WARRANTY; without even the implied |
19 | * ************************ | 19 | * ************************ |
20 | * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 20 | * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
21 | * See the GNU General Public License for more details. | 21 | * See the GNU General Public License for more details. |
22 | * | 22 | * |
23 | * You should have received a copy of the GNU General Public License | 23 | * You should have received a copy of the GNU General Public License |
24 | * along with GNU CC; see the file COPYING. If not, write to | 24 | * along with GNU CC; see the file COPYING. If not, write to |
25 | * the Free Software Foundation, 59 Temple Place - Suite 330, | 25 | * the Free Software Foundation, 59 Temple Place - Suite 330, |
26 | * Boston, MA 02111-1307, USA. | 26 | * Boston, MA 02111-1307, USA. |
27 | * | 27 | * |
28 | * Please send any bug reports or fixes you make to the | 28 | * Please send any bug reports or fixes you make to the |
29 | * email address(es): | 29 | * email address(es): |
30 | * lksctp developers <lksctp-developers@lists.sourceforge.net> | 30 | * lksctp developers <lksctp-developers@lists.sourceforge.net> |
31 | * | 31 | * |
32 | * Or submit a bug report through the following website: | 32 | * Or submit a bug report through the following website: |
33 | * http://www.sf.net/projects/lksctp | 33 | * http://www.sf.net/projects/lksctp |
34 | * | 34 | * |
35 | * Written or modified by: | 35 | * Written or modified by: |
36 | * Jon Grimm <jgrimm@us.ibm.com> | 36 | * Jon Grimm <jgrimm@us.ibm.com> |
37 | * La Monte H.P. Yarroll <piggy@acm.org> | 37 | * La Monte H.P. Yarroll <piggy@acm.org> |
38 | * Ardelle Fan <ardelle.fan@intel.com> | 38 | * Ardelle Fan <ardelle.fan@intel.com> |
39 | * Sridhar Samudrala <sri@us.ibm.com> | 39 | * Sridhar Samudrala <sri@us.ibm.com> |
40 | * | 40 | * |
41 | * Any bugs reported given to us we will try to fix... any fixes shared will | 41 | * Any bugs reported given to us we will try to fix... any fixes shared will |
42 | * be incorporated into the next SCTP release. | 42 | * be incorporated into the next SCTP release. |
43 | */ | 43 | */ |
44 | 44 | ||
45 | #include <linux/types.h> | 45 | #include <linux/types.h> |
46 | #include <linux/skbuff.h> | 46 | #include <linux/skbuff.h> |
47 | #include <net/sctp/structs.h> | 47 | #include <net/sctp/structs.h> |
48 | #include <net/sctp/sctp.h> | 48 | #include <net/sctp/sctp.h> |
49 | #include <net/sctp/sm.h> | 49 | #include <net/sctp/sm.h> |
50 | 50 | ||
51 | static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event, | 51 | static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event, |
52 | struct sctp_association *asoc); | 52 | struct sctp_association *asoc); |
53 | static void sctp_ulpevent_release_data(struct sctp_ulpevent *event); | 53 | static void sctp_ulpevent_release_data(struct sctp_ulpevent *event); |
54 | static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event); | 54 | static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event); |
55 | 55 | ||
56 | 56 | ||
57 | /* Initialize an ULP event from an given skb. */ | 57 | /* Initialize an ULP event from an given skb. */ |
58 | SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, | 58 | SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, |
59 | int msg_flags, | 59 | int msg_flags, |
60 | unsigned int len) | 60 | unsigned int len) |
61 | { | 61 | { |
62 | memset(event, 0, sizeof(struct sctp_ulpevent)); | 62 | memset(event, 0, sizeof(struct sctp_ulpevent)); |
63 | event->msg_flags = msg_flags; | 63 | event->msg_flags = msg_flags; |
64 | event->rmem_len = len; | 64 | event->rmem_len = len; |
65 | } | 65 | } |
66 | 66 | ||
67 | /* Create a new sctp_ulpevent. */ | 67 | /* Create a new sctp_ulpevent. */ |
68 | SCTP_STATIC struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags, | 68 | SCTP_STATIC struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags, |
69 | gfp_t gfp) | 69 | gfp_t gfp) |
70 | { | 70 | { |
71 | struct sctp_ulpevent *event; | 71 | struct sctp_ulpevent *event; |
72 | struct sk_buff *skb; | 72 | struct sk_buff *skb; |
73 | 73 | ||
74 | skb = alloc_skb(size, gfp); | 74 | skb = alloc_skb(size, gfp); |
75 | if (!skb) | 75 | if (!skb) |
76 | goto fail; | 76 | goto fail; |
77 | 77 | ||
78 | event = sctp_skb2event(skb); | 78 | event = sctp_skb2event(skb); |
79 | sctp_ulpevent_init(event, msg_flags, skb->truesize); | 79 | sctp_ulpevent_init(event, msg_flags, skb->truesize); |
80 | 80 | ||
81 | return event; | 81 | return event; |
82 | 82 | ||
83 | fail: | 83 | fail: |
84 | return NULL; | 84 | return NULL; |
85 | } | 85 | } |
86 | 86 | ||
87 | /* Is this a MSG_NOTIFICATION? */ | 87 | /* Is this a MSG_NOTIFICATION? */ |
88 | int sctp_ulpevent_is_notification(const struct sctp_ulpevent *event) | 88 | int sctp_ulpevent_is_notification(const struct sctp_ulpevent *event) |
89 | { | 89 | { |
90 | return MSG_NOTIFICATION == (event->msg_flags & MSG_NOTIFICATION); | 90 | return MSG_NOTIFICATION == (event->msg_flags & MSG_NOTIFICATION); |
91 | } | 91 | } |
92 | 92 | ||
93 | /* Hold the association in case the msg_name needs read out of | 93 | /* Hold the association in case the msg_name needs read out of |
94 | * the association. | 94 | * the association. |
95 | */ | 95 | */ |
96 | static inline void sctp_ulpevent_set_owner(struct sctp_ulpevent *event, | 96 | static inline void sctp_ulpevent_set_owner(struct sctp_ulpevent *event, |
97 | const struct sctp_association *asoc) | 97 | const struct sctp_association *asoc) |
98 | { | 98 | { |
99 | struct sk_buff *skb; | 99 | struct sk_buff *skb; |
100 | 100 | ||
101 | /* Cast away the const, as we are just wanting to | 101 | /* Cast away the const, as we are just wanting to |
102 | * bump the reference count. | 102 | * bump the reference count. |
103 | */ | 103 | */ |
104 | sctp_association_hold((struct sctp_association *)asoc); | 104 | sctp_association_hold((struct sctp_association *)asoc); |
105 | skb = sctp_event2skb(event); | 105 | skb = sctp_event2skb(event); |
106 | event->asoc = (struct sctp_association *)asoc; | 106 | event->asoc = (struct sctp_association *)asoc; |
107 | atomic_add(event->rmem_len, &event->asoc->rmem_alloc); | 107 | atomic_add(event->rmem_len, &event->asoc->rmem_alloc); |
108 | sctp_skb_set_owner_r(skb, asoc->base.sk); | 108 | sctp_skb_set_owner_r(skb, asoc->base.sk); |
109 | } | 109 | } |
110 | 110 | ||
111 | /* A simple destructor to give up the reference to the association. */ | 111 | /* A simple destructor to give up the reference to the association. */ |
112 | static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event) | 112 | static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event) |
113 | { | 113 | { |
114 | struct sctp_association *asoc = event->asoc; | 114 | struct sctp_association *asoc = event->asoc; |
115 | 115 | ||
116 | atomic_sub(event->rmem_len, &asoc->rmem_alloc); | 116 | atomic_sub(event->rmem_len, &asoc->rmem_alloc); |
117 | sctp_association_put(asoc); | 117 | sctp_association_put(asoc); |
118 | } | 118 | } |
119 | 119 | ||
120 | /* Create and initialize an SCTP_ASSOC_CHANGE event. | 120 | /* Create and initialize an SCTP_ASSOC_CHANGE event. |
121 | * | 121 | * |
122 | * 5.3.1.1 SCTP_ASSOC_CHANGE | 122 | * 5.3.1.1 SCTP_ASSOC_CHANGE |
123 | * | 123 | * |
124 | * Communication notifications inform the ULP that an SCTP association | 124 | * Communication notifications inform the ULP that an SCTP association |
125 | * has either begun or ended. The identifier for a new association is | 125 | * has either begun or ended. The identifier for a new association is |
126 | * provided by this notification. | 126 | * provided by this notification. |
127 | * | 127 | * |
128 | * Note: There is no field checking here. If a field is unused it will be | 128 | * Note: There is no field checking here. If a field is unused it will be |
129 | * zero'd out. | 129 | * zero'd out. |
130 | */ | 130 | */ |
131 | struct sctp_ulpevent *sctp_ulpevent_make_assoc_change( | 131 | struct sctp_ulpevent *sctp_ulpevent_make_assoc_change( |
132 | const struct sctp_association *asoc, | 132 | const struct sctp_association *asoc, |
133 | __u16 flags, __u16 state, __u16 error, __u16 outbound, | 133 | __u16 flags, __u16 state, __u16 error, __u16 outbound, |
134 | __u16 inbound, struct sctp_chunk *chunk, gfp_t gfp) | 134 | __u16 inbound, struct sctp_chunk *chunk, gfp_t gfp) |
135 | { | 135 | { |
136 | struct sctp_ulpevent *event; | 136 | struct sctp_ulpevent *event; |
137 | struct sctp_assoc_change *sac; | 137 | struct sctp_assoc_change *sac; |
138 | struct sk_buff *skb; | 138 | struct sk_buff *skb; |
139 | 139 | ||
140 | /* If the lower layer passed in the chunk, it will be | 140 | /* If the lower layer passed in the chunk, it will be |
141 | * an ABORT, so we need to include it in the sac_info. | 141 | * an ABORT, so we need to include it in the sac_info. |
142 | */ | 142 | */ |
143 | if (chunk) { | 143 | if (chunk) { |
144 | /* sctp_inqu_pop() has allready pulled off the chunk | ||
145 | * header. We need to put it back temporarily | ||
146 | */ | ||
147 | skb_push(chunk->skb, sizeof(sctp_chunkhdr_t)); | ||
148 | |||
149 | /* Copy the chunk data to a new skb and reserve enough | 144 | /* Copy the chunk data to a new skb and reserve enough |
150 | * head room to use as notification. | 145 | * head room to use as notification. |
151 | */ | 146 | */ |
152 | skb = skb_copy_expand(chunk->skb, | 147 | skb = skb_copy_expand(chunk->skb, |
153 | sizeof(struct sctp_assoc_change), 0, gfp); | 148 | sizeof(struct sctp_assoc_change), 0, gfp); |
154 | 149 | ||
155 | if (!skb) | 150 | if (!skb) |
156 | goto fail; | 151 | goto fail; |
157 | 152 | ||
158 | /* put back the chunk header now that we have a copy */ | ||
159 | skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t)); | ||
160 | |||
161 | /* Embed the event fields inside the cloned skb. */ | 153 | /* Embed the event fields inside the cloned skb. */ |
162 | event = sctp_skb2event(skb); | 154 | event = sctp_skb2event(skb); |
163 | sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize); | 155 | sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize); |
164 | 156 | ||
165 | /* Include the notification structure */ | 157 | /* Include the notification structure */ |
166 | sac = (struct sctp_assoc_change *) | 158 | sac = (struct sctp_assoc_change *) |
167 | skb_push(skb, sizeof(struct sctp_assoc_change)); | 159 | skb_push(skb, sizeof(struct sctp_assoc_change)); |
168 | 160 | ||
169 | /* Trim the buffer to the right length. */ | 161 | /* Trim the buffer to the right length. */ |
170 | skb_trim(skb, sizeof(struct sctp_assoc_change) + | 162 | skb_trim(skb, sizeof(struct sctp_assoc_change) + |
171 | ntohs(chunk->chunk_hdr->length)); | 163 | ntohs(chunk->chunk_hdr->length) - |
164 | sizeof(sctp_chunkhdr_t)); | ||
172 | } else { | 165 | } else { |
173 | event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change), | 166 | event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change), |
174 | MSG_NOTIFICATION, gfp); | 167 | MSG_NOTIFICATION, gfp); |
175 | if (!event) | 168 | if (!event) |
176 | goto fail; | 169 | goto fail; |
177 | 170 | ||
178 | skb = sctp_event2skb(event); | 171 | skb = sctp_event2skb(event); |
179 | sac = (struct sctp_assoc_change *) skb_put(skb, | 172 | sac = (struct sctp_assoc_change *) skb_put(skb, |
180 | sizeof(struct sctp_assoc_change)); | 173 | sizeof(struct sctp_assoc_change)); |
181 | } | 174 | } |
182 | 175 | ||
183 | /* Socket Extensions for SCTP | 176 | /* Socket Extensions for SCTP |
184 | * 5.3.1.1 SCTP_ASSOC_CHANGE | 177 | * 5.3.1.1 SCTP_ASSOC_CHANGE |
185 | * | 178 | * |
186 | * sac_type: | 179 | * sac_type: |
187 | * It should be SCTP_ASSOC_CHANGE. | 180 | * It should be SCTP_ASSOC_CHANGE. |
188 | */ | 181 | */ |
189 | sac->sac_type = SCTP_ASSOC_CHANGE; | 182 | sac->sac_type = SCTP_ASSOC_CHANGE; |
190 | 183 | ||
191 | /* Socket Extensions for SCTP | 184 | /* Socket Extensions for SCTP |
192 | * 5.3.1.1 SCTP_ASSOC_CHANGE | 185 | * 5.3.1.1 SCTP_ASSOC_CHANGE |
193 | * | 186 | * |
194 | * sac_state: 32 bits (signed integer) | 187 | * sac_state: 32 bits (signed integer) |
195 | * This field holds one of a number of values that communicate the | 188 | * This field holds one of a number of values that communicate the |
196 | * event that happened to the association. | 189 | * event that happened to the association. |
197 | */ | 190 | */ |
198 | sac->sac_state = state; | 191 | sac->sac_state = state; |
199 | 192 | ||
200 | /* Socket Extensions for SCTP | 193 | /* Socket Extensions for SCTP |
201 | * 5.3.1.1 SCTP_ASSOC_CHANGE | 194 | * 5.3.1.1 SCTP_ASSOC_CHANGE |
202 | * | 195 | * |
203 | * sac_flags: 16 bits (unsigned integer) | 196 | * sac_flags: 16 bits (unsigned integer) |
204 | * Currently unused. | 197 | * Currently unused. |
205 | */ | 198 | */ |
206 | sac->sac_flags = 0; | 199 | sac->sac_flags = 0; |
207 | 200 | ||
208 | /* Socket Extensions for SCTP | 201 | /* Socket Extensions for SCTP |
209 | * 5.3.1.1 SCTP_ASSOC_CHANGE | 202 | * 5.3.1.1 SCTP_ASSOC_CHANGE |
210 | * | 203 | * |
211 | * sac_length: sizeof (__u32) | 204 | * sac_length: sizeof (__u32) |
212 | * This field is the total length of the notification data, including | 205 | * This field is the total length of the notification data, including |
213 | * the notification header. | 206 | * the notification header. |
214 | */ | 207 | */ |
215 | sac->sac_length = sizeof(struct sctp_assoc_change); | 208 | sac->sac_length = sizeof(struct sctp_assoc_change); |
216 | 209 | ||
217 | /* Socket Extensions for SCTP | 210 | /* Socket Extensions for SCTP |
218 | * 5.3.1.1 SCTP_ASSOC_CHANGE | 211 | * 5.3.1.1 SCTP_ASSOC_CHANGE |
219 | * | 212 | * |
220 | * sac_error: 32 bits (signed integer) | 213 | * sac_error: 32 bits (signed integer) |
221 | * | 214 | * |
222 | * If the state was reached due to a error condition (e.g. | 215 | * If the state was reached due to a error condition (e.g. |
223 | * COMMUNICATION_LOST) any relevant error information is available in | 216 | * COMMUNICATION_LOST) any relevant error information is available in |
224 | * this field. This corresponds to the protocol error codes defined in | 217 | * this field. This corresponds to the protocol error codes defined in |
225 | * [SCTP]. | 218 | * [SCTP]. |
226 | */ | 219 | */ |
227 | sac->sac_error = error; | 220 | sac->sac_error = error; |
228 | 221 | ||
229 | /* Socket Extensions for SCTP | 222 | /* Socket Extensions for SCTP |
230 | * 5.3.1.1 SCTP_ASSOC_CHANGE | 223 | * 5.3.1.1 SCTP_ASSOC_CHANGE |
231 | * | 224 | * |
232 | * sac_outbound_streams: 16 bits (unsigned integer) | 225 | * sac_outbound_streams: 16 bits (unsigned integer) |
233 | * sac_inbound_streams: 16 bits (unsigned integer) | 226 | * sac_inbound_streams: 16 bits (unsigned integer) |
234 | * | 227 | * |
235 | * The maximum number of streams allowed in each direction are | 228 | * The maximum number of streams allowed in each direction are |
236 | * available in sac_outbound_streams and sac_inbound streams. | 229 | * available in sac_outbound_streams and sac_inbound streams. |
237 | */ | 230 | */ |
238 | sac->sac_outbound_streams = outbound; | 231 | sac->sac_outbound_streams = outbound; |
239 | sac->sac_inbound_streams = inbound; | 232 | sac->sac_inbound_streams = inbound; |
240 | 233 | ||
241 | /* Socket Extensions for SCTP | 234 | /* Socket Extensions for SCTP |
242 | * 5.3.1.1 SCTP_ASSOC_CHANGE | 235 | * 5.3.1.1 SCTP_ASSOC_CHANGE |
243 | * | 236 | * |
244 | * sac_assoc_id: sizeof (sctp_assoc_t) | 237 | * sac_assoc_id: sizeof (sctp_assoc_t) |
245 | * | 238 | * |
246 | * The association id field, holds the identifier for the association. | 239 | * The association id field, holds the identifier for the association. |
247 | * All notifications for a given association have the same association | 240 | * All notifications for a given association have the same association |
248 | * identifier. For TCP style socket, this field is ignored. | 241 | * identifier. For TCP style socket, this field is ignored. |
249 | */ | 242 | */ |
250 | sctp_ulpevent_set_owner(event, asoc); | 243 | sctp_ulpevent_set_owner(event, asoc); |
251 | sac->sac_assoc_id = sctp_assoc2id(asoc); | 244 | sac->sac_assoc_id = sctp_assoc2id(asoc); |
252 | 245 | ||
253 | return event; | 246 | return event; |
254 | 247 | ||
255 | fail: | 248 | fail: |
256 | return NULL; | 249 | return NULL; |
257 | } | 250 | } |
258 | 251 | ||
259 | /* Create and initialize an SCTP_PEER_ADDR_CHANGE event. | 252 | /* Create and initialize an SCTP_PEER_ADDR_CHANGE event. |
260 | * | 253 | * |
261 | * Socket Extensions for SCTP - draft-01 | 254 | * Socket Extensions for SCTP - draft-01 |
262 | * 5.3.1.2 SCTP_PEER_ADDR_CHANGE | 255 | * 5.3.1.2 SCTP_PEER_ADDR_CHANGE |
263 | * | 256 | * |
264 | * When a destination address on a multi-homed peer encounters a change | 257 | * When a destination address on a multi-homed peer encounters a change |
265 | * an interface details event is sent. | 258 | * an interface details event is sent. |
266 | */ | 259 | */ |
267 | struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change( | 260 | struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change( |
268 | const struct sctp_association *asoc, | 261 | const struct sctp_association *asoc, |
269 | const struct sockaddr_storage *aaddr, | 262 | const struct sockaddr_storage *aaddr, |
270 | int flags, int state, int error, gfp_t gfp) | 263 | int flags, int state, int error, gfp_t gfp) |
271 | { | 264 | { |
272 | struct sctp_ulpevent *event; | 265 | struct sctp_ulpevent *event; |
273 | struct sctp_paddr_change *spc; | 266 | struct sctp_paddr_change *spc; |
274 | struct sk_buff *skb; | 267 | struct sk_buff *skb; |
275 | 268 | ||
276 | event = sctp_ulpevent_new(sizeof(struct sctp_paddr_change), | 269 | event = sctp_ulpevent_new(sizeof(struct sctp_paddr_change), |
277 | MSG_NOTIFICATION, gfp); | 270 | MSG_NOTIFICATION, gfp); |
278 | if (!event) | 271 | if (!event) |
279 | goto fail; | 272 | goto fail; |
280 | 273 | ||
281 | skb = sctp_event2skb(event); | 274 | skb = sctp_event2skb(event); |
282 | spc = (struct sctp_paddr_change *) | 275 | spc = (struct sctp_paddr_change *) |
283 | skb_put(skb, sizeof(struct sctp_paddr_change)); | 276 | skb_put(skb, sizeof(struct sctp_paddr_change)); |
284 | 277 | ||
285 | /* Sockets API Extensions for SCTP | 278 | /* Sockets API Extensions for SCTP |
286 | * Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE | 279 | * Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE |
287 | * | 280 | * |
288 | * spc_type: | 281 | * spc_type: |
289 | * | 282 | * |
290 | * It should be SCTP_PEER_ADDR_CHANGE. | 283 | * It should be SCTP_PEER_ADDR_CHANGE. |
291 | */ | 284 | */ |
292 | spc->spc_type = SCTP_PEER_ADDR_CHANGE; | 285 | spc->spc_type = SCTP_PEER_ADDR_CHANGE; |
293 | 286 | ||
294 | /* Sockets API Extensions for SCTP | 287 | /* Sockets API Extensions for SCTP |
295 | * Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE | 288 | * Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE |
296 | * | 289 | * |
297 | * spc_length: sizeof (__u32) | 290 | * spc_length: sizeof (__u32) |
298 | * | 291 | * |
299 | * This field is the total length of the notification data, including | 292 | * This field is the total length of the notification data, including |
300 | * the notification header. | 293 | * the notification header. |
301 | */ | 294 | */ |
302 | spc->spc_length = sizeof(struct sctp_paddr_change); | 295 | spc->spc_length = sizeof(struct sctp_paddr_change); |
303 | 296 | ||
304 | /* Sockets API Extensions for SCTP | 297 | /* Sockets API Extensions for SCTP |
305 | * Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE | 298 | * Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE |
306 | * | 299 | * |
307 | * spc_flags: 16 bits (unsigned integer) | 300 | * spc_flags: 16 bits (unsigned integer) |
308 | * Currently unused. | 301 | * Currently unused. |
309 | */ | 302 | */ |
310 | spc->spc_flags = 0; | 303 | spc->spc_flags = 0; |
311 | 304 | ||
312 | /* Sockets API Extensions for SCTP | 305 | /* Sockets API Extensions for SCTP |
313 | * Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE | 306 | * Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE |
314 | * | 307 | * |
315 | * spc_state: 32 bits (signed integer) | 308 | * spc_state: 32 bits (signed integer) |
316 | * | 309 | * |
317 | * This field holds one of a number of values that communicate the | 310 | * This field holds one of a number of values that communicate the |
318 | * event that happened to the address. | 311 | * event that happened to the address. |
319 | */ | 312 | */ |
320 | spc->spc_state = state; | 313 | spc->spc_state = state; |
321 | 314 | ||
322 | /* Sockets API Extensions for SCTP | 315 | /* Sockets API Extensions for SCTP |
323 | * Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE | 316 | * Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE |
324 | * | 317 | * |
325 | * spc_error: 32 bits (signed integer) | 318 | * spc_error: 32 bits (signed integer) |
326 | * | 319 | * |
327 | * If the state was reached due to any error condition (e.g. | 320 | * If the state was reached due to any error condition (e.g. |
328 | * ADDRESS_UNREACHABLE) any relevant error information is available in | 321 | * ADDRESS_UNREACHABLE) any relevant error information is available in |
329 | * this field. | 322 | * this field. |
330 | */ | 323 | */ |
331 | spc->spc_error = error; | 324 | spc->spc_error = error; |
332 | 325 | ||
333 | /* Socket Extensions for SCTP | 326 | /* Socket Extensions for SCTP |
334 | * 5.3.1.1 SCTP_ASSOC_CHANGE | 327 | * 5.3.1.1 SCTP_ASSOC_CHANGE |
335 | * | 328 | * |
336 | * spc_assoc_id: sizeof (sctp_assoc_t) | 329 | * spc_assoc_id: sizeof (sctp_assoc_t) |
337 | * | 330 | * |
338 | * The association id field, holds the identifier for the association. | 331 | * The association id field, holds the identifier for the association. |
339 | * All notifications for a given association have the same association | 332 | * All notifications for a given association have the same association |
340 | * identifier. For TCP style socket, this field is ignored. | 333 | * identifier. For TCP style socket, this field is ignored. |
341 | */ | 334 | */ |
342 | sctp_ulpevent_set_owner(event, asoc); | 335 | sctp_ulpevent_set_owner(event, asoc); |
343 | spc->spc_assoc_id = sctp_assoc2id(asoc); | 336 | spc->spc_assoc_id = sctp_assoc2id(asoc); |
344 | 337 | ||
345 | /* Sockets API Extensions for SCTP | 338 | /* Sockets API Extensions for SCTP |
346 | * Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE | 339 | * Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE |
347 | * | 340 | * |
348 | * spc_aaddr: sizeof (struct sockaddr_storage) | 341 | * spc_aaddr: sizeof (struct sockaddr_storage) |
349 | * | 342 | * |
350 | * The affected address field, holds the remote peer's address that is | 343 | * The affected address field, holds the remote peer's address that is |
351 | * encountering the change of state. | 344 | * encountering the change of state. |
352 | */ | 345 | */ |
353 | memcpy(&spc->spc_aaddr, aaddr, sizeof(struct sockaddr_storage)); | 346 | memcpy(&spc->spc_aaddr, aaddr, sizeof(struct sockaddr_storage)); |
354 | 347 | ||
355 | /* Map ipv4 address into v4-mapped-on-v6 address. */ | 348 | /* Map ipv4 address into v4-mapped-on-v6 address. */ |
356 | sctp_get_pf_specific(asoc->base.sk->sk_family)->addr_v4map( | 349 | sctp_get_pf_specific(asoc->base.sk->sk_family)->addr_v4map( |
357 | sctp_sk(asoc->base.sk), | 350 | sctp_sk(asoc->base.sk), |
358 | (union sctp_addr *)&spc->spc_aaddr); | 351 | (union sctp_addr *)&spc->spc_aaddr); |
359 | 352 | ||
360 | return event; | 353 | return event; |
361 | 354 | ||
362 | fail: | 355 | fail: |
363 | return NULL; | 356 | return NULL; |
364 | } | 357 | } |
365 | 358 | ||
366 | /* Create and initialize an SCTP_REMOTE_ERROR notification. | 359 | /* Create and initialize an SCTP_REMOTE_ERROR notification. |
367 | * | 360 | * |
368 | * Note: This assumes that the chunk->skb->data already points to the | 361 | * Note: This assumes that the chunk->skb->data already points to the |
369 | * operation error payload. | 362 | * operation error payload. |
370 | * | 363 | * |
371 | * Socket Extensions for SCTP - draft-01 | 364 | * Socket Extensions for SCTP - draft-01 |
372 | * 5.3.1.3 SCTP_REMOTE_ERROR | 365 | * 5.3.1.3 SCTP_REMOTE_ERROR |
373 | * | 366 | * |
374 | * A remote peer may send an Operational Error message to its peer. | 367 | * A remote peer may send an Operational Error message to its peer. |
375 | * This message indicates a variety of error conditions on an | 368 | * This message indicates a variety of error conditions on an |
376 | * association. The entire error TLV as it appears on the wire is | 369 | * association. The entire error TLV as it appears on the wire is |
377 | * included in a SCTP_REMOTE_ERROR event. Please refer to the SCTP | 370 | * included in a SCTP_REMOTE_ERROR event. Please refer to the SCTP |
378 | * specification [SCTP] and any extensions for a list of possible | 371 | * specification [SCTP] and any extensions for a list of possible |
379 | * error formats. | 372 | * error formats. |
380 | */ | 373 | */ |
381 | struct sctp_ulpevent *sctp_ulpevent_make_remote_error( | 374 | struct sctp_ulpevent *sctp_ulpevent_make_remote_error( |
382 | const struct sctp_association *asoc, struct sctp_chunk *chunk, | 375 | const struct sctp_association *asoc, struct sctp_chunk *chunk, |
383 | __u16 flags, gfp_t gfp) | 376 | __u16 flags, gfp_t gfp) |
384 | { | 377 | { |
385 | struct sctp_ulpevent *event; | 378 | struct sctp_ulpevent *event; |
386 | struct sctp_remote_error *sre; | 379 | struct sctp_remote_error *sre; |
387 | struct sk_buff *skb; | 380 | struct sk_buff *skb; |
388 | sctp_errhdr_t *ch; | 381 | sctp_errhdr_t *ch; |
389 | __be16 cause; | 382 | __be16 cause; |
390 | int elen; | 383 | int elen; |
391 | 384 | ||
392 | ch = (sctp_errhdr_t *)(chunk->skb->data); | 385 | ch = (sctp_errhdr_t *)(chunk->skb->data); |
393 | cause = ch->cause; | 386 | cause = ch->cause; |
394 | elen = WORD_ROUND(ntohs(ch->length)) - sizeof(sctp_errhdr_t); | 387 | elen = WORD_ROUND(ntohs(ch->length)) - sizeof(sctp_errhdr_t); |
395 | 388 | ||
396 | /* Pull off the ERROR header. */ | 389 | /* Pull off the ERROR header. */ |
397 | skb_pull(chunk->skb, sizeof(sctp_errhdr_t)); | 390 | skb_pull(chunk->skb, sizeof(sctp_errhdr_t)); |
398 | 391 | ||
399 | /* Copy the skb to a new skb with room for us to prepend | 392 | /* Copy the skb to a new skb with room for us to prepend |
400 | * notification with. | 393 | * notification with. |
401 | */ | 394 | */ |
402 | skb = skb_copy_expand(chunk->skb, sizeof(struct sctp_remote_error), | 395 | skb = skb_copy_expand(chunk->skb, sizeof(struct sctp_remote_error), |
403 | 0, gfp); | 396 | 0, gfp); |
404 | 397 | ||
405 | /* Pull off the rest of the cause TLV from the chunk. */ | 398 | /* Pull off the rest of the cause TLV from the chunk. */ |
406 | skb_pull(chunk->skb, elen); | 399 | skb_pull(chunk->skb, elen); |
407 | if (!skb) | 400 | if (!skb) |
408 | goto fail; | 401 | goto fail; |
409 | 402 | ||
410 | /* Embed the event fields inside the cloned skb. */ | 403 | /* Embed the event fields inside the cloned skb. */ |
411 | event = sctp_skb2event(skb); | 404 | event = sctp_skb2event(skb); |
412 | sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize); | 405 | sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize); |
413 | 406 | ||
414 | sre = (struct sctp_remote_error *) | 407 | sre = (struct sctp_remote_error *) |
415 | skb_push(skb, sizeof(struct sctp_remote_error)); | 408 | skb_push(skb, sizeof(struct sctp_remote_error)); |
416 | 409 | ||
417 | /* Trim the buffer to the right length. */ | 410 | /* Trim the buffer to the right length. */ |
418 | skb_trim(skb, sizeof(struct sctp_remote_error) + elen); | 411 | skb_trim(skb, sizeof(struct sctp_remote_error) + elen); |
419 | 412 | ||
420 | /* Socket Extensions for SCTP | 413 | /* Socket Extensions for SCTP |
421 | * 5.3.1.3 SCTP_REMOTE_ERROR | 414 | * 5.3.1.3 SCTP_REMOTE_ERROR |
422 | * | 415 | * |
423 | * sre_type: | 416 | * sre_type: |
424 | * It should be SCTP_REMOTE_ERROR. | 417 | * It should be SCTP_REMOTE_ERROR. |
425 | */ | 418 | */ |
426 | sre->sre_type = SCTP_REMOTE_ERROR; | 419 | sre->sre_type = SCTP_REMOTE_ERROR; |
427 | 420 | ||
428 | /* | 421 | /* |
429 | * Socket Extensions for SCTP | 422 | * Socket Extensions for SCTP |
430 | * 5.3.1.3 SCTP_REMOTE_ERROR | 423 | * 5.3.1.3 SCTP_REMOTE_ERROR |
431 | * | 424 | * |
432 | * sre_flags: 16 bits (unsigned integer) | 425 | * sre_flags: 16 bits (unsigned integer) |
433 | * Currently unused. | 426 | * Currently unused. |
434 | */ | 427 | */ |
435 | sre->sre_flags = 0; | 428 | sre->sre_flags = 0; |
436 | 429 | ||
437 | /* Socket Extensions for SCTP | 430 | /* Socket Extensions for SCTP |
438 | * 5.3.1.3 SCTP_REMOTE_ERROR | 431 | * 5.3.1.3 SCTP_REMOTE_ERROR |
439 | * | 432 | * |
440 | * sre_length: sizeof (__u32) | 433 | * sre_length: sizeof (__u32) |
441 | * | 434 | * |
442 | * This field is the total length of the notification data, | 435 | * This field is the total length of the notification data, |
443 | * including the notification header. | 436 | * including the notification header. |
444 | */ | 437 | */ |
445 | sre->sre_length = skb->len; | 438 | sre->sre_length = skb->len; |
446 | 439 | ||
447 | /* Socket Extensions for SCTP | 440 | /* Socket Extensions for SCTP |
448 | * 5.3.1.3 SCTP_REMOTE_ERROR | 441 | * 5.3.1.3 SCTP_REMOTE_ERROR |
449 | * | 442 | * |
450 | * sre_error: 16 bits (unsigned integer) | 443 | * sre_error: 16 bits (unsigned integer) |
451 | * This value represents one of the Operational Error causes defined in | 444 | * This value represents one of the Operational Error causes defined in |
452 | * the SCTP specification, in network byte order. | 445 | * the SCTP specification, in network byte order. |
453 | */ | 446 | */ |
454 | sre->sre_error = cause; | 447 | sre->sre_error = cause; |
455 | 448 | ||
456 | /* Socket Extensions for SCTP | 449 | /* Socket Extensions for SCTP |
457 | * 5.3.1.3 SCTP_REMOTE_ERROR | 450 | * 5.3.1.3 SCTP_REMOTE_ERROR |
458 | * | 451 | * |
459 | * sre_assoc_id: sizeof (sctp_assoc_t) | 452 | * sre_assoc_id: sizeof (sctp_assoc_t) |
460 | * | 453 | * |
461 | * The association id field, holds the identifier for the association. | 454 | * The association id field, holds the identifier for the association. |
462 | * All notifications for a given association have the same association | 455 | * All notifications for a given association have the same association |
463 | * identifier. For TCP style socket, this field is ignored. | 456 | * identifier. For TCP style socket, this field is ignored. |
464 | */ | 457 | */ |
465 | sctp_ulpevent_set_owner(event, asoc); | 458 | sctp_ulpevent_set_owner(event, asoc); |
466 | sre->sre_assoc_id = sctp_assoc2id(asoc); | 459 | sre->sre_assoc_id = sctp_assoc2id(asoc); |
467 | 460 | ||
468 | return event; | 461 | return event; |
469 | 462 | ||
470 | fail: | 463 | fail: |
471 | return NULL; | 464 | return NULL; |
472 | } | 465 | } |
473 | 466 | ||
474 | /* Create and initialize a SCTP_SEND_FAILED notification. | 467 | /* Create and initialize a SCTP_SEND_FAILED notification. |
475 | * | 468 | * |
476 | * Socket Extensions for SCTP - draft-01 | 469 | * Socket Extensions for SCTP - draft-01 |
477 | * 5.3.1.4 SCTP_SEND_FAILED | 470 | * 5.3.1.4 SCTP_SEND_FAILED |
478 | */ | 471 | */ |
479 | struct sctp_ulpevent *sctp_ulpevent_make_send_failed( | 472 | struct sctp_ulpevent *sctp_ulpevent_make_send_failed( |
480 | const struct sctp_association *asoc, struct sctp_chunk *chunk, | 473 | const struct sctp_association *asoc, struct sctp_chunk *chunk, |
481 | __u16 flags, __u32 error, gfp_t gfp) | 474 | __u16 flags, __u32 error, gfp_t gfp) |
482 | { | 475 | { |
483 | struct sctp_ulpevent *event; | 476 | struct sctp_ulpevent *event; |
484 | struct sctp_send_failed *ssf; | 477 | struct sctp_send_failed *ssf; |
485 | struct sk_buff *skb; | 478 | struct sk_buff *skb; |
486 | 479 | ||
487 | /* Pull off any padding. */ | 480 | /* Pull off any padding. */ |
488 | int len = ntohs(chunk->chunk_hdr->length); | 481 | int len = ntohs(chunk->chunk_hdr->length); |
489 | 482 | ||
490 | /* Make skb with more room so we can prepend notification. */ | 483 | /* Make skb with more room so we can prepend notification. */ |
491 | skb = skb_copy_expand(chunk->skb, | 484 | skb = skb_copy_expand(chunk->skb, |
492 | sizeof(struct sctp_send_failed), /* headroom */ | 485 | sizeof(struct sctp_send_failed), /* headroom */ |
493 | 0, /* tailroom */ | 486 | 0, /* tailroom */ |
494 | gfp); | 487 | gfp); |
495 | if (!skb) | 488 | if (!skb) |
496 | goto fail; | 489 | goto fail; |
497 | 490 | ||
498 | /* Pull off the common chunk header and DATA header. */ | 491 | /* Pull off the common chunk header and DATA header. */ |
499 | skb_pull(skb, sizeof(struct sctp_data_chunk)); | 492 | skb_pull(skb, sizeof(struct sctp_data_chunk)); |
500 | len -= sizeof(struct sctp_data_chunk); | 493 | len -= sizeof(struct sctp_data_chunk); |
501 | 494 | ||
502 | /* Embed the event fields inside the cloned skb. */ | 495 | /* Embed the event fields inside the cloned skb. */ |
503 | event = sctp_skb2event(skb); | 496 | event = sctp_skb2event(skb); |
504 | sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize); | 497 | sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize); |
505 | 498 | ||
506 | ssf = (struct sctp_send_failed *) | 499 | ssf = (struct sctp_send_failed *) |
507 | skb_push(skb, sizeof(struct sctp_send_failed)); | 500 | skb_push(skb, sizeof(struct sctp_send_failed)); |
508 | 501 | ||
509 | /* Socket Extensions for SCTP | 502 | /* Socket Extensions for SCTP |
510 | * 5.3.1.4 SCTP_SEND_FAILED | 503 | * 5.3.1.4 SCTP_SEND_FAILED |
511 | * | 504 | * |
512 | * ssf_type: | 505 | * ssf_type: |
513 | * It should be SCTP_SEND_FAILED. | 506 | * It should be SCTP_SEND_FAILED. |
514 | */ | 507 | */ |
515 | ssf->ssf_type = SCTP_SEND_FAILED; | 508 | ssf->ssf_type = SCTP_SEND_FAILED; |
516 | 509 | ||
517 | /* Socket Extensions for SCTP | 510 | /* Socket Extensions for SCTP |
518 | * 5.3.1.4 SCTP_SEND_FAILED | 511 | * 5.3.1.4 SCTP_SEND_FAILED |
519 | * | 512 | * |
520 | * ssf_flags: 16 bits (unsigned integer) | 513 | * ssf_flags: 16 bits (unsigned integer) |
521 | * The flag value will take one of the following values | 514 | * The flag value will take one of the following values |
522 | * | 515 | * |
523 | * SCTP_DATA_UNSENT - Indicates that the data was never put on | 516 | * SCTP_DATA_UNSENT - Indicates that the data was never put on |
524 | * the wire. | 517 | * the wire. |
525 | * | 518 | * |
526 | * SCTP_DATA_SENT - Indicates that the data was put on the wire. | 519 | * SCTP_DATA_SENT - Indicates that the data was put on the wire. |
527 | * Note that this does not necessarily mean that the | 520 | * Note that this does not necessarily mean that the |
528 | * data was (or was not) successfully delivered. | 521 | * data was (or was not) successfully delivered. |
529 | */ | 522 | */ |
530 | ssf->ssf_flags = flags; | 523 | ssf->ssf_flags = flags; |
531 | 524 | ||
532 | /* Socket Extensions for SCTP | 525 | /* Socket Extensions for SCTP |
533 | * 5.3.1.4 SCTP_SEND_FAILED | 526 | * 5.3.1.4 SCTP_SEND_FAILED |
534 | * | 527 | * |
535 | * ssf_length: sizeof (__u32) | 528 | * ssf_length: sizeof (__u32) |
536 | * This field is the total length of the notification data, including | 529 | * This field is the total length of the notification data, including |
537 | * the notification header. | 530 | * the notification header. |
538 | */ | 531 | */ |
539 | ssf->ssf_length = sizeof(struct sctp_send_failed) + len; | 532 | ssf->ssf_length = sizeof(struct sctp_send_failed) + len; |
540 | skb_trim(skb, ssf->ssf_length); | 533 | skb_trim(skb, ssf->ssf_length); |
541 | 534 | ||
542 | /* Socket Extensions for SCTP | 535 | /* Socket Extensions for SCTP |
543 | * 5.3.1.4 SCTP_SEND_FAILED | 536 | * 5.3.1.4 SCTP_SEND_FAILED |
544 | * | 537 | * |
545 | * ssf_error: 16 bits (unsigned integer) | 538 | * ssf_error: 16 bits (unsigned integer) |
546 | * This value represents the reason why the send failed, and if set, | 539 | * This value represents the reason why the send failed, and if set, |
547 | * will be a SCTP protocol error code as defined in [SCTP] section | 540 | * will be a SCTP protocol error code as defined in [SCTP] section |
548 | * 3.3.10. | 541 | * 3.3.10. |
549 | */ | 542 | */ |
550 | ssf->ssf_error = error; | 543 | ssf->ssf_error = error; |
551 | 544 | ||
552 | /* Socket Extensions for SCTP | 545 | /* Socket Extensions for SCTP |
553 | * 5.3.1.4 SCTP_SEND_FAILED | 546 | * 5.3.1.4 SCTP_SEND_FAILED |
554 | * | 547 | * |
555 | * ssf_info: sizeof (struct sctp_sndrcvinfo) | 548 | * ssf_info: sizeof (struct sctp_sndrcvinfo) |
556 | * The original send information associated with the undelivered | 549 | * The original send information associated with the undelivered |
557 | * message. | 550 | * message. |
558 | */ | 551 | */ |
559 | memcpy(&ssf->ssf_info, &chunk->sinfo, sizeof(struct sctp_sndrcvinfo)); | 552 | memcpy(&ssf->ssf_info, &chunk->sinfo, sizeof(struct sctp_sndrcvinfo)); |
560 | 553 | ||
561 | /* Per TSVWG discussion with Randy. Allow the application to | 554 | /* Per TSVWG discussion with Randy. Allow the application to |
562 | * ressemble a fragmented message. | 555 | * ressemble a fragmented message. |
563 | */ | 556 | */ |
564 | ssf->ssf_info.sinfo_flags = chunk->chunk_hdr->flags; | 557 | ssf->ssf_info.sinfo_flags = chunk->chunk_hdr->flags; |
565 | 558 | ||
566 | /* Socket Extensions for SCTP | 559 | /* Socket Extensions for SCTP |
567 | * 5.3.1.4 SCTP_SEND_FAILED | 560 | * 5.3.1.4 SCTP_SEND_FAILED |
568 | * | 561 | * |
569 | * ssf_assoc_id: sizeof (sctp_assoc_t) | 562 | * ssf_assoc_id: sizeof (sctp_assoc_t) |
570 | * The association id field, sf_assoc_id, holds the identifier for the | 563 | * The association id field, sf_assoc_id, holds the identifier for the |
571 | * association. All notifications for a given association have the | 564 | * association. All notifications for a given association have the |
572 | * same association identifier. For TCP style socket, this field is | 565 | * same association identifier. For TCP style socket, this field is |
573 | * ignored. | 566 | * ignored. |
574 | */ | 567 | */ |
575 | sctp_ulpevent_set_owner(event, asoc); | 568 | sctp_ulpevent_set_owner(event, asoc); |
576 | ssf->ssf_assoc_id = sctp_assoc2id(asoc); | 569 | ssf->ssf_assoc_id = sctp_assoc2id(asoc); |
577 | return event; | 570 | return event; |
578 | 571 | ||
579 | fail: | 572 | fail: |
580 | return NULL; | 573 | return NULL; |
581 | } | 574 | } |
582 | 575 | ||
583 | /* Create and initialize a SCTP_SHUTDOWN_EVENT notification. | 576 | /* Create and initialize a SCTP_SHUTDOWN_EVENT notification. |
584 | * | 577 | * |
585 | * Socket Extensions for SCTP - draft-01 | 578 | * Socket Extensions for SCTP - draft-01 |
586 | * 5.3.1.5 SCTP_SHUTDOWN_EVENT | 579 | * 5.3.1.5 SCTP_SHUTDOWN_EVENT |
587 | */ | 580 | */ |
588 | struct sctp_ulpevent *sctp_ulpevent_make_shutdown_event( | 581 | struct sctp_ulpevent *sctp_ulpevent_make_shutdown_event( |
589 | const struct sctp_association *asoc, | 582 | const struct sctp_association *asoc, |
590 | __u16 flags, gfp_t gfp) | 583 | __u16 flags, gfp_t gfp) |
591 | { | 584 | { |
592 | struct sctp_ulpevent *event; | 585 | struct sctp_ulpevent *event; |
593 | struct sctp_shutdown_event *sse; | 586 | struct sctp_shutdown_event *sse; |
594 | struct sk_buff *skb; | 587 | struct sk_buff *skb; |
595 | 588 | ||
596 | event = sctp_ulpevent_new(sizeof(struct sctp_shutdown_event), | 589 | event = sctp_ulpevent_new(sizeof(struct sctp_shutdown_event), |
597 | MSG_NOTIFICATION, gfp); | 590 | MSG_NOTIFICATION, gfp); |
598 | if (!event) | 591 | if (!event) |
599 | goto fail; | 592 | goto fail; |
600 | 593 | ||
601 | skb = sctp_event2skb(event); | 594 | skb = sctp_event2skb(event); |
602 | sse = (struct sctp_shutdown_event *) | 595 | sse = (struct sctp_shutdown_event *) |
603 | skb_put(skb, sizeof(struct sctp_shutdown_event)); | 596 | skb_put(skb, sizeof(struct sctp_shutdown_event)); |
604 | 597 | ||
605 | /* Socket Extensions for SCTP | 598 | /* Socket Extensions for SCTP |
606 | * 5.3.1.5 SCTP_SHUTDOWN_EVENT | 599 | * 5.3.1.5 SCTP_SHUTDOWN_EVENT |
607 | * | 600 | * |
608 | * sse_type | 601 | * sse_type |
609 | * It should be SCTP_SHUTDOWN_EVENT | 602 | * It should be SCTP_SHUTDOWN_EVENT |
610 | */ | 603 | */ |
611 | sse->sse_type = SCTP_SHUTDOWN_EVENT; | 604 | sse->sse_type = SCTP_SHUTDOWN_EVENT; |
612 | 605 | ||
613 | /* Socket Extensions for SCTP | 606 | /* Socket Extensions for SCTP |
614 | * 5.3.1.5 SCTP_SHUTDOWN_EVENT | 607 | * 5.3.1.5 SCTP_SHUTDOWN_EVENT |
615 | * | 608 | * |
616 | * sse_flags: 16 bits (unsigned integer) | 609 | * sse_flags: 16 bits (unsigned integer) |
617 | * Currently unused. | 610 | * Currently unused. |
618 | */ | 611 | */ |
619 | sse->sse_flags = 0; | 612 | sse->sse_flags = 0; |
620 | 613 | ||
621 | /* Socket Extensions for SCTP | 614 | /* Socket Extensions for SCTP |
622 | * 5.3.1.5 SCTP_SHUTDOWN_EVENT | 615 | * 5.3.1.5 SCTP_SHUTDOWN_EVENT |
623 | * | 616 | * |
624 | * sse_length: sizeof (__u32) | 617 | * sse_length: sizeof (__u32) |
625 | * This field is the total length of the notification data, including | 618 | * This field is the total length of the notification data, including |
626 | * the notification header. | 619 | * the notification header. |
627 | */ | 620 | */ |
628 | sse->sse_length = sizeof(struct sctp_shutdown_event); | 621 | sse->sse_length = sizeof(struct sctp_shutdown_event); |
629 | 622 | ||
630 | /* Socket Extensions for SCTP | 623 | /* Socket Extensions for SCTP |
631 | * 5.3.1.5 SCTP_SHUTDOWN_EVENT | 624 | * 5.3.1.5 SCTP_SHUTDOWN_EVENT |
632 | * | 625 | * |
633 | * sse_assoc_id: sizeof (sctp_assoc_t) | 626 | * sse_assoc_id: sizeof (sctp_assoc_t) |
634 | * The association id field, holds the identifier for the association. | 627 | * The association id field, holds the identifier for the association. |
635 | * All notifications for a given association have the same association | 628 | * All notifications for a given association have the same association |
636 | * identifier. For TCP style socket, this field is ignored. | 629 | * identifier. For TCP style socket, this field is ignored. |
637 | */ | 630 | */ |
638 | sctp_ulpevent_set_owner(event, asoc); | 631 | sctp_ulpevent_set_owner(event, asoc); |
639 | sse->sse_assoc_id = sctp_assoc2id(asoc); | 632 | sse->sse_assoc_id = sctp_assoc2id(asoc); |
640 | 633 | ||
641 | return event; | 634 | return event; |
642 | 635 | ||
643 | fail: | 636 | fail: |
644 | return NULL; | 637 | return NULL; |
645 | } | 638 | } |
646 | 639 | ||
647 | /* Create and initialize a SCTP_ADAPTATION_INDICATION notification. | 640 | /* Create and initialize a SCTP_ADAPTATION_INDICATION notification. |
648 | * | 641 | * |
649 | * Socket Extensions for SCTP | 642 | * Socket Extensions for SCTP |
650 | * 5.3.1.6 SCTP_ADAPTATION_INDICATION | 643 | * 5.3.1.6 SCTP_ADAPTATION_INDICATION |
651 | */ | 644 | */ |
652 | struct sctp_ulpevent *sctp_ulpevent_make_adaptation_indication( | 645 | struct sctp_ulpevent *sctp_ulpevent_make_adaptation_indication( |
653 | const struct sctp_association *asoc, gfp_t gfp) | 646 | const struct sctp_association *asoc, gfp_t gfp) |
654 | { | 647 | { |
655 | struct sctp_ulpevent *event; | 648 | struct sctp_ulpevent *event; |
656 | struct sctp_adaptation_event *sai; | 649 | struct sctp_adaptation_event *sai; |
657 | struct sk_buff *skb; | 650 | struct sk_buff *skb; |
658 | 651 | ||
659 | event = sctp_ulpevent_new(sizeof(struct sctp_adaptation_event), | 652 | event = sctp_ulpevent_new(sizeof(struct sctp_adaptation_event), |
660 | MSG_NOTIFICATION, gfp); | 653 | MSG_NOTIFICATION, gfp); |
661 | if (!event) | 654 | if (!event) |
662 | goto fail; | 655 | goto fail; |
663 | 656 | ||
664 | skb = sctp_event2skb(event); | 657 | skb = sctp_event2skb(event); |
665 | sai = (struct sctp_adaptation_event *) | 658 | sai = (struct sctp_adaptation_event *) |
666 | skb_put(skb, sizeof(struct sctp_adaptation_event)); | 659 | skb_put(skb, sizeof(struct sctp_adaptation_event)); |
667 | 660 | ||
668 | sai->sai_type = SCTP_ADAPTATION_INDICATION; | 661 | sai->sai_type = SCTP_ADAPTATION_INDICATION; |
669 | sai->sai_flags = 0; | 662 | sai->sai_flags = 0; |
670 | sai->sai_length = sizeof(struct sctp_adaptation_event); | 663 | sai->sai_length = sizeof(struct sctp_adaptation_event); |
671 | sai->sai_adaptation_ind = asoc->peer.adaptation_ind; | 664 | sai->sai_adaptation_ind = asoc->peer.adaptation_ind; |
672 | sctp_ulpevent_set_owner(event, asoc); | 665 | sctp_ulpevent_set_owner(event, asoc); |
673 | sai->sai_assoc_id = sctp_assoc2id(asoc); | 666 | sai->sai_assoc_id = sctp_assoc2id(asoc); |
674 | 667 | ||
675 | return event; | 668 | return event; |
676 | 669 | ||
677 | fail: | 670 | fail: |
678 | return NULL; | 671 | return NULL; |
679 | } | 672 | } |
680 | 673 | ||
681 | /* A message has been received. Package this message as a notification | 674 | /* A message has been received. Package this message as a notification |
682 | * to pass it to the upper layers. Go ahead and calculate the sndrcvinfo | 675 | * to pass it to the upper layers. Go ahead and calculate the sndrcvinfo |
683 | * even if filtered out later. | 676 | * even if filtered out later. |
684 | * | 677 | * |
685 | * Socket Extensions for SCTP | 678 | * Socket Extensions for SCTP |
686 | * 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV) | 679 | * 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV) |
687 | */ | 680 | */ |
688 | struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc, | 681 | struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc, |
689 | struct sctp_chunk *chunk, | 682 | struct sctp_chunk *chunk, |
690 | gfp_t gfp) | 683 | gfp_t gfp) |
691 | { | 684 | { |
692 | struct sctp_ulpevent *event = NULL; | 685 | struct sctp_ulpevent *event = NULL; |
693 | struct sk_buff *skb; | 686 | struct sk_buff *skb; |
694 | size_t padding, len; | 687 | size_t padding, len; |
695 | 688 | ||
696 | /* Clone the original skb, sharing the data. */ | 689 | /* Clone the original skb, sharing the data. */ |
697 | skb = skb_clone(chunk->skb, gfp); | 690 | skb = skb_clone(chunk->skb, gfp); |
698 | if (!skb) | 691 | if (!skb) |
699 | goto fail; | 692 | goto fail; |
700 | 693 | ||
701 | /* First calculate the padding, so we don't inadvertently | 694 | /* First calculate the padding, so we don't inadvertently |
702 | * pass up the wrong length to the user. | 695 | * pass up the wrong length to the user. |
703 | * | 696 | * |
704 | * RFC 2960 - Section 3.2 Chunk Field Descriptions | 697 | * RFC 2960 - Section 3.2 Chunk Field Descriptions |
705 | * | 698 | * |
706 | * The total length of a chunk(including Type, Length and Value fields) | 699 | * The total length of a chunk(including Type, Length and Value fields) |
707 | * MUST be a multiple of 4 bytes. If the length of the chunk is not a | 700 | * MUST be a multiple of 4 bytes. If the length of the chunk is not a |
708 | * multiple of 4 bytes, the sender MUST pad the chunk with all zero | 701 | * multiple of 4 bytes, the sender MUST pad the chunk with all zero |
709 | * bytes and this padding is not included in the chunk length field. | 702 | * bytes and this padding is not included in the chunk length field. |
710 | * The sender should never pad with more than 3 bytes. The receiver | 703 | * The sender should never pad with more than 3 bytes. The receiver |
711 | * MUST ignore the padding bytes. | 704 | * MUST ignore the padding bytes. |
712 | */ | 705 | */ |
713 | len = ntohs(chunk->chunk_hdr->length); | 706 | len = ntohs(chunk->chunk_hdr->length); |
714 | padding = WORD_ROUND(len) - len; | 707 | padding = WORD_ROUND(len) - len; |
715 | 708 | ||
716 | /* Fixup cloned skb with just this chunks data. */ | 709 | /* Fixup cloned skb with just this chunks data. */ |
717 | skb_trim(skb, chunk->chunk_end - padding - skb->data); | 710 | skb_trim(skb, chunk->chunk_end - padding - skb->data); |
718 | 711 | ||
719 | /* Embed the event fields inside the cloned skb. */ | 712 | /* Embed the event fields inside the cloned skb. */ |
720 | event = sctp_skb2event(skb); | 713 | event = sctp_skb2event(skb); |
721 | 714 | ||
722 | /* Initialize event with flags 0 and correct length | 715 | /* Initialize event with flags 0 and correct length |
723 | * Since this is a clone of the original skb, only account for | 716 | * Since this is a clone of the original skb, only account for |
724 | * the data of this chunk as other chunks will be accounted separately. | 717 | * the data of this chunk as other chunks will be accounted separately. |
725 | */ | 718 | */ |
726 | sctp_ulpevent_init(event, 0, skb->len + sizeof(struct sk_buff)); | 719 | sctp_ulpevent_init(event, 0, skb->len + sizeof(struct sk_buff)); |
727 | 720 | ||
728 | sctp_ulpevent_receive_data(event, asoc); | 721 | sctp_ulpevent_receive_data(event, asoc); |
729 | 722 | ||
730 | event->stream = ntohs(chunk->subh.data_hdr->stream); | 723 | event->stream = ntohs(chunk->subh.data_hdr->stream); |
731 | event->ssn = ntohs(chunk->subh.data_hdr->ssn); | 724 | event->ssn = ntohs(chunk->subh.data_hdr->ssn); |
732 | event->ppid = chunk->subh.data_hdr->ppid; | 725 | event->ppid = chunk->subh.data_hdr->ppid; |
733 | if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) { | 726 | if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) { |
734 | event->flags |= SCTP_UNORDERED; | 727 | event->flags |= SCTP_UNORDERED; |
735 | event->cumtsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map); | 728 | event->cumtsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map); |
736 | } | 729 | } |
737 | event->tsn = ntohl(chunk->subh.data_hdr->tsn); | 730 | event->tsn = ntohl(chunk->subh.data_hdr->tsn); |
738 | event->msg_flags |= chunk->chunk_hdr->flags; | 731 | event->msg_flags |= chunk->chunk_hdr->flags; |
739 | event->iif = sctp_chunk_iif(chunk); | 732 | event->iif = sctp_chunk_iif(chunk); |
740 | 733 | ||
741 | fail: | 734 | fail: |
742 | return event; | 735 | return event; |
743 | } | 736 | } |
744 | 737 | ||
745 | /* Create a partial delivery related event. | 738 | /* Create a partial delivery related event. |
746 | * | 739 | * |
747 | * 5.3.1.7 SCTP_PARTIAL_DELIVERY_EVENT | 740 | * 5.3.1.7 SCTP_PARTIAL_DELIVERY_EVENT |
748 | * | 741 | * |
749 | * When a receiver is engaged in a partial delivery of a | 742 | * When a receiver is engaged in a partial delivery of a |
750 | * message this notification will be used to indicate | 743 | * message this notification will be used to indicate |
751 | * various events. | 744 | * various events. |
752 | */ | 745 | */ |
753 | struct sctp_ulpevent *sctp_ulpevent_make_pdapi( | 746 | struct sctp_ulpevent *sctp_ulpevent_make_pdapi( |
754 | const struct sctp_association *asoc, __u32 indication, | 747 | const struct sctp_association *asoc, __u32 indication, |
755 | gfp_t gfp) | 748 | gfp_t gfp) |
756 | { | 749 | { |
757 | struct sctp_ulpevent *event; | 750 | struct sctp_ulpevent *event; |
758 | struct sctp_pdapi_event *pd; | 751 | struct sctp_pdapi_event *pd; |
759 | struct sk_buff *skb; | 752 | struct sk_buff *skb; |
760 | 753 | ||
761 | event = sctp_ulpevent_new(sizeof(struct sctp_pdapi_event), | 754 | event = sctp_ulpevent_new(sizeof(struct sctp_pdapi_event), |
762 | MSG_NOTIFICATION, gfp); | 755 | MSG_NOTIFICATION, gfp); |
763 | if (!event) | 756 | if (!event) |
764 | goto fail; | 757 | goto fail; |
765 | 758 | ||
766 | skb = sctp_event2skb(event); | 759 | skb = sctp_event2skb(event); |
767 | pd = (struct sctp_pdapi_event *) | 760 | pd = (struct sctp_pdapi_event *) |
768 | skb_put(skb, sizeof(struct sctp_pdapi_event)); | 761 | skb_put(skb, sizeof(struct sctp_pdapi_event)); |
769 | 762 | ||
770 | /* pdapi_type | 763 | /* pdapi_type |
771 | * It should be SCTP_PARTIAL_DELIVERY_EVENT | 764 | * It should be SCTP_PARTIAL_DELIVERY_EVENT |
772 | * | 765 | * |
773 | * pdapi_flags: 16 bits (unsigned integer) | 766 | * pdapi_flags: 16 bits (unsigned integer) |
774 | * Currently unused. | 767 | * Currently unused. |
775 | */ | 768 | */ |
776 | pd->pdapi_type = SCTP_PARTIAL_DELIVERY_EVENT; | 769 | pd->pdapi_type = SCTP_PARTIAL_DELIVERY_EVENT; |
777 | pd->pdapi_flags = 0; | 770 | pd->pdapi_flags = 0; |
778 | 771 | ||
779 | /* pdapi_length: 32 bits (unsigned integer) | 772 | /* pdapi_length: 32 bits (unsigned integer) |
780 | * | 773 | * |
781 | * This field is the total length of the notification data, including | 774 | * This field is the total length of the notification data, including |
782 | * the notification header. It will generally be sizeof (struct | 775 | * the notification header. It will generally be sizeof (struct |
783 | * sctp_pdapi_event). | 776 | * sctp_pdapi_event). |
784 | */ | 777 | */ |
785 | pd->pdapi_length = sizeof(struct sctp_pdapi_event); | 778 | pd->pdapi_length = sizeof(struct sctp_pdapi_event); |
786 | 779 | ||
787 | /* pdapi_indication: 32 bits (unsigned integer) | 780 | /* pdapi_indication: 32 bits (unsigned integer) |
788 | * | 781 | * |
789 | * This field holds the indication being sent to the application. | 782 | * This field holds the indication being sent to the application. |
790 | */ | 783 | */ |
791 | pd->pdapi_indication = indication; | 784 | pd->pdapi_indication = indication; |
792 | 785 | ||
793 | /* pdapi_assoc_id: sizeof (sctp_assoc_t) | 786 | /* pdapi_assoc_id: sizeof (sctp_assoc_t) |
794 | * | 787 | * |
795 | * The association id field, holds the identifier for the association. | 788 | * The association id field, holds the identifier for the association. |
796 | */ | 789 | */ |
797 | sctp_ulpevent_set_owner(event, asoc); | 790 | sctp_ulpevent_set_owner(event, asoc); |
798 | pd->pdapi_assoc_id = sctp_assoc2id(asoc); | 791 | pd->pdapi_assoc_id = sctp_assoc2id(asoc); |
799 | 792 | ||
800 | return event; | 793 | return event; |
801 | fail: | 794 | fail: |
802 | return NULL; | 795 | return NULL; |
803 | } | 796 | } |
804 | 797 | ||
805 | /* Return the notification type, assuming this is a notification | 798 | /* Return the notification type, assuming this is a notification |
806 | * event. | 799 | * event. |
807 | */ | 800 | */ |
808 | __u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event) | 801 | __u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event) |
809 | { | 802 | { |
810 | union sctp_notification *notification; | 803 | union sctp_notification *notification; |
811 | struct sk_buff *skb; | 804 | struct sk_buff *skb; |
812 | 805 | ||
813 | skb = sctp_event2skb((struct sctp_ulpevent *)event); | 806 | skb = sctp_event2skb((struct sctp_ulpevent *)event); |
814 | notification = (union sctp_notification *) skb->data; | 807 | notification = (union sctp_notification *) skb->data; |
815 | return notification->sn_header.sn_type; | 808 | return notification->sn_header.sn_type; |
816 | } | 809 | } |
817 | 810 | ||
818 | /* Copy out the sndrcvinfo into a msghdr. */ | 811 | /* Copy out the sndrcvinfo into a msghdr. */ |
819 | void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event, | 812 | void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event, |
820 | struct msghdr *msghdr) | 813 | struct msghdr *msghdr) |
821 | { | 814 | { |
822 | struct sctp_sndrcvinfo sinfo; | 815 | struct sctp_sndrcvinfo sinfo; |
823 | 816 | ||
824 | if (sctp_ulpevent_is_notification(event)) | 817 | if (sctp_ulpevent_is_notification(event)) |
825 | return; | 818 | return; |
826 | 819 | ||
827 | /* Sockets API Extensions for SCTP | 820 | /* Sockets API Extensions for SCTP |
828 | * Section 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV) | 821 | * Section 5.2.2 SCTP Header Information Structure (SCTP_SNDRCV) |
829 | * | 822 | * |
830 | * sinfo_stream: 16 bits (unsigned integer) | 823 | * sinfo_stream: 16 bits (unsigned integer) |
831 | * | 824 | * |
832 | * For recvmsg() the SCTP stack places the message's stream number in | 825 | * For recvmsg() the SCTP stack places the message's stream number in |
833 | * this value. | 826 | * this value. |
834 | */ | 827 | */ |
835 | sinfo.sinfo_stream = event->stream; | 828 | sinfo.sinfo_stream = event->stream; |
836 | /* sinfo_ssn: 16 bits (unsigned integer) | 829 | /* sinfo_ssn: 16 bits (unsigned integer) |
837 | * | 830 | * |
838 | * For recvmsg() this value contains the stream sequence number that | 831 | * For recvmsg() this value contains the stream sequence number that |
839 | * the remote endpoint placed in the DATA chunk. For fragmented | 832 | * the remote endpoint placed in the DATA chunk. For fragmented |
840 | * messages this is the same number for all deliveries of the message | 833 | * messages this is the same number for all deliveries of the message |
841 | * (if more than one recvmsg() is needed to read the message). | 834 | * (if more than one recvmsg() is needed to read the message). |
842 | */ | 835 | */ |
843 | sinfo.sinfo_ssn = event->ssn; | 836 | sinfo.sinfo_ssn = event->ssn; |
844 | /* sinfo_ppid: 32 bits (unsigned integer) | 837 | /* sinfo_ppid: 32 bits (unsigned integer) |
845 | * | 838 | * |
846 | * In recvmsg() this value is | 839 | * In recvmsg() this value is |
847 | * the same information that was passed by the upper layer in the peer | 840 | * the same information that was passed by the upper layer in the peer |
848 | * application. Please note that byte order issues are NOT accounted | 841 | * application. Please note that byte order issues are NOT accounted |
849 | * for and this information is passed opaquely by the SCTP stack from | 842 | * for and this information is passed opaquely by the SCTP stack from |
850 | * one end to the other. | 843 | * one end to the other. |
851 | */ | 844 | */ |
852 | sinfo.sinfo_ppid = event->ppid; | 845 | sinfo.sinfo_ppid = event->ppid; |
853 | /* sinfo_flags: 16 bits (unsigned integer) | 846 | /* sinfo_flags: 16 bits (unsigned integer) |
854 | * | 847 | * |
855 | * This field may contain any of the following flags and is composed of | 848 | * This field may contain any of the following flags and is composed of |
856 | * a bitwise OR of these values. | 849 | * a bitwise OR of these values. |
857 | * | 850 | * |
858 | * recvmsg() flags: | 851 | * recvmsg() flags: |
859 | * | 852 | * |
860 | * SCTP_UNORDERED - This flag is present when the message was sent | 853 | * SCTP_UNORDERED - This flag is present when the message was sent |
861 | * non-ordered. | 854 | * non-ordered. |
862 | */ | 855 | */ |
863 | sinfo.sinfo_flags = event->flags; | 856 | sinfo.sinfo_flags = event->flags; |
864 | /* sinfo_tsn: 32 bit (unsigned integer) | 857 | /* sinfo_tsn: 32 bit (unsigned integer) |
865 | * | 858 | * |
866 | * For the receiving side, this field holds a TSN that was | 859 | * For the receiving side, this field holds a TSN that was |
867 | * assigned to one of the SCTP Data Chunks. | 860 | * assigned to one of the SCTP Data Chunks. |
868 | */ | 861 | */ |
869 | sinfo.sinfo_tsn = event->tsn; | 862 | sinfo.sinfo_tsn = event->tsn; |
870 | /* sinfo_cumtsn: 32 bit (unsigned integer) | 863 | /* sinfo_cumtsn: 32 bit (unsigned integer) |
871 | * | 864 | * |
872 | * This field will hold the current cumulative TSN as | 865 | * This field will hold the current cumulative TSN as |
873 | * known by the underlying SCTP layer. Note this field is | 866 | * known by the underlying SCTP layer. Note this field is |
874 | * ignored when sending and only valid for a receive | 867 | * ignored when sending and only valid for a receive |
875 | * operation when sinfo_flags are set to SCTP_UNORDERED. | 868 | * operation when sinfo_flags are set to SCTP_UNORDERED. |
876 | */ | 869 | */ |
877 | sinfo.sinfo_cumtsn = event->cumtsn; | 870 | sinfo.sinfo_cumtsn = event->cumtsn; |
878 | /* sinfo_assoc_id: sizeof (sctp_assoc_t) | 871 | /* sinfo_assoc_id: sizeof (sctp_assoc_t) |
879 | * | 872 | * |
880 | * The association handle field, sinfo_assoc_id, holds the identifier | 873 | * The association handle field, sinfo_assoc_id, holds the identifier |
881 | * for the association announced in the COMMUNICATION_UP notification. | 874 | * for the association announced in the COMMUNICATION_UP notification. |
882 | * All notifications for a given association have the same identifier. | 875 | * All notifications for a given association have the same identifier. |
883 | * Ignored for one-to-one style sockets. | 876 | * Ignored for one-to-one style sockets. |
884 | */ | 877 | */ |
885 | sinfo.sinfo_assoc_id = sctp_assoc2id(event->asoc); | 878 | sinfo.sinfo_assoc_id = sctp_assoc2id(event->asoc); |
886 | 879 | ||
887 | /* context value that is set via SCTP_CONTEXT socket option. */ | 880 | /* context value that is set via SCTP_CONTEXT socket option. */ |
888 | sinfo.sinfo_context = event->asoc->default_rcv_context; | 881 | sinfo.sinfo_context = event->asoc->default_rcv_context; |
889 | 882 | ||
890 | /* These fields are not used while receiving. */ | 883 | /* These fields are not used while receiving. */ |
891 | sinfo.sinfo_timetolive = 0; | 884 | sinfo.sinfo_timetolive = 0; |
892 | 885 | ||
893 | put_cmsg(msghdr, IPPROTO_SCTP, SCTP_SNDRCV, | 886 | put_cmsg(msghdr, IPPROTO_SCTP, SCTP_SNDRCV, |
894 | sizeof(struct sctp_sndrcvinfo), (void *)&sinfo); | 887 | sizeof(struct sctp_sndrcvinfo), (void *)&sinfo); |
895 | } | 888 | } |
896 | 889 | ||
897 | /* Do accounting for bytes received and hold a reference to the association | 890 | /* Do accounting for bytes received and hold a reference to the association |
898 | * for each skb. | 891 | * for each skb. |
899 | */ | 892 | */ |
900 | static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event, | 893 | static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event, |
901 | struct sctp_association *asoc) | 894 | struct sctp_association *asoc) |
902 | { | 895 | { |
903 | struct sk_buff *skb, *frag; | 896 | struct sk_buff *skb, *frag; |
904 | 897 | ||
905 | skb = sctp_event2skb(event); | 898 | skb = sctp_event2skb(event); |
906 | /* Set the owner and charge rwnd for bytes received. */ | 899 | /* Set the owner and charge rwnd for bytes received. */ |
907 | sctp_ulpevent_set_owner(event, asoc); | 900 | sctp_ulpevent_set_owner(event, asoc); |
908 | sctp_assoc_rwnd_decrease(asoc, skb_headlen(skb)); | 901 | sctp_assoc_rwnd_decrease(asoc, skb_headlen(skb)); |
909 | 902 | ||
910 | if (!skb->data_len) | 903 | if (!skb->data_len) |
911 | return; | 904 | return; |
912 | 905 | ||
913 | /* Note: Not clearing the entire event struct as this is just a | 906 | /* Note: Not clearing the entire event struct as this is just a |
914 | * fragment of the real event. However, we still need to do rwnd | 907 | * fragment of the real event. However, we still need to do rwnd |
915 | * accounting. | 908 | * accounting. |
916 | * In general, the skb passed from IP can have only 1 level of | 909 | * In general, the skb passed from IP can have only 1 level of |
917 | * fragments. But we allow multiple levels of fragments. | 910 | * fragments. But we allow multiple levels of fragments. |
918 | */ | 911 | */ |
919 | for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) { | 912 | for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) { |
920 | sctp_ulpevent_receive_data(sctp_skb2event(frag), asoc); | 913 | sctp_ulpevent_receive_data(sctp_skb2event(frag), asoc); |
921 | } | 914 | } |
922 | } | 915 | } |
923 | 916 | ||
924 | /* Do accounting for bytes just read by user and release the references to | 917 | /* Do accounting for bytes just read by user and release the references to |
925 | * the association. | 918 | * the association. |
926 | */ | 919 | */ |
927 | static void sctp_ulpevent_release_data(struct sctp_ulpevent *event) | 920 | static void sctp_ulpevent_release_data(struct sctp_ulpevent *event) |
928 | { | 921 | { |
929 | struct sk_buff *skb, *frag; | 922 | struct sk_buff *skb, *frag; |
930 | unsigned int len; | 923 | unsigned int len; |
931 | 924 | ||
932 | /* Current stack structures assume that the rcv buffer is | 925 | /* Current stack structures assume that the rcv buffer is |
933 | * per socket. For UDP style sockets this is not true as | 926 | * per socket. For UDP style sockets this is not true as |
934 | * multiple associations may be on a single UDP-style socket. | 927 | * multiple associations may be on a single UDP-style socket. |
935 | * Use the local private area of the skb to track the owning | 928 | * Use the local private area of the skb to track the owning |
936 | * association. | 929 | * association. |
937 | */ | 930 | */ |
938 | 931 | ||
939 | skb = sctp_event2skb(event); | 932 | skb = sctp_event2skb(event); |
940 | len = skb->len; | 933 | len = skb->len; |
941 | 934 | ||
942 | if (!skb->data_len) | 935 | if (!skb->data_len) |
943 | goto done; | 936 | goto done; |
944 | 937 | ||
945 | /* Don't forget the fragments. */ | 938 | /* Don't forget the fragments. */ |
946 | for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) { | 939 | for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) { |
947 | /* NOTE: skb_shinfos are recursive. Although IP returns | 940 | /* NOTE: skb_shinfos are recursive. Although IP returns |
948 | * skb's with only 1 level of fragments, SCTP reassembly can | 941 | * skb's with only 1 level of fragments, SCTP reassembly can |
949 | * increase the levels. | 942 | * increase the levels. |
950 | */ | 943 | */ |
951 | sctp_ulpevent_release_frag_data(sctp_skb2event(frag)); | 944 | sctp_ulpevent_release_frag_data(sctp_skb2event(frag)); |
952 | } | 945 | } |
953 | 946 | ||
954 | done: | 947 | done: |
955 | sctp_assoc_rwnd_increase(event->asoc, len); | 948 | sctp_assoc_rwnd_increase(event->asoc, len); |
956 | sctp_ulpevent_release_owner(event); | 949 | sctp_ulpevent_release_owner(event); |
957 | } | 950 | } |
958 | 951 | ||
959 | static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event) | 952 | static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event) |
960 | { | 953 | { |
961 | struct sk_buff *skb, *frag; | 954 | struct sk_buff *skb, *frag; |
962 | 955 | ||
963 | skb = sctp_event2skb(event); | 956 | skb = sctp_event2skb(event); |
964 | 957 | ||
965 | if (!skb->data_len) | 958 | if (!skb->data_len) |
966 | goto done; | 959 | goto done; |
967 | 960 | ||
968 | /* Don't forget the fragments. */ | 961 | /* Don't forget the fragments. */ |
969 | for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) { | 962 | for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) { |
970 | /* NOTE: skb_shinfos are recursive. Although IP returns | 963 | /* NOTE: skb_shinfos are recursive. Although IP returns |
971 | * skb's with only 1 level of fragments, SCTP reassembly can | 964 | * skb's with only 1 level of fragments, SCTP reassembly can |
972 | * increase the levels. | 965 | * increase the levels. |
973 | */ | 966 | */ |
974 | sctp_ulpevent_release_frag_data(sctp_skb2event(frag)); | 967 | sctp_ulpevent_release_frag_data(sctp_skb2event(frag)); |
975 | } | 968 | } |
976 | 969 | ||
977 | done: | 970 | done: |
978 | sctp_ulpevent_release_owner(event); | 971 | sctp_ulpevent_release_owner(event); |
979 | } | 972 | } |
980 | 973 | ||
981 | /* Free a ulpevent that has an owner. It includes releasing the reference | 974 | /* Free a ulpevent that has an owner. It includes releasing the reference |
982 | * to the owner, updating the rwnd in case of a DATA event and freeing the | 975 | * to the owner, updating the rwnd in case of a DATA event and freeing the |
983 | * skb. | 976 | * skb. |
984 | */ | 977 | */ |
985 | void sctp_ulpevent_free(struct sctp_ulpevent *event) | 978 | void sctp_ulpevent_free(struct sctp_ulpevent *event) |
986 | { | 979 | { |
987 | if (sctp_ulpevent_is_notification(event)) | 980 | if (sctp_ulpevent_is_notification(event)) |
988 | sctp_ulpevent_release_owner(event); | 981 | sctp_ulpevent_release_owner(event); |
989 | else | 982 | else |
990 | sctp_ulpevent_release_data(event); | 983 | sctp_ulpevent_release_data(event); |
991 | 984 | ||
992 | kfree_skb(sctp_event2skb(event)); | 985 | kfree_skb(sctp_event2skb(event)); |
993 | } | 986 | } |
994 | 987 | ||
995 | /* Purge the skb lists holding ulpevents. */ | 988 | /* Purge the skb lists holding ulpevents. */ |
996 | void sctp_queue_purge_ulpevents(struct sk_buff_head *list) | 989 | void sctp_queue_purge_ulpevents(struct sk_buff_head *list) |
997 | { | 990 | { |
998 | struct sk_buff *skb; | 991 | struct sk_buff *skb; |
999 | while ((skb = skb_dequeue(list)) != NULL) | 992 | while ((skb = skb_dequeue(list)) != NULL) |
1000 | sctp_ulpevent_free(sctp_skb2event(skb)); | 993 | sctp_ulpevent_free(sctp_skb2event(skb)); |
1001 | } | 994 | } |