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