1 // SPDX-License-Identifier: GPL-2.0-only 2 3 #include <net/netdev_lock.h> 4 #include <net/netdev_queues.h> 5 #include <net/sock.h> 6 #include <linux/ethtool_netlink.h> 7 #include <linux/phy_link_topology.h> 8 #include <linux/pm_runtime.h> 9 #include "netlink.h" 10 #include "module_fw.h" 11 12 static struct genl_family ethtool_genl_family; 13 14 static bool ethnl_ok __read_mostly; 15 static u32 ethnl_bcast_seq; 16 17 #define ETHTOOL_FLAGS_BASIC (ETHTOOL_FLAG_COMPACT_BITSETS | \ 18 ETHTOOL_FLAG_OMIT_REPLY) 19 #define ETHTOOL_FLAGS_STATS (ETHTOOL_FLAGS_BASIC | ETHTOOL_FLAG_STATS) 20 21 const struct nla_policy ethnl_header_policy[] = { 22 [ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 }, 23 [ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING, 24 .len = ALTIFNAMSIZ - 1 }, 25 [ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32, 26 ETHTOOL_FLAGS_BASIC), 27 }; 28 29 const struct nla_policy ethnl_header_policy_stats[] = { 30 [ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 }, 31 [ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING, 32 .len = ALTIFNAMSIZ - 1 }, 33 [ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32, 34 ETHTOOL_FLAGS_STATS), 35 }; 36 37 const struct nla_policy ethnl_header_policy_phy[] = { 38 [ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 }, 39 [ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING, 40 .len = ALTIFNAMSIZ - 1 }, 41 [ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32, 42 ETHTOOL_FLAGS_BASIC), 43 [ETHTOOL_A_HEADER_PHY_INDEX] = NLA_POLICY_MIN(NLA_U32, 1), 44 }; 45 46 const struct nla_policy ethnl_header_policy_phy_stats[] = { 47 [ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 }, 48 [ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING, 49 .len = ALTIFNAMSIZ - 1 }, 50 [ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32, 51 ETHTOOL_FLAGS_STATS), 52 [ETHTOOL_A_HEADER_PHY_INDEX] = NLA_POLICY_MIN(NLA_U32, 1), 53 }; 54 55 int ethnl_sock_priv_set(struct sk_buff *skb, struct net_device *dev, u32 portid, 56 enum ethnl_sock_type type) 57 { 58 struct ethnl_sock_priv *sk_priv; 59 60 sk_priv = genl_sk_priv_get(ðtool_genl_family, NETLINK_CB(skb).sk); 61 if (IS_ERR(sk_priv)) 62 return PTR_ERR(sk_priv); 63 64 sk_priv->dev = dev; 65 sk_priv->portid = portid; 66 sk_priv->type = type; 67 68 return 0; 69 } 70 71 static void ethnl_sock_priv_destroy(void *priv) 72 { 73 struct ethnl_sock_priv *sk_priv = priv; 74 75 switch (sk_priv->type) { 76 case ETHTOOL_SOCK_TYPE_MODULE_FW_FLASH: 77 ethnl_module_fw_flash_sock_destroy(sk_priv); 78 break; 79 default: 80 break; 81 } 82 } 83 84 int ethnl_ops_begin(struct net_device *dev) 85 { 86 int ret; 87 88 if (!dev) 89 return -ENODEV; 90 91 if (dev->dev.parent) 92 pm_runtime_get_sync(dev->dev.parent); 93 94 netdev_ops_assert_locked(dev); 95 96 if (!netif_device_present(dev) || 97 dev->reg_state >= NETREG_UNREGISTERING) { 98 ret = -ENODEV; 99 goto err; 100 } 101 102 if (dev->ethtool_ops->begin) { 103 ret = dev->ethtool_ops->begin(dev); 104 if (ret) 105 goto err; 106 } 107 108 return 0; 109 err: 110 if (dev->dev.parent) 111 pm_runtime_put(dev->dev.parent); 112 113 return ret; 114 } 115 116 void ethnl_ops_complete(struct net_device *dev) 117 { 118 if (dev->ethtool_ops->complete) 119 dev->ethtool_ops->complete(dev); 120 121 if (dev->dev.parent) 122 pm_runtime_put(dev->dev.parent); 123 } 124 125 /** 126 * ethnl_parse_header_dev_get() - parse request header 127 * @req_info: structure to put results into 128 * @header: nest attribute with request header 129 * @net: request netns 130 * @extack: netlink extack for error reporting 131 * @require_dev: fail if no device identified in header 132 * 133 * Parse request header in nested attribute @nest and puts results into 134 * the structure pointed to by @req_info. Extack from @info is used for error 135 * reporting. If req_info->dev is not null on return, reference to it has 136 * been taken. If error is returned, *req_info is null initialized and no 137 * reference is held. 138 * 139 * Return: 0 on success or negative error code 140 */ 141 int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info, 142 const struct nlattr *header, struct net *net, 143 struct netlink_ext_ack *extack, bool require_dev) 144 { 145 struct nlattr *tb[ARRAY_SIZE(ethnl_header_policy_phy)]; 146 const struct nlattr *devname_attr; 147 struct net_device *dev = NULL; 148 u32 flags = 0; 149 int ret; 150 151 if (!header) { 152 if (!require_dev) 153 return 0; 154 NL_SET_ERR_MSG(extack, "request header missing"); 155 return -EINVAL; 156 } 157 /* No validation here, command policy should have a nested policy set 158 * for the header, therefore validation should have already been done. 159 */ 160 ret = nla_parse_nested(tb, ARRAY_SIZE(ethnl_header_policy_phy) - 1, header, 161 NULL, extack); 162 if (ret < 0) 163 return ret; 164 if (tb[ETHTOOL_A_HEADER_FLAGS]) 165 flags = nla_get_u32(tb[ETHTOOL_A_HEADER_FLAGS]); 166 167 devname_attr = tb[ETHTOOL_A_HEADER_DEV_NAME]; 168 if (tb[ETHTOOL_A_HEADER_DEV_INDEX]) { 169 u32 ifindex = nla_get_u32(tb[ETHTOOL_A_HEADER_DEV_INDEX]); 170 171 dev = netdev_get_by_index(net, ifindex, &req_info->dev_tracker, 172 GFP_KERNEL); 173 if (!dev) { 174 NL_SET_ERR_MSG_ATTR(extack, 175 tb[ETHTOOL_A_HEADER_DEV_INDEX], 176 "no device matches ifindex"); 177 return -ENODEV; 178 } 179 /* if both ifindex and ifname are passed, they must match */ 180 if (devname_attr && 181 strncmp(dev->name, nla_data(devname_attr), IFNAMSIZ)) { 182 netdev_put(dev, &req_info->dev_tracker); 183 NL_SET_ERR_MSG_ATTR(extack, header, 184 "ifindex and name do not match"); 185 return -ENODEV; 186 } 187 } else if (devname_attr) { 188 dev = netdev_get_by_name(net, nla_data(devname_attr), 189 &req_info->dev_tracker, GFP_KERNEL); 190 if (!dev) { 191 NL_SET_ERR_MSG_ATTR(extack, devname_attr, 192 "no device matches name"); 193 return -ENODEV; 194 } 195 } else if (require_dev) { 196 NL_SET_ERR_MSG_ATTR(extack, header, 197 "neither ifindex nor name specified"); 198 return -EINVAL; 199 } 200 201 if (tb[ETHTOOL_A_HEADER_PHY_INDEX]) { 202 if (dev) { 203 req_info->phy_index = nla_get_u32(tb[ETHTOOL_A_HEADER_PHY_INDEX]); 204 } else { 205 NL_SET_ERR_MSG_ATTR(extack, header, 206 "phy_index set without a netdev"); 207 return -EINVAL; 208 } 209 } 210 211 req_info->dev = dev; 212 req_info->flags = flags; 213 return 0; 214 } 215 216 struct phy_device *ethnl_req_get_phydev(const struct ethnl_req_info *req_info, 217 struct nlattr **tb, unsigned int header, 218 struct netlink_ext_ack *extack) 219 { 220 struct phy_device *phydev; 221 222 ASSERT_RTNL(); 223 224 if (!req_info->dev) 225 return NULL; 226 227 if (!req_info->phy_index) 228 return req_info->dev->phydev; 229 230 phydev = phy_link_topo_get_phy(req_info->dev, req_info->phy_index); 231 if (!phydev && tb) { 232 NL_SET_ERR_MSG_ATTR(extack, tb[header], 233 "no phy matching phyindex"); 234 return ERR_PTR(-ENODEV); 235 } 236 237 return phydev; 238 } 239 240 /** 241 * ethnl_fill_reply_header() - Put common header into a reply message 242 * @skb: skb with the message 243 * @dev: network device to describe in header 244 * @attrtype: attribute type to use for the nest 245 * 246 * Create a nested attribute with attributes describing given network device. 247 * 248 * Return: 0 on success, error value (-EMSGSIZE only) on error 249 */ 250 int ethnl_fill_reply_header(struct sk_buff *skb, struct net_device *dev, 251 u16 attrtype) 252 { 253 struct nlattr *nest; 254 255 if (!dev) 256 return 0; 257 nest = nla_nest_start(skb, attrtype); 258 if (!nest) 259 return -EMSGSIZE; 260 261 if (nla_put_u32(skb, ETHTOOL_A_HEADER_DEV_INDEX, (u32)dev->ifindex) || 262 nla_put_string(skb, ETHTOOL_A_HEADER_DEV_NAME, dev->name)) 263 goto nla_put_failure; 264 /* If more attributes are put into reply header, ethnl_header_size() 265 * must be updated to account for them. 266 */ 267 268 nla_nest_end(skb, nest); 269 return 0; 270 271 nla_put_failure: 272 nla_nest_cancel(skb, nest); 273 return -EMSGSIZE; 274 } 275 276 /** 277 * ethnl_reply_init() - Create skb for a reply and fill device identification 278 * @payload: payload length (without netlink and genetlink header) 279 * @dev: device the reply is about (may be null) 280 * @cmd: ETHTOOL_MSG_* message type for reply 281 * @hdr_attrtype: attribute type for common header 282 * @info: genetlink info of the received packet we respond to 283 * @ehdrp: place to store payload pointer returned by genlmsg_new() 284 * 285 * Return: pointer to allocated skb on success, NULL on error 286 */ 287 struct sk_buff *ethnl_reply_init(size_t payload, struct net_device *dev, u8 cmd, 288 u16 hdr_attrtype, struct genl_info *info, 289 void **ehdrp) 290 { 291 struct sk_buff *skb; 292 293 skb = genlmsg_new(payload, GFP_KERNEL); 294 if (!skb) 295 goto err; 296 *ehdrp = genlmsg_put_reply(skb, info, ðtool_genl_family, 0, cmd); 297 if (!*ehdrp) 298 goto err_free; 299 300 if (dev) { 301 int ret; 302 303 ret = ethnl_fill_reply_header(skb, dev, hdr_attrtype); 304 if (ret < 0) 305 goto err_free; 306 } 307 return skb; 308 309 err_free: 310 nlmsg_free(skb); 311 err: 312 if (info) 313 GENL_SET_ERR_MSG(info, "failed to setup reply message"); 314 return NULL; 315 } 316 317 void *ethnl_dump_put(struct sk_buff *skb, struct netlink_callback *cb, u8 cmd) 318 { 319 return genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, 320 ðtool_genl_family, 0, cmd); 321 } 322 323 void *ethnl_bcastmsg_put(struct sk_buff *skb, u8 cmd) 324 { 325 return genlmsg_put(skb, 0, ++ethnl_bcast_seq, ðtool_genl_family, 0, 326 cmd); 327 } 328 329 void *ethnl_unicast_put(struct sk_buff *skb, u32 portid, u32 seq, u8 cmd) 330 { 331 return genlmsg_put(skb, portid, seq, ðtool_genl_family, 0, cmd); 332 } 333 334 int ethnl_multicast(struct sk_buff *skb, struct net_device *dev) 335 { 336 return genlmsg_multicast_netns(ðtool_genl_family, dev_net(dev), skb, 337 0, ETHNL_MCGRP_MONITOR, GFP_KERNEL); 338 } 339 340 /* GET request helpers */ 341 342 /** 343 * struct ethnl_dump_ctx - context structure for generic dumpit() callback 344 * @ops: request ops of currently processed message type 345 * @req_info: parsed request header of processed request 346 * @reply_data: data needed to compose the reply 347 * @pos_ifindex: saved iteration position - ifindex 348 * 349 * These parameters are kept in struct netlink_callback as context preserved 350 * between iterations. They are initialized by ethnl_default_start() and used 351 * in ethnl_default_dumpit() and ethnl_default_done(). 352 */ 353 struct ethnl_dump_ctx { 354 const struct ethnl_request_ops *ops; 355 struct ethnl_req_info *req_info; 356 struct ethnl_reply_data *reply_data; 357 unsigned long pos_ifindex; 358 }; 359 360 /** 361 * struct ethnl_perphy_dump_ctx - context for dumpit() PHY-aware callbacks 362 * @ethnl_ctx: generic ethnl context 363 * @ifindex: For Filtered DUMP requests, the ifindex of the targeted netdev 364 * @pos_phyindex: iterator position for multi-msg DUMP 365 */ 366 struct ethnl_perphy_dump_ctx { 367 struct ethnl_dump_ctx ethnl_ctx; 368 unsigned int ifindex; 369 unsigned long pos_phyindex; 370 }; 371 372 static const struct ethnl_request_ops * 373 ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = { 374 [ETHTOOL_MSG_STRSET_GET] = ðnl_strset_request_ops, 375 [ETHTOOL_MSG_LINKINFO_GET] = ðnl_linkinfo_request_ops, 376 [ETHTOOL_MSG_LINKINFO_SET] = ðnl_linkinfo_request_ops, 377 [ETHTOOL_MSG_LINKMODES_GET] = ðnl_linkmodes_request_ops, 378 [ETHTOOL_MSG_LINKMODES_SET] = ðnl_linkmodes_request_ops, 379 [ETHTOOL_MSG_LINKSTATE_GET] = ðnl_linkstate_request_ops, 380 [ETHTOOL_MSG_DEBUG_GET] = ðnl_debug_request_ops, 381 [ETHTOOL_MSG_DEBUG_SET] = ðnl_debug_request_ops, 382 [ETHTOOL_MSG_WOL_GET] = ðnl_wol_request_ops, 383 [ETHTOOL_MSG_WOL_SET] = ðnl_wol_request_ops, 384 [ETHTOOL_MSG_FEATURES_GET] = ðnl_features_request_ops, 385 [ETHTOOL_MSG_PRIVFLAGS_GET] = ðnl_privflags_request_ops, 386 [ETHTOOL_MSG_PRIVFLAGS_SET] = ðnl_privflags_request_ops, 387 [ETHTOOL_MSG_RINGS_GET] = ðnl_rings_request_ops, 388 [ETHTOOL_MSG_RINGS_SET] = ðnl_rings_request_ops, 389 [ETHTOOL_MSG_CHANNELS_GET] = ðnl_channels_request_ops, 390 [ETHTOOL_MSG_CHANNELS_SET] = ðnl_channels_request_ops, 391 [ETHTOOL_MSG_COALESCE_GET] = ðnl_coalesce_request_ops, 392 [ETHTOOL_MSG_COALESCE_SET] = ðnl_coalesce_request_ops, 393 [ETHTOOL_MSG_PAUSE_GET] = ðnl_pause_request_ops, 394 [ETHTOOL_MSG_PAUSE_SET] = ðnl_pause_request_ops, 395 [ETHTOOL_MSG_EEE_GET] = ðnl_eee_request_ops, 396 [ETHTOOL_MSG_EEE_SET] = ðnl_eee_request_ops, 397 [ETHTOOL_MSG_FEC_GET] = ðnl_fec_request_ops, 398 [ETHTOOL_MSG_FEC_SET] = ðnl_fec_request_ops, 399 [ETHTOOL_MSG_TSINFO_GET] = ðnl_tsinfo_request_ops, 400 [ETHTOOL_MSG_MODULE_EEPROM_GET] = ðnl_module_eeprom_request_ops, 401 [ETHTOOL_MSG_STATS_GET] = ðnl_stats_request_ops, 402 [ETHTOOL_MSG_PHC_VCLOCKS_GET] = ðnl_phc_vclocks_request_ops, 403 [ETHTOOL_MSG_MODULE_GET] = ðnl_module_request_ops, 404 [ETHTOOL_MSG_MODULE_SET] = ðnl_module_request_ops, 405 [ETHTOOL_MSG_PSE_GET] = ðnl_pse_request_ops, 406 [ETHTOOL_MSG_PSE_SET] = ðnl_pse_request_ops, 407 [ETHTOOL_MSG_RSS_GET] = ðnl_rss_request_ops, 408 [ETHTOOL_MSG_RSS_SET] = ðnl_rss_request_ops, 409 [ETHTOOL_MSG_PLCA_GET_CFG] = ðnl_plca_cfg_request_ops, 410 [ETHTOOL_MSG_PLCA_SET_CFG] = ðnl_plca_cfg_request_ops, 411 [ETHTOOL_MSG_PLCA_GET_STATUS] = ðnl_plca_status_request_ops, 412 [ETHTOOL_MSG_MM_GET] = ðnl_mm_request_ops, 413 [ETHTOOL_MSG_MM_SET] = ðnl_mm_request_ops, 414 [ETHTOOL_MSG_TSCONFIG_GET] = ðnl_tsconfig_request_ops, 415 [ETHTOOL_MSG_TSCONFIG_SET] = ðnl_tsconfig_request_ops, 416 [ETHTOOL_MSG_PHY_GET] = ðnl_phy_request_ops, 417 }; 418 419 static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb) 420 { 421 return (struct ethnl_dump_ctx *)cb->ctx; 422 } 423 424 static struct ethnl_perphy_dump_ctx * 425 ethnl_perphy_dump_context(struct netlink_callback *cb) 426 { 427 return (struct ethnl_perphy_dump_ctx *)cb->ctx; 428 } 429 430 /** 431 * ethnl_default_parse() - Parse request message 432 * @req_info: pointer to structure to put data into 433 * @info: genl_info from the request 434 * @request_ops: struct request_ops for request type 435 * @require_dev: fail if no device identified in header 436 * 437 * Parse universal request header and call request specific ->parse_request() 438 * callback (if defined) to parse the rest of the message. 439 * 440 * Return: 0 on success or negative error code 441 */ 442 static int ethnl_default_parse(struct ethnl_req_info *req_info, 443 const struct genl_info *info, 444 const struct ethnl_request_ops *request_ops, 445 bool require_dev) 446 { 447 struct nlattr **tb = info->attrs; 448 int ret; 449 450 ret = ethnl_parse_header_dev_get(req_info, tb[request_ops->hdr_attr], 451 genl_info_net(info), info->extack, 452 require_dev); 453 if (ret < 0) 454 return ret; 455 456 if (request_ops->parse_request) { 457 ret = request_ops->parse_request(req_info, tb, info->extack); 458 if (ret < 0) 459 goto err_dev; 460 } 461 462 return 0; 463 464 err_dev: 465 netdev_put(req_info->dev, &req_info->dev_tracker); 466 req_info->dev = NULL; 467 return ret; 468 } 469 470 /** 471 * ethnl_init_reply_data() - Initialize reply data for GET request 472 * @reply_data: pointer to embedded struct ethnl_reply_data 473 * @ops: instance of struct ethnl_request_ops describing the layout 474 * @dev: network device to initialize the reply for 475 * 476 * Fills the reply data part with zeros and sets the dev member. Must be called 477 * before calling the ->fill_reply() callback (for each iteration when handling 478 * dump requests). 479 */ 480 static void ethnl_init_reply_data(struct ethnl_reply_data *reply_data, 481 const struct ethnl_request_ops *ops, 482 struct net_device *dev) 483 { 484 memset(reply_data, 0, ops->reply_data_size); 485 reply_data->dev = dev; 486 } 487 488 /* default ->doit() handler for GET type requests */ 489 static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info) 490 { 491 struct ethnl_reply_data *reply_data = NULL; 492 struct ethnl_req_info *req_info = NULL; 493 const u8 cmd = info->genlhdr->cmd; 494 const struct ethnl_request_ops *ops; 495 int hdr_len, reply_len; 496 struct sk_buff *rskb; 497 void *reply_payload; 498 int ret; 499 500 ops = ethnl_default_requests[cmd]; 501 if (WARN_ONCE(!ops, "cmd %u has no ethnl_request_ops\n", cmd)) 502 return -EOPNOTSUPP; 503 if (GENL_REQ_ATTR_CHECK(info, ops->hdr_attr)) 504 return -EINVAL; 505 506 req_info = kzalloc(ops->req_info_size, GFP_KERNEL); 507 if (!req_info) 508 return -ENOMEM; 509 reply_data = kmalloc(ops->reply_data_size, GFP_KERNEL); 510 if (!reply_data) { 511 kfree(req_info); 512 return -ENOMEM; 513 } 514 515 ret = ethnl_default_parse(req_info, info, ops, !ops->allow_nodev_do); 516 if (ret < 0) 517 goto err_free; 518 ethnl_init_reply_data(reply_data, ops, req_info->dev); 519 520 rtnl_lock(); 521 if (req_info->dev) 522 netdev_lock_ops(req_info->dev); 523 ret = ops->prepare_data(req_info, reply_data, info); 524 if (req_info->dev) 525 netdev_unlock_ops(req_info->dev); 526 rtnl_unlock(); 527 if (ret < 0) 528 goto err_dev; 529 ret = ops->reply_size(req_info, reply_data); 530 if (ret < 0) 531 goto err_cleanup; 532 reply_len = ret; 533 ret = -ENOMEM; 534 rskb = ethnl_reply_init(reply_len + ethnl_reply_header_size(), 535 req_info->dev, ops->reply_cmd, 536 ops->hdr_attr, info, &reply_payload); 537 if (!rskb) 538 goto err_cleanup; 539 hdr_len = rskb->len; 540 ret = ops->fill_reply(rskb, req_info, reply_data); 541 if (ret < 0) 542 goto err_msg; 543 WARN_ONCE(rskb->len - hdr_len > reply_len, 544 "ethnl cmd %d: calculated reply length %d, but consumed %d\n", 545 cmd, reply_len, rskb->len - hdr_len); 546 if (ops->cleanup_data) 547 ops->cleanup_data(reply_data); 548 549 genlmsg_end(rskb, reply_payload); 550 netdev_put(req_info->dev, &req_info->dev_tracker); 551 kfree(reply_data); 552 kfree(req_info); 553 return genlmsg_reply(rskb, info); 554 555 err_msg: 556 WARN_ONCE(ret == -EMSGSIZE, "calculated message payload length (%d) not sufficient\n", reply_len); 557 nlmsg_free(rskb); 558 err_cleanup: 559 if (ops->cleanup_data) 560 ops->cleanup_data(reply_data); 561 err_dev: 562 netdev_put(req_info->dev, &req_info->dev_tracker); 563 err_free: 564 kfree(reply_data); 565 kfree(req_info); 566 return ret; 567 } 568 569 static int ethnl_default_dump_one(struct sk_buff *skb, struct net_device *dev, 570 const struct ethnl_dump_ctx *ctx, 571 const struct genl_info *info) 572 { 573 void *ehdr; 574 int ret; 575 576 ehdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 577 ðtool_genl_family, NLM_F_MULTI, 578 ctx->ops->reply_cmd); 579 if (!ehdr) 580 return -EMSGSIZE; 581 582 ethnl_init_reply_data(ctx->reply_data, ctx->ops, dev); 583 rtnl_lock(); 584 netdev_lock_ops(dev); 585 ret = ctx->ops->prepare_data(ctx->req_info, ctx->reply_data, info); 586 netdev_unlock_ops(dev); 587 rtnl_unlock(); 588 if (ret < 0) 589 goto out_cancel; 590 ret = ethnl_fill_reply_header(skb, dev, ctx->ops->hdr_attr); 591 if (ret < 0) 592 goto out; 593 ret = ctx->ops->fill_reply(skb, ctx->req_info, ctx->reply_data); 594 595 out: 596 if (ctx->ops->cleanup_data) 597 ctx->ops->cleanup_data(ctx->reply_data); 598 out_cancel: 599 ctx->reply_data->dev = NULL; 600 if (ret < 0) 601 genlmsg_cancel(skb, ehdr); 602 else 603 genlmsg_end(skb, ehdr); 604 return ret; 605 } 606 607 /* Default ->dumpit() handler for GET requests. */ 608 static int ethnl_default_dumpit(struct sk_buff *skb, 609 struct netlink_callback *cb) 610 { 611 struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb); 612 struct net *net = sock_net(skb->sk); 613 netdevice_tracker dev_tracker; 614 struct net_device *dev; 615 int ret = 0; 616 617 rcu_read_lock(); 618 for_each_netdev_dump(net, dev, ctx->pos_ifindex) { 619 netdev_hold(dev, &dev_tracker, GFP_ATOMIC); 620 rcu_read_unlock(); 621 622 ret = ethnl_default_dump_one(skb, dev, ctx, genl_info_dump(cb)); 623 624 rcu_read_lock(); 625 netdev_put(dev, &dev_tracker); 626 627 if (ret < 0 && ret != -EOPNOTSUPP) { 628 if (likely(skb->len)) 629 ret = skb->len; 630 break; 631 } 632 ret = 0; 633 } 634 rcu_read_unlock(); 635 636 return ret; 637 } 638 639 /* generic ->start() handler for GET requests */ 640 static int ethnl_default_start(struct netlink_callback *cb) 641 { 642 const struct genl_dumpit_info *info = genl_dumpit_info(cb); 643 struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb); 644 struct ethnl_reply_data *reply_data; 645 const struct ethnl_request_ops *ops; 646 struct ethnl_req_info *req_info; 647 struct genlmsghdr *ghdr; 648 int ret; 649 650 BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx)); 651 652 ghdr = nlmsg_data(cb->nlh); 653 ops = ethnl_default_requests[ghdr->cmd]; 654 if (WARN_ONCE(!ops, "cmd %u has no ethnl_request_ops\n", ghdr->cmd)) 655 return -EOPNOTSUPP; 656 req_info = kzalloc(ops->req_info_size, GFP_KERNEL); 657 if (!req_info) 658 return -ENOMEM; 659 reply_data = kmalloc(ops->reply_data_size, GFP_KERNEL); 660 if (!reply_data) { 661 ret = -ENOMEM; 662 goto free_req_info; 663 } 664 665 ret = ethnl_default_parse(req_info, &info->info, ops, false); 666 if (ret < 0) 667 goto free_reply_data; 668 if (req_info->dev) { 669 /* We ignore device specification in dump requests but as the 670 * same parser as for non-dump (doit) requests is used, it 671 * would take reference to the device if it finds one 672 */ 673 netdev_put(req_info->dev, &req_info->dev_tracker); 674 req_info->dev = NULL; 675 } 676 677 ctx->ops = ops; 678 ctx->req_info = req_info; 679 ctx->reply_data = reply_data; 680 ctx->pos_ifindex = 0; 681 682 return 0; 683 684 free_reply_data: 685 kfree(reply_data); 686 free_req_info: 687 kfree(req_info); 688 689 return ret; 690 } 691 692 /* per-PHY ->start() handler for GET requests */ 693 static int ethnl_perphy_start(struct netlink_callback *cb) 694 { 695 struct ethnl_perphy_dump_ctx *phy_ctx = ethnl_perphy_dump_context(cb); 696 const struct genl_dumpit_info *info = genl_dumpit_info(cb); 697 struct ethnl_dump_ctx *ctx = &phy_ctx->ethnl_ctx; 698 struct ethnl_reply_data *reply_data; 699 const struct ethnl_request_ops *ops; 700 struct ethnl_req_info *req_info; 701 struct genlmsghdr *ghdr; 702 int ret; 703 704 BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx)); 705 706 ghdr = nlmsg_data(cb->nlh); 707 ops = ethnl_default_requests[ghdr->cmd]; 708 if (WARN_ONCE(!ops, "cmd %u has no ethnl_request_ops\n", ghdr->cmd)) 709 return -EOPNOTSUPP; 710 req_info = kzalloc(ops->req_info_size, GFP_KERNEL); 711 if (!req_info) 712 return -ENOMEM; 713 reply_data = kmalloc(ops->reply_data_size, GFP_KERNEL); 714 if (!reply_data) { 715 ret = -ENOMEM; 716 goto free_req_info; 717 } 718 719 /* Unlike per-dev dump, don't ignore dev. The dump handler 720 * will notice it and dump PHYs from given dev. We only keep track of 721 * the dev's ifindex, .dumpit() will grab and release the netdev itself. 722 */ 723 ret = ethnl_default_parse(req_info, &info->info, ops, false); 724 if (ret < 0) 725 goto free_reply_data; 726 if (req_info->dev) { 727 phy_ctx->ifindex = req_info->dev->ifindex; 728 netdev_put(req_info->dev, &req_info->dev_tracker); 729 req_info->dev = NULL; 730 } 731 732 ctx->ops = ops; 733 ctx->req_info = req_info; 734 ctx->reply_data = reply_data; 735 ctx->pos_ifindex = 0; 736 737 return 0; 738 739 free_reply_data: 740 kfree(reply_data); 741 free_req_info: 742 kfree(req_info); 743 744 return ret; 745 } 746 747 static int ethnl_perphy_dump_one_dev(struct sk_buff *skb, 748 struct ethnl_perphy_dump_ctx *ctx, 749 const struct genl_info *info) 750 { 751 struct ethnl_dump_ctx *ethnl_ctx = &ctx->ethnl_ctx; 752 struct net_device *dev = ethnl_ctx->req_info->dev; 753 struct phy_device_node *pdn; 754 int ret; 755 756 if (!dev->link_topo) 757 return 0; 758 759 xa_for_each_start(&dev->link_topo->phys, ctx->pos_phyindex, pdn, 760 ctx->pos_phyindex) { 761 ethnl_ctx->req_info->phy_index = ctx->pos_phyindex; 762 763 /* We can re-use the original dump_one as ->prepare_data in 764 * commands use ethnl_req_get_phydev(), which gets the PHY from 765 * the req_info->phy_index 766 */ 767 ret = ethnl_default_dump_one(skb, dev, ethnl_ctx, info); 768 if (ret) 769 return ret; 770 } 771 772 ctx->pos_phyindex = 0; 773 774 return 0; 775 } 776 777 static int ethnl_perphy_dump_all_dev(struct sk_buff *skb, 778 struct ethnl_perphy_dump_ctx *ctx, 779 const struct genl_info *info) 780 { 781 struct ethnl_dump_ctx *ethnl_ctx = &ctx->ethnl_ctx; 782 struct net *net = sock_net(skb->sk); 783 netdevice_tracker dev_tracker; 784 struct net_device *dev; 785 int ret = 0; 786 787 rcu_read_lock(); 788 for_each_netdev_dump(net, dev, ethnl_ctx->pos_ifindex) { 789 netdev_hold(dev, &dev_tracker, GFP_ATOMIC); 790 rcu_read_unlock(); 791 792 /* per-PHY commands use ethnl_req_get_phydev(), which needs the 793 * net_device in the req_info 794 */ 795 ethnl_ctx->req_info->dev = dev; 796 ret = ethnl_perphy_dump_one_dev(skb, ctx, info); 797 798 rcu_read_lock(); 799 netdev_put(dev, &dev_tracker); 800 ethnl_ctx->req_info->dev = NULL; 801 802 if (ret < 0 && ret != -EOPNOTSUPP) { 803 if (likely(skb->len)) 804 ret = skb->len; 805 break; 806 } 807 ret = 0; 808 } 809 rcu_read_unlock(); 810 811 return ret; 812 } 813 814 /* per-PHY ->dumpit() handler for GET requests. */ 815 static int ethnl_perphy_dumpit(struct sk_buff *skb, 816 struct netlink_callback *cb) 817 { 818 struct ethnl_perphy_dump_ctx *ctx = ethnl_perphy_dump_context(cb); 819 const struct genl_dumpit_info *info = genl_dumpit_info(cb); 820 struct ethnl_dump_ctx *ethnl_ctx = &ctx->ethnl_ctx; 821 int ret = 0; 822 823 if (ctx->ifindex) { 824 netdevice_tracker dev_tracker; 825 struct net_device *dev; 826 827 dev = netdev_get_by_index(genl_info_net(&info->info), 828 ctx->ifindex, &dev_tracker, 829 GFP_KERNEL); 830 if (!dev) 831 return -ENODEV; 832 833 ethnl_ctx->req_info->dev = dev; 834 ret = ethnl_perphy_dump_one_dev(skb, ctx, genl_info_dump(cb)); 835 836 if (ret < 0 && ret != -EOPNOTSUPP && likely(skb->len)) 837 ret = skb->len; 838 839 netdev_put(dev, &dev_tracker); 840 } else { 841 ret = ethnl_perphy_dump_all_dev(skb, ctx, genl_info_dump(cb)); 842 } 843 844 return ret; 845 } 846 847 /* per-PHY ->done() handler for GET requests */ 848 static int ethnl_perphy_done(struct netlink_callback *cb) 849 { 850 struct ethnl_perphy_dump_ctx *ctx = ethnl_perphy_dump_context(cb); 851 struct ethnl_dump_ctx *ethnl_ctx = &ctx->ethnl_ctx; 852 853 kfree(ethnl_ctx->reply_data); 854 kfree(ethnl_ctx->req_info); 855 856 return 0; 857 } 858 859 /* default ->done() handler for GET requests */ 860 static int ethnl_default_done(struct netlink_callback *cb) 861 { 862 struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb); 863 864 kfree(ctx->reply_data); 865 kfree(ctx->req_info); 866 867 return 0; 868 } 869 870 static int ethnl_default_set_doit(struct sk_buff *skb, struct genl_info *info) 871 { 872 const struct ethnl_request_ops *ops; 873 const u8 cmd = info->genlhdr->cmd; 874 struct ethnl_req_info *req_info; 875 struct net_device *dev; 876 int ret; 877 878 ops = ethnl_default_requests[cmd]; 879 if (WARN_ONCE(!ops, "cmd %u has no ethnl_request_ops\n", cmd)) 880 return -EOPNOTSUPP; 881 if (GENL_REQ_ATTR_CHECK(info, ops->hdr_attr)) 882 return -EINVAL; 883 884 req_info = kzalloc(ops->req_info_size, GFP_KERNEL); 885 if (!req_info) 886 return -ENOMEM; 887 888 ret = ethnl_default_parse(req_info, info, ops, true); 889 if (ret < 0) 890 goto out_free_req; 891 892 if (ops->set_validate) { 893 ret = ops->set_validate(req_info, info); 894 /* 0 means nothing to do */ 895 if (ret <= 0) 896 goto out_dev; 897 } 898 899 dev = req_info->dev; 900 901 rtnl_lock(); 902 netdev_lock_ops(dev); 903 dev->cfg_pending = kmemdup(dev->cfg, sizeof(*dev->cfg), 904 GFP_KERNEL_ACCOUNT); 905 if (!dev->cfg_pending) { 906 ret = -ENOMEM; 907 goto out_tie_cfg; 908 } 909 910 ret = ethnl_ops_begin(dev); 911 if (ret < 0) 912 goto out_free_cfg; 913 914 ret = ops->set(req_info, info); 915 if (ret < 0) 916 goto out_ops; 917 918 swap(dev->cfg, dev->cfg_pending); 919 if (!ret) 920 goto out_ops; 921 ethnl_notify(dev, ops->set_ntf_cmd, req_info); 922 923 ret = 0; 924 out_ops: 925 ethnl_ops_complete(dev); 926 out_free_cfg: 927 kfree(dev->cfg_pending); 928 out_tie_cfg: 929 dev->cfg_pending = dev->cfg; 930 netdev_unlock_ops(dev); 931 rtnl_unlock(); 932 out_dev: 933 ethnl_parse_header_dev_put(req_info); 934 out_free_req: 935 kfree(req_info); 936 return ret; 937 } 938 939 static const struct ethnl_request_ops * 940 ethnl_default_notify_ops[ETHTOOL_MSG_KERNEL_MAX + 1] = { 941 [ETHTOOL_MSG_LINKINFO_NTF] = ðnl_linkinfo_request_ops, 942 [ETHTOOL_MSG_LINKMODES_NTF] = ðnl_linkmodes_request_ops, 943 [ETHTOOL_MSG_DEBUG_NTF] = ðnl_debug_request_ops, 944 [ETHTOOL_MSG_WOL_NTF] = ðnl_wol_request_ops, 945 [ETHTOOL_MSG_FEATURES_NTF] = ðnl_features_request_ops, 946 [ETHTOOL_MSG_PRIVFLAGS_NTF] = ðnl_privflags_request_ops, 947 [ETHTOOL_MSG_RINGS_NTF] = ðnl_rings_request_ops, 948 [ETHTOOL_MSG_CHANNELS_NTF] = ðnl_channels_request_ops, 949 [ETHTOOL_MSG_COALESCE_NTF] = ðnl_coalesce_request_ops, 950 [ETHTOOL_MSG_PAUSE_NTF] = ðnl_pause_request_ops, 951 [ETHTOOL_MSG_EEE_NTF] = ðnl_eee_request_ops, 952 [ETHTOOL_MSG_FEC_NTF] = ðnl_fec_request_ops, 953 [ETHTOOL_MSG_MODULE_NTF] = ðnl_module_request_ops, 954 [ETHTOOL_MSG_PLCA_NTF] = ðnl_plca_cfg_request_ops, 955 [ETHTOOL_MSG_MM_NTF] = ðnl_mm_request_ops, 956 [ETHTOOL_MSG_RSS_NTF] = ðnl_rss_request_ops, 957 }; 958 959 /* default notification handler */ 960 static void ethnl_default_notify(struct net_device *dev, unsigned int cmd, 961 const struct ethnl_req_info *orig_req_info) 962 { 963 struct ethnl_reply_data *reply_data; 964 const struct ethnl_request_ops *ops; 965 struct ethnl_req_info *req_info; 966 struct genl_info info; 967 struct sk_buff *skb; 968 void *reply_payload; 969 int reply_len; 970 int ret; 971 972 genl_info_init_ntf(&info, ðtool_genl_family, cmd); 973 974 if (WARN_ONCE(cmd > ETHTOOL_MSG_KERNEL_MAX || 975 !ethnl_default_notify_ops[cmd], 976 "unexpected notification type %u\n", cmd)) 977 return; 978 ops = ethnl_default_notify_ops[cmd]; 979 req_info = kzalloc(ops->req_info_size, GFP_KERNEL); 980 if (!req_info) 981 return; 982 reply_data = kmalloc(ops->reply_data_size, GFP_KERNEL); 983 if (!reply_data) { 984 kfree(req_info); 985 return; 986 } 987 988 req_info->dev = dev; 989 req_info->flags |= ETHTOOL_FLAG_COMPACT_BITSETS; 990 if (orig_req_info) { 991 req_info->phy_index = orig_req_info->phy_index; 992 memcpy(&req_info[1], &orig_req_info[1], 993 ops->req_info_size - sizeof(*req_info)); 994 } 995 996 netdev_ops_assert_locked(dev); 997 998 ethnl_init_reply_data(reply_data, ops, dev); 999 ret = ops->prepare_data(req_info, reply_data, &info); 1000 if (ret < 0) 1001 goto err_rep; 1002 ret = ops->reply_size(req_info, reply_data); 1003 if (ret < 0) 1004 goto err_cleanup; 1005 reply_len = ret + ethnl_reply_header_size(); 1006 skb = genlmsg_new(reply_len, GFP_KERNEL); 1007 if (!skb) 1008 goto err_cleanup; 1009 reply_payload = ethnl_bcastmsg_put(skb, cmd); 1010 if (!reply_payload) 1011 goto err_skb; 1012 ret = ethnl_fill_reply_header(skb, dev, ops->hdr_attr); 1013 if (ret < 0) 1014 goto err_msg; 1015 ret = ops->fill_reply(skb, req_info, reply_data); 1016 if (ret < 0) 1017 goto err_msg; 1018 if (ops->cleanup_data) 1019 ops->cleanup_data(reply_data); 1020 1021 genlmsg_end(skb, reply_payload); 1022 kfree(reply_data); 1023 kfree(req_info); 1024 ethnl_multicast(skb, dev); 1025 return; 1026 1027 err_msg: 1028 WARN_ONCE(ret == -EMSGSIZE, 1029 "calculated message payload length (%d) not sufficient\n", 1030 reply_len); 1031 err_skb: 1032 nlmsg_free(skb); 1033 err_cleanup: 1034 if (ops->cleanup_data) 1035 ops->cleanup_data(reply_data); 1036 err_rep: 1037 kfree(reply_data); 1038 kfree(req_info); 1039 return; 1040 } 1041 1042 /* notifications */ 1043 1044 typedef void (*ethnl_notify_handler_t)(struct net_device *dev, unsigned int cmd, 1045 const struct ethnl_req_info *req_info); 1046 1047 static const ethnl_notify_handler_t ethnl_notify_handlers[] = { 1048 [ETHTOOL_MSG_LINKINFO_NTF] = ethnl_default_notify, 1049 [ETHTOOL_MSG_LINKMODES_NTF] = ethnl_default_notify, 1050 [ETHTOOL_MSG_DEBUG_NTF] = ethnl_default_notify, 1051 [ETHTOOL_MSG_WOL_NTF] = ethnl_default_notify, 1052 [ETHTOOL_MSG_FEATURES_NTF] = ethnl_default_notify, 1053 [ETHTOOL_MSG_PRIVFLAGS_NTF] = ethnl_default_notify, 1054 [ETHTOOL_MSG_RINGS_NTF] = ethnl_default_notify, 1055 [ETHTOOL_MSG_CHANNELS_NTF] = ethnl_default_notify, 1056 [ETHTOOL_MSG_COALESCE_NTF] = ethnl_default_notify, 1057 [ETHTOOL_MSG_PAUSE_NTF] = ethnl_default_notify, 1058 [ETHTOOL_MSG_EEE_NTF] = ethnl_default_notify, 1059 [ETHTOOL_MSG_FEC_NTF] = ethnl_default_notify, 1060 [ETHTOOL_MSG_MODULE_NTF] = ethnl_default_notify, 1061 [ETHTOOL_MSG_PLCA_NTF] = ethnl_default_notify, 1062 [ETHTOOL_MSG_MM_NTF] = ethnl_default_notify, 1063 [ETHTOOL_MSG_RSS_NTF] = ethnl_default_notify, 1064 }; 1065 1066 void ethnl_notify(struct net_device *dev, unsigned int cmd, 1067 const struct ethnl_req_info *req_info) 1068 { 1069 if (unlikely(!ethnl_ok)) 1070 return; 1071 ASSERT_RTNL(); 1072 1073 if (likely(cmd < ARRAY_SIZE(ethnl_notify_handlers) && 1074 ethnl_notify_handlers[cmd])) 1075 ethnl_notify_handlers[cmd](dev, cmd, req_info); 1076 else 1077 WARN_ONCE(1, "notification %u not implemented (dev=%s)\n", 1078 cmd, netdev_name(dev)); 1079 } 1080 1081 void ethtool_notify(struct net_device *dev, unsigned int cmd) 1082 { 1083 ethnl_notify(dev, cmd, NULL); 1084 } 1085 EXPORT_SYMBOL(ethtool_notify); 1086 1087 static void ethnl_notify_features(struct netdev_notifier_info *info) 1088 { 1089 struct net_device *dev = netdev_notifier_info_to_dev(info); 1090 1091 ethtool_notify(dev, ETHTOOL_MSG_FEATURES_NTF); 1092 } 1093 1094 static int ethnl_netdev_event(struct notifier_block *this, unsigned long event, 1095 void *ptr) 1096 { 1097 struct netdev_notifier_info *info = ptr; 1098 struct netlink_ext_ack *extack; 1099 struct net_device *dev; 1100 1101 dev = netdev_notifier_info_to_dev(info); 1102 extack = netdev_notifier_info_to_extack(info); 1103 1104 switch (event) { 1105 case NETDEV_FEAT_CHANGE: 1106 ethnl_notify_features(ptr); 1107 break; 1108 case NETDEV_PRE_UP: 1109 if (dev->ethtool->module_fw_flash_in_progress) { 1110 NL_SET_ERR_MSG(extack, "Can't set port up while flashing module firmware"); 1111 return NOTIFY_BAD; 1112 } 1113 } 1114 1115 return NOTIFY_DONE; 1116 } 1117 1118 static struct notifier_block ethnl_netdev_notifier = { 1119 .notifier_call = ethnl_netdev_event, 1120 }; 1121 1122 /* genetlink setup */ 1123 1124 static const struct genl_ops ethtool_genl_ops[] = { 1125 { 1126 .cmd = ETHTOOL_MSG_STRSET_GET, 1127 .doit = ethnl_default_doit, 1128 .start = ethnl_default_start, 1129 .dumpit = ethnl_default_dumpit, 1130 .done = ethnl_default_done, 1131 .policy = ethnl_strset_get_policy, 1132 .maxattr = ARRAY_SIZE(ethnl_strset_get_policy) - 1, 1133 }, 1134 { 1135 .cmd = ETHTOOL_MSG_LINKINFO_GET, 1136 .doit = ethnl_default_doit, 1137 .start = ethnl_default_start, 1138 .dumpit = ethnl_default_dumpit, 1139 .done = ethnl_default_done, 1140 .policy = ethnl_linkinfo_get_policy, 1141 .maxattr = ARRAY_SIZE(ethnl_linkinfo_get_policy) - 1, 1142 }, 1143 { 1144 .cmd = ETHTOOL_MSG_LINKINFO_SET, 1145 .flags = GENL_UNS_ADMIN_PERM, 1146 .doit = ethnl_default_set_doit, 1147 .policy = ethnl_linkinfo_set_policy, 1148 .maxattr = ARRAY_SIZE(ethnl_linkinfo_set_policy) - 1, 1149 }, 1150 { 1151 .cmd = ETHTOOL_MSG_LINKMODES_GET, 1152 .doit = ethnl_default_doit, 1153 .start = ethnl_default_start, 1154 .dumpit = ethnl_default_dumpit, 1155 .done = ethnl_default_done, 1156 .policy = ethnl_linkmodes_get_policy, 1157 .maxattr = ARRAY_SIZE(ethnl_linkmodes_get_policy) - 1, 1158 }, 1159 { 1160 .cmd = ETHTOOL_MSG_LINKMODES_SET, 1161 .flags = GENL_UNS_ADMIN_PERM, 1162 .doit = ethnl_default_set_doit, 1163 .policy = ethnl_linkmodes_set_policy, 1164 .maxattr = ARRAY_SIZE(ethnl_linkmodes_set_policy) - 1, 1165 }, 1166 { 1167 .cmd = ETHTOOL_MSG_LINKSTATE_GET, 1168 .doit = ethnl_default_doit, 1169 .start = ethnl_default_start, 1170 .dumpit = ethnl_default_dumpit, 1171 .done = ethnl_default_done, 1172 .policy = ethnl_linkstate_get_policy, 1173 .maxattr = ARRAY_SIZE(ethnl_linkstate_get_policy) - 1, 1174 }, 1175 { 1176 .cmd = ETHTOOL_MSG_DEBUG_GET, 1177 .doit = ethnl_default_doit, 1178 .start = ethnl_default_start, 1179 .dumpit = ethnl_default_dumpit, 1180 .done = ethnl_default_done, 1181 .policy = ethnl_debug_get_policy, 1182 .maxattr = ARRAY_SIZE(ethnl_debug_get_policy) - 1, 1183 }, 1184 { 1185 .cmd = ETHTOOL_MSG_DEBUG_SET, 1186 .flags = GENL_UNS_ADMIN_PERM, 1187 .doit = ethnl_default_set_doit, 1188 .policy = ethnl_debug_set_policy, 1189 .maxattr = ARRAY_SIZE(ethnl_debug_set_policy) - 1, 1190 }, 1191 { 1192 .cmd = ETHTOOL_MSG_WOL_GET, 1193 .flags = GENL_UNS_ADMIN_PERM, 1194 .doit = ethnl_default_doit, 1195 .start = ethnl_default_start, 1196 .dumpit = ethnl_default_dumpit, 1197 .done = ethnl_default_done, 1198 .policy = ethnl_wol_get_policy, 1199 .maxattr = ARRAY_SIZE(ethnl_wol_get_policy) - 1, 1200 }, 1201 { 1202 .cmd = ETHTOOL_MSG_WOL_SET, 1203 .flags = GENL_UNS_ADMIN_PERM, 1204 .doit = ethnl_default_set_doit, 1205 .policy = ethnl_wol_set_policy, 1206 .maxattr = ARRAY_SIZE(ethnl_wol_set_policy) - 1, 1207 }, 1208 { 1209 .cmd = ETHTOOL_MSG_FEATURES_GET, 1210 .doit = ethnl_default_doit, 1211 .start = ethnl_default_start, 1212 .dumpit = ethnl_default_dumpit, 1213 .done = ethnl_default_done, 1214 .policy = ethnl_features_get_policy, 1215 .maxattr = ARRAY_SIZE(ethnl_features_get_policy) - 1, 1216 }, 1217 { 1218 .cmd = ETHTOOL_MSG_FEATURES_SET, 1219 .flags = GENL_UNS_ADMIN_PERM, 1220 .doit = ethnl_set_features, 1221 .policy = ethnl_features_set_policy, 1222 .maxattr = ARRAY_SIZE(ethnl_features_set_policy) - 1, 1223 }, 1224 { 1225 .cmd = ETHTOOL_MSG_PRIVFLAGS_GET, 1226 .doit = ethnl_default_doit, 1227 .start = ethnl_default_start, 1228 .dumpit = ethnl_default_dumpit, 1229 .done = ethnl_default_done, 1230 .policy = ethnl_privflags_get_policy, 1231 .maxattr = ARRAY_SIZE(ethnl_privflags_get_policy) - 1, 1232 }, 1233 { 1234 .cmd = ETHTOOL_MSG_PRIVFLAGS_SET, 1235 .flags = GENL_UNS_ADMIN_PERM, 1236 .doit = ethnl_default_set_doit, 1237 .policy = ethnl_privflags_set_policy, 1238 .maxattr = ARRAY_SIZE(ethnl_privflags_set_policy) - 1, 1239 }, 1240 { 1241 .cmd = ETHTOOL_MSG_RINGS_GET, 1242 .doit = ethnl_default_doit, 1243 .start = ethnl_default_start, 1244 .dumpit = ethnl_default_dumpit, 1245 .done = ethnl_default_done, 1246 .policy = ethnl_rings_get_policy, 1247 .maxattr = ARRAY_SIZE(ethnl_rings_get_policy) - 1, 1248 }, 1249 { 1250 .cmd = ETHTOOL_MSG_RINGS_SET, 1251 .flags = GENL_UNS_ADMIN_PERM, 1252 .doit = ethnl_default_set_doit, 1253 .policy = ethnl_rings_set_policy, 1254 .maxattr = ARRAY_SIZE(ethnl_rings_set_policy) - 1, 1255 }, 1256 { 1257 .cmd = ETHTOOL_MSG_CHANNELS_GET, 1258 .doit = ethnl_default_doit, 1259 .start = ethnl_default_start, 1260 .dumpit = ethnl_default_dumpit, 1261 .done = ethnl_default_done, 1262 .policy = ethnl_channels_get_policy, 1263 .maxattr = ARRAY_SIZE(ethnl_channels_get_policy) - 1, 1264 }, 1265 { 1266 .cmd = ETHTOOL_MSG_CHANNELS_SET, 1267 .flags = GENL_UNS_ADMIN_PERM, 1268 .doit = ethnl_default_set_doit, 1269 .policy = ethnl_channels_set_policy, 1270 .maxattr = ARRAY_SIZE(ethnl_channels_set_policy) - 1, 1271 }, 1272 { 1273 .cmd = ETHTOOL_MSG_COALESCE_GET, 1274 .doit = ethnl_default_doit, 1275 .start = ethnl_default_start, 1276 .dumpit = ethnl_default_dumpit, 1277 .done = ethnl_default_done, 1278 .policy = ethnl_coalesce_get_policy, 1279 .maxattr = ARRAY_SIZE(ethnl_coalesce_get_policy) - 1, 1280 }, 1281 { 1282 .cmd = ETHTOOL_MSG_COALESCE_SET, 1283 .flags = GENL_UNS_ADMIN_PERM, 1284 .doit = ethnl_default_set_doit, 1285 .policy = ethnl_coalesce_set_policy, 1286 .maxattr = ARRAY_SIZE(ethnl_coalesce_set_policy) - 1, 1287 }, 1288 { 1289 .cmd = ETHTOOL_MSG_PAUSE_GET, 1290 .doit = ethnl_default_doit, 1291 .start = ethnl_default_start, 1292 .dumpit = ethnl_default_dumpit, 1293 .done = ethnl_default_done, 1294 .policy = ethnl_pause_get_policy, 1295 .maxattr = ARRAY_SIZE(ethnl_pause_get_policy) - 1, 1296 }, 1297 { 1298 .cmd = ETHTOOL_MSG_PAUSE_SET, 1299 .flags = GENL_UNS_ADMIN_PERM, 1300 .doit = ethnl_default_set_doit, 1301 .policy = ethnl_pause_set_policy, 1302 .maxattr = ARRAY_SIZE(ethnl_pause_set_policy) - 1, 1303 }, 1304 { 1305 .cmd = ETHTOOL_MSG_EEE_GET, 1306 .doit = ethnl_default_doit, 1307 .start = ethnl_default_start, 1308 .dumpit = ethnl_default_dumpit, 1309 .done = ethnl_default_done, 1310 .policy = ethnl_eee_get_policy, 1311 .maxattr = ARRAY_SIZE(ethnl_eee_get_policy) - 1, 1312 }, 1313 { 1314 .cmd = ETHTOOL_MSG_EEE_SET, 1315 .flags = GENL_UNS_ADMIN_PERM, 1316 .doit = ethnl_default_set_doit, 1317 .policy = ethnl_eee_set_policy, 1318 .maxattr = ARRAY_SIZE(ethnl_eee_set_policy) - 1, 1319 }, 1320 { 1321 .cmd = ETHTOOL_MSG_TSINFO_GET, 1322 .doit = ethnl_default_doit, 1323 .start = ethnl_tsinfo_start, 1324 .dumpit = ethnl_tsinfo_dumpit, 1325 .done = ethnl_tsinfo_done, 1326 .policy = ethnl_tsinfo_get_policy, 1327 .maxattr = ARRAY_SIZE(ethnl_tsinfo_get_policy) - 1, 1328 }, 1329 { 1330 .cmd = ETHTOOL_MSG_CABLE_TEST_ACT, 1331 .flags = GENL_UNS_ADMIN_PERM, 1332 .doit = ethnl_act_cable_test, 1333 .policy = ethnl_cable_test_act_policy, 1334 .maxattr = ARRAY_SIZE(ethnl_cable_test_act_policy) - 1, 1335 }, 1336 { 1337 .cmd = ETHTOOL_MSG_CABLE_TEST_TDR_ACT, 1338 .flags = GENL_UNS_ADMIN_PERM, 1339 .doit = ethnl_act_cable_test_tdr, 1340 .policy = ethnl_cable_test_tdr_act_policy, 1341 .maxattr = ARRAY_SIZE(ethnl_cable_test_tdr_act_policy) - 1, 1342 }, 1343 { 1344 .cmd = ETHTOOL_MSG_TUNNEL_INFO_GET, 1345 .doit = ethnl_tunnel_info_doit, 1346 .start = ethnl_tunnel_info_start, 1347 .dumpit = ethnl_tunnel_info_dumpit, 1348 .policy = ethnl_tunnel_info_get_policy, 1349 .maxattr = ARRAY_SIZE(ethnl_tunnel_info_get_policy) - 1, 1350 }, 1351 { 1352 .cmd = ETHTOOL_MSG_FEC_GET, 1353 .doit = ethnl_default_doit, 1354 .start = ethnl_default_start, 1355 .dumpit = ethnl_default_dumpit, 1356 .done = ethnl_default_done, 1357 .policy = ethnl_fec_get_policy, 1358 .maxattr = ARRAY_SIZE(ethnl_fec_get_policy) - 1, 1359 }, 1360 { 1361 .cmd = ETHTOOL_MSG_FEC_SET, 1362 .flags = GENL_UNS_ADMIN_PERM, 1363 .doit = ethnl_default_set_doit, 1364 .policy = ethnl_fec_set_policy, 1365 .maxattr = ARRAY_SIZE(ethnl_fec_set_policy) - 1, 1366 }, 1367 { 1368 .cmd = ETHTOOL_MSG_MODULE_EEPROM_GET, 1369 .flags = GENL_UNS_ADMIN_PERM, 1370 .doit = ethnl_default_doit, 1371 .start = ethnl_default_start, 1372 .dumpit = ethnl_default_dumpit, 1373 .done = ethnl_default_done, 1374 .policy = ethnl_module_eeprom_get_policy, 1375 .maxattr = ARRAY_SIZE(ethnl_module_eeprom_get_policy) - 1, 1376 }, 1377 { 1378 .cmd = ETHTOOL_MSG_STATS_GET, 1379 .doit = ethnl_default_doit, 1380 .start = ethnl_default_start, 1381 .dumpit = ethnl_default_dumpit, 1382 .done = ethnl_default_done, 1383 .policy = ethnl_stats_get_policy, 1384 .maxattr = ARRAY_SIZE(ethnl_stats_get_policy) - 1, 1385 }, 1386 { 1387 .cmd = ETHTOOL_MSG_PHC_VCLOCKS_GET, 1388 .doit = ethnl_default_doit, 1389 .start = ethnl_default_start, 1390 .dumpit = ethnl_default_dumpit, 1391 .done = ethnl_default_done, 1392 .policy = ethnl_phc_vclocks_get_policy, 1393 .maxattr = ARRAY_SIZE(ethnl_phc_vclocks_get_policy) - 1, 1394 }, 1395 { 1396 .cmd = ETHTOOL_MSG_MODULE_GET, 1397 .doit = ethnl_default_doit, 1398 .start = ethnl_default_start, 1399 .dumpit = ethnl_default_dumpit, 1400 .done = ethnl_default_done, 1401 .policy = ethnl_module_get_policy, 1402 .maxattr = ARRAY_SIZE(ethnl_module_get_policy) - 1, 1403 }, 1404 { 1405 .cmd = ETHTOOL_MSG_MODULE_SET, 1406 .flags = GENL_UNS_ADMIN_PERM, 1407 .doit = ethnl_default_set_doit, 1408 .policy = ethnl_module_set_policy, 1409 .maxattr = ARRAY_SIZE(ethnl_module_set_policy) - 1, 1410 }, 1411 { 1412 .cmd = ETHTOOL_MSG_PSE_GET, 1413 .doit = ethnl_default_doit, 1414 .start = ethnl_perphy_start, 1415 .dumpit = ethnl_perphy_dumpit, 1416 .done = ethnl_perphy_done, 1417 .policy = ethnl_pse_get_policy, 1418 .maxattr = ARRAY_SIZE(ethnl_pse_get_policy) - 1, 1419 }, 1420 { 1421 .cmd = ETHTOOL_MSG_PSE_SET, 1422 .flags = GENL_UNS_ADMIN_PERM, 1423 .doit = ethnl_default_set_doit, 1424 .policy = ethnl_pse_set_policy, 1425 .maxattr = ARRAY_SIZE(ethnl_pse_set_policy) - 1, 1426 }, 1427 { 1428 .cmd = ETHTOOL_MSG_RSS_GET, 1429 .doit = ethnl_default_doit, 1430 .start = ethnl_rss_dump_start, 1431 .dumpit = ethnl_rss_dumpit, 1432 .policy = ethnl_rss_get_policy, 1433 .maxattr = ARRAY_SIZE(ethnl_rss_get_policy) - 1, 1434 }, 1435 { 1436 .cmd = ETHTOOL_MSG_PLCA_GET_CFG, 1437 .doit = ethnl_default_doit, 1438 .start = ethnl_perphy_start, 1439 .dumpit = ethnl_perphy_dumpit, 1440 .done = ethnl_perphy_done, 1441 .policy = ethnl_plca_get_cfg_policy, 1442 .maxattr = ARRAY_SIZE(ethnl_plca_get_cfg_policy) - 1, 1443 }, 1444 { 1445 .cmd = ETHTOOL_MSG_PLCA_SET_CFG, 1446 .flags = GENL_UNS_ADMIN_PERM, 1447 .doit = ethnl_default_set_doit, 1448 .policy = ethnl_plca_set_cfg_policy, 1449 .maxattr = ARRAY_SIZE(ethnl_plca_set_cfg_policy) - 1, 1450 }, 1451 { 1452 .cmd = ETHTOOL_MSG_PLCA_GET_STATUS, 1453 .doit = ethnl_default_doit, 1454 .start = ethnl_perphy_start, 1455 .dumpit = ethnl_perphy_dumpit, 1456 .done = ethnl_perphy_done, 1457 .policy = ethnl_plca_get_status_policy, 1458 .maxattr = ARRAY_SIZE(ethnl_plca_get_status_policy) - 1, 1459 }, 1460 { 1461 .cmd = ETHTOOL_MSG_MM_GET, 1462 .doit = ethnl_default_doit, 1463 .start = ethnl_default_start, 1464 .dumpit = ethnl_default_dumpit, 1465 .done = ethnl_default_done, 1466 .policy = ethnl_mm_get_policy, 1467 .maxattr = ARRAY_SIZE(ethnl_mm_get_policy) - 1, 1468 }, 1469 { 1470 .cmd = ETHTOOL_MSG_MM_SET, 1471 .flags = GENL_UNS_ADMIN_PERM, 1472 .doit = ethnl_default_set_doit, 1473 .policy = ethnl_mm_set_policy, 1474 .maxattr = ARRAY_SIZE(ethnl_mm_set_policy) - 1, 1475 }, 1476 { 1477 .cmd = ETHTOOL_MSG_MODULE_FW_FLASH_ACT, 1478 .flags = GENL_UNS_ADMIN_PERM, 1479 .doit = ethnl_act_module_fw_flash, 1480 .policy = ethnl_module_fw_flash_act_policy, 1481 .maxattr = ARRAY_SIZE(ethnl_module_fw_flash_act_policy) - 1, 1482 }, 1483 { 1484 .cmd = ETHTOOL_MSG_PHY_GET, 1485 .doit = ethnl_default_doit, 1486 .start = ethnl_perphy_start, 1487 .dumpit = ethnl_perphy_dumpit, 1488 .done = ethnl_perphy_done, 1489 .policy = ethnl_phy_get_policy, 1490 .maxattr = ARRAY_SIZE(ethnl_phy_get_policy) - 1, 1491 }, 1492 { 1493 .cmd = ETHTOOL_MSG_TSCONFIG_GET, 1494 .doit = ethnl_default_doit, 1495 .start = ethnl_default_start, 1496 .dumpit = ethnl_default_dumpit, 1497 .done = ethnl_default_done, 1498 .policy = ethnl_tsconfig_get_policy, 1499 .maxattr = ARRAY_SIZE(ethnl_tsconfig_get_policy) - 1, 1500 }, 1501 { 1502 .cmd = ETHTOOL_MSG_TSCONFIG_SET, 1503 .flags = GENL_UNS_ADMIN_PERM, 1504 .doit = ethnl_default_set_doit, 1505 .policy = ethnl_tsconfig_set_policy, 1506 .maxattr = ARRAY_SIZE(ethnl_tsconfig_set_policy) - 1, 1507 }, 1508 { 1509 .cmd = ETHTOOL_MSG_RSS_SET, 1510 .flags = GENL_UNS_ADMIN_PERM, 1511 .doit = ethnl_default_set_doit, 1512 .policy = ethnl_rss_set_policy, 1513 .maxattr = ARRAY_SIZE(ethnl_rss_set_policy) - 1, 1514 }, 1515 }; 1516 1517 static const struct genl_multicast_group ethtool_nl_mcgrps[] = { 1518 [ETHNL_MCGRP_MONITOR] = { .name = ETHTOOL_MCGRP_MONITOR_NAME }, 1519 }; 1520 1521 static struct genl_family ethtool_genl_family __ro_after_init = { 1522 .name = ETHTOOL_GENL_NAME, 1523 .version = ETHTOOL_GENL_VERSION, 1524 .netnsok = true, 1525 .parallel_ops = true, 1526 .ops = ethtool_genl_ops, 1527 .n_ops = ARRAY_SIZE(ethtool_genl_ops), 1528 .resv_start_op = ETHTOOL_MSG_MODULE_GET + 1, 1529 .mcgrps = ethtool_nl_mcgrps, 1530 .n_mcgrps = ARRAY_SIZE(ethtool_nl_mcgrps), 1531 .sock_priv_size = sizeof(struct ethnl_sock_priv), 1532 .sock_priv_destroy = ethnl_sock_priv_destroy, 1533 }; 1534 1535 /* module setup */ 1536 1537 static int __init ethnl_init(void) 1538 { 1539 int ret; 1540 1541 ret = genl_register_family(ðtool_genl_family); 1542 if (WARN(ret < 0, "ethtool: genetlink family registration failed")) 1543 return ret; 1544 ethnl_ok = true; 1545 1546 ret = register_netdevice_notifier(ðnl_netdev_notifier); 1547 WARN(ret < 0, "ethtool: net device notifier registration failed"); 1548 return ret; 1549 } 1550 1551 subsys_initcall(ethnl_init); 1552