aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-10-13 15:55:20 -0400
committerDavid S. Miller <davem@davemloft.net>2009-10-13 15:55:20 -0400
commit421355de876b9f3fcc7e4cb6026e416fb12a5068 (patch)
treefb814456af86c75e1eb9e330994dda461fc5b4f7 /net/ipv4
parentaace495933a981274b6491d71b915165a61defdc (diff)
parent0fe7463a35aadfaf22d1ca58325ab3851b8d757c (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/tcp_minisocks.c1
-rw-r--r--net/ipv4/udp.c73
2 files changed, 44 insertions, 30 deletions
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 624c3c9b3c2b..e320afea07fc 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -644,6 +644,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
644 /* If TCP_DEFER_ACCEPT is set, drop bare ACK. */ 644 /* If TCP_DEFER_ACCEPT is set, drop bare ACK. */
645 if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && 645 if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept &&
646 TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) { 646 TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) {
647 inet_csk(sk)->icsk_accept_queue.rskq_defer_accept--;
647 inet_rsk(req)->acked = 1; 648 inet_rsk(req)->acked = 1;
648 return NULL; 649 return NULL;
649 } 650 }
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 71e5353b30c8..ee61b3fc4cae 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -845,6 +845,42 @@ out:
845 return ret; 845 return ret;
846} 846}
847 847
848
849/**
850 * first_packet_length - return length of first packet in receive queue
851 * @sk: socket
852 *
853 * Drops all bad checksum frames, until a valid one is found.
854 * Returns the length of found skb, or 0 if none is found.
855 */
856static unsigned int first_packet_length(struct sock *sk)
857{
858 struct sk_buff_head list_kill, *rcvq = &sk->sk_receive_queue;
859 struct sk_buff *skb;
860 unsigned int res;
861
862 __skb_queue_head_init(&list_kill);
863
864 spin_lock_bh(&rcvq->lock);
865 while ((skb = skb_peek(rcvq)) != NULL &&
866 udp_lib_checksum_complete(skb)) {
867 UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS,
868 IS_UDPLITE(sk));
869 __skb_unlink(skb, rcvq);
870 __skb_queue_tail(&list_kill, skb);
871 }
872 res = skb ? skb->len : 0;
873 spin_unlock_bh(&rcvq->lock);
874
875 if (!skb_queue_empty(&list_kill)) {
876 lock_sock(sk);
877 __skb_queue_purge(&list_kill);
878 sk_mem_reclaim_partial(sk);
879 release_sock(sk);
880 }
881 return res;
882}
883
848/* 884/*
849 * IOCTL requests applicable to the UDP protocol 885 * IOCTL requests applicable to the UDP protocol
850 */ 886 */
@@ -861,21 +897,16 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
861 897
862 case SIOCINQ: 898 case SIOCINQ:
863 { 899 {
864 struct sk_buff *skb; 900 unsigned int amount = first_packet_length(sk);
865 unsigned long amount;
866 901
867 amount = 0; 902 if (amount)
868 spin_lock_bh(&sk->sk_receive_queue.lock);
869 skb = skb_peek(&sk->sk_receive_queue);
870 if (skb != NULL) {
871 /* 903 /*
872 * We will only return the amount 904 * We will only return the amount
873 * of this packet since that is all 905 * of this packet since that is all
874 * that will be read. 906 * that will be read.
875 */ 907 */
876 amount = skb->len - sizeof(struct udphdr); 908 amount -= sizeof(struct udphdr);
877 } 909
878 spin_unlock_bh(&sk->sk_receive_queue.lock);
879 return put_user(amount, (int __user *)arg); 910 return put_user(amount, (int __user *)arg);
880 } 911 }
881 912
@@ -1544,29 +1575,11 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
1544{ 1575{
1545 unsigned int mask = datagram_poll(file, sock, wait); 1576 unsigned int mask = datagram_poll(file, sock, wait);
1546 struct sock *sk = sock->sk; 1577 struct sock *sk = sock->sk;
1547 int is_lite = IS_UDPLITE(sk);
1548 1578
1549 /* Check for false positives due to checksum errors */ 1579 /* Check for false positives due to checksum errors */
1550 if ((mask & POLLRDNORM) && 1580 if ((mask & POLLRDNORM) && !(file->f_flags & O_NONBLOCK) &&
1551 !(file->f_flags & O_NONBLOCK) && 1581 !(sk->sk_shutdown & RCV_SHUTDOWN) && !first_packet_length(sk))
1552 !(sk->sk_shutdown & RCV_SHUTDOWN)) { 1582 mask &= ~(POLLIN | POLLRDNORM);
1553 struct sk_buff_head *rcvq = &sk->sk_receive_queue;
1554 struct sk_buff *skb;
1555
1556 spin_lock_bh(&rcvq->lock);
1557 while ((skb = skb_peek(rcvq)) != NULL &&
1558 udp_lib_checksum_complete(skb)) {
1559 UDP_INC_STATS_BH(sock_net(sk),
1560 UDP_MIB_INERRORS, is_lite);
1561 __skb_unlink(skb, rcvq);
1562 kfree_skb(skb);
1563 }
1564 spin_unlock_bh(&rcvq->lock);
1565
1566 /* nothing to see, move along */
1567 if (skb == NULL)
1568 mask &= ~(POLLIN | POLLRDNORM);
1569 }
1570 1583
1571 return mask; 1584 return mask;
1572 1585