aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/genetlink.h18
-rw-r--r--net/netlink/genetlink.c14
2 files changed, 31 insertions, 1 deletions
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index f7dcd2c70412..8a64b811a39a 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -20,6 +20,9 @@ struct genl_multicast_group {
20 u32 id; 20 u32 id;
21}; 21};
22 22
23struct genl_ops;
24struct genl_info;
25
23/** 26/**
24 * struct genl_family - generic netlink family 27 * struct genl_family - generic netlink family
25 * @id: protocol family idenfitier 28 * @id: protocol family idenfitier
@@ -29,6 +32,10 @@ struct genl_multicast_group {
29 * @maxattr: maximum number of attributes supported 32 * @maxattr: maximum number of attributes supported
30 * @netnsok: set to true if the family can handle network 33 * @netnsok: set to true if the family can handle network
31 * namespaces and should be presented in all of them 34 * namespaces and should be presented in all of them
35 * @pre_doit: called before an operation's doit callback, it may
36 * do additional, common, filtering and return an error
37 * @post_doit: called after an operation's doit callback, it may
38 * undo operations done by pre_doit, for example release locks
32 * @attrbuf: buffer to store parsed attributes 39 * @attrbuf: buffer to store parsed attributes
33 * @ops_list: list of all assigned operations 40 * @ops_list: list of all assigned operations
34 * @family_list: family list 41 * @family_list: family list
@@ -41,6 +48,12 @@ struct genl_family {
41 unsigned int version; 48 unsigned int version;
42 unsigned int maxattr; 49 unsigned int maxattr;
43 bool netnsok; 50 bool netnsok;
51 int (*pre_doit)(struct genl_ops *ops,
52 struct sk_buff *skb,
53 struct genl_info *info);
54 void (*post_doit)(struct genl_ops *ops,
55 struct sk_buff *skb,
56 struct genl_info *info);
44 struct nlattr ** attrbuf; /* private */ 57 struct nlattr ** attrbuf; /* private */
45 struct list_head ops_list; /* private */ 58 struct list_head ops_list; /* private */
46 struct list_head family_list; /* private */ 59 struct list_head family_list; /* private */
@@ -55,6 +68,8 @@ struct genl_family {
55 * @genlhdr: generic netlink message header 68 * @genlhdr: generic netlink message header
56 * @userhdr: user specific header 69 * @userhdr: user specific header
57 * @attrs: netlink attributes 70 * @attrs: netlink attributes
71 * @_net: network namespace
72 * @user_ptr: user pointers
58 */ 73 */
59struct genl_info { 74struct genl_info {
60 u32 snd_seq; 75 u32 snd_seq;
@@ -66,6 +81,7 @@ struct genl_info {
66#ifdef CONFIG_NET_NS 81#ifdef CONFIG_NET_NS
67 struct net * _net; 82 struct net * _net;
68#endif 83#endif
84 void * user_ptr[2];
69}; 85};
70 86
71static inline struct net *genl_info_net(struct genl_info *info) 87static inline struct net *genl_info_net(struct genl_info *info)
@@ -81,6 +97,7 @@ static inline void genl_info_net_set(struct genl_info *info, struct net *net)
81/** 97/**
82 * struct genl_ops - generic netlink operations 98 * struct genl_ops - generic netlink operations
83 * @cmd: command identifier 99 * @cmd: command identifier
100 * @internal_flags: flags used by the family
84 * @flags: flags 101 * @flags: flags
85 * @policy: attribute validation policy 102 * @policy: attribute validation policy
86 * @doit: standard command callback 103 * @doit: standard command callback
@@ -90,6 +107,7 @@ static inline void genl_info_net_set(struct genl_info *info, struct net *net)
90 */ 107 */
91struct genl_ops { 108struct genl_ops {
92 u8 cmd; 109 u8 cmd;
110 u8 internal_flags;
93 unsigned int flags; 111 unsigned int flags;
94 const struct nla_policy *policy; 112 const struct nla_policy *policy;
95 int (*doit)(struct sk_buff *skb, 113 int (*doit)(struct sk_buff *skb,
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 26ed3e8587c2..1781d99145e2 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -547,8 +547,20 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
547 info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN; 547 info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN;
548 info.attrs = family->attrbuf; 548 info.attrs = family->attrbuf;
549 genl_info_net_set(&info, net); 549 genl_info_net_set(&info, net);
550 memset(&info.user_ptr, 0, sizeof(info.user_ptr));
550 551
551 return ops->doit(skb, &info); 552 if (family->pre_doit) {
553 err = family->pre_doit(ops, skb, &info);
554 if (err)
555 return err;
556 }
557
558 err = ops->doit(skb, &info);
559
560 if (family->post_doit)
561 family->post_doit(ops, skb, &info);
562
563 return err;
552} 564}
553 565
554static void genl_rcv(struct sk_buff *skb) 566static void genl_rcv(struct sk_buff *skb)