aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/input.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/input.c')
-rw-r--r--net/sctp/input.c43
1 files changed, 28 insertions, 15 deletions
diff --git a/net/sctp/input.c b/net/sctp/input.c
index c0c973e67add..2a570184e5a9 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -53,6 +53,7 @@
53#include <linux/socket.h> 53#include <linux/socket.h>
54#include <linux/ip.h> 54#include <linux/ip.h>
55#include <linux/time.h> /* For struct timeval */ 55#include <linux/time.h> /* For struct timeval */
56#include <linux/slab.h>
56#include <net/ip.h> 57#include <net/ip.h>
57#include <net/icmp.h> 58#include <net/icmp.h>
58#include <net/snmp.h> 59#include <net/snmp.h>
@@ -75,7 +76,7 @@ static struct sctp_association *__sctp_lookup_association(
75 const union sctp_addr *peer, 76 const union sctp_addr *peer,
76 struct sctp_transport **pt); 77 struct sctp_transport **pt);
77 78
78static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb); 79static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb);
79 80
80 81
81/* Calculate the SCTP checksum of an SCTP packet. */ 82/* Calculate the SCTP checksum of an SCTP packet. */
@@ -265,8 +266,13 @@ int sctp_rcv(struct sk_buff *skb)
265 } 266 }
266 267
267 if (sock_owned_by_user(sk)) { 268 if (sock_owned_by_user(sk)) {
269 if (sctp_add_backlog(sk, skb)) {
270 sctp_bh_unlock_sock(sk);
271 sctp_chunk_free(chunk);
272 skb = NULL; /* sctp_chunk_free already freed the skb */
273 goto discard_release;
274 }
268 SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_BACKLOG); 275 SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_BACKLOG);
269 sctp_add_backlog(sk, skb);
270 } else { 276 } else {
271 SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_SOFTIRQ); 277 SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_SOFTIRQ);
272 sctp_inq_push(&chunk->rcvr->inqueue, chunk); 278 sctp_inq_push(&chunk->rcvr->inqueue, chunk);
@@ -336,8 +342,10 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
336 sctp_bh_lock_sock(sk); 342 sctp_bh_lock_sock(sk);
337 343
338 if (sock_owned_by_user(sk)) { 344 if (sock_owned_by_user(sk)) {
339 sk_add_backlog(sk, skb); 345 if (sk_add_backlog(sk, skb))
340 backloged = 1; 346 sctp_chunk_free(chunk);
347 else
348 backloged = 1;
341 } else 349 } else
342 sctp_inq_push(inqueue, chunk); 350 sctp_inq_push(inqueue, chunk);
343 351
@@ -362,22 +370,27 @@ done:
362 return 0; 370 return 0;
363} 371}
364 372
365static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb) 373static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
366{ 374{
367 struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk; 375 struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
368 struct sctp_ep_common *rcvr = chunk->rcvr; 376 struct sctp_ep_common *rcvr = chunk->rcvr;
377 int ret;
369 378
370 /* Hold the assoc/ep while hanging on the backlog queue. 379 ret = sk_add_backlog(sk, skb);
371 * This way, we know structures we need will not disappear from us 380 if (!ret) {
372 */ 381 /* Hold the assoc/ep while hanging on the backlog queue.
373 if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type) 382 * This way, we know structures we need will not disappear
374 sctp_association_hold(sctp_assoc(rcvr)); 383 * from us
375 else if (SCTP_EP_TYPE_SOCKET == rcvr->type) 384 */
376 sctp_endpoint_hold(sctp_ep(rcvr)); 385 if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
377 else 386 sctp_association_hold(sctp_assoc(rcvr));
378 BUG(); 387 else if (SCTP_EP_TYPE_SOCKET == rcvr->type)
388 sctp_endpoint_hold(sctp_ep(rcvr));
389 else
390 BUG();
391 }
392 return ret;
379 393
380 sk_add_backlog(sk, skb);
381} 394}
382 395
383/* Handle icmp frag needed error. */ 396/* Handle icmp frag needed error. */