diff options
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r-- | net/tipc/socket.c | 48 |
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 | */ |
781 | void tipc_sk_mcast_rcv(struct net *net, struct sk_buff *buf) | 781 | void 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); | ||
821 | exit: | 815 | exit: |
822 | tipc_port_list_free(&dports); | 816 | kfree_skb(skb); |
823 | } | 817 | } |
824 | 818 | ||
825 | /** | 819 | /** |