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