| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 |
- /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
- #ifndef __YNL_C_PRIV_H
- #define __YNL_C_PRIV_H 1
- #include <stdbool.h>
- #include <stddef.h>
- #include <linux/types.h>
- struct ynl_parse_arg;
- /*
- * YNL internals / low level stuff
- */
- 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_UINT,
- YNL_PT_NUL_STR,
- YNL_PT_BITFIELD32,
- };
- enum ynl_parse_result {
- YNL_PARSE_CB_ERROR = -1,
- YNL_PARSE_CB_STOP = 0,
- YNL_PARSE_CB_OK = 1,
- };
- #define YNL_SOCKET_BUFFER_SIZE (1 << 17)
- #define YNL_ARRAY_SIZE(array) (sizeof(array) ? \
- sizeof(array) / sizeof(array[0]) : 0)
- typedef int (*ynl_parse_cb_t)(const struct nlmsghdr *nlh,
- struct ynl_parse_arg *yarg);
- struct ynl_policy_attr {
- enum ynl_policy_type type;
- unsigned int len;
- const char *name;
- const struct ynl_policy_nest *nest;
- };
- struct ynl_policy_nest {
- unsigned int max_attr;
- const struct ynl_policy_attr *table;
- };
- struct ynl_parse_arg {
- struct ynl_sock *ys;
- const 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 = (struct ynl_dump_list_type *)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)));
- };
- 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);
- /* YNL specific helpers used by the auto-generated code */
- struct ynl_req_state {
- struct ynl_parse_arg yarg;
- ynl_parse_cb_t cb;
- __u32 rsp_cmd;
- };
- struct ynl_dump_state {
- struct ynl_parse_arg yarg;
- void *first;
- struct ynl_dump_list_type *last;
- size_t alloc_sz;
- ynl_parse_cb_t cb;
- __u32 rsp_cmd;
- };
- struct ynl_ntf_info {
- const struct ynl_policy_nest *policy;
- ynl_parse_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);
- /* Netlink message handling helpers */
- #define YNL_MSG_OVERFLOW 1
- static inline struct nlmsghdr *ynl_nlmsg_put_header(void *buf)
- {
- struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
- memset(nlh, 0, sizeof(*nlh));
- nlh->nlmsg_len = NLMSG_HDRLEN;
- return nlh;
- }
- static inline unsigned int ynl_nlmsg_data_len(const struct nlmsghdr *nlh)
- {
- return nlh->nlmsg_len - NLMSG_HDRLEN;
- }
- static inline void *ynl_nlmsg_data(const struct nlmsghdr *nlh)
- {
- return (unsigned char *)nlh + NLMSG_HDRLEN;
- }
- static inline void *
- ynl_nlmsg_data_offset(const struct nlmsghdr *nlh, unsigned int offset)
- {
- return (unsigned char *)nlh + NLMSG_HDRLEN + offset;
- }
- static inline void *ynl_nlmsg_end_addr(const struct nlmsghdr *nlh)
- {
- return (char *)nlh + nlh->nlmsg_len;
- }
- static inline void *
- ynl_nlmsg_put_extra_header(struct nlmsghdr *nlh, unsigned int size)
- {
- void *tail = ynl_nlmsg_end_addr(nlh);
- nlh->nlmsg_len += NLMSG_ALIGN(size);
- return tail;
- }
- /* Netlink attribute helpers */
- static inline unsigned int ynl_attr_type(const struct nlattr *attr)
- {
- return attr->nla_type & NLA_TYPE_MASK;
- }
- static inline unsigned int ynl_attr_data_len(const struct nlattr *attr)
- {
- return attr->nla_len - NLA_HDRLEN;
- }
- static inline void *ynl_attr_data(const struct nlattr *attr)
- {
- return (unsigned char *)attr + NLA_HDRLEN;
- }
- static inline void *ynl_attr_data_end(const struct nlattr *attr)
- {
- return (char *)ynl_attr_data(attr) + ynl_attr_data_len(attr);
- }
- #define ynl_attr_for_each(attr, nlh, fixed_hdr_sz) \
- for ((attr) = ynl_attr_first(nlh, (nlh)->nlmsg_len, \
- NLMSG_HDRLEN + fixed_hdr_sz); attr; \
- (attr) = ynl_attr_next(ynl_nlmsg_end_addr(nlh), attr))
- #define ynl_attr_for_each_nested(attr, outer) \
- for ((attr) = ynl_attr_first(outer, outer->nla_len, \
- sizeof(struct nlattr)); attr; \
- (attr) = ynl_attr_next(ynl_attr_data_end(outer), attr))
- #define ynl_attr_for_each_payload(start, len, attr) \
- for ((attr) = ynl_attr_first(start, len, 0); attr; \
- (attr) = ynl_attr_next(start + len, attr))
- static inline struct nlattr *
- ynl_attr_if_good(const void *end, struct nlattr *attr)
- {
- if (attr + 1 > (const struct nlattr *)end)
- return NULL;
- if (ynl_attr_data_end(attr) > end)
- return NULL;
- return attr;
- }
- static inline struct nlattr *
- ynl_attr_next(const void *end, const struct nlattr *prev)
- {
- struct nlattr *attr;
- attr = (struct nlattr *)((char *)prev + NLA_ALIGN(prev->nla_len));
- return ynl_attr_if_good(end, attr);
- }
- static inline struct nlattr *
- ynl_attr_first(const void *start, size_t len, size_t skip)
- {
- struct nlattr *attr;
- attr = (struct nlattr *)((char *)start + NLMSG_ALIGN(skip));
- return ynl_attr_if_good((char *)start + len, attr);
- }
- static inline bool
- __ynl_attr_put_overflow(struct nlmsghdr *nlh, size_t size)
- {
- bool o;
- /* ynl_msg_start() stashed buffer length in nlmsg_pid. */
- o = nlh->nlmsg_len + NLA_HDRLEN + NLMSG_ALIGN(size) > nlh->nlmsg_pid;
- if (o)
- /* YNL_MSG_OVERFLOW is < NLMSG_HDRLEN, all subsequent checks
- * are guaranteed to fail.
- */
- nlh->nlmsg_pid = YNL_MSG_OVERFLOW;
- return o;
- }
- static inline struct nlattr *
- ynl_attr_nest_start(struct nlmsghdr *nlh, unsigned int attr_type)
- {
- struct nlattr *attr;
- if (__ynl_attr_put_overflow(nlh, 0))
- return (struct nlattr *)ynl_nlmsg_end_addr(nlh) - 1;
- attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);
- attr->nla_type = attr_type | NLA_F_NESTED;
- nlh->nlmsg_len += NLA_HDRLEN;
- return attr;
- }
- static inline void
- ynl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *attr)
- {
- attr->nla_len = (char *)ynl_nlmsg_end_addr(nlh) - (char *)attr;
- }
- static inline void
- ynl_attr_put(struct nlmsghdr *nlh, unsigned int attr_type,
- const void *value, size_t size)
- {
- struct nlattr *attr;
- if (__ynl_attr_put_overflow(nlh, size))
- return;
- attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);
- attr->nla_type = attr_type;
- attr->nla_len = NLA_HDRLEN + size;
- memcpy(ynl_attr_data(attr), value, size);
- nlh->nlmsg_len += NLMSG_ALIGN(attr->nla_len);
- }
- static inline void
- ynl_attr_put_str(struct nlmsghdr *nlh, unsigned int attr_type, const char *str)
- {
- struct nlattr *attr;
- size_t len;
- len = strlen(str);
- if (__ynl_attr_put_overflow(nlh, len))
- return;
- attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);
- attr->nla_type = attr_type;
- strcpy((char *)ynl_attr_data(attr), str);
- attr->nla_len = NLA_HDRLEN + NLA_ALIGN(len);
- nlh->nlmsg_len += NLMSG_ALIGN(attr->nla_len);
- }
- static inline const char *ynl_attr_get_str(const struct nlattr *attr)
- {
- return (const char *)ynl_attr_data(attr);
- }
- static inline __s8 ynl_attr_get_s8(const struct nlattr *attr)
- {
- return *(__s8 *)ynl_attr_data(attr);
- }
- static inline __s16 ynl_attr_get_s16(const struct nlattr *attr)
- {
- return *(__s16 *)ynl_attr_data(attr);
- }
- static inline __s32 ynl_attr_get_s32(const struct nlattr *attr)
- {
- return *(__s32 *)ynl_attr_data(attr);
- }
- static inline __s64 ynl_attr_get_s64(const struct nlattr *attr)
- {
- __s64 tmp;
- memcpy(&tmp, (unsigned char *)(attr + 1), sizeof(tmp));
- return tmp;
- }
- static inline __u8 ynl_attr_get_u8(const struct nlattr *attr)
- {
- return *(__u8 *)ynl_attr_data(attr);
- }
- static inline __u16 ynl_attr_get_u16(const struct nlattr *attr)
- {
- return *(__u16 *)ynl_attr_data(attr);
- }
- static inline __u32 ynl_attr_get_u32(const struct nlattr *attr)
- {
- return *(__u32 *)ynl_attr_data(attr);
- }
- static inline __u64 ynl_attr_get_u64(const struct nlattr *attr)
- {
- __u64 tmp;
- memcpy(&tmp, (unsigned char *)(attr + 1), sizeof(tmp));
- return tmp;
- }
- static inline void
- ynl_attr_put_s8(struct nlmsghdr *nlh, unsigned int attr_type, __s8 value)
- {
- ynl_attr_put(nlh, attr_type, &value, sizeof(value));
- }
- static inline void
- ynl_attr_put_s16(struct nlmsghdr *nlh, unsigned int attr_type, __s16 value)
- {
- ynl_attr_put(nlh, attr_type, &value, sizeof(value));
- }
- static inline void
- ynl_attr_put_s32(struct nlmsghdr *nlh, unsigned int attr_type, __s32 value)
- {
- ynl_attr_put(nlh, attr_type, &value, sizeof(value));
- }
- static inline void
- ynl_attr_put_s64(struct nlmsghdr *nlh, unsigned int attr_type, __s64 value)
- {
- ynl_attr_put(nlh, attr_type, &value, sizeof(value));
- }
- static inline void
- ynl_attr_put_u8(struct nlmsghdr *nlh, unsigned int attr_type, __u8 value)
- {
- ynl_attr_put(nlh, attr_type, &value, sizeof(value));
- }
- static inline void
- ynl_attr_put_u16(struct nlmsghdr *nlh, unsigned int attr_type, __u16 value)
- {
- ynl_attr_put(nlh, attr_type, &value, sizeof(value));
- }
- static inline void
- ynl_attr_put_u32(struct nlmsghdr *nlh, unsigned int attr_type, __u32 value)
- {
- ynl_attr_put(nlh, attr_type, &value, sizeof(value));
- }
- static inline void
- ynl_attr_put_u64(struct nlmsghdr *nlh, unsigned int attr_type, __u64 value)
- {
- ynl_attr_put(nlh, attr_type, &value, sizeof(value));
- }
- static inline __u64 ynl_attr_get_uint(const struct nlattr *attr)
- {
- switch (ynl_attr_data_len(attr)) {
- case 4:
- return ynl_attr_get_u32(attr);
- case 8:
- return ynl_attr_get_u64(attr);
- default:
- return 0;
- }
- }
- static inline __s64 ynl_attr_get_sint(const struct nlattr *attr)
- {
- switch (ynl_attr_data_len(attr)) {
- case 4:
- return ynl_attr_get_s32(attr);
- case 8:
- return ynl_attr_get_s64(attr);
- default:
- return 0;
- }
- }
- static inline void
- ynl_attr_put_uint(struct nlmsghdr *nlh, __u16 type, __u64 data)
- {
- if ((__u32)data == (__u64)data)
- ynl_attr_put_u32(nlh, type, data);
- else
- ynl_attr_put_u64(nlh, type, data);
- }
- static inline void
- ynl_attr_put_sint(struct nlmsghdr *nlh, __u16 type, __s64 data)
- {
- if ((__s32)data == (__s64)data)
- ynl_attr_put_s32(nlh, type, data);
- else
- ynl_attr_put_s64(nlh, type, data);
- }
- #endif
|