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