diff options
author | Patrick McHardy <kaber@trash.net> | 2005-08-14 22:27:50 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 19:00:49 -0400 |
commit | d629b836d151d43332492651dd841d32e57ebe3b (patch) | |
tree | 0276547438963b51b8d92df201e91d867c7fa9c0 /net | |
parent | 77247bbb3094246be9d057e7be442cc708f123a8 (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')
-rw-r--r-- | net/netlink/af_netlink.c | 35 |
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 | ||
117 | static struct notifier_block *netlink_chain; | 117 | static struct notifier_block *netlink_chain; |
118 | 118 | ||
119 | static u32 netlink_group_mask(u32 group) | ||
120 | { | ||
121 | return group ? 1 << (group - 1) : 0; | ||
122 | } | ||
123 | |||
119 | static struct hlist_head *nl_pid_hashfn(struct nl_pid_hash *hash, u32 pid) | 124 | static 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 | ||