1 #ifndef GENL_MAGIC_FUNC_H
2 #define GENL_MAGIC_FUNC_H
4 #include <linux/genl_magic_struct.h>
7 * Extension of genl attribute validation policies {{{1
12 * nla_is_required - return true if this attribute is required
13 * @nla: netlink attribute
15 static inline int nla_is_required(const struct nlattr
*nla
)
17 return nla
->nla_type
& GENLA_F_REQUIRED
;
21 * nla_is_mandatory - return true if understanding this attribute is mandatory
22 * @nla: netlink attribute
23 * Note: REQUIRED attributes are implicitly MANDATORY as well
25 static inline int nla_is_mandatory(const struct nlattr
*nla
)
27 return nla
->nla_type
& (GENLA_F_MANDATORY
| GENLA_F_REQUIRED
);
30 /* Functionality to be integrated into nla_parse(), and validate_nla(),
33 * Enforcing the "mandatory" bit is done here,
34 * by rejecting unknown mandatory attributes.
36 * Part of enforcing the "required" flag would mean to embed it into
37 * nla_policy.type, and extending validate_nla(), which currently does
38 * BUG_ON(pt->type > NLA_TYPE_MAX); we have to work on existing kernels,
39 * so we cannot do that. Thats why enforcing "required" is done in the
40 * generated assignment functions below. */
41 static int nla_check_unknown(int maxtype
, struct nlattr
*head
, int len
)
45 nla_for_each_attr(nla
, head
, len
, rem
) {
46 __u16 type
= nla_type(nla
);
47 if (type
> maxtype
&& nla_is_mandatory(nla
))
54 * Magic: declare tla policy {{{1
55 * Magic: declare nested policies
59 #define GENL_mc_group(group)
61 #undef GENL_notification
62 #define GENL_notification(op_name, op_num, mcast_group, tla_list)
65 #define GENL_op(op_name, op_num, handler, tla_list)
68 #define GENL_struct(tag_name, tag_number, s_name, s_fields) \
69 [tag_name] = { .type = NLA_NESTED },
71 static struct nla_policy
CONCAT_(GENL_MAGIC_FAMILY
, _tla_nl_policy
)[] = {
72 #include GENL_MAGIC_INCLUDE_FILE
76 #define GENL_struct(tag_name, tag_number, s_name, s_fields) \
77 static struct nla_policy s_name ## _nl_policy[] __read_mostly = \
81 #define __field(attr_nr, attr_flag, name, nla_type, _type, __get, __put) \
82 [__nla_type(attr_nr)] = { .type = nla_type },
85 #define __array(attr_nr, attr_flag, name, nla_type, _type, maxlen, \
87 [__nla_type(attr_nr)] = { .type = nla_type, \
88 .len = maxlen - (nla_type == NLA_NUL_STRING) },
90 #include GENL_MAGIC_INCLUDE_FILE
94 #define pr_info(args...) fprintf(stderr, args);
98 #ifdef GENL_MAGIC_DEBUG
99 static void dprint_field(const char *dir
, int nla_type
,
100 const char *name
, void *valp
)
102 __u64 val
= valp
? *(__u32
*)valp
: 1;
104 case NLA_U8
: val
= (__u8
)val
;
105 case NLA_U16
: val
= (__u16
)val
;
106 case NLA_U32
: val
= (__u32
)val
;
107 pr_info("%s attr %s: %d 0x%08x\n", dir
,
108 name
, (int)val
, (unsigned)val
);
112 pr_info("%s attr %s: %lld 0x%08llx\n", dir
,
113 name
, (long long)val
, (unsigned long long)val
);
117 pr_info("%s attr %s: set\n", dir
, name
);
122 static void dprint_array(const char *dir
, int nla_type
,
123 const char *name
, const char *val
, unsigned len
)
127 if (len
&& val
[len
-1] == '\0')
129 pr_info("%s attr %s: [len:%u] '%s'\n", dir
, name
, len
, val
);
132 /* we can always show 4 byte,
133 * thats what nlattr are aligned to. */
134 pr_info("%s attr %s: [len:%u] %02x%02x%02x%02x ...\n",
135 dir
, name
, len
, val
[0], val
[1], val
[2], val
[3]);
139 #define DPRINT_TLA(a, op, b) pr_info("%s %s %s\n", a, op, b);
141 /* Name is a member field name of the struct s.
142 * If s is NULL (only parsing, no copy requested in *_from_attrs()),
143 * nla is supposed to point to the attribute containing the information
144 * corresponding to that struct member. */
145 #define DPRINT_FIELD(dir, nla_type, name, s, nla) \
148 dprint_field(dir, nla_type, #name, &s->name); \
150 dprint_field(dir, nla_type, #name, \
151 (nla_type == NLA_FLAG) ? NULL \
155 #define DPRINT_ARRAY(dir, nla_type, name, s, nla) \
158 dprint_array(dir, nla_type, #name, \
159 s->name, s->name ## _len); \
161 dprint_array(dir, nla_type, #name, \
162 nla_data(nla), nla_len(nla)); \
165 #define DPRINT_TLA(a, op, b) do {} while (0)
166 #define DPRINT_FIELD(dir, nla_type, name, s, nla) do {} while (0)
167 #define DPRINT_ARRAY(dir, nla_type, name, s, nla) do {} while (0)
171 * Magic: provide conversion functions {{{1
172 * populate struct from attribute table:
176 /* processing of generic netlink messages is serialized.
177 * use one static buffer for parsing of nested attributes */
178 static struct nlattr
*nested_attr_tb
[128];
181 /* Force a compilation error if condition is true */
182 #define BUILD_BUG_ON(condition) ((void)BUILD_BUG_ON_ZERO(condition))
183 /* Force a compilation error if condition is true, but also produce a
184 result (of value 0 and type size_t), so the expression can be used
185 e.g. in a structure initializer (or where-ever else comma expressions
186 aren't permitted). */
187 #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
188 #define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
192 #define GENL_struct(tag_name, tag_number, s_name, s_fields) \
193 /* *_from_attrs functions are static, but potentially unused */ \
194 static int __ ## s_name ## _from_attrs(struct s_name *s, \
195 struct genl_info *info, bool exclude_invariants) \
197 const int maxtype = ARRAY_SIZE(s_name ## _nl_policy)-1; \
198 struct nlattr *tla = info->attrs[tag_number]; \
199 struct nlattr **ntb = nested_attr_tb; \
200 struct nlattr *nla; \
202 BUILD_BUG_ON(ARRAY_SIZE(s_name ## _nl_policy) > ARRAY_SIZE(nested_attr_tb)); \
205 DPRINT_TLA(#s_name, "<=-", #tag_name); \
206 err = nla_parse_nested(ntb, maxtype, tla, s_name ## _nl_policy); \
209 err = nla_check_unknown(maxtype, nla_data(tla), nla_len(tla)); \
215 } __attribute__((unused)) \
216 static int s_name ## _from_attrs(struct s_name *s, \
217 struct genl_info *info) \
219 return __ ## s_name ## _from_attrs(s, info, false); \
220 } __attribute__((unused)) \
221 static int s_name ## _from_attrs_for_change(struct s_name *s, \
222 struct genl_info *info) \
224 return __ ## s_name ## _from_attrs(s, info, true); \
225 } __attribute__((unused)) \
227 #define __assign(attr_nr, attr_flag, name, nla_type, type, assignment...) \
228 nla = ntb[__nla_type(attr_nr)]; \
230 if (exclude_invariants && ((attr_flag) & GENLA_F_INVARIANT)) { \
231 pr_info("<< must not change invariant attr: %s\n", #name); \
235 } else if (exclude_invariants && ((attr_flag) & GENLA_F_INVARIANT)) { \
236 /* attribute missing from payload, */ \
237 /* which was expected */ \
238 } else if ((attr_flag) & GENLA_F_REQUIRED) { \
239 pr_info("<< missing attr: %s\n", #name); \
244 #define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put) \
245 __assign(attr_nr, attr_flag, name, nla_type, type, \
247 s->name = __get(nla); \
248 DPRINT_FIELD("<<", nla_type, name, s, nla))
250 /* validate_nla() already checked nla_len <= maxlen appropriately. */
252 #define __array(attr_nr, attr_flag, name, nla_type, type, maxlen, __get, __put) \
253 __assign(attr_nr, attr_flag, name, nla_type, type, \
256 __get(s->name, nla, maxlen); \
257 DPRINT_ARRAY("<<", nla_type, name, s, nla))
259 #include GENL_MAGIC_INCLUDE_FILE
262 #define GENL_struct(tag_name, tag_number, s_name, s_fields)
265 * Magic: define op number to op name mapping {{{1
268 const char *CONCAT_(GENL_MAGIC_FAMILY
, _genl_cmd_to_str
)(__u8 cmd
)
272 #define GENL_op(op_name, op_num, handler, tla_list) \
273 case op_num: return #op_name;
274 #include GENL_MAGIC_INCLUDE_FILE
281 #include <linux/stringify.h>
283 * Magic: define genl_ops {{{1
288 #define GENL_op(op_name, op_num, handler, tla_list) \
292 .policy = CONCAT_(GENL_MAGIC_FAMILY, _tla_nl_policy), \
295 #define ZZZ_genl_ops CONCAT_(GENL_MAGIC_FAMILY, _genl_ops)
296 static struct genl_ops ZZZ_genl_ops
[] __read_mostly
= {
297 #include GENL_MAGIC_INCLUDE_FILE
301 #define GENL_op(op_name, op_num, handler, tla_list)
304 * Define the genl_family, multicast groups, {{{1
305 * and provide register/unregister functions.
308 #define ZZZ_genl_family CONCAT_(GENL_MAGIC_FAMILY, _genl_family)
309 static struct genl_family ZZZ_genl_family __read_mostly
= {
310 .id
= GENL_ID_GENERATE
,
311 .name
= __stringify(GENL_MAGIC_FAMILY
),
312 .version
= GENL_MAGIC_VERSION
,
313 #ifdef GENL_MAGIC_FAMILY_HDRSZ
314 .hdrsize
= NLA_ALIGN(GENL_MAGIC_FAMILY_HDRSZ
),
316 .maxattr
= ARRAY_SIZE(drbd_tla_nl_policy
)-1,
320 * Magic: define multicast groups
321 * Magic: define multicast group registration helper
324 #define GENL_mc_group(group) \
325 static struct genl_multicast_group \
326 CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group) __read_mostly = { \
329 static int CONCAT_(GENL_MAGIC_FAMILY, _genl_multicast_ ## group)( \
330 struct sk_buff *skb, gfp_t flags) \
332 unsigned int group_id = \
333 CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id; \
336 return genlmsg_multicast(skb, 0, group_id, flags); \
339 #include GENL_MAGIC_INCLUDE_FILE
341 int CONCAT_(GENL_MAGIC_FAMILY
, _genl_register
)(void)
343 int err
= genl_register_family_with_ops(&ZZZ_genl_family
,
344 ZZZ_genl_ops
, ARRAY_SIZE(ZZZ_genl_ops
));
348 #define GENL_mc_group(group) \
349 err = genl_register_mc_group(&ZZZ_genl_family, \
350 &CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group)); \
354 pr_info("%s: mcg %s: %u\n", #group, \
355 __stringify(GENL_MAGIC_FAMILY), \
356 CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id);
358 #include GENL_MAGIC_INCLUDE_FILE
361 #define GENL_mc_group(group)
364 genl_unregister_family(&ZZZ_genl_family
);
368 void CONCAT_(GENL_MAGIC_FAMILY
, _genl_unregister
)(void)
370 genl_unregister_family(&ZZZ_genl_family
);
374 * Magic: provide conversion functions {{{1
375 * populate skb from struct.
380 #define GENL_op(op_name, op_num, handler, tla_list)
383 #define GENL_struct(tag_name, tag_number, s_name, s_fields) \
384 static int s_name ## _to_skb(struct sk_buff *skb, struct s_name *s, \
385 const bool exclude_sensitive) \
387 struct nlattr *tla = nla_nest_start(skb, tag_number); \
389 goto nla_put_failure; \
390 DPRINT_TLA(#s_name, "-=>", #tag_name); \
392 nla_nest_end(skb, tla); \
397 nla_nest_cancel(skb, tla); \
400 static inline int s_name ## _to_priv_skb(struct sk_buff *skb, \
403 return s_name ## _to_skb(skb, s, 0); \
405 static inline int s_name ## _to_unpriv_skb(struct sk_buff *skb, \
408 return s_name ## _to_skb(skb, s, 1); \
413 #define __field(attr_nr, attr_flag, name, nla_type, type, __get, __put) \
414 if (!exclude_sensitive || !((attr_flag) & GENLA_F_SENSITIVE)) { \
415 DPRINT_FIELD(">>", nla_type, name, s, NULL); \
416 __put(skb, attr_nr, s->name); \
420 #define __array(attr_nr, attr_flag, name, nla_type, type, maxlen, __get, __put) \
421 if (!exclude_sensitive || !((attr_flag) & GENLA_F_SENSITIVE)) { \
422 DPRINT_ARRAY(">>",nla_type, name, s, NULL); \
423 __put(skb, attr_nr, min_t(int, maxlen, \
424 s->name ## _len + (nla_type == NLA_NUL_STRING)),\
428 #include GENL_MAGIC_INCLUDE_FILE
430 #endif /* __KERNEL__ */
433 #endif /* GENL_MAGIC_FUNC_H */
434 /* vim: set foldmethod=marker foldlevel=1 nofoldenable : */