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