[NETLINK]: Add notification message sending interface
authorThomas Graf <tgraf@suug.ch>
Tue, 15 Aug 2006 07:31:06 +0000 (00:31 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Fri, 22 Sep 2006 21:54:49 +0000 (14:54 -0700)
Adds nlmsg_notify() implementing proper notification logic. The
message is multicasted to all listeners in the group. The
applications the requests orignates from can request a unicast
back report in which case said socket will be excluded from the
multicast to avoid duplicated notifications.

nlmsg_multicast() is extended to take allocation flags to
allow notification in atomic contexts.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/genetlink.h
include/net/netlink.h
net/netlabel/netlabel_user.c
net/netlink/af_netlink.c
net/netlink/genetlink.c

index 8c2287264266776771e08a2fa4387c5b5542112c..97d6d3aba9d2c02f4d3553388ac0162fc9d7e7ee 100644 (file)
@@ -133,11 +133,12 @@ static inline int genlmsg_cancel(struct sk_buff *skb, void *hdr)
  * @skb: netlink message as socket buffer
  * @pid: own netlink pid to avoid sending to yourself
  * @group: multicast group id
+ * @flags: allocation flags
  */
 static inline int genlmsg_multicast(struct sk_buff *skb, u32 pid,
-                                   unsigned int group)
+                                   unsigned int group, gfp_t flags)
 {
-       return nlmsg_multicast(genl_sock, skb, pid, group);
+       return nlmsg_multicast(genl_sock, skb, pid, group, flags);
 }
 
 /**
index 3a5e40b1e045030896a837942bd1645c5f9decd7..b154b81d9a7a80ca6b40ee068e356648492bc617 100644 (file)
@@ -43,6 +43,7 @@
  * Message Sending:
  *   nlmsg_multicast()                 multicast message to several groups
  *   nlmsg_unicast()                   unicast a message to a single socket
+ *   nlmsg_notify()                    send notification message
  *
  * Message Length Calculations:
  *   nlmsg_msg_size(payload)           length of message w/o padding
@@ -545,15 +546,16 @@ static inline void nlmsg_free(struct sk_buff *skb)
  * @skb: netlink message as socket buffer
  * @pid: own netlink pid to avoid sending to yourself
  * @group: multicast group id
+ * @flags: allocation flags
  */
 static inline int nlmsg_multicast(struct sock *sk, struct sk_buff *skb,
-                                 u32 pid, unsigned int group)
+                                 u32 pid, unsigned int group, gfp_t flags)
 {
        int err;
 
        NETLINK_CB(skb).dst_group = group;
 
-       err = netlink_broadcast(sk, skb, pid, group, GFP_KERNEL);
+       err = netlink_broadcast(sk, skb, pid, group, flags);
        if (err > 0)
                err = 0;
 
index 80022221b0a75ccc20537c8a8b30a7ba9de265ae..73cbe66e42ffe6bf00be2252868cc5e0e5780b7a 100644 (file)
@@ -154,5 +154,5 @@ int netlbl_netlink_snd(struct sk_buff *skb, u32 pid)
  */
 int netlbl_netlink_snd_multicast(struct sk_buff *skb, u32 pid, u32 group)
 {
-       return genlmsg_multicast(skb, pid, group);
+       return genlmsg_multicast(skb, pid, group, GFP_KERNEL);
 }
index 0f36ddc0b72d7bfdeab851573404f851b5469266..a80e4456e204be372c2ee305b809d76eff15f4ed 100644 (file)
@@ -1549,6 +1549,38 @@ void netlink_queue_skip(struct nlmsghdr *nlh, struct sk_buff *skb)
        skb_pull(skb, msglen);
 }
 
+/**
+ * nlmsg_notify - send a notification netlink message
+ * @sk: netlink socket to use
+ * @skb: notification message
+ * @pid: destination netlink pid for reports or 0
+ * @group: destination multicast group or 0
+ * @report: 1 to report back, 0 to disable
+ * @flags: allocation flags
+ */
+int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 pid,
+                unsigned int group, int report, gfp_t flags)
+{
+       int err = 0;
+
+       if (group) {
+               int exclude_pid = 0;
+
+               if (report) {
+                       atomic_inc(&skb->users);
+                       exclude_pid = pid;
+               }
+
+               /* errors reported via destination sk->sk_err */
+               nlmsg_multicast(sk, skb, exclude_pid, group, flags);
+       }
+
+       if (report)
+               err = nlmsg_unicast(sk, skb, pid);
+
+       return err;
+}
+
 #ifdef CONFIG_PROC_FS
 struct nl_seq_iter {
        int link;
@@ -1802,4 +1834,4 @@ EXPORT_SYMBOL(netlink_set_err);
 EXPORT_SYMBOL(netlink_set_nonroot);
 EXPORT_SYMBOL(netlink_unicast);
 EXPORT_SYMBOL(netlink_unregister_notifier);
-
+EXPORT_SYMBOL(nlmsg_notify);
index 75bb47a898dd7a7de700f5fd13e250967bae5c10..d32599116c567c429d040ce8dbb53ac3371545cf 100644 (file)
@@ -510,7 +510,7 @@ static int genl_ctrl_event(int event, void *data)
                if (IS_ERR(msg))
                        return PTR_ERR(msg);
 
-               genlmsg_multicast(msg, 0, GENL_ID_CTRL);
+               genlmsg_multicast(msg, 0, GENL_ID_CTRL, GFP_KERNEL);
                break;
        }