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        struct sk_buff *skb;
 209        char addr_string[16];
 210        u32 bearer_id;
 211        u32 with_this_prio;
 212        u32 i;
 213        int res = -EINVAL;
 214
 215        if (!tn->own_addr) {
 216                pr_warn("Bearer <%s> rejected, not supported in standalone mode\n",
 217                        name);
 218                return -ENOPROTOOPT;
 219        }
 220        if (!bearer_name_validate(name, &b_names)) {
 221                pr_warn("Bearer <%s> rejected, illegal name\n", name);
 222                return -EINVAL;
 223        }
 224        if (tipc_addr_domain_valid(disc_domain) &&
 225            (disc_domain != tn->own_addr)) {
 226                if (tipc_in_scope(disc_domain, tn->own_addr)) {
 227                        disc_domain = tn->own_addr & TIPC_CLUSTER_MASK;
 228                        res = 0;   /* accept any node in own cluster */
 229                } else if (in_own_cluster_exact(net, disc_domain))
 230                        res = 0;   /* accept specified node in own cluster */
 231        }
 232        if (res) {
 233                pr_warn("Bearer <%s> rejected, illegal discovery domain\n",
 234                        name);
 235                return -EINVAL;
 236        }
 237        if ((priority > TIPC_MAX_LINK_PRI) &&
 238            (priority != TIPC_MEDIA_LINK_PRI)) {
 239                pr_warn("Bearer <%s> rejected, illegal priority\n", name);
 240                return -EINVAL;
 241        }
 242
 243        m = tipc_media_find(b_names.media_name);
 244        if (!m) {
 245                pr_warn("Bearer <%s> rejected, media <%s> not registered\n",
 246                        name, b_names.media_name);
 247                return -EINVAL;
 248        }
 249
 250        if (priority == TIPC_MEDIA_LINK_PRI)
 251                priority = m->priority;
 252
 253restart:
 254        bearer_id = MAX_BEARERS;
 255        with_this_prio = 1;
 256        for (i = MAX_BEARERS; i-- != 0; ) {
 257                b = rtnl_dereference(tn->bearer_list[i]);
 258                if (!b) {
 259                        bearer_id = i;
 260                        continue;
 261                }
 262                if (!strcmp(name, b->name)) {
 263                        pr_warn("Bearer <%s> rejected, already enabled\n",
 264                                name);
 265                        return -EINVAL;
 266                }
 267                if ((b->priority == priority) &&
 268                    (++with_this_prio > 2)) {
 269                        if (priority-- == 0) {
 270                                pr_warn("Bearer <%s> rejected, duplicate priority\n",
 271                                        name);
 272                                return -EINVAL;
 273                        }
 274                        pr_warn("Bearer <%s> priority adjustment required %u->%u\n",
 275                                name, priority + 1, priority);
 276                        goto restart;
 277                }
 278        }
 279        if (bearer_id >= MAX_BEARERS) {
 280                pr_warn("Bearer <%s> rejected, bearer limit reached (%u)\n",
 281                        name, MAX_BEARERS);
 282                return -EINVAL;
 283        }
 284
 285        b = kzalloc(sizeof(*b), GFP_ATOMIC);
 286        if (!b)
 287                return -ENOMEM;
 288
 289        strcpy(b->name, name);
 290        b->media = m;
 291        res = m->enable_media(net, b, attr);
 292        if (res) {
 293                pr_warn("Bearer <%s> rejected, enable failure (%d)\n",
 294                        name, -res);
 295                return -EINVAL;
 296        }
 297
 298        b->identity = bearer_id;
 299        b->tolerance = m->tolerance;
 300        b->window = m->window;
 301        b->domain = disc_domain;
 302        b->net_plane = bearer_id + 'A';
 303        b->priority = priority;
 304
 305        res = tipc_disc_create(net, b, &b->bcast_addr, &skb);
 306        if (res) {
 307                bearer_disable(net, b);
 308                pr_warn("Bearer <%s> rejected, discovery object creation failed\n",
 309                        name);
 310                return -EINVAL;
 311        }
 312
 313        rcu_assign_pointer(tn->bearer_list[bearer_id], b);
 314        if (skb)
 315                tipc_bearer_xmit_skb(net, bearer_id, skb, &b->bcast_addr);
 316        pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n",
 317                name,
 318                tipc_addr_string_fill(addr_string, disc_domain), priority);
 319        return res;
 320}
 321
 322/**
 323 * tipc_reset_bearer - Reset all links established over this bearer
 324 */
 325static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b)
 326{
 327        pr_info("Resetting bearer <%s>\n", b->name);
 328        tipc_node_delete_links(net, b->identity);
 329        tipc_disc_reset(net, b);
 330        return 0;
 331}
 332
 333/* tipc_bearer_reset_all - reset all links on all bearers
 334 */
 335void tipc_bearer_reset_all(struct net *net)
 336{
 337        struct tipc_net *tn = tipc_net(net);
 338        struct tipc_bearer *b;
 339        int i;
 340
 341        for (i = 0; i < MAX_BEARERS; i++) {
 342                b = rcu_dereference_rtnl(tn->bearer_list[i]);
 343                if (b)
 344                        tipc_reset_bearer(net, b);
 345        }
 346}
 347
 348/**
 349 * bearer_disable
 350 *
 351 * Note: This routine assumes caller holds RTNL lock.
 352 */
 353static void bearer_disable(struct net *net, struct tipc_bearer *b)
 354{
 355        struct tipc_net *tn = tipc_net(net);
 356        int bearer_id = b->identity;
 357
 358        pr_info("Disabling bearer <%s>\n", b->name);
 359        b->media->disable_media(b);
 360        tipc_node_delete_links(net, bearer_id);
 361        RCU_INIT_POINTER(b->media_ptr, NULL);
 362        if (b->link_req)
 363                tipc_disc_delete(b->link_req);
 364        RCU_INIT_POINTER(tn->bearer_list[bearer_id], NULL);
 365        kfree_rcu(b, rcu);
 366}
 367
 368int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b,
 369                         struct nlattr *attr[])
 370{
 371        struct net_device *dev;
 372        char *driver_name = strchr((const char *)b->name, ':') + 1;
 373
 374        /* Find device with specified name */
 375        dev = dev_get_by_name(net, driver_name);
 376        if (!dev)
 377                return -ENODEV;
 378
 379        /* Associate TIPC bearer with L2 bearer */
 380        rcu_assign_pointer(b->media_ptr, dev);
 381        memset(&b->bcast_addr, 0, sizeof(b->bcast_addr));
 382        memcpy(b->bcast_addr.value, dev->broadcast, b->media->hwaddr_len);
 383        b->bcast_addr.media_id = b->media->type_id;
 384        b->bcast_addr.broadcast = 1;
 385        b->mtu = dev->mtu;
 386        b->media->raw2addr(b, &b->addr, (char *)dev->dev_addr);
 387        rcu_assign_pointer(dev->tipc_ptr, b);
 388        return 0;
 389}
 390
 391/* tipc_disable_l2_media - detach TIPC bearer from an L2 interface
 392 *
 393 * Mark L2 bearer as inactive so that incoming buffers are thrown away
 394 */
 395void tipc_disable_l2_media(struct tipc_bearer *b)
 396{
 397        struct net_device *dev;
 398
 399        dev = (struct net_device *)rtnl_dereference(b->media_ptr);
 400        RCU_INIT_POINTER(dev->tipc_ptr, NULL);
 401        synchronize_net();
 402        dev_put(dev);
 403}
 404
 405/**
 406 * tipc_l2_send_msg - send a TIPC packet out over an L2 interface
 407 * @skb: the packet to be sent
 408 * @b: the bearer through which the packet is to be sent
 409 * @dest: peer destination address
 410 */
 411int tipc_l2_send_msg(struct net *net, struct sk_buff *skb,
 412                     struct tipc_bearer *b, struct tipc_media_addr *dest)
 413{
 414        struct net_device *dev;
 415        int delta;
 416        void *tipc_ptr;
 417
 418        dev = (struct net_device *)rcu_dereference_rtnl(b->media_ptr);
 419        if (!dev)
 420                return 0;
 421
 422        /* Send RESET message even if bearer is detached from device */
 423        tipc_ptr = rcu_dereference_rtnl(dev->tipc_ptr);
 424        if (unlikely(!tipc_ptr && !msg_is_reset(buf_msg(skb))))
 425                goto drop;
 426
 427        delta = dev->hard_header_len - skb_headroom(skb);
 428        if ((delta > 0) &&
 429            pskb_expand_head(skb, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC))
 430                goto drop;
 431
 432        skb_reset_network_header(skb);
 433        skb->dev = dev;
 434        skb->protocol = htons(ETH_P_TIPC);
 435        dev_hard_header(skb, dev, ETH_P_TIPC, dest->value,
 436                        dev->dev_addr, skb->len);
 437        dev_queue_xmit(skb);
 438        return 0;
 439drop:
 440        kfree_skb(skb);
 441        return 0;
 442}
 443
 444int tipc_bearer_mtu(struct net *net, u32 bearer_id)
 445{
 446        int mtu = 0;
 447        struct tipc_bearer *b;
 448
 449        rcu_read_lock();
 450        b = rcu_dereference_rtnl(tipc_net(net)->bearer_list[bearer_id]);
 451        if (b)
 452                mtu = b->mtu;
 453        rcu_read_unlock();
 454        return mtu;
 455}
 456
 457/* tipc_bearer_xmit_skb - sends buffer to destination over bearer
 458 */
 459void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id,
 460                          struct sk_buff *skb,
 461                          struct tipc_media_addr *dest)
 462{
 463        struct tipc_net *tn = tipc_net(net);
 464        struct tipc_bearer *b;
 465
 466        rcu_read_lock();
 467        b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]);
 468        if (likely(b))
 469                b->media->send_msg(net, skb, b, dest);
 470        else
 471                kfree_skb(skb);
 472        rcu_read_unlock();
 473}
 474
 475/* tipc_bearer_xmit() -send buffer to destination over bearer
 476 */
 477void tipc_bearer_xmit(struct net *net, u32 bearer_id,
 478                      struct sk_buff_head *xmitq,
 479                      struct tipc_media_addr *dst)
 480{
 481        struct tipc_net *tn = net_generic(net, tipc_net_id);
 482        struct tipc_bearer *b;
 483        struct sk_buff *skb, *tmp;
 484
 485        if (skb_queue_empty(xmitq))
 486                return;
 487
 488        rcu_read_lock();
 489        b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]);
 490        if (unlikely(!b))
 491                __skb_queue_purge(xmitq);
 492        skb_queue_walk_safe(xmitq, skb, tmp) {
 493                __skb_dequeue(xmitq);
 494                b->media->send_msg(net, skb, b, dst);
 495        }
 496        rcu_read_unlock();
 497}
 498
 499/* tipc_bearer_bc_xmit() - broadcast buffers to all destinations
 500 */
 501void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id,
 502                         struct sk_buff_head *xmitq)
 503{
 504        struct tipc_net *tn = tipc_net(net);
 505        int net_id = tn->net_id;
 506        struct tipc_bearer *b;
 507        struct sk_buff *skb, *tmp;
 508        struct tipc_msg *hdr;
 509
 510        rcu_read_lock();
 511        b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]);
 512        if (unlikely(!b))
 513                __skb_queue_purge(xmitq);
 514        skb_queue_walk_safe(xmitq, skb, tmp) {
 515                hdr = buf_msg(skb);
 516                msg_set_non_seq(hdr, 1);
 517                msg_set_mc_netid(hdr, net_id);
 518                __skb_dequeue(xmitq);
 519                b->media->send_msg(net, skb, b, &b->bcast_addr);
 520        }
 521        rcu_read_unlock();
 522}
 523
 524/**
 525 * tipc_l2_rcv_msg - handle incoming TIPC message from an interface
 526 * @buf: the received packet
 527 * @dev: the net device that the packet was received on
 528 * @pt: the packet_type structure which was used to register this handler
 529 * @orig_dev: the original receive net device in case the device is a bond
 530 *
 531 * Accept only packets explicitly sent to this node, or broadcast packets;
 532 * ignores packets sent using interface multicast, and traffic sent to other
 533 * nodes (which can happen if interface is running in promiscuous mode).
 534 */
 535static int tipc_l2_rcv_msg(struct sk_buff *skb, struct net_device *dev,
 536                           struct packet_type *pt, struct net_device *orig_dev)
 537{
 538        struct tipc_bearer *b;
 539
 540        rcu_read_lock();
 541        b = rcu_dereference_rtnl(dev->tipc_ptr);
 542        if (likely(b && (skb->pkt_type <= PACKET_BROADCAST))) {
 543                skb->next = NULL;
 544                tipc_rcv(dev_net(dev), skb, b);
 545                rcu_read_unlock();
 546                return NET_RX_SUCCESS;
 547        }
 548        rcu_read_unlock();
 549        kfree_skb(skb);
 550        return NET_RX_DROP;
 551}
 552
 553/**
 554 * tipc_l2_device_event - handle device events from network device
 555 * @nb: the context of the notification
 556 * @evt: the type of event
 557 * @ptr: the net device that the event was on
 558 *
 559 * This function is called by the Ethernet driver in case of link
 560 * change event.
 561 */
 562static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
 563                                void *ptr)
 564{
 565        struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 566        struct net *net = dev_net(dev);
 567        struct tipc_net *tn = tipc_net(net);
 568        struct tipc_bearer *b;
 569        int i;
 570
 571        b = rtnl_dereference(dev->tipc_ptr);
 572        if (!b) {
 573                for (i = 0; i < MAX_BEARERS; b = NULL, i++) {
 574                        b = rtnl_dereference(tn->bearer_list[i]);
 575                        if (b && (b->media_ptr == dev))
 576                                break;
 577                }
 578        }
 579        if (!b)
 580                return NOTIFY_DONE;
 581
 582        b->mtu = dev->mtu;
 583
 584        switch (evt) {
 585        case NETDEV_CHANGE:
 586                if (netif_carrier_ok(dev))
 587                        break;
 588        case NETDEV_UP:
 589                rcu_assign_pointer(dev->tipc_ptr, b);
 590                break;
 591        case NETDEV_GOING_DOWN:
 592                RCU_INIT_POINTER(dev->tipc_ptr, NULL);
 593                synchronize_net();
 594                tipc_reset_bearer(net, b);
 595                break;
 596        case NETDEV_CHANGEMTU:
 597                tipc_reset_bearer(net, b);
 598                break;
 599        case NETDEV_CHANGEADDR:
 600                b->media->raw2addr(b, &b->addr,
 601                                   (char *)dev->dev_addr);
 602                tipc_reset_bearer(net, b);
 603                break;
 604        case NETDEV_UNREGISTER:
 605        case NETDEV_CHANGENAME:
 606                bearer_disable(dev_net(dev), b);
 607                break;
 608        }
 609        return NOTIFY_OK;
 610}
 611
 612static struct packet_type tipc_packet_type __read_mostly = {
 613        .type = htons(ETH_P_TIPC),
 614        .func = tipc_l2_rcv_msg,
 615};
 616
 617static struct notifier_block notifier = {
 618        .notifier_call  = tipc_l2_device_event,
 619        .priority       = 0,
 620};
 621
 622int tipc_bearer_setup(void)
 623{
 624        int err;
 625
 626        err = register_netdevice_notifier(&notifier);
 627        if (err)
 628                return err;
 629        dev_add_pack(&tipc_packet_type);
 630        return 0;
 631}
 632
 633void tipc_bearer_cleanup(void)
 634{
 635        unregister_netdevice_notifier(&notifier);
 636        dev_remove_pack(&tipc_packet_type);
 637}
 638
 639void tipc_bearer_stop(struct net *net)
 640{
 641        struct tipc_net *tn = net_generic(net, tipc_net_id);
 642        struct tipc_bearer *b;
 643        u32 i;
 644
 645        for (i = 0; i < MAX_BEARERS; i++) {
 646                b = rtnl_dereference(tn->bearer_list[i]);
 647                if (b) {
 648                        bearer_disable(net, b);
 649                        tn->bearer_list[i] = NULL;
 650                }
 651        }
 652}
 653
 654/* Caller should hold rtnl_lock to protect the bearer */
 655static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg,
 656                                struct tipc_bearer *bearer, int nlflags)
 657{
 658        void *hdr;
 659        struct nlattr *attrs;
 660        struct nlattr *prop;
 661
 662        hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
 663                          nlflags, TIPC_NL_BEARER_GET);
 664        if (!hdr)
 665                return -EMSGSIZE;
 666
 667        attrs = nla_nest_start(msg->skb, TIPC_NLA_BEARER);
 668        if (!attrs)
 669                goto msg_full;
 670
 671        if (nla_put_string(msg->skb, TIPC_NLA_BEARER_NAME, bearer->name))
 672                goto attr_msg_full;
 673
 674        prop = nla_nest_start(msg->skb, TIPC_NLA_BEARER_PROP);
 675        if (!prop)
 676                goto prop_msg_full;
 677        if (nla_put_u32(msg->skb, TIPC_NLA_PROP_PRIO, bearer->priority))
 678                goto prop_msg_full;
 679        if (nla_put_u32(msg->skb, TIPC_NLA_PROP_TOL, bearer->tolerance))
 680                goto prop_msg_full;
 681        if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bearer->window))
 682                goto prop_msg_full;
 683
 684        nla_nest_end(msg->skb, prop);
 685        nla_nest_end(msg->skb, attrs);
 686        genlmsg_end(msg->skb, hdr);
 687
 688        return 0;
 689
 690prop_msg_full:
 691        nla_nest_cancel(msg->skb, prop);
 692attr_msg_full:
 693        nla_nest_cancel(msg->skb, attrs);
 694msg_full:
 695        genlmsg_cancel(msg->skb, hdr);
 696
 697        return -EMSGSIZE;
 698}
 699
 700int tipc_nl_bearer_dump(struct sk_buff *skb, struct netlink_callback *cb)
 701{
 702        int err;
 703        int i = cb->args[0];
 704        struct tipc_bearer *bearer;
 705        struct tipc_nl_msg msg;
 706        struct net *net = sock_net(skb->sk);
 707        struct tipc_net *tn = net_generic(net, tipc_net_id);
 708
 709        if (i == MAX_BEARERS)
 710                return 0;
 711
 712        msg.skb = skb;
 713        msg.portid = NETLINK_CB(cb->skb).portid;
 714        msg.seq = cb->nlh->nlmsg_seq;
 715
 716        rtnl_lock();
 717        for (i = 0; i < MAX_BEARERS; i++) {
 718                bearer = rtnl_dereference(tn->bearer_list[i]);
 719                if (!bearer)
 720                        continue;
 721
 722                err = __tipc_nl_add_bearer(&msg, bearer, NLM_F_MULTI);
 723                if (err)
 724                        break;
 725        }
 726        rtnl_unlock();
 727
 728        cb->args[0] = i;
 729        return skb->len;
 730}
 731
 732int tipc_nl_bearer_get(struct sk_buff *skb, struct genl_info *info)
 733{
 734        int err;
 735        char *name;
 736        struct sk_buff *rep;
 737        struct tipc_bearer *bearer;
 738        struct tipc_nl_msg msg;
 739        struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
 740        struct net *net = genl_info_net(info);
 741
 742        if (!info->attrs[TIPC_NLA_BEARER])
 743                return -EINVAL;
 744
 745        err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
 746                               info->attrs[TIPC_NLA_BEARER],
 747                               tipc_nl_bearer_policy);
 748        if (err)
 749                return err;
 750
 751        if (!attrs[TIPC_NLA_BEARER_NAME])
 752                return -EINVAL;
 753        name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
 754
 755        rep = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
 756        if (!rep)
 757                return -ENOMEM;
 758
 759        msg.skb = rep;
 760        msg.portid = info->snd_portid;
 761        msg.seq = info->snd_seq;
 762
 763        rtnl_lock();
 764        bearer = tipc_bearer_find(net, name);
 765        if (!bearer) {
 766                err = -EINVAL;
 767                goto err_out;
 768        }
 769
 770        err = __tipc_nl_add_bearer(&msg, bearer, 0);
 771        if (err)
 772                goto err_out;
 773        rtnl_unlock();
 774
 775        return genlmsg_reply(rep, info);
 776err_out:
 777        rtnl_unlock();
 778        nlmsg_free(rep);
 779
 780        return err;
 781}
 782
 783int tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info)
 784{
 785        int err;
 786        char *name;
 787        struct tipc_bearer *bearer;
 788        struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
 789        struct net *net = sock_net(skb->sk);
 790
 791        if (!info->attrs[TIPC_NLA_BEARER])
 792                return -EINVAL;
 793
 794        err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
 795                               info->attrs[TIPC_NLA_BEARER],
 796                               tipc_nl_bearer_policy);
 797        if (err)
 798                return err;
 799
 800        if (!attrs[TIPC_NLA_BEARER_NAME])
 801                return -EINVAL;
 802
 803        name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
 804
 805        rtnl_lock();
 806        bearer = tipc_bearer_find(net, name);
 807        if (!bearer) {
 808                rtnl_unlock();
 809                return -EINVAL;
 810        }
 811
 812        bearer_disable(net, bearer);
 813        rtnl_unlock();
 814
 815        return 0;
 816}
 817
 818int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info)
 819{
 820        int err;
 821        char *bearer;
 822        struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
 823        struct net *net = sock_net(skb->sk);
 824        struct tipc_net *tn = net_generic(net, tipc_net_id);
 825        u32 domain;
 826        u32 prio;
 827
 828        prio = TIPC_MEDIA_LINK_PRI;
 829        domain = tn->own_addr & TIPC_CLUSTER_MASK;
 830
 831        if (!info->attrs[TIPC_NLA_BEARER])
 832                return -EINVAL;
 833
 834        err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
 835                               info->attrs[TIPC_NLA_BEARER],
 836                               tipc_nl_bearer_policy);
 837        if (err)
 838                return err;
 839
 840        if (!attrs[TIPC_NLA_BEARER_NAME])
 841                return -EINVAL;
 842
 843        bearer = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
 844
 845        if (attrs[TIPC_NLA_BEARER_DOMAIN])
 846                domain = nla_get_u32(attrs[TIPC_NLA_BEARER_DOMAIN]);
 847
 848        if (attrs[TIPC_NLA_BEARER_PROP]) {
 849                struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
 850
 851                err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_BEARER_PROP],
 852                                              props);
 853                if (err)
 854                        return err;
 855
 856                if (props[TIPC_NLA_PROP_PRIO])
 857                        prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
 858        }
 859
 860        rtnl_lock();
 861        err = tipc_enable_bearer(net, bearer, domain, prio, attrs);
 862        if (err) {
 863                rtnl_unlock();
 864                return err;
 865        }
 866        rtnl_unlock();
 867
 868        return 0;
 869}
 870
 871int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info)
 872{
 873        int err;
 874        char *name;
 875        struct tipc_bearer *b;
 876        struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
 877        struct net *net = sock_net(skb->sk);
 878
 879        if (!info->attrs[TIPC_NLA_BEARER])
 880                return -EINVAL;
 881
 882        err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
 883                               info->attrs[TIPC_NLA_BEARER],
 884                               tipc_nl_bearer_policy);
 885        if (err)
 886                return err;
 887
 888        if (!attrs[TIPC_NLA_BEARER_NAME])
 889                return -EINVAL;
 890        name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
 891
 892        rtnl_lock();
 893        b = tipc_bearer_find(net, name);
 894        if (!b) {
 895                rtnl_unlock();
 896                return -EINVAL;
 897        }
 898
 899        if (attrs[TIPC_NLA_BEARER_PROP]) {
 900                struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
 901
 902                err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_BEARER_PROP],
 903                                              props);
 904                if (err) {
 905                        rtnl_unlock();
 906                        return err;
 907                }
 908
 909                if (props[TIPC_NLA_PROP_TOL])
 910                        b->tolerance = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
 911                if (props[TIPC_NLA_PROP_PRIO])
 912                        b->priority = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
 913                if (props[TIPC_NLA_PROP_WIN])
 914                        b->window = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
 915        }
 916        rtnl_unlock();
 917
 918        return 0;
 919}
 920
 921static int __tipc_nl_add_media(struct tipc_nl_msg *msg,
 922                               struct tipc_media *media, int nlflags)
 923{
 924        void *hdr;
 925        struct nlattr *attrs;
 926        struct nlattr *prop;
 927
 928        hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
 929                          nlflags, TIPC_NL_MEDIA_GET);
 930        if (!hdr)
 931                return -EMSGSIZE;
 932
 933        attrs = nla_nest_start(msg->skb, TIPC_NLA_MEDIA);
 934        if (!attrs)
 935                goto msg_full;
 936
 937        if (nla_put_string(msg->skb, TIPC_NLA_MEDIA_NAME, media->name))
 938                goto attr_msg_full;
 939
 940        prop = nla_nest_start(msg->skb, TIPC_NLA_MEDIA_PROP);
 941        if (!prop)
 942                goto prop_msg_full;
 943        if (nla_put_u32(msg->skb, TIPC_NLA_PROP_PRIO, media->priority))
 944                goto prop_msg_full;
 945        if (nla_put_u32(msg->skb, TIPC_NLA_PROP_TOL, media->tolerance))
 946                goto prop_msg_full;
 947        if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, media->window))
 948                goto prop_msg_full;
 949
 950        nla_nest_end(msg->skb, prop);
 951        nla_nest_end(msg->skb, attrs);
 952        genlmsg_end(msg->skb, hdr);
 953
 954        return 0;
 955
 956prop_msg_full:
 957        nla_nest_cancel(msg->skb, prop);
 958attr_msg_full:
 959        nla_nest_cancel(msg->skb, attrs);
 960msg_full:
 961        genlmsg_cancel(msg->skb, hdr);
 962
 963        return -EMSGSIZE;
 964}
 965
 966int tipc_nl_media_dump(struct sk_buff *skb, struct netlink_callback *cb)
 967{
 968        int err;
 969        int i = cb->args[0];
 970        struct tipc_nl_msg msg;
 971
 972        if (i == MAX_MEDIA)
 973                return 0;
 974
 975        msg.skb = skb;
 976        msg.portid = NETLINK_CB(cb->skb).portid;
 977        msg.seq = cb->nlh->nlmsg_seq;
 978
 979        rtnl_lock();
 980        for (; media_info_array[i] != NULL; i++) {
 981                err = __tipc_nl_add_media(&msg, media_info_array[i],
 982                                          NLM_F_MULTI);
 983                if (err)
 984                        break;
 985        }
 986        rtnl_unlock();
 987
 988        cb->args[0] = i;
 989        return skb->len;
 990}
 991
 992int tipc_nl_media_get(struct sk_buff *skb, struct genl_info *info)
 993{
 994        int err;
 995        char *name;
 996        struct tipc_nl_msg msg;
 997        struct tipc_media *media;
 998        struct sk_buff *rep;
 999        struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
1000
1001        if (!info->attrs[TIPC_NLA_MEDIA])
1002                return -EINVAL;
1003
1004        err = nla_parse_nested(attrs, TIPC_NLA_MEDIA_MAX,
1005                               info->attrs[TIPC_NLA_MEDIA],
1006                               tipc_nl_media_policy);
1007        if (err)
1008                return err;
1009
1010        if (!attrs[TIPC_NLA_MEDIA_NAME])
1011                return -EINVAL;
1012        name = nla_data(attrs[TIPC_NLA_MEDIA_NAME]);
1013
1014        rep = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1015        if (!rep)
1016                return -ENOMEM;
1017
1018        msg.skb = rep;
1019        msg.portid = info->snd_portid;
1020        msg.seq = info->snd_seq;
1021
1022        rtnl_lock();
1023        media = tipc_media_find(name);
1024        if (!media) {
1025                err = -EINVAL;
1026                goto err_out;
1027        }
1028
1029        err = __tipc_nl_add_media(&msg, media, 0);
1030        if (err)
1031                goto err_out;
1032        rtnl_unlock();
1033
1034        return genlmsg_reply(rep, info);
1035err_out:
1036        rtnl_unlock();
1037        nlmsg_free(rep);
1038
1039        return err;
1040}
1041
1042int tipc_nl_media_set(struct sk_buff *skb, struct genl_info *info)
1043{
1044        int err;
1045        char *name;
1046        struct tipc_media *m;
1047        struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
1048
1049        if (!info->attrs[TIPC_NLA_MEDIA])
1050                return -EINVAL;
1051
1052        err = nla_parse_nested(attrs, TIPC_NLA_MEDIA_MAX,
1053                               info->attrs[TIPC_NLA_MEDIA],
1054                               tipc_nl_media_policy);
1055
1056        if (!attrs[TIPC_NLA_MEDIA_NAME])
1057                return -EINVAL;
1058        name = nla_data(attrs[TIPC_NLA_MEDIA_NAME]);
1059
1060        rtnl_lock();
1061        m = tipc_media_find(name);
1062        if (!m) {
1063                rtnl_unlock();
1064                return -EINVAL;
1065        }
1066
1067        if (attrs[TIPC_NLA_MEDIA_PROP]) {
1068                struct nlattr *props[TIPC_NLA_PROP_MAX + 1];
1069
1070                err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_MEDIA_PROP],
1071                                              props);
1072                if (err) {
1073                        rtnl_unlock();
1074                        return err;
1075                }
1076
1077                if (props[TIPC_NLA_PROP_TOL])
1078                        m->tolerance = nla_get_u32(props[TIPC_NLA_PROP_TOL]);
1079                if (props[TIPC_NLA_PROP_PRIO])
1080                        m->priority = nla_get_u32(props[TIPC_NLA_PROP_PRIO]);
1081                if (props[TIPC_NLA_PROP_WIN])
1082                        m->window = nla_get_u32(props[TIPC_NLA_PROP_WIN]);
1083        }
1084        rtnl_unlock();
1085
1086        return 0;
1087}
1088