linux/net/bridge/br_mdb.c
<<
>>
Prefs
   1#include <linux/err.h>
   2#include <linux/igmp.h>
   3#include <linux/kernel.h>
   4#include <linux/netdevice.h>
   5#include <linux/rculist.h>
   6#include <linux/skbuff.h>
   7#include <linux/if_ether.h>
   8#include <net/ip.h>
   9#include <net/netlink.h>
  10#if IS_ENABLED(CONFIG_IPV6)
  11#include <net/ipv6.h>
  12#endif
  13
  14#include "br_private.h"
  15
  16static int br_rports_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
  17                               struct net_device *dev)
  18{
  19        struct net_bridge *br = netdev_priv(dev);
  20        struct net_bridge_port *p;
  21        struct nlattr *nest;
  22
  23        if (!br->multicast_router || hlist_empty(&br->router_list))
  24                return 0;
  25
  26        nest = nla_nest_start(skb, MDBA_ROUTER);
  27        if (nest == NULL)
  28                return -EMSGSIZE;
  29
  30        hlist_for_each_entry_rcu(p, &br->router_list, rlist) {
  31                if (p && nla_put_u32(skb, MDBA_ROUTER_PORT, p->dev->ifindex))
  32                        goto fail;
  33        }
  34
  35        nla_nest_end(skb, nest);
  36        return 0;
  37fail:
  38        nla_nest_cancel(skb, nest);
  39        return -EMSGSIZE;
  40}
  41
  42static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
  43                            struct net_device *dev)
  44{
  45        struct net_bridge *br = netdev_priv(dev);
  46        struct net_bridge_mdb_htable *mdb;
  47        struct nlattr *nest, *nest2;
  48        int i, err = 0;
  49        int idx = 0, s_idx = cb->args[1];
  50
  51        if (br->multicast_disabled)
  52                return 0;
  53
  54        mdb = rcu_dereference(br->mdb);
  55        if (!mdb)
  56                return 0;
  57
  58        nest = nla_nest_start(skb, MDBA_MDB);
  59        if (nest == NULL)
  60                return -EMSGSIZE;
  61
  62        for (i = 0; i < mdb->max; i++) {
  63                struct net_bridge_mdb_entry *mp;
  64                struct net_bridge_port_group *p, **pp;
  65                struct net_bridge_port *port;
  66
  67                hlist_for_each_entry_rcu(mp, &mdb->mhash[i], hlist[mdb->ver]) {
  68                        if (idx < s_idx)
  69                                goto skip;
  70
  71                        nest2 = nla_nest_start(skb, MDBA_MDB_ENTRY);
  72                        if (nest2 == NULL) {
  73                                err = -EMSGSIZE;
  74                                goto out;
  75                        }
  76
  77                        for (pp = &mp->ports;
  78                             (p = rcu_dereference(*pp)) != NULL;
  79                              pp = &p->next) {
  80                                port = p->port;
  81                                if (port) {
  82                                        struct br_mdb_entry e;
  83                                        memset(&e, 0, sizeof(e));
  84                                        e.ifindex = port->dev->ifindex;
  85                                        e.state = p->state;
  86                                        if (p->addr.proto == htons(ETH_P_IP))
  87                                                e.addr.u.ip4 = p->addr.u.ip4;
  88#if IS_ENABLED(CONFIG_IPV6)
  89                                        if (p->addr.proto == htons(ETH_P_IPV6))
  90                                                e.addr.u.ip6 = p->addr.u.ip6;
  91#endif
  92                                        e.addr.proto = p->addr.proto;
  93                                        if (nla_put(skb, MDBA_MDB_ENTRY_INFO, sizeof(e), &e)) {
  94                                                nla_nest_cancel(skb, nest2);
  95                                                err = -EMSGSIZE;
  96                                                goto out;
  97                                        }
  98                                }
  99                        }
 100                        nla_nest_end(skb, nest2);
 101                skip:
 102                        idx++;
 103                }
 104        }
 105
 106out:
 107        cb->args[1] = idx;
 108        nla_nest_end(skb, nest);
 109        return err;
 110}
 111
 112static int br_mdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
 113{
 114        struct net_device *dev;
 115        struct net *net = sock_net(skb->sk);
 116        struct nlmsghdr *nlh = NULL;
 117        int idx = 0, s_idx;
 118
 119        s_idx = cb->args[0];
 120
 121        rcu_read_lock();
 122
 123        /* In theory this could be wrapped to 0... */
 124        cb->seq = net->dev_base_seq + br_mdb_rehash_seq;
 125
 126        for_each_netdev_rcu(net, dev) {
 127                if (dev->priv_flags & IFF_EBRIDGE) {
 128                        struct br_port_msg *bpm;
 129
 130                        if (idx < s_idx)
 131                                goto skip;
 132
 133                        nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid,
 134                                        cb->nlh->nlmsg_seq, RTM_GETMDB,
 135                                        sizeof(*bpm), NLM_F_MULTI);
 136                        if (nlh == NULL)
 137                                break;
 138
 139                        bpm = nlmsg_data(nlh);
 140                        memset(bpm, 0, sizeof(*bpm));
 141                        bpm->ifindex = dev->ifindex;
 142                        if (br_mdb_fill_info(skb, cb, dev) < 0)
 143                                goto out;
 144                        if (br_rports_fill_info(skb, cb, dev) < 0)
 145                                goto out;
 146
 147                        cb->args[1] = 0;
 148                        nlmsg_end(skb, nlh);
 149                skip:
 150                        idx++;
 151                }
 152        }
 153
 154out:
 155        if (nlh)
 156                nlmsg_end(skb, nlh);
 157        rcu_read_unlock();
 158        cb->args[0] = idx;
 159        return skb->len;
 160}
 161
 162static int nlmsg_populate_mdb_fill(struct sk_buff *skb,
 163                                   struct net_device *dev,
 164                                   struct br_mdb_entry *entry, u32 pid,
 165                                   u32 seq, int type, unsigned int flags)
 166{
 167        struct nlmsghdr *nlh;
 168        struct br_port_msg *bpm;
 169        struct nlattr *nest, *nest2;
 170
 171        nlh = nlmsg_put(skb, pid, seq, type, sizeof(*bpm), NLM_F_MULTI);
 172        if (!nlh)
 173                return -EMSGSIZE;
 174
 175        bpm = nlmsg_data(nlh);
 176        memset(bpm, 0, sizeof(*bpm));
 177        bpm->family  = AF_BRIDGE;
 178        bpm->ifindex = dev->ifindex;
 179        nest = nla_nest_start(skb, MDBA_MDB);
 180        if (nest == NULL)
 181                goto cancel;
 182        nest2 = nla_nest_start(skb, MDBA_MDB_ENTRY);
 183        if (nest2 == NULL)
 184                goto end;
 185
 186        if (nla_put(skb, MDBA_MDB_ENTRY_INFO, sizeof(*entry), entry))
 187                goto end;
 188
 189        nla_nest_end(skb, nest2);
 190        nla_nest_end(skb, nest);
 191        return nlmsg_end(skb, nlh);
 192
 193end:
 194        nla_nest_end(skb, nest);
 195cancel:
 196        nlmsg_cancel(skb, nlh);
 197        return -EMSGSIZE;
 198}
 199
 200static inline size_t rtnl_mdb_nlmsg_size(void)
 201{
 202        return NLMSG_ALIGN(sizeof(struct br_port_msg))
 203                + nla_total_size(sizeof(struct br_mdb_entry));
 204}
 205
 206static void __br_mdb_notify(struct net_device *dev, struct br_mdb_entry *entry,
 207                            int type)
 208{
 209        struct net *net = dev_net(dev);
 210        struct sk_buff *skb;
 211        int err = -ENOBUFS;
 212
 213        skb = nlmsg_new(rtnl_mdb_nlmsg_size(), GFP_ATOMIC);
 214        if (!skb)
 215                goto errout;
 216
 217        err = nlmsg_populate_mdb_fill(skb, dev, entry, 0, 0, type, NTF_SELF);
 218        if (err < 0) {
 219                kfree_skb(skb);
 220                goto errout;
 221        }
 222
 223        rtnl_notify(skb, net, 0, RTNLGRP_MDB, NULL, GFP_ATOMIC);
 224        return;
 225errout:
 226        rtnl_set_sk_err(net, RTNLGRP_MDB, err);
 227}
 228
 229void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
 230                   struct br_ip *group, int type)
 231{
 232        struct br_mdb_entry entry;
 233
 234        memset(&entry, 0, sizeof(entry));
 235        entry.ifindex = port->dev->ifindex;
 236        entry.addr.proto = group->proto;
 237        entry.addr.u.ip4 = group->u.ip4;
 238#if IS_ENABLED(CONFIG_IPV6)
 239        entry.addr.u.ip6 = group->u.ip6;
 240#endif
 241        __br_mdb_notify(dev, &entry, type);
 242}
 243
 244static bool is_valid_mdb_entry(struct br_mdb_entry *entry)
 245{
 246        if (entry->ifindex == 0)
 247                return false;
 248
 249        if (entry->addr.proto == htons(ETH_P_IP)) {
 250                if (!ipv4_is_multicast(entry->addr.u.ip4))
 251                        return false;
 252                if (ipv4_is_local_multicast(entry->addr.u.ip4))
 253                        return false;
 254#if IS_ENABLED(CONFIG_IPV6)
 255        } else if (entry->addr.proto == htons(ETH_P_IPV6)) {
 256                if (!ipv6_is_transient_multicast(&entry->addr.u.ip6))
 257                        return false;
 258#endif
 259        } else
 260                return false;
 261        if (entry->state != MDB_PERMANENT && entry->state != MDB_TEMPORARY)
 262                return false;
 263
 264        return true;
 265}
 266
 267static int br_mdb_parse(struct sk_buff *skb, struct nlmsghdr *nlh,
 268                        struct net_device **pdev, struct br_mdb_entry **pentry)
 269{
 270        struct net *net = sock_net(skb->sk);
 271        struct br_mdb_entry *entry;
 272        struct br_port_msg *bpm;
 273        struct nlattr *tb[MDBA_SET_ENTRY_MAX+1];
 274        struct net_device *dev;
 275        int err;
 276
 277        err = nlmsg_parse(nlh, sizeof(*bpm), tb, MDBA_SET_ENTRY, NULL);
 278        if (err < 0)
 279                return err;
 280
 281        bpm = nlmsg_data(nlh);
 282        if (bpm->ifindex == 0) {
 283                pr_info("PF_BRIDGE: br_mdb_parse() with invalid ifindex\n");
 284                return -EINVAL;
 285        }
 286
 287        dev = __dev_get_by_index(net, bpm->ifindex);
 288        if (dev == NULL) {
 289                pr_info("PF_BRIDGE: br_mdb_parse() with unknown ifindex\n");
 290                return -ENODEV;
 291        }
 292
 293        if (!(dev->priv_flags & IFF_EBRIDGE)) {
 294                pr_info("PF_BRIDGE: br_mdb_parse() with non-bridge\n");
 295                return -EOPNOTSUPP;
 296        }
 297
 298        *pdev = dev;
 299
 300        if (!tb[MDBA_SET_ENTRY] ||
 301            nla_len(tb[MDBA_SET_ENTRY]) != sizeof(struct br_mdb_entry)) {
 302                pr_info("PF_BRIDGE: br_mdb_parse() with invalid attr\n");
 303                return -EINVAL;
 304        }
 305
 306        entry = nla_data(tb[MDBA_SET_ENTRY]);
 307        if (!is_valid_mdb_entry(entry)) {
 308                pr_info("PF_BRIDGE: br_mdb_parse() with invalid entry\n");
 309                return -EINVAL;
 310        }
 311
 312        *pentry = entry;
 313        return 0;
 314}
 315
 316static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port,
 317                            struct br_ip *group, unsigned char state)
 318{
 319        struct net_bridge_mdb_entry *mp;
 320        struct net_bridge_port_group *p;
 321        struct net_bridge_port_group __rcu **pp;
 322        struct net_bridge_mdb_htable *mdb;
 323        int err;
 324
 325        mdb = mlock_dereference(br->mdb, br);
 326        mp = br_mdb_ip_get(mdb, group);
 327        if (!mp) {
 328                mp = br_multicast_new_group(br, port, group);
 329                err = PTR_ERR(mp);
 330                if (IS_ERR(mp))
 331                        return err;
 332        }
 333
 334        for (pp = &mp->ports;
 335             (p = mlock_dereference(*pp, br)) != NULL;
 336             pp = &p->next) {
 337                if (p->port == port)
 338                        return -EEXIST;
 339                if ((unsigned long)p->port < (unsigned long)port)
 340                        break;
 341        }
 342
 343        p = br_multicast_new_port_group(port, group, *pp, state);
 344        if (unlikely(!p))
 345                return -ENOMEM;
 346        rcu_assign_pointer(*pp, p);
 347
 348        br_mdb_notify(br->dev, port, group, RTM_NEWMDB);
 349        return 0;
 350}
 351
 352static int __br_mdb_add(struct net *net, struct net_bridge *br,
 353                        struct br_mdb_entry *entry)
 354{
 355        struct br_ip ip;
 356        struct net_device *dev;
 357        struct net_bridge_port *p;
 358        int ret;
 359
 360        if (!netif_running(br->dev) || br->multicast_disabled)
 361                return -EINVAL;
 362
 363        dev = __dev_get_by_index(net, entry->ifindex);
 364        if (!dev)
 365                return -ENODEV;
 366
 367        p = br_port_get_rtnl(dev);
 368        if (!p || p->br != br || p->state == BR_STATE_DISABLED)
 369                return -EINVAL;
 370
 371        ip.proto = entry->addr.proto;
 372        if (ip.proto == htons(ETH_P_IP))
 373                ip.u.ip4 = entry->addr.u.ip4;
 374#if IS_ENABLED(CONFIG_IPV6)
 375        else
 376                ip.u.ip6 = entry->addr.u.ip6;
 377#endif
 378
 379        spin_lock_bh(&br->multicast_lock);
 380        ret = br_mdb_add_group(br, p, &ip, entry->state);
 381        spin_unlock_bh(&br->multicast_lock);
 382        return ret;
 383}
 384
 385static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh)
 386{
 387        struct net *net = sock_net(skb->sk);
 388        struct br_mdb_entry *entry;
 389        struct net_device *dev;
 390        struct net_bridge *br;
 391        int err;
 392
 393        err = br_mdb_parse(skb, nlh, &dev, &entry);
 394        if (err < 0)
 395                return err;
 396
 397        br = netdev_priv(dev);
 398
 399        err = __br_mdb_add(net, br, entry);
 400        if (!err)
 401                __br_mdb_notify(dev, entry, RTM_NEWMDB);
 402        return err;
 403}
 404
 405static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry)
 406{
 407        struct net_bridge_mdb_htable *mdb;
 408        struct net_bridge_mdb_entry *mp;
 409        struct net_bridge_port_group *p;
 410        struct net_bridge_port_group __rcu **pp;
 411        struct br_ip ip;
 412        int err = -EINVAL;
 413
 414        if (!netif_running(br->dev) || br->multicast_disabled)
 415                return -EINVAL;
 416
 417        if (timer_pending(&br->multicast_querier_timer))
 418                return -EBUSY;
 419
 420        ip.proto = entry->addr.proto;
 421        if (ip.proto == htons(ETH_P_IP))
 422                ip.u.ip4 = entry->addr.u.ip4;
 423#if IS_ENABLED(CONFIG_IPV6)
 424        else
 425                ip.u.ip6 = entry->addr.u.ip6;
 426#endif
 427
 428        spin_lock_bh(&br->multicast_lock);
 429        mdb = mlock_dereference(br->mdb, br);
 430
 431        mp = br_mdb_ip_get(mdb, &ip);
 432        if (!mp)
 433                goto unlock;
 434
 435        for (pp = &mp->ports;
 436             (p = mlock_dereference(*pp, br)) != NULL;
 437             pp = &p->next) {
 438                if (!p->port || p->port->dev->ifindex != entry->ifindex)
 439                        continue;
 440
 441                if (p->port->state == BR_STATE_DISABLED)
 442                        goto unlock;
 443
 444                rcu_assign_pointer(*pp, p->next);
 445                hlist_del_init(&p->mglist);
 446                del_timer(&p->timer);
 447                call_rcu_bh(&p->rcu, br_multicast_free_pg);
 448                err = 0;
 449
 450                if (!mp->ports && !mp->mglist &&
 451                    netif_running(br->dev))
 452                        mod_timer(&mp->timer, jiffies);
 453                break;
 454        }
 455
 456unlock:
 457        spin_unlock_bh(&br->multicast_lock);
 458        return err;
 459}
 460
 461static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh)
 462{
 463        struct net_device *dev;
 464        struct br_mdb_entry *entry;
 465        struct net_bridge *br;
 466        int err;
 467
 468        err = br_mdb_parse(skb, nlh, &dev, &entry);
 469        if (err < 0)
 470                return err;
 471
 472        br = netdev_priv(dev);
 473
 474        err = __br_mdb_del(br, entry);
 475        if (!err)
 476                __br_mdb_notify(dev, entry, RTM_DELMDB);
 477        return err;
 478}
 479
 480void br_mdb_init(void)
 481{
 482        rtnl_register(PF_BRIDGE, RTM_GETMDB, NULL, br_mdb_dump, NULL);
 483        rtnl_register(PF_BRIDGE, RTM_NEWMDB, br_mdb_add, NULL, NULL);
 484        rtnl_register(PF_BRIDGE, RTM_DELMDB, br_mdb_del, NULL, NULL);
 485}
 486
 487void br_mdb_uninit(void)
 488{
 489        rtnl_unregister(PF_BRIDGE, RTM_GETMDB);
 490        rtnl_unregister(PF_BRIDGE, RTM_NEWMDB);
 491        rtnl_unregister(PF_BRIDGE, RTM_DELMDB);
 492}
 493