tree 0276547438963b51b8d92df201e91d867c7fa9c0
parent 77247bbb3094246be9d057e7be442cc708f123a8
author Patrick McHardy <[EMAIL PROTECTED]> Mon, 15 Aug 2005 09:27:50 -0700
committer David S. Miller <[EMAIL PROTECTED]> Tue, 30 Aug 2005 06:00:49 -0700

[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 <[EMAIL PROTECTED]>
Signed-off-by: David S. Miller <[EMAIL PROTECTED]>

 include/linux/netlink.h  |    2 +-
 net/netlink/af_netlink.c |   35 ++++++++++++++++++++---------------
 2 files changed, 21 insertions(+), 16 deletions(-)

diff --git a/include/linux/netlink.h b/include/linux/netlink.h
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -107,7 +107,7 @@ struct netlink_skb_parms
        struct ucred            creds;          /* Skb credentials      */
        __u32                   pid;
        __u32                   dst_pid;
-       __u32                   dst_groups;
+       __u32                   dst_group;
        kernel_cap_t            eff_cap;
        __u32                   loginuid;       /* Login (audit) uid */
 };
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -67,7 +67,7 @@ struct netlink_sock {
        u32                     pid;
        unsigned int            groups;
        u32                     dst_pid;
-       unsigned int            dst_groups;
+       u32                     dst_group;
        unsigned long           state;
        wait_queue_head_t       wait;
        struct netlink_callback *cb;
@@ -116,6 +116,11 @@ static atomic_t nl_table_users = ATOMIC_
 
 static struct notifier_block *netlink_chain;
 
+static u32 netlink_group_mask(u32 group)
+{
+       return group ? 1 << (group - 1) : 0;
+}
+
 static struct hlist_head *nl_pid_hashfn(struct nl_pid_hash *hash, u32 pid)
 {
        return &hash->table[jhash_1word(pid, hash->rnd) & hash->mask];
@@ -533,7 +538,7 @@ static int netlink_connect(struct socket
        if (addr->sa_family == AF_UNSPEC) {
                sk->sk_state    = NETLINK_UNCONNECTED;
                nlk->dst_pid    = 0;
-               nlk->dst_groups = 0;
+               nlk->dst_group  = 0;
                return 0;
        }
        if (addr->sa_family != AF_NETLINK)
@@ -549,7 +554,7 @@ static int netlink_connect(struct socket
        if (err == 0) {
                sk->sk_state    = NETLINK_CONNECTED;
                nlk->dst_pid    = nladdr->nl_pid;
-               nlk->dst_groups = nladdr->nl_groups;
+               nlk->dst_group  = ffs(nladdr->nl_groups);
        }
 
        return err;
@@ -567,10 +572,10 @@ static int netlink_getname(struct socket
 
        if (peer) {
                nladdr->nl_pid = nlk->dst_pid;
-               nladdr->nl_groups = nlk->dst_groups;
+               nladdr->nl_groups = netlink_group_mask(nlk->dst_group);
        } else {
                nladdr->nl_pid = nlk->pid;
-               nladdr->nl_groups = nlk->groups;
+               nladdr->nl_groups = nlk->groups; 
        }
        return 0;
 }
@@ -771,7 +776,7 @@ static inline int do_one_broadcast(struc
        if (p->exclude_sk == sk)
                goto out;
 
-       if (nlk->pid == p->pid || !(nlk->groups & p->group))
+       if (nlk->pid == p->pid || !(nlk->groups & netlink_group_mask(p->group)))
                goto out;
 
        if (p->failure) {
@@ -867,7 +872,7 @@ static inline int do_one_set_err(struct 
        if (sk == p->exclude_sk)
                goto out;
 
-       if (nlk->pid == p->pid || !(nlk->groups & p->group))
+       if (nlk->pid == p->pid || !(nlk->groups & netlink_group_mask(p->group)))
                goto out;
 
        sk->sk_err = p->code;
@@ -913,7 +918,7 @@ static int netlink_sendmsg(struct kiocb 
        struct netlink_sock *nlk = nlk_sk(sk);
        struct sockaddr_nl *addr=msg->msg_name;
        u32 dst_pid;
-       u32 dst_groups;
+       u32 dst_group;
        struct sk_buff *skb;
        int err;
        struct scm_cookie scm;
@@ -931,12 +936,12 @@ static int netlink_sendmsg(struct kiocb 
                if (addr->nl_family != AF_NETLINK)
                        return -EINVAL;
                dst_pid = addr->nl_pid;
-               dst_groups = addr->nl_groups;
-               if (dst_groups && !netlink_capable(sock, NL_NONROOT_SEND))
+               dst_group = ffs(addr->nl_groups);
+               if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND))
                        return -EPERM;
        } else {
                dst_pid = nlk->dst_pid;
-               dst_groups = nlk->dst_groups;
+               dst_group = nlk->dst_group;
        }
 
        if (!nlk->pid) {
@@ -955,7 +960,7 @@ static int netlink_sendmsg(struct kiocb 
 
        NETLINK_CB(skb).pid     = nlk->pid;
        NETLINK_CB(skb).dst_pid = dst_pid;
-       NETLINK_CB(skb).dst_groups = dst_groups;
+       NETLINK_CB(skb).dst_group = dst_group;
        NETLINK_CB(skb).loginuid = audit_get_loginuid(current->audit_context);
        memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
 
@@ -977,9 +982,9 @@ static int netlink_sendmsg(struct kiocb 
                goto out;
        }
 
-       if (dst_groups) {
+       if (dst_group) {
                atomic_inc(&skb->users);
-               netlink_broadcast(sk, skb, dst_pid, dst_groups, GFP_KERNEL);
+               netlink_broadcast(sk, skb, dst_pid, dst_group, GFP_KERNEL);
        }
        err = netlink_unicast(sk, skb, dst_pid, msg->msg_flags&MSG_DONTWAIT);
 
@@ -1025,7 +1030,7 @@ static int netlink_recvmsg(struct kiocb 
                addr->nl_family = AF_NETLINK;
                addr->nl_pad    = 0;
                addr->nl_pid    = NETLINK_CB(skb).pid;
-               addr->nl_groups = NETLINK_CB(skb).dst_groups;
+               addr->nl_groups = netlink_group_mask(NETLINK_CB(skb).dst_group);
                msg->msg_namelen = sizeof(*addr);
        }
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to