ethtool.c 35 KB

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