diff options
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/socket.c | 120 |
1 files changed, 58 insertions, 62 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index b384e658dfeb..f9cd587e4090 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -818,17 +818,14 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff *buf) | |||
818 | /** | 818 | /** |
819 | * tipc_sk_proto_rcv - receive a connection mng protocol message | 819 | * tipc_sk_proto_rcv - receive a connection mng protocol message |
820 | * @tsk: receiving socket | 820 | * @tsk: receiving socket |
821 | * @dnode: node to send response message to, if any | 821 | * @skb: pointer to message buffer. Set to NULL if buffer is consumed. |
822 | * @buf: buffer containing protocol message | ||
823 | * Returns 0 (TIPC_OK) if message was consumed, 1 (TIPC_FWD_MSG) if | ||
824 | * (CONN_PROBE_REPLY) message should be forwarded. | ||
825 | */ | 822 | */ |
826 | static int tipc_sk_proto_rcv(struct tipc_sock *tsk, u32 *dnode, | 823 | static void tipc_sk_proto_rcv(struct tipc_sock *tsk, struct sk_buff **skb) |
827 | struct sk_buff *buf) | ||
828 | { | 824 | { |
829 | struct tipc_msg *msg = buf_msg(buf); | 825 | struct tipc_msg *msg = buf_msg(*skb); |
830 | int conn_cong; | 826 | int conn_cong; |
831 | 827 | u32 dnode; | |
828 | u32 own_node = tsk_own_node(tsk); | ||
832 | /* Ignore if connection cannot be validated: */ | 829 | /* Ignore if connection cannot be validated: */ |
833 | if (!tsk_peer_msg(tsk, msg)) | 830 | if (!tsk_peer_msg(tsk, msg)) |
834 | goto exit; | 831 | goto exit; |
@@ -841,15 +838,15 @@ static int tipc_sk_proto_rcv(struct tipc_sock *tsk, u32 *dnode, | |||
841 | if (conn_cong) | 838 | if (conn_cong) |
842 | tsk->sk.sk_write_space(&tsk->sk); | 839 | tsk->sk.sk_write_space(&tsk->sk); |
843 | } else if (msg_type(msg) == CONN_PROBE) { | 840 | } else if (msg_type(msg) == CONN_PROBE) { |
844 | if (!tipc_msg_reverse(tsk_own_node(tsk), buf, dnode, TIPC_OK)) | 841 | if (tipc_msg_reverse(own_node, *skb, &dnode, TIPC_OK)) { |
845 | return TIPC_OK; | 842 | msg_set_type(msg, CONN_PROBE_REPLY); |
846 | msg_set_type(msg, CONN_PROBE_REPLY); | 843 | return; |
847 | return TIPC_FWD_MSG; | 844 | } |
848 | } | 845 | } |
849 | /* Do nothing if msg_type() == CONN_PROBE_REPLY */ | 846 | /* Do nothing if msg_type() == CONN_PROBE_REPLY */ |
850 | exit: | 847 | exit: |
851 | kfree_skb(buf); | 848 | kfree_skb(*skb); |
852 | return TIPC_OK; | 849 | *skb = NULL; |
853 | } | 850 | } |
854 | 851 | ||
855 | static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p) | 852 | static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p) |
@@ -1568,16 +1565,16 @@ static void tipc_data_ready(struct sock *sk) | |||
1568 | /** | 1565 | /** |
1569 | * filter_connect - Handle all incoming messages for a connection-based socket | 1566 | * filter_connect - Handle all incoming messages for a connection-based socket |
1570 | * @tsk: TIPC socket | 1567 | * @tsk: TIPC socket |
1571 | * @msg: message | 1568 | * @skb: pointer to message buffer. Set to NULL if buffer is consumed |
1572 | * | 1569 | * |
1573 | * Returns 0 (TIPC_OK) if everything ok, -TIPC_ERR_NO_PORT otherwise | 1570 | * Returns 0 (TIPC_OK) if everything ok, -TIPC_ERR_NO_PORT otherwise |
1574 | */ | 1571 | */ |
1575 | static int filter_connect(struct tipc_sock *tsk, struct sk_buff **buf) | 1572 | static int filter_connect(struct tipc_sock *tsk, struct sk_buff **skb) |
1576 | { | 1573 | { |
1577 | struct sock *sk = &tsk->sk; | 1574 | struct sock *sk = &tsk->sk; |
1578 | struct net *net = sock_net(sk); | 1575 | struct net *net = sock_net(sk); |
1579 | struct socket *sock = sk->sk_socket; | 1576 | struct socket *sock = sk->sk_socket; |
1580 | struct tipc_msg *msg = buf_msg(*buf); | 1577 | struct tipc_msg *msg = buf_msg(*skb); |
1581 | int retval = -TIPC_ERR_NO_PORT; | 1578 | int retval = -TIPC_ERR_NO_PORT; |
1582 | 1579 | ||
1583 | if (msg_mcast(msg)) | 1580 | if (msg_mcast(msg)) |
@@ -1627,8 +1624,8 @@ static int filter_connect(struct tipc_sock *tsk, struct sk_buff **buf) | |||
1627 | * connect() routine if sleeping. | 1624 | * connect() routine if sleeping. |
1628 | */ | 1625 | */ |
1629 | if (msg_data_sz(msg) == 0) { | 1626 | if (msg_data_sz(msg) == 0) { |
1630 | kfree_skb(*buf); | 1627 | kfree_skb(*skb); |
1631 | *buf = NULL; | 1628 | *skb = NULL; |
1632 | if (waitqueue_active(sk_sleep(sk))) | 1629 | if (waitqueue_active(sk_sleep(sk))) |
1633 | wake_up_interruptible(sk_sleep(sk)); | 1630 | wake_up_interruptible(sk_sleep(sk)); |
1634 | } | 1631 | } |
@@ -1680,32 +1677,33 @@ static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *buf) | |||
1680 | /** | 1677 | /** |
1681 | * filter_rcv - validate incoming message | 1678 | * filter_rcv - validate incoming message |
1682 | * @sk: socket | 1679 | * @sk: socket |
1683 | * @buf: message | 1680 | * @skb: pointer to message. Set to NULL if buffer is consumed. |
1684 | * | 1681 | * |
1685 | * Enqueues message on receive queue if acceptable; optionally handles | 1682 | * Enqueues message on receive queue if acceptable; optionally handles |
1686 | * disconnect indication for a connected socket. | 1683 | * disconnect indication for a connected socket. |
1687 | * | 1684 | * |
1688 | * Called with socket lock already taken; port lock may also be taken. | 1685 | * Called with socket lock already taken |
1689 | * | 1686 | * |
1690 | * Returns 0 (TIPC_OK) if message was consumed, -TIPC error code if message | 1687 | * Returns 0 (TIPC_OK) if message was ok, -TIPC error code if rejected |
1691 | * to be rejected, 1 (TIPC_FWD_MSG) if (CONN_MANAGER) message to be forwarded | ||
1692 | */ | 1688 | */ |
1693 | static int filter_rcv(struct sock *sk, struct sk_buff *buf) | 1689 | static int filter_rcv(struct sock *sk, struct sk_buff **skb) |
1694 | { | 1690 | { |
1695 | struct socket *sock = sk->sk_socket; | 1691 | struct socket *sock = sk->sk_socket; |
1696 | struct tipc_sock *tsk = tipc_sk(sk); | 1692 | struct tipc_sock *tsk = tipc_sk(sk); |
1697 | struct tipc_msg *msg = buf_msg(buf); | 1693 | struct tipc_msg *msg = buf_msg(*skb); |
1698 | unsigned int limit = rcvbuf_limit(sk, buf); | 1694 | unsigned int limit = rcvbuf_limit(sk, *skb); |
1699 | u32 onode; | ||
1700 | int rc = TIPC_OK; | 1695 | int rc = TIPC_OK; |
1701 | 1696 | ||
1702 | if (unlikely(msg_user(msg) == CONN_MANAGER)) | 1697 | if (unlikely(msg_user(msg) == CONN_MANAGER)) { |
1703 | return tipc_sk_proto_rcv(tsk, &onode, buf); | 1698 | tipc_sk_proto_rcv(tsk, skb); |
1699 | return TIPC_OK; | ||
1700 | } | ||
1704 | 1701 | ||
1705 | if (unlikely(msg_user(msg) == SOCK_WAKEUP)) { | 1702 | if (unlikely(msg_user(msg) == SOCK_WAKEUP)) { |
1706 | kfree_skb(buf); | 1703 | kfree_skb(*skb); |
1707 | tsk->link_cong = 0; | 1704 | tsk->link_cong = 0; |
1708 | sk->sk_write_space(sk); | 1705 | sk->sk_write_space(sk); |
1706 | *skb = NULL; | ||
1709 | return TIPC_OK; | 1707 | return TIPC_OK; |
1710 | } | 1708 | } |
1711 | 1709 | ||
@@ -1717,21 +1715,22 @@ static int filter_rcv(struct sock *sk, struct sk_buff *buf) | |||
1717 | if (msg_connected(msg)) | 1715 | if (msg_connected(msg)) |
1718 | return -TIPC_ERR_NO_PORT; | 1716 | return -TIPC_ERR_NO_PORT; |
1719 | } else { | 1717 | } else { |
1720 | rc = filter_connect(tsk, &buf); | 1718 | rc = filter_connect(tsk, skb); |
1721 | if (rc != TIPC_OK || buf == NULL) | 1719 | if (rc != TIPC_OK || !*skb) |
1722 | return rc; | 1720 | return rc; |
1723 | } | 1721 | } |
1724 | 1722 | ||
1725 | /* Reject message if there isn't room to queue it */ | 1723 | /* Reject message if there isn't room to queue it */ |
1726 | if (sk_rmem_alloc_get(sk) + buf->truesize >= limit) | 1724 | if (sk_rmem_alloc_get(sk) + (*skb)->truesize >= limit) |
1727 | return -TIPC_ERR_OVERLOAD; | 1725 | return -TIPC_ERR_OVERLOAD; |
1728 | 1726 | ||
1729 | /* Enqueue message */ | 1727 | /* Enqueue message */ |
1730 | TIPC_SKB_CB(buf)->handle = NULL; | 1728 | TIPC_SKB_CB(*skb)->handle = NULL; |
1731 | __skb_queue_tail(&sk->sk_receive_queue, buf); | 1729 | __skb_queue_tail(&sk->sk_receive_queue, *skb); |
1732 | skb_set_owner_r(buf, sk); | 1730 | skb_set_owner_r(*skb, sk); |
1733 | 1731 | ||
1734 | sk->sk_data_ready(sk); | 1732 | sk->sk_data_ready(sk); |
1733 | *skb = NULL; | ||
1735 | return TIPC_OK; | 1734 | return TIPC_OK; |
1736 | } | 1735 | } |
1737 | 1736 | ||
@@ -1746,25 +1745,22 @@ static int filter_rcv(struct sock *sk, struct sk_buff *buf) | |||
1746 | */ | 1745 | */ |
1747 | static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb) | 1746 | static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb) |
1748 | { | 1747 | { |
1749 | int rc; | 1748 | int err; |
1750 | u32 onode; | 1749 | atomic_t *dcnt; |
1750 | u32 dnode; | ||
1751 | struct tipc_sock *tsk = tipc_sk(sk); | 1751 | struct tipc_sock *tsk = tipc_sk(sk); |
1752 | struct net *net = sock_net(sk); | 1752 | struct net *net = sock_net(sk); |
1753 | uint truesize = skb->truesize; | 1753 | uint truesize = skb->truesize; |
1754 | 1754 | ||
1755 | rc = filter_rcv(sk, skb); | 1755 | err = filter_rcv(sk, &skb); |
1756 | 1756 | if (likely(!skb)) { | |
1757 | if (likely(!rc)) { | 1757 | dcnt = &tsk->dupl_rcvcnt; |
1758 | if (atomic_read(&tsk->dupl_rcvcnt) < TIPC_CONN_OVERLOAD_LIMIT) | 1758 | if (atomic_read(dcnt) < TIPC_CONN_OVERLOAD_LIMIT) |
1759 | atomic_add(truesize, &tsk->dupl_rcvcnt); | 1759 | atomic_add(truesize, dcnt); |
1760 | return 0; | 1760 | return 0; |
1761 | } | 1761 | } |
1762 | 1762 | if (!err || tipc_msg_reverse(tsk_own_node(tsk), skb, &dnode, -err)) | |
1763 | if ((rc < 0) && !tipc_msg_reverse(tsk_own_node(tsk), skb, &onode, -rc)) | 1763 | tipc_link_xmit_skb(net, skb, dnode, tsk->portid); |
1764 | return 0; | ||
1765 | |||
1766 | tipc_link_xmit_skb(net, skb, onode, 0); | ||
1767 | |||
1768 | return 0; | 1764 | return 0; |
1769 | } | 1765 | } |
1770 | 1766 | ||
@@ -1780,14 +1776,14 @@ int tipc_sk_rcv(struct net *net, struct sk_buff *skb) | |||
1780 | struct tipc_net *tn; | 1776 | struct tipc_net *tn; |
1781 | struct sock *sk; | 1777 | struct sock *sk; |
1782 | u32 dport = msg_destport(buf_msg(skb)); | 1778 | u32 dport = msg_destport(buf_msg(skb)); |
1783 | int rc = TIPC_OK; | 1779 | int err = TIPC_OK; |
1784 | uint limit; | 1780 | uint limit; |
1785 | u32 dnode; | 1781 | u32 dnode; |
1786 | 1782 | ||
1787 | /* Validate destination and message */ | 1783 | /* Validate destination and message */ |
1788 | tsk = tipc_sk_lookup(net, dport); | 1784 | tsk = tipc_sk_lookup(net, dport); |
1789 | if (unlikely(!tsk)) { | 1785 | if (unlikely(!tsk)) { |
1790 | rc = tipc_msg_eval(net, skb, &dnode); | 1786 | err = tipc_msg_eval(net, skb, &dnode); |
1791 | goto exit; | 1787 | goto exit; |
1792 | } | 1788 | } |
1793 | sk = &tsk->sk; | 1789 | sk = &tsk->sk; |
@@ -1796,25 +1792,25 @@ int tipc_sk_rcv(struct net *net, struct sk_buff *skb) | |||
1796 | spin_lock_bh(&sk->sk_lock.slock); | 1792 | spin_lock_bh(&sk->sk_lock.slock); |
1797 | 1793 | ||
1798 | if (!sock_owned_by_user(sk)) { | 1794 | if (!sock_owned_by_user(sk)) { |
1799 | rc = filter_rcv(sk, skb); | 1795 | err = filter_rcv(sk, &skb); |
1800 | } else { | 1796 | } else { |
1801 | if (sk->sk_backlog.len == 0) | 1797 | if (sk->sk_backlog.len == 0) |
1802 | atomic_set(&tsk->dupl_rcvcnt, 0); | 1798 | atomic_set(&tsk->dupl_rcvcnt, 0); |
1803 | limit = rcvbuf_limit(sk, skb) + atomic_read(&tsk->dupl_rcvcnt); | 1799 | limit = rcvbuf_limit(sk, skb) + atomic_read(&tsk->dupl_rcvcnt); |
1804 | if (sk_add_backlog(sk, skb, limit)) | 1800 | if (likely(!sk_add_backlog(sk, skb, limit))) |
1805 | rc = -TIPC_ERR_OVERLOAD; | 1801 | skb = NULL; |
1802 | else | ||
1803 | err = -TIPC_ERR_OVERLOAD; | ||
1806 | } | 1804 | } |
1807 | spin_unlock_bh(&sk->sk_lock.slock); | 1805 | spin_unlock_bh(&sk->sk_lock.slock); |
1808 | sock_put(sk); | 1806 | sock_put(sk); |
1809 | if (likely(!rc)) | ||
1810 | return 0; | ||
1811 | exit: | 1807 | exit: |
1812 | tn = net_generic(net, tipc_net_id); | 1808 | if (unlikely(skb)) { |
1813 | if ((rc < 0) && !tipc_msg_reverse(tn->own_addr, skb, &dnode, -rc)) | 1809 | tn = net_generic(net, tipc_net_id); |
1814 | return -EHOSTUNREACH; | 1810 | if (!err || tipc_msg_reverse(tn->own_addr, skb, &dnode, -err)) |
1815 | 1811 | tipc_link_xmit_skb(net, skb, dnode, 0); | |
1816 | tipc_link_xmit_skb(net, skb, dnode, 0); | 1812 | } |
1817 | return (rc < 0) ? -EHOSTUNREACH : 0; | 1813 | return err ? -EHOSTUNREACH : 0; |
1818 | } | 1814 | } |
1819 | 1815 | ||
1820 | static int tipc_wait_for_connect(struct socket *sock, long *timeo_p) | 1816 | static int tipc_wait_for_connect(struct socket *sock, long *timeo_p) |