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