File Index
Files and directories
Sign in
FILE

ynl-priv.h

File preview with syntax highlighting.

linux-6.19.14/tools/net/ynl/lib/ynl-priv.h C
  1/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
  2#ifndef __YNL_C_PRIV_H
  3#define __YNL_C_PRIV_H 1
  4
  5#include <stdbool.h>
  6#include <stddef.h>
  7#include <linux/types.h>
  8
  9struct ynl_parse_arg;
 10
 11/*
 12 * YNL internals / low level stuff
 13 */
 14
 15enum ynl_policy_type {
 16	YNL_PT_REJECT = 1,
 17	YNL_PT_IGNORE,
 18	YNL_PT_NEST,
 19	YNL_PT_FLAG,
 20	YNL_PT_BINARY,
 21	YNL_PT_U8,
 22	YNL_PT_U16,
 23	YNL_PT_U32,
 24	YNL_PT_U64,
 25	YNL_PT_UINT,
 26	YNL_PT_NUL_STR,
 27	YNL_PT_BITFIELD32,
 28	YNL_PT_SUBMSG,
 29};
 30
 31enum ynl_parse_result {
 32	YNL_PARSE_CB_ERROR = -1,
 33	YNL_PARSE_CB_STOP = 0,
 34	YNL_PARSE_CB_OK = 1,
 35};
 36
 37#define YNL_SOCKET_BUFFER_SIZE		(1 << 17)
 38
 39#define YNL_ARRAY_SIZE(array)	(sizeof(array) ?			\
 40				 sizeof(array) / sizeof(array[0]) : 0)
 41
 42typedef int (*ynl_parse_cb_t)(const struct nlmsghdr *nlh,
 43			      struct ynl_parse_arg *yarg);
 44
 45struct ynl_policy_attr {
 46	enum ynl_policy_type type:8;
 47	__u8 is_submsg:1;
 48	__u8 is_selector:1;
 49	__u16 selector_type;
 50	unsigned int len;
 51	const char *name;
 52	const struct ynl_policy_nest *nest;
 53};
 54
 55struct ynl_policy_nest {
 56	unsigned int max_attr;
 57	const struct ynl_policy_attr *table;
 58};
 59
 60struct ynl_parse_arg {
 61	struct ynl_sock *ys;
 62	const struct ynl_policy_nest *rsp_policy;
 63	void *data;
 64};
 65
 66struct ynl_dump_list_type {
 67	struct ynl_dump_list_type *next;
 68	unsigned char data[] __attribute__((aligned(8)));
 69};
 70extern struct ynl_dump_list_type *YNL_LIST_END;
 71
 72static inline bool ynl_dump_obj_is_last(void *obj)
 73{
 74	unsigned long uptr = (unsigned long)obj;
 75
 76	uptr -= offsetof(struct ynl_dump_list_type, data);
 77	return uptr == (unsigned long)YNL_LIST_END;
 78}
 79
 80static inline void *ynl_dump_obj_next(void *obj)
 81{
 82	unsigned long uptr = (unsigned long)obj;
 83	struct ynl_dump_list_type *list;
 84
 85	uptr -= offsetof(struct ynl_dump_list_type, data);
 86	list = (struct ynl_dump_list_type *)uptr;
 87	uptr = (unsigned long)list->next;
 88	uptr += offsetof(struct ynl_dump_list_type, data);
 89
 90	return (void *)uptr;
 91}
 92
 93struct ynl_ntf_base_type {
 94	__u16 family;
 95	__u8 cmd;
 96	struct ynl_ntf_base_type *next;
 97	void (*free)(struct ynl_ntf_base_type *ntf);
 98	unsigned char data[] __attribute__((aligned(8)));
 99};
