diff options
author | Thomas Graf <tgraf@suug.ch> | 2006-08-15 03:31:06 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-09-22 17:54:49 -0400 |
commit | d387f6ad10764fc2174373b4a1cca443adee36e3 (patch) | |
tree | ed22c34f55de9c668eed1727d46239f3b48599b7 | |
parent | 2942e90050569525628a9f34e0daaa9b661b49cc (diff) |
[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.h | 5 | ||||
-rw-r--r-- | include/net/netlink.h | 6 | ||||
-rw-r--r-- | net/netlabel/netlabel_user.c | 2 | ||||
-rw-r--r-- | net/netlink/af_netlink.c | 34 | ||||
-rw-r--r-- | net/netlink/genetlink.c | 2 |
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) | |||
133 | * @skb: netlink message as socket buffer | 133 | * @skb: netlink message as socket buffer |
134 | * @pid: own netlink pid to avoid sending to yourself | 134 | * @pid: own netlink pid to avoid sending to yourself |
135 | * @group: multicast group id | 135 | * @group: multicast group id |
136 | * @flags: allocation flags | ||
136 | */ | 137 | */ |
137 | static inline int genlmsg_multicast(struct sk_buff *skb, u32 pid, | 138 | static inline int genlmsg_multicast(struct sk_buff *skb, u32 pid, |
138 | unsigned int group) | 139 | unsigned int group, gfp_t flags) |
139 | { | 140 | { |
140 | return nlmsg_multicast(genl_sock, skb, pid, group); | 141 | return nlmsg_multicast(genl_sock, skb, pid, group, flags); |
141 | } | 142 | } |
142 | 143 | ||
143 | /** | 144 | /** |
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 @@ | |||
43 | * Message Sending: | 43 | * Message Sending: |
44 | * nlmsg_multicast() multicast message to several groups | 44 | * nlmsg_multicast() multicast message to several groups |
45 | * nlmsg_unicast() unicast a message to a single socket | 45 | * nlmsg_unicast() unicast a message to a single socket |
46 | * nlmsg_notify() send notification message | ||
46 | * | 47 | * |
47 | * Message Length Calculations: | 48 | * Message Length Calculations: |
48 | * nlmsg_msg_size(payload) length of message w/o padding | 49 | * nlmsg_msg_size(payload) length of message w/o padding |
@@ -545,15 +546,16 @@ static inline void nlmsg_free(struct sk_buff *skb) | |||
545 | * @skb: netlink message as socket buffer | 546 | * @skb: netlink message as socket buffer |
546 | * @pid: own netlink pid to avoid sending to yourself | 547 | * @pid: own netlink pid to avoid sending to yourself |
547 | * @group: multicast group id | 548 | * @group: multicast group id |
549 | * @flags: allocation flags | ||
548 | */ | 550 | */ |
549 | static inline int nlmsg_multicast(struct sock *sk, struct sk_buff *skb, | 551 | static inline int nlmsg_multicast(struct sock *sk, struct sk_buff *skb, |
550 | u32 pid, unsigned int group) | 552 | u32 pid, unsigned int group, gfp_t flags) |
551 | { | 553 | { |
552 | int err; | 554 | int err; |
553 | 555 | ||
554 | NETLINK_CB(skb).dst_group = group; | 556 | NETLINK_CB(skb).dst_group = group; |
555 | 557 | ||
556 | err = netlink_broadcast(sk, skb, pid, group, GFP_KERNEL); | 558 | err = netlink_broadcast(sk, skb, pid, group, flags); |
557 | if (err > 0) | 559 | if (err > 0) |
558 | err = 0; | 560 | err = 0; |
559 | 561 | ||
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) | |||
154 | */ | 154 | */ |
155 | int netlbl_netlink_snd_multicast(struct sk_buff *skb, u32 pid, u32 group) | 155 | int netlbl_netlink_snd_multicast(struct sk_buff *skb, u32 pid, u32 group) |
156 | { | 156 | { |
157 | return genlmsg_multicast(skb, pid, group); | 157 | return genlmsg_multicast(skb, pid, group, GFP_KERNEL); |
158 | } | 158 | } |
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) | |||
1549 | skb_pull(skb, msglen); | 1549 | skb_pull(skb, msglen); |
1550 | } | 1550 | } |
1551 | 1551 | ||
1552 | /** | ||
1553 | * nlmsg_notify - send a notification netlink message | ||
1554 | * @sk: netlink socket to use | ||
1555 | * @skb: notification message | ||
1556 | * @pid: destination netlink pid for reports or 0 | ||
1557 | * @group: destination multicast group or 0 | ||
1558 | * @report: 1 to report back, 0 to disable | ||
1559 | * @flags: allocation flags | ||
1560 | */ | ||
1561 | int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 pid, | ||
1562 | unsigned int group, int report, gfp_t flags) | ||
1563 | { | ||
1564 | int err = 0; | ||
1565 | |||
1566 | if (group) { | ||
1567 | int exclude_pid = 0; | ||
1568 | |||
1569 | if (report) { | ||
1570 | atomic_inc(&skb->users); | ||
1571 | exclude_pid = pid; | ||
1572 | } | ||
1573 | |||
1574 | /* errors reported via destination sk->sk_err */ | ||
1575 | nlmsg_multicast(sk, skb, exclude_pid, group, flags); | ||
1576 | } | ||
1577 | |||
1578 | if (report) | ||
1579 | err = nlmsg_unicast(sk, skb, pid); | ||
1580 | |||
1581 | return err; | ||
1582 | } | ||
1583 | |||
1552 | #ifdef CONFIG_PROC_FS | 1584 | #ifdef CONFIG_PROC_FS |
1553 | struct nl_seq_iter { | 1585 | struct nl_seq_iter { |
1554 | int link; | 1586 | int link; |
@@ -1802,4 +1834,4 @@ EXPORT_SYMBOL(netlink_set_err); | |||
1802 | EXPORT_SYMBOL(netlink_set_nonroot); | 1834 | EXPORT_SYMBOL(netlink_set_nonroot); |
1803 | EXPORT_SYMBOL(netlink_unicast); | 1835 | EXPORT_SYMBOL(netlink_unicast); |
1804 | EXPORT_SYMBOL(netlink_unregister_notifier); | 1836 | EXPORT_SYMBOL(netlink_unregister_notifier); |
1805 | 1837 | 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) | |||
510 | if (IS_ERR(msg)) | 510 | if (IS_ERR(msg)) |
511 | return PTR_ERR(msg); | 511 | return PTR_ERR(msg); |
512 | 512 | ||
513 | genlmsg_multicast(msg, 0, GENL_ID_CTRL); | 513 | genlmsg_multicast(msg, 0, GENL_ID_CTRL, GFP_KERNEL); |
514 | break; | 514 | break; |
515 | } | 515 | } |
516 | 516 | ||