| // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause | |
| #ifndef __YNL_C_H | |
| #define __YNL_C_H 1 | |
| #include <stdbool.h> | |
| #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, | |
| YNL_ERROR_SUBMSG_KEY, | |
| }; | |
| /** | |
| * 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; | |
| bool is_classic; | |
| __u16 classic_id; | |
| 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; | |
| size_t req_hdr_len; | |
| unsigned char *tx_buf; | |
| unsigned char *rx_buf; | |
| unsigned char raw_buf[]; | |
| }; | |
| /** | |
| * struct ynl_string - parsed individual string | |
| * @len: length of the string (excluding terminating character) | |
| * @str: value of the string | |
| * | |
| * Parsed and nul-terminated string. This struct is only used for arrays of | |
| * strings. Non-array string members are placed directly in respective types. | |
| */ | |
| struct ynl_string { | |
| unsigned int len; | |
| char str[]; | |
| }; | |
| 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 |