aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r--net/tipc/socket.c48
1 files changed, 21 insertions, 27 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index c1a4611649ab..26aec8414ac1 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * net/tipc/socket.c: TIPC socket API 2 * net/tipc/socket.c: TIPC socket API
3 * 3 *
4 * Copyright (c) 2001-2007, 2012-2014, Ericsson AB 4 * Copyright (c) 2001-2007, 2012-2015, Ericsson AB
5 * Copyright (c) 2004-2008, 2010-2013, Wind River Systems 5 * Copyright (c) 2004-2008, 2010-2013, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
@@ -778,48 +778,42 @@ new_mtu:
778 778
779/* tipc_sk_mcast_rcv - Deliver multicast message to all destination sockets 779/* tipc_sk_mcast_rcv - Deliver multicast message to all destination sockets
780 */ 780 */
781void tipc_sk_mcast_rcv(struct net *net, struct sk_buff *buf) 781void tipc_sk_mcast_rcv(struct net *net, struct sk_buff *skb)
782{ 782{
783 struct tipc_msg *msg = buf_msg(buf); 783 struct tipc_msg *msg = buf_msg(skb);
784 struct tipc_port_list dports = {0, NULL, }; 784 struct tipc_plist dports;
785 struct tipc_port_list *item; 785 struct sk_buff *cskb;
786 struct sk_buff *b; 786 u32 portid;
787 uint i, last, dst = 0;
788 u32 scope = TIPC_CLUSTER_SCOPE; 787 u32 scope = TIPC_CLUSTER_SCOPE;
789 struct sk_buff_head msgs; 788 struct sk_buff_head msgq;
789 uint hsz = skb_headroom(skb) + msg_hdr_sz(msg);
790
791 skb_queue_head_init(&msgq);
792 tipc_plist_init(&dports);
790 793
791 if (in_own_node(net, msg_orignode(msg))) 794 if (in_own_node(net, msg_orignode(msg)))
792 scope = TIPC_NODE_SCOPE; 795 scope = TIPC_NODE_SCOPE;
793 796
794 if (unlikely(!msg_mcast(msg))) { 797 if (unlikely(!msg_mcast(msg))) {
795 pr_warn("Received non-multicast msg in multicast\n"); 798 pr_warn("Received non-multicast msg in multicast\n");
796 kfree_skb(buf);
797 goto exit; 799 goto exit;
798 } 800 }
799 /* Create destination port list: */ 801 /* Create destination port list: */
800 tipc_nametbl_mc_translate(net, msg_nametype(msg), msg_namelower(msg), 802 tipc_nametbl_mc_translate(net, msg_nametype(msg), msg_namelower(msg),
801 msg_nameupper(msg), scope, &dports); 803 msg_nameupper(msg), scope, &dports);
802 last = dports.count; 804 portid = tipc_plist_pop(&dports);
803 if (!last) { 805 for (; portid; portid = tipc_plist_pop(&dports)) {
804 kfree_skb(buf); 806 cskb = __pskb_copy(skb, hsz, GFP_ATOMIC);
805 return; 807 if (!cskb) {
806 } 808 pr_warn("Failed do clone mcast rcv buffer\n");
807 809 continue;
808 for (item = &dports; item; item = item->next) {
809 for (i = 0; i < PLSIZE && ++dst <= last; i++) {
810 b = (dst != last) ? skb_clone(buf, GFP_ATOMIC) : buf;
811 if (!b) {
812 pr_warn("Failed do clone mcast rcv buffer\n");
813 continue;
814 }
815 msg_set_destport(msg, item->ports[i]);
816 skb_queue_head_init(&msgs);
817 skb_queue_tail(&msgs, b);
818 tipc_sk_rcv(net, &msgs);
819 } 810 }
811 msg_set_destport(buf_msg(cskb), portid);
812 skb_queue_tail(&msgq, cskb);
820 } 813 }
814 tipc_sk_rcv(net, &msgq);
821exit: 815exit:
822 tipc_port_list_free(&dports); 816 kfree_skb(skb);
823} 817}
824 818
825/** 819/**