cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

qeth_l3_sys.c (21041B)


      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};