bool connected = !tipc_sk_type_connectionless(sk);
        struct tipc_sock *tsk = tipc_sk(sk);
        int rc, err, hlen, dlen, copy;
+       struct tipc_skb_cb *skb_cb;
        struct sk_buff_head xmitq;
        struct tipc_msg *hdr;
        struct sk_buff *skb;
                if (unlikely(rc))
                        goto exit;
                skb = skb_peek(&sk->sk_receive_queue);
+               skb_cb = TIPC_SKB_CB(skb);
                hdr = buf_msg(skb);
                dlen = msg_data_sz(hdr);
                hlen = msg_hdr_sz(hdr);
 
        /* Capture data if non-error msg, otherwise just set return value */
        if (likely(!err)) {
-               copy = min_t(int, dlen, buflen);
-               if (unlikely(copy != dlen))
-                       m->msg_flags |= MSG_TRUNC;
-               rc = skb_copy_datagram_msg(skb, hlen, m, copy);
+               int offset = skb_cb->bytes_read;
+
+               copy = min_t(int, dlen - offset, buflen);
+               rc = skb_copy_datagram_msg(skb, hlen + offset, m, copy);
+               if (unlikely(rc))
+                       goto exit;
+               if (unlikely(offset + copy < dlen)) {
+                       if (flags & MSG_EOR) {
+                               if (!(flags & MSG_PEEK))
+                                       skb_cb->bytes_read = offset + copy;
+                       } else {
+                               m->msg_flags |= MSG_TRUNC;
+                               skb_cb->bytes_read = 0;
+                       }
+               } else {
+                       if (flags & MSG_EOR)
+                               m->msg_flags |= MSG_EOR;
+                       skb_cb->bytes_read = 0;
+               }
        } else {
                copy = 0;
                rc = 0;
-               if (err != TIPC_CONN_SHUTDOWN && connected && !m->msg_control)
+               if (err != TIPC_CONN_SHUTDOWN && connected && !m->msg_control) {
                        rc = -ECONNRESET;
+                       goto exit;
+               }
        }
-       if (unlikely(rc))
-               goto exit;
 
        /* Mark message as group event if applicable */
        if (unlikely(grp_evt)) {
                tipc_node_distr_xmit(sock_net(sk), &xmitq);
        }
 
-       tsk_advance_rx_queue(sk);
+       if (!skb_cb->bytes_read)
+               tsk_advance_rx_queue(sk);
 
-       if (likely(!connected))
+       if (likely(!connected) || skb_cb->bytes_read)
                goto exit;
 
        /* Send connection flow control advertisement when applicable */