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_PLCA_GET_CFG] = ðnl_plca_cfg_request_ops, 409 [ETHTOOL_MSG_PLCA_SET_CFG] = ðnl_plca_cfg_request_ops, 410 [ETHTOOL_MSG_PLCA_GET_STATUS] = ðnl_plca_status_request_ops, 411 [ETHTOOL_MSG_MM_GET] = ðnl_mm_request_ops, 412 [ETHTOOL_MSG_MM_SET] = ðnl_mm_request_ops, 413 [ETHTOOL_MSG_TSCONFIG_GET] = ðnl_tsconfig_request_ops, 414 [ETHTOOL_MSG_TSCONFIG_SET] = ðnl_tsconfig_request_ops, 415 [ETHTOOL_MSG_PHY_GET] = ðnl_phy_request_ops, 416 }; 417 418 static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb) 419 { 420 return (struct ethnl_dump_ctx *)cb->ctx; 421 } 422 423 static struct ethnl_perphy_dump_ctx * 424 ethnl_perphy_dump_context(struct netlink_callback *cb) 425 { 426 return (struct ethnl_perphy_dump_ctx *)cb->ctx; 427 } 428 429 /** 430 * ethnl_default_parse() - Parse request message 431 * @req_info: pointer to structure to put data into 432 * @info: genl_info from the request 433 * @request_ops: struct request_ops for request type 434 * @require_dev: fail if no device identified in header 435 * 436 * Parse universal request header and call request specific ->parse_request() 437 * callback (if defined) to parse the rest of the message. 438 * 439 * Return: 0 on success or negative error code 440 */ 441 static int ethnl_default_parse(struct ethnl_req_info *req_info, 442 const struct genl_info *info, 443 const struct ethnl_request_ops *request_ops, 444 bool require_dev) 445 { 446 struct nlattr **tb = info->attrs; 447 int ret; 448 449 ret = ethnl_parse_header_dev_get(req_info, tb[request_ops->hdr_attr], 450 genl_info_net(info), info->extack, 451 require_dev); 452 if (ret < 0) 453 return ret; 454 455 if (request_ops->parse_request) { 456 ret = request_ops->parse_request(req_info, tb, info->extack); 457 if (ret < 0) 458 goto err_dev; 459 } 460 461 return 0; 462 463 err_dev: 464 netdev_put(req_info->dev, &req_info->dev_tracker); 465 req_info->dev = NULL; 466 return ret; 467 } 468 469 /** 470 * ethnl_init_reply_data() - Initialize reply data for GET request 471 * @reply_data: pointer to embedded struct ethnl_reply_data 472 * @ops: instance of struct ethnl_request_ops describing the layout 473 * @dev: network device to initialize the reply for 474 * 475 * Fills the reply data part with zeros and sets the dev member. Must be called 476 * before calling the ->fill_reply() callback (for each iteration when handling 477 * dump requests). 478 */ 479 static void ethnl_init_reply_data(struct ethnl_reply_data *reply_data, 480 const struct ethnl_request_ops *ops, 481 struct net_device *dev) 482 { 483 memset(reply_data, 0, ops->reply_data_size); 484 reply_data->dev = dev; 485 } 486 487 /* default ->doit() handler for GET type requests */ 488 static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info) 489 { 490 struct ethnl_reply_data *reply_data = NULL; 491 struct ethnl_req_info *req_info = NULL; 492 const u8 cmd = info->genlhdr->cmd; 493 const struct ethnl_request_ops *ops; 494 int hdr_len, reply_len; 495 struct sk_buff *rskb; 496 void *reply_payload; 497 int ret; 498 499 ops = ethnl_default_requests[cmd]; 500 if (WARN_ONCE(!ops, "cmd %u has no ethnl_request_ops\n", cmd)) 501 return -EOPNOTSUPP; 502 if (GENL_REQ_ATTR_CHECK(info, ops->hdr_attr)) 503 return -EINVAL; 504 505 req_info = kzalloc(ops->req_info_size, GFP_KERNEL); 506 if (!req_info) 507 return -ENOMEM; 508 reply_data = kmalloc(ops->reply_data_size, GFP_KERNEL); 509 if (!reply_data) { 510 kfree(req_info); 511 return -ENOMEM; 512 } 513 514 ret = ethnl_default_parse(req_info, info, ops, !ops->allow_nodev_do); 515 if (ret < 0) 516 goto err_free; 517 ethnl_init_reply_data(reply_data, ops, req_info->dev); 518 519 rtnl_lock(); 520 if (req_info->dev) 521 netdev_lock_ops(req_info->dev); 522 ret = ops->prepare_data(req_info, reply_data, info); 523 if (req_info->dev) 524 netdev_unlock_ops(req_info->dev); 525 rtnl_unlock(); 526 if (ret < 0) 527 goto err_dev; 528 ret = ops->reply_size(req_info, reply_data); 529 if (ret < 0) 530 goto err_cleanup; 531 reply_len = ret; 532 ret = -ENOMEM; 533 rskb = ethnl_reply_init(reply_len + ethnl_reply_header_size(), 534 req_info->dev, ops->reply_cmd, 535 ops->hdr_attr, info, &reply_payload); 536 if (!rskb) 537 goto err_cleanup; 538 hdr_len = rskb->len; 539 ret = ops->fill_reply(rskb, req_info, reply_data); 540 if (ret < 0) 541 goto err_msg; 542 WARN_ONCE(rskb->len - hdr_len > reply_len, 543 "ethnl cmd %d: calculated reply length %d, but consumed %d\n", 544 cmd, reply_len, rskb->len - hdr_len); 545 if (ops->cleanup_data) 546 ops->cleanup_data(reply_data); 547 548 genlmsg_end(rskb, reply_payload); 549 netdev_put(req_info->dev, &req_info->dev_tracker); 550 kfree(reply_data); 551 kfree(req_info); 552 return genlmsg_reply(rskb, info); 553 554 err_msg: 555 WARN_ONCE(ret == -EMSGSIZE, "calculated message payload length (%d) not sufficient\n", reply_len); 556 nlmsg_free(rskb); 557 err_cleanup: 558 if (ops->cleanup_data) 559 ops->cleanup_data(reply_data); 560 err_dev: 561 netdev_put(req_info->dev, &req_info->dev_tracker); 562 err_free: 563 kfree(reply_data); 564 kfree(req_info); 565 return ret; 566 } 567 568 static int ethnl_default_dump_one(struct sk_buff *skb, struct net_device *dev, 569 const struct ethnl_dump_ctx *ctx, 570 const struct genl_info *info) 571 { 572 void *ehdr; 573 int ret; 574 575 ehdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 576 ðtool_genl_family, NLM_F_MULTI, 577 ctx->ops->reply_cmd); 578 if (!ehdr) 579 return -EMSGSIZE; 580 581 ethnl_init_reply_data(ctx->reply_data, ctx->ops, dev); 582 rtnl_lock(); 583 netdev_lock_ops(dev); 584 ret = ctx->ops->prepare_data(ctx->req_info, ctx->reply_data, info); 585 netdev_unlock_ops(dev); 586 rtnl_unlock(); 587 if (ret < 0) 588 goto out_cancel; 589 ret = ethnl_fill_reply_header(skb, dev, ctx->ops->hdr_attr); 590 if (ret < 0) 591 goto out; 592 ret = ctx->ops->fill_reply(skb, ctx->req_info, ctx->reply_data); 593 594 out: 595 if (ctx->ops->cleanup_data) 596 ctx->ops->cleanup_data(ctx->reply_data); 597 out_cancel: 598 ctx->reply_data->dev = NULL; 599 if (ret < 0) 600 genlmsg_cancel(skb, ehdr); 601 else 602 genlmsg_end(skb, ehdr); 603 return ret; 604 } 605 606 /* Default ->dumpit() handler for GET requests. */ 607 static int ethnl_default_dumpit(struct sk_buff *skb, 608 struct netlink_callback *cb) 609 { 610 struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb); 611 struct net *net = sock_net(skb->sk); 612 netdevice_tracker dev_tracker; 613 struct net_device *dev; 614 int ret = 0; 615 616 rcu_read_lock(); 617 for_each_netdev_dump(net, dev, ctx->pos_ifindex) { 618 netdev_hold(dev, &dev_tracker, GFP_ATOMIC); 619 rcu_read_unlock(); 620 621 ret = ethnl_default_dump_one(skb, dev, ctx, genl_info_dump(cb)); 622 623 rcu_read_lock(); 624 netdev_put(dev, &dev_tracker); 625 626 if (ret < 0 && ret != -EOPNOTSUPP) { 627 if (likely(skb->len)) 628 ret = skb->len; 629 break; 630 } 631 ret = 0; 632 } 633 rcu_read_unlock(); 634 635 return ret; 636 } 637 638 /* generic ->start() handler for GET requests */ 639 static int ethnl_default_start(struct netlink_callback *cb) 640 { 641 const struct genl_dumpit_info *info = genl_dumpit_info(cb); 642 struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb); 643 struct ethnl_reply_data *reply_data; 644 const struct ethnl_request_ops *ops; 645 struct ethnl_req_info *req_info; 646 struct genlmsghdr *ghdr; 647 int ret; 648 649 BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx)); 650 651 ghdr = nlmsg_data(cb->nlh); 652 ops = ethnl_default_requests[ghdr->cmd]; 653 if (WARN_ONCE(!ops, "cmd %u has no ethnl_request_ops\n", ghdr->cmd)) 654 return -EOPNOTSUPP; 655 req_info = kzalloc(ops->req_info_size, GFP_KERNEL); 656 if (!req_info) 657 return -ENOMEM; 658 reply_data = kmalloc(ops->reply_data_size, GFP_KERNEL); 659 if (!reply_data) { 660 ret = -ENOMEM; 661 goto free_req_info; 662 } 663 664 ret = ethnl_default_parse(req_info, &info->info, ops, false); 665 if (ret < 0) 666 goto free_reply_data; 667 if (req_info->dev) { 668 /* We ignore device specification in dump requests but as the 669 * same parser as for non-dump (doit) requests is used, it 670 * would take reference to the device if it finds one 671 */ 672 netdev_put(req_info->dev, &req_info->dev_tracker); 673 req_info->dev = NULL; 674 } 675 676 ctx->ops = ops; 677 ctx->req_info = req_info; 678 ctx->reply_data = reply_data; 679 ctx->pos_ifindex = 0; 680 681 return 0; 682 683 free_reply_data: 684 kfree(reply_data); 685 free_req_info: 686 kfree(req_info); 687 688 return ret; 689 } 690 691 /* per-PHY ->start() handler for GET requests */ 692 static int ethnl_perphy_start(struct netlink_callback *cb) 693 { 694 struct ethnl_perphy_dump_ctx *phy_ctx = ethnl_perphy_dump_context(cb); 695 const struct genl_dumpit_info *info = genl_dumpit_info(cb); 696 struct ethnl_dump_ctx *ctx = &phy_ctx->ethnl_ctx; 697 struct ethnl_reply_data *reply_data; 698 const struct ethnl_request_ops *ops; 699 struct ethnl_req_info *req_info; 700 struct genlmsghdr *ghdr; 701 int ret; 702 703 BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx)); 704 705 ghdr = nlmsg_data(cb->nlh); 706 ops = ethnl_default_requests[ghdr->cmd]; 707 if (WARN_ONCE(!ops, "cmd %u has no ethnl_request_ops\n", ghdr->cmd)) 708 return -EOPNOTSUPP; 709 req_info = kzalloc(ops->req_info_size, GFP_KERNEL); 710 if (!req_info) 711 return -ENOMEM; 712 reply_data = kmalloc(ops->reply_data_size, GFP_KERNEL); 713 if (!reply_data) { 714 ret = -ENOMEM; 715 goto free_req_info; 716 } 717 718 /* Unlike per-dev dump, don't ignore dev. The dump handler 719 * will notice it and dump PHYs from given dev. We only keep track of 720 * the dev's ifindex, .dumpit() will grab and release the netdev itself. 721 */ 722 ret = ethnl_default_parse(req_info, &info->info, ops, false); 723 if (ret < 0) 724 goto free_reply_data; 725 if (req_info->dev) { 726 phy_ctx->ifindex = req_info->dev->ifindex; 727 netdev_put(req_info->dev, &req_info->dev_tracker); 728 req_info->dev = NULL; 729 } 730 731 ctx->ops = ops; 732 ctx->req_info = req_info; 733 ctx->reply_data = reply_data; 734 ctx->pos_ifindex = 0; 735 736 return 0; 737 738 free_reply_data: 739 kfree(reply_data); 740 free_req_info: 741 kfree(req_info); 742 743 return ret; 744 } 745 746 static int ethnl_perphy_dump_one_dev(struct sk_buff *skb, 747 struct ethnl_perphy_dump_ctx *ctx, 748 const struct genl_info *info) 749 { 750 struct ethnl_dump_ctx *ethnl_ctx = &ctx->ethnl_ctx; 751 struct net_device *dev = ethnl_ctx->req_info->dev; 752 struct phy_device_node *pdn; 753 int ret; 754 755 if (!dev->link_topo) 756 return 0; 757 758 xa_for_each_start(&dev->link_topo->phys, ctx->pos_phyindex, pdn, 759 ctx->pos_phyindex) { 760 ethnl_ctx->req_info->phy_index = ctx->pos_phyindex; 761 762 /* We can re-use the original dump_one as ->prepare_data in 763 * commands use ethnl_req_get_phydev(), which gets the PHY from 764 * the req_info->phy_index 765 */ 766 ret = ethnl_default_dump_one(skb, dev, ethnl_ctx, info); 767 if (ret) 768 return ret; 769 } 770 771 ctx->pos_phyindex = 0; 772 773 return 0; 774 } 775 776 static int ethnl_perphy_dump_all_dev(struct sk_buff *skb, 777 struct ethnl_perphy_dump_ctx *ctx, 778 const struct genl_info *info) 779 { 780 struct ethnl_dump_ctx *ethnl_ctx = &ctx->ethnl_ctx; 781 struct net *net = sock_net(skb->sk); 782 netdevice_tracker dev_tracker; 783 struct net_device *dev; 784 int ret = 0; 785 786 rcu_read_lock(); 787 for_each_netdev_dump(net, dev, ethnl_ctx->pos_ifindex) { 788 netdev_hold(dev, &dev_tracker, GFP_ATOMIC); 789 rcu_read_unlock(); 790 791 /* per-PHY commands use ethnl_req_get_phydev(), which needs the 792 * net_device in the req_info 793 */ 794 ethnl_ctx->req_info->dev = dev; 795 ret = ethnl_perphy_dump_one_dev(skb, ctx, info); 796 797 rcu_read_lock(); 798 netdev_put(dev, &dev_tracker); 799 ethnl_ctx->req_info->dev = NULL; 800 801 if (ret < 0 && ret != -EOPNOTSUPP) { 802 if (likely(skb->len)) 803 ret = skb->len; 804 break; 805 } 806 ret = 0; 807 } 808 rcu_read_unlock(); 809 810 return ret; 811 } 812 813 /* per-PHY ->dumpit() handler for GET requests. */ 814 static int ethnl_perphy_dumpit(struct sk_buff *skb, 815 struct netlink_callback *cb) 816 { 817 struct ethnl_perphy_dump_ctx *ctx = ethnl_perphy_dump_context(cb); 818 const struct genl_dumpit_info *info = genl_dumpit_info(cb); 819 struct ethnl_dump_ctx *ethnl_ctx = &ctx->ethnl_ctx; 820 int ret = 0; 821 822 if (ctx->ifindex) { 823 netdevice_tracker dev_tracker; 824 struct net_device *dev; 825 826 dev = netdev_get_by_index(genl_info_net(&info->info), 827 ctx->ifindex, &dev_tracker, 828 GFP_KERNEL); 829 if (!dev) 830 return -ENODEV; 831 832 ethnl_ctx->req_info->dev = dev; 833 ret = ethnl_perphy_dump_one_dev(skb, ctx, genl_info_dump(cb)); 834 835 if (ret < 0 && ret != -EOPNOTSUPP && likely(skb->len)) 836 ret = skb->len; 837 838 netdev_put(dev, &dev_tracker); 839 } else { 840 ret = ethnl_perphy_dump_all_dev(skb, ctx, genl_info_dump(cb)); 841 } 842 843 return ret; 844 } 845 846 /* per-PHY ->done() handler for GET requests */ 847 static int ethnl_perphy_done(struct netlink_callback *cb) 848 { 849 struct ethnl_perphy_dump_ctx *ctx = ethnl_perphy_dump_context(cb); 850 struct ethnl_dump_ctx *ethnl_ctx = &ctx->ethnl_ctx; 851 852 kfree(ethnl_ctx->reply_data); 853 kfree(ethnl_ctx->req_info); 854 855 return 0; 856 } 857 858 /* default ->done() handler for GET requests */ 859 static int ethnl_default_done(struct netlink_callback *cb) 860 { 861 struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb); 862 863 kfree(ctx->reply_data); 864 kfree(ctx->req_info); 865 866 return 0; 867 } 868 869 static int ethnl_default_set_doit(struct sk_buff *skb, struct genl_info *info) 870 { 871 const struct ethnl_request_ops *ops; 872 const u8 cmd = info->genlhdr->cmd; 873 struct ethnl_req_info *req_info; 874 struct net_device *dev; 875 int ret; 876 877 ops = ethnl_default_requests[cmd]; 878 if (WARN_ONCE(!ops, "cmd %u has no ethnl_request_ops\n", cmd)) 879 return -EOPNOTSUPP; 880 if (GENL_REQ_ATTR_CHECK(info, ops->hdr_attr)) 881 return -EINVAL; 882 883 req_info = kzalloc(ops->req_info_size, GFP_KERNEL); 884 if (!req_info) 885 return -ENOMEM; 886 887 ret = ethnl_default_parse(req_info, info, ops, true); 888 if (ret < 0) 889 goto out_free_req; 890 891 if (ops->set_validate) { 892 ret = ops->set_validate(req_info, info); 893 /* 0 means nothing to do */ 894 if (ret <= 0) 895 goto out_dev; 896 } 897 898 dev = req_info->dev; 899 900 rtnl_lock(); 901 netdev_lock_ops(dev); 902 dev->cfg_pending = kmemdup(dev->cfg, sizeof(*dev->cfg), 903 GFP_KERNEL_ACCOUNT); 904 if (!dev->cfg_pending) { 905 ret = -ENOMEM; 906 goto out_tie_cfg; 907 } 908 909 ret = ethnl_ops_begin(dev); 910 if (ret < 0) 911 goto out_free_cfg; 912 913 ret = ops->set(req_info, info); 914 if (ret < 0) 915 goto out_ops; 916 917 swap(dev->cfg, dev->cfg_pending); 918 if (!ret) 919 goto out_ops; 920 ethnl_notify(dev, ops->set_ntf_cmd, req_info); 921 922 ret = 0; 923 out_ops: 924 ethnl_ops_complete(dev); 925 out_free_cfg: 926 kfree(dev->cfg_pending); 927 out_tie_cfg: 928 dev->cfg_pending = dev->cfg; 929 netdev_unlock_ops(dev); 930 rtnl_unlock(); 931 out_dev: 932 ethnl_parse_header_dev_put(req_info); 933 out_free_req: 934 kfree(req_info); 935 return ret; 936 } 937 938 static const struct ethnl_request_ops * 939 ethnl_default_notify_ops[ETHTOOL_MSG_KERNEL_MAX + 1] = { 940 [ETHTOOL_MSG_LINKINFO_NTF] = ðnl_linkinfo_request_ops, 941 [ETHTOOL_MSG_LINKMODES_NTF] = ðnl_linkmodes_request_ops, 942 [ETHTOOL_MSG_DEBUG_NTF] = ðnl_debug_request_ops, 943 [ETHTOOL_MSG_WOL_NTF] = ðnl_wol_request_ops, 944 [ETHTOOL_MSG_FEATURES_NTF] = ðnl_features_request_ops, 945 [ETHTOOL_MSG_PRIVFLAGS_NTF] = ðnl_privflags_request_ops, 946 [ETHTOOL_MSG_RINGS_NTF] = ðnl_rings_request_ops, 947 [ETHTOOL_MSG_CHANNELS_NTF] = ðnl_channels_request_ops, 948 [ETHTOOL_MSG_COALESCE_NTF] = ðnl_coalesce_request_ops, 949 [ETHTOOL_MSG_PAUSE_NTF] = ðnl_pause_request_ops, 950 [ETHTOOL_MSG_EEE_NTF] = ðnl_eee_request_ops, 951 [ETHTOOL_MSG_FEC_NTF] = ðnl_fec_request_ops, 952 [ETHTOOL_MSG_MODULE_NTF] = ðnl_module_request_ops, 953 [ETHTOOL_MSG_PLCA_NTF] = ðnl_plca_cfg_request_ops, 954 [ETHTOOL_MSG_MM_NTF] = ðnl_mm_request_ops, 955 [ETHTOOL_MSG_RSS_NTF] = ðnl_rss_request_ops, 956 }; 957 958 /* default notification handler */ 959 static void ethnl_default_notify(struct net_device *dev, unsigned int cmd, 960 const struct ethnl_req_info *orig_req_info) 961 { 962 struct ethnl_reply_data *reply_data; 963 const struct ethnl_request_ops *ops; 964 struct ethnl_req_info *req_info; 965 struct genl_info info; 966 struct sk_buff *skb; 967 void *reply_payload; 968 int reply_len; 969 int ret; 970 971 genl_info_init_ntf(&info, ðtool_genl_family, cmd); 972 973 if (WARN_ONCE(cmd > ETHTOOL_MSG_KERNEL_MAX || 974 !ethnl_default_notify_ops[cmd], 975 "unexpected notification type %u\n", cmd)) 976 return; 977 ops = ethnl_default_notify_ops[cmd]; 978 req_info = kzalloc(ops->req_info_size, GFP_KERNEL); 979 if (!req_info) 980 return; 981 reply_data = kmalloc(ops->reply_data_size, GFP_KERNEL); 982 if (!reply_data) { 983 kfree(req_info); 984 return; 985 } 986 987 req_info->dev = dev; 988 req_info->flags |= ETHTOOL_FLAG_COMPACT_BITSETS; 989 if (orig_req_info) { 990 req_info->phy_index = orig_req_info->phy_index; 991 memcpy(&req_info[1], &orig_req_info[1], 992 ops->req_info_size - sizeof(*req_info)); 993 } 994 995 netdev_ops_assert_locked(dev); 996 997 ethnl_init_reply_data(reply_data, ops, dev); 998 ret = ops->prepare_data(req_info, reply_data, &info); 999 if (ret < 0) 1000 goto err_rep; 1001 ret = ops->reply_size(req_info, reply_data); 1002 if (ret < 0) 1003 goto err_cleanup; 1004 reply_len = ret + ethnl_reply_header_size(); 1005 skb = genlmsg_new(reply_len, GFP_KERNEL); 1006 if (!skb) 1007 goto err_cleanup; 1008 reply_payload = ethnl_bcastmsg_put(skb, cmd); 1009 if (!reply_payload) 1010 goto err_skb; 1011 ret = ethnl_fill_reply_header(skb, dev, ops->hdr_attr); 1012 if (ret < 0) 1013 goto err_msg; 1014 ret = ops->fill_reply(skb, req_info, reply_data); 1015 if (ret < 0) 1016 goto err_msg; 1017 if (ops->cleanup_data) 1018 ops->cleanup_data(reply_data); 1019 1020 genlmsg_end(skb, reply_payload); 1021 kfree(reply_data); 1022 kfree(req_info); 1023 ethnl_multicast(skb, dev); 1024 return; 1025 1026 err_msg: 1027 WARN_ONCE(ret == -EMSGSIZE, 1028 "calculated message payload length (%d) not sufficient\n", 1029 reply_len); 1030 err_skb: 1031 nlmsg_free(skb); 1032 err_cleanup: 1033 if (ops->cleanup_data) 1034 ops->cleanup_data(reply_data); 1035 err_rep: 1036 kfree(reply_data); 1037 kfree(req_info); 1038 return; 1039 } 1040 1041 /* notifications */ 1042 1043 typedef void (*ethnl_notify_handler_t)(struct net_device *dev, unsigned int cmd, 1044 const struct ethnl_req_info *req_info); 1045 1046 static const ethnl_notify_handler_t ethnl_notify_handlers[] = { 1047 [ETHTOOL_MSG_LINKINFO_NTF] = ethnl_default_notify, 1048 [ETHTOOL_MSG_LINKMODES_NTF] = ethnl_default_notify, 1049 [ETHTOOL_MSG_DEBUG_NTF] = ethnl_default_notify, 1050 [ETHTOOL_MSG_WOL_NTF] = ethnl_default_notify, 1051 [ETHTOOL_MSG_FEATURES_NTF] = ethnl_default_notify, 1052 [ETHTOOL_MSG_PRIVFLAGS_NTF] = ethnl_default_notify, 1053 [ETHTOOL_MSG_RINGS_NTF] = ethnl_default_notify, 1054 [ETHTOOL_MSG_CHANNELS_NTF] = ethnl_default_notify, 1055 [ETHTOOL_MSG_COALESCE_NTF] = ethnl_default_notify, 1056 [ETHTOOL_MSG_PAUSE_NTF] = ethnl_default_notify, 1057 [ETHTOOL_MSG_EEE_NTF] = ethnl_default_notify, 1058 [ETHTOOL_MSG_FEC_NTF] = ethnl_default_notify, 1059 [ETHTOOL_MSG_MODULE_NTF] = ethnl_default_notify, 1060 [ETHTOOL_MSG_PLCA_NTF] = ethnl_default_notify, 1061 [ETHTOOL_MSG_MM_NTF] = ethnl_default_notify, 1062 [ETHTOOL_MSG_RSS_NTF] = ethnl_default_notify, 1063 }; 1064 1065 void ethnl_notify(struct net_device *dev, unsigned int cmd, 1066 const struct ethnl_req_info *req_info) 1067 { 1068 if (unlikely(!ethnl_ok)) 1069 return; 1070 ASSERT_RTNL(); 1071 1072 if (likely(cmd < ARRAY_SIZE(ethnl_notify_handlers) && 1073 ethnl_notify_handlers[cmd])) 1074 ethnl_notify_handlers[cmd](dev, cmd, req_info); 1075 else 1076 WARN_ONCE(1, "notification %u not implemented (dev=%s)\n", 1077 cmd, netdev_name(dev)); 1078 } 1079 1080 void ethtool_notify(struct net_device *dev, unsigned int cmd) 1081 { 1082 ethnl_notify(dev, cmd, NULL); 1083 } 1084 EXPORT_SYMBOL(ethtool_notify); 1085 1086 static void ethnl_notify_features(struct netdev_notifier_info *info) 1087 { 1088 struct net_device *dev = netdev_notifier_info_to_dev(info); 1089 1090 ethtool_notify(dev, ETHTOOL_MSG_FEATURES_NTF); 1091 } 1092 1093 static int ethnl_netdev_event(struct notifier_block *this, unsigned long event, 1094 void *ptr) 1095 { 1096 struct netdev_notifier_info *info = ptr; 1097 struct netlink_ext_ack *extack; 1098 struct net_device *dev; 1099 1100 dev = netdev_notifier_info_to_dev(info); 1101 extack = netdev_notifier_info_to_extack(info); 1102 1103 switch (event) { 1104 case NETDEV_FEAT_CHANGE: 1105 ethnl_notify_features(ptr); 1106 break; 1107 case NETDEV_PRE_UP: 1108 if (dev->ethtool->module_fw_flash_in_progress) { 1109 NL_SET_ERR_MSG(extack, "Can't set port up while flashing module firmware"); 1110 return NOTIFY_BAD; 1111 } 1112 } 1113 1114 return NOTIFY_DONE; 1115 } 1116 1117 static struct notifier_block ethnl_netdev_notifier = { 1118 .notifier_call = ethnl_netdev_event, 1119 }; 1120 1121 /* genetlink setup */ 1122 1123 static const struct genl_ops ethtool_genl_ops[] = { 1124 { 1125 .cmd = ETHTOOL_MSG_STRSET_GET, 1126 .doit = ethnl_default_doit, 1127 .start = ethnl_default_start, 1128 .dumpit = ethnl_default_dumpit, 1129 .done = ethnl_default_done, 1130 .policy = ethnl_strset_get_policy, 1131 .maxattr = ARRAY_SIZE(ethnl_strset_get_policy) - 1, 1132 }, 1133 { 1134 .cmd = ETHTOOL_MSG_LINKINFO_GET, 1135 .doit = ethnl_default_doit, 1136 .start = ethnl_default_start, 1137 .dumpit = ethnl_default_dumpit, 1138 .done = ethnl_default_done, 1139 .policy = ethnl_linkinfo_get_policy, 1140 .maxattr = ARRAY_SIZE(ethnl_linkinfo_get_policy) - 1, 1141 }, 1142 { 1143 .cmd = ETHTOOL_MSG_LINKINFO_SET, 1144 .flags = GENL_UNS_ADMIN_PERM, 1145 .doit = ethnl_default_set_doit, 1146 .policy = ethnl_linkinfo_set_policy, 1147 .maxattr = ARRAY_SIZE(ethnl_linkinfo_set_policy) - 1, 1148 }, 1149 { 1150 .cmd = ETHTOOL_MSG_LINKMODES_GET, 1151 .doit = ethnl_default_doit, 1152 .start = ethnl_default_start, 1153 .dumpit = ethnl_default_dumpit, 1154 .done = ethnl_default_done, 1155 .policy = ethnl_linkmodes_get_policy, 1156 .maxattr = ARRAY_SIZE(ethnl_linkmodes_get_policy) - 1, 1157 }, 1158 { 1159 .cmd = ETHTOOL_MSG_LINKMODES_SET, 1160 .flags = GENL_UNS_ADMIN_PERM, 1161 .doit = ethnl_default_set_doit, 1162 .policy = ethnl_linkmodes_set_policy, 1163 .maxattr = ARRAY_SIZE(ethnl_linkmodes_set_policy) - 1, 1164 }, 1165 { 1166 .cmd = ETHTOOL_MSG_LINKSTATE_GET, 1167 .doit = ethnl_default_doit, 1168 .start = ethnl_default_start, 1169 .dumpit = ethnl_default_dumpit, 1170 .done = ethnl_default_done, 1171 .policy = ethnl_linkstate_get_policy, 1172 .maxattr = ARRAY_SIZE(ethnl_linkstate_get_policy) - 1, 1173 }, 1174 { 1175 .cmd = ETHTOOL_MSG_DEBUG_GET, 1176 .doit = ethnl_default_doit, 1177 .start = ethnl_default_start, 1178 .dumpit = ethnl_default_dumpit, 1179 .done = ethnl_default_done, 1180 .policy = ethnl_debug_get_policy, 1181 .maxattr = ARRAY_SIZE(ethnl_debug_get_policy) - 1, 1182 }, 1183 { 1184 .cmd = ETHTOOL_MSG_DEBUG_SET, 1185 .flags = GENL_UNS_ADMIN_PERM, 1186 .doit = ethnl_default_set_doit, 1187 .policy = ethnl_debug_set_policy, 1188 .maxattr = ARRAY_SIZE(ethnl_debug_set_policy) - 1, 1189 }, 1190 { 1191 .cmd = ETHTOOL_MSG_WOL_GET, 1192 .flags = GENL_UNS_ADMIN_PERM, 1193 .doit = ethnl_default_doit, 1194 .start = ethnl_default_start, 1195 .dumpit = ethnl_default_dumpit, 1196 .done = ethnl_default_done, 1197 .policy = ethnl_wol_get_policy, 1198 .maxattr = ARRAY_SIZE(ethnl_wol_get_policy) - 1, 1199 }, 1200 { 1201 .cmd = ETHTOOL_MSG_WOL_SET, 1202 .flags = GENL_UNS_ADMIN_PERM, 1203 .doit = ethnl_default_set_doit, 1204 .policy = ethnl_wol_set_policy, 1205 .maxattr = ARRAY_SIZE(ethnl_wol_set_policy) - 1, 1206 }, 1207 { 1208 .cmd = ETHTOOL_MSG_FEATURES_GET, 1209 .doit = ethnl_default_doit, 1210 .start = ethnl_default_start, 1211 .dumpit = ethnl_default_dumpit, 1212 .done = ethnl_default_done, 1213 .policy = ethnl_features_get_policy, 1214 .maxattr = ARRAY_SIZE(ethnl_features_get_policy) - 1, 1215 }, 1216 { 1217 .cmd = ETHTOOL_MSG_FEATURES_SET, 1218 .flags = GENL_UNS_ADMIN_PERM, 1219 .doit = ethnl_set_features, 1220 .policy = ethnl_features_set_policy, 1221 .maxattr = ARRAY_SIZE(ethnl_features_set_policy) - 1, 1222 }, 1223 { 1224 .cmd = ETHTOOL_MSG_PRIVFLAGS_GET, 1225 .doit = ethnl_default_doit, 1226 .start = ethnl_default_start, 1227 .dumpit = ethnl_default_dumpit, 1228 .done = ethnl_default_done, 1229 .policy = ethnl_privflags_get_policy, 1230 .maxattr = ARRAY_SIZE(ethnl_privflags_get_policy) - 1, 1231 }, 1232 { 1233 .cmd = ETHTOOL_MSG_PRIVFLAGS_SET, 1234 .flags = GENL_UNS_ADMIN_PERM, 1235 .doit = ethnl_default_set_doit, 1236 .policy = ethnl_privflags_set_policy, 1237 .maxattr = ARRAY_SIZE(ethnl_privflags_set_policy) - 1, 1238 }, 1239 { 1240 .cmd = ETHTOOL_MSG_RINGS_GET, 1241 .doit = ethnl_default_doit, 1242 .start = ethnl_default_start, 1243 .dumpit = ethnl_default_dumpit, 1244 .done = ethnl_default_done, 1245 .policy = ethnl_rings_get_policy, 1246 .maxattr = ARRAY_SIZE(ethnl_rings_get_policy) - 1, 1247 }, 1248 { 1249 .cmd = ETHTOOL_MSG_RINGS_SET, 1250 .flags = GENL_UNS_ADMIN_PERM, 1251 .doit = ethnl_default_set_doit, 1252 .policy = ethnl_rings_set_policy, 1253 .maxattr = ARRAY_SIZE(ethnl_rings_set_policy) - 1, 1254 }, 1255 { 1256 .cmd = ETHTOOL_MSG_CHANNELS_GET, 1257 .doit = ethnl_default_doit, 1258 .start = ethnl_default_start, 1259 .dumpit = ethnl_default_dumpit, 1260 .done = ethnl_default_done, 1261 .policy = ethnl_channels_get_policy, 1262 .maxattr = ARRAY_SIZE(ethnl_channels_get_policy) - 1, 1263 }, 1264 { 1265 .cmd = ETHTOOL_MSG_CHANNELS_SET, 1266 .flags = GENL_UNS_ADMIN_PERM, 1267 .doit = ethnl_default_set_doit, 1268 .policy = ethnl_channels_set_policy, 1269 .maxattr = ARRAY_SIZE(ethnl_channels_set_policy) - 1, 1270 }, 1271 { 1272 .cmd = ETHTOOL_MSG_COALESCE_GET, 1273 .doit = ethnl_default_doit, 1274 .start = ethnl_default_start, 1275 .dumpit = ethnl_default_dumpit, 1276 .done = ethnl_default_done, 1277 .policy = ethnl_coalesce_get_policy, 1278 .maxattr = ARRAY_SIZE(ethnl_coalesce_get_policy) - 1, 1279 }, 1280 { 1281 .cmd = ETHTOOL_MSG_COALESCE_SET, 1282 .flags = GENL_UNS_ADMIN_PERM, 1283 .doit = ethnl_default_set_doit, 1284 .policy = ethnl_coalesce_set_policy, 1285 .maxattr = ARRAY_SIZE(ethnl_coalesce_set_policy) - 1, 1286 }, 1287 { 1288 .cmd = ETHTOOL_MSG_PAUSE_GET, 1289 .doit = ethnl_default_doit, 1290 .start = ethnl_default_start, 1291 .dumpit = ethnl_default_dumpit, 1292 .done = ethnl_default_done, 1293 .policy = ethnl_pause_get_policy, 1294 .maxattr = ARRAY_SIZE(ethnl_pause_get_policy) - 1, 1295 }, 1296 { 1297 .cmd = ETHTOOL_MSG_PAUSE_SET, 1298 .flags = GENL_UNS_ADMIN_PERM, 1299 .doit = ethnl_default_set_doit, 1300 .policy = ethnl_pause_set_policy, 1301 .maxattr = ARRAY_SIZE(ethnl_pause_set_policy) - 1, 1302 }, 1303 { 1304 .cmd = ETHTOOL_MSG_EEE_GET, 1305 .doit = ethnl_default_doit, 1306 .start = ethnl_default_start, 1307 .dumpit = ethnl_default_dumpit, 1308 .done = ethnl_default_done, 1309 .policy = ethnl_eee_get_policy, 1310 .maxattr = ARRAY_SIZE(ethnl_eee_get_policy) - 1, 1311 }, 1312 { 1313 .cmd = ETHTOOL_MSG_EEE_SET, 1314 .flags = GENL_UNS_ADMIN_PERM, 1315 .doit = ethnl_default_set_doit, 1316 .policy = ethnl_eee_set_policy, 1317 .maxattr = ARRAY_SIZE(ethnl_eee_set_policy) - 1, 1318 }, 1319 { 1320 .cmd = ETHTOOL_MSG_TSINFO_GET, 1321 .doit = ethnl_default_doit, 1322 .start = ethnl_tsinfo_start, 1323 .dumpit = ethnl_tsinfo_dumpit, 1324 .done = ethnl_tsinfo_done, 1325 .policy = ethnl_tsinfo_get_policy, 1326 .maxattr = ARRAY_SIZE(ethnl_tsinfo_get_policy) - 1, 1327 }, 1328 { 1329 .cmd = ETHTOOL_MSG_CABLE_TEST_ACT, 1330 .flags = GENL_UNS_ADMIN_PERM, 1331 .doit = ethnl_act_cable_test, 1332 .policy = ethnl_cable_test_act_policy, 1333 .maxattr = ARRAY_SIZE(ethnl_cable_test_act_policy) - 1, 1334 }, 1335 { 1336 .cmd = ETHTOOL_MSG_CABLE_TEST_TDR_ACT, 1337 .flags = GENL_UNS_ADMIN_PERM, 1338 .doit = ethnl_act_cable_test_tdr, 1339 .policy = ethnl_cable_test_tdr_act_policy, 1340 .maxattr = ARRAY_SIZE(ethnl_cable_test_tdr_act_policy) - 1, 1341 }, 1342 { 1343 .cmd = ETHTOOL_MSG_TUNNEL_INFO_GET, 1344 .doit = ethnl_tunnel_info_doit, 1345 .start = ethnl_tunnel_info_start, 1346 .dumpit = ethnl_tunnel_info_dumpit, 1347 .policy = ethnl_tunnel_info_get_policy, 1348 .maxattr = ARRAY_SIZE(ethnl_tunnel_info_get_policy) - 1, 1349 }, 1350 { 1351 .cmd = ETHTOOL_MSG_FEC_GET, 1352 .doit = ethnl_default_doit, 1353 .start = ethnl_default_start, 1354 .dumpit = ethnl_default_dumpit, 1355 .done = ethnl_default_done, 1356 .policy = ethnl_fec_get_policy, 1357 .maxattr = ARRAY_SIZE(ethnl_fec_get_policy) - 1, 1358 }, 1359 { 1360 .cmd = ETHTOOL_MSG_FEC_SET, 1361 .flags = GENL_UNS_ADMIN_PERM, 1362 .doit = ethnl_default_set_doit, 1363 .policy = ethnl_fec_set_policy, 1364 .maxattr = ARRAY_SIZE(ethnl_fec_set_policy) - 1, 1365 }, 1366 { 1367 .cmd = ETHTOOL_MSG_MODULE_EEPROM_GET, 1368 .flags = GENL_UNS_ADMIN_PERM, 1369 .doit = ethnl_default_doit, 1370 .start = ethnl_default_start, 1371 .dumpit = ethnl_default_dumpit, 1372 .done = ethnl_default_done, 1373 .policy = ethnl_module_eeprom_get_policy, 1374 .maxattr = ARRAY_SIZE(ethnl_module_eeprom_get_policy) - 1, 1375 }, 1376 { 1377 .cmd = ETHTOOL_MSG_STATS_GET, 1378 .doit = ethnl_default_doit, 1379 .start = ethnl_default_start, 1380 .dumpit = ethnl_default_dumpit, 1381 .done = ethnl_default_done, 1382 .policy = ethnl_stats_get_policy, 1383 .maxattr = ARRAY_SIZE(ethnl_stats_get_policy) - 1, 1384 }, 1385 { 1386 .cmd = ETHTOOL_MSG_PHC_VCLOCKS_GET, 1387 .doit = ethnl_default_doit, 1388 .start = ethnl_default_start, 1389 .dumpit = ethnl_default_dumpit, 1390 .done = ethnl_default_done, 1391 .policy = ethnl_phc_vclocks_get_policy, 1392 .maxattr = ARRAY_SIZE(ethnl_phc_vclocks_get_policy) - 1, 1393 }, 1394 { 1395 .cmd = ETHTOOL_MSG_MODULE_GET, 1396 .doit = ethnl_default_doit, 1397 .start = ethnl_default_start, 1398 .dumpit = ethnl_default_dumpit, 1399 .done = ethnl_default_done, 1400 .policy = ethnl_module_get_policy, 1401 .maxattr = ARRAY_SIZE(ethnl_module_get_policy) - 1, 1402 }, 1403 { 1404 .cmd = ETHTOOL_MSG_MODULE_SET, 1405 .flags = GENL_UNS_ADMIN_PERM, 1406 .doit = ethnl_default_set_doit, 1407 .policy = ethnl_module_set_policy, 1408 .maxattr = ARRAY_SIZE(ethnl_module_set_policy) - 1, 1409 }, 1410 { 1411 .cmd = ETHTOOL_MSG_PSE_GET, 1412 .doit = ethnl_default_doit, 1413 .start = ethnl_perphy_start, 1414 .dumpit = ethnl_perphy_dumpit, 1415 .done = ethnl_perphy_done, 1416 .policy = ethnl_pse_get_policy, 1417 .maxattr = ARRAY_SIZE(ethnl_pse_get_policy) - 1, 1418 }, 1419 { 1420 .cmd = ETHTOOL_MSG_PSE_SET, 1421 .flags = GENL_UNS_ADMIN_PERM, 1422 .doit = ethnl_default_set_doit, 1423 .policy = ethnl_pse_set_policy, 1424 .maxattr = ARRAY_SIZE(ethnl_pse_set_policy) - 1, 1425 }, 1426 { 1427 .cmd = ETHTOOL_MSG_RSS_GET, 1428 .doit = ethnl_default_doit, 1429 .start = ethnl_rss_dump_start, 1430 .dumpit = ethnl_rss_dumpit, 1431 .policy = ethnl_rss_get_policy, 1432 .maxattr = ARRAY_SIZE(ethnl_rss_get_policy) - 1, 1433 }, 1434 { 1435 .cmd = ETHTOOL_MSG_PLCA_GET_CFG, 1436 .doit = ethnl_default_doit, 1437 .start = ethnl_perphy_start, 1438 .dumpit = ethnl_perphy_dumpit, 1439 .done = ethnl_perphy_done, 1440 .policy = ethnl_plca_get_cfg_policy, 1441 .maxattr = ARRAY_SIZE(ethnl_plca_get_cfg_policy) - 1, 1442 }, 1443 { 1444 .cmd = ETHTOOL_MSG_PLCA_SET_CFG, 1445 .flags = GENL_UNS_ADMIN_PERM, 1446 .doit = ethnl_default_set_doit, 1447 .policy = ethnl_plca_set_cfg_policy, 1448 .maxattr = ARRAY_SIZE(ethnl_plca_set_cfg_policy) - 1, 1449 }, 1450 { 1451 .cmd = ETHTOOL_MSG_PLCA_GET_STATUS, 1452 .doit = ethnl_default_doit, 1453 .start = ethnl_perphy_start, 1454 .dumpit = ethnl_perphy_dumpit, 1455 .done = ethnl_perphy_done, 1456 .policy = ethnl_plca_get_status_policy, 1457 .maxattr = ARRAY_SIZE(ethnl_plca_get_status_policy) - 1, 1458 }, 1459 { 1460 .cmd = ETHTOOL_MSG_MM_GET, 1461 .doit = ethnl_default_doit, 1462 .start = ethnl_default_start, 1463 .dumpit = ethnl_default_dumpit, 1464 .done = ethnl_default_done, 1465 .policy = ethnl_mm_get_policy, 1466 .maxattr = ARRAY_SIZE(ethnl_mm_get_policy) - 1, 1467 }, 1468 { 1469 .cmd = ETHTOOL_MSG_MM_SET, 1470 .flags = GENL_UNS_ADMIN_PERM, 1471 .doit = ethnl_default_set_doit, 1472 .policy = ethnl_mm_set_policy, 1473 .maxattr = ARRAY_SIZE(ethnl_mm_set_policy) - 1, 1474 }, 1475 { 1476 .cmd = ETHTOOL_MSG_MODULE_FW_FLASH_ACT, 1477 .flags = GENL_UNS_ADMIN_PERM, 1478 .doit = ethnl_act_module_fw_flash, 1479 .policy = ethnl_module_fw_flash_act_policy, 1480 .maxattr = ARRAY_SIZE(ethnl_module_fw_flash_act_policy) - 1, 1481 }, 1482 { 1483 .cmd = ETHTOOL_MSG_PHY_GET, 1484 .doit = ethnl_default_doit, 1485 .start = ethnl_perphy_start, 1486 .dumpit = ethnl_perphy_dumpit, 1487 .done = ethnl_perphy_done, 1488 .policy = ethnl_phy_get_policy, 1489 .maxattr = ARRAY_SIZE(ethnl_phy_get_policy) - 1, 1490 }, 1491 { 1492 .cmd = ETHTOOL_MSG_TSCONFIG_GET, 1493 .doit = ethnl_default_doit, 1494 .start = ethnl_default_start, 1495 .dumpit = ethnl_default_dumpit, 1496 .done = ethnl_default_done, 1497 .policy = ethnl_tsconfig_get_policy, 1498 .maxattr = ARRAY_SIZE(ethnl_tsconfig_get_policy) - 1, 1499 }, 1500 { 1501 .cmd = ETHTOOL_MSG_TSCONFIG_SET, 1502 .flags = GENL_UNS_ADMIN_PERM, 1503 .doit = ethnl_default_set_doit, 1504 .policy = ethnl_tsconfig_set_policy, 1505 .maxattr = ARRAY_SIZE(ethnl_tsconfig_set_policy) - 1, 1506 }, 1507 }; 1508 1509 static const struct genl_multicast_group ethtool_nl_mcgrps[] = { 1510 [ETHNL_MCGRP_MONITOR] = { .name = ETHTOOL_MCGRP_MONITOR_NAME }, 1511 }; 1512 1513 static struct genl_family ethtool_genl_family __ro_after_init = { 1514 .name = ETHTOOL_GENL_NAME, 1515 .version = ETHTOOL_GENL_VERSION, 1516 .netnsok = true, 1517 .parallel_ops = true, 1518 .ops = ethtool_genl_ops, 1519 .n_ops = ARRAY_SIZE(ethtool_genl_ops), 1520 .resv_start_op = ETHTOOL_MSG_MODULE_GET + 1, 1521 .mcgrps = ethtool_nl_mcgrps, 1522 .n_mcgrps = ARRAY_SIZE(ethtool_nl_mcgrps), 1523 .sock_priv_size = sizeof(struct ethnl_sock_priv), 1524 .sock_priv_destroy = ethnl_sock_priv_destroy, 1525 }; 1526 1527 /* module setup */ 1528 1529 static int __init ethnl_init(void) 1530 { 1531 int ret; 1532 1533 ret = genl_register_family(ðtool_genl_family); 1534 if (WARN(ret < 0, "ethtool: genetlink family registration failed")) 1535 return ret; 1536 ethnl_ok = true; 1537 1538 ret = register_netdevice_notifier(ðnl_netdev_notifier); 1539 WARN(ret < 0, "ethtool: net device notifier registration failed"); 1540 return ret; 1541 } 1542 1543 subsys_initcall(ethnl_init); 1544