| /* |
| * netlink.h - common interface for all netlink code |
| * |
| * Declarations of data structures, global data and helpers for netlink code |
| */ |
| |
| #ifndef ETHTOOL_NETLINK_INT_H__ |
| #define ETHTOOL_NETLINK_INT_H__ |
| |
| #include <libmnl/libmnl.h> |
| #include <linux/netlink.h> |
| #include <linux/genetlink.h> |
| #include <linux/ethtool_netlink.h> |
| #include "nlsock.h" |
| |
| #define WILDCARD_DEVNAME "*" |
| #define CMDMASK_WORDS DIV_ROUND_UP(__ETHTOOL_MSG_KERNEL_CNT, 32) |
| |
| enum link_mode_class { |
| LM_CLASS_UNKNOWN, |
| LM_CLASS_REAL, |
| LM_CLASS_AUTONEG, |
| LM_CLASS_PORT, |
| LM_CLASS_PAUSE, |
| LM_CLASS_FEC, |
| }; |
| |
| struct nl_op_info { |
| uint32_t op_flags; |
| uint32_t hdr_flags; |
| uint8_t hdr_policy_loaded:1; |
| }; |
| |
| struct nl_context { |
| struct cmd_context *ctx; |
| void *cmd_private; |
| const char *devname; |
| bool is_dump; |
| int exit_code; |
| unsigned int suppress_nlerr; |
| uint16_t ethnl_fam; |
| uint32_t ethnl_mongrp; |
| struct nl_op_info *ops_info; |
| struct nl_socket *ethnl_socket; |
| struct nl_socket *ethnl2_socket; |
| struct nl_socket *rtnl_socket; |
| bool is_monitor; |
| uint32_t filter_cmds[CMDMASK_WORDS]; |
| const char *filter_devname; |
| bool no_banner; |
| const char *cmd; |
| const char *param; |
| char **argp; |
| unsigned int argc; |
| bool ioctl_fallback; |
| bool wildcard_unsupported; |
| }; |
| |
| struct attr_tb_info { |
| const struct nlattr **tb; |
| unsigned int max_type; |
| }; |
| |
| #define DECLARE_ATTR_TB_INFO(tbl) \ |
| struct attr_tb_info tbl ## _info = { (tbl), (MNL_ARRAY_SIZE(tbl) - 1) } |
| |
| int nomsg_reply_cb(const struct nlmsghdr *nlhdr, void *data); |
| int attr_cb(const struct nlattr *attr, void *data); |
| |
| int netlink_init(struct cmd_context *ctx); |
| bool netlink_cmd_check(struct cmd_context *ctx, unsigned int cmd, |
| bool allow_wildcard); |
| const char *get_dev_name(const struct nlattr *nest); |
| int get_dev_info(const struct nlattr *nest, int *ifindex, char *ifname); |
| u32 get_stats_flag(struct nl_context *nlctx, unsigned int nlcmd, |
| unsigned int hdrattr); |
| |
| int linkmodes_reply_cb(const struct nlmsghdr *nlhdr, void *data); |
| int linkinfo_reply_cb(const struct nlmsghdr *nlhdr, void *data); |
| int wol_reply_cb(const struct nlmsghdr *nlhdr, void *data); |
| int debug_reply_cb(const struct nlmsghdr *nlhdr, void *data); |
| int features_reply_cb(const struct nlmsghdr *nlhdr, void *data); |
| int privflags_reply_cb(const struct nlmsghdr *nlhdr, void *data); |
| int rings_reply_cb(const struct nlmsghdr *nlhdr, void *data); |
| int channels_reply_cb(const struct nlmsghdr *nlhdr, void *data); |
| int coalesce_reply_cb(const struct nlmsghdr *nlhdr, void *data); |
| int pause_reply_cb(const struct nlmsghdr *nlhdr, void *data); |
| int eee_reply_cb(const struct nlmsghdr *nlhdr, void *data); |
| int cable_test_reply_cb(const struct nlmsghdr *nlhdr, void *data); |
| int cable_test_ntf_cb(const struct nlmsghdr *nlhdr, void *data); |
| int cable_test_tdr_reply_cb(const struct nlmsghdr *nlhdr, void *data); |
| int cable_test_tdr_ntf_cb(const struct nlmsghdr *nlhdr, void *data); |
| int fec_reply_cb(const struct nlmsghdr *nlhdr, void *data); |
| int module_reply_cb(const struct nlmsghdr *nlhdr, void *data); |
| int plca_get_cfg_reply_cb(const struct nlmsghdr *nlhdr, void *data); |
| |
| /* dump helpers */ |
| |
| int dump_link_modes(struct nl_context *nlctx, const struct nlattr *bitset, |
| bool mask, unsigned int class, const char *before, |
| const char *between, const char *after, |
| const char *if_none, const char *json_key); |
| |
| static inline void show_u32(const char *key, |
| const char *fmt, |
| const struct nlattr *attr) |
| { |
| if (is_json_context()) { |
| if (attr) |
| print_uint(PRINT_JSON, key, NULL, |
| mnl_attr_get_u32(attr)); |
| } else { |
| if (attr) |
| printf("%s%u\n", fmt, mnl_attr_get_u32(attr)); |
| else |
| printf("%sn/a\n", fmt); |
| } |
| } |
| |
| static inline const char *u8_to_bool(const uint8_t *val) |
| { |
| if (val) |
| return *val ? "on" : "off"; |
| else |
| return "n/a"; |
| } |
| |
| static inline void show_bool_val(const char *key, const char *fmt, uint8_t *val) |
| { |
| if (is_json_context()) { |
| if (val) |
| print_bool(PRINT_JSON, key, NULL, *val); |
| } else { |
| print_string(PRINT_FP, NULL, fmt, u8_to_bool(val)); |
| } |
| } |
| |
| static inline void show_bool(const char *key, const char *fmt, |
| const struct nlattr *attr) |
| { |
| show_bool_val(key, fmt, attr ? mnl_attr_get_payload(attr) : NULL); |
| } |
| |
| static inline void show_cr(void) |
| { |
| if (!is_json_context()) |
| putchar('\n'); |
| } |
| |
| /* misc */ |
| |
| static inline void copy_devname(char *dst, const char *src) |
| { |
| strncpy(dst, src, ALTIFNAMSIZ); |
| dst[ALTIFNAMSIZ - 1] = '\0'; |
| } |
| |
| static inline bool dev_ok(const struct nl_context *nlctx) |
| { |
| return !nlctx->filter_devname || |
| (nlctx->devname && |
| !strcmp(nlctx->devname, nlctx->filter_devname)); |
| } |
| |
| static inline int netlink_init_ethnl2_socket(struct nl_context *nlctx) |
| { |
| if (nlctx->ethnl2_socket) |
| return 0; |
| return nlsock_init(nlctx, &nlctx->ethnl2_socket, NETLINK_GENERIC); |
| } |
| |
| static inline int netlink_init_rtnl_socket(struct nl_context *nlctx) |
| { |
| if (nlctx->rtnl_socket) |
| return 0; |
| return nlsock_init(nlctx, &nlctx->rtnl_socket, NETLINK_ROUTE); |
| } |
| |
| static inline uint64_t attr_get_uint(const struct nlattr *attr) |
| { |
| switch (mnl_attr_get_payload_len(attr)) { |
| case sizeof(uint8_t): |
| return mnl_attr_get_u8(attr); |
| case sizeof(uint16_t): |
| return mnl_attr_get_u16(attr); |
| case sizeof(uint32_t): |
| return mnl_attr_get_u32(attr); |
| case sizeof(uint64_t): |
| return mnl_attr_get_u64(attr); |
| } |
| |
| return -1ULL; |
| } |
| |
| #endif /* ETHTOOL_NETLINK_INT_H__ */ |