xref: /linux/tools/net/ynl/lib/ynl.h (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
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 <linux/genetlink.h>
7 #include <linux/types.h>
8 
9 #include "ynl-priv.h"
10 
11 enum ynl_error_code {
12 	YNL_ERROR_NONE = 0,
13 	__YNL_ERRNO_END = 4096,
14 	YNL_ERROR_INTERNAL,
15 	YNL_ERROR_DUMP_INTER,
16 	YNL_ERROR_EXPECT_ACK,
17 	YNL_ERROR_EXPECT_MSG,
18 	YNL_ERROR_UNEXPECT_MSG,
19 	YNL_ERROR_ATTR_MISSING,
20 	YNL_ERROR_ATTR_INVALID,
21 	YNL_ERROR_UNKNOWN_NTF,
22 	YNL_ERROR_INV_RESP,
23 	YNL_ERROR_INPUT_INVALID,
24 	YNL_ERROR_INPUT_TOO_BIG,
25 };
26 
27 /**
28  * struct ynl_error - error encountered by YNL
29  * @code:	errno (low values) or YNL error code (enum ynl_error_code)
30  * @attr_offs:	offset of bad attribute (for very advanced users)
31  * @msg:	error message
32  *
33  * Error information for when YNL operations fail.
34  * Users should interact with the err member of struct ynl_sock directly.
35  * The main exception to that rule is ynl_sock_create().
36  */
37 struct ynl_error {
38 	enum ynl_error_code code;
39 	unsigned int attr_offs;
40 	char msg[512];
41 };
42 
43 /**
44  * struct ynl_family - YNL family info
45  * Family description generated by codegen. Pass to ynl_sock_create().
46  */
47 struct ynl_family {
48 /* private: */
49 	const char *name;
50 	size_t hdr_len;
51 	const struct ynl_ntf_info *ntf_info;
52 	unsigned int ntf_info_size;
53 };
54 
55 /**
56  * struct ynl_sock - YNL wrapped netlink socket
57  * @err: YNL error descriptor, cleared on every request.
58  */
59 struct ynl_sock {
60 	struct ynl_error err;
61 
62 /* private: */
63 	const struct ynl_family *family;
64 	int socket;
65 	__u32 seq;
66 	__u32 portid;
67 	__u16 family_id;
68 
69 	unsigned int n_mcast_groups;
70 	struct {
71 		unsigned int id;
72 		char name[GENL_NAMSIZ];
73 	} *mcast_groups;
74 
75 	struct ynl_ntf_base_type *ntf_first;
76 	struct ynl_ntf_base_type **ntf_last_next;
77 
78 	struct nlmsghdr *nlh;
79 	const struct ynl_policy_nest *req_policy;
80 	unsigned char *tx_buf;
81 	unsigned char *rx_buf;
82 	unsigned char raw_buf[];
83 };
84 
85 struct ynl_sock *
86 ynl_sock_create(const struct ynl_family *yf, struct ynl_error *e);
87 void ynl_sock_destroy(struct ynl_sock *ys);
88 
89 #define ynl_dump_foreach(dump, iter)					\
90 	for (typeof(dump->obj) *iter = &dump->obj;			\
91 	     !ynl_dump_obj_is_last(iter);				\
92 	     iter = ynl_dump_obj_next(iter))
93 
94 /**
95  * ynl_dump_empty() - does the dump have no entries
96  * @dump: pointer to the dump list, as returned by a dump call
97  *
98  * Check if the dump is empty, i.e. contains no objects.
99  * Dump calls return NULL on error, and terminator element if empty.
100  */
ynl_dump_empty(void * dump)101 static inline bool ynl_dump_empty(void *dump)
102 {
103 	return dump == (void *)YNL_LIST_END;
104 }
105 
106 int ynl_subscribe(struct ynl_sock *ys, const char *grp_name);
107 int ynl_socket_get_fd(struct ynl_sock *ys);
108 int ynl_ntf_check(struct ynl_sock *ys);
109 
110 /**
111  * ynl_has_ntf() - check if socket has *parsed* notifications
112  * @ys: active YNL socket
113  *
114  * Note that this does not take into account notifications sitting
115  * in netlink socket, just the notifications which have already been
116  * read and parsed (e.g. during a ynl_ntf_check() call).
117  */
ynl_has_ntf(struct ynl_sock * ys)118 static inline bool ynl_has_ntf(struct ynl_sock *ys)
119 {
120 	return ys->ntf_last_next != &ys->ntf_first;
121 }
122 struct ynl_ntf_base_type *ynl_ntf_dequeue(struct ynl_sock *ys);
123 
124 void ynl_ntf_free(struct ynl_ntf_base_type *ntf);
125 #endif
126