diff options
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r-- | net/tipc/socket.c | 114 |
1 files changed, 64 insertions, 50 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 2aa46e8cd8fe..163f3a547501 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -116,6 +116,7 @@ struct tipc_sock { | |||
116 | struct tipc_mc_method mc_method; | 116 | struct tipc_mc_method mc_method; |
117 | struct rcu_head rcu; | 117 | struct rcu_head rcu; |
118 | struct tipc_group *group; | 118 | struct tipc_group *group; |
119 | bool group_is_open; | ||
119 | }; | 120 | }; |
120 | 121 | ||
121 | static int tipc_sk_backlog_rcv(struct sock *sk, struct sk_buff *skb); | 122 | static int tipc_sk_backlog_rcv(struct sock *sk, struct sk_buff *skb); |
@@ -715,7 +716,6 @@ static __poll_t tipc_poll(struct file *file, struct socket *sock, | |||
715 | { | 716 | { |
716 | struct sock *sk = sock->sk; | 717 | struct sock *sk = sock->sk; |
717 | struct tipc_sock *tsk = tipc_sk(sk); | 718 | struct tipc_sock *tsk = tipc_sk(sk); |
718 | struct tipc_group *grp = tsk->group; | ||
719 | __poll_t revents = 0; | 719 | __poll_t revents = 0; |
720 | 720 | ||
721 | sock_poll_wait(file, sk_sleep(sk), wait); | 721 | sock_poll_wait(file, sk_sleep(sk), wait); |
@@ -736,9 +736,8 @@ static __poll_t tipc_poll(struct file *file, struct socket *sock, | |||
736 | revents |= POLLIN | POLLRDNORM; | 736 | revents |= POLLIN | POLLRDNORM; |
737 | break; | 737 | break; |
738 | case TIPC_OPEN: | 738 | case TIPC_OPEN: |
739 | if (!grp || tipc_group_size(grp)) | 739 | if (tsk->group_is_open && !tsk->cong_link_cnt) |
740 | if (!tsk->cong_link_cnt) | 740 | revents |= POLLOUT; |
741 | revents |= POLLOUT; | ||
742 | if (!tipc_sk_type_connectionless(sk)) | 741 | if (!tipc_sk_type_connectionless(sk)) |
743 | break; | 742 | break; |
744 | if (skb_queue_empty(&sk->sk_receive_queue)) | 743 | if (skb_queue_empty(&sk->sk_receive_queue)) |
@@ -772,7 +771,6 @@ static int tipc_sendmcast(struct socket *sock, struct tipc_name_seq *seq, | |||
772 | struct net *net = sock_net(sk); | 771 | struct net *net = sock_net(sk); |
773 | int mtu = tipc_bcast_get_mtu(net); | 772 | int mtu = tipc_bcast_get_mtu(net); |
774 | struct tipc_mc_method *method = &tsk->mc_method; | 773 | struct tipc_mc_method *method = &tsk->mc_method; |
775 | u32 domain = addr_domain(net, TIPC_CLUSTER_SCOPE); | ||
776 | struct sk_buff_head pkts; | 774 | struct sk_buff_head pkts; |
777 | struct tipc_nlist dsts; | 775 | struct tipc_nlist dsts; |
778 | int rc; | 776 | int rc; |
@@ -788,7 +786,7 @@ static int tipc_sendmcast(struct socket *sock, struct tipc_name_seq *seq, | |||
788 | /* Lookup destination nodes */ | 786 | /* Lookup destination nodes */ |
789 | tipc_nlist_init(&dsts, tipc_own_addr(net)); | 787 | tipc_nlist_init(&dsts, tipc_own_addr(net)); |
790 | tipc_nametbl_lookup_dst_nodes(net, seq->type, seq->lower, | 788 | tipc_nametbl_lookup_dst_nodes(net, seq->type, seq->lower, |
791 | seq->upper, domain, &dsts); | 789 | seq->upper, &dsts); |
792 | if (!dsts.local && !dsts.remote) | 790 | if (!dsts.local && !dsts.remote) |
793 | return -EHOSTUNREACH; | 791 | return -EHOSTUNREACH; |
794 | 792 | ||
@@ -928,21 +926,22 @@ static int tipc_send_group_anycast(struct socket *sock, struct msghdr *m, | |||
928 | struct list_head *cong_links = &tsk->cong_links; | 926 | struct list_head *cong_links = &tsk->cong_links; |
929 | int blks = tsk_blocks(GROUP_H_SIZE + dlen); | 927 | int blks = tsk_blocks(GROUP_H_SIZE + dlen); |
930 | struct tipc_group *grp = tsk->group; | 928 | struct tipc_group *grp = tsk->group; |
929 | struct tipc_msg *hdr = &tsk->phdr; | ||
931 | struct tipc_member *first = NULL; | 930 | struct tipc_member *first = NULL; |
932 | struct tipc_member *mbr = NULL; | 931 | struct tipc_member *mbr = NULL; |
933 | struct net *net = sock_net(sk); | 932 | struct net *net = sock_net(sk); |
934 | u32 node, port, exclude; | 933 | u32 node, port, exclude; |
935 | u32 type, inst, domain; | ||
936 | struct list_head dsts; | 934 | struct list_head dsts; |
935 | u32 type, inst, scope; | ||
937 | int lookups = 0; | 936 | int lookups = 0; |
938 | int dstcnt, rc; | 937 | int dstcnt, rc; |
939 | bool cong; | 938 | bool cong; |
940 | 939 | ||
941 | INIT_LIST_HEAD(&dsts); | 940 | INIT_LIST_HEAD(&dsts); |
942 | 941 | ||
943 | type = dest->addr.name.name.type; | 942 | type = msg_nametype(hdr); |
944 | inst = dest->addr.name.name.instance; | 943 | inst = dest->addr.name.name.instance; |
945 | domain = addr_domain(net, dest->scope); | 944 | scope = msg_lookup_scope(hdr); |
946 | exclude = tipc_group_exclude(grp); | 945 | exclude = tipc_group_exclude(grp); |
947 | 946 | ||
948 | while (++lookups < 4) { | 947 | while (++lookups < 4) { |
@@ -950,7 +949,7 @@ static int tipc_send_group_anycast(struct socket *sock, struct msghdr *m, | |||
950 | 949 | ||
951 | /* Look for a non-congested destination member, if any */ | 950 | /* Look for a non-congested destination member, if any */ |
952 | while (1) { | 951 | while (1) { |
953 | if (!tipc_nametbl_lookup(net, type, inst, domain, &dsts, | 952 | if (!tipc_nametbl_lookup(net, type, inst, scope, &dsts, |
954 | &dstcnt, exclude, false)) | 953 | &dstcnt, exclude, false)) |
955 | return -EHOSTUNREACH; | 954 | return -EHOSTUNREACH; |
956 | tipc_dest_pop(&dsts, &node, &port); | 955 | tipc_dest_pop(&dsts, &node, &port); |
@@ -1079,22 +1078,23 @@ static int tipc_send_group_mcast(struct socket *sock, struct msghdr *m, | |||
1079 | { | 1078 | { |
1080 | struct sock *sk = sock->sk; | 1079 | struct sock *sk = sock->sk; |
1081 | DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); | 1080 | DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); |
1082 | struct tipc_name_seq *seq = &dest->addr.nameseq; | ||
1083 | struct tipc_sock *tsk = tipc_sk(sk); | 1081 | struct tipc_sock *tsk = tipc_sk(sk); |
1084 | struct tipc_group *grp = tsk->group; | 1082 | struct tipc_group *grp = tsk->group; |
1083 | struct tipc_msg *hdr = &tsk->phdr; | ||
1085 | struct net *net = sock_net(sk); | 1084 | struct net *net = sock_net(sk); |
1086 | u32 domain, exclude, dstcnt; | 1085 | u32 type, inst, scope, exclude; |
1087 | struct list_head dsts; | 1086 | struct list_head dsts; |
1087 | u32 dstcnt; | ||
1088 | 1088 | ||
1089 | INIT_LIST_HEAD(&dsts); | 1089 | INIT_LIST_HEAD(&dsts); |
1090 | 1090 | ||
1091 | if (seq->lower != seq->upper) | 1091 | type = msg_nametype(hdr); |
1092 | return -ENOTSUPP; | 1092 | inst = dest->addr.name.name.instance; |
1093 | 1093 | scope = msg_lookup_scope(hdr); | |
1094 | domain = addr_domain(net, dest->scope); | ||
1095 | exclude = tipc_group_exclude(grp); | 1094 | exclude = tipc_group_exclude(grp); |
1096 | if (!tipc_nametbl_lookup(net, seq->type, seq->lower, domain, | 1095 | |
1097 | &dsts, &dstcnt, exclude, true)) | 1096 | if (!tipc_nametbl_lookup(net, type, inst, scope, &dsts, |
1097 | &dstcnt, exclude, true)) | ||
1098 | return -EHOSTUNREACH; | 1098 | return -EHOSTUNREACH; |
1099 | 1099 | ||
1100 | if (dstcnt == 1) { | 1100 | if (dstcnt == 1) { |
@@ -1116,24 +1116,29 @@ static int tipc_send_group_mcast(struct socket *sock, struct msghdr *m, | |||
1116 | void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq, | 1116 | void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq, |
1117 | struct sk_buff_head *inputq) | 1117 | struct sk_buff_head *inputq) |
1118 | { | 1118 | { |
1119 | u32 scope = TIPC_CLUSTER_SCOPE; | ||
1120 | u32 self = tipc_own_addr(net); | 1119 | u32 self = tipc_own_addr(net); |
1120 | u32 type, lower, upper, scope; | ||
1121 | struct sk_buff *skb, *_skb; | 1121 | struct sk_buff *skb, *_skb; |
1122 | u32 lower = 0, upper = ~0; | ||
1123 | struct sk_buff_head tmpq; | ||
1124 | u32 portid, oport, onode; | 1122 | u32 portid, oport, onode; |
1123 | struct sk_buff_head tmpq; | ||
1125 | struct list_head dports; | 1124 | struct list_head dports; |
1126 | struct tipc_msg *msg; | 1125 | struct tipc_msg *hdr; |
1127 | int user, mtyp, hsz; | 1126 | int user, mtyp, hlen; |
1127 | bool exact; | ||
1128 | 1128 | ||
1129 | __skb_queue_head_init(&tmpq); | 1129 | __skb_queue_head_init(&tmpq); |
1130 | INIT_LIST_HEAD(&dports); | 1130 | INIT_LIST_HEAD(&dports); |
1131 | 1131 | ||
1132 | skb = tipc_skb_peek(arrvq, &inputq->lock); | 1132 | skb = tipc_skb_peek(arrvq, &inputq->lock); |
1133 | for (; skb; skb = tipc_skb_peek(arrvq, &inputq->lock)) { | 1133 | for (; skb; skb = tipc_skb_peek(arrvq, &inputq->lock)) { |
1134 | msg = buf_msg(skb); | 1134 | hdr = buf_msg(skb); |
1135 | user = msg_user(msg); | 1135 | user = msg_user(hdr); |
1136 | mtyp = msg_type(msg); | 1136 | mtyp = msg_type(hdr); |
1137 | hlen = skb_headroom(skb) + msg_hdr_sz(hdr); | ||
1138 | oport = msg_origport(hdr); | ||
1139 | onode = msg_orignode(hdr); | ||
1140 | type = msg_nametype(hdr); | ||
1141 | |||
1137 | if (mtyp == TIPC_GRP_UCAST_MSG || user == GROUP_PROTOCOL) { | 1142 | if (mtyp == TIPC_GRP_UCAST_MSG || user == GROUP_PROTOCOL) { |
1138 | spin_lock_bh(&inputq->lock); | 1143 | spin_lock_bh(&inputq->lock); |
1139 | if (skb_peek(arrvq) == skb) { | 1144 | if (skb_peek(arrvq) == skb) { |
@@ -1144,21 +1149,31 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq, | |||
1144 | spin_unlock_bh(&inputq->lock); | 1149 | spin_unlock_bh(&inputq->lock); |
1145 | continue; | 1150 | continue; |
1146 | } | 1151 | } |
1147 | hsz = skb_headroom(skb) + msg_hdr_sz(msg); | 1152 | |
1148 | oport = msg_origport(msg); | 1153 | /* Group messages require exact scope match */ |
1149 | onode = msg_orignode(msg); | 1154 | if (msg_in_group(hdr)) { |
1150 | if (onode == self) | 1155 | lower = 0; |
1151 | scope = TIPC_NODE_SCOPE; | 1156 | upper = ~0; |
1152 | 1157 | scope = msg_lookup_scope(hdr); | |
1153 | /* Create destination port list and message clones: */ | 1158 | exact = true; |
1154 | if (!msg_in_group(msg)) { | 1159 | } else { |
1155 | lower = msg_namelower(msg); | 1160 | /* TIPC_NODE_SCOPE means "any scope" in this context */ |
1156 | upper = msg_nameupper(msg); | 1161 | if (onode == self) |
1162 | scope = TIPC_NODE_SCOPE; | ||
1163 | else | ||
1164 | scope = TIPC_CLUSTER_SCOPE; | ||
1165 | exact = false; | ||
1166 | lower = msg_namelower(hdr); | ||
1167 | upper = msg_nameupper(hdr); | ||
1157 | } | 1168 | } |
1158 | tipc_nametbl_mc_translate(net, msg_nametype(msg), lower, upper, | 1169 | |
1159 | scope, &dports); | 1170 | /* Create destination port list: */ |
1171 | tipc_nametbl_mc_lookup(net, type, lower, upper, | ||
1172 | scope, exact, &dports); | ||
1173 | |||
1174 | /* Clone message per destination */ | ||
1160 | while (tipc_dest_pop(&dports, NULL, &portid)) { | 1175 | while (tipc_dest_pop(&dports, NULL, &portid)) { |
1161 | _skb = __pskb_copy(skb, hsz, GFP_ATOMIC); | 1176 | _skb = __pskb_copy(skb, hlen, GFP_ATOMIC); |
1162 | if (_skb) { | 1177 | if (_skb) { |
1163 | msg_set_destport(buf_msg(_skb), portid); | 1178 | msg_set_destport(buf_msg(_skb), portid); |
1164 | __skb_queue_tail(&tmpq, _skb); | 1179 | __skb_queue_tail(&tmpq, _skb); |
@@ -1933,8 +1948,7 @@ static void tipc_sk_proto_rcv(struct sock *sk, | |||
1933 | break; | 1948 | break; |
1934 | case TOP_SRV: | 1949 | case TOP_SRV: |
1935 | tipc_group_member_evt(tsk->group, &wakeup, &sk->sk_rcvbuf, | 1950 | tipc_group_member_evt(tsk->group, &wakeup, &sk->sk_rcvbuf, |
1936 | skb, inputq, xmitq); | 1951 | hdr, inputq, xmitq); |
1937 | skb = NULL; | ||
1938 | break; | 1952 | break; |
1939 | default: | 1953 | default: |
1940 | break; | 1954 | break; |
@@ -2640,9 +2654,7 @@ void tipc_sk_reinit(struct net *net) | |||
2640 | rhashtable_walk_enter(&tn->sk_rht, &iter); | 2654 | rhashtable_walk_enter(&tn->sk_rht, &iter); |
2641 | 2655 | ||
2642 | do { | 2656 | do { |
2643 | tsk = ERR_PTR(rhashtable_walk_start(&iter)); | 2657 | rhashtable_walk_start(&iter); |
2644 | if (IS_ERR(tsk)) | ||
2645 | goto walk_stop; | ||
2646 | 2658 | ||
2647 | while ((tsk = rhashtable_walk_next(&iter)) && !IS_ERR(tsk)) { | 2659 | while ((tsk = rhashtable_walk_next(&iter)) && !IS_ERR(tsk)) { |
2648 | spin_lock_bh(&tsk->sk.sk_lock.slock); | 2660 | spin_lock_bh(&tsk->sk.sk_lock.slock); |
@@ -2651,7 +2663,7 @@ void tipc_sk_reinit(struct net *net) | |||
2651 | msg_set_orignode(msg, tn->own_addr); | 2663 | msg_set_orignode(msg, tn->own_addr); |
2652 | spin_unlock_bh(&tsk->sk.sk_lock.slock); | 2664 | spin_unlock_bh(&tsk->sk.sk_lock.slock); |
2653 | } | 2665 | } |
2654 | walk_stop: | 2666 | |
2655 | rhashtable_walk_stop(&iter); | 2667 | rhashtable_walk_stop(&iter); |
2656 | } while (tsk == ERR_PTR(-EAGAIN)); | 2668 | } while (tsk == ERR_PTR(-EAGAIN)); |
2657 | } | 2669 | } |
@@ -2734,7 +2746,6 @@ void tipc_sk_rht_destroy(struct net *net) | |||
2734 | static int tipc_sk_join(struct tipc_sock *tsk, struct tipc_group_req *mreq) | 2746 | static int tipc_sk_join(struct tipc_sock *tsk, struct tipc_group_req *mreq) |
2735 | { | 2747 | { |
2736 | struct net *net = sock_net(&tsk->sk); | 2748 | struct net *net = sock_net(&tsk->sk); |
2737 | u32 domain = addr_domain(net, mreq->scope); | ||
2738 | struct tipc_group *grp = tsk->group; | 2749 | struct tipc_group *grp = tsk->group; |
2739 | struct tipc_msg *hdr = &tsk->phdr; | 2750 | struct tipc_msg *hdr = &tsk->phdr; |
2740 | struct tipc_name_seq seq; | 2751 | struct tipc_name_seq seq; |
@@ -2742,9 +2753,11 @@ static int tipc_sk_join(struct tipc_sock *tsk, struct tipc_group_req *mreq) | |||
2742 | 2753 | ||
2743 | if (mreq->type < TIPC_RESERVED_TYPES) | 2754 | if (mreq->type < TIPC_RESERVED_TYPES) |
2744 | return -EACCES; | 2755 | return -EACCES; |
2756 | if (mreq->scope > TIPC_NODE_SCOPE) | ||
2757 | return -EINVAL; | ||
2745 | if (grp) | 2758 | if (grp) |
2746 | return -EACCES; | 2759 | return -EACCES; |
2747 | grp = tipc_group_create(net, tsk->portid, mreq); | 2760 | grp = tipc_group_create(net, tsk->portid, mreq, &tsk->group_is_open); |
2748 | if (!grp) | 2761 | if (!grp) |
2749 | return -ENOMEM; | 2762 | return -ENOMEM; |
2750 | tsk->group = grp; | 2763 | tsk->group = grp; |
@@ -2754,16 +2767,17 @@ static int tipc_sk_join(struct tipc_sock *tsk, struct tipc_group_req *mreq) | |||
2754 | seq.type = mreq->type; | 2767 | seq.type = mreq->type; |
2755 | seq.lower = mreq->instance; | 2768 | seq.lower = mreq->instance; |
2756 | seq.upper = seq.lower; | 2769 | seq.upper = seq.lower; |
2757 | tipc_nametbl_build_group(net, grp, mreq->type, domain); | 2770 | tipc_nametbl_build_group(net, grp, mreq->type, mreq->scope); |
2758 | rc = tipc_sk_publish(tsk, mreq->scope, &seq); | 2771 | rc = tipc_sk_publish(tsk, mreq->scope, &seq); |
2759 | if (rc) { | 2772 | if (rc) { |
2760 | tipc_group_delete(net, grp); | 2773 | tipc_group_delete(net, grp); |
2761 | tsk->group = NULL; | 2774 | tsk->group = NULL; |
2775 | return rc; | ||
2762 | } | 2776 | } |
2763 | 2777 | /* Eliminate any risk that a broadcast overtakes sent JOINs */ | |
2764 | /* Eliminate any risk that a broadcast overtakes the sent JOIN */ | ||
2765 | tsk->mc_method.rcast = true; | 2778 | tsk->mc_method.rcast = true; |
2766 | tsk->mc_method.mandatory = true; | 2779 | tsk->mc_method.mandatory = true; |
2780 | tipc_group_join(net, grp, &tsk->sk.sk_rcvbuf); | ||
2767 | return rc; | 2781 | return rc; |
2768 | } | 2782 | } |
2769 | 2783 | ||