|  | // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause | 
|  | #ifndef __YNL_C_H | 
|  | #define __YNL_C_H 1 | 
|  |  | 
|  | #include <stddef.h> | 
|  | #include <linux/genetlink.h> | 
|  | #include <linux/types.h> | 
|  |  | 
|  | #include "ynl-priv.h" | 
|  |  | 
|  | enum ynl_error_code { | 
|  | YNL_ERROR_NONE = 0, | 
|  | __YNL_ERRNO_END = 4096, | 
|  | YNL_ERROR_INTERNAL, | 
|  | YNL_ERROR_DUMP_INTER, | 
|  | 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, | 
|  | YNL_ERROR_INPUT_INVALID, | 
|  | YNL_ERROR_INPUT_TOO_BIG, | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * 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; | 
|  | size_t hdr_len; | 
|  | 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; | 
|  | int socket; | 
|  | __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; | 
|  | const 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)) | 
|  |  | 
|  | /** | 
|  | * ynl_dump_empty() - does the dump have no entries | 
|  | * @dump: pointer to the dump list, as returned by a dump call | 
|  | * | 
|  | * Check if the dump is empty, i.e. contains no objects. | 
|  | * Dump calls return NULL on error, and terminator element if empty. | 
|  | */ | 
|  | static inline bool ynl_dump_empty(void *dump) | 
|  | { | 
|  | return dump == (void *)YNL_LIST_END; | 
|  | } | 
|  |  | 
|  | 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); | 
|  | #endif |