aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/ulpevent.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/ulpevent.c')
-rw-r--r--net/sctp/ulpevent.c49
1 files changed, 42 insertions, 7 deletions
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 2e11bc8d5d35..661ea2dd78ba 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -131,19 +131,54 @@ static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event)
131struct sctp_ulpevent *sctp_ulpevent_make_assoc_change( 131struct 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, 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 event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change), 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.
142 */
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
150 * head room to use as notification.
151 */
152 skb = skb_copy_expand(chunk->skb,
153 sizeof(struct sctp_assoc_change), 0, gfp);
154
155 if (!skb)
156 goto fail;
157
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. */
162 event = sctp_skb2event(skb);
163 sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize);
164
165 /* Include the notification structure */
166 sac = (struct sctp_assoc_change *)
167 skb_push(skb, sizeof(struct sctp_assoc_change));
168
169 /* Trim the buffer to the right length. */
170 skb_trim(skb, sizeof(struct sctp_assoc_change) +
171 ntohs(chunk->chunk_hdr->length));
172 } else {
173 event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),
141 MSG_NOTIFICATION, gfp); 174 MSG_NOTIFICATION, gfp);
142 if (!event) 175 if (!event)
143 goto fail; 176 goto fail;
144 skb = sctp_event2skb(event); 177
145 sac = (struct sctp_assoc_change *) 178 skb = sctp_event2skb(event);
146 skb_put(skb, sizeof(struct sctp_assoc_change)); 179 sac = (struct sctp_assoc_change *) skb_put(skb,
180 sizeof(struct sctp_assoc_change));
181 }
147 182
148 /* Socket Extensions for SCTP 183 /* Socket Extensions for SCTP
149 * 5.3.1.1 SCTP_ASSOC_CHANGE 184 * 5.3.1.1 SCTP_ASSOC_CHANGE