summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2006-08-15 00:31:06 -0700
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 14:54:49 -0700
commitd387f6ad10764fc2174373b4a1cca443adee36e3 (patch)
treeed22c34f55de9c668eed1727d46239f3b48599b7
parent2942e90050569525628a9f34e0daaa9b661b49cc (diff)
downloadblackbird-op-linux-d387f6ad10764fc2174373b4a1cca443adee36e3.tar.gz
blackbird-op-linux-d387f6ad10764fc2174373b4a1cca443adee36e3.zip
[NETLINK]: Add notification message sending interface
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>
-rw-r--r--include/net/genetlink.h5
-rw-r--r--include/net/netlink.h6
-rw-r--r--net/netlabel/netlabel_user.c2
-rw-r--r--net/netlink/af_netlink.c34
-rw-r--r--net/netlink/genetlink.c2
5 files changed, 42 insertions, 7 deletions
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index 8c2287264266..97d6d3aba9d2 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -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);
}
/**
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 3a5e40b1e045..b154b81d9a7a 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -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;
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index 80022221b0a7..73cbe66e42ff 100644
--- a/net/netlabel/netlabel_user.c
+++ b/net/netlabel/netlabel_user.c
@@ -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);
}
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 0f36ddc0b72d..a80e4456e204 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -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);
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 75bb47a898dd..d32599116c56 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -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;
}
OpenPOWER on IntegriCloud