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