^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/ethtool_netlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include "netlink.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) static struct genl_family ethtool_genl_family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) static bool ethnl_ok __read_mostly;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) static u32 ethnl_bcast_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #define ETHTOOL_FLAGS_BASIC (ETHTOOL_FLAG_COMPACT_BITSETS | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) ETHTOOL_FLAG_OMIT_REPLY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define ETHTOOL_FLAGS_STATS (ETHTOOL_FLAGS_BASIC | ETHTOOL_FLAG_STATS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) const struct nla_policy ethnl_header_policy[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) [ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) [ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) .len = ALTIFNAMSIZ - 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) [ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) ETHTOOL_FLAGS_BASIC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) const struct nla_policy ethnl_header_policy_stats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) [ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) [ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) .len = ALTIFNAMSIZ - 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) [ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) ETHTOOL_FLAGS_STATS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * ethnl_parse_header_dev_get() - parse request header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * @req_info: structure to put results into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * @header: nest attribute with request header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * @net: request netns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * @extack: netlink extack for error reporting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * @require_dev: fail if no device identified in header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * Parse request header in nested attribute @nest and puts results into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * the structure pointed to by @req_info. Extack from @info is used for error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * reporting. If req_info->dev is not null on return, reference to it has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * been taken. If error is returned, *req_info is null initialized and no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * reference is held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * Return: 0 on success or negative error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) const struct nlattr *header, struct net *net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct netlink_ext_ack *extack, bool require_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct nlattr *tb[ARRAY_SIZE(ethnl_header_policy)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) const struct nlattr *devname_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct net_device *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) u32 flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (!header) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) NL_SET_ERR_MSG(extack, "request header missing");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* No validation here, command policy should have a nested policy set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * for the header, therefore validation should have already been done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) ret = nla_parse_nested(tb, ARRAY_SIZE(ethnl_header_policy) - 1, header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) NULL, extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (tb[ETHTOOL_A_HEADER_FLAGS])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) flags = nla_get_u32(tb[ETHTOOL_A_HEADER_FLAGS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) devname_attr = tb[ETHTOOL_A_HEADER_DEV_NAME];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (tb[ETHTOOL_A_HEADER_DEV_INDEX]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) u32 ifindex = nla_get_u32(tb[ETHTOOL_A_HEADER_DEV_INDEX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) dev = dev_get_by_index(net, ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (!dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) NL_SET_ERR_MSG_ATTR(extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) tb[ETHTOOL_A_HEADER_DEV_INDEX],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) "no device matches ifindex");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* if both ifindex and ifname are passed, they must match */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (devname_attr &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) strncmp(dev->name, nla_data(devname_attr), IFNAMSIZ)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) NL_SET_ERR_MSG_ATTR(extack, header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) "ifindex and name do not match");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) } else if (devname_attr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) dev = dev_get_by_name(net, nla_data(devname_attr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (!dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) NL_SET_ERR_MSG_ATTR(extack, devname_attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) "no device matches name");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) } else if (require_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) NL_SET_ERR_MSG_ATTR(extack, header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) "neither ifindex nor name specified");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (dev && !netif_device_present(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) NL_SET_ERR_MSG(extack, "device not present");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) req_info->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) req_info->flags = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * ethnl_fill_reply_header() - Put common header into a reply message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * @skb: skb with the message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * @dev: network device to describe in header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * @attrtype: attribute type to use for the nest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * Create a nested attribute with attributes describing given network device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * Return: 0 on success, error value (-EMSGSIZE only) on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int ethnl_fill_reply_header(struct sk_buff *skb, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) u16 attrtype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct nlattr *nest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) nest = nla_nest_start(skb, attrtype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (!nest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (nla_put_u32(skb, ETHTOOL_A_HEADER_DEV_INDEX, (u32)dev->ifindex) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) nla_put_string(skb, ETHTOOL_A_HEADER_DEV_NAME, dev->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /* If more attributes are put into reply header, ethnl_header_size()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * must be updated to account for them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) nla_nest_end(skb, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) nla_nest_cancel(skb, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * ethnl_reply_init() - Create skb for a reply and fill device identification
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * @payload: payload length (without netlink and genetlink header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * @dev: device the reply is about (may be null)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * @cmd: ETHTOOL_MSG_* message type for reply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * @hdr_attrtype: attribute type for common header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * @info: genetlink info of the received packet we respond to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * @ehdrp: place to store payload pointer returned by genlmsg_new()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * Return: pointer to allocated skb on success, NULL on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct sk_buff *ethnl_reply_init(size_t payload, struct net_device *dev, u8 cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) u16 hdr_attrtype, struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) void **ehdrp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) skb = genlmsg_new(payload, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) *ehdrp = genlmsg_put_reply(skb, info, ðtool_genl_family, 0, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (!*ehdrp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) ret = ethnl_fill_reply_header(skb, dev, hdr_attrtype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) err_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) nlmsg_free(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) GENL_SET_ERR_MSG(info, "failed to setup reply message");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) void *ethnl_dump_put(struct sk_buff *skb, struct netlink_callback *cb, u8 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) ðtool_genl_family, 0, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) void *ethnl_bcastmsg_put(struct sk_buff *skb, u8 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return genlmsg_put(skb, 0, ++ethnl_bcast_seq, ðtool_genl_family, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) int ethnl_multicast(struct sk_buff *skb, struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return genlmsg_multicast_netns(ðtool_genl_family, dev_net(dev), skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 0, ETHNL_MCGRP_MONITOR, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* GET request helpers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * struct ethnl_dump_ctx - context structure for generic dumpit() callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * @ops: request ops of currently processed message type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * @req_info: parsed request header of processed request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * @reply_data: data needed to compose the reply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * @pos_hash: saved iteration position - hashbucket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * @pos_idx: saved iteration position - index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * These parameters are kept in struct netlink_callback as context preserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * between iterations. They are initialized by ethnl_default_start() and used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * in ethnl_default_dumpit() and ethnl_default_done().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct ethnl_dump_ctx {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) const struct ethnl_request_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) struct ethnl_req_info *req_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct ethnl_reply_data *reply_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) int pos_hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) int pos_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static const struct ethnl_request_ops *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) [ETHTOOL_MSG_STRSET_GET] = ðnl_strset_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) [ETHTOOL_MSG_LINKINFO_GET] = ðnl_linkinfo_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) [ETHTOOL_MSG_LINKMODES_GET] = ðnl_linkmodes_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) [ETHTOOL_MSG_LINKSTATE_GET] = ðnl_linkstate_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) [ETHTOOL_MSG_DEBUG_GET] = ðnl_debug_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) [ETHTOOL_MSG_WOL_GET] = ðnl_wol_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) [ETHTOOL_MSG_FEATURES_GET] = ðnl_features_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) [ETHTOOL_MSG_PRIVFLAGS_GET] = ðnl_privflags_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) [ETHTOOL_MSG_RINGS_GET] = ðnl_rings_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) [ETHTOOL_MSG_CHANNELS_GET] = ðnl_channels_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) [ETHTOOL_MSG_COALESCE_GET] = ðnl_coalesce_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) [ETHTOOL_MSG_PAUSE_GET] = ðnl_pause_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) [ETHTOOL_MSG_EEE_GET] = ðnl_eee_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) [ETHTOOL_MSG_TSINFO_GET] = ðnl_tsinfo_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return (struct ethnl_dump_ctx *)cb->ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * ethnl_default_parse() - Parse request message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * @req_info: pointer to structure to put data into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * @tb: parsed attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * @net: request netns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * @request_ops: struct request_ops for request type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * @extack: netlink extack for error reporting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * @require_dev: fail if no device identified in header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * Parse universal request header and call request specific ->parse_request()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * callback (if defined) to parse the rest of the message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * Return: 0 on success or negative error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static int ethnl_default_parse(struct ethnl_req_info *req_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct nlattr **tb, struct net *net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) const struct ethnl_request_ops *request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct netlink_ext_ack *extack, bool require_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) ret = ethnl_parse_header_dev_get(req_info, tb[request_ops->hdr_attr],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) net, extack, require_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (request_ops->parse_request) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) ret = request_ops->parse_request(req_info, tb, extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * ethnl_init_reply_data() - Initialize reply data for GET request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * @reply_data: pointer to embedded struct ethnl_reply_data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * @ops: instance of struct ethnl_request_ops describing the layout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * @dev: network device to initialize the reply for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * Fills the reply data part with zeros and sets the dev member. Must be called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * before calling the ->fill_reply() callback (for each iteration when handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * dump requests).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static void ethnl_init_reply_data(struct ethnl_reply_data *reply_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) const struct ethnl_request_ops *ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) memset(reply_data, 0, ops->reply_data_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) reply_data->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /* default ->doit() handler for GET type requests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct ethnl_reply_data *reply_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) struct ethnl_req_info *req_info = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) const u8 cmd = info->genlhdr->cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) const struct ethnl_request_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) struct sk_buff *rskb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) void *reply_payload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) int reply_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) ops = ethnl_default_requests[cmd];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (WARN_ONCE(!ops, "cmd %u has no ethnl_request_ops\n", cmd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) req_info = kzalloc(ops->req_info_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (!req_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) reply_data = kmalloc(ops->reply_data_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (!reply_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) kfree(req_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) ret = ethnl_default_parse(req_info, info->attrs, genl_info_net(info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) ops, info->extack, !ops->allow_nodev_do);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) goto err_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) ethnl_init_reply_data(reply_data, ops, req_info->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) ret = ops->prepare_data(req_info, reply_data, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) goto err_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) ret = ops->reply_size(req_info, reply_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) goto err_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) reply_len = ret + ethnl_reply_header_size();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) rskb = ethnl_reply_init(reply_len, req_info->dev, ops->reply_cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) ops->hdr_attr, info, &reply_payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (!rskb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) goto err_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) ret = ops->fill_reply(rskb, req_info, reply_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) goto err_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (ops->cleanup_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) ops->cleanup_data(reply_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) genlmsg_end(rskb, reply_payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (req_info->dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) dev_put(req_info->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) kfree(reply_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) kfree(req_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return genlmsg_reply(rskb, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) err_msg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) WARN_ONCE(ret == -EMSGSIZE, "calculated message payload length (%d) not sufficient\n", reply_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) nlmsg_free(rskb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) err_cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (ops->cleanup_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) ops->cleanup_data(reply_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) err_dev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (req_info->dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) dev_put(req_info->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) kfree(reply_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) kfree(req_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static int ethnl_default_dump_one(struct sk_buff *skb, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) const struct ethnl_dump_ctx *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) void *ehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) ehdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) ðtool_genl_family, NLM_F_MULTI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) ctx->ops->reply_cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (!ehdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) ethnl_init_reply_data(ctx->reply_data, ctx->ops, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) ret = ctx->ops->prepare_data(ctx->req_info, ctx->reply_data, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) ret = ethnl_fill_reply_header(skb, dev, ctx->ops->hdr_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) ret = ctx->ops->fill_reply(skb, ctx->req_info, ctx->reply_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (ctx->ops->cleanup_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) ctx->ops->cleanup_data(ctx->reply_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) ctx->reply_data->dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) genlmsg_cancel(skb, ehdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) genlmsg_end(skb, ehdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) /* Default ->dumpit() handler for GET requests. Device iteration copied from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * rtnl_dump_ifinfo(); we have to be more careful about device hashtable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * persistence as we cannot guarantee to hold RTNL lock through the whole
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * function as rtnetnlink does.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) static int ethnl_default_dumpit(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) struct net *net = sock_net(skb->sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) int s_idx = ctx->pos_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) int h, idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) for (h = ctx->pos_hash; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) struct hlist_head *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) unsigned int seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) head = &net->dev_index_head[h];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) restart_chain:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) seq = net->dev_base_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) cb->seq = seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) hlist_for_each_entry(dev, head, index_hlist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (idx < s_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) goto cont;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) dev_hold(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) ret = ethnl_default_dump_one(skb, dev, ctx, cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (ret == -EOPNOTSUPP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) goto lock_and_cont;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (likely(skb->len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) ret = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) lock_and_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (net->dev_base_seq != seq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) s_idx = idx + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) goto restart_chain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) ctx->pos_hash = h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) ctx->pos_idx = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) nl_dump_check_consistent(cb, nlmsg_hdr(skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) /* generic ->start() handler for GET requests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) static int ethnl_default_start(struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) const struct genl_dumpit_info *info = genl_dumpit_info(cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) struct ethnl_reply_data *reply_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) const struct ethnl_request_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) struct ethnl_req_info *req_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) struct genlmsghdr *ghdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) ghdr = nlmsg_data(cb->nlh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) ops = ethnl_default_requests[ghdr->cmd];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (WARN_ONCE(!ops, "cmd %u has no ethnl_request_ops\n", ghdr->cmd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) req_info = kzalloc(ops->req_info_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (!req_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) reply_data = kmalloc(ops->reply_data_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (!reply_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) goto free_req_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) ret = ethnl_default_parse(req_info, info->attrs, sock_net(cb->skb->sk),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) ops, cb->extack, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (req_info->dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) /* We ignore device specification in dump requests but as the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) * same parser as for non-dump (doit) requests is used, it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * would take reference to the device if it finds one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) dev_put(req_info->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) req_info->dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) goto free_reply_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) ctx->ops = ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) ctx->req_info = req_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) ctx->reply_data = reply_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) ctx->pos_hash = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) ctx->pos_idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) free_reply_data:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) kfree(reply_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) free_req_info:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) kfree(req_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) /* default ->done() handler for GET requests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) static int ethnl_default_done(struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) kfree(ctx->reply_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) kfree(ctx->req_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) static const struct ethnl_request_ops *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) ethnl_default_notify_ops[ETHTOOL_MSG_KERNEL_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) [ETHTOOL_MSG_LINKINFO_NTF] = ðnl_linkinfo_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) [ETHTOOL_MSG_LINKMODES_NTF] = ðnl_linkmodes_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) [ETHTOOL_MSG_DEBUG_NTF] = ðnl_debug_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) [ETHTOOL_MSG_WOL_NTF] = ðnl_wol_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) [ETHTOOL_MSG_FEATURES_NTF] = ðnl_features_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) [ETHTOOL_MSG_PRIVFLAGS_NTF] = ðnl_privflags_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) [ETHTOOL_MSG_RINGS_NTF] = ðnl_rings_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) [ETHTOOL_MSG_CHANNELS_NTF] = ðnl_channels_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) [ETHTOOL_MSG_COALESCE_NTF] = ðnl_coalesce_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) [ETHTOOL_MSG_PAUSE_NTF] = ðnl_pause_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) [ETHTOOL_MSG_EEE_NTF] = ðnl_eee_request_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) /* default notification handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) static void ethnl_default_notify(struct net_device *dev, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) const void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) struct ethnl_reply_data *reply_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) const struct ethnl_request_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) struct ethnl_req_info *req_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) void *reply_payload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) int reply_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) if (WARN_ONCE(cmd > ETHTOOL_MSG_KERNEL_MAX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) !ethnl_default_notify_ops[cmd],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) "unexpected notification type %u\n", cmd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) ops = ethnl_default_notify_ops[cmd];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) req_info = kzalloc(ops->req_info_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (!req_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) reply_data = kmalloc(ops->reply_data_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (!reply_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) kfree(req_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) req_info->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) req_info->flags |= ETHTOOL_FLAG_COMPACT_BITSETS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) ethnl_init_reply_data(reply_data, ops, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) ret = ops->prepare_data(req_info, reply_data, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) goto err_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) ret = ops->reply_size(req_info, reply_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) goto err_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) reply_len = ret + ethnl_reply_header_size();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) skb = genlmsg_new(reply_len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) goto err_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) reply_payload = ethnl_bcastmsg_put(skb, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (!reply_payload)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) goto err_skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) ret = ethnl_fill_reply_header(skb, dev, ops->hdr_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) goto err_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) ret = ops->fill_reply(skb, req_info, reply_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) goto err_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (ops->cleanup_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) ops->cleanup_data(reply_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) genlmsg_end(skb, reply_payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) kfree(reply_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) kfree(req_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) ethnl_multicast(skb, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) err_msg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) WARN_ONCE(ret == -EMSGSIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) "calculated message payload length (%d) not sufficient\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) reply_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) err_skb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) nlmsg_free(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) err_cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (ops->cleanup_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) ops->cleanup_data(reply_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) kfree(reply_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) kfree(req_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) /* notifications */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) typedef void (*ethnl_notify_handler_t)(struct net_device *dev, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) const void *data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) static const ethnl_notify_handler_t ethnl_notify_handlers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) [ETHTOOL_MSG_LINKINFO_NTF] = ethnl_default_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) [ETHTOOL_MSG_LINKMODES_NTF] = ethnl_default_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) [ETHTOOL_MSG_DEBUG_NTF] = ethnl_default_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) [ETHTOOL_MSG_WOL_NTF] = ethnl_default_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) [ETHTOOL_MSG_FEATURES_NTF] = ethnl_default_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) [ETHTOOL_MSG_PRIVFLAGS_NTF] = ethnl_default_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) [ETHTOOL_MSG_RINGS_NTF] = ethnl_default_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) [ETHTOOL_MSG_CHANNELS_NTF] = ethnl_default_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) [ETHTOOL_MSG_COALESCE_NTF] = ethnl_default_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) [ETHTOOL_MSG_PAUSE_NTF] = ethnl_default_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) [ETHTOOL_MSG_EEE_NTF] = ethnl_default_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) void ethtool_notify(struct net_device *dev, unsigned int cmd, const void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (unlikely(!ethnl_ok))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (likely(cmd < ARRAY_SIZE(ethnl_notify_handlers) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) ethnl_notify_handlers[cmd]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) ethnl_notify_handlers[cmd](dev, cmd, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) WARN_ONCE(1, "notification %u not implemented (dev=%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) cmd, netdev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) EXPORT_SYMBOL(ethtool_notify);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) static void ethnl_notify_features(struct netdev_notifier_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) struct net_device *dev = netdev_notifier_info_to_dev(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) ethtool_notify(dev, ETHTOOL_MSG_FEATURES_NTF, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) static int ethnl_netdev_event(struct notifier_block *this, unsigned long event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) void *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) case NETDEV_FEAT_CHANGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) ethnl_notify_features(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return NOTIFY_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) static struct notifier_block ethnl_netdev_notifier = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) .notifier_call = ethnl_netdev_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) /* genetlink setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) static const struct genl_ops ethtool_genl_ops[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) .cmd = ETHTOOL_MSG_STRSET_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) .doit = ethnl_default_doit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) .start = ethnl_default_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) .dumpit = ethnl_default_dumpit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) .done = ethnl_default_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) .policy = ethnl_strset_get_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) .maxattr = ARRAY_SIZE(ethnl_strset_get_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) .cmd = ETHTOOL_MSG_LINKINFO_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) .doit = ethnl_default_doit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) .start = ethnl_default_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) .dumpit = ethnl_default_dumpit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) .done = ethnl_default_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) .policy = ethnl_linkinfo_get_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) .maxattr = ARRAY_SIZE(ethnl_linkinfo_get_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) .cmd = ETHTOOL_MSG_LINKINFO_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) .doit = ethnl_set_linkinfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) .policy = ethnl_linkinfo_set_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) .maxattr = ARRAY_SIZE(ethnl_linkinfo_set_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) .cmd = ETHTOOL_MSG_LINKMODES_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) .doit = ethnl_default_doit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) .start = ethnl_default_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) .dumpit = ethnl_default_dumpit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) .done = ethnl_default_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) .policy = ethnl_linkmodes_get_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) .maxattr = ARRAY_SIZE(ethnl_linkmodes_get_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) .cmd = ETHTOOL_MSG_LINKMODES_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) .doit = ethnl_set_linkmodes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) .policy = ethnl_linkmodes_set_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) .maxattr = ARRAY_SIZE(ethnl_linkmodes_set_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) .cmd = ETHTOOL_MSG_LINKSTATE_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) .doit = ethnl_default_doit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) .start = ethnl_default_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) .dumpit = ethnl_default_dumpit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) .done = ethnl_default_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) .policy = ethnl_linkstate_get_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) .maxattr = ARRAY_SIZE(ethnl_linkstate_get_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) .cmd = ETHTOOL_MSG_DEBUG_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) .doit = ethnl_default_doit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) .start = ethnl_default_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) .dumpit = ethnl_default_dumpit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) .done = ethnl_default_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) .policy = ethnl_debug_get_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) .maxattr = ARRAY_SIZE(ethnl_debug_get_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) .cmd = ETHTOOL_MSG_DEBUG_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) .doit = ethnl_set_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) .policy = ethnl_debug_set_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) .maxattr = ARRAY_SIZE(ethnl_debug_set_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) .cmd = ETHTOOL_MSG_WOL_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) .doit = ethnl_default_doit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) .start = ethnl_default_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) .dumpit = ethnl_default_dumpit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) .done = ethnl_default_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) .policy = ethnl_wol_get_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) .maxattr = ARRAY_SIZE(ethnl_wol_get_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) .cmd = ETHTOOL_MSG_WOL_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) .doit = ethnl_set_wol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) .policy = ethnl_wol_set_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) .maxattr = ARRAY_SIZE(ethnl_wol_set_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) .cmd = ETHTOOL_MSG_FEATURES_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) .doit = ethnl_default_doit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) .start = ethnl_default_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) .dumpit = ethnl_default_dumpit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) .done = ethnl_default_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) .policy = ethnl_features_get_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) .maxattr = ARRAY_SIZE(ethnl_features_get_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) .cmd = ETHTOOL_MSG_FEATURES_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) .doit = ethnl_set_features,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) .policy = ethnl_features_set_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) .maxattr = ARRAY_SIZE(ethnl_features_set_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) .cmd = ETHTOOL_MSG_PRIVFLAGS_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) .doit = ethnl_default_doit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) .start = ethnl_default_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) .dumpit = ethnl_default_dumpit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) .done = ethnl_default_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) .policy = ethnl_privflags_get_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) .maxattr = ARRAY_SIZE(ethnl_privflags_get_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) .cmd = ETHTOOL_MSG_PRIVFLAGS_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) .doit = ethnl_set_privflags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) .policy = ethnl_privflags_set_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) .maxattr = ARRAY_SIZE(ethnl_privflags_set_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) .cmd = ETHTOOL_MSG_RINGS_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) .doit = ethnl_default_doit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) .start = ethnl_default_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) .dumpit = ethnl_default_dumpit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) .done = ethnl_default_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) .policy = ethnl_rings_get_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) .maxattr = ARRAY_SIZE(ethnl_rings_get_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) .cmd = ETHTOOL_MSG_RINGS_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) .doit = ethnl_set_rings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) .policy = ethnl_rings_set_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) .maxattr = ARRAY_SIZE(ethnl_rings_set_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) .cmd = ETHTOOL_MSG_CHANNELS_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) .doit = ethnl_default_doit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) .start = ethnl_default_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) .dumpit = ethnl_default_dumpit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) .done = ethnl_default_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) .policy = ethnl_channels_get_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) .maxattr = ARRAY_SIZE(ethnl_channels_get_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) .cmd = ETHTOOL_MSG_CHANNELS_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) .doit = ethnl_set_channels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) .policy = ethnl_channels_set_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) .maxattr = ARRAY_SIZE(ethnl_channels_set_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) .cmd = ETHTOOL_MSG_COALESCE_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) .doit = ethnl_default_doit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) .start = ethnl_default_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) .dumpit = ethnl_default_dumpit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) .done = ethnl_default_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) .policy = ethnl_coalesce_get_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) .maxattr = ARRAY_SIZE(ethnl_coalesce_get_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) .cmd = ETHTOOL_MSG_COALESCE_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) .doit = ethnl_set_coalesce,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) .policy = ethnl_coalesce_set_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) .maxattr = ARRAY_SIZE(ethnl_coalesce_set_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) .cmd = ETHTOOL_MSG_PAUSE_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) .doit = ethnl_default_doit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) .start = ethnl_default_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) .dumpit = ethnl_default_dumpit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) .done = ethnl_default_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) .policy = ethnl_pause_get_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) .maxattr = ARRAY_SIZE(ethnl_pause_get_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) .cmd = ETHTOOL_MSG_PAUSE_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) .doit = ethnl_set_pause,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) .policy = ethnl_pause_set_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) .maxattr = ARRAY_SIZE(ethnl_pause_set_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) .cmd = ETHTOOL_MSG_EEE_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) .doit = ethnl_default_doit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) .start = ethnl_default_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) .dumpit = ethnl_default_dumpit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) .done = ethnl_default_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) .policy = ethnl_eee_get_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) .maxattr = ARRAY_SIZE(ethnl_eee_get_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) .cmd = ETHTOOL_MSG_EEE_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) .doit = ethnl_set_eee,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) .policy = ethnl_eee_set_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) .maxattr = ARRAY_SIZE(ethnl_eee_set_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) .cmd = ETHTOOL_MSG_TSINFO_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) .doit = ethnl_default_doit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) .start = ethnl_default_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) .dumpit = ethnl_default_dumpit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) .done = ethnl_default_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) .policy = ethnl_tsinfo_get_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) .maxattr = ARRAY_SIZE(ethnl_tsinfo_get_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) .cmd = ETHTOOL_MSG_CABLE_TEST_ACT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) .doit = ethnl_act_cable_test,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) .policy = ethnl_cable_test_act_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) .maxattr = ARRAY_SIZE(ethnl_cable_test_act_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) .cmd = ETHTOOL_MSG_CABLE_TEST_TDR_ACT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) .flags = GENL_UNS_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) .doit = ethnl_act_cable_test_tdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) .policy = ethnl_cable_test_tdr_act_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) .maxattr = ARRAY_SIZE(ethnl_cable_test_tdr_act_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) .cmd = ETHTOOL_MSG_TUNNEL_INFO_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) .doit = ethnl_tunnel_info_doit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) .start = ethnl_tunnel_info_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) .dumpit = ethnl_tunnel_info_dumpit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) .policy = ethnl_tunnel_info_get_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) .maxattr = ARRAY_SIZE(ethnl_tunnel_info_get_policy) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) static const struct genl_multicast_group ethtool_nl_mcgrps[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) [ETHNL_MCGRP_MONITOR] = { .name = ETHTOOL_MCGRP_MONITOR_NAME },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) static struct genl_family ethtool_genl_family __ro_after_init = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) .name = ETHTOOL_GENL_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) .version = ETHTOOL_GENL_VERSION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) .netnsok = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) .parallel_ops = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) .ops = ethtool_genl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) .n_ops = ARRAY_SIZE(ethtool_genl_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) .mcgrps = ethtool_nl_mcgrps,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) .n_mcgrps = ARRAY_SIZE(ethtool_nl_mcgrps),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) /* module setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) static int __init ethnl_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) ret = genl_register_family(ðtool_genl_family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) if (WARN(ret < 0, "ethtool: genetlink family registration failed"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) ethnl_ok = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) ret = register_netdevice_notifier(ðnl_netdev_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) WARN(ret < 0, "ethtool: net device notifier registration failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) subsys_initcall(ethnl_init);