aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlink/af_netlink.c
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2005-08-14 22:27:50 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 19:00:49 -0400
commitd629b836d151d43332492651dd841d32e57ebe3b (patch)
tree0276547438963b51b8d92df201e91d867c7fa9c0 /net/netlink/af_netlink.c
parent77247bbb3094246be9d057e7be442cc708f123a8 (diff)
[NETLINK]: Use group numbers instead of bitmasks internally
Using the group number allows increasing the number of groups without beeing limited by the size of the bitmask. It introduces one limitation for netlink users: messages can't be broadcasted to multiple groups anymore, however this feature was never used inside the kernel. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netlink/af_netlink.c')
-rw-r--r--net/netlink/af_netlink.c35
1 files changed, 20 insertions, 15 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index c41a88100fea..3c56b96b4a4b 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -67,7 +67,7 @@ struct netlink_sock {
67 u32 pid; 67 u32 pid;
68 unsigned int groups; 68 unsigned int groups;
69 u32 dst_pid; 69 u32 dst_pid;
70 unsigned int dst_groups; 70 u32 dst_group;
71 unsigned long state; 71 unsigned long state;
72 wait_queue_head_t wait; 72 wait_queue_head_t wait;
73 struct netlink_callback *cb; 73 struct netlink_callback *cb;
@@ -116,6 +116,11 @@ static atomic_t nl_table_users = ATOMIC_INIT(0);
116 116
117static struct notifier_block *netlink_chain; 117static struct notifier_block *netlink_chain;
118 118
119static u32 netlink_group_mask(u32 group)
120{
121 return group ? 1 << (group - 1) : 0;
122}
123
119static struct hlist_head *nl_pid_hashfn(struct nl_pid_hash *hash, u32 pid) 124static struct hlist_head *nl_pid_hashfn(struct nl_pid_hash *hash, u32 pid)
120{ 125{
121 return &hash->table[jhash_1word(pid, hash->rnd) & hash->mask]; 126 return &hash->table[jhash_1word(pid, hash->rnd) & hash->mask];
@@ -533,7 +538,7 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr,
533 if (addr->sa_family == AF_UNSPEC) { 538 if (addr->sa_family == AF_UNSPEC) {
534 sk->sk_state = NETLINK_UNCONNECTED; 539 sk->sk_state = NETLINK_UNCONNECTED;
535 nlk->dst_pid = 0; 540 nlk->dst_pid = 0;
536 nlk->dst_groups = 0; 541 nlk->dst_group = 0;
537 return 0; 542 return 0;
538 } 543 }
539 if (addr->sa_family != AF_NETLINK) 544 if (addr->sa_family != AF_NETLINK)
@@ -549,7 +554,7 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr,
549 if (err == 0) { 554 if (err == 0) {
550 sk->sk_state = NETLINK_CONNECTED; 555 sk->sk_state = NETLINK_CONNECTED;
551 nlk->dst_pid = nladdr->nl_pid; 556 nlk->dst_pid = nladdr->nl_pid;
552 nlk->dst_groups = nladdr->nl_groups; 557 nlk->dst_group = ffs(nladdr->nl_groups);
553 } 558 }
554 559
555 return err; 560 return err;
@@ -567,10 +572,10 @@ static int netlink_getname(struct socket *sock, struct sockaddr *addr, int *addr
567 572
568 if (peer) { 573 if (peer) {
569 nladdr->nl_pid = nlk->dst_pid; 574 nladdr->nl_pid = nlk->dst_pid;
570 nladdr->nl_groups = nlk->dst_groups; 575 nladdr->nl_groups = netlink_group_mask(nlk->dst_group);
571 } else { 576 } else {
572 nladdr->nl_pid = nlk->pid; 577 nladdr->nl_pid = nlk->pid;
573 nladdr->nl_groups = nlk->groups; 578 nladdr->nl_groups = nlk->groups;
574 } 579 }
575 return 0; 580 return 0;
576} 581}
@@ -771,7 +776,7 @@ static inline int do_one_broadcast(struct sock *sk,
771 if (p->exclude_sk == sk) 776 if (p->exclude_sk == sk)
772 goto out; 777 goto out;
773 778
774 if (nlk->pid == p->pid || !(nlk->groups & p->group)) 779 if (nlk->pid == p->pid || !(nlk->groups & netlink_group_mask(p->group)))
775 goto out; 780 goto out;
776 781
777 if (p->failure) { 782 if (p->failure) {
@@ -867,7 +872,7 @@ static inline int do_one_set_err(struct sock *sk,
867 if (sk == p->exclude_sk) 872 if (sk == p->exclude_sk)
868 goto out; 873 goto out;
869 874
870 if (nlk->pid == p->pid || !(nlk->groups & p->group)) 875 if (nlk->pid == p->pid || !(nlk->groups & netlink_group_mask(p->group)))
871 goto out; 876 goto out;
872 877
873 sk->sk_err = p->code; 878 sk->sk_err = p->code;
@@ -913,7 +918,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
913 struct netlink_sock *nlk = nlk_sk(sk); 918 struct netlink_sock *nlk = nlk_sk(sk);
914 struct sockaddr_nl *addr=msg->msg_name; 919 struct sockaddr_nl *addr=msg->msg_name;
915 u32 dst_pid; 920 u32 dst_pid;
916 u32 dst_groups; 921 u32 dst_group;
917 struct sk_buff *skb; 922 struct sk_buff *skb;
918 int err; 923 int err;
919 struct scm_cookie scm; 924 struct scm_cookie scm;
@@ -931,12 +936,12 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
931 if (addr->nl_family != AF_NETLINK) 936 if (addr->nl_family != AF_NETLINK)
932 return -EINVAL; 937 return -EINVAL;
933 dst_pid = addr->nl_pid; 938 dst_pid = addr->nl_pid;
934 dst_groups = addr->nl_groups; 939 dst_group = ffs(addr->nl_groups);
935 if (dst_groups && !netlink_capable(sock, NL_NONROOT_SEND)) 940 if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND))
936 return -EPERM; 941 return -EPERM;
937 } else { 942 } else {
938 dst_pid = nlk->dst_pid; 943 dst_pid = nlk->dst_pid;
939 dst_groups = nlk->dst_groups; 944 dst_group = nlk->dst_group;
940 } 945 }
941 946
942 if (!nlk->pid) { 947 if (!nlk->pid) {
@@ -955,7 +960,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
955 960
956 NETLINK_CB(skb).pid = nlk->pid; 961 NETLINK_CB(skb).pid = nlk->pid;
957 NETLINK_CB(skb).dst_pid = dst_pid; 962 NETLINK_CB(skb).dst_pid = dst_pid;
958 NETLINK_CB(skb).dst_groups = dst_groups; 963 NETLINK_CB(skb).dst_group = dst_group;
959 NETLINK_CB(skb).loginuid = audit_get_loginuid(current->audit_context); 964 NETLINK_CB(skb).loginuid = audit_get_loginuid(current->audit_context);
960 memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); 965 memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
961 966
@@ -977,9 +982,9 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
977 goto out; 982 goto out;
978 } 983 }
979 984
980 if (dst_groups) { 985 if (dst_group) {
981 atomic_inc(&skb->users); 986 atomic_inc(&skb->users);
982 netlink_broadcast(sk, skb, dst_pid, dst_groups, GFP_KERNEL); 987 netlink_broadcast(sk, skb, dst_pid, dst_group, GFP_KERNEL);
983 } 988 }
984 err = netlink_unicast(sk, skb, dst_pid, msg->msg_flags&MSG_DONTWAIT); 989 err = netlink_unicast(sk, skb, dst_pid, msg->msg_flags&MSG_DONTWAIT);
985 990
@@ -1025,7 +1030,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
1025 addr->nl_family = AF_NETLINK; 1030 addr->nl_family = AF_NETLINK;
1026 addr->nl_pad = 0; 1031 addr->nl_pad = 0;
1027 addr->nl_pid = NETLINK_CB(skb).pid; 1032 addr->nl_pid = NETLINK_CB(skb).pid;
1028 addr->nl_groups = NETLINK_CB(skb).dst_groups; 1033 addr->nl_groups = netlink_group_mask(NETLINK_CB(skb).dst_group);
1029 msg->msg_namelen = sizeof(*addr); 1034 msg->msg_namelen = sizeof(*addr);
1030 } 1035 }
1031 1036