at v2.6.32-rc1 1154 lines 27 kB view raw
1/* 2 * net/core/ethtool.c - Ethtool ioctl handler 3 * Copyright (c) 2003 Matthew Wilcox <matthew@wil.cx> 4 * 5 * This file is where we call all the ethtool_ops commands to get 6 * the information ethtool needs. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 */ 13 14#include <linux/module.h> 15#include <linux/types.h> 16#include <linux/capability.h> 17#include <linux/errno.h> 18#include <linux/ethtool.h> 19#include <linux/netdevice.h> 20#include <asm/uaccess.h> 21 22/* 23 * Some useful ethtool_ops methods that're device independent. 24 * If we find that all drivers want to do the same thing here, 25 * we can turn these into dev_() function calls. 26 */ 27 28u32 ethtool_op_get_link(struct net_device *dev) 29{ 30 return netif_carrier_ok(dev) ? 1 : 0; 31} 32 33u32 ethtool_op_get_rx_csum(struct net_device *dev) 34{ 35 return (dev->features & NETIF_F_ALL_CSUM) != 0; 36} 37EXPORT_SYMBOL(ethtool_op_get_rx_csum); 38 39u32 ethtool_op_get_tx_csum(struct net_device *dev) 40{ 41 return (dev->features & NETIF_F_ALL_CSUM) != 0; 42} 43EXPORT_SYMBOL(ethtool_op_get_tx_csum); 44 45int ethtool_op_set_tx_csum(struct net_device *dev, u32 data) 46{ 47 if (data) 48 dev->features |= NETIF_F_IP_CSUM; 49 else 50 dev->features &= ~NETIF_F_IP_CSUM; 51 52 return 0; 53} 54 55int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data) 56{ 57 if (data) 58 dev->features |= NETIF_F_HW_CSUM; 59 else 60 dev->features &= ~NETIF_F_HW_CSUM; 61 62 return 0; 63} 64 65int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data) 66{ 67 if (data) 68 dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; 69 else 70 dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); 71 72 return 0; 73} 74 75u32 ethtool_op_get_sg(struct net_device *dev) 76{ 77 return (dev->features & NETIF_F_SG) != 0; 78} 79 80int ethtool_op_set_sg(struct net_device *dev, u32 data) 81{ 82 if (data) 83 dev->features |= NETIF_F_SG; 84 else 85 dev->features &= ~NETIF_F_SG; 86 87 return 0; 88} 89 90u32 ethtool_op_get_tso(struct net_device *dev) 91{ 92 return (dev->features & NETIF_F_TSO) != 0; 93} 94 95int ethtool_op_set_tso(struct net_device *dev, u32 data) 96{ 97 if (data) 98 dev->features |= NETIF_F_TSO; 99 else 100 dev->features &= ~NETIF_F_TSO; 101 102 return 0; 103} 104 105u32 ethtool_op_get_ufo(struct net_device *dev) 106{ 107 return (dev->features & NETIF_F_UFO) != 0; 108} 109 110int ethtool_op_set_ufo(struct net_device *dev, u32 data) 111{ 112 if (data) 113 dev->features |= NETIF_F_UFO; 114 else 115 dev->features &= ~NETIF_F_UFO; 116 return 0; 117} 118 119/* the following list of flags are the same as their associated 120 * NETIF_F_xxx values in include/linux/netdevice.h 121 */ 122static const u32 flags_dup_features = 123 ETH_FLAG_LRO; 124 125u32 ethtool_op_get_flags(struct net_device *dev) 126{ 127 /* in the future, this function will probably contain additional 128 * handling for flags which are not so easily handled 129 * by a simple masking operation 130 */ 131 132 return dev->features & flags_dup_features; 133} 134 135int ethtool_op_set_flags(struct net_device *dev, u32 data) 136{ 137 if (data & ETH_FLAG_LRO) 138 dev->features |= NETIF_F_LRO; 139 else 140 dev->features &= ~NETIF_F_LRO; 141 142 return 0; 143} 144 145/* Handlers for each ethtool command */ 146 147static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) 148{ 149 struct ethtool_cmd cmd = { ETHTOOL_GSET }; 150 int err; 151 152 if (!dev->ethtool_ops->get_settings) 153 return -EOPNOTSUPP; 154 155 err = dev->ethtool_ops->get_settings(dev, &cmd); 156 if (err < 0) 157 return err; 158 159 if (copy_to_user(useraddr, &cmd, sizeof(cmd))) 160 return -EFAULT; 161 return 0; 162} 163 164static int ethtool_set_settings(struct net_device *dev, void __user *useraddr) 165{ 166 struct ethtool_cmd cmd; 167 168 if (!dev->ethtool_ops->set_settings) 169 return -EOPNOTSUPP; 170 171 if (copy_from_user(&cmd, useraddr, sizeof(cmd))) 172 return -EFAULT; 173 174 return dev->ethtool_ops->set_settings(dev, &cmd); 175} 176 177static int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr) 178{ 179 struct ethtool_drvinfo info; 180 const struct ethtool_ops *ops = dev->ethtool_ops; 181 182 if (!ops->get_drvinfo) 183 return -EOPNOTSUPP; 184 185 memset(&info, 0, sizeof(info)); 186 info.cmd = ETHTOOL_GDRVINFO; 187 ops->get_drvinfo(dev, &info); 188 189 if (ops->get_sset_count) { 190 int rc; 191 192 rc = ops->get_sset_count(dev, ETH_SS_TEST); 193 if (rc >= 0) 194 info.testinfo_len = rc; 195 rc = ops->get_sset_count(dev, ETH_SS_STATS); 196 if (rc >= 0) 197 info.n_stats = rc; 198 rc = ops->get_sset_count(dev, ETH_SS_PRIV_FLAGS); 199 if (rc >= 0) 200 info.n_priv_flags = rc; 201 } else { 202 /* code path for obsolete hooks */ 203 204 if (ops->self_test_count) 205 info.testinfo_len = ops->self_test_count(dev); 206 if (ops->get_stats_count) 207 info.n_stats = ops->get_stats_count(dev); 208 } 209 if (ops->get_regs_len) 210 info.regdump_len = ops->get_regs_len(dev); 211 if (ops->get_eeprom_len) 212 info.eedump_len = ops->get_eeprom_len(dev); 213 214 if (copy_to_user(useraddr, &info, sizeof(info))) 215 return -EFAULT; 216 return 0; 217} 218 219static int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr) 220{ 221 struct ethtool_rxnfc cmd; 222 223 if (!dev->ethtool_ops->set_rxnfc) 224 return -EOPNOTSUPP; 225 226 if (copy_from_user(&cmd, useraddr, sizeof(cmd))) 227 return -EFAULT; 228 229 return dev->ethtool_ops->set_rxnfc(dev, &cmd); 230} 231 232static int ethtool_get_rxnfc(struct net_device *dev, void __user *useraddr) 233{ 234 struct ethtool_rxnfc info; 235 const struct ethtool_ops *ops = dev->ethtool_ops; 236 int ret; 237 void *rule_buf = NULL; 238 239 if (!ops->get_rxnfc) 240 return -EOPNOTSUPP; 241 242 if (copy_from_user(&info, useraddr, sizeof(info))) 243 return -EFAULT; 244 245 if (info.cmd == ETHTOOL_GRXCLSRLALL) { 246 if (info.rule_cnt > 0) { 247 rule_buf = kmalloc(info.rule_cnt * sizeof(u32), 248 GFP_USER); 249 if (!rule_buf) 250 return -ENOMEM; 251 } 252 } 253 254 ret = ops->get_rxnfc(dev, &info, rule_buf); 255 if (ret < 0) 256 goto err_out; 257 258 ret = -EFAULT; 259 if (copy_to_user(useraddr, &info, sizeof(info))) 260 goto err_out; 261 262 if (rule_buf) { 263 useraddr += offsetof(struct ethtool_rxnfc, rule_locs); 264 if (copy_to_user(useraddr, rule_buf, 265 info.rule_cnt * sizeof(u32))) 266 goto err_out; 267 } 268 ret = 0; 269 270err_out: 271 kfree(rule_buf); 272 273 return ret; 274} 275 276static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) 277{ 278 struct ethtool_regs regs; 279 const struct ethtool_ops *ops = dev->ethtool_ops; 280 void *regbuf; 281 int reglen, ret; 282 283 if (!ops->get_regs || !ops->get_regs_len) 284 return -EOPNOTSUPP; 285 286 if (copy_from_user(&regs, useraddr, sizeof(regs))) 287 return -EFAULT; 288 289 reglen = ops->get_regs_len(dev); 290 if (regs.len > reglen) 291 regs.len = reglen; 292 293 regbuf = kmalloc(reglen, GFP_USER); 294 if (!regbuf) 295 return -ENOMEM; 296 297 ops->get_regs(dev, &regs, regbuf); 298 299 ret = -EFAULT; 300 if (copy_to_user(useraddr, &regs, sizeof(regs))) 301 goto out; 302 useraddr += offsetof(struct ethtool_regs, data); 303 if (copy_to_user(useraddr, regbuf, regs.len)) 304 goto out; 305 ret = 0; 306 307 out: 308 kfree(regbuf); 309 return ret; 310} 311 312static int ethtool_get_wol(struct net_device *dev, char __user *useraddr) 313{ 314 struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; 315 316 if (!dev->ethtool_ops->get_wol) 317 return -EOPNOTSUPP; 318 319 dev->ethtool_ops->get_wol(dev, &wol); 320 321 if (copy_to_user(useraddr, &wol, sizeof(wol))) 322 return -EFAULT; 323 return 0; 324} 325 326static int ethtool_set_wol(struct net_device *dev, char __user *useraddr) 327{ 328 struct ethtool_wolinfo wol; 329 330 if (!dev->ethtool_ops->set_wol) 331 return -EOPNOTSUPP; 332 333 if (copy_from_user(&wol, useraddr, sizeof(wol))) 334 return -EFAULT; 335 336 return dev->ethtool_ops->set_wol(dev, &wol); 337} 338 339static int ethtool_nway_reset(struct net_device *dev) 340{ 341 if (!dev->ethtool_ops->nway_reset) 342 return -EOPNOTSUPP; 343 344 return dev->ethtool_ops->nway_reset(dev); 345} 346 347static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr) 348{ 349 struct ethtool_eeprom eeprom; 350 const struct ethtool_ops *ops = dev->ethtool_ops; 351 void __user *userbuf = useraddr + sizeof(eeprom); 352 u32 bytes_remaining; 353 u8 *data; 354 int ret = 0; 355 356 if (!ops->get_eeprom || !ops->get_eeprom_len) 357 return -EOPNOTSUPP; 358 359 if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) 360 return -EFAULT; 361 362 /* Check for wrap and zero */ 363 if (eeprom.offset + eeprom.len <= eeprom.offset) 364 return -EINVAL; 365 366 /* Check for exceeding total eeprom len */ 367 if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) 368 return -EINVAL; 369 370 data = kmalloc(PAGE_SIZE, GFP_USER); 371 if (!data) 372 return -ENOMEM; 373 374 bytes_remaining = eeprom.len; 375 while (bytes_remaining > 0) { 376 eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE); 377 378 ret = ops->get_eeprom(dev, &eeprom, data); 379 if (ret) 380 break; 381 if (copy_to_user(userbuf, data, eeprom.len)) { 382 ret = -EFAULT; 383 break; 384 } 385 userbuf += eeprom.len; 386 eeprom.offset += eeprom.len; 387 bytes_remaining -= eeprom.len; 388 } 389 390 eeprom.len = userbuf - (useraddr + sizeof(eeprom)); 391 eeprom.offset -= eeprom.len; 392 if (copy_to_user(useraddr, &eeprom, sizeof(eeprom))) 393 ret = -EFAULT; 394 395 kfree(data); 396 return ret; 397} 398 399static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr) 400{ 401 struct ethtool_eeprom eeprom; 402 const struct ethtool_ops *ops = dev->ethtool_ops; 403 void __user *userbuf = useraddr + sizeof(eeprom); 404 u32 bytes_remaining; 405 u8 *data; 406 int ret = 0; 407 408 if (!ops->set_eeprom || !ops->get_eeprom_len) 409 return -EOPNOTSUPP; 410 411 if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) 412 return -EFAULT; 413 414 /* Check for wrap and zero */ 415 if (eeprom.offset + eeprom.len <= eeprom.offset) 416 return -EINVAL; 417 418 /* Check for exceeding total eeprom len */ 419 if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) 420 return -EINVAL; 421 422 data = kmalloc(PAGE_SIZE, GFP_USER); 423 if (!data) 424 return -ENOMEM; 425 426 bytes_remaining = eeprom.len; 427 while (bytes_remaining > 0) { 428 eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE); 429 430 if (copy_from_user(data, userbuf, eeprom.len)) { 431 ret = -EFAULT; 432 break; 433 } 434 ret = ops->set_eeprom(dev, &eeprom, data); 435 if (ret) 436 break; 437 userbuf += eeprom.len; 438 eeprom.offset += eeprom.len; 439 bytes_remaining -= eeprom.len; 440 } 441 442 kfree(data); 443 return ret; 444} 445 446static int ethtool_get_coalesce(struct net_device *dev, void __user *useraddr) 447{ 448 struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE }; 449 450 if (!dev->ethtool_ops->get_coalesce) 451 return -EOPNOTSUPP; 452 453 dev->ethtool_ops->get_coalesce(dev, &coalesce); 454 455 if (copy_to_user(useraddr, &coalesce, sizeof(coalesce))) 456 return -EFAULT; 457 return 0; 458} 459 460static int ethtool_set_coalesce(struct net_device *dev, void __user *useraddr) 461{ 462 struct ethtool_coalesce coalesce; 463 464 if (!dev->ethtool_ops->set_coalesce) 465 return -EOPNOTSUPP; 466 467 if (copy_from_user(&coalesce, useraddr, sizeof(coalesce))) 468 return -EFAULT; 469 470 return dev->ethtool_ops->set_coalesce(dev, &coalesce); 471} 472 473static int ethtool_get_ringparam(struct net_device *dev, void __user *useraddr) 474{ 475 struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM }; 476 477 if (!dev->ethtool_ops->get_ringparam) 478 return -EOPNOTSUPP; 479 480 dev->ethtool_ops->get_ringparam(dev, &ringparam); 481 482 if (copy_to_user(useraddr, &ringparam, sizeof(ringparam))) 483 return -EFAULT; 484 return 0; 485} 486 487static int ethtool_set_ringparam(struct net_device *dev, void __user *useraddr) 488{ 489 struct ethtool_ringparam ringparam; 490 491 if (!dev->ethtool_ops->set_ringparam) 492 return -EOPNOTSUPP; 493 494 if (copy_from_user(&ringparam, useraddr, sizeof(ringparam))) 495 return -EFAULT; 496 497 return dev->ethtool_ops->set_ringparam(dev, &ringparam); 498} 499 500static int ethtool_get_pauseparam(struct net_device *dev, void __user *useraddr) 501{ 502 struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM }; 503 504 if (!dev->ethtool_ops->get_pauseparam) 505 return -EOPNOTSUPP; 506 507 dev->ethtool_ops->get_pauseparam(dev, &pauseparam); 508 509 if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam))) 510 return -EFAULT; 511 return 0; 512} 513 514static int ethtool_set_pauseparam(struct net_device *dev, void __user *useraddr) 515{ 516 struct ethtool_pauseparam pauseparam; 517 518 if (!dev->ethtool_ops->set_pauseparam) 519 return -EOPNOTSUPP; 520 521 if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam))) 522 return -EFAULT; 523 524 return dev->ethtool_ops->set_pauseparam(dev, &pauseparam); 525} 526 527static int __ethtool_set_sg(struct net_device *dev, u32 data) 528{ 529 int err; 530 531 if (!data && dev->ethtool_ops->set_tso) { 532 err = dev->ethtool_ops->set_tso(dev, 0); 533 if (err) 534 return err; 535 } 536 537 if (!data && dev->ethtool_ops->set_ufo) { 538 err = dev->ethtool_ops->set_ufo(dev, 0); 539 if (err) 540 return err; 541 } 542 return dev->ethtool_ops->set_sg(dev, data); 543} 544 545static int ethtool_set_tx_csum(struct net_device *dev, char __user *useraddr) 546{ 547 struct ethtool_value edata; 548 int err; 549 550 if (!dev->ethtool_ops->set_tx_csum) 551 return -EOPNOTSUPP; 552 553 if (copy_from_user(&edata, useraddr, sizeof(edata))) 554 return -EFAULT; 555 556 if (!edata.data && dev->ethtool_ops->set_sg) { 557 err = __ethtool_set_sg(dev, 0); 558 if (err) 559 return err; 560 } 561 562 return dev->ethtool_ops->set_tx_csum(dev, edata.data); 563} 564 565static int ethtool_set_rx_csum(struct net_device *dev, char __user *useraddr) 566{ 567 struct ethtool_value edata; 568 569 if (!dev->ethtool_ops->set_rx_csum) 570 return -EOPNOTSUPP; 571 572 if (copy_from_user(&edata, useraddr, sizeof(edata))) 573 return -EFAULT; 574 575 if (!edata.data && dev->ethtool_ops->set_sg) 576 dev->features &= ~NETIF_F_GRO; 577 578 return dev->ethtool_ops->set_rx_csum(dev, edata.data); 579} 580 581static int ethtool_set_sg(struct net_device *dev, char __user *useraddr) 582{ 583 struct ethtool_value edata; 584 585 if (!dev->ethtool_ops->set_sg) 586 return -EOPNOTSUPP; 587 588 if (copy_from_user(&edata, useraddr, sizeof(edata))) 589 return -EFAULT; 590 591 if (edata.data && 592 !(dev->features & NETIF_F_ALL_CSUM)) 593 return -EINVAL; 594 595 return __ethtool_set_sg(dev, edata.data); 596} 597 598static int ethtool_set_tso(struct net_device *dev, char __user *useraddr) 599{ 600 struct ethtool_value edata; 601 602 if (!dev->ethtool_ops->set_tso) 603 return -EOPNOTSUPP; 604 605 if (copy_from_user(&edata, useraddr, sizeof(edata))) 606 return -EFAULT; 607 608 if (edata.data && !(dev->features & NETIF_F_SG)) 609 return -EINVAL; 610 611 return dev->ethtool_ops->set_tso(dev, edata.data); 612} 613 614static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr) 615{ 616 struct ethtool_value edata; 617 618 if (!dev->ethtool_ops->set_ufo) 619 return -EOPNOTSUPP; 620 if (copy_from_user(&edata, useraddr, sizeof(edata))) 621 return -EFAULT; 622 if (edata.data && !(dev->features & NETIF_F_SG)) 623 return -EINVAL; 624 if (edata.data && !(dev->features & NETIF_F_HW_CSUM)) 625 return -EINVAL; 626 return dev->ethtool_ops->set_ufo(dev, edata.data); 627} 628 629static int ethtool_get_gso(struct net_device *dev, char __user *useraddr) 630{ 631 struct ethtool_value edata = { ETHTOOL_GGSO }; 632 633 edata.data = dev->features & NETIF_F_GSO; 634 if (copy_to_user(useraddr, &edata, sizeof(edata))) 635 return -EFAULT; 636 return 0; 637} 638 639static int ethtool_set_gso(struct net_device *dev, char __user *useraddr) 640{ 641 struct ethtool_value edata; 642 643 if (copy_from_user(&edata, useraddr, sizeof(edata))) 644 return -EFAULT; 645 if (edata.data) 646 dev->features |= NETIF_F_GSO; 647 else 648 dev->features &= ~NETIF_F_GSO; 649 return 0; 650} 651 652static int ethtool_get_gro(struct net_device *dev, char __user *useraddr) 653{ 654 struct ethtool_value edata = { ETHTOOL_GGRO }; 655 656 edata.data = dev->features & NETIF_F_GRO; 657 if (copy_to_user(useraddr, &edata, sizeof(edata))) 658 return -EFAULT; 659 return 0; 660} 661 662static int ethtool_set_gro(struct net_device *dev, char __user *useraddr) 663{ 664 struct ethtool_value edata; 665 666 if (copy_from_user(&edata, useraddr, sizeof(edata))) 667 return -EFAULT; 668 669 if (edata.data) { 670 if (!dev->ethtool_ops->get_rx_csum || 671 !dev->ethtool_ops->get_rx_csum(dev)) 672 return -EINVAL; 673 dev->features |= NETIF_F_GRO; 674 } else 675 dev->features &= ~NETIF_F_GRO; 676 677 return 0; 678} 679 680static int ethtool_self_test(struct net_device *dev, char __user *useraddr) 681{ 682 struct ethtool_test test; 683 const struct ethtool_ops *ops = dev->ethtool_ops; 684 u64 *data; 685 int ret, test_len; 686 687 if (!ops->self_test) 688 return -EOPNOTSUPP; 689 if (!ops->get_sset_count && !ops->self_test_count) 690 return -EOPNOTSUPP; 691 692 if (ops->get_sset_count) 693 test_len = ops->get_sset_count(dev, ETH_SS_TEST); 694 else 695 /* code path for obsolete hook */ 696 test_len = ops->self_test_count(dev); 697 if (test_len < 0) 698 return test_len; 699 WARN_ON(test_len == 0); 700 701 if (copy_from_user(&test, useraddr, sizeof(test))) 702 return -EFAULT; 703 704 test.len = test_len; 705 data = kmalloc(test_len * sizeof(u64), GFP_USER); 706 if (!data) 707 return -ENOMEM; 708 709 ops->self_test(dev, &test, data); 710 711 ret = -EFAULT; 712 if (copy_to_user(useraddr, &test, sizeof(test))) 713 goto out; 714 useraddr += sizeof(test); 715 if (copy_to_user(useraddr, data, test.len * sizeof(u64))) 716 goto out; 717 ret = 0; 718 719 out: 720 kfree(data); 721 return ret; 722} 723 724static int ethtool_get_strings(struct net_device *dev, void __user *useraddr) 725{ 726 struct ethtool_gstrings gstrings; 727 const struct ethtool_ops *ops = dev->ethtool_ops; 728 u8 *data; 729 int ret; 730 731 if (!ops->get_strings) 732 return -EOPNOTSUPP; 733 734 if (copy_from_user(&gstrings, useraddr, sizeof(gstrings))) 735 return -EFAULT; 736 737 if (ops->get_sset_count) { 738 ret = ops->get_sset_count(dev, gstrings.string_set); 739 if (ret < 0) 740 return ret; 741 742 gstrings.len = ret; 743 } else { 744 /* code path for obsolete hooks */ 745 746 switch (gstrings.string_set) { 747 case ETH_SS_TEST: 748 if (!ops->self_test_count) 749 return -EOPNOTSUPP; 750 gstrings.len = ops->self_test_count(dev); 751 break; 752 case ETH_SS_STATS: 753 if (!ops->get_stats_count) 754 return -EOPNOTSUPP; 755 gstrings.len = ops->get_stats_count(dev); 756 break; 757 default: 758 return -EINVAL; 759 } 760 } 761 762 data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); 763 if (!data) 764 return -ENOMEM; 765 766 ops->get_strings(dev, gstrings.string_set, data); 767 768 ret = -EFAULT; 769 if (copy_to_user(useraddr, &gstrings, sizeof(gstrings))) 770 goto out; 771 useraddr += sizeof(gstrings); 772 if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN)) 773 goto out; 774 ret = 0; 775 776 out: 777 kfree(data); 778 return ret; 779} 780 781static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) 782{ 783 struct ethtool_value id; 784 785 if (!dev->ethtool_ops->phys_id) 786 return -EOPNOTSUPP; 787 788 if (copy_from_user(&id, useraddr, sizeof(id))) 789 return -EFAULT; 790 791 return dev->ethtool_ops->phys_id(dev, id.data); 792} 793 794static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) 795{ 796 struct ethtool_stats stats; 797 const struct ethtool_ops *ops = dev->ethtool_ops; 798 u64 *data; 799 int ret, n_stats; 800 801 if (!ops->get_ethtool_stats) 802 return -EOPNOTSUPP; 803 if (!ops->get_sset_count && !ops->get_stats_count) 804 return -EOPNOTSUPP; 805 806 if (ops->get_sset_count) 807 n_stats = ops->get_sset_count(dev, ETH_SS_STATS); 808 else 809 /* code path for obsolete hook */ 810 n_stats = ops->get_stats_count(dev); 811 if (n_stats < 0) 812 return n_stats; 813 WARN_ON(n_stats == 0); 814 815 if (copy_from_user(&stats, useraddr, sizeof(stats))) 816 return -EFAULT; 817 818 stats.n_stats = n_stats; 819 data = kmalloc(n_stats * sizeof(u64), GFP_USER); 820 if (!data) 821 return -ENOMEM; 822 823 ops->get_ethtool_stats(dev, &stats, data); 824 825 ret = -EFAULT; 826 if (copy_to_user(useraddr, &stats, sizeof(stats))) 827 goto out; 828 useraddr += sizeof(stats); 829 if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64))) 830 goto out; 831 ret = 0; 832 833 out: 834 kfree(data); 835 return ret; 836} 837 838static int ethtool_get_perm_addr(struct net_device *dev, void __user *useraddr) 839{ 840 struct ethtool_perm_addr epaddr; 841 842 if (copy_from_user(&epaddr, useraddr, sizeof(epaddr))) 843 return -EFAULT; 844 845 if (epaddr.size < dev->addr_len) 846 return -ETOOSMALL; 847 epaddr.size = dev->addr_len; 848 849 if (copy_to_user(useraddr, &epaddr, sizeof(epaddr))) 850 return -EFAULT; 851 useraddr += sizeof(epaddr); 852 if (copy_to_user(useraddr, dev->perm_addr, epaddr.size)) 853 return -EFAULT; 854 return 0; 855} 856 857static int ethtool_get_value(struct net_device *dev, char __user *useraddr, 858 u32 cmd, u32 (*actor)(struct net_device *)) 859{ 860 struct ethtool_value edata = { cmd }; 861 862 if (!actor) 863 return -EOPNOTSUPP; 864 865 edata.data = actor(dev); 866 867 if (copy_to_user(useraddr, &edata, sizeof(edata))) 868 return -EFAULT; 869 return 0; 870} 871 872static int ethtool_set_value_void(struct net_device *dev, char __user *useraddr, 873 void (*actor)(struct net_device *, u32)) 874{ 875 struct ethtool_value edata; 876 877 if (!actor) 878 return -EOPNOTSUPP; 879 880 if (copy_from_user(&edata, useraddr, sizeof(edata))) 881 return -EFAULT; 882 883 actor(dev, edata.data); 884 return 0; 885} 886 887static int ethtool_set_value(struct net_device *dev, char __user *useraddr, 888 int (*actor)(struct net_device *, u32)) 889{ 890 struct ethtool_value edata; 891 892 if (!actor) 893 return -EOPNOTSUPP; 894 895 if (copy_from_user(&edata, useraddr, sizeof(edata))) 896 return -EFAULT; 897 898 return actor(dev, edata.data); 899} 900 901static int ethtool_flash_device(struct net_device *dev, char __user *useraddr) 902{ 903 struct ethtool_flash efl; 904 905 if (copy_from_user(&efl, useraddr, sizeof(efl))) 906 return -EFAULT; 907 908 if (!dev->ethtool_ops->flash_device) 909 return -EOPNOTSUPP; 910 911 return dev->ethtool_ops->flash_device(dev, &efl); 912} 913 914/* The main entry point in this file. Called from net/core/dev.c */ 915 916int dev_ethtool(struct net *net, struct ifreq *ifr) 917{ 918 struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name); 919 void __user *useraddr = ifr->ifr_data; 920 u32 ethcmd; 921 int rc; 922 unsigned long old_features; 923 924 if (!dev || !netif_device_present(dev)) 925 return -ENODEV; 926 927 if (!dev->ethtool_ops) 928 return -EOPNOTSUPP; 929 930 if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd))) 931 return -EFAULT; 932 933 /* Allow some commands to be done by anyone */ 934 switch(ethcmd) { 935 case ETHTOOL_GDRVINFO: 936 case ETHTOOL_GMSGLVL: 937 case ETHTOOL_GCOALESCE: 938 case ETHTOOL_GRINGPARAM: 939 case ETHTOOL_GPAUSEPARAM: 940 case ETHTOOL_GRXCSUM: 941 case ETHTOOL_GTXCSUM: 942 case ETHTOOL_GSG: 943 case ETHTOOL_GSTRINGS: 944 case ETHTOOL_GTSO: 945 case ETHTOOL_GPERMADDR: 946 case ETHTOOL_GUFO: 947 case ETHTOOL_GGSO: 948 case ETHTOOL_GFLAGS: 949 case ETHTOOL_GPFLAGS: 950 case ETHTOOL_GRXFH: 951 case ETHTOOL_GRXRINGS: 952 case ETHTOOL_GRXCLSRLCNT: 953 case ETHTOOL_GRXCLSRULE: 954 case ETHTOOL_GRXCLSRLALL: 955 break; 956 default: 957 if (!capable(CAP_NET_ADMIN)) 958 return -EPERM; 959 } 960 961 if (dev->ethtool_ops->begin) 962 if ((rc = dev->ethtool_ops->begin(dev)) < 0) 963 return rc; 964 965 old_features = dev->features; 966 967 switch (ethcmd) { 968 case ETHTOOL_GSET: 969 rc = ethtool_get_settings(dev, useraddr); 970 break; 971 case ETHTOOL_SSET: 972 rc = ethtool_set_settings(dev, useraddr); 973 break; 974 case ETHTOOL_GDRVINFO: 975 rc = ethtool_get_drvinfo(dev, useraddr); 976 break; 977 case ETHTOOL_GREGS: 978 rc = ethtool_get_regs(dev, useraddr); 979 break; 980 case ETHTOOL_GWOL: 981 rc = ethtool_get_wol(dev, useraddr); 982 break; 983 case ETHTOOL_SWOL: 984 rc = ethtool_set_wol(dev, useraddr); 985 break; 986 case ETHTOOL_GMSGLVL: 987 rc = ethtool_get_value(dev, useraddr, ethcmd, 988 dev->ethtool_ops->get_msglevel); 989 break; 990 case ETHTOOL_SMSGLVL: 991 rc = ethtool_set_value_void(dev, useraddr, 992 dev->ethtool_ops->set_msglevel); 993 break; 994 case ETHTOOL_NWAY_RST: 995 rc = ethtool_nway_reset(dev); 996 break; 997 case ETHTOOL_GLINK: 998 rc = ethtool_get_value(dev, useraddr, ethcmd, 999 dev->ethtool_ops->get_link); 1000 break; 1001 case ETHTOOL_GEEPROM: 1002 rc = ethtool_get_eeprom(dev, useraddr); 1003 break; 1004 case ETHTOOL_SEEPROM: 1005 rc = ethtool_set_eeprom(dev, useraddr); 1006 break; 1007 case ETHTOOL_GCOALESCE: 1008 rc = ethtool_get_coalesce(dev, useraddr); 1009 break; 1010 case ETHTOOL_SCOALESCE: 1011 rc = ethtool_set_coalesce(dev, useraddr); 1012 break; 1013 case ETHTOOL_GRINGPARAM: 1014 rc = ethtool_get_ringparam(dev, useraddr); 1015 break; 1016 case ETHTOOL_SRINGPARAM: 1017 rc = ethtool_set_ringparam(dev, useraddr); 1018 break; 1019 case ETHTOOL_GPAUSEPARAM: 1020 rc = ethtool_get_pauseparam(dev, useraddr); 1021 break; 1022 case ETHTOOL_SPAUSEPARAM: 1023 rc = ethtool_set_pauseparam(dev, useraddr); 1024 break; 1025 case ETHTOOL_GRXCSUM: 1026 rc = ethtool_get_value(dev, useraddr, ethcmd, 1027 (dev->ethtool_ops->get_rx_csum ? 1028 dev->ethtool_ops->get_rx_csum : 1029 ethtool_op_get_rx_csum)); 1030 break; 1031 case ETHTOOL_SRXCSUM: 1032 rc = ethtool_set_rx_csum(dev, useraddr); 1033 break; 1034 case ETHTOOL_GTXCSUM: 1035 rc = ethtool_get_value(dev, useraddr, ethcmd, 1036 (dev->ethtool_ops->get_tx_csum ? 1037 dev->ethtool_ops->get_tx_csum : 1038 ethtool_op_get_tx_csum)); 1039 break; 1040 case ETHTOOL_STXCSUM: 1041 rc = ethtool_set_tx_csum(dev, useraddr); 1042 break; 1043 case ETHTOOL_GSG: 1044 rc = ethtool_get_value(dev, useraddr, ethcmd, 1045 (dev->ethtool_ops->get_sg ? 1046 dev->ethtool_ops->get_sg : 1047 ethtool_op_get_sg)); 1048 break; 1049 case ETHTOOL_SSG: 1050 rc = ethtool_set_sg(dev, useraddr); 1051 break; 1052 case ETHTOOL_GTSO: 1053 rc = ethtool_get_value(dev, useraddr, ethcmd, 1054 (dev->ethtool_ops->get_tso ? 1055 dev->ethtool_ops->get_tso : 1056 ethtool_op_get_tso)); 1057 break; 1058 case ETHTOOL_STSO: 1059 rc = ethtool_set_tso(dev, useraddr); 1060 break; 1061 case ETHTOOL_TEST: 1062 rc = ethtool_self_test(dev, useraddr); 1063 break; 1064 case ETHTOOL_GSTRINGS: 1065 rc = ethtool_get_strings(dev, useraddr); 1066 break; 1067 case ETHTOOL_PHYS_ID: 1068 rc = ethtool_phys_id(dev, useraddr); 1069 break; 1070 case ETHTOOL_GSTATS: 1071 rc = ethtool_get_stats(dev, useraddr); 1072 break; 1073 case ETHTOOL_GPERMADDR: 1074 rc = ethtool_get_perm_addr(dev, useraddr); 1075 break; 1076 case ETHTOOL_GUFO: 1077 rc = ethtool_get_value(dev, useraddr, ethcmd, 1078 (dev->ethtool_ops->get_ufo ? 1079 dev->ethtool_ops->get_ufo : 1080 ethtool_op_get_ufo)); 1081 break; 1082 case ETHTOOL_SUFO: 1083 rc = ethtool_set_ufo(dev, useraddr); 1084 break; 1085 case ETHTOOL_GGSO: 1086 rc = ethtool_get_gso(dev, useraddr); 1087 break; 1088 case ETHTOOL_SGSO: 1089 rc = ethtool_set_gso(dev, useraddr); 1090 break; 1091 case ETHTOOL_GFLAGS: 1092 rc = ethtool_get_value(dev, useraddr, ethcmd, 1093 (dev->ethtool_ops->get_flags ? 1094 dev->ethtool_ops->get_flags : 1095 ethtool_op_get_flags)); 1096 break; 1097 case ETHTOOL_SFLAGS: 1098 rc = ethtool_set_value(dev, useraddr, 1099 dev->ethtool_ops->set_flags); 1100 break; 1101 case ETHTOOL_GPFLAGS: 1102 rc = ethtool_get_value(dev, useraddr, ethcmd, 1103 dev->ethtool_ops->get_priv_flags); 1104 break; 1105 case ETHTOOL_SPFLAGS: 1106 rc = ethtool_set_value(dev, useraddr, 1107 dev->ethtool_ops->set_priv_flags); 1108 break; 1109 case ETHTOOL_GRXFH: 1110 case ETHTOOL_GRXRINGS: 1111 case ETHTOOL_GRXCLSRLCNT: 1112 case ETHTOOL_GRXCLSRULE: 1113 case ETHTOOL_GRXCLSRLALL: 1114 rc = ethtool_get_rxnfc(dev, useraddr); 1115 break; 1116 case ETHTOOL_SRXFH: 1117 case ETHTOOL_SRXCLSRLDEL: 1118 case ETHTOOL_SRXCLSRLINS: 1119 rc = ethtool_set_rxnfc(dev, useraddr); 1120 break; 1121 case ETHTOOL_GGRO: 1122 rc = ethtool_get_gro(dev, useraddr); 1123 break; 1124 case ETHTOOL_SGRO: 1125 rc = ethtool_set_gro(dev, useraddr); 1126 break; 1127 case ETHTOOL_FLASHDEV: 1128 rc = ethtool_flash_device(dev, useraddr); 1129 break; 1130 default: 1131 rc = -EOPNOTSUPP; 1132 } 1133 1134 if (dev->ethtool_ops->complete) 1135 dev->ethtool_ops->complete(dev); 1136 1137 if (old_features != dev->features) 1138 netdev_features_change(dev); 1139 1140 return rc; 1141} 1142 1143EXPORT_SYMBOL(ethtool_op_get_link); 1144EXPORT_SYMBOL(ethtool_op_get_sg); 1145EXPORT_SYMBOL(ethtool_op_get_tso); 1146EXPORT_SYMBOL(ethtool_op_set_sg); 1147EXPORT_SYMBOL(ethtool_op_set_tso); 1148EXPORT_SYMBOL(ethtool_op_set_tx_csum); 1149EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); 1150EXPORT_SYMBOL(ethtool_op_set_tx_ipv6_csum); 1151EXPORT_SYMBOL(ethtool_op_set_ufo); 1152EXPORT_SYMBOL(ethtool_op_get_ufo); 1153EXPORT_SYMBOL(ethtool_op_set_flags); 1154EXPORT_SYMBOL(ethtool_op_get_flags);