summaryrefslogtreecommitdiffstats
path: root/netlink/netlink.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--netlink/netlink.h164
1 files changed, 164 insertions, 0 deletions
diff --git a/netlink/netlink.h b/netlink/netlink.h
new file mode 100644
index 0000000..f43c1bf
--- /dev/null
+++ b/netlink/netlink.h
@@ -0,0 +1,164 @@
+/*
+ * 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);
+
+/* 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);
+
+static inline void show_u32(const struct nlattr *attr, const char *label)
+{
+ if (attr)
+ printf("%s%u\n", label, mnl_attr_get_u32(attr));
+ else
+ printf("%sn/a\n", label);
+}
+
+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);
+}
+
+/* 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);
+}
+
+#endif /* ETHTOOL_NETLINK_INT_H__ */