linux/net/tipc/bearer.c
<<
>>
Prefs
   1/*
   2 * net/tipc/bearer.c: TIPC bearer code
   3 *
   4 * Copyright (c) 1996-2006, 2013-2014, Ericsson AB
   5 * Copyright (c) 2004-2006, 2010-2013, Wind River Systems
   6 * All rights reserved.
   7 *
   8 * Redistribution and use in source and binary forms, with or without
   9 * modification, are permitted provided that the following conditions are met:
  10 *
  11 * 1. Redistributions of source code must retain the above copyright
  12 *    notice, this list of conditions and the following disclaimer.
  13 * 2. Redistributions in binary form must reproduce the above copyright
  14 *    notice, this list of conditions and the following disclaimer in the
  15 *    documentation and/or other materials provided with the distribution.
  16 * 3. Neither the names of the copyright holders nor the names of its
  17 *    contributors may be used to endorse or promote products derived from
  18 *    this software without specific prior written permission.
  19 *
  20 * Alternatively, this software may be distributed under the terms of the
  21 * GNU General Public License ("GPL") version 2 as published by the Free
  22 * Software Foundation.
  23 *
  24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  34 * POSSIBILITY OF SUCH DAMAGE.
  35 */
  36
  37#include <net/sock.h>
  38#include "core.h"
  39#include "bearer.h"
  40#include "link.h"
  41#include "discover.h"
  42#include "bcast.h"
  43#include "netlink.h"
  44
  45#define MAX_ADDR_STR 60
  46
  47static struct tipc_media * const media_info_array[] = {
  48        &eth_media_info,
  49#ifdef CONFIG_TIPC_MEDIA_IB
  50        &ib_media_info,
  51#endif
  52#ifdef CONFIG_TIPC_MEDIA_UDP
  53        &udp_media_info,
  54#endif
  55        NULL
  56};
  57
  58static void bearer_disable(struct net *net, struct tipc_bearer *b);
  59
  60/**
  61 * tipc_media_find - locates specified media object by name
  62 */
  63struct tipc_media *tipc_media_find(const char *name)
  64{
  65        u32 i;
  66
  67        for (i = 0; media_info_array[i] != NULL; i++) {
  68                if (!strcmp(media_info_array[i]->name, name))
  69                        break;
  70        }
  71        return media_info_array[i];
  72}
  73
  74/**
  75 * media_find_id - locates specified media object by type identifier
  76 */
  77static struct tipc_media *media_find_id(u8 type)
  78{
  79        u32 i;
  80
  81        for (i = 0; media_info_array[i] != NULL; i++) {
  82                if (media_info_array[i]->type_id == type)
  83                        break;
  84        }
  85        return media_info_array[i];
  86}
  87
  88/**
  89 * tipc_media_addr_printf - record media address in print buffer
  90 */
  91void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a)
  92{
  93        char addr_str[MAX_ADDR_STR];
  94        struct tipc_media *m;
  95        int ret;
  96
  97        m = media_find_id(a->media_id);
  98
  99        if (m && !m->addr2str(a, addr_str, sizeof(addr_str)))
 100                ret = scnprintf(buf, len, "%s(%s)", m->name, addr_str);
 101        else {
 102                u32 i;
 103
 104                ret = scnprintf(buf, len, "UNKNOWN(%u)", a->media_id);
 105                for (i = 0; i < sizeof(a->value); i++)
 106                        ret += scnprintf(buf - ret, len + ret,
 107                                            "-%02x", a->value[i]);
 108        }
 109}
 110
 111/**
 112 * bearer_name_validate - validate & (optionally) deconstruct bearer name
 113 * @name: ptr to bearer name string
 114 * @name_parts: ptr to area for bearer name components (or NULL if not needed)
 115 *
 116 * Returns 1 if bearer name is valid, otherwise 0.
 117 */
 118static int bearer_name_validate(const char *name,
 119                                struct tipc_bearer_names *name_parts)
 120{
 121        char name_copy[TIPC_MAX_BEARER_NAME];
 122        char *media_name;
 123        char *if_name;
 124        u32 media_len;
 125        u32 if_len;
 126
 127        /* copy bearer name & ensure length is OK */
 128        name_copy[TIPC_MAX_BEARER_NAME - 1] = 0;
 129        /* need above in case non-Posix strncpy() doesn't pad with nulls */
 130        strncpy(name_copy, name, TIPC_MAX_BEARER_NAME);
 131        if (name_copy[TIPC_MAX_BEARER_NAME - 1] != 0)
 132                return 0;
 133
 134        /* ensure all component parts of bearer name are present */
 135        media_name = name_copy;
 136        if_name = strchr(media_name, ':');
 137        if (if_name == NULL)
 138                return 0;
 139        *(if_name++) = 0;
 140        media_len = if_name - media_name;
 141        if_len = strlen(if_name) + 1;
 142
 143        /* validate component parts of bearer name */
 144        if ((media_len <= 1) || (media_len > TIPC_MAX_MEDIA_NAME) ||
 145            (if_len <= 1) || (if_len > TIPC_MAX_IF_NAME))
 146                return 0;
 147
 148        /* return bearer name components, if necessary */
 149        if (name_parts) {
 150                strcpy(name_parts->media_name, media_name);
 151                strcpy(name_parts->if_name, if_name);
 152        }
 153        return 1;
 154}
 155
 156/**
 157 * tipc_bearer_find - locates bearer object with matching bearer name
 158 */
 159struct tipc_bearer *tipc_bearer_find(struct net *net, const char *name)
 160{
 161        struct tipc_net *tn = net_generic(net, tipc_net_id);
 162        struct tipc_bearer *b;
 163        u32 i;
 164
 165        for (i = 0; i < MAX_BEARERS; i++) {
 166                b = rtnl_dereference(tn->bearer_list[i]);
 167                if (b && (!strcmp(b->name, name)))
 168                        return b;
 169        }
 170        return NULL;
 171}
 172
 173void tipc_bearer_add_dest(struct net *net, u32 bearer_id, u32 dest)
 174{
 175        struct tipc_net *tn = net_generic(net, tipc_net_id);
 176        struct tipc_bearer *b;
 177
 178        rcu_read_lock();
 179        b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]);
 180        if (b)
 181                tipc_disc_add_dest(b->link_req);
 182        rcu_read_unlock();
 183}
 184
 185void tipc_bearer_remove_dest(struct net *net, u32 bearer_id, u32 dest)
 186{
 187        struct tipc_net *tn = net_generic(net, tipc_net_id);
 188        struct tipc_bearer *b;
 189
 190        rcu_read_lock();
 191        b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]);
 192        if (b)
 193                tipc_disc_remove_dest(b->link_req);
 194        rcu_read_unlock();
 195}
 196
 197/**
 198 * tipc_enable_bearer - enable bearer with the given name
 199 */
 200static int tipc_enable_bearer(struct net *net, const char *name,
 201                              u32 disc_domain, u32 priority,
 202                              struct nlattr *attr[])
 203{
 204        struct tipc_net *tn = net_generic(net, tipc_net_id);
 205        struct tipc_bearer *b;
 206        struct tipc_media *m;
 207        struct tipc_bearer_names b_names;
 208        char addr_string[16];
 209        u32 bearer_id;
 210        u32 with_this_prio;
 211        u32 i;
 212        int res = -EINVAL;
 213
 214        if (!tn->own_addr) {
 215                pr_warn("Bearer <%s> rejected, not supported in standalone mode\n",
 216                        name);
 217                return -ENOPROTOOPT;
 218        }
 219        if (!bearer_name_validate(name, &b_names)) {
 220                pr_warn("Bearer <%s> rejected, illegal name\n", name);
 221                return -EINVAL;
 222        }
 223        if (tipc_addr_domain_valid(disc_domain) &&
 224            (disc_domain != tn->own_addr)) {
 225                if (tipc_in_scope(disc_domain, tn->own_addr)) {
 226                        disc_domain = tn->own_addr & TIPC_CLUSTER_MASK;
 227                        res = 0;   /* accept any node in own cluster */
 228                } else if (in_own_cluster_exact(net, disc_domain))
 229                        res = 0;   /* accept specified node in own cluster */
 230        }
 231        if (res) {
 232                pr_warn("Bearer <%s> rejected, illegal discovery domain\n",
 233                        name);
 234                return -EINVAL;
 235        }
 236        if ((priority > TIPC_MAX_LINK_PRI) &&
 237            (priority != TIPC_MEDIA_LINK_PRI)) {
 238                pr_warn("Bearer <%s> rejected, illegal priority\n", name);
 239                return -EINVAL;
 240        }
 241
 242        m = tipc_media_find(b_names.media_name);
 243        if (!m) {
 244                pr_warn("Bearer <%s> rejected, media <%s> not registered\n",
 245                        name, b_names.media_name);
 246                return -EINVAL;
 247        }
 248
 249        if (priority == TIPC_MEDIA_LINK_PRI)
 250                priority = m->priority;
 251
 252restart:
 253        bearer_id = MAX_BEARERS;
 254        with_this_prio = 1;
 255        for (i = MAX_BEARERS; i-- != 0; ) {
 256                b = rtnl_dereference(tn->bearer_list[i]);
 257                if (!b) {
 258                        bearer_id = i;
 259                        continue;
 260                }
 261                if (!strcmp(name, b->name)) {
 262                        pr_warn("Bearer <%s> rejected, already enabled\n",
 263                                name);
 264                        return -EINVAL;
 265                }
 266                if ((b->priority == priority) &&
 267                    (++with_this_prio > 2)) {
 268                        if (priority-- == 0) {
 269                                pr_warn("Bearer <%s> rejected, duplicate priority\n",
 270                                        name);
 271                                return -EINVAL;
 272                        }
 273                        pr_warn("Bearer <%s> priority adjustment required %u->%u\n",
 274                                name, priority + 1, priority);
 275                        goto restart;
 276                }
 277        }
 278        if (bearer_id >= MAX_BEARERS) {
 279                pr_warn("Bearer <%s> rejected, bearer limit reached (%u)\n",
 280                        name, MAX_BEARERS);
 281                return -EINVAL;
 282        }
 283
 284        b = kzalloc(sizeof(*b), GFP_ATOMIC);
 285        if (!b)
 286                return -ENOMEM;
 287
 288        strcpy(b->name, name);
 289        b->media = m;
 290        res = m->enable_media(net, b, attr);
 291        if (res) {
 292                pr_warn("Bearer <%s> rejected, enable failure (%d)\n",
 293                        name, -res);
 294                return -EINVAL;
 295        }
 296
 297        b->identity = bearer_id;
 298        b->tolerance = m->tolerance;
 299        b->window = m->window;
 300        b->domain = disc_domain;
 301        b->net_plane = bearer_id + 'A';
 302        b->priority = priority;
 303
 304        res = tipc_disc_create(net, b, &b->bcast_addr);
 305        if (res) {
 306                bearer_disable(net, b);
 307                pr_warn("Bearer <%s> rejected, discovery object creation failed\n",
 308                        name);
 309                return -EINVAL;
 310        }
 311
 312        rcu_assign_pointer(tn->bearer_list[bearer_id], b);
 313
 314        pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n",
 315                name,
 316                tipc_addr_string_fill(addr_string, disc_domain), priority);
 317        return res;
 318}
 319
 320/**
 321 * tipc_reset_bearer - Reset all links established over this bearer
 322 */
 323static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b)
 324{
 325        pr_info("Resetting bearer <%s>\n", b->name);
 326        tipc_node_delete_links(net, b->identity);
 327        tipc_disc_reset(net, b);
 328        return 0;
 329}
 330
 331/**
 332 * bearer_disable
 333 *
 334 * Note: This routine assumes caller holds RTNL lock.
 335 */
 336static void bearer_disable(struct net *net, struct tipc_bearer *b)
 337{
 338        struct tipc_net *tn = net_generic(net, tipc_net_id);
 339        u32 i;
 340
 341        pr_info("Disabling bearer <%s>\n", b->name);
 342        b->media->disable_media(b);
 343
 344        tipc_node_delete_links(net, b->identity);
 345        RCU_INIT_POINTER(b->media_ptr, NULL);
 346        if (b->link_req)
 347                tipc_disc_delete(b->link_req);
 348
 349        for (i = 0; i < MAX_BEARERS; i++) {
 350                if (b == rtnl_dereference(tn->bearer_list[i])) {
 351                        RCU_INIT_POINTER(tn->bearer_list[i], NULL);
 352                        break;
 353                }
 354        }
 355        kfree_rcu(b, rcu);
 356}
 357
 358int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b,
 359                         struct nlattr *attr[])
 360{
 361        struct net_device *dev;
 362        char *driver_name = strchr((const char *)b->name, ':') + 1;
 363
 364        /* Find device with specified name */
 365        dev = dev_get_by_name(net, driver_name);
 366        if (!dev)
 367                return -ENODEV;
 368
 369        /* Associate TIPC bearer with L2 bearer */
 370        rcu_assign_pointer(b->media_ptr, dev);
 371        memset(&b->bcast_addr, 0, sizeof(b->bcast_addr));
 372        memcpy(b->bcast_addr.value, dev->broadcast, b->media->hwaddr_len);
 373        b->bcast_addr.media_id = b->media->type_id;
 374        b->bcast_addr.broadcast = 1;
 375        b->mtu = dev->mtu;
 376        b->media->raw2addr(b, &b->addr, (char *)dev->dev_addr);
 377        rcu_assign_pointer(dev->tipc_ptr, b);
 378        return 0;
 379}
 380
 381/* tipc_disable_l2_media - detach TIPC bearer from an L2 interface
 382 *
 383 * Mark L2 bearer as inactive so that incoming buffers are thrown away
 384 */
 385void tipc_disable_l2_media(struct tipc_bearer *b)
 386{
 387        struct net_device *dev;
 388
 389        dev = (struct net_device *)rtnl_dereference(b->media_ptr);
 390        RCU_INIT_POINTER(dev->tipc_ptr, NULL);
 391        synchronize_net();
 392        dev_put(dev);
 393}
 394
 395/**
 396 * tipc_l2_send_msg - send a TIPC packet out over an L2 interface
 397 * @buf: the packet to be sent
 398 * @b: the bearer through which the packet is to be sent
 399 * @dest: peer destination address
 400 */
 401int tipc_l2_send_msg(struct net *net, struct sk_buff *skb,
 402                     struct tipc_bearer *b, struct tipc_media_addr *dest)
 403{
 404        struct net_device *dev;
 405        int delta;
 406
 407        dev = (struct net_device *)rcu_dereference_rtnl(b->media_ptr);
 408        if (!dev)
 409                return 0;
 410
 411        delta = dev->hard_header_len - skb_headroom(skb);
 412        if ((delta > 0) &&
 413            pskb_expand_head(skb, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) {
 414                kfree_skb(skb);
 415                return 0;
 416        }
 417
 418        skb_reset_network_header(skb);
 419        skb->dev = dev;
 420        skb->protocol = htons(ETH_P_TIPC);
 421        dev_hard_header(skb, dev, ETH_P_TIPC, dest->value,
 422                        dev->dev_addr, skb->len);
 423        dev_queue_xmit(skb);
 424        return 0;
 425}
 426
 427int tipc_bearer_mtu(struct net *net, u32 bearer_id)
 428{
 429        int mtu = 0;
 430        struct tipc_bearer *b;
 431
 432        rcu_read_lock();
 433        b = rcu_dereference_rtnl(tipc_net(net)->bearer_list[bearer_id]);
 434        if (b)
 435                mtu = b->mtu;
 436        rcu_read_unlock();
 437        return mtu;
 438}
 439
 440/* tipc_bearer_xmit_skb - sends buffer to destination over bearer
 441 */
 442void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id,
 443                          struct sk_buff *skb,
 444                          struct tipc_media_addr *dest)
 445{
 446        struct tipc_net *tn = tipc_net(net);
 447        struct tipc_bearer *b;
 448
 449        rcu_read_lock();
 450        b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]);
 451        if (likely(b))
 452                b->media->send_msg(net, skb, b, dest);
 453        rcu_read_unlock();
 454}
 455
 456/* tipc_bearer_xmit() -send buffer to destination over bearer
 457 */
 458void tipc_bearer_xmit(struct net *net, u32 bearer_id,
 459                      struct sk_buff_head *xmitq,
 460                      struct tipc_media_addr *dst)
 461{
 462        struct tipc_net *tn = net_generic(net, tipc_net_id);
 463        struct tipc_bearer *b;
 464        struct sk_buff *skb, *tmp;
 465
 466        if (skb_queue_empty(xmitq))
 467                return;
 468
 469        rcu_read_lock();
 470        b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]);
 471        if (likely(b)) {
 472                skb_queue_walk_safe(xmitq, skb, tmp) {
 473                        __skb_dequeue(xmitq);
 474                        b->media->send_msg(net, skb, b, dst);
 475                }
 476        }
 477        rcu_read_unlock();
 478}
 479
 480/* tipc_bearer_bc_xmit() - broadcast buffers to all destinations
 481 */
 482void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id,
 483                         struct sk_buff_head *xmitq)
 484{
 485        struct tipc_net *tn = tipc_net(net);
 486        int net_id = tn->net_id;
 487        struct tipc_bearer *b;
 488        struct sk_buff *skb, *tmp;
 489        struct tipc_msg *hdr;
 490
 491        rcu_read_lock();
 492        b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]);
 493        if (likely(b)) {
 494                skb_queue_walk_safe(xmitq, skb, tmp) {
 495                        hdr = buf_msg(skb);
 496                        msg_set_non_seq(hdr, 1);
 497                        msg_set_mc_netid(hdr, net_id);
 498                        __skb_dequeue(xmitq);
 499                        b->media->send_msg(net, skb, b, &b->bcast_addr);
 500                }
 501        }
 502        rcu_read_unlock();
 503}
 504
 505/**
 506 * tipc_l2_rcv_msg - handle incoming TIPC message from an interface
 507 * @buf: the received packet
 508 * @dev: the net device that the packet was received on
 509 * @pt: the packet_type structure which was used to register this handler
 510 * @orig_dev: the original receive net device in case the device is a bond
 511 *
 512 * Accept only packets explicitly sent to this node, or broadcast packets;
 513 * ignores packets sent using interface multicast, and traffic sent to other
 514 * nodes (which can happen if interface is running in promiscuous mode).
 515 */
 516static int tipc_l2_rcv_msg(struct sk_buff *buf, struct net_device *dev,
 517                           struct packet_type *pt, struct net_device *orig_dev)
 518{
 519        struct tipc_bearer *b;
 520
 521        rcu_read_lock();
 522        b = rcu_dereference_rtnl(dev->tipc_ptr);
 523        if (likely(b)) {
 524                if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
 525                        buf->next = NULL;
 526                        tipc_rcv(dev_net(dev), buf, b);
 527                        rcu_read_unlock();
 528                        return NET_RX_SUCCESS;
 529                }
 530        }
 531        rcu_read_unlock();
 532
 533        kfree_skb(buf);
 534        return NET_RX_DROP;
 535}
 536
 537/**
 538 * tipc_l2_device_event - handle device events from network device
 539 * @nb: the context of the notification
 540 * @evt: the type of event
 541 * @ptr: the net device that the event was on
 542 *
 543 * This function is called by the Ethernet driver in case of link
 544 * change event.
 545 */
 546static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
 547                                void *ptr)
 548{
 549        struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 550        struct net *net = dev_net(dev);
 551        struct tipc_bearer *b;
 552
 553        b = rtnl_dereference(dev->tipc_ptr);
 554        if (!b)
 555                return NOTIFY_DONE;
 556
 557        b->mtu = dev->mtu;
 558
 559        switch (evt) {
 560        case NETDEV_CHANGE:
 561                if (netif_carrier_ok(dev))
 562                        break;
 563        case NETDEV_GOING_DOWN:
 564        case NETDEV_CHANGEMTU:
 565                tipc_reset_bearer(net, b);
 566                break;
 567        case NETDEV_CHANGEADDR:
 568                b->media->raw2addr(b, &b->addr,
 569                                       (char *)dev->dev_addr);
 570                tipc_reset_bearer(net, b);
 571                break;
 572        case NETDEV_UNREGISTER:
 573        case NETDEV_CHANGENAME:
 574                bearer_disable(dev_net(dev), b);
 575                break;
 576        }
 577        return NOTIFY_OK;
 578}
 579
 580static struct packet_type tipc_packet_type __read_mostly = {
 581        .type = htons(ETH_P_TIPC),
 582        .func = tipc_l2_rcv_msg,
 583};
 584
 585static struct notifier_block notifier = {
 586        .notifier_call  = tipc_l2_device_event,
 587        .priority       = 0,
 588};
 589
 590int tipc_bearer_setup(void)
 591{
 592        int err;
 593
 594        err = register_netdevice_notifier(&notifier);
 595        if (err)
 596                return err;
 597        dev_add_pack(&tipc_packet_type);
 598        return 0;
 599}
 600
 601void tipc_bearer_cleanup(void)
 602{
 603        unregister_netdevice_notifier(&notifier);
 604        dev_remove_pack(&tipc_packet_type);
 605}
 606
 607void tipc_bearer_stop(struct net *net)
 608{
 609        struct tipc_net *tn = net_generic(net, tipc_net_id);
 610        struct tipc_bearer *b;
 611        u32 i;
 612
 613        for (i = 0; i < MAX_BEARERS; i++) {
 614                b = rtnl_dereference(tn->bearer_list[i]);
 615                if (b) {
 616                        bearer_disable(net, b);
 617                        tn->bearer_list[i] = NULL;
 618                }
 619        }
 620}
 621
 622/* Caller should hold rtnl_lock to protect the bearer */
 623static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg,
 624                                struct tipc_bearer *bearer, int nlflags)
 625{
 626        void *hdr;
 627        struct nlattr *attrs;
 628        struct nlattr *prop;
 629
 630        hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
 631                          nlflags, TIPC_NL_BEARER_GET);
 632        if (!hdr)
 633                return -EMSGSIZE;
 634
 635        attrs = nla_nest_start(msg->skb, TIPC_NLA_BEARER);
 636        if (!attrs)
 637                goto msg_full;
 638
 639        if (nla_put_string(msg->skb, TIPC_NLA_BEARER_NAME, bearer->name))
 640                goto attr_msg_full;
 641
 642        prop = nla_nest_start(msg->skb, TIPC_NLA_BEARER_PROP);
 643        if (!prop)
 644                goto prop_msg_full;
 645        if (nla_put_u32(msg->skb, TIPC_NLA_PROP_PRIO, bearer->priority))
 646                goto prop_msg_full;
 647        if (nla_put_u32(msg->skb, TIPC_NLA_PROP_TOL, bearer->tolerance))
 648                goto prop_msg_full;
 649        if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bearer->window))
 650                goto prop_msg_full;
 651
 652        nla_nest_end(msg->skb, prop);
 653        nla_nest_end(msg->skb, attrs);
 654        genlmsg_end(msg->skb, hdr);
 655
 656        return 0;
 657
 658prop_msg_full:
 659        nla_nest_cancel(msg->skb, prop);
 660attr_msg_full:
 661        nla_nest_cancel(msg->skb, attrs);
 662msg_full:
 663        genlmsg_cancel(msg->skb, hdr);
 664
 665        return -EMSGSIZE;
 666}
 667
 668int tipc_nl_bearer_dump(struct sk_buff *skb, struct netlink_callback *cb)
 669{
 670        int err;
 671        int i = cb->args[0];
 672        struct tipc_bearer *bearer;
 673        struct tipc_nl_msg msg;
 674        struct net *net = sock_net(skb->sk);
 675        struct tipc_net *tn = net_generic(net, tipc_net_id);
 676
 677        if (i == MAX_BEARERS)
 678                return 0;
 679
 680        msg.skb = skb;
 681        msg.portid = NETLINK_CB(cb->skb).portid;
 682        msg.seq = cb->nlh->nlmsg_seq;
 683
 684        rtnl_lock();
 685        for (i = 0; i < MAX_BEARERS; i++) {
 686                bearer = rtnl_dereference(tn->bearer_list[i]);
 687                if (!bearer)
 688                        continue;
 689
 690                err = __tipc_nl_add_bearer(&msg, bearer, NLM_F_MULTI);
 691                if (err)
 692                        break;
 693        }
 694        rtnl_unlock();
 695
 696        cb->args[0] = i;
 697        return skb->len;
 698}
 699
 700int tipc_nl_bearer_get(struct sk_buff *skb, struct genl_info *info)
 701{
 702        int err;
 703        char *name;
 704        struct sk_buff *rep;
 705        struct tipc_bearer *bearer;
 706        struct tipc_nl_msg msg;
 707        struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
 708        struct net *net = genl_info_net(info);
 709
 710        if (!info->attrs[TIPC_NLA_BEARER])
 711                return -EINVAL;
 712
 713        err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
 714                               info->attrs[TIPC_NLA_BEARER],
 715                               tipc_nl_bearer_policy);
 716        if (err)
 717                return err;
 718
 719        if (!attrs[TIPC_NLA_BEARER_NAME])
 720                return -EINVAL;
 721        name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
 722
 723        rep = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
 724        if (!rep)
 725                return -ENOMEM;
 726
 727        msg.skb = rep;
 728        msg.portid = info->snd_portid;
 729        msg.seq = info->snd_seq;
 730
 731        rtnl_lock();
 732        bearer = tipc_bearer_find(net, name);
 733        if (!bearer) {
 734                err = -EINVAL;
 735                goto err_out;
 736        }
 737
 738        err = __tipc_nl_add_bearer(&msg, bearer, 0);
 739        if (err)
 740                goto err_out;
 741        rtnl_unlock();
 742
 743        return genlmsg_reply(rep, info);
 744err_out:
 745        rtnl_unlock();
 746        nlmsg_free(rep);
 747
 748        return err;
 749}
 750
 751int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info)
 752{
 753        int err;
 754        char *name;
 755        struct tipc_bearer *bearer;
 756        struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
 757        struct net *net = sock_net(skb->sk);
 758
 759        if (!info->attrs[TIPC_NLA_BEARER])
 760                return -EINVAL;
 761
 762        err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
 763                               info->attrs[TIPC_NLA_BEARER],
 764                               tipc_nl_bearer_policy);
 765        if (err)
 766                return err;
 767
 768        if (!attrs[TIPC_NLA_BEARER_NAME])
 769                return -EINVAL;
 770
 771        name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
 772
 773        rtnl_lock();
 774        bearer = tipc_bearer_find(net, name);
 775        if (!bearer) {
 776                rtnl_unlock();
 777                return -EINVAL;
 778        }
 779
 780        bearer_disable(net, bearer);
 781        rtnl_unlock();
 782
 783        return 0;
 784}
 785
 786int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info)
 787{
 788        int err;
 789        char *bearer;
 790        struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
 791        struct net *net = sock_net(skb->sk);
 792        struct tipc_net *tn = net_generic(net, tipc_net_id);
 793        u32 domain;
 794        u32 prio;
 795
 796        prio = TIPC_MEDIA_LINK_PRI;
 797        domain = tn->own_addr & TIPC_CLUSTER_MASK;
 798
 799        if (!info->attrs[TIPC_NLA_BEARER])
 800                return -EINVAL;
 801
 802        err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
 803                               info->attrs[TIPC_NLA_BEARER],
 804                               tipc_nl_bearer_policy);
 805        if (err)
 806                return err;
 807
 808        if (!attrs[TIPC_NLA_BEARER_NAME])
 809                return -EINVAL;
 810
 811        bearer = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
 812
 813        if (attrs[TIPC_NLA_BEARER_DOMAIN])
 814                domain = nla_get_u32(attrs[TIPC_NLA_BEARER_DOMAIN]);
 815
 816        if (attrs[TIPC_NLA_BEARER_PROP]) {
 817                struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
 818
 819                err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_BEARER_PROP],
 820                                              props);
 821                if (err)
 822                        return err;
 823
 824                if (props[TIPC_NLA_PROP_PRIO])
 825                        prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
 826        }
 827
 828        rtnl_lock();
 829        err = tipc_enable_bearer(net, bearer, domain, prio, attrs);
 830        if (err) {
 831                rtnl_unlock();
 832                return err;
 833        }
 834        rtnl_unlock();
 835
 836        return 0;
 837}
 838
 839int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info)
 840{
 841        int err;
 842        char *name;
 843        struct tipc_bearer *b;
 844        struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
 845        struct net *net = sock_net(skb->sk);
 846
 847        if (!info->attrs[TIPC_NLA_BEARER])
 848                return -EINVAL;
 849
 850        err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
 851                               info->attrs[TIPC_NLA_BEARER],
 852                               tipc_nl_bearer_policy);
 853        if (err)
 854                return err;
 855
 856        if (!attrs[TIPC_NLA_BEARER_NAME])
 857                return -EINVAL;
 858        name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
 859
 860        rtnl_lock();
 861        b = tipc_bearer_find(net, name);
 862        if (!b) {
 863                rtnl_unlock();
 864                return -EINVAL;
 865        }
 866
 867        if (attrs[TIPC_NLA_BEARER_PROP]) {
 868                struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
 869
 870                err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_BEARER_PROP],
 871                                              props);
 872                if (err) {
 873                        rtnl_unlock();
 874                        return err;
 875                }
 876
 877                if (props[TIPC_NLA_PROP_TOL])
 878                        b->tolerance = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
 879                if (props[TIPC_NLA_PROP_PRIO])
 880                        b->priority = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
 881                if (props[TIPC_NLA_PROP_WIN])
 882                        b->window = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
 883        }
 884        rtnl_unlock();
 885
 886        return 0;
 887}
 888
 889static int __tipc_nl_add_media(struct tipc_nl_msg *msg,
 890                               struct tipc_media *media, int nlflags)
 891{
 892        void *hdr;
 893        struct nlattr *attrs;
 894        struct nlattr *prop;
 895
 896        hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
 897                          nlflags, TIPC_NL_MEDIA_GET);
 898        if (!hdr)
 899                return -EMSGSIZE;
 900
 901        attrs = nla_nest_start(msg->skb, TIPC_NLA_MEDIA);
 902        if (!attrs)
 903                goto msg_full;
 904
 905        if (nla_put_string(msg->skb, TIPC_NLA_MEDIA_NAME, media->name))
 906                goto attr_msg_full;
 907
 908        prop = nla_nest_start(msg->skb, TIPC_NLA_MEDIA_PROP);
 909        if (!prop)
 910                goto prop_msg_full;
 911        if (nla_put_u32(msg->skb, TIPC_NLA_PROP_PRIO, media->priority))
 912                goto prop_msg_full;
 913        if (nla_put_u32(msg->skb, TIPC_NLA_PROP_TOL, media->tolerance))
 914                goto prop_msg_full;
 915        if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, media->window))
 916                goto prop_msg_full;
 917
 918        nla_nest_end(msg->skb, prop);
 919        nla_nest_end(msg->skb, attrs);
 920        genlmsg_end(msg->skb, hdr);
 921
 922        return 0;
 923
 924prop_msg_full:
 925        nla_nest_cancel(msg->skb, prop);
 926attr_msg_full:
 927        nla_nest_cancel(msg->skb, attrs);
 928msg_full:
 929        genlmsg_cancel(msg->skb, hdr);
 930
 931        return -EMSGSIZE;
 932}
 933
 934int tipc_nl_media_dump(struct sk_buff *skb, struct netlink_callback *cb)
 935{
 936        int err;
 937        int i = cb->args[0];
 938        struct tipc_nl_msg msg;
 939
 940        if (i == MAX_MEDIA)
 941                return 0;
 942
 943        msg.skb = skb;
 944        msg.portid = NETLINK_CB(cb->skb).portid;
 945        msg.seq = cb->nlh->nlmsg_seq;
 946
 947        rtnl_lock();
 948        for (; media_info_array[i] != NULL; i++) {
 949                err = __tipc_nl_add_media(&msg, media_info_array[i],
 950                                          NLM_F_MULTI);
 951                if (err)
 952                        break;
 953        }
 954        rtnl_unlock();
 955
 956        cb->args[0] = i;
 957        return skb->len;
 958}
 959
 960int tipc_nl_media_get(struct sk_buff *skb, struct genl_info *info)
 961{
 962        int err;
 963        char *name;
 964        struct tipc_nl_msg msg;
 965        struct tipc_media *media;
 966        struct sk_buff *rep;
 967        struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
 968
 969        if (!info->attrs[TIPC_NLA_MEDIA])
 970                return -EINVAL;
 971
 972        err = nla_parse_nested(attrs, TIPC_NLA_MEDIA_MAX,
 973                               info->attrs[TIPC_NLA_MEDIA],
 974                               tipc_nl_media_policy);
 975        if (err)
 976                return err;
 977
 978        if (!attrs[TIPC_NLA_MEDIA_NAME])
 979                return -EINVAL;
 980        name = nla_data(attrs[TIPC_NLA_MEDIA_NAME]);
 981
 982        rep = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
 983        if (!rep)
 984                return -ENOMEM;
 985
 986        msg.skb = rep;
 987        msg.portid = info->snd_portid;
 988        msg.seq = info->snd_seq;
 989
 990        rtnl_lock();
 991        media = tipc_media_find(name);
 992        if (!media) {
 993                err = -EINVAL;
 994                goto err_out;
 995        }
 996
 997        err = __tipc_nl_add_media(&msg, media, 0);
 998        if (err)
 999                goto err_out;
1000        rtnl_unlock();
1001
1002        return genlmsg_reply(rep, info);
1003err_out:
1004        rtnl_unlock();
1005        nlmsg_free(rep);
1006
1007        return err;
1008}
1009
1010int tipc_nl_media_set(struct sk_buff *skb, struct genl_info *info)
1011{
1012        int err;
1013        char *name;
1014        struct tipc_media *m;
1015        struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
1016
1017        if (!info->attrs[TIPC_NLA_MEDIA])
1018                return -EINVAL;
1019
1020        err = nla_parse_nested(attrs, TIPC_NLA_MEDIA_MAX,
1021                               info->attrs[TIPC_NLA_MEDIA],
1022                               tipc_nl_media_policy);
1023
1024        if (!attrs[TIPC_NLA_MEDIA_NAME])
1025                return -EINVAL;
1026        name = nla_data(attrs[TIPC_NLA_MEDIA_NAME]);
1027
1028        rtnl_lock();
1029        m = tipc_media_find(name);
1030        if (!m) {
1031                rtnl_unlock();
1032                return -EINVAL;
1033        }
1034
1035        if (attrs[TIPC_NLA_MEDIA_PROP]) {
1036                struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
1037
1038                err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_MEDIA_PROP],
1039                                              props);
1040                if (err) {
1041                        rtnl_unlock();
1042                        return err;
1043                }
1044
1045                if (props[TIPC_NLA_PROP_TOL])
1046                        m->tolerance = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
1047                if (props[TIPC_NLA_PROP_PRIO])
1048                        m->priority = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
1049                if (props[TIPC_NLA_PROP_WIN])
1050                        m->window = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
1051        }
1052        rtnl_unlock();
1053
1054        return 0;
1055}
1056