backports: fully add netlink extack for generic netlink
[openwrt/staging/blogic.git] / backport / backport-include / net / genetlink.h
1 #ifndef __BACKPORT_NET_GENETLINK_H
2 #define __BACKPORT_NET_GENETLINK_H
3 #include_next <net/genetlink.h>
4 #include <linux/version.h>
5
6 #if LINUX_VERSION_IS_LESS(4,12,0)
7 #define GENL_SET_ERR_MSG(info, msg) do { } while (0)
8
9 static inline int genl_err_attr(struct genl_info *info, int err,
10 struct nlattr *attr)
11 {
12 #if LINUX_VERSION_IS_GEQ(4,12,0)
13 info->extack->bad_attr = attr;
14 #endif
15
16 return err;
17 }
18 #endif
19
20 /* this is for patches we apply */
21 static inline struct netlink_ext_ack *genl_info_extack(struct genl_info *info)
22 {
23 #if LINUX_VERSION_IS_GEQ(4,12,0)
24 return info->extack;
25 #else
26 return info->userhdr;
27 #endif
28 }
29
30 /* this gets put in place of info->userhdr, since we use that above */
31 static inline void *genl_info_userhdr(struct genl_info *info)
32 {
33 return (u8 *)info->genlhdr + GENL_HDRLEN;
34 }
35
36 /* this is for patches we apply */
37 #if LINUX_VERSION_IS_LESS(3,7,0)
38 #define genl_info_snd_portid(__genl_info) (__genl_info->snd_pid)
39 #else
40 #define genl_info_snd_portid(__genl_info) (__genl_info->snd_portid)
41 #endif
42
43 #ifndef GENLMSG_DEFAULT_SIZE
44 #define GENLMSG_DEFAULT_SIZE (NLMSG_DEFAULT_SIZE - GENL_HDRLEN)
45 #endif
46
47 #if LINUX_VERSION_IS_LESS(3,1,0)
48 #define genl_dump_check_consistent(cb, user_hdr, family)
49 #endif
50
51 #if LINUX_VERSION_IS_LESS(3,13,0) && RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,0)
52 static inline int __real_genl_register_family(struct genl_family *family)
53 {
54 return genl_register_family(family);
55 }
56
57 /* Needed for the mcgrps pointer */
58 struct backport_genl_family {
59 struct genl_family family;
60
61 unsigned int id, hdrsize, version, maxattr;
62 char name[GENL_NAMSIZ];
63 bool netnsok;
64 bool parallel_ops;
65
66 struct nlattr **attrbuf;
67
68 int (*pre_doit)(struct genl_ops *ops, struct sk_buff *skb,
69 struct genl_info *info);
70
71 void (*post_doit)(struct genl_ops *ops, struct sk_buff *skb,
72 struct genl_info *info);
73
74 struct genl_multicast_group *mcgrps;
75 struct genl_ops *ops;
76 unsigned int n_mcgrps, n_ops;
77
78 struct module *module;
79 };
80 #define genl_family LINUX_BACKPORT(genl_family)
81
82 int __backport_genl_register_family(struct genl_family *family);
83
84 #define genl_register_family LINUX_BACKPORT(genl_register_family)
85 static inline int
86 genl_register_family(struct genl_family *family)
87 {
88 family->module = THIS_MODULE;
89 return __backport_genl_register_family(family);
90 }
91
92 #define _genl_register_family_with_ops_grps \
93 _backport_genl_register_family_with_ops_grps
94 static inline int
95 _genl_register_family_with_ops_grps(struct genl_family *family,
96 struct genl_ops *ops, size_t n_ops,
97 struct genl_multicast_group *mcgrps,
98 size_t n_mcgrps)
99 {
100 family->ops = ops;
101 family->n_ops = n_ops;
102 family->mcgrps = mcgrps;
103 family->n_mcgrps = n_mcgrps;
104 return genl_register_family(family);
105 }
106
107 #define genl_register_family_with_ops(family, ops) \
108 _genl_register_family_with_ops_grps((family), \
109 (ops), ARRAY_SIZE(ops), \
110 NULL, 0)
111 #define genl_register_family_with_ops_groups(family, ops, grps) \
112 _genl_register_family_with_ops_grps((family), \
113 (ops), ARRAY_SIZE(ops), \
114 (grps), ARRAY_SIZE(grps))
115
116 #define genl_unregister_family backport_genl_unregister_family
117 int genl_unregister_family(struct genl_family *family);
118
119 #if LINUX_VERSION_IS_LESS(3,3,0)
120 extern void genl_notify(struct sk_buff *skb, struct net *net, u32 pid,
121 u32 group, struct nlmsghdr *nlh, gfp_t flags);
122 #endif
123 #define genl_notify(_fam, _skb, _info, _group, _flags) \
124 genl_notify(_skb, genl_info_net(_info), \
125 genl_info_snd_portid(_info), \
126 (_fam)->mcgrps[_group].id, _info->nlhdr, _flags)
127 #define genlmsg_put(_skb, _pid, _seq, _fam, _flags, _cmd) \
128 genlmsg_put(_skb, _pid, _seq, &(_fam)->family, _flags, _cmd)
129 #define genlmsg_nlhdr(_hdr, _fam) \
130 genlmsg_nlhdr(_hdr, &(_fam)->family)
131 #ifndef genl_dump_check_consistent
132 #define genl_dump_check_consistent(_cb, _hdr, _fam) \
133 genl_dump_check_consistent(_cb, _hdr, &(_fam)->family)
134 #endif
135 #ifndef genlmsg_put_reply /* might already be there from _info override above */
136 #define genlmsg_put_reply(_skb, _info, _fam, _flags, _cmd) \
137 genlmsg_put_reply(_skb, _info, &(_fam)->family, _flags, _cmd)
138 #endif
139 #define genlmsg_multicast_netns LINUX_BACKPORT(genlmsg_multicast_netns)
140 static inline int genlmsg_multicast_netns(struct genl_family *family,
141 struct net *net, struct sk_buff *skb,
142 u32 portid, unsigned int group,
143 gfp_t flags)
144 {
145 if (WARN_ON_ONCE(group >= family->n_mcgrps))
146 return -EINVAL;
147 group = family->mcgrps[group].id;
148 return nlmsg_multicast(
149 net->genl_sock,
150 skb, portid, group, flags);
151 }
152 #define genlmsg_multicast LINUX_BACKPORT(genlmsg_multicast)
153 static inline int genlmsg_multicast(struct genl_family *family,
154 struct sk_buff *skb, u32 portid,
155 unsigned int group, gfp_t flags)
156 {
157 if (WARN_ON_ONCE(group >= family->n_mcgrps))
158 return -EINVAL;
159 group = family->mcgrps[group].id;
160 return nlmsg_multicast(
161 init_net.genl_sock,
162 skb, portid, group, flags);
163 }
164 static inline int
165 backport_genlmsg_multicast_allns(struct genl_family *family,
166 struct sk_buff *skb, u32 portid,
167 unsigned int group, gfp_t flags)
168 {
169 if (WARN_ON_ONCE(group >= family->n_mcgrps))
170 return -EINVAL;
171 group = family->mcgrps[group].id;
172 return genlmsg_multicast_allns(skb, portid, group, flags);
173 }
174 #define genlmsg_multicast_allns LINUX_BACKPORT(genlmsg_multicast_allns)
175
176 #define __genl_const
177 #else /* < 3.13 */
178 #define __genl_const const
179 #if LINUX_VERSION_IS_LESS(4,4,0)
180 #define genl_notify(_fam, _skb, _info, _group, _flags) \
181 genl_notify(_fam, _skb, genl_info_net(_info), \
182 genl_info_snd_portid(_info), \
183 _group, _info->nlhdr, _flags)
184 #endif /* < 4.4 */
185 #endif /* < 3.13 */
186
187 #if LINUX_VERSION_IS_LESS(4,10,0)
188 /**
189 * genl_family_attrbuf - return family's attrbuf
190 * @family: the family
191 *
192 * Return the family's attrbuf, while validating that it's
193 * actually valid to access it.
194 *
195 * You cannot use this function with a family that has parallel_ops
196 * and you can only use it within (pre/post) doit/dumpit callbacks.
197 */
198 #define genl_family_attrbuf LINUX_BACKPORT(genl_family_attrbuf)
199 static inline struct nlattr **genl_family_attrbuf(struct genl_family *family)
200 {
201 WARN_ON(family->parallel_ops);
202
203 return family->attrbuf;
204 }
205
206 #define __genl_ro_after_init
207 #else
208 #define __genl_ro_after_init __ro_after_init
209 #endif
210
211 #if LINUX_VERSION_IS_LESS(4,12,0)
212 static inline int
213 __real_bp_extack_genl_register_family(struct genl_family *family)
214 {
215 return genl_register_family(family);
216 }
217 static inline int
218 __real_bp_extack_genl_unregister_family(struct genl_family *family)
219 {
220 return genl_unregister_family(family);
221 }
222 int bp_extack_genl_register_family(struct genl_family *family);
223 int bp_extack_genl_unregister_family(struct genl_family *family);
224 #undef genl_register_family
225 #define genl_register_family bp_extack_genl_register_family
226 #undef genl_unregister_family
227 #define genl_unregister_family bp_extack_genl_unregister_family
228 #endif
229
230 #endif /* __BACKPORT_NET_GENETLINK_H */