diff options
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r-- | net/tipc/socket.c | 88 |
1 files changed, 53 insertions, 35 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index e3a02f1fcab5..b24dab3996c9 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -928,21 +928,22 @@ static int tipc_send_group_anycast(struct socket *sock, struct msghdr *m, | |||
928 | struct list_head *cong_links = &tsk->cong_links; | 928 | struct list_head *cong_links = &tsk->cong_links; |
929 | int blks = tsk_blocks(GROUP_H_SIZE + dlen); | 929 | int blks = tsk_blocks(GROUP_H_SIZE + dlen); |
930 | struct tipc_group *grp = tsk->group; | 930 | struct tipc_group *grp = tsk->group; |
931 | struct tipc_msg *hdr = &tsk->phdr; | ||
931 | struct tipc_member *first = NULL; | 932 | struct tipc_member *first = NULL; |
932 | struct tipc_member *mbr = NULL; | 933 | struct tipc_member *mbr = NULL; |
933 | struct net *net = sock_net(sk); | 934 | struct net *net = sock_net(sk); |
934 | u32 node, port, exclude; | 935 | u32 node, port, exclude; |
935 | u32 type, inst, domain; | ||
936 | struct list_head dsts; | 936 | struct list_head dsts; |
937 | u32 type, inst, scope; | ||
937 | int lookups = 0; | 938 | int lookups = 0; |
938 | int dstcnt, rc; | 939 | int dstcnt, rc; |
939 | bool cong; | 940 | bool cong; |
940 | 941 | ||
941 | INIT_LIST_HEAD(&dsts); | 942 | INIT_LIST_HEAD(&dsts); |
942 | 943 | ||
943 | type = dest->addr.name.name.type; | 944 | type = msg_nametype(hdr); |
944 | inst = dest->addr.name.name.instance; | 945 | inst = dest->addr.name.name.instance; |
945 | domain = addr_domain(net, dest->scope); | 946 | scope = msg_lookup_scope(hdr); |
946 | exclude = tipc_group_exclude(grp); | 947 | exclude = tipc_group_exclude(grp); |
947 | 948 | ||
948 | while (++lookups < 4) { | 949 | while (++lookups < 4) { |
@@ -950,7 +951,7 @@ static int tipc_send_group_anycast(struct socket *sock, struct msghdr *m, | |||
950 | 951 | ||
951 | /* Look for a non-congested destination member, if any */ | 952 | /* Look for a non-congested destination member, if any */ |
952 | while (1) { | 953 | while (1) { |
953 | if (!tipc_nametbl_lookup(net, type, inst, domain, &dsts, | 954 | if (!tipc_nametbl_lookup(net, type, inst, scope, &dsts, |
954 | &dstcnt, exclude, false)) | 955 | &dstcnt, exclude, false)) |
955 | return -EHOSTUNREACH; | 956 | return -EHOSTUNREACH; |
956 | tipc_dest_pop(&dsts, &node, &port); | 957 | tipc_dest_pop(&dsts, &node, &port); |
@@ -1079,22 +1080,23 @@ static int tipc_send_group_mcast(struct socket *sock, struct msghdr *m, | |||
1079 | { | 1080 | { |
1080 | struct sock *sk = sock->sk; | 1081 | struct sock *sk = sock->sk; |
1081 | DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); | 1082 | 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); | 1083 | struct tipc_sock *tsk = tipc_sk(sk); |
1084 | struct tipc_group *grp = tsk->group; | 1084 | struct tipc_group *grp = tsk->group; |
1085 | struct tipc_msg *hdr = &tsk->phdr; | ||
1085 | struct net *net = sock_net(sk); | 1086 | struct net *net = sock_net(sk); |
1086 | u32 domain, exclude, dstcnt; | 1087 | u32 type, inst, scope, exclude; |
1087 | struct list_head dsts; | 1088 | struct list_head dsts; |
1089 | u32 dstcnt; | ||
1088 | 1090 | ||
1089 | INIT_LIST_HEAD(&dsts); | 1091 | INIT_LIST_HEAD(&dsts); |
1090 | 1092 | ||
1091 | if (seq->lower != seq->upper) | 1093 | type = msg_nametype(hdr); |
1092 | return -ENOTSUPP; | 1094 | inst = dest->addr.name.name.instance; |
1093 | 1095 | scope = msg_lookup_scope(hdr); | |
1094 | domain = addr_domain(net, dest->scope); | ||
1095 | exclude = tipc_group_exclude(grp); | 1096 | exclude = tipc_group_exclude(grp); |
1096 | if (!tipc_nametbl_lookup(net, seq->type, seq->lower, domain, | 1097 | |
1097 | &dsts, &dstcnt, exclude, true)) | 1098 | if (!tipc_nametbl_lookup(net, type, inst, scope, &dsts, |
1099 | &dstcnt, exclude, true)) | ||
1098 | return -EHOSTUNREACH; | 1100 | return -EHOSTUNREACH; |
1099 | 1101 | ||
1100 | if (dstcnt == 1) { | 1102 | if (dstcnt == 1) { |
@@ -1116,24 +1118,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, | 1118 | void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq, |
1117 | struct sk_buff_head *inputq) | 1119 | struct sk_buff_head *inputq) |
1118 | { | 1120 | { |
1119 | u32 scope = TIPC_CLUSTER_SCOPE; | ||
1120 | u32 self = tipc_own_addr(net); | 1121 | u32 self = tipc_own_addr(net); |
1122 | u32 type, lower, upper, scope; | ||
1121 | struct sk_buff *skb, *_skb; | 1123 | struct sk_buff *skb, *_skb; |
1122 | u32 lower = 0, upper = ~0; | ||
1123 | struct sk_buff_head tmpq; | ||
1124 | u32 portid, oport, onode; | 1124 | u32 portid, oport, onode; |
1125 | struct sk_buff_head tmpq; | ||
1125 | struct list_head dports; | 1126 | struct list_head dports; |
1126 | struct tipc_msg *msg; | 1127 | struct tipc_msg *hdr; |
1127 | int user, mtyp, hsz; | 1128 | int user, mtyp, hlen; |
1129 | bool exact; | ||
1128 | 1130 | ||
1129 | __skb_queue_head_init(&tmpq); | 1131 | __skb_queue_head_init(&tmpq); |
1130 | INIT_LIST_HEAD(&dports); | 1132 | INIT_LIST_HEAD(&dports); |
1131 | 1133 | ||
1132 | skb = tipc_skb_peek(arrvq, &inputq->lock); | 1134 | skb = tipc_skb_peek(arrvq, &inputq->lock); |
1133 | for (; skb; skb = tipc_skb_peek(arrvq, &inputq->lock)) { | 1135 | for (; skb; skb = tipc_skb_peek(arrvq, &inputq->lock)) { |
1134 | msg = buf_msg(skb); | 1136 | hdr = buf_msg(skb); |
1135 | user = msg_user(msg); | 1137 | user = msg_user(hdr); |
1136 | mtyp = msg_type(msg); | 1138 | mtyp = msg_type(hdr); |
1139 | hlen = skb_headroom(skb) + msg_hdr_sz(hdr); | ||
1140 | oport = msg_origport(hdr); | ||
1141 | onode = msg_orignode(hdr); | ||
1142 | type = msg_nametype(hdr); | ||
1143 | |||
1137 | if (mtyp == TIPC_GRP_UCAST_MSG || user == GROUP_PROTOCOL) { | 1144 | if (mtyp == TIPC_GRP_UCAST_MSG || user == GROUP_PROTOCOL) { |
1138 | spin_lock_bh(&inputq->lock); | 1145 | spin_lock_bh(&inputq->lock); |
1139 | if (skb_peek(arrvq) == skb) { | 1146 | if (skb_peek(arrvq) == skb) { |
@@ -1144,21 +1151,31 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq, | |||
1144 | spin_unlock_bh(&inputq->lock); | 1151 | spin_unlock_bh(&inputq->lock); |
1145 | continue; | 1152 | continue; |
1146 | } | 1153 | } |
1147 | hsz = skb_headroom(skb) + msg_hdr_sz(msg); | 1154 | |
1148 | oport = msg_origport(msg); | 1155 | /* Group messages require exact scope match */ |
1149 | onode = msg_orignode(msg); | 1156 | if (msg_in_group(hdr)) { |
1150 | if (onode == self) | 1157 | lower = 0; |
1151 | scope = TIPC_NODE_SCOPE; | 1158 | upper = ~0; |
1152 | 1159 | scope = msg_lookup_scope(hdr); | |
1153 | /* Create destination port list and message clones: */ | 1160 | exact = true; |
1154 | if (!msg_in_group(msg)) { | 1161 | } else { |
1155 | lower = msg_namelower(msg); | 1162 | /* TIPC_NODE_SCOPE means "any scope" in this context */ |
1156 | upper = msg_nameupper(msg); | 1163 | if (onode == self) |
1164 | scope = TIPC_NODE_SCOPE; | ||
1165 | else | ||
1166 | scope = TIPC_CLUSTER_SCOPE; | ||
1167 | exact = false; | ||
1168 | lower = msg_namelower(hdr); | ||
1169 | upper = msg_nameupper(hdr); | ||
1157 | } | 1170 | } |
1158 | tipc_nametbl_mc_translate(net, msg_nametype(msg), lower, upper, | 1171 | |
1159 | scope, &dports); | 1172 | /* Create destination port list: */ |
1173 | tipc_nametbl_mc_lookup(net, type, lower, upper, | ||
1174 | scope, exact, &dports); | ||
1175 | |||
1176 | /* Clone message per destination */ | ||
1160 | while (tipc_dest_pop(&dports, NULL, &portid)) { | 1177 | while (tipc_dest_pop(&dports, NULL, &portid)) { |
1161 | _skb = __pskb_copy(skb, hsz, GFP_ATOMIC); | 1178 | _skb = __pskb_copy(skb, hlen, GFP_ATOMIC); |
1162 | if (_skb) { | 1179 | if (_skb) { |
1163 | msg_set_destport(buf_msg(_skb), portid); | 1180 | msg_set_destport(buf_msg(_skb), portid); |
1164 | __skb_queue_tail(&tmpq, _skb); | 1181 | __skb_queue_tail(&tmpq, _skb); |
@@ -2731,7 +2748,6 @@ void tipc_sk_rht_destroy(struct net *net) | |||
2731 | static int tipc_sk_join(struct tipc_sock *tsk, struct tipc_group_req *mreq) | 2748 | static int tipc_sk_join(struct tipc_sock *tsk, struct tipc_group_req *mreq) |
2732 | { | 2749 | { |
2733 | struct net *net = sock_net(&tsk->sk); | 2750 | struct net *net = sock_net(&tsk->sk); |
2734 | u32 domain = addr_domain(net, mreq->scope); | ||
2735 | struct tipc_group *grp = tsk->group; | 2751 | struct tipc_group *grp = tsk->group; |
2736 | struct tipc_msg *hdr = &tsk->phdr; | 2752 | struct tipc_msg *hdr = &tsk->phdr; |
2737 | struct tipc_name_seq seq; | 2753 | struct tipc_name_seq seq; |
@@ -2739,6 +2755,8 @@ static int tipc_sk_join(struct tipc_sock *tsk, struct tipc_group_req *mreq) | |||
2739 | 2755 | ||
2740 | if (mreq->type < TIPC_RESERVED_TYPES) | 2756 | if (mreq->type < TIPC_RESERVED_TYPES) |
2741 | return -EACCES; | 2757 | return -EACCES; |
2758 | if (mreq->scope > TIPC_NODE_SCOPE) | ||
2759 | return -EINVAL; | ||
2742 | if (grp) | 2760 | if (grp) |
2743 | return -EACCES; | 2761 | return -EACCES; |
2744 | grp = tipc_group_create(net, tsk->portid, mreq); | 2762 | grp = tipc_group_create(net, tsk->portid, mreq); |
@@ -2751,7 +2769,7 @@ static int tipc_sk_join(struct tipc_sock *tsk, struct tipc_group_req *mreq) | |||
2751 | seq.type = mreq->type; | 2769 | seq.type = mreq->type; |
2752 | seq.lower = mreq->instance; | 2770 | seq.lower = mreq->instance; |
2753 | seq.upper = seq.lower; | 2771 | seq.upper = seq.lower; |
2754 | tipc_nametbl_build_group(net, grp, mreq->type, domain); | 2772 | tipc_nametbl_build_group(net, grp, mreq->type, mreq->scope); |
2755 | rc = tipc_sk_publish(tsk, mreq->scope, &seq); | 2773 | rc = tipc_sk_publish(tsk, mreq->scope, &seq); |
2756 | if (rc) { | 2774 | if (rc) { |
2757 | tipc_group_delete(net, grp); | 2775 | tipc_group_delete(net, grp); |