aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netlink.h4
-rw-r--r--net/netlink/af_netlink.c21
2 files changed, 23 insertions, 2 deletions
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 6eaca5e1e8ca..59d066936ab9 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -188,6 +188,10 @@ extern int netlink_has_listeners(struct sock *sk, unsigned int group);
188extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock); 188extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock);
189extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid, 189extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid,
190 __u32 group, gfp_t allocation); 190 __u32 group, gfp_t allocation);
191extern int netlink_broadcast_filtered(struct sock *ssk, struct sk_buff *skb,
192 __u32 pid, __u32 group, gfp_t allocation,
193 int (*filter)(struct sock *dsk, struct sk_buff *skb, void *data),
194 void *filter_data);
191extern int netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code); 195extern int netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code);
192extern int netlink_register_notifier(struct notifier_block *nb); 196extern int netlink_register_notifier(struct notifier_block *nb);
193extern int netlink_unregister_notifier(struct notifier_block *nb); 197extern int netlink_unregister_notifier(struct notifier_block *nb);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 6464a1972a69..a2eb965207d3 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -978,6 +978,8 @@ struct netlink_broadcast_data {
978 int delivered; 978 int delivered;
979 gfp_t allocation; 979 gfp_t allocation;
980 struct sk_buff *skb, *skb2; 980 struct sk_buff *skb, *skb2;
981 int (*tx_filter)(struct sock *dsk, struct sk_buff *skb, void *data);
982 void *tx_data;
981}; 983};
982 984
983static inline int do_one_broadcast(struct sock *sk, 985static inline int do_one_broadcast(struct sock *sk,
@@ -1020,6 +1022,9 @@ static inline int do_one_broadcast(struct sock *sk,
1020 p->failure = 1; 1022 p->failure = 1;
1021 if (nlk->flags & NETLINK_BROADCAST_SEND_ERROR) 1023 if (nlk->flags & NETLINK_BROADCAST_SEND_ERROR)
1022 p->delivery_failure = 1; 1024 p->delivery_failure = 1;
1025 } else if (p->tx_filter && p->tx_filter(sk, p->skb2, p->tx_data)) {
1026 kfree_skb(p->skb2);
1027 p->skb2 = NULL;
1023 } else if (sk_filter(sk, p->skb2)) { 1028 } else if (sk_filter(sk, p->skb2)) {
1024 kfree_skb(p->skb2); 1029 kfree_skb(p->skb2);
1025 p->skb2 = NULL; 1030 p->skb2 = NULL;
@@ -1038,8 +1043,10 @@ out:
1038 return 0; 1043 return 0;
1039} 1044}
1040 1045
1041int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, 1046int netlink_broadcast_filtered(struct sock *ssk, struct sk_buff *skb, u32 pid,
1042 u32 group, gfp_t allocation) 1047 u32 group, gfp_t allocation,
1048 int (*filter)(struct sock *dsk, struct sk_buff *skb, void *data),
1049 void *filter_data)
1043{ 1050{
1044 struct net *net = sock_net(ssk); 1051 struct net *net = sock_net(ssk);
1045 struct netlink_broadcast_data info; 1052 struct netlink_broadcast_data info;
@@ -1059,6 +1066,8 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
1059 info.allocation = allocation; 1066 info.allocation = allocation;
1060 info.skb = skb; 1067 info.skb = skb;
1061 info.skb2 = NULL; 1068 info.skb2 = NULL;
1069 info.tx_filter = filter;
1070 info.tx_data = filter_data;
1062 1071
1063 /* While we sleep in clone, do not allow to change socket list */ 1072 /* While we sleep in clone, do not allow to change socket list */
1064 1073
@@ -1083,6 +1092,14 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
1083 } 1092 }
1084 return -ESRCH; 1093 return -ESRCH;
1085} 1094}
1095EXPORT_SYMBOL(netlink_broadcast_filtered);
1096
1097int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
1098 u32 group, gfp_t allocation)
1099{
1100 return netlink_broadcast_filtered(ssk, skb, pid, group, allocation,
1101 NULL, NULL);
1102}
1086EXPORT_SYMBOL(netlink_broadcast); 1103EXPORT_SYMBOL(netlink_broadcast);
1087 1104
1088struct netlink_set_err_data { 1105struct netlink_set_err_data {