aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/socket.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-07-14 10:56:40 -0400
committerDavid S. Miller <davem@davemloft.net>2011-07-14 10:56:40 -0400
commit6a7ebdf2fd15417e87b4fd02ff411aeaca34da5f (patch)
tree86b15d8cd3e25c97b348b5a61bdb16c02726a480 /net/sctp/socket.c
parentf6b72b6217f8c24f2a54988e58af858b4e66024d (diff)
parent51414d41084496aaefd06d7f19eb8206e8bfac2d (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts: net/bluetooth/l2cap_core.c
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r--net/sctp/socket.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 1c6aec1f9ec4..836aa63ee121 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1454,6 +1454,7 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
1454 struct sctp_endpoint *ep; 1454 struct sctp_endpoint *ep;
1455 struct sctp_association *asoc; 1455 struct sctp_association *asoc;
1456 struct list_head *pos, *temp; 1456 struct list_head *pos, *temp;
1457 unsigned int data_was_unread;
1457 1458
1458 SCTP_DEBUG_PRINTK("sctp_close(sk: 0x%p, timeout:%ld)\n", sk, timeout); 1459 SCTP_DEBUG_PRINTK("sctp_close(sk: 0x%p, timeout:%ld)\n", sk, timeout);
1459 1460
@@ -1463,6 +1464,10 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
1463 1464
1464 ep = sctp_sk(sk)->ep; 1465 ep = sctp_sk(sk)->ep;
1465 1466
1467 /* Clean up any skbs sitting on the receive queue. */
1468 data_was_unread = sctp_queue_purge_ulpevents(&sk->sk_receive_queue);
1469 data_was_unread += sctp_queue_purge_ulpevents(&sctp_sk(sk)->pd_lobby);
1470
1466 /* Walk all associations on an endpoint. */ 1471 /* Walk all associations on an endpoint. */
1467 list_for_each_safe(pos, temp, &ep->asocs) { 1472 list_for_each_safe(pos, temp, &ep->asocs) {
1468 asoc = list_entry(pos, struct sctp_association, asocs); 1473 asoc = list_entry(pos, struct sctp_association, asocs);
@@ -1480,7 +1485,9 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
1480 } 1485 }
1481 } 1486 }
1482 1487
1483 if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) { 1488 if (data_was_unread || !skb_queue_empty(&asoc->ulpq.lobby) ||
1489 !skb_queue_empty(&asoc->ulpq.reasm) ||
1490 (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime)) {
1484 struct sctp_chunk *chunk; 1491 struct sctp_chunk *chunk;
1485 1492
1486 chunk = sctp_make_abort_user(asoc, NULL, 0); 1493 chunk = sctp_make_abort_user(asoc, NULL, 0);
@@ -1490,10 +1497,6 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
1490 sctp_primitive_SHUTDOWN(asoc, NULL); 1497 sctp_primitive_SHUTDOWN(asoc, NULL);
1491 } 1498 }
1492 1499
1493 /* Clean up any skbs sitting on the receive queue. */
1494 sctp_queue_purge_ulpevents(&sk->sk_receive_queue);
1495 sctp_queue_purge_ulpevents(&sctp_sk(sk)->pd_lobby);
1496
1497 /* On a TCP-style socket, block for at most linger_time if set. */ 1500 /* On a TCP-style socket, block for at most linger_time if set. */
1498 if (sctp_style(sk, TCP) && timeout) 1501 if (sctp_style(sk, TCP) && timeout)
1499 sctp_wait_for_close(sk, timeout); 1502 sctp_wait_for_close(sk, timeout);
@@ -2143,10 +2146,33 @@ static int sctp_setsockopt_disable_fragments(struct sock *sk,
2143static int sctp_setsockopt_events(struct sock *sk, char __user *optval, 2146static int sctp_setsockopt_events(struct sock *sk, char __user *optval,
2144 unsigned int optlen) 2147 unsigned int optlen)
2145{ 2148{
2149 struct sctp_association *asoc;
2150 struct sctp_ulpevent *event;
2151
2146 if (optlen > sizeof(struct sctp_event_subscribe)) 2152 if (optlen > sizeof(struct sctp_event_subscribe))
2147 return -EINVAL; 2153 return -EINVAL;
2148 if (copy_from_user(&sctp_sk(sk)->subscribe, optval, optlen)) 2154 if (copy_from_user(&sctp_sk(sk)->subscribe, optval, optlen))
2149 return -EFAULT; 2155 return -EFAULT;
2156
2157 /*
2158 * At the time when a user app subscribes to SCTP_SENDER_DRY_EVENT,
2159 * if there is no data to be sent or retransmit, the stack will
2160 * immediately send up this notification.
2161 */
2162 if (sctp_ulpevent_type_enabled(SCTP_SENDER_DRY_EVENT,
2163 &sctp_sk(sk)->subscribe)) {
2164 asoc = sctp_id2assoc(sk, 0);
2165
2166 if (asoc && sctp_outq_is_empty(&asoc->outqueue)) {
2167 event = sctp_ulpevent_make_sender_dry_event(asoc,
2168 GFP_ATOMIC);
2169 if (!event)
2170 return -ENOMEM;
2171
2172 sctp_ulpq_tail_event(&asoc->ulpq, event);
2173 }
2174 }
2175
2150 return 0; 2176 return 0;
2151} 2177}
2152 2178