100
101struct nlmsghdr *ynl_msg_start_req(struct ynl_sock *ys, __u32 id, __u16 flags);
102struct nlmsghdr *ynl_msg_start_dump(struct ynl_sock *ys, __u32 id);
103
104struct nlmsghdr *
105ynl_gemsg_start_req(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version);
106struct nlmsghdr *
107ynl_gemsg_start_dump(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version);
108
109int ynl_submsg_failed(struct ynl_parse_arg *yarg, const char *field_name,
110		      const char *sel_name);
111
112/* YNL specific helpers used by the auto-generated code */
113
114struct ynl_req_state {
115	struct ynl_parse_arg yarg;
116	ynl_parse_cb_t cb;
117	__u32 rsp_cmd;
118};
119
120struct ynl_dump_state {
121	struct ynl_parse_arg yarg;
122	void *first;
123	struct ynl_dump_list_type *last;
124	size_t alloc_sz;
125	ynl_parse_cb_t cb;
126	__u32 rsp_cmd;
127};
128
129struct ynl_ntf_info {
130	const struct ynl_policy_nest *policy;
131	ynl_parse_cb_t cb;
132	size_t alloc_sz;
133	void (*free)(struct ynl_ntf_base_type *ntf);
134};
135
136int ynl_exec(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
137	     struct ynl_req_state *yrs);
138int ynl_exec_dump(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
139		  struct ynl_dump_state *yds);
140
141void ynl_error_unknown_notification(struct ynl_sock *ys, __u8 cmd);
142int ynl_error_parse(struct ynl_parse_arg *yarg, const char *msg);
143
144/* Netlink message handling helpers */
145
146#define YNL_MSG_OVERFLOW	1
147
148static inline struct nlmsghdr *ynl_nlmsg_put_header(void *buf)
149{
150	struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
151
152	memset(nlh, 0, sizeof(*nlh));
153	nlh->nlmsg_len = NLMSG_HDRLEN;
154
155	return nlh;
156}
157
158static inline unsigned int ynl_nlmsg_data_len(const struct nlmsghdr *nlh)
159{
160	return nlh->nlmsg_len - NLMSG_HDRLEN;
161}
162
163static inline void *ynl_nlmsg_data(const struct nlmsghdr *nlh)
164{
165	return (unsigned char *)nlh + NLMSG_HDRLEN;
166}
167
168static inline void *
169ynl_nlmsg_data_offset(const struct nlmsghdr *nlh, unsigned int offset)
170{
171	return (unsigned char *)nlh + NLMSG_HDRLEN + offset;
172}
173
174static inline void *ynl_nlmsg_end_addr(const struct nlmsghdr *nlh)
175{
176	return (char *)nlh + nlh->nlmsg_len;
177}
178
179static inline void *
180ynl_nlmsg_put_extra_header(struct nlmsghdr *nlh, unsigned int size)
181{
182	void *tail = ynl_nlmsg_end_addr(nlh);
183
184	nlh->nlmsg_len += NLMSG_ALIGN(size);
185	return tail;
186}
187
188/* Netlink attribute helpers */
189
190static inline unsigned int ynl_attr_type(const struct nlattr *attr)
191{
192	return attr->nla_type & NLA_TYPE_MASK;
193}
194
195static inline unsigned int ynl_attr_data_len(const struct nlattr *attr)
196{
197	return attr->nla_len - NLA_HDRLEN;
198}
199
200static inline void *ynl_attr_data(const struct nlattr *attr)
201{
202	return (unsigned char *)attr + NLA_HDRLEN;
203}
204
205static inline void *ynl_attr_data_end(const struct nlattr *attr)
206{
207	return (char *)ynl_attr_data(attr) + ynl_attr_data_len(attr);
208}
209
210#define ynl_attr_for_each(attr, nlh, fixed_hdr_sz)			\
211	for ((attr) = ynl_attr_first(nlh, (nlh)->nlmsg_len,		\
212				     NLMSG_HDRLEN + fixed_hdr_sz); attr; \
213	     (attr) = ynl_attr_next(ynl_nlmsg_end_addr(nlh), attr))
214
215#define ynl_attr_for_each_nested_off(attr, outer, offset)		\
216	for ((attr) = ynl_attr_first(outer, outer->nla_len,		\
217				     sizeof(struct nlattr) + offset);	\
218	     attr;							\
219	     (attr) = ynl_attr_next(ynl_attr_data_end(outer), attr))
220
221#define ynl_attr_for_each_nested(attr, outer)				\
222	ynl_attr_for_each_nested_off(attr, outer, 0)
223
224#define ynl_attr_for_each_payload(start, len, attr)			\
225	for ((attr) = ynl_attr_first(start, len, 0); attr;		\
226	     (attr) = ynl_attr_next(start + len, attr))
227
228static inline struct nlattr *
229ynl_attr_if_good(const void *end, struct nlattr *attr)
230{
231	if (attr + 1 > (const struct nlattr *)end)
232		return NULL;
233	if (ynl_attr_data_end(attr) > end)
234		return NULL;
235	return attr;
236}
237
238static inline struct nlattr *
239ynl_attr_next(const void *end, const struct nlattr *prev)
240{
241	struct nlattr *attr;
242
243	attr = (struct nlattr *)((char *)prev + NLA_ALIGN(prev->nla_len));
244	return ynl_attr_if_good(end, attr);
245}
246
247static inline struct nlattr *
248ynl_attr_first(const void *start, size_t len, size_t skip)
249{
250	struct nlattr *attr;
251
252	attr = (struct nlattr *)((char *)start + NLMSG_ALIGN(skip));
253	return ynl_attr_if_good((char *)start + len, attr);
254}
255
256static inline bool
257__ynl_attr_put_overflow(struct nlmsghdr *nlh, size_t size)
258{
259	bool o;
260
261	/* ynl_msg_start() stashed buffer length in nlmsg_pid. */
262	o = nlh->nlmsg_len + NLA_HDRLEN + NLMSG_ALIGN(size) > nlh->nlmsg_pid;
263	if (o)
264		/* YNL_MSG_OVERFLOW is < NLMSG_HDRLEN, all subsequent checks
265		 * are guaranteed to fail.
266		 */
267		nlh->nlmsg_pid = YNL_MSG_OVERFLOW;
268	return o;
269}
270
271static inline struct nlattr *
272ynl_attr_nest_start(struct nlmsghdr *nlh, unsigned int attr_type)
273{
274	struct nlattr *attr;
275
276	if (__ynl_attr_put_overflow(nlh, 0))
277		return (struct nlattr *)ynl_nlmsg_end_addr(nlh) - 1;
278
279	attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);
280	attr->nla_type = attr_type | NLA_F_NESTED;
281	nlh->nlmsg_len += NLA_HDRLEN;
282
283	return attr;
284}
285
286static inline void
287ynl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *attr)
288{
289	attr->nla_len = (char *)ynl_nlmsg_end_addr(nlh) - (char *)attr;
290}
291
292static inline void
293ynl_attr_put(struct nlmsghdr *nlh, unsigned int attr_type,
294	     const void *value, size_t size)
295{
296	struct nlattr *attr;
297
298	if (__ynl_attr_put_overflow(nlh, size))
299		return;
300
301	attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);
302	attr->nla_type = attr_type;
303	attr->nla_len = NLA_HDRLEN + size;
304
305	memcpy(ynl_attr_data(attr), value, size);
306
307	nlh->nlmsg_len += NLMSG_ALIGN(attr->nla_len);
308}
309
310static inline void
311ynl_attr_put_str(struct nlmsghdr *nlh, unsigned int attr_type, const char *str)
312{
313	struct nlattr *attr;
314	size_t len;
315
316	len = strlen(str) + 1;
317	if (__ynl_attr_put_overflow(nlh, len))
318		return;
319
320	attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);
321	attr->nla_type = attr_type;
322
323	strcpy((char *)ynl_attr_data(attr), str);
324	attr->nla_len = NLA_HDRLEN + len;
325
326	nlh->nlmsg_len += NLMSG_ALIGN(attr->nla_len);
327}
328
329static inline const char *ynl_attr_get_str(const struct nlattr *attr)
330{
331	return (const char *)ynl_attr_data(attr);
332}
333
334static inline __s8 ynl_attr_get_s8(const struct nlattr *attr)
335{
336	return *(__s8 *)ynl_attr_data(attr);
337}
338
339static inline __s16 ynl_attr_get_s16(const struct nlattr *attr)
340{
341	return *(__s16 *)ynl_attr_data(attr);
342}
343
344static inline __s32 ynl_attr_get_s32(const struct nlattr *attr)
345{
346	return *(__s32 *)ynl_attr_data(attr);
347}
348
349static inline __s64 ynl_attr_get_s64(const struct nlattr *attr)
350{
351	__s64 tmp;
352
353	memcpy(&tmp, (unsigned char *)(attr + 1), sizeof(tmp));
354	return tmp;
355}
356
357static inline __u8 ynl_attr_get_u8(const struct nlattr *attr)
358{
359	return *(__u8 *)ynl_attr_data(attr);
360}
361
362static inline __u16 ynl_attr_get_u16(const struct nlattr *attr)
363{
364	return *(__u16 *)ynl_attr_data(attr);
365}
366
367static inline __u32 ynl_attr_get_u32(const struct nlattr *attr)
368{
369	return *(__u32 *)ynl_attr_data(attr);
370}
371
372static inline __u64 ynl_attr_get_u64(const struct nlattr *attr)
373{
374	__u64 tmp;
375
376	memcpy(&tmp, (unsigned char *)(attr + 1), sizeof(tmp));
377	return tmp;
378}
379
380static inline void
381ynl_attr_put_s8(struct nlmsghdr *nlh, unsigned int attr_type, __s8 value)
382{
383	ynl_attr_put(nlh, attr_type, &value, sizeof(value));
384}
385
386static inline void
387ynl_attr_put_s16(struct nlmsghdr *nlh, unsigned int attr_type, __s16 value)
388{
389	ynl_attr_put(nlh, attr_type, &value, sizeof(value));
390}
391
392static inline void
393ynl_attr_put_s32(struct nlmsghdr *nlh, unsigned int attr_type, __s32 value)
394{
395	ynl_attr_put(nlh, attr_type, &value, sizeof(value));
396}
397
398static inline void
399ynl_attr_put_s64(struct nlmsghdr *nlh, unsigned int attr_type, __s64 value)
400{
401	ynl_attr_put(nlh, attr_type, &value, sizeof(value));
402}
403
404static inline void
405ynl_attr_put_u8(struct nlmsghdr *nlh, unsigned int attr_type, __u8 value)
406{
407	ynl_attr_put(nlh, attr_type, &value, sizeof(value));
408}
409
410static inline void
411ynl_attr_put_u16(struct nlmsghdr *nlh, unsigned int attr_type, __u16 value)
412{
413	ynl_attr_put(nlh, attr_type, &value, sizeof(value));
414}
415
416static inline void
417ynl_attr_put_u32(struct nlmsghdr *nlh, unsigned int attr_type, __u32 value)
418{
419	ynl_attr_put(nlh, attr_type, &value, sizeof(value));
420}
421
422static inline void
423ynl_attr_put_u64(struct nlmsghdr *nlh, unsigned int attr_type, __u64 value)
424{
425	ynl_attr_put(nlh, attr_type, &value, sizeof(value));
426}
427
428static inline __u64 ynl_attr_get_uint(const struct nlattr *attr)
429{
430	switch (ynl_attr_data_len(attr)) {
431	case 4:
432		return ynl_attr_get_u32(attr);
433	case 8:
434		return ynl_attr_get_u64(attr);
435	default:
436		return 0;
437	}
438}
439
440static inline __s64 ynl_attr_get_sint(const struct nlattr *attr)
441{
442	switch (ynl_attr_data_len(attr)) {
443	case 4:
444		return ynl_attr_get_s32(attr);
445	case 8:
446		return ynl_attr_get_s64(attr);
447	default:
448		return 0;
449	}
450}
451
452static inline void
453ynl_attr_put_uint(struct nlmsghdr *nlh, __u16 type, __u64 data)
454{
455	if ((__u32)data == (__u64)data)
456		ynl_attr_put_u32(nlh, type, data);
457	else
458		ynl_attr_put_u64(nlh, type, data);
459}
460
461static inline void
462ynl_attr_put_sint(struct nlmsghdr *nlh, __u16 type, __s64 data)
463{
464	if ((__s32)data == (__s64)data)
465		ynl_attr_put_s32(nlh, type, data);
466	else
467		ynl_attr_put_s64(nlh, type, data);
468}
469
470int __ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr,
471			unsigned int type);
472
473static inline int ynl_attr_validate(struct ynl_parse_arg *yarg,
474				    const struct nlattr *attr)
475{
476	return __ynl_attr_validate(yarg, attr, ynl_attr_type(attr));
477}
478#endif
~/ Read-only file preview.