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