diff options
Diffstat (limited to 'net/tipc/link.c')
| -rw-r--r-- | net/tipc/link.c | 111 |
1 files changed, 91 insertions, 20 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c index cefa99824c58..2a26a16e269f 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
| @@ -1785,6 +1785,56 @@ static struct sk_buff *link_insert_deferred_queue(struct link *l_ptr, | |||
| 1785 | return buf; | 1785 | return buf; |
| 1786 | } | 1786 | } |
| 1787 | 1787 | ||
| 1788 | /** | ||
| 1789 | * link_recv_buf_validate - validate basic format of received message | ||
| 1790 | * | ||
| 1791 | * This routine ensures a TIPC message has an acceptable header, and at least | ||
| 1792 | * as much data as the header indicates it should. The routine also ensures | ||
| 1793 | * that the entire message header is stored in the main fragment of the message | ||
| 1794 | * buffer, to simplify future access to message header fields. | ||
| 1795 | * | ||
| 1796 | * Note: Having extra info present in the message header or data areas is OK. | ||
| 1797 | * TIPC will ignore the excess, under the assumption that it is optional info | ||
| 1798 | * introduced by a later release of the protocol. | ||
| 1799 | */ | ||
| 1800 | |||
| 1801 | static int link_recv_buf_validate(struct sk_buff *buf) | ||
| 1802 | { | ||
| 1803 | static u32 min_data_hdr_size[8] = { | ||
| 1804 | SHORT_H_SIZE, MCAST_H_SIZE, LONG_H_SIZE, DIR_MSG_H_SIZE, | ||
| 1805 | MAX_H_SIZE, MAX_H_SIZE, MAX_H_SIZE, MAX_H_SIZE | ||
| 1806 | }; | ||
| 1807 | |||
| 1808 | struct tipc_msg *msg; | ||
| 1809 | u32 tipc_hdr[2]; | ||
| 1810 | u32 size; | ||
| 1811 | u32 hdr_size; | ||
| 1812 | u32 min_hdr_size; | ||
| 1813 | |||
| 1814 | if (unlikely(buf->len < MIN_H_SIZE)) | ||
| 1815 | return 0; | ||
| 1816 | |||
| 1817 | msg = skb_header_pointer(buf, 0, sizeof(tipc_hdr), tipc_hdr); | ||
| 1818 | if (msg == NULL) | ||
| 1819 | return 0; | ||
| 1820 | |||
| 1821 | if (unlikely(msg_version(msg) != TIPC_VERSION)) | ||
| 1822 | return 0; | ||
| 1823 | |||
| 1824 | size = msg_size(msg); | ||
| 1825 | hdr_size = msg_hdr_sz(msg); | ||
| 1826 | min_hdr_size = msg_isdata(msg) ? | ||
| 1827 | min_data_hdr_size[msg_type(msg)] : INT_H_SIZE; | ||
| 1828 | |||
| 1829 | if (unlikely((hdr_size < min_hdr_size) || | ||
| 1830 | (size < hdr_size) || | ||
| 1831 | (buf->len < size) || | ||
| 1832 | (size - hdr_size > TIPC_MAX_USER_MSG_SIZE))) | ||
| 1833 | return 0; | ||
| 1834 | |||
| 1835 | return pskb_may_pull(buf, hdr_size); | ||
| 1836 | } | ||
| 1837 | |||
| 1788 | void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) | 1838 | void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) |
| 1789 | { | 1839 | { |
| 1790 | read_lock_bh(&tipc_net_lock); | 1840 | read_lock_bh(&tipc_net_lock); |
| @@ -1794,9 +1844,9 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) | |||
| 1794 | struct link *l_ptr; | 1844 | struct link *l_ptr; |
| 1795 | struct sk_buff *crs; | 1845 | struct sk_buff *crs; |
| 1796 | struct sk_buff *buf = head; | 1846 | struct sk_buff *buf = head; |
| 1797 | struct tipc_msg *msg = buf_msg(buf); | 1847 | struct tipc_msg *msg; |
| 1798 | u32 seq_no = msg_seqno(msg); | 1848 | u32 seq_no; |
| 1799 | u32 ackd = msg_ack(msg); | 1849 | u32 ackd; |
| 1800 | u32 released = 0; | 1850 | u32 released = 0; |
| 1801 | int type; | 1851 | int type; |
| 1802 | 1852 | ||
| @@ -1804,12 +1854,21 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) | |||
| 1804 | TIPC_SKB_CB(buf)->handle = b_ptr; | 1854 | TIPC_SKB_CB(buf)->handle = b_ptr; |
| 1805 | 1855 | ||
| 1806 | head = head->next; | 1856 | head = head->next; |
| 1807 | if (unlikely(msg_version(msg) != TIPC_VERSION)) | 1857 | |
| 1858 | /* Ensure message is well-formed */ | ||
| 1859 | |||
| 1860 | if (unlikely(!link_recv_buf_validate(buf))) | ||
| 1808 | goto cont; | 1861 | goto cont; |
| 1809 | #if 0 | 1862 | |
| 1810 | if (msg_user(msg) != LINK_PROTOCOL) | 1863 | /* Ensure message data is a single contiguous unit */ |
| 1811 | #endif | 1864 | |
| 1812 | msg_dbg(msg,"<REC<"); | 1865 | if (unlikely(buf_linearize(buf))) { |
| 1866 | goto cont; | ||
| 1867 | } | ||
| 1868 | |||
| 1869 | /* Handle arrival of a non-unicast link message */ | ||
| 1870 | |||
| 1871 | msg = buf_msg(buf); | ||
| 1813 | 1872 | ||
| 1814 | if (unlikely(msg_non_seq(msg))) { | 1873 | if (unlikely(msg_non_seq(msg))) { |
| 1815 | link_recv_non_seq(buf); | 1874 | link_recv_non_seq(buf); |
| @@ -1820,19 +1879,26 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) | |||
| 1820 | (msg_destnode(msg) != tipc_own_addr))) | 1879 | (msg_destnode(msg) != tipc_own_addr))) |
| 1821 | goto cont; | 1880 | goto cont; |
| 1822 | 1881 | ||
| 1882 | /* Locate unicast link endpoint that should handle message */ | ||
| 1883 | |||
| 1823 | n_ptr = tipc_node_find(msg_prevnode(msg)); | 1884 | n_ptr = tipc_node_find(msg_prevnode(msg)); |
| 1824 | if (unlikely(!n_ptr)) | 1885 | if (unlikely(!n_ptr)) |
| 1825 | goto cont; | 1886 | goto cont; |
| 1826 | |||
| 1827 | tipc_node_lock(n_ptr); | 1887 | tipc_node_lock(n_ptr); |
| 1888 | |||
| 1828 | l_ptr = n_ptr->links[b_ptr->identity]; | 1889 | l_ptr = n_ptr->links[b_ptr->identity]; |
| 1829 | if (unlikely(!l_ptr)) { | 1890 | if (unlikely(!l_ptr)) { |
| 1830 | tipc_node_unlock(n_ptr); | 1891 | tipc_node_unlock(n_ptr); |
| 1831 | goto cont; | 1892 | goto cont; |
| 1832 | } | 1893 | } |
| 1833 | /* | 1894 | |
| 1834 | * Release acked messages | 1895 | /* Validate message sequence number info */ |
| 1835 | */ | 1896 | |
| 1897 | seq_no = msg_seqno(msg); | ||
| 1898 | ackd = msg_ack(msg); | ||
| 1899 | |||
| 1900 | /* Release acked messages */ | ||
| 1901 | |||
| 1836 | if (less(n_ptr->bclink.acked, msg_bcast_ack(msg))) { | 1902 | if (less(n_ptr->bclink.acked, msg_bcast_ack(msg))) { |
| 1837 | if (tipc_node_is_up(n_ptr) && n_ptr->bclink.supported) | 1903 | if (tipc_node_is_up(n_ptr) && n_ptr->bclink.supported) |
| 1838 | tipc_bclink_acknowledge(n_ptr, msg_bcast_ack(msg)); | 1904 | tipc_bclink_acknowledge(n_ptr, msg_bcast_ack(msg)); |
| @@ -1851,6 +1917,9 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) | |||
| 1851 | l_ptr->first_out = crs; | 1917 | l_ptr->first_out = crs; |
| 1852 | l_ptr->out_queue_size -= released; | 1918 | l_ptr->out_queue_size -= released; |
| 1853 | } | 1919 | } |
| 1920 | |||
| 1921 | /* Try sending any messages link endpoint has pending */ | ||
| 1922 | |||
| 1854 | if (unlikely(l_ptr->next_out)) | 1923 | if (unlikely(l_ptr->next_out)) |
| 1855 | tipc_link_push_queue(l_ptr); | 1924 | tipc_link_push_queue(l_ptr); |
| 1856 | if (unlikely(!list_empty(&l_ptr->waiting_ports))) | 1925 | if (unlikely(!list_empty(&l_ptr->waiting_ports))) |
| @@ -1860,6 +1929,8 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) | |||
| 1860 | tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); | 1929 | tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); |
| 1861 | } | 1930 | } |
| 1862 | 1931 | ||
| 1932 | /* Now (finally!) process the incoming message */ | ||
| 1933 | |||
| 1863 | protocol_check: | 1934 | protocol_check: |
| 1864 | if (likely(link_working_working(l_ptr))) { | 1935 | if (likely(link_working_working(l_ptr))) { |
| 1865 | if (likely(seq_no == mod(l_ptr->next_in_no))) { | 1936 | if (likely(seq_no == mod(l_ptr->next_in_no))) { |
| @@ -2832,15 +2903,15 @@ static void link_set_supervision_props(struct link *l_ptr, u32 tolerance) | |||
| 2832 | void tipc_link_set_queue_limits(struct link *l_ptr, u32 window) | 2903 | void tipc_link_set_queue_limits(struct link *l_ptr, u32 window) |
| 2833 | { | 2904 | { |
| 2834 | /* Data messages from this node, inclusive FIRST_FRAGM */ | 2905 | /* Data messages from this node, inclusive FIRST_FRAGM */ |
| 2835 | l_ptr->queue_limit[DATA_LOW] = window; | 2906 | l_ptr->queue_limit[TIPC_LOW_IMPORTANCE] = window; |
| 2836 | l_ptr->queue_limit[DATA_MEDIUM] = (window / 3) * 4; | 2907 | l_ptr->queue_limit[TIPC_MEDIUM_IMPORTANCE] = (window / 3) * 4; |
| 2837 | l_ptr->queue_limit[DATA_HIGH] = (window / 3) * 5; | 2908 | l_ptr->queue_limit[TIPC_HIGH_IMPORTANCE] = (window / 3) * 5; |
| 2838 | l_ptr->queue_limit[DATA_CRITICAL] = (window / 3) * 6; | 2909 | l_ptr->queue_limit[TIPC_CRITICAL_IMPORTANCE] = (window / 3) * 6; |
| 2839 | /* Transiting data messages,inclusive FIRST_FRAGM */ | 2910 | /* Transiting data messages,inclusive FIRST_FRAGM */ |
| 2840 | l_ptr->queue_limit[DATA_LOW + 4] = 300; | 2911 | l_ptr->queue_limit[TIPC_LOW_IMPORTANCE + 4] = 300; |
| 2841 | l_ptr->queue_limit[DATA_MEDIUM + 4] = 600; | 2912 | l_ptr->queue_limit[TIPC_MEDIUM_IMPORTANCE + 4] = 600; |
| 2842 | l_ptr->queue_limit[DATA_HIGH + 4] = 900; | 2913 | l_ptr->queue_limit[TIPC_HIGH_IMPORTANCE + 4] = 900; |
| 2843 | l_ptr->queue_limit[DATA_CRITICAL + 4] = 1200; | 2914 | l_ptr->queue_limit[TIPC_CRITICAL_IMPORTANCE + 4] = 1200; |
| 2844 | l_ptr->queue_limit[CONN_MANAGER] = 1200; | 2915 | l_ptr->queue_limit[CONN_MANAGER] = 1200; |
| 2845 | l_ptr->queue_limit[ROUTE_DISTRIBUTOR] = 1200; | 2916 | l_ptr->queue_limit[ROUTE_DISTRIBUTOR] = 1200; |
| 2846 | l_ptr->queue_limit[CHANGEOVER_PROTOCOL] = 2500; | 2917 | l_ptr->queue_limit[CHANGEOVER_PROTOCOL] = 2500; |
