xref: /kernel/linux/linux-6.6/tools/net/ynl/lib/ynl.h (revision 62306a36)
1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2#ifndef __YNL_C_H
3#define __YNL_C_H 1
4
5#include <stddef.h>
6#include <libmnl/libmnl.h>
7#include <linux/genetlink.h>
8#include <linux/types.h>
9
10struct mnl_socket;
11struct nlmsghdr;
12
13/*
14 * User facing code
15 */
16
17struct ynl_ntf_base_type;
18struct ynl_ntf_info;
19struct ynl_sock;
20
21enum ynl_error_code {
22	YNL_ERROR_NONE = 0,
23	__YNL_ERRNO_END = 4096,
24	YNL_ERROR_INTERNAL,
25	YNL_ERROR_EXPECT_ACK,
26	YNL_ERROR_EXPECT_MSG,
27	YNL_ERROR_UNEXPECT_MSG,
28	YNL_ERROR_ATTR_MISSING,
29	YNL_ERROR_ATTR_INVALID,
30	YNL_ERROR_UNKNOWN_NTF,
31	YNL_ERROR_INV_RESP,
32};
33
34/**
35 * struct ynl_error - error encountered by YNL
36 * @code:	errno (low values) or YNL error code (enum ynl_error_code)
37 * @attr_offs:	offset of bad attribute (for very advanced users)
38 * @msg:	error message
39 *
40 * Error information for when YNL operations fail.
41 * Users should interact with the err member of struct ynl_sock directly.
42 * The main exception to that rule is ynl_sock_create().
43 */
44struct ynl_error {
45	enum ynl_error_code code;
46	unsigned int attr_offs;
47	char msg[512];
48};
49
50/**
51 * struct ynl_family - YNL family info
52 * Family description generated by codegen. Pass to ynl_sock_create().
53 */
54struct ynl_family {
55/* private: */
56	const char *name;
57	const struct ynl_ntf_info *ntf_info;
58	unsigned int ntf_info_size;
59};
60
61/**
62 * struct ynl_sock - YNL wrapped netlink socket
63 * @err: YNL error descriptor, cleared on every request.
64 */
65struct ynl_sock {
66	struct ynl_error err;
67
68/* private: */
69	const struct ynl_family *family;
70	struct mnl_socket *sock;
71	__u32 seq;
72	__u32 portid;
73	__u16 family_id;
74
75	unsigned int n_mcast_groups;
76	struct {
77		unsigned int id;
78		char name[GENL_NAMSIZ];
79	} *mcast_groups;
80
81	struct ynl_ntf_base_type *ntf_first;
82	struct ynl_ntf_base_type **ntf_last_next;
83
84	struct nlmsghdr *nlh;
85	struct ynl_policy_nest *req_policy;
86	unsigned char *tx_buf;
87	unsigned char *rx_buf;
88	unsigned char raw_buf[];
89};
90
91struct ynl_sock *
92ynl_sock_create(const struct ynl_family *yf, struct ynl_error *e);
93void ynl_sock_destroy(struct ynl_sock *ys);
94
95#define ynl_dump_foreach(dump, iter)					\
96	for (typeof(dump->obj) *iter = &dump->obj;			\
97	     !ynl_dump_obj_is_last(iter);				\
98	     iter = ynl_dump_obj_next(iter))
99
100int ynl_subscribe(struct ynl_sock *ys, const char *grp_name);
101int ynl_socket_get_fd(struct ynl_sock *ys);
102int ynl_ntf_check(struct ynl_sock *ys);
103
104/**
105 * ynl_has_ntf() - check if socket has *parsed* notifications
106 * @ys: active YNL socket
107 *
108 * Note that this does not take into account notifications sitting
109 * in netlink socket, just the notifications which have already been
110 * read and parsed (e.g. during a ynl_ntf_check() call).
111 */
112static inline bool ynl_has_ntf(struct ynl_sock *ys)
113{
114	return ys->ntf_last_next != &ys->ntf_first;
115}
116struct ynl_ntf_base_type *ynl_ntf_dequeue(struct ynl_sock *ys);
117
118void ynl_ntf_free(struct ynl_ntf_base_type *ntf);
119
120/*
121 * YNL internals / low level stuff
122 */
123
124/* Generic mnl helper code */
125
126enum ynl_policy_type {
127	YNL_PT_REJECT = 1,
128	YNL_PT_IGNORE,
129	YNL_PT_NEST,
130	YNL_PT_FLAG,
131	YNL_PT_BINARY,
132	YNL_PT_U8,
133	YNL_PT_U16,
134	YNL_PT_U32,
135	YNL_PT_U64,
136	YNL_PT_NUL_STR,
137};
138
139struct ynl_policy_attr {
140	enum ynl_policy_type type;
141	unsigned int len;
142	const char *name;
143	struct ynl_policy_nest *nest;
144};
145
146struct ynl_policy_nest {
147	unsigned int max_attr;
148	struct ynl_policy_attr *table;
149};
150
151struct ynl_parse_arg {
152	struct ynl_sock *ys;
153	struct ynl_policy_nest *rsp_policy;
154	void *data;
155};
156
157struct ynl_dump_list_type {
158	struct ynl_dump_list_type *next;
159	unsigned char data[] __attribute__ ((aligned (8)));
160};
161extern struct ynl_dump_list_type *YNL_LIST_END;
162
163static inline bool ynl_dump_obj_is_last(void *obj)
164{
165	unsigned long uptr = (unsigned long)obj;
166
167	uptr -= offsetof(struct ynl_dump_list_type, data);
168	return uptr == (unsigned long)YNL_LIST_END;
169}
170
171static inline void *ynl_dump_obj_next(void *obj)
172{
173	unsigned long uptr = (unsigned long)obj;
174	struct ynl_dump_list_type *list;
175
176	uptr -= offsetof(struct ynl_dump_list_type, data);
177	list = (void *)uptr;
178	uptr = (unsigned long)list->next;
179	uptr += offsetof(struct ynl_dump_list_type, data);
180
181	return (void *)uptr;
182}
183
184struct ynl_ntf_base_type {
185	__u16 family;
186	__u8 cmd;
187	struct ynl_ntf_base_type *next;
188	void (*free)(struct ynl_ntf_base_type *ntf);
189	unsigned char data[] __attribute__ ((aligned (8)));
190};
191
192extern mnl_cb_t ynl_cb_array[NLMSG_MIN_TYPE];
193
194struct nlmsghdr *
195ynl_gemsg_start_req(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version);
196struct nlmsghdr *
197ynl_gemsg_start_dump(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version);
198
199int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr);
200
201int ynl_recv_ack(struct ynl_sock *ys, int ret);
202int ynl_cb_null(const struct nlmsghdr *nlh, void *data);
203
204/* YNL specific helpers used by the auto-generated code */
205
206struct ynl_req_state {
207	struct ynl_parse_arg yarg;
208	mnl_cb_t cb;
209	__u32 rsp_cmd;
210};
211
212struct ynl_dump_state {
213	struct ynl_sock *ys;
214	struct ynl_policy_nest *rsp_policy;
215	void *first;
216	struct ynl_dump_list_type *last;
217	size_t alloc_sz;
218	mnl_cb_t cb;
219	__u32 rsp_cmd;
220};
221
222struct ynl_ntf_info {
223	struct ynl_policy_nest *policy;
224	mnl_cb_t cb;
225	size_t alloc_sz;
226	void (*free)(struct ynl_ntf_base_type *ntf);
227};
228
229int ynl_exec(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
230	     struct ynl_req_state *yrs);
231int ynl_exec_dump(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
232		  struct ynl_dump_state *yds);
233
234void ynl_error_unknown_notification(struct ynl_sock *ys, __u8 cmd);
235int ynl_error_parse(struct ynl_parse_arg *yarg, const char *msg);
236
237#endif
238