1 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
3 #define __YNL_C_PRIV_H 1
7 #include <linux/types.h>
12 * YNL internals / low level stuff
15 enum ynl_policy_type
{
30 enum ynl_parse_result
{
31 YNL_PARSE_CB_ERROR
= -1,
32 YNL_PARSE_CB_STOP
= 0,
36 #define YNL_SOCKET_BUFFER_SIZE (1 << 17)
38 #define YNL_ARRAY_SIZE(array) (sizeof(array) ? \
39 sizeof(array) / sizeof(array[0]) : 0)
41 typedef int (*ynl_parse_cb_t
)(const struct nlmsghdr
*nlh
,
42 struct ynl_parse_arg
*yarg
);
44 struct ynl_policy_attr
{
45 enum ynl_policy_type type
;
48 const struct ynl_policy_nest
*nest
;
51 struct ynl_policy_nest
{
52 unsigned int max_attr
;
53 const struct ynl_policy_attr
*table
;
56 struct ynl_parse_arg
{
58 const struct ynl_policy_nest
*rsp_policy
;
62 struct ynl_dump_list_type
{
63 struct ynl_dump_list_type
*next
;
64 unsigned char data
[] __attribute__((aligned(8)));
66 extern struct ynl_dump_list_type
*YNL_LIST_END
;
68 static inline bool ynl_dump_obj_is_last(void *obj
)
70 unsigned long uptr
= (unsigned long)obj
;
72 uptr
-= offsetof(struct ynl_dump_list_type
, data
);
73 return uptr
== (unsigned long)YNL_LIST_END
;
76 static inline void *ynl_dump_obj_next(void *obj
)
78 unsigned long uptr
= (unsigned long)obj
;
79 struct ynl_dump_list_type
*list
;
81 uptr
-= offsetof(struct ynl_dump_list_type
, data
);
82 list
= (struct ynl_dump_list_type
*)uptr
;
83 uptr
= (unsigned long)list
->next
;
84 uptr
+= offsetof(struct ynl_dump_list_type
, data
);
89 struct ynl_ntf_base_type
{
92 struct ynl_ntf_base_type
*next
;
93 void (*free
)(struct ynl_ntf_base_type
*ntf
);
94 unsigned char data
[] __attribute__((aligned(8)));
98 ynl_gemsg_start_req(struct ynl_sock
*ys
, __u32 id
, __u8 cmd
, __u8 version
);
100 ynl_gemsg_start_dump(struct ynl_sock
*ys
, __u32 id
, __u8 cmd
, __u8 version
);
102 int ynl_attr_validate(struct ynl_parse_arg
*yarg
, const struct nlattr
*attr
);
104 /* YNL specific helpers used by the auto-generated code */
106 struct ynl_req_state
{
107 struct ynl_parse_arg yarg
;
112 struct ynl_dump_state
{
113 struct ynl_parse_arg yarg
;
115 struct ynl_dump_list_type
*last
;
121 struct ynl_ntf_info
{
122 const struct ynl_policy_nest
*policy
;
125 void (*free
)(struct ynl_ntf_base_type
*ntf
);
128 int ynl_exec(struct ynl_sock
*ys
, struct nlmsghdr
*req_nlh
,
129 struct ynl_req_state
*yrs
);
130 int ynl_exec_dump(struct ynl_sock
*ys
, struct nlmsghdr
*req_nlh
,
131 struct ynl_dump_state
*yds
);
133 void ynl_error_unknown_notification(struct ynl_sock
*ys
, __u8 cmd
);
134 int ynl_error_parse(struct ynl_parse_arg
*yarg
, const char *msg
);
136 /* Netlink message handling helpers */
138 #define YNL_MSG_OVERFLOW 1
140 static inline struct nlmsghdr
*ynl_nlmsg_put_header(void *buf
)
142 struct nlmsghdr
*nlh
= (struct nlmsghdr
*)buf
;
144 memset(nlh
, 0, sizeof(*nlh
));
145 nlh
->nlmsg_len
= NLMSG_HDRLEN
;
150 static inline unsigned int ynl_nlmsg_data_len(const struct nlmsghdr
*nlh
)
152 return nlh
->nlmsg_len
- NLMSG_HDRLEN
;
155 static inline void *ynl_nlmsg_data(const struct nlmsghdr
*nlh
)
157 return (unsigned char *)nlh
+ NLMSG_HDRLEN
;
161 ynl_nlmsg_data_offset(const struct nlmsghdr
*nlh
, unsigned int offset
)
163 return (unsigned char *)nlh
+ NLMSG_HDRLEN
+ offset
;
166 static inline void *ynl_nlmsg_end_addr(const struct nlmsghdr
*nlh
)
168 return (char *)nlh
+ nlh
->nlmsg_len
;
172 ynl_nlmsg_put_extra_header(struct nlmsghdr
*nlh
, unsigned int size
)
174 void *tail
= ynl_nlmsg_end_addr(nlh
);
176 nlh
->nlmsg_len
+= NLMSG_ALIGN(size
);
180 /* Netlink attribute helpers */
182 static inline unsigned int ynl_attr_type(const struct nlattr
*attr
)
184 return attr
->nla_type
& NLA_TYPE_MASK
;
187 static inline unsigned int ynl_attr_data_len(const struct nlattr
*attr
)
189 return attr
->nla_len
- NLA_HDRLEN
;
192 static inline void *ynl_attr_data(const struct nlattr
*attr
)
194 return (unsigned char *)attr
+ NLA_HDRLEN
;
197 static inline void *ynl_attr_data_end(const struct nlattr
*attr
)
199 return (char *)ynl_attr_data(attr
) + ynl_attr_data_len(attr
);
202 #define ynl_attr_for_each(attr, nlh, fixed_hdr_sz) \
203 for ((attr) = ynl_attr_first(nlh, (nlh)->nlmsg_len, \
204 NLMSG_HDRLEN + fixed_hdr_sz); attr; \
205 (attr) = ynl_attr_next(ynl_nlmsg_end_addr(nlh), attr))
207 #define ynl_attr_for_each_nested(attr, outer) \
208 for ((attr) = ynl_attr_first(outer, outer->nla_len, \
209 sizeof(struct nlattr)); attr; \
210 (attr) = ynl_attr_next(ynl_attr_data_end(outer), attr))
212 #define ynl_attr_for_each_payload(start, len, attr) \
213 for ((attr) = ynl_attr_first(start, len, 0); attr; \
214 (attr) = ynl_attr_next(start + len, attr))
216 static inline struct nlattr
*
217 ynl_attr_if_good(const void *end
, struct nlattr
*attr
)
219 if (attr
+ 1 > (const struct nlattr
*)end
)
221 if (ynl_attr_data_end(attr
) > end
)
226 static inline struct nlattr
*
227 ynl_attr_next(const void *end
, const struct nlattr
*prev
)
231 attr
= (struct nlattr
*)((char *)prev
+ NLA_ALIGN(prev
->nla_len
));
232 return ynl_attr_if_good(end
, attr
);
235 static inline struct nlattr
*
236 ynl_attr_first(const void *start
, size_t len
, size_t skip
)
240 attr
= (struct nlattr
*)((char *)start
+ NLMSG_ALIGN(skip
));
241 return ynl_attr_if_good((char *)start
+ len
, attr
);
245 __ynl_attr_put_overflow(struct nlmsghdr
*nlh
, size_t size
)
249 /* ynl_msg_start() stashed buffer length in nlmsg_pid. */
250 o
= nlh
->nlmsg_len
+ NLA_HDRLEN
+ NLMSG_ALIGN(size
) > nlh
->nlmsg_pid
;
252 /* YNL_MSG_OVERFLOW is < NLMSG_HDRLEN, all subsequent checks
253 * are guaranteed to fail.
255 nlh
->nlmsg_pid
= YNL_MSG_OVERFLOW
;
259 static inline struct nlattr
*
260 ynl_attr_nest_start(struct nlmsghdr
*nlh
, unsigned int attr_type
)
264 if (__ynl_attr_put_overflow(nlh
, 0))
265 return (struct nlattr
*)ynl_nlmsg_end_addr(nlh
) - 1;
267 attr
= (struct nlattr
*)ynl_nlmsg_end_addr(nlh
);
268 attr
->nla_type
= attr_type
| NLA_F_NESTED
;
269 nlh
->nlmsg_len
+= NLA_HDRLEN
;
275 ynl_attr_nest_end(struct nlmsghdr
*nlh
, struct nlattr
*attr
)
277 attr
->nla_len
= (char *)ynl_nlmsg_end_addr(nlh
) - (char *)attr
;
281 ynl_attr_put(struct nlmsghdr
*nlh
, unsigned int attr_type
,
282 const void *value
, size_t size
)
286 if (__ynl_attr_put_overflow(nlh
, size
))
289 attr
= (struct nlattr
*)ynl_nlmsg_end_addr(nlh
);
290 attr
->nla_type
= attr_type
;
291 attr
->nla_len
= NLA_HDRLEN
+ size
;
293 memcpy(ynl_attr_data(attr
), value
, size
);
295 nlh
->nlmsg_len
+= NLMSG_ALIGN(attr
->nla_len
);
299 ynl_attr_put_str(struct nlmsghdr
*nlh
, unsigned int attr_type
, const char *str
)
305 if (__ynl_attr_put_overflow(nlh
, len
))
308 attr
= (struct nlattr
*)ynl_nlmsg_end_addr(nlh
);
309 attr
->nla_type
= attr_type
;
311 strcpy((char *)ynl_attr_data(attr
), str
);
312 attr
->nla_len
= NLA_HDRLEN
+ NLA_ALIGN(len
);
314 nlh
->nlmsg_len
+= NLMSG_ALIGN(attr
->nla_len
);
317 static inline const char *ynl_attr_get_str(const struct nlattr
*attr
)
319 return (const char *)ynl_attr_data(attr
);
322 static inline __s8
ynl_attr_get_s8(const struct nlattr
*attr
)
324 return *(__s8
*)ynl_attr_data(attr
);
327 static inline __s16
ynl_attr_get_s16(const struct nlattr
*attr
)
329 return *(__s16
*)ynl_attr_data(attr
);
332 static inline __s32
ynl_attr_get_s32(const struct nlattr
*attr
)
334 return *(__s32
*)ynl_attr_data(attr
);
337 static inline __s64
ynl_attr_get_s64(const struct nlattr
*attr
)
341 memcpy(&tmp
, (unsigned char *)(attr
+ 1), sizeof(tmp
));
345 static inline __u8
ynl_attr_get_u8(const struct nlattr
*attr
)
347 return *(__u8
*)ynl_attr_data(attr
);
350 static inline __u16
ynl_attr_get_u16(const struct nlattr
*attr
)
352 return *(__u16
*)ynl_attr_data(attr
);
355 static inline __u32
ynl_attr_get_u32(const struct nlattr
*attr
)
357 return *(__u32
*)ynl_attr_data(attr
);
360 static inline __u64
ynl_attr_get_u64(const struct nlattr
*attr
)
364 memcpy(&tmp
, (unsigned char *)(attr
+ 1), sizeof(tmp
));
369 ynl_attr_put_s8(struct nlmsghdr
*nlh
, unsigned int attr_type
, __s8 value
)
371 ynl_attr_put(nlh
, attr_type
, &value
, sizeof(value
));
375 ynl_attr_put_s16(struct nlmsghdr
*nlh
, unsigned int attr_type
, __s16 value
)
377 ynl_attr_put(nlh
, attr_type
, &value
, sizeof(value
));
381 ynl_attr_put_s32(struct nlmsghdr
*nlh
, unsigned int attr_type
, __s32 value
)
383 ynl_attr_put(nlh
, attr_type
, &value
, sizeof(value
));
387 ynl_attr_put_s64(struct nlmsghdr
*nlh
, unsigned int attr_type
, __s64 value
)
389 ynl_attr_put(nlh
, attr_type
, &value
, sizeof(value
));
393 ynl_attr_put_u8(struct nlmsghdr
*nlh
, unsigned int attr_type
, __u8 value
)
395 ynl_attr_put(nlh
, attr_type
, &value
, sizeof(value
));
399 ynl_attr_put_u16(struct nlmsghdr
*nlh
, unsigned int attr_type
, __u16 value
)
401 ynl_attr_put(nlh
, attr_type
, &value
, sizeof(value
));
405 ynl_attr_put_u32(struct nlmsghdr
*nlh
, unsigned int attr_type
, __u32 value
)
407 ynl_attr_put(nlh
, attr_type
, &value
, sizeof(value
));
411 ynl_attr_put_u64(struct nlmsghdr
*nlh
, unsigned int attr_type
, __u64 value
)
413 ynl_attr_put(nlh
, attr_type
, &value
, sizeof(value
));
416 static inline __u64
ynl_attr_get_uint(const struct nlattr
*attr
)
418 switch (ynl_attr_data_len(attr
)) {
420 return ynl_attr_get_u32(attr
);
422 return ynl_attr_get_u64(attr
);
428 static inline __s64
ynl_attr_get_sint(const struct nlattr
*attr
)
430 switch (ynl_attr_data_len(attr
)) {
432 return ynl_attr_get_s32(attr
);
434 return ynl_attr_get_s64(attr
);
441 ynl_attr_put_uint(struct nlmsghdr
*nlh
, __u16 type
, __u64 data
)
443 if ((__u32
)data
== (__u64
)data
)
444 ynl_attr_put_u32(nlh
, type
, data
);
446 ynl_attr_put_u64(nlh
, type
, data
);
450 ynl_attr_put_sint(struct nlmsghdr
*nlh
, __u16 type
, __s64 data
)
452 if ((__s32
)data
== (__s64
)data
)
453 ynl_attr_put_s32(nlh
, type
, data
);
455 ynl_attr_put_s64(nlh
, type
, data
);