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