Bcc: Evgeniy Polyakov <[EMAIL PROTECTED]> Subject: [RFC] Netlink subscription/multicasting. Reply-To: [EMAIL PROTECTED]
Hello, developers. Here is some thoughts about netlink subscription/multicasting/group number. Attached [only compile tested] patch implements two socket options for netlink sockets, which enables/disables so called subscription. Subscription is a netlink socket option, which, if enabled, ends up in direct message delivering, but not multicast one. I.e. socket with such option enbled will only receive data directed exactly to the specifined on bind() time group, it will not receive any multicast traffic. This option also allows to have 2^32 different groups for specified socket. This idea was originally implemented in connector. This usage case is the most popular in kernel event notifications, and the most of the userspace -> kernelspace messages can be be converted into it too. Implementation is quite raw though... I gladly wait for your comments. --- ./net/netlink/af_netlink.c.orig 2005-07-29 13:29:40.000000000 +0400 +++ ./net/netlink/af_netlink.c 2005-07-29 14:01:45.000000000 +0400 @@ -725,7 +725,13 @@ if (p->exclude_sk == sk) goto out; - if (nlk->pid == p->pid || !(nlk->groups & p->group)) + if (nlk->pid == p->pid) + goto out; + + if (test_bit(1, &nlk->state)) { + if (nlk->groups != p->group) + goto out; + } else if (!(nlk->groups & p->group)) goto out; if (p->failure) { @@ -1185,6 +1191,52 @@ netlink_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); } +static int netlink_is_bound(struct sock *sk, u32 pid) +{ + struct nl_pid_hash *hash = &nl_table[sk->sk_protocol].hash; + struct hlist_head *head; + struct sock *osk; + struct hlist_node *node; + int bound = 0; + + head = nl_pid_hashfn(hash, pid); + sk_for_each(osk, node, head) { + if (nlk_sk(osk)->pid == pid) { + bound = 1; + break; + } + } + + return bound; +} + +static int netlink_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen) +{ + struct sock *sk = sock->sk; + struct netlink_sock *nlk = nlk_sk(sk); + int err = 0; + + if (level != SOL_RAW && level != SOL_PACKET) + return -ENOPROTOOPT; + + netlink_table_grab(); + switch (optname) { + case NETLINK_OPT_SUBSCRIBE: + case NETLINK_OPT_UNSUBSCRIBE: + if (!netlink_is_bound(sk, current->pid)) { + err = -EINVAL; + break; + } + if (optname == NETLINK_OPT_SUBSCRIBE) + set_bit(1, &nlk->state); + else + clear_bit(1, &nlk->state); + break; + } + netlink_table_ungrab(); + + return err; +} #ifdef CONFIG_PROC_FS struct nl_seq_iter { @@ -1354,7 +1406,7 @@ .ioctl = sock_no_ioctl, .listen = sock_no_listen, .shutdown = sock_no_shutdown, - .setsockopt = sock_no_setsockopt, + .setsockopt = netlink_setsockopt, .getsockopt = sock_no_getsockopt, .sendmsg = netlink_sendmsg, .recvmsg = netlink_recvmsg, --- ./include/linux/netlink.h.orig 2005-07-29 13:33:41.000000000 +0400 +++ ./include/linux/netlink.h 2005-07-29 13:37:43.000000000 +0400 @@ -97,6 +97,9 @@ NETLINK_CONNECTED, }; +#define NETLINK_OPT_SUBSCRIBE 1 +#define NETLINK_OPT_UNSUBSCRIBE 2 + #ifdef __KERNEL__ #include <linux/capability.h> Evgeniy Polyakov - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html