qeth_l3_sys.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051
  1. /*
  2. * drivers/s390/net/qeth_l3_sys.c
  3. *
  4. * Copyright IBM Corp. 2007
  5. * Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
  6. * Frank Pavlic <fpavlic@de.ibm.com>,
  7. * Thomas Spatzier <tspat@de.ibm.com>,
  8. * Frank Blaschka <frank.blaschka@de.ibm.com>
  9. */
  10. #include "qeth_l3.h"
  11. #define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
  12. struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store)
  13. static const char *qeth_l3_get_checksum_str(struct qeth_card *card)
  14. {
  15. if (card->options.checksum_type == SW_CHECKSUMMING)
  16. return "sw";
  17. else if (card->options.checksum_type == HW_CHECKSUMMING)
  18. return "hw";
  19. else
  20. return "no";
  21. }
  22. static ssize_t qeth_l3_dev_route_show(struct qeth_card *card,
  23. struct qeth_routing_info *route, char *buf)
  24. {
  25. switch (route->type) {
  26. case PRIMARY_ROUTER:
  27. return sprintf(buf, "%s\n", "primary router");
  28. case SECONDARY_ROUTER:
  29. return sprintf(buf, "%s\n", "secondary router");
  30. case MULTICAST_ROUTER:
  31. if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
  32. return sprintf(buf, "%s\n", "multicast router+");
  33. else
  34. return sprintf(buf, "%s\n", "multicast router");
  35. case PRIMARY_CONNECTOR:
  36. if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
  37. return sprintf(buf, "%s\n", "primary connector+");
  38. else
  39. return sprintf(buf, "%s\n", "primary connector");
  40. case SECONDARY_CONNECTOR:
  41. if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO)
  42. return sprintf(buf, "%s\n", "secondary connector+");
  43. else
  44. return sprintf(buf, "%s\n", "secondary connector");
  45. default:
  46. return sprintf(buf, "%s\n", "no");
  47. }
  48. }
  49. static ssize_t qeth_l3_dev_route4_show(struct device *dev,
  50. struct device_attribute *attr, char *buf)
  51. {
  52. struct qeth_card *card = dev_get_drvdata(dev);
  53. if (!card)
  54. return -EINVAL;
  55. return qeth_l3_dev_route_show(card, &card->options.route4, buf);
  56. }
  57. static ssize_t qeth_l3_dev_route_store(struct qeth_card *card,
  58. struct qeth_routing_info *route, enum qeth_prot_versions prot,
  59. const char *buf, size_t count)
  60. {
  61. enum qeth_routing_types old_route_type = route->type;
  62. char *tmp;
  63. int rc;
  64. tmp = strsep((char **) &buf, "\n");
  65. if (!strcmp(tmp, "no_router")) {
  66. route->type = NO_ROUTER;
  67. } else if (!strcmp(tmp, "primary_connector")) {
  68. route->type = PRIMARY_CONNECTOR;
  69. } else if (!strcmp(tmp, "secondary_connector")) {
  70. route->type = SECONDARY_CONNECTOR;
  71. } else if (!strcmp(tmp, "primary_router")) {
  72. route->type = PRIMARY_ROUTER;
  73. } else if (!strcmp(tmp, "secondary_router")) {
  74. route->type = SECONDARY_ROUTER;
  75. } else if (!strcmp(tmp, "multicast_router")) {
  76. route->type = MULTICAST_ROUTER;
  77. } else {
  78. PRINT_WARN("Invalid routing type '%s'.\n", tmp);
  79. return -EINVAL;
  80. }
  81. if (((card->state == CARD_STATE_SOFTSETUP) ||
  82. (card->state == CARD_STATE_UP)) &&
  83. (old_route_type != route->type)) {
  84. if (prot == QETH_PROT_IPV4)
  85. rc = qeth_l3_setrouting_v4(card);
  86. else if (prot == QETH_PROT_IPV6)
  87. rc = qeth_l3_setrouting_v6(card);
  88. }
  89. return count;
  90. }
  91. static ssize_t qeth_l3_dev_route4_store(struct device *dev,
  92. struct device_attribute *attr, const char *buf, size_t count)
  93. {
  94. struct qeth_card *card = dev_get_drvdata(dev);
  95. if (!card)
  96. return -EINVAL;
  97. return qeth_l3_dev_route_store(card, &card->options.route4,
  98. QETH_PROT_IPV4, buf, count);
  99. }
  100. static DEVICE_ATTR(route4, 0644, qeth_l3_dev_route4_show,
  101. qeth_l3_dev_route4_store);
  102. static ssize_t qeth_l3_dev_route6_show(struct device *dev,
  103. struct device_attribute *attr, char *buf)
  104. {
  105. struct qeth_card *card = dev_get_drvdata(dev);
  106. if (!card)
  107. return -EINVAL;
  108. if (!qeth_is_supported(card, IPA_IPV6))
  109. return sprintf(buf, "%s\n", "n/a");
  110. return qeth_l3_dev_route_show(card, &card->options.route6, buf);
  111. }
  112. static ssize_t qeth_l3_dev_route6_store(struct device *dev,
  113. struct device_attribute *attr, const char *buf, size_t count)
  114. {
  115. struct qeth_card *card = dev_get_drvdata(dev);
  116. if (!card)
  117. return -EINVAL;
  118. if (!qeth_is_supported(card, IPA_IPV6)) {
  119. PRINT_WARN("IPv6 not supported for interface %s.\n"
  120. "Routing status no changed.\n",
  121. QETH_CARD_IFNAME(card));
  122. return -ENOTSUPP;
  123. }
  124. return qeth_l3_dev_route_store(card, &card->options.route6,
  125. QETH_PROT_IPV6, buf, count);
  126. }
  127. static DEVICE_ATTR(route6, 0644, qeth_l3_dev_route6_show,
  128. qeth_l3_dev_route6_store);
  129. static ssize_t qeth_l3_dev_fake_broadcast_show(struct device *dev,
  130. struct device_attribute *attr, char *buf)
  131. {
  132. struct qeth_card *card = dev_get_drvdata(dev);
  133. if (!card)
  134. return -EINVAL;
  135. return sprintf(buf, "%i\n", card->options.fake_broadcast? 1:0);
  136. }
  137. static ssize_t qeth_l3_dev_fake_broadcast_store(struct device *dev,
  138. struct device_attribute *attr, const char *buf, size_t count)
  139. {
  140. struct qeth_card *card = dev_get_drvdata(dev);
  141. char *tmp;
  142. int i;
  143. if (!card)
  144. return -EINVAL;
  145. if ((card->state != CARD_STATE_DOWN) &&
  146. (card->state != CARD_STATE_RECOVER))
  147. return -EPERM;
  148. i = simple_strtoul(buf, &tmp, 16);
  149. if ((i == 0) || (i == 1))
  150. card->options.fake_broadcast = i;
  151. else {
  152. PRINT_WARN("fake_broadcast: write 0 or 1 to this file!\n");
  153. return -EINVAL;
  154. }
  155. return count;
  156. }
  157. static DEVICE_ATTR(fake_broadcast, 0644, qeth_l3_dev_fake_broadcast_show,
  158. qeth_l3_dev_fake_broadcast_store);
  159. static ssize_t qeth_l3_dev_broadcast_mode_show(struct device *dev,
  160. struct device_attribute *attr, char *buf)
  161. {
  162. struct qeth_card *card = dev_get_drvdata(dev);
  163. if (!card)
  164. return -EINVAL;
  165. if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
  166. (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
  167. return sprintf(buf, "n/a\n");
  168. return sprintf(buf, "%s\n", (card->options.broadcast_mode ==
  169. QETH_TR_BROADCAST_ALLRINGS)?
  170. "all rings":"local");
  171. }
  172. static ssize_t qeth_l3_dev_broadcast_mode_store(struct device *dev,
  173. struct device_attribute *attr, const char *buf, size_t count)
  174. {
  175. struct qeth_card *card = dev_get_drvdata(dev);
  176. char *tmp;
  177. if (!card)
  178. return -EINVAL;
  179. if ((card->state != CARD_STATE_DOWN) &&
  180. (card->state != CARD_STATE_RECOVER))
  181. return -EPERM;
  182. if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
  183. (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
  184. PRINT_WARN("Device is not a tokenring device!\n");
  185. return -EINVAL;
  186. }
  187. tmp = strsep((char **) &buf, "\n");
  188. if (!strcmp(tmp, "local")) {
  189. card->options.broadcast_mode = QETH_TR_BROADCAST_LOCAL;
  190. return count;
  191. } else if (!strcmp(tmp, "all_rings")) {
  192. card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
  193. return count;
  194. } else {
  195. PRINT_WARN("broadcast_mode: invalid mode %s!\n",
  196. tmp);
  197. return -EINVAL;
  198. }
  199. return count;
  200. }
  201. static DEVICE_ATTR(broadcast_mode, 0644, qeth_l3_dev_broadcast_mode_show,
  202. qeth_l3_dev_broadcast_mode_store);
  203. static ssize_t qeth_l3_dev_canonical_macaddr_show(struct device *dev,
  204. struct device_attribute *attr, char *buf)
  205. {
  206. struct qeth_card *card = dev_get_drvdata(dev);
  207. if (!card)
  208. return -EINVAL;
  209. if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
  210. (card->info.link_type == QETH_LINK_TYPE_LANE_TR)))
  211. return sprintf(buf, "n/a\n");
  212. return sprintf(buf, "%i\n", (card->options.macaddr_mode ==
  213. QETH_TR_MACADDR_CANONICAL)? 1:0);
  214. }
  215. static ssize_t qeth_l3_dev_canonical_macaddr_store(struct device *dev,
  216. struct device_attribute *attr, const char *buf, size_t count)
  217. {
  218. struct qeth_card *card = dev_get_drvdata(dev);
  219. char *tmp;
  220. int i;
  221. if (!card)
  222. return -EINVAL;
  223. if ((card->state != CARD_STATE_DOWN) &&
  224. (card->state != CARD_STATE_RECOVER))
  225. return -EPERM;
  226. if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
  227. (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
  228. PRINT_WARN("Device is not a tokenring device!\n");
  229. return -EINVAL;
  230. }
  231. i = simple_strtoul(buf, &tmp, 16);
  232. if ((i == 0) || (i == 1))
  233. card->options.macaddr_mode = i?
  234. QETH_TR_MACADDR_CANONICAL :
  235. QETH_TR_MACADDR_NONCANONICAL;
  236. else {
  237. PRINT_WARN("canonical_macaddr: write 0 or 1 to this file!\n");
  238. return -EINVAL;
  239. }
  240. return count;
  241. }
  242. static DEVICE_ATTR(canonical_macaddr, 0644, qeth_l3_dev_canonical_macaddr_show,
  243. qeth_l3_dev_canonical_macaddr_store);
  244. static ssize_t qeth_l3_dev_checksum_show(struct device *dev,
  245. struct device_attribute *attr, char *buf)
  246. {
  247. struct qeth_card *card = dev_get_drvdata(dev);
  248. if (!card)
  249. return -EINVAL;
  250. return sprintf(buf, "%s checksumming\n",
  251. qeth_l3_get_checksum_str(card));
  252. }
  253. static ssize_t qeth_l3_dev_checksum_store(struct device *dev,
  254. struct device_attribute *attr, const char *buf, size_t count)
  255. {
  256. struct qeth_card *card = dev_get_drvdata(dev);
  257. char *tmp;
  258. if (!card)
  259. return -EINVAL;
  260. if ((card->state != CARD_STATE_DOWN) &&
  261. (card->state != CARD_STATE_RECOVER))
  262. return -EPERM;
  263. tmp = strsep((char **) &buf, "\n");
  264. if (!strcmp(tmp, "sw_checksumming"))
  265. card->options.checksum_type = SW_CHECKSUMMING;
  266. else if (!strcmp(tmp, "hw_checksumming"))
  267. card->options.checksum_type = HW_CHECKSUMMING;
  268. else if (!strcmp(tmp, "no_checksumming"))
  269. card->options.checksum_type = NO_CHECKSUMMING;
  270. else {
  271. PRINT_WARN("Unknown checksumming type '%s'\n", tmp);
  272. return -EINVAL;
  273. }
  274. return count;
  275. }
  276. static DEVICE_ATTR(checksumming, 0644, qeth_l3_dev_checksum_show,
  277. qeth_l3_dev_checksum_store);
  278. static struct attribute *qeth_l3_device_attrs[] = {
  279. &dev_attr_route4.attr,
  280. &dev_attr_route6.attr,
  281. &dev_attr_fake_broadcast.attr,
  282. &dev_attr_broadcast_mode.attr,
  283. &dev_attr_canonical_macaddr.attr,
  284. &dev_attr_checksumming.attr,
  285. NULL,
  286. };
  287. static struct attribute_group qeth_l3_device_attr_group = {
  288. .attrs = qeth_l3_device_attrs,
  289. };
  290. static ssize_t qeth_l3_dev_ipato_enable_show(struct device *dev,
  291. struct device_attribute *attr, char *buf)
  292. {
  293. struct qeth_card *card = dev_get_drvdata(dev);
  294. if (!card)
  295. return -EINVAL;
  296. return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);
  297. }
  298. static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev,
  299. struct device_attribute *attr, const char *buf, size_t count)
  300. {
  301. struct qeth_card *card = dev_get_drvdata(dev);
  302. char *tmp;
  303. if (!card)
  304. return -EINVAL;
  305. if ((card->state != CARD_STATE_DOWN) &&
  306. (card->state != CARD_STATE_RECOVER))
  307. return -EPERM;
  308. tmp = strsep((char **) &buf, "\n");
  309. if (!strcmp(tmp, "toggle")) {
  310. card->ipato.enabled = (card->ipato.enabled)? 0 : 1;
  311. } else if (!strcmp(tmp, "1")) {
  312. card->ipato.enabled = 1;
  313. } else if (!strcmp(tmp, "0")) {
  314. card->ipato.enabled = 0;
  315. } else {
  316. PRINT_WARN("ipato_enable: write 0, 1 or 'toggle' to "
  317. "this file\n");
  318. return -EINVAL;
  319. }
  320. return count;
  321. }
  322. static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
  323. qeth_l3_dev_ipato_enable_show,
  324. qeth_l3_dev_ipato_enable_store);
  325. static ssize_t qeth_l3_dev_ipato_invert4_show(struct device *dev,
  326. struct device_attribute *attr, char *buf)
  327. {
  328. struct qeth_card *card = dev_get_drvdata(dev);
  329. if (!card)
  330. return -EINVAL;
  331. return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);
  332. }
  333. static ssize_t qeth_l3_dev_ipato_invert4_store(struct device *dev,
  334. struct device_attribute *attr,
  335. const char *buf, size_t count)
  336. {
  337. struct qeth_card *card = dev_get_drvdata(dev);
  338. char *tmp;
  339. if (!card)
  340. return -EINVAL;
  341. tmp = strsep((char **) &buf, "\n");
  342. if (!strcmp(tmp, "toggle")) {
  343. card->ipato.invert4 = (card->ipato.invert4)? 0 : 1;
  344. } else if (!strcmp(tmp, "1")) {
  345. card->ipato.invert4 = 1;
  346. } else if (!strcmp(tmp, "0")) {
  347. card->ipato.invert4 = 0;
  348. } else {
  349. PRINT_WARN("ipato_invert4: write 0, 1 or 'toggle' to "
  350. "this file\n");
  351. return -EINVAL;
  352. }
  353. return count;
  354. }
  355. static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
  356. qeth_l3_dev_ipato_invert4_show,
  357. qeth_l3_dev_ipato_invert4_store);
  358. static ssize_t qeth_l3_dev_ipato_add_show(char *buf, struct qeth_card *card,
  359. enum qeth_prot_versions proto)
  360. {
  361. struct qeth_ipato_entry *ipatoe;
  362. unsigned long flags;
  363. char addr_str[40];
  364. int entry_len; /* length of 1 entry string, differs between v4 and v6 */
  365. int i = 0;
  366. entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
  367. /* add strlen for "/<mask>\n" */
  368. entry_len += (proto == QETH_PROT_IPV4)? 5 : 6;
  369. spin_lock_irqsave(&card->ip_lock, flags);
  370. list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
  371. if (ipatoe->proto != proto)
  372. continue;
  373. /* String must not be longer than PAGE_SIZE. So we check if
  374. * string length gets near PAGE_SIZE. Then we can savely display
  375. * the next IPv6 address (worst case, compared to IPv4) */
  376. if ((PAGE_SIZE - i) <= entry_len)
  377. break;
  378. qeth_l3_ipaddr_to_string(proto, ipatoe->addr, addr_str);
  379. i += snprintf(buf + i, PAGE_SIZE - i,
  380. "%s/%i\n", addr_str, ipatoe->mask_bits);
  381. }
  382. spin_unlock_irqrestore(&card->ip_lock, flags);
  383. i += snprintf(buf + i, PAGE_SIZE - i, "\n");
  384. return i;
  385. }
  386. static ssize_t qeth_l3_dev_ipato_add4_show(struct device *dev,
  387. struct device_attribute *attr, char *buf)
  388. {
  389. struct qeth_card *card = dev_get_drvdata(dev);
  390. if (!card)
  391. return -EINVAL;
  392. return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
  393. }
  394. static int qeth_l3_parse_ipatoe(const char *buf, enum qeth_prot_versions proto,
  395. u8 *addr, int *mask_bits)
  396. {
  397. const char *start, *end;
  398. char *tmp;
  399. char buffer[40] = {0, };
  400. start = buf;
  401. /* get address string */
  402. end = strchr(start, '/');
  403. if (!end || (end - start >= 40)) {
  404. PRINT_WARN("Invalid format for ipato_addx/delx. "
  405. "Use <ip addr>/<mask bits>\n");
  406. return -EINVAL;
  407. }
  408. strncpy(buffer, start, end - start);
  409. if (qeth_l3_string_to_ipaddr(buffer, proto, addr)) {
  410. PRINT_WARN("Invalid IP address format!\n");
  411. return -EINVAL;
  412. }
  413. start = end + 1;
  414. *mask_bits = simple_strtoul(start, &tmp, 10);
  415. if (!strlen(start) ||
  416. (tmp == start) ||
  417. (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) {
  418. PRINT_WARN("Invalid mask bits for ipato_addx/delx !\n");
  419. return -EINVAL;
  420. }
  421. return 0;
  422. }
  423. static ssize_t qeth_l3_dev_ipato_add_store(const char *buf, size_t count,
  424. struct qeth_card *card, enum qeth_prot_versions proto)
  425. {
  426. struct qeth_ipato_entry *ipatoe;
  427. u8 addr[16];
  428. int mask_bits;
  429. int rc;
  430. rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
  431. if (rc)
  432. return rc;
  433. ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL);
  434. if (!ipatoe) {
  435. PRINT_WARN("No memory to allocate ipato entry\n");
  436. return -ENOMEM;
  437. }
  438. ipatoe->proto = proto;
  439. memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
  440. ipatoe->mask_bits = mask_bits;
  441. rc = qeth_l3_add_ipato_entry(card, ipatoe);
  442. if (rc) {
  443. kfree(ipatoe);
  444. return rc;
  445. }
  446. return count;
  447. }
  448. static ssize_t qeth_l3_dev_ipato_add4_store(struct device *dev,
  449. struct device_attribute *attr, const char *buf, size_t count)
  450. {
  451. struct qeth_card *card = dev_get_drvdata(dev);
  452. if (!card)
  453. return -EINVAL;
  454. return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV4);
  455. }
  456. static QETH_DEVICE_ATTR(ipato_add4, add4, 0644,
  457. qeth_l3_dev_ipato_add4_show,
  458. qeth_l3_dev_ipato_add4_store);
  459. static ssize_t qeth_l3_dev_ipato_del_store(const char *buf, size_t count,
  460. struct qeth_card *card, enum qeth_prot_versions proto)
  461. {
  462. u8 addr[16];
  463. int mask_bits;
  464. int rc;
  465. rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
  466. if (rc)
  467. return rc;
  468. qeth_l3_del_ipato_entry(card, proto, addr, mask_bits);
  469. return count;
  470. }
  471. static ssize_t qeth_l3_dev_ipato_del4_store(struct device *dev,
  472. struct device_attribute *attr, const char *buf, size_t count)
  473. {
  474. struct qeth_card *card = dev_get_drvdata(dev);
  475. if (!card)
  476. return -EINVAL;
  477. return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV4);
  478. }
  479. static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL,
  480. qeth_l3_dev_ipato_del4_store);
  481. static ssize_t qeth_l3_dev_ipato_invert6_show(struct device *dev,
  482. struct device_attribute *attr, char *buf)
  483. {
  484. struct qeth_card *card = dev_get_drvdata(dev);
  485. if (!card)
  486. return -EINVAL;
  487. return sprintf(buf, "%i\n", card->ipato.invert6? 1:0);
  488. }
  489. static ssize_t qeth_l3_dev_ipato_invert6_store(struct device *dev,
  490. struct device_attribute *attr, const char *buf, size_t count)
  491. {
  492. struct qeth_card *card = dev_get_drvdata(dev);
  493. char *tmp;
  494. if (!card)
  495. return -EINVAL;
  496. tmp = strsep((char **) &buf, "\n");
  497. if (!strcmp(tmp, "toggle")) {
  498. card->ipato.invert6 = (card->ipato.invert6)? 0 : 1;
  499. } else if (!strcmp(tmp, "1")) {
  500. card->ipato.invert6 = 1;
  501. } else if (!strcmp(tmp, "0")) {
  502. card->ipato.invert6 = 0;
  503. } else {
  504. PRINT_WARN("ipato_invert6: write 0, 1 or 'toggle' to "
  505. "this file\n");
  506. return -EINVAL;
  507. }
  508. return count;
  509. }
  510. static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
  511. qeth_l3_dev_ipato_invert6_show,
  512. qeth_l3_dev_ipato_invert6_store);
  513. static ssize_t qeth_l3_dev_ipato_add6_show(struct device *dev,
  514. struct device_attribute *attr, char *buf)
  515. {
  516. struct qeth_card *card = dev_get_drvdata(dev);
  517. if (!card)
  518. return -EINVAL;
  519. return qeth_l3_dev_ipato_add_show(buf, card, QETH_PROT_IPV6);
  520. }
  521. static ssize_t qeth_l3_dev_ipato_add6_store(struct device *dev,
  522. struct device_attribute *attr, const char *buf, size_t count)
  523. {
  524. struct qeth_card *card = dev_get_drvdata(dev);
  525. if (!card)
  526. return -EINVAL;
  527. return qeth_l3_dev_ipato_add_store(buf, count, card, QETH_PROT_IPV6);
  528. }
  529. static QETH_DEVICE_ATTR(ipato_add6, add6, 0644,
  530. qeth_l3_dev_ipato_add6_show,
  531. qeth_l3_dev_ipato_add6_store);
  532. static ssize_t qeth_l3_dev_ipato_del6_store(struct device *dev,
  533. struct device_attribute *attr, const char *buf, size_t count)
  534. {
  535. struct qeth_card *card = dev_get_drvdata(dev);
  536. if (!card)
  537. return -EINVAL;
  538. return qeth_l3_dev_ipato_del_store(buf, count, card, QETH_PROT_IPV6);
  539. }
  540. static QETH_DEVICE_ATTR(ipato_del6, del6, 0200, NULL,
  541. qeth_l3_dev_ipato_del6_store);
  542. static struct attribute *qeth_ipato_device_attrs[] = {
  543. &dev_attr_ipato_enable.attr,
  544. &dev_attr_ipato_invert4.attr,
  545. &dev_attr_ipato_add4.attr,
  546. &dev_attr_ipato_del4.attr,
  547. &dev_attr_ipato_invert6.attr,
  548. &dev_attr_ipato_add6.attr,
  549. &dev_attr_ipato_del6.attr,
  550. NULL,
  551. };
  552. static struct attribute_group qeth_device_ipato_group = {
  553. .name = "ipa_takeover",
  554. .attrs = qeth_ipato_device_attrs,
  555. };
  556. static ssize_t qeth_l3_dev_vipa_add_show(char *buf, struct qeth_card *card,
  557. enum qeth_prot_versions proto)
  558. {
  559. struct qeth_ipaddr *ipaddr;
  560. char addr_str[40];
  561. int entry_len; /* length of 1 entry string, differs between v4 and v6 */
  562. unsigned long flags;
  563. int i = 0;
  564. entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
  565. entry_len += 2; /* \n + terminator */
  566. spin_lock_irqsave(&card->ip_lock, flags);
  567. list_for_each_entry(ipaddr, &card->ip_list, entry) {
  568. if (ipaddr->proto != proto)
  569. continue;
  570. if (ipaddr->type != QETH_IP_TYPE_VIPA)
  571. continue;
  572. /* String must not be longer than PAGE_SIZE. So we check if
  573. * string length gets near PAGE_SIZE. Then we can savely display
  574. * the next IPv6 address (worst case, compared to IPv4) */
  575. if ((PAGE_SIZE - i) <= entry_len)
  576. break;
  577. qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
  578. addr_str);
  579. i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
  580. }
  581. spin_unlock_irqrestore(&card->ip_lock, flags);
  582. i += snprintf(buf + i, PAGE_SIZE - i, "\n");
  583. return i;
  584. }
  585. static ssize_t qeth_l3_dev_vipa_add4_show(struct device *dev,
  586. struct device_attribute *attr, char *buf)
  587. {
  588. struct qeth_card *card = dev_get_drvdata(dev);
  589. if (!card)
  590. return -EINVAL;
  591. return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV4);
  592. }
  593. static int qeth_l3_parse_vipae(const char *buf, enum qeth_prot_versions proto,
  594. u8 *addr)
  595. {
  596. if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
  597. PRINT_WARN("Invalid IP address format!\n");
  598. return -EINVAL;
  599. }
  600. return 0;
  601. }
  602. static ssize_t qeth_l3_dev_vipa_add_store(const char *buf, size_t count,
  603. struct qeth_card *card, enum qeth_prot_versions proto)
  604. {
  605. u8 addr[16] = {0, };
  606. int rc;
  607. rc = qeth_l3_parse_vipae(buf, proto, addr);
  608. if (rc)
  609. return rc;
  610. rc = qeth_l3_add_vipa(card, proto, addr);
  611. if (rc)
  612. return rc;
  613. return count;
  614. }
  615. static ssize_t qeth_l3_dev_vipa_add4_store(struct device *dev,
  616. struct device_attribute *attr, const char *buf, size_t count)
  617. {
  618. struct qeth_card *card = dev_get_drvdata(dev);
  619. if (!card)
  620. return -EINVAL;
  621. return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV4);
  622. }
  623. static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
  624. qeth_l3_dev_vipa_add4_show,
  625. qeth_l3_dev_vipa_add4_store);
  626. static ssize_t qeth_l3_dev_vipa_del_store(const char *buf, size_t count,
  627. struct qeth_card *card, enum qeth_prot_versions proto)
  628. {
  629. u8 addr[16];
  630. int rc;
  631. rc = qeth_l3_parse_vipae(buf, proto, addr);
  632. if (rc)
  633. return rc;
  634. qeth_l3_del_vipa(card, proto, addr);
  635. return count;
  636. }
  637. static ssize_t qeth_l3_dev_vipa_del4_store(struct device *dev,
  638. struct device_attribute *attr, const char *buf, size_t count)
  639. {
  640. struct qeth_card *card = dev_get_drvdata(dev);
  641. if (!card)
  642. return -EINVAL;
  643. return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV4);
  644. }
  645. static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
  646. qeth_l3_dev_vipa_del4_store);
  647. static ssize_t qeth_l3_dev_vipa_add6_show(struct device *dev,
  648. struct device_attribute *attr, char *buf)
  649. {
  650. struct qeth_card *card = dev_get_drvdata(dev);
  651. if (!card)
  652. return -EINVAL;
  653. return qeth_l3_dev_vipa_add_show(buf, card, QETH_PROT_IPV6);
  654. }
  655. static ssize_t qeth_l3_dev_vipa_add6_store(struct device *dev,
  656. struct device_attribute *attr, const char *buf, size_t count)
  657. {
  658. struct qeth_card *card = dev_get_drvdata(dev);
  659. if (!card)
  660. return -EINVAL;
  661. return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV6);
  662. }
  663. static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
  664. qeth_l3_dev_vipa_add6_show,
  665. qeth_l3_dev_vipa_add6_store);
  666. static ssize_t qeth_l3_dev_vipa_del6_store(struct device *dev,
  667. struct device_attribute *attr, const char *buf, size_t count)
  668. {
  669. struct qeth_card *card = dev_get_drvdata(dev);
  670. if (!card)
  671. return -EINVAL;
  672. return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6);
  673. }
  674. static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL,
  675. qeth_l3_dev_vipa_del6_store);
  676. static struct attribute *qeth_vipa_device_attrs[] = {
  677. &dev_attr_vipa_add4.attr,
  678. &dev_attr_vipa_del4.attr,
  679. &dev_attr_vipa_add6.attr,
  680. &dev_attr_vipa_del6.attr,
  681. NULL,
  682. };
  683. static struct attribute_group qeth_device_vipa_group = {
  684. .name = "vipa",
  685. .attrs = qeth_vipa_device_attrs,
  686. };
  687. static ssize_t qeth_l3_dev_rxip_add_show(char *buf, struct qeth_card *card,
  688. enum qeth_prot_versions proto)
  689. {
  690. struct qeth_ipaddr *ipaddr;
  691. char addr_str[40];
  692. int entry_len; /* length of 1 entry string, differs between v4 and v6 */
  693. unsigned long flags;
  694. int i = 0;
  695. entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
  696. entry_len += 2; /* \n + terminator */
  697. spin_lock_irqsave(&card->ip_lock, flags);
  698. list_for_each_entry(ipaddr, &card->ip_list, entry) {
  699. if (ipaddr->proto != proto)
  700. continue;
  701. if (ipaddr->type != QETH_IP_TYPE_RXIP)
  702. continue;
  703. /* String must not be longer than PAGE_SIZE. So we check if
  704. * string length gets near PAGE_SIZE. Then we can savely display
  705. * the next IPv6 address (worst case, compared to IPv4) */
  706. if ((PAGE_SIZE - i) <= entry_len)
  707. break;
  708. qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
  709. addr_str);
  710. i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
  711. }
  712. spin_unlock_irqrestore(&card->ip_lock, flags);
  713. i += snprintf(buf + i, PAGE_SIZE - i, "\n");
  714. return i;
  715. }
  716. static ssize_t qeth_l3_dev_rxip_add4_show(struct device *dev,
  717. struct device_attribute *attr, char *buf)
  718. {
  719. struct qeth_card *card = dev_get_drvdata(dev);
  720. if (!card)
  721. return -EINVAL;
  722. return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV4);
  723. }
  724. static int qeth_l3_parse_rxipe(const char *buf, enum qeth_prot_versions proto,
  725. u8 *addr)
  726. {
  727. if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
  728. PRINT_WARN("Invalid IP address format!\n");
  729. return -EINVAL;
  730. }
  731. return 0;
  732. }
  733. static ssize_t qeth_l3_dev_rxip_add_store(const char *buf, size_t count,
  734. struct qeth_card *card, enum qeth_prot_versions proto)
  735. {
  736. u8 addr[16] = {0, };
  737. int rc;
  738. rc = qeth_l3_parse_rxipe(buf, proto, addr);
  739. if (rc)
  740. return rc;
  741. rc = qeth_l3_add_rxip(card, proto, addr);
  742. if (rc)
  743. return rc;
  744. return count;
  745. }
  746. static ssize_t qeth_l3_dev_rxip_add4_store(struct device *dev,
  747. struct device_attribute *attr, const char *buf, size_t count)
  748. {
  749. struct qeth_card *card = dev_get_drvdata(dev);
  750. if (!card)
  751. return -EINVAL;
  752. return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV4);
  753. }
  754. static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,
  755. qeth_l3_dev_rxip_add4_show,
  756. qeth_l3_dev_rxip_add4_store);
  757. static ssize_t qeth_l3_dev_rxip_del_store(const char *buf, size_t count,
  758. struct qeth_card *card, enum qeth_prot_versions proto)
  759. {
  760. u8 addr[16];
  761. int rc;
  762. rc = qeth_l3_parse_rxipe(buf, proto, addr);
  763. if (rc)
  764. return rc;
  765. qeth_l3_del_rxip(card, proto, addr);
  766. return count;
  767. }
  768. static ssize_t qeth_l3_dev_rxip_del4_store(struct device *dev,
  769. struct device_attribute *attr, const char *buf, size_t count)
  770. {
  771. struct qeth_card *card = dev_get_drvdata(dev);
  772. if (!card)
  773. return -EINVAL;
  774. return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV4);
  775. }
  776. static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,
  777. qeth_l3_dev_rxip_del4_store);
  778. static ssize_t qeth_l3_dev_rxip_add6_show(struct device *dev,
  779. struct device_attribute *attr, char *buf)
  780. {
  781. struct qeth_card *card = dev_get_drvdata(dev);
  782. if (!card)
  783. return -EINVAL;
  784. return qeth_l3_dev_rxip_add_show(buf, card, QETH_PROT_IPV6);
  785. }
  786. static ssize_t qeth_l3_dev_rxip_add6_store(struct device *dev,
  787. struct device_attribute *attr, const char *buf, size_t count)
  788. {
  789. struct qeth_card *card = dev_get_drvdata(dev);
  790. if (!card)
  791. return -EINVAL;
  792. return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV6);
  793. }
  794. static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
  795. qeth_l3_dev_rxip_add6_show,
  796. qeth_l3_dev_rxip_add6_store);
  797. static ssize_t qeth_l3_dev_rxip_del6_store(struct device *dev,
  798. struct device_attribute *attr, const char *buf, size_t count)
  799. {
  800. struct qeth_card *card = dev_get_drvdata(dev);
  801. if (!card)
  802. return -EINVAL;
  803. return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV6);
  804. }
  805. static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL,
  806. qeth_l3_dev_rxip_del6_store);
  807. static struct attribute *qeth_rxip_device_attrs[] = {
  808. &dev_attr_rxip_add4.attr,
  809. &dev_attr_rxip_del4.attr,
  810. &dev_attr_rxip_add6.attr,
  811. &dev_attr_rxip_del6.attr,
  812. NULL,
  813. };
  814. static struct attribute_group qeth_device_rxip_group = {
  815. .name = "rxip",
  816. .attrs = qeth_rxip_device_attrs,
  817. };
  818. int qeth_l3_create_device_attributes(struct device *dev)
  819. {
  820. int ret;
  821. ret = sysfs_create_group(&dev->kobj, &qeth_l3_device_attr_group);
  822. if (ret)
  823. return ret;
  824. ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group);
  825. if (ret) {
  826. sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
  827. return ret;
  828. }
  829. ret = sysfs_create_group(&dev->kobj, &qeth_device_vipa_group);
  830. if (ret) {
  831. sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
  832. sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
  833. return ret;
  834. }
  835. ret = sysfs_create_group(&dev->kobj, &qeth_device_rxip_group);
  836. if (ret) {
  837. sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
  838. sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
  839. sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
  840. return ret;
  841. }
  842. return 0;
  843. }
  844. void qeth_l3_remove_device_attributes(struct device *dev)
  845. {
  846. sysfs_remove_group(&dev->kobj, &qeth_l3_device_attr_group);
  847. sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
  848. sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
  849. sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);
  850. }