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