rtnetlink.c (e5a55a898720096f43bc24938f8875c0a1b34cd7) rtnetlink.c (2469ffd723f76ac2d3ce3d4f31ee31ee0a06cd38)
1/*
2 * INET An implementation of the TCP/IP protocol suite for the LINUX
3 * operating system. INET is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
5 *
6 * Routing netlink socket interface: protocol independent part.
7 *
8 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>

--- 2281 unchanged lines hidden (view full) ---

2290 }
2291 }
2292 rcu_read_unlock();
2293 cb->args[0] = idx;
2294
2295 return skb->len;
2296}
2297
1/*
2 * INET An implementation of the TCP/IP protocol suite for the LINUX
3 * operating system. INET is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
5 *
6 * Routing netlink socket interface: protocol independent part.
7 *
8 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>

--- 2281 unchanged lines hidden (view full) ---

2290 }
2291 }
2292 rcu_read_unlock();
2293 cb->args[0] = idx;
2294
2295 return skb->len;
2296}
2297
2298static inline size_t bridge_nlmsg_size(void)
2299{
2300 return NLMSG_ALIGN(sizeof(struct ifinfomsg))
2301 + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
2302 + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
2303 + nla_total_size(sizeof(u32)) /* IFLA_MASTER */
2304 + nla_total_size(sizeof(u32)) /* IFLA_MTU */
2305 + nla_total_size(sizeof(u32)) /* IFLA_LINK */
2306 + nla_total_size(sizeof(u32)) /* IFLA_OPERSTATE */
2307 + nla_total_size(sizeof(u8)) /* IFLA_PROTINFO */
2308 + nla_total_size(sizeof(struct nlattr)) /* IFLA_AF_SPEC */
2309 + nla_total_size(sizeof(u16)) /* IFLA_BRIDGE_FLAGS */
2310 + nla_total_size(sizeof(u16)); /* IFLA_BRIDGE_MODE */
2311}
2312
2313static int rtnl_bridge_notify(struct net_device *dev, u16 flags)
2314{
2315 struct net *net = dev_net(dev);
2316 struct net_device *master = dev->master;
2317 struct sk_buff *skb;
2318 int err = -EOPNOTSUPP;
2319
2320 skb = nlmsg_new(bridge_nlmsg_size(), GFP_ATOMIC);
2321 if (!skb) {
2322 err = -ENOMEM;
2323 goto errout;
2324 }
2325
2326 if (!flags && master && master->netdev_ops->ndo_bridge_getlink)
2327 err = master->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev);
2328 else if (dev->netdev_ops->ndo_bridge_getlink)
2329 err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev);
2330
2331 if (err < 0)
2332 goto errout;
2333
2334 rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
2335 return 0;
2336errout:
2337 WARN_ON(err == -EMSGSIZE);
2338 kfree_skb(skb);
2339 rtnl_set_sk_err(net, RTNLGRP_LINK, err);
2340 return err;
2341}
2342
2298static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
2299 void *arg)
2300{
2301 struct net *net = sock_net(skb->sk);
2302 struct ifinfomsg *ifm;
2303 struct net_device *dev;
2343static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
2344 void *arg)
2345{
2346 struct net *net = sock_net(skb->sk);
2347 struct ifinfomsg *ifm;
2348 struct net_device *dev;
2304 int err = -EINVAL;
2349 struct nlattr *br_spec, *attr = NULL;
2350 int rem, err = -EOPNOTSUPP;
2351 u16 flags = 0;
2305
2306 if (nlmsg_len(nlh) < sizeof(*ifm))
2307 return -EINVAL;
2308
2309 ifm = nlmsg_data(nlh);
2310 if (ifm->ifi_family != AF_BRIDGE)
2311 return -EPFNOSUPPORT;
2312
2313 dev = __dev_get_by_index(net, ifm->ifi_index);
2314 if (!dev) {
2315 pr_info("PF_BRIDGE: RTM_SETLINK with unknown ifindex\n");
2316 return -ENODEV;
2317 }
2318
2352
2353 if (nlmsg_len(nlh) < sizeof(*ifm))
2354 return -EINVAL;
2355
2356 ifm = nlmsg_data(nlh);
2357 if (ifm->ifi_family != AF_BRIDGE)
2358 return -EPFNOSUPPORT;
2359
2360 dev = __dev_get_by_index(net, ifm->ifi_index);
2361 if (!dev) {
2362 pr_info("PF_BRIDGE: RTM_SETLINK with unknown ifindex\n");
2363 return -ENODEV;
2364 }
2365
2319 if (dev->master && dev->master->netdev_ops->ndo_bridge_setlink) {
2366 br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
2367 if (br_spec) {
2368 nla_for_each_nested(attr, br_spec, rem) {
2369 if (nla_type(attr) == IFLA_BRIDGE_FLAGS) {
2370 flags = nla_get_u16(attr);
2371 break;
2372 }
2373 }
2374 }
2375
2376 if (!flags || (flags & BRIDGE_FLAGS_MASTER)) {
2377 if (!dev->master ||
2378 !dev->master->netdev_ops->ndo_bridge_setlink) {
2379 err = -EOPNOTSUPP;
2380 goto out;
2381 }
2382
2320 err = dev->master->netdev_ops->ndo_bridge_setlink(dev, nlh);
2321 if (err)
2322 goto out;
2383 err = dev->master->netdev_ops->ndo_bridge_setlink(dev, nlh);
2384 if (err)
2385 goto out;
2386
2387 flags &= ~BRIDGE_FLAGS_MASTER;
2323 }
2324
2388 }
2389
2325 if (dev->netdev_ops->ndo_bridge_setlink)
2326 err = dev->netdev_ops->ndo_bridge_setlink(dev, nlh);
2390 if ((flags & BRIDGE_FLAGS_SELF)) {
2391 if (!dev->netdev_ops->ndo_bridge_setlink)
2392 err = -EOPNOTSUPP;
2393 else
2394 err = dev->netdev_ops->ndo_bridge_setlink(dev, nlh);
2327
2395
2396 if (!err)
2397 flags &= ~BRIDGE_FLAGS_SELF;
2398 }
2399
2400 if (attr && nla_type(attr) == IFLA_BRIDGE_FLAGS)
2401 memcpy(nla_data(attr), &flags, sizeof(flags));
2402 /* Generate event to notify upper layer of bridge change */
2403 if (!err)
2404 err = rtnl_bridge_notify(dev, flags);
2328out:
2329 return err;
2330}
2331
2332/* Protected by RTNL sempahore. */
2333static struct rtattr **rta_buf;
2334static int rtattr_max;
2335

--- 182 unchanged lines hidden ---
2405out:
2406 return err;
2407}
2408
2409/* Protected by RTNL sempahore. */
2410static struct rtattr **rta_buf;
2411static int rtattr_max;
2412

--- 182 unchanged lines hidden ---