aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/socket.c
diff options
context:
space:
mode:
authorJon Maloy <jon.maloy@ericsson.com>2017-10-13 05:04:23 -0400
committerDavid S. Miller <davem@davemloft.net>2017-10-13 11:46:00 -0400
commit75da2163dbb6af9f2dce1d80056d11d290dd19a5 (patch)
tree3c38c9e2a9085c1422826e861e5252fdb42b7d40 /net/tipc/socket.c
parenta80ae5306a7346d4e52f59462878beb8362f4bbd (diff)
tipc: introduce communication groups
As a preparation for introducing flow control for multicast and datagram messaging we need a more strictly defined framework than we have now. A socket must be able keep track of exactly how many and which other sockets it is allowed to communicate with at any moment, and keep the necessary state for those. We therefore introduce a new concept we have named Communication Group. Sockets can join a group via a new setsockopt() call TIPC_GROUP_JOIN. The call takes four parameters: 'type' serves as group identifier, 'instance' serves as an logical member identifier, and 'scope' indicates the visibility of the group (node/cluster/zone). Finally, 'flags' makes it possible to set certain properties for the member. For now, there is only one flag, indicating if the creator of the socket wants to receive a copy of broadcast or multicast messages it is sending via the socket, and if wants to be eligible as destination for its own anycasts. A group is closed, i.e., sockets which have not joined a group will not be able to send messages to or receive messages from members of the group, and vice versa. Any member of a group can send multicast ('group broadcast') messages to all group members, optionally including itself, using the primitive send(). The messages are received via the recvmsg() primitive. A socket can only be member of one group at a time. Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Acked-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r--net/tipc/socket.c209
1 files changed, 182 insertions, 27 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index daf7c4df4531..64bbf9d03629 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-2016, Ericsson AB 4 * Copyright (c) 2001-2007, 2012-2017, 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 *
@@ -45,6 +45,7 @@
45#include "socket.h" 45#include "socket.h"
46#include "bcast.h" 46#include "bcast.h"
47#include "netlink.h" 47#include "netlink.h"
48#include "group.h"
48 49
49#define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */ 50#define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */
50#define CONN_PROBING_INTERVAL msecs_to_jiffies(3600000) /* [ms] => 1 h */ 51#define CONN_PROBING_INTERVAL msecs_to_jiffies(3600000) /* [ms] => 1 h */
@@ -78,7 +79,7 @@ enum {
78 * @conn_timeout: the time we can wait for an unresponded setup request 79 * @conn_timeout: the time we can wait for an unresponded setup request
79 * @dupl_rcvcnt: number of bytes counted twice, in both backlog and rcv queue 80 * @dupl_rcvcnt: number of bytes counted twice, in both backlog and rcv queue
80 * @cong_link_cnt: number of congested links 81 * @cong_link_cnt: number of congested links
81 * @sent_unacked: # messages sent by socket, and not yet acked by peer 82 * @snt_unacked: # messages sent by socket, and not yet acked by peer
82 * @rcv_unacked: # messages read by user, but not yet acked back to peer 83 * @rcv_unacked: # messages read by user, but not yet acked back to peer
83 * @peer: 'connected' peer for dgram/rdm 84 * @peer: 'connected' peer for dgram/rdm
84 * @node: hash table node 85 * @node: hash table node
@@ -109,6 +110,7 @@ struct tipc_sock {
109 struct rhash_head node; 110 struct rhash_head node;
110 struct tipc_mc_method mc_method; 111 struct tipc_mc_method mc_method;
111 struct rcu_head rcu; 112 struct rcu_head rcu;
113 struct tipc_group *group;
112}; 114};
113 115
114static int tipc_sk_backlog_rcv(struct sock *sk, struct sk_buff *skb); 116static int tipc_sk_backlog_rcv(struct sock *sk, struct sk_buff *skb);
@@ -123,6 +125,7 @@ static int tipc_sk_publish(struct tipc_sock *tsk, uint scope,
123 struct tipc_name_seq const *seq); 125 struct tipc_name_seq const *seq);
124static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope, 126static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope,
125 struct tipc_name_seq const *seq); 127 struct tipc_name_seq const *seq);
128static int tipc_sk_leave(struct tipc_sock *tsk);
126static struct tipc_sock *tipc_sk_lookup(struct net *net, u32 portid); 129static struct tipc_sock *tipc_sk_lookup(struct net *net, u32 portid);
127static int tipc_sk_insert(struct tipc_sock *tsk); 130static int tipc_sk_insert(struct tipc_sock *tsk);
128static void tipc_sk_remove(struct tipc_sock *tsk); 131static void tipc_sk_remove(struct tipc_sock *tsk);
@@ -559,6 +562,7 @@ static int tipc_release(struct socket *sock)
559 562
560 __tipc_shutdown(sock, TIPC_ERR_NO_PORT); 563 __tipc_shutdown(sock, TIPC_ERR_NO_PORT);
561 sk->sk_shutdown = SHUTDOWN_MASK; 564 sk->sk_shutdown = SHUTDOWN_MASK;
565 tipc_sk_leave(tsk);
562 tipc_sk_withdraw(tsk, 0, NULL); 566 tipc_sk_withdraw(tsk, 0, NULL);
563 sk_stop_timer(sk, &sk->sk_timer); 567 sk_stop_timer(sk, &sk->sk_timer);
564 tipc_sk_remove(tsk); 568 tipc_sk_remove(tsk);
@@ -601,7 +605,10 @@ static int tipc_bind(struct socket *sock, struct sockaddr *uaddr,
601 res = tipc_sk_withdraw(tsk, 0, NULL); 605 res = tipc_sk_withdraw(tsk, 0, NULL);
602 goto exit; 606 goto exit;
603 } 607 }
604 608 if (tsk->group) {
609 res = -EACCES;
610 goto exit;
611 }
605 if (uaddr_len < sizeof(struct sockaddr_tipc)) { 612 if (uaddr_len < sizeof(struct sockaddr_tipc)) {
606 res = -EINVAL; 613 res = -EINVAL;
607 goto exit; 614 goto exit;
@@ -698,6 +705,7 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,
698{ 705{
699 struct sock *sk = sock->sk; 706 struct sock *sk = sock->sk;
700 struct tipc_sock *tsk = tipc_sk(sk); 707 struct tipc_sock *tsk = tipc_sk(sk);
708 struct tipc_group *grp = tsk->group;
701 u32 mask = 0; 709 u32 mask = 0;
702 710
703 sock_poll_wait(file, sk_sleep(sk), wait); 711 sock_poll_wait(file, sk_sleep(sk), wait);
@@ -718,8 +726,9 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,
718 mask |= (POLLIN | POLLRDNORM); 726 mask |= (POLLIN | POLLRDNORM);
719 break; 727 break;
720 case TIPC_OPEN: 728 case TIPC_OPEN:
721 if (!tsk->cong_link_cnt) 729 if (!grp || tipc_group_size(grp))
722 mask |= POLLOUT; 730 if (!tsk->cong_link_cnt)
731 mask |= POLLOUT;
723 if (tipc_sk_type_connectionless(sk) && 732 if (tipc_sk_type_connectionless(sk) &&
724 (!skb_queue_empty(&sk->sk_receive_queue))) 733 (!skb_queue_empty(&sk->sk_receive_queue)))
725 mask |= (POLLIN | POLLRDNORM); 734 mask |= (POLLIN | POLLRDNORM);
@@ -757,6 +766,9 @@ static int tipc_sendmcast(struct socket *sock, struct tipc_name_seq *seq,
757 struct tipc_nlist dsts; 766 struct tipc_nlist dsts;
758 int rc; 767 int rc;
759 768
769 if (tsk->group)
770 return -EACCES;
771
760 /* Block or return if any destination link is congested */ 772 /* Block or return if any destination link is congested */
761 rc = tipc_wait_for_cond(sock, &timeout, !tsk->cong_link_cnt); 773 rc = tipc_wait_for_cond(sock, &timeout, !tsk->cong_link_cnt);
762 if (unlikely(rc)) 774 if (unlikely(rc))
@@ -794,6 +806,64 @@ static int tipc_sendmcast(struct socket *sock, struct tipc_name_seq *seq,
794} 806}
795 807
796/** 808/**
809 * tipc_send_group_bcast - send message to all members in communication group
810 * @sk: socket structure
811 * @m: message to send
812 * @dlen: total length of message data
813 * @timeout: timeout to wait for wakeup
814 *
815 * Called from function tipc_sendmsg(), which has done all sanity checks
816 * Returns the number of bytes sent on success, or errno
817 */
818static int tipc_send_group_bcast(struct socket *sock, struct msghdr *m,
819 int dlen, long timeout)
820{
821 struct sock *sk = sock->sk;
822 struct net *net = sock_net(sk);
823 struct tipc_sock *tsk = tipc_sk(sk);
824 struct tipc_group *grp = tsk->group;
825 struct tipc_nlist *dsts = tipc_group_dests(grp);
826 struct tipc_mc_method *method = &tsk->mc_method;
827 struct tipc_msg *hdr = &tsk->phdr;
828 int mtu = tipc_bcast_get_mtu(net);
829 struct sk_buff_head pkts;
830 int rc = -EHOSTUNREACH;
831
832 if (!dsts->local && !dsts->remote)
833 return -EHOSTUNREACH;
834
835 /* Block or return if any destination link is congested */
836 rc = tipc_wait_for_cond(sock, &timeout, !tsk->cong_link_cnt);
837 if (unlikely(rc))
838 return rc;
839
840 /* Complete message header */
841 msg_set_type(hdr, TIPC_GRP_BCAST_MSG);
842 msg_set_hdr_sz(hdr, MCAST_H_SIZE);
843 msg_set_destport(hdr, 0);
844 msg_set_destnode(hdr, 0);
845 msg_set_nameinst(hdr, 0);
846 msg_set_grp_bc_seqno(hdr, tipc_group_bc_snd_nxt(grp));
847
848 /* Build message as chain of buffers */
849 skb_queue_head_init(&pkts);
850 rc = tipc_msg_build(hdr, m, 0, dlen, mtu, &pkts);
851 if (unlikely(rc != dlen))
852 return rc;
853
854 /* Send message */
855 rc = tipc_mcast_xmit(net, &pkts, method, dsts,
856 &tsk->cong_link_cnt);
857 if (unlikely(rc))
858 return rc;
859
860 /* Update broadcast sequence number */
861 tipc_group_update_bc_members(tsk->group);
862
863 return dlen;
864}
865
866/**
797 * tipc_sk_mcast_rcv - Deliver multicast messages to all destination sockets 867 * tipc_sk_mcast_rcv - Deliver multicast messages to all destination sockets
798 * @arrvq: queue with arriving messages, to be cloned after destination lookup 868 * @arrvq: queue with arriving messages, to be cloned after destination lookup
799 * @inputq: queue with cloned messages, delivered to socket after dest lookup 869 * @inputq: queue with cloned messages, delivered to socket after dest lookup
@@ -803,13 +873,15 @@ static int tipc_sendmcast(struct socket *sock, struct tipc_name_seq *seq,
803void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq, 873void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq,
804 struct sk_buff_head *inputq) 874 struct sk_buff_head *inputq)
805{ 875{
806 struct tipc_msg *msg;
807 struct list_head dports;
808 u32 portid;
809 u32 scope = TIPC_CLUSTER_SCOPE; 876 u32 scope = TIPC_CLUSTER_SCOPE;
810 struct sk_buff_head tmpq; 877 u32 self = tipc_own_addr(net);
811 uint hsz;
812 struct sk_buff *skb, *_skb; 878 struct sk_buff *skb, *_skb;
879 u32 lower = 0, upper = ~0;
880 struct sk_buff_head tmpq;
881 u32 portid, oport, onode;
882 struct list_head dports;
883 struct tipc_msg *msg;
884 int hsz;
813 885
814 __skb_queue_head_init(&tmpq); 886 __skb_queue_head_init(&tmpq);
815 INIT_LIST_HEAD(&dports); 887 INIT_LIST_HEAD(&dports);
@@ -818,14 +890,18 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq,
818 for (; skb; skb = tipc_skb_peek(arrvq, &inputq->lock)) { 890 for (; skb; skb = tipc_skb_peek(arrvq, &inputq->lock)) {
819 msg = buf_msg(skb); 891 msg = buf_msg(skb);
820 hsz = skb_headroom(skb) + msg_hdr_sz(msg); 892 hsz = skb_headroom(skb) + msg_hdr_sz(msg);
821 893 oport = msg_origport(msg);
822 if (in_own_node(net, msg_orignode(msg))) 894 onode = msg_orignode(msg);
895 if (onode == self)
823 scope = TIPC_NODE_SCOPE; 896 scope = TIPC_NODE_SCOPE;
824 897
825 /* Create destination port list and message clones: */ 898 /* Create destination port list and message clones: */
826 tipc_nametbl_mc_translate(net, 899 if (!msg_in_group(msg)) {
827 msg_nametype(msg), msg_namelower(msg), 900 lower = msg_namelower(msg);
828 msg_nameupper(msg), scope, &dports); 901 upper = msg_nameupper(msg);
902 }
903 tipc_nametbl_mc_translate(net, msg_nametype(msg), lower, upper,
904 scope, &dports);
829 while (tipc_dest_pop(&dports, NULL, &portid)) { 905 while (tipc_dest_pop(&dports, NULL, &portid)) {
830 _skb = __pskb_copy(skb, hsz, GFP_ATOMIC); 906 _skb = __pskb_copy(skb, hsz, GFP_ATOMIC);
831 if (_skb) { 907 if (_skb) {
@@ -895,10 +971,6 @@ exit:
895 kfree_skb(skb); 971 kfree_skb(skb);
896} 972}
897 973
898static void tipc_sk_top_evt(struct tipc_sock *tsk, struct tipc_event *evt)
899{
900}
901
902/** 974/**
903 * tipc_sendmsg - send message in connectionless manner 975 * tipc_sendmsg - send message in connectionless manner
904 * @sock: socket structure 976 * @sock: socket structure
@@ -934,6 +1006,7 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen)
934 long timeout = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); 1006 long timeout = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
935 struct list_head *clinks = &tsk->cong_links; 1007 struct list_head *clinks = &tsk->cong_links;
936 bool syn = !tipc_sk_type_connectionless(sk); 1008 bool syn = !tipc_sk_type_connectionless(sk);
1009 struct tipc_group *grp = tsk->group;
937 struct tipc_msg *hdr = &tsk->phdr; 1010 struct tipc_msg *hdr = &tsk->phdr;
938 struct tipc_name_seq *seq; 1011 struct tipc_name_seq *seq;
939 struct sk_buff_head pkts; 1012 struct sk_buff_head pkts;
@@ -944,6 +1017,9 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen)
944 if (unlikely(dlen > TIPC_MAX_USER_MSG_SIZE)) 1017 if (unlikely(dlen > TIPC_MAX_USER_MSG_SIZE))
945 return -EMSGSIZE; 1018 return -EMSGSIZE;
946 1019
1020 if (unlikely(grp))
1021 return tipc_send_group_bcast(sock, m, dlen, timeout);
1022
947 if (unlikely(!dest)) { 1023 if (unlikely(!dest)) {
948 dest = &tsk->peer; 1024 dest = &tsk->peer;
949 if (!syn || dest->family != AF_TIPC) 1025 if (!syn || dest->family != AF_TIPC)
@@ -1543,6 +1619,7 @@ static void tipc_sk_proto_rcv(struct sock *sk,
1543 struct sk_buff *skb = __skb_dequeue(inputq); 1619 struct sk_buff *skb = __skb_dequeue(inputq);
1544 struct tipc_sock *tsk = tipc_sk(sk); 1620 struct tipc_sock *tsk = tipc_sk(sk);
1545 struct tipc_msg *hdr = buf_msg(skb); 1621 struct tipc_msg *hdr = buf_msg(skb);
1622 struct tipc_group *grp = tsk->group;
1546 1623
1547 switch (msg_user(hdr)) { 1624 switch (msg_user(hdr)) {
1548 case CONN_MANAGER: 1625 case CONN_MANAGER:
@@ -1553,8 +1630,12 @@ static void tipc_sk_proto_rcv(struct sock *sk,
1553 tsk->cong_link_cnt--; 1630 tsk->cong_link_cnt--;
1554 sk->sk_write_space(sk); 1631 sk->sk_write_space(sk);
1555 break; 1632 break;
1633 case GROUP_PROTOCOL:
1634 tipc_group_proto_rcv(grp, hdr, xmitq);
1635 break;
1556 case TOP_SRV: 1636 case TOP_SRV:
1557 tipc_sk_top_evt(tsk, (void *)msg_data(hdr)); 1637 tipc_group_member_evt(tsk->group, skb, xmitq);
1638 skb = NULL;
1558 break; 1639 break;
1559 default: 1640 default:
1560 break; 1641 break;
@@ -1699,6 +1780,7 @@ static void tipc_sk_filter_rcv(struct sock *sk, struct sk_buff *skb,
1699{ 1780{
1700 bool sk_conn = !tipc_sk_type_connectionless(sk); 1781 bool sk_conn = !tipc_sk_type_connectionless(sk);
1701 struct tipc_sock *tsk = tipc_sk(sk); 1782 struct tipc_sock *tsk = tipc_sk(sk);
1783 struct tipc_group *grp = tsk->group;
1702 struct tipc_msg *hdr = buf_msg(skb); 1784 struct tipc_msg *hdr = buf_msg(skb);
1703 struct net *net = sock_net(sk); 1785 struct net *net = sock_net(sk);
1704 struct sk_buff_head inputq; 1786 struct sk_buff_head inputq;
@@ -1710,15 +1792,19 @@ static void tipc_sk_filter_rcv(struct sock *sk, struct sk_buff *skb,
1710 1792
1711 if (unlikely(!msg_isdata(hdr))) 1793 if (unlikely(!msg_isdata(hdr)))
1712 tipc_sk_proto_rcv(sk, &inputq, xmitq); 1794 tipc_sk_proto_rcv(sk, &inputq, xmitq);
1713 else if (unlikely(msg_type(hdr) > TIPC_DIRECT_MSG)) 1795 else if (unlikely(msg_type(hdr) > TIPC_GRP_BCAST_MSG))
1714 return kfree_skb(skb); 1796 return kfree_skb(skb);
1715 1797
1798 if (unlikely(grp))
1799 tipc_group_filter_msg(grp, &inputq, xmitq);
1800
1716 /* Validate and add to receive buffer if there is space */ 1801 /* Validate and add to receive buffer if there is space */
1717 while ((skb = __skb_dequeue(&inputq))) { 1802 while ((skb = __skb_dequeue(&inputq))) {
1718 hdr = buf_msg(skb); 1803 hdr = buf_msg(skb);
1719 limit = rcvbuf_limit(sk, skb); 1804 limit = rcvbuf_limit(sk, skb);
1720 if ((sk_conn && !tipc_sk_filter_connect(tsk, skb)) || 1805 if ((sk_conn && !tipc_sk_filter_connect(tsk, skb)) ||
1721 (!sk_conn && msg_connected(hdr))) 1806 (!sk_conn && msg_connected(hdr)) ||
1807 (!grp && msg_in_group(hdr)))
1722 err = TIPC_ERR_NO_PORT; 1808 err = TIPC_ERR_NO_PORT;
1723 else if (sk_rmem_alloc_get(sk) + skb->truesize >= limit) 1809 else if (sk_rmem_alloc_get(sk) + skb->truesize >= limit)
1724 err = TIPC_ERR_OVERLOAD; 1810 err = TIPC_ERR_OVERLOAD;
@@ -1837,7 +1923,6 @@ void tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq)
1837 sock_put(sk); 1923 sock_put(sk);
1838 continue; 1924 continue;
1839 } 1925 }
1840
1841 /* No destination socket => dequeue skb if still there */ 1926 /* No destination socket => dequeue skb if still there */
1842 skb = tipc_skb_dequeue(inputq, dport); 1927 skb = tipc_skb_dequeue(inputq, dport);
1843 if (!skb) 1928 if (!skb)
@@ -1905,6 +1990,11 @@ static int tipc_connect(struct socket *sock, struct sockaddr *dest,
1905 1990
1906 lock_sock(sk); 1991 lock_sock(sk);
1907 1992
1993 if (tsk->group) {
1994 res = -EINVAL;
1995 goto exit;
1996 }
1997
1908 if (dst->family == AF_UNSPEC) { 1998 if (dst->family == AF_UNSPEC) {
1909 memset(&tsk->peer, 0, sizeof(struct sockaddr_tipc)); 1999 memset(&tsk->peer, 0, sizeof(struct sockaddr_tipc));
1910 if (!tipc_sk_type_connectionless(sk)) 2000 if (!tipc_sk_type_connectionless(sk))
@@ -2341,6 +2431,52 @@ void tipc_sk_rht_destroy(struct net *net)
2341 rhashtable_destroy(&tn->sk_rht); 2431 rhashtable_destroy(&tn->sk_rht);
2342} 2432}
2343 2433
2434static int tipc_sk_join(struct tipc_sock *tsk, struct tipc_group_req *mreq)
2435{
2436 struct net *net = sock_net(&tsk->sk);
2437 u32 domain = addr_domain(net, mreq->scope);
2438 struct tipc_group *grp = tsk->group;
2439 struct tipc_msg *hdr = &tsk->phdr;
2440 struct tipc_name_seq seq;
2441 int rc;
2442
2443 if (mreq->type < TIPC_RESERVED_TYPES)
2444 return -EACCES;
2445 if (grp)
2446 return -EACCES;
2447 grp = tipc_group_create(net, tsk->portid, mreq);
2448 if (!grp)
2449 return -ENOMEM;
2450 tsk->group = grp;
2451 msg_set_lookup_scope(hdr, mreq->scope);
2452 msg_set_nametype(hdr, mreq->type);
2453 msg_set_dest_droppable(hdr, true);
2454 seq.type = mreq->type;
2455 seq.lower = mreq->instance;
2456 seq.upper = seq.lower;
2457 tipc_nametbl_build_group(net, grp, mreq->type, domain);
2458 rc = tipc_sk_publish(tsk, mreq->scope, &seq);
2459 if (rc)
2460 tipc_group_delete(net, grp);
2461 return rc;
2462}
2463
2464static int tipc_sk_leave(struct tipc_sock *tsk)
2465{
2466 struct net *net = sock_net(&tsk->sk);
2467 struct tipc_group *grp = tsk->group;
2468 struct tipc_name_seq seq;
2469 int scope;
2470
2471 if (!grp)
2472 return -EINVAL;
2473 tipc_group_self(grp, &seq, &scope);
2474 tipc_group_delete(net, grp);
2475 tsk->group = NULL;
2476 tipc_sk_withdraw(tsk, scope, &seq);
2477 return 0;
2478}
2479
2344/** 2480/**
2345 * tipc_setsockopt - set socket option 2481 * tipc_setsockopt - set socket option
2346 * @sock: socket structure 2482 * @sock: socket structure
@@ -2359,6 +2495,7 @@ static int tipc_setsockopt(struct socket *sock, int lvl, int opt,
2359{ 2495{
2360 struct sock *sk = sock->sk; 2496 struct sock *sk = sock->sk;
2361 struct tipc_sock *tsk = tipc_sk(sk); 2497 struct tipc_sock *tsk = tipc_sk(sk);
2498 struct tipc_group_req mreq;
2362 u32 value = 0; 2499 u32 value = 0;
2363 int res = 0; 2500 int res = 0;
2364 2501
@@ -2374,9 +2511,14 @@ static int tipc_setsockopt(struct socket *sock, int lvl, int opt,
2374 case TIPC_CONN_TIMEOUT: 2511 case TIPC_CONN_TIMEOUT:
2375 if (ol < sizeof(value)) 2512 if (ol < sizeof(value))
2376 return -EINVAL; 2513 return -EINVAL;
2377 res = get_user(value, (u32 __user *)ov); 2514 if (get_user(value, (u32 __user *)ov))
2378 if (res) 2515 return -EFAULT;
2379 return res; 2516 break;
2517 case TIPC_GROUP_JOIN:
2518 if (ol < sizeof(mreq))
2519 return -EINVAL;
2520 if (copy_from_user(&mreq, ov, sizeof(mreq)))
2521 return -EFAULT;
2380 break; 2522 break;
2381 default: 2523 default:
2382 if (ov || ol) 2524 if (ov || ol)
@@ -2409,6 +2551,12 @@ static int tipc_setsockopt(struct socket *sock, int lvl, int opt,
2409 tsk->mc_method.rcast = true; 2551 tsk->mc_method.rcast = true;
2410 tsk->mc_method.mandatory = true; 2552 tsk->mc_method.mandatory = true;
2411 break; 2553 break;
2554 case TIPC_GROUP_JOIN:
2555 res = tipc_sk_join(tsk, &mreq);
2556 break;
2557 case TIPC_GROUP_LEAVE:
2558 res = tipc_sk_leave(tsk);
2559 break;
2412 default: 2560 default:
2413 res = -EINVAL; 2561 res = -EINVAL;
2414 } 2562 }
@@ -2436,7 +2584,8 @@ static int tipc_getsockopt(struct socket *sock, int lvl, int opt,
2436{ 2584{
2437 struct sock *sk = sock->sk; 2585 struct sock *sk = sock->sk;
2438 struct tipc_sock *tsk = tipc_sk(sk); 2586 struct tipc_sock *tsk = tipc_sk(sk);
2439 int len; 2587 struct tipc_name_seq seq;
2588 int len, scope;
2440 u32 value; 2589 u32 value;
2441 int res; 2590 int res;
2442 2591
@@ -2470,6 +2619,12 @@ static int tipc_getsockopt(struct socket *sock, int lvl, int opt,
2470 case TIPC_SOCK_RECVQ_DEPTH: 2619 case TIPC_SOCK_RECVQ_DEPTH:
2471 value = skb_queue_len(&sk->sk_receive_queue); 2620 value = skb_queue_len(&sk->sk_receive_queue);
2472 break; 2621 break;
2622 case TIPC_GROUP_JOIN:
2623 seq.type = 0;
2624 if (tsk->group)
2625 tipc_group_self(tsk->group, &seq, &scope);
2626 value = seq.type;
2627 break;
2473 default: 2628 default:
2474 res = -EINVAL; 2629 res = -EINVAL;
2475 } 2630 }