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