Linux Audio

Check our new training course

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