diff options
Diffstat (limited to 'netlink/msgbuff.h')
-rw-r--r-- | netlink/msgbuff.h | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/netlink/msgbuff.h b/netlink/msgbuff.h new file mode 100644 index 0000000..7d6731f --- /dev/null +++ b/netlink/msgbuff.h @@ -0,0 +1,123 @@ +/* + * msgbuff.h - netlink message buffer + * + * Declarations of netlink message buffer and related functions. + */ + +#ifndef ETHTOOL_NETLINK_MSGBUFF_H__ +#define ETHTOOL_NETLINK_MSGBUFF_H__ + +#include <string.h> +#include <libmnl/libmnl.h> +#include <linux/netlink.h> +#include <linux/genetlink.h> + +struct nl_context; + +/** + * struct nl_msg_buff - message buffer abstraction + * @buff: pointer to buffer + * @size: total size of allocated buffer + * @left: remaining length current message end to end of buffer + * @nlhdr: pointer to netlink header of current message + * @genlhdr: pointer to genetlink header of current message + * @payload: pointer to message payload (after genetlink header) + */ +struct nl_msg_buff { + char *buff; + unsigned int size; + unsigned int left; + struct nlmsghdr *nlhdr; + struct genlmsghdr *genlhdr; + void *payload; +}; + +void msgbuff_init(struct nl_msg_buff *msgbuff); +void msgbuff_done(struct nl_msg_buff *msgbuff); +int msgbuff_realloc(struct nl_msg_buff *msgbuff, unsigned int new_size); +int msgbuff_append(struct nl_msg_buff *dest, struct nl_msg_buff *src); + +int __msg_init(struct nl_msg_buff *msgbuff, int family, int cmd, + unsigned int flags, int version); +int msg_init(struct nl_context *nlctx, struct nl_msg_buff *msgbuff, int cmd, + unsigned int flags); + +bool ethnla_put(struct nl_msg_buff *msgbuff, uint16_t type, size_t len, + const void *data); +struct nlattr *ethnla_nest_start(struct nl_msg_buff *msgbuff, uint16_t type); +bool ethnla_fill_header(struct nl_msg_buff *msgbuff, uint16_t type, + const char *devname, uint32_t flags); + +/* length of current message */ +static inline unsigned int msgbuff_len(const struct nl_msg_buff *msgbuff) +{ + return msgbuff->nlhdr->nlmsg_len; +} + +/* reset message length to position returned by msgbuff_len() */ +static inline void msgbuff_reset(const struct nl_msg_buff *msgbuff, + unsigned int len) +{ + msgbuff->nlhdr->nlmsg_len = len; +} + +/* put data wrappers */ + +static inline void ethnla_nest_end(struct nl_msg_buff *msgbuff, + struct nlattr *nest) +{ + mnl_attr_nest_end(msgbuff->nlhdr, nest); +} + +static inline void ethnla_nest_cancel(struct nl_msg_buff *msgbuff, + struct nlattr *nest) +{ + mnl_attr_nest_cancel(msgbuff->nlhdr, nest); +} + +static inline bool ethnla_put_u32(struct nl_msg_buff *msgbuff, uint16_t type, + uint32_t data) +{ + return ethnla_put(msgbuff, type, sizeof(uint32_t), &data); +} + +static inline bool ethnla_put_u16(struct nl_msg_buff *msgbuff, uint16_t type, + uint16_t data) +{ + return ethnla_put(msgbuff, type, sizeof(uint16_t), &data); +} + +static inline bool ethnla_put_u8(struct nl_msg_buff *msgbuff, uint16_t type, + uint8_t data) +{ + return ethnla_put(msgbuff, type, sizeof(uint8_t), &data); +} + +static inline bool ethnla_put_flag(struct nl_msg_buff *msgbuff, uint16_t type, + bool val) +{ + if (val) + return ethnla_put(msgbuff, type, 0, &val); + else + return false; +} + +static inline bool ethnla_put_bitfield32(struct nl_msg_buff *msgbuff, + uint16_t type, uint32_t value, + uint32_t selector) +{ + struct nla_bitfield32 val = { + .value = value, + .selector = selector, + }; + + return ethnla_put(msgbuff, type, sizeof(val), &val); +} + +static inline bool ethnla_put_strz(struct nl_msg_buff *msgbuff, uint16_t type, + const char *data) +{ + return ethnla_put(msgbuff, type, strlen(data) + 1, data); +} + +#endif /* ETHTOOL_NETLINK_MSGBUFF_H__ */ |