/*
*
- * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.33 $)
+ * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.49 $)
*
* Linux on zSeries OSA Express and HiperSockets support
* This file contains code related to sysfs.
#include "qeth_mpc.h"
#include "qeth_fs.h"
-const char *VERSION_QETH_SYS_C = "$Revision: 1.33 $";
+const char *VERSION_QETH_SYS_C = "$Revision: 1.49 $";
/*****************************************************************************/
/* */
struct qeth_card *card = dev->driver_data;
if (!card)
return -EINVAL;
-
- return sprintf(buf, "%s\n", card->info.if_name);
+ return sprintf(buf, "%s\n", QETH_CARD_IFNAME(card));
}
static DEVICE_ATTR(if_name, 0444, qeth_dev_if_name_show, NULL);
if (!qeth_is_supported(card, IPA_IPV6)){
PRINT_WARN("IPv6 not supported for interface %s.\n"
"Routing status no changed.\n",
- card->info.if_name);
+ QETH_CARD_IFNAME(card));
return -ENOTSUPP;
}
return -EPERM;
i = simple_strtoul(buf, &tmp, 16);
- if ((i == 0) || (i == 1))
- card->options.fake_ll = i;
- else {
+ if ((i != 0) && (i != 1)) {
PRINT_WARN("fake_ll: write 0 or 1 to this file!\n");
return -EINVAL;
}
+ card->options.fake_ll = i;
return count;
}
static DEVICE_ATTR(canonical_macaddr, 0644, qeth_dev_canonical_macaddr_show,
qeth_dev_canonical_macaddr_store);
+static ssize_t
+qeth_dev_layer2_show(struct device *dev, char *buf)
+{
+ struct qeth_card *card = dev->driver_data;
+
+ if (!card)
+ return -EINVAL;
+
+ return sprintf(buf, "%i\n", card->options.layer2 ? 1:0);
+}
+
+static ssize_t
+qeth_dev_layer2_store(struct device *dev, const char *buf, size_t count)
+{
+ struct qeth_card *card = dev->driver_data;
+ char *tmp;
+ int i;
+
+ if (!card)
+ return -EINVAL;
+
+ if (((card->state != CARD_STATE_DOWN) &&
+ (card->state != CARD_STATE_RECOVER)) ||
+ (card->info.type != QETH_CARD_TYPE_OSAE))
+ return -EPERM;
+
+ i = simple_strtoul(buf, &tmp, 16);
+ if ((i == 0) || (i == 1))
+ card->options.layer2 = i;
+ else {
+ PRINT_WARN("layer2: write 0 or 1 to this file!\n");
+ return -EINVAL;
+ }
+ return count;
+}
+
+static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
+ qeth_dev_layer2_store);
+
static struct device_attribute * qeth_device_attrs[] = {
&dev_attr_state,
&dev_attr_chpid,
&dev_attr_recover,
&dev_attr_broadcast_mode,
&dev_attr_canonical_macaddr,
+ &dev_attr_layer2,
NULL,
};
.store = _store, \
};
+int
+qeth_check_layer2(struct qeth_card *card)
+{
+ if (card->options.layer2)
+ return -EPERM;
+ return 0;
+}
+
+
static ssize_t
qeth_dev_ipato_enable_show(struct device *dev, char *buf)
{
if (!card)
return -EINVAL;
+ if (qeth_check_layer2(card))
+ return -EPERM;
return sprintf(buf, "%i\n", card->ipato.enabled? 1:0);
}
(card->state != CARD_STATE_RECOVER))
return -EPERM;
+ if (qeth_check_layer2(card))
+ return -EPERM;
+
tmp = strsep((char **) &buf, "\n");
if (!strcmp(tmp, "toggle")){
card->ipato.enabled = (card->ipato.enabled)? 0 : 1;
if (!card)
return -EINVAL;
+ if (qeth_check_layer2(card))
+ return -EPERM;
+
return sprintf(buf, "%i\n", card->ipato.invert4? 1:0);
}
if (!card)
return -EINVAL;
+ if (qeth_check_layer2(card))
+ return -EPERM;
+
tmp = strsep((char **) &buf, "\n");
if (!strcmp(tmp, "toggle")){
card->ipato.invert4 = (card->ipato.invert4)? 0 : 1;
{
struct qeth_ipato_entry *ipatoe;
unsigned long flags;
- char addr_str[49];
+ char addr_str[40];
+ int entry_len; /* length of 1 entry string, differs between v4 and v6 */
int i = 0;
+ if (qeth_check_layer2(card))
+ return -EPERM;
+
+ entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
+ /* add strlen for "/<mask>\n" */
+ entry_len += (proto == QETH_PROT_IPV4)? 5 : 6;
spin_lock_irqsave(&card->ip_lock, flags);
list_for_each_entry(ipatoe, &card->ipato.entries, entry){
if (ipatoe->proto != proto)
continue;
+ /* String must not be longer than PAGE_SIZE. So we check if
+ * string length gets near PAGE_SIZE. Then we can savely display
+ * the next IPv6 address (worst case, compared to IPv4) */
+ if ((PAGE_SIZE - i) <= entry_len)
+ break;
qeth_ipaddr_to_string(proto, ipatoe->addr, addr_str);
- i += sprintf(buf + i, "%s/%i\n", addr_str, ipatoe->mask_bits);
+ i += snprintf(buf + i, PAGE_SIZE - i,
+ "%s/%i\n", addr_str, ipatoe->mask_bits);
}
spin_unlock_irqrestore(&card->ip_lock, flags);
- i += sprintf(buf + i, "\n");
+ i += snprintf(buf + i, PAGE_SIZE - i, "\n");
return i;
}
int mask_bits;
int rc;
+ if (qeth_check_layer2(card))
+ return -EPERM;
if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits)))
return rc;
int mask_bits;
int rc;
+ if (qeth_check_layer2(card))
+ return -EPERM;
if ((rc = qeth_parse_ipatoe(buf, proto, addr, &mask_bits)))
return rc;
if (!card)
return -EINVAL;
+ if (qeth_check_layer2(card))
+ return -EPERM;
+
return sprintf(buf, "%i\n", card->ipato.invert6? 1:0);
}
if (!card)
return -EINVAL;
+ if (qeth_check_layer2(card))
+ return -EPERM;
+
tmp = strsep((char **) &buf, "\n");
if (!strcmp(tmp, "toggle")){
card->ipato.invert6 = (card->ipato.invert6)? 0 : 1;
enum qeth_prot_versions proto)
{
struct qeth_ipaddr *ipaddr;
- char addr_str[49];
+ char addr_str[40];
+ int entry_len; /* length of 1 entry string, differs between v4 and v6 */
unsigned long flags;
int i = 0;
+ if (qeth_check_layer2(card))
+ return -EPERM;
+
+ entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
+ entry_len += 2; /* \n + terminator */
spin_lock_irqsave(&card->ip_lock, flags);
list_for_each_entry(ipaddr, &card->ip_list, entry){
if (ipaddr->proto != proto)
continue;
if (ipaddr->type != QETH_IP_TYPE_VIPA)
continue;
+ /* String must not be longer than PAGE_SIZE. So we check if
+ * string length gets near PAGE_SIZE. Then we can savely display
+ * the next IPv6 address (worst case, compared to IPv4) */
+ if ((PAGE_SIZE - i) <= entry_len)
+ break;
qeth_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, addr_str);
- i += sprintf(buf + i, "%s\n", addr_str);
+ i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
}
spin_unlock_irqrestore(&card->ip_lock, flags);
- i += sprintf(buf + i, "\n");
+ i += snprintf(buf + i, PAGE_SIZE - i, "\n");
return i;
}
u8 addr[16] = {0, };
int rc;
+ if (qeth_check_layer2(card))
+ return -EPERM;
if ((rc = qeth_parse_vipae(buf, proto, addr)))
return rc;
u8 addr[16];
int rc;
+ if (qeth_check_layer2(card))
+ return -EPERM;
if ((rc = qeth_parse_vipae(buf, proto, addr)))
return rc;
if (!card)
return -EINVAL;
+ if (qeth_check_layer2(card))
+ return -EPERM;
+
return qeth_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6);
}
enum qeth_prot_versions proto)
{
struct qeth_ipaddr *ipaddr;
- char addr_str[49];
+ char addr_str[40];
+ int entry_len; /* length of 1 entry string, differs between v4 and v6 */
unsigned long flags;
int i = 0;
+ if (qeth_check_layer2(card))
+ return -EPERM;
+
+ entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
+ entry_len += 2; /* \n + terminator */
spin_lock_irqsave(&card->ip_lock, flags);
list_for_each_entry(ipaddr, &card->ip_list, entry){
if (ipaddr->proto != proto)
continue;
if (ipaddr->type != QETH_IP_TYPE_RXIP)
continue;
+ /* String must not be longer than PAGE_SIZE. So we check if
+ * string length gets near PAGE_SIZE. Then we can savely display
+ * the next IPv6 address (worst case, compared to IPv4) */
+ if ((PAGE_SIZE - i) <= entry_len)
+ break;
qeth_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, addr_str);
- i += sprintf(buf + i, "%s\n", addr_str);
+ i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str);
}
spin_unlock_irqrestore(&card->ip_lock, flags);
- i += sprintf(buf + i, "\n");
+ i += snprintf(buf + i, PAGE_SIZE - i, "\n");
return i;
}
u8 addr[16] = {0, };
int rc;
+ if (qeth_check_layer2(card))
+ return -EPERM;
if ((rc = qeth_parse_rxipe(buf, proto, addr)))
return rc;
u8 addr[16];
int rc;
+ if (qeth_check_layer2(card))
+ return -EPERM;
if ((rc = qeth_parse_rxipe(buf, proto, addr)))
return rc;