aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/rtnetlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r--net/core/rtnetlink.c214
1 files changed, 149 insertions, 65 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 1868625af25e..d8aa20f6a46e 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -780,6 +780,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
780 + nla_total_size(4) /* IFLA_MTU */ 780 + nla_total_size(4) /* IFLA_MTU */
781 + nla_total_size(4) /* IFLA_LINK */ 781 + nla_total_size(4) /* IFLA_LINK */
782 + nla_total_size(4) /* IFLA_MASTER */ 782 + nla_total_size(4) /* IFLA_MASTER */
783 + nla_total_size(1) /* IFLA_CARRIER */
783 + nla_total_size(4) /* IFLA_PROMISCUITY */ 784 + nla_total_size(4) /* IFLA_PROMISCUITY */
784 + nla_total_size(4) /* IFLA_NUM_TX_QUEUES */ 785 + nla_total_size(4) /* IFLA_NUM_TX_QUEUES */
785 + nla_total_size(4) /* IFLA_NUM_RX_QUEUES */ 786 + nla_total_size(4) /* IFLA_NUM_RX_QUEUES */
@@ -879,6 +880,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
879 const struct rtnl_link_stats64 *stats; 880 const struct rtnl_link_stats64 *stats;
880 struct nlattr *attr, *af_spec; 881 struct nlattr *attr, *af_spec;
881 struct rtnl_af_ops *af_ops; 882 struct rtnl_af_ops *af_ops;
883 struct net_device *upper_dev = netdev_master_upper_dev_get(dev);
882 884
883 ASSERT_RTNL(); 885 ASSERT_RTNL();
884 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags); 886 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
@@ -907,8 +909,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
907#endif 909#endif
908 (dev->ifindex != dev->iflink && 910 (dev->ifindex != dev->iflink &&
909 nla_put_u32(skb, IFLA_LINK, dev->iflink)) || 911 nla_put_u32(skb, IFLA_LINK, dev->iflink)) ||
910 (dev->master && 912 (upper_dev &&
911 nla_put_u32(skb, IFLA_MASTER, dev->master->ifindex)) || 913 nla_put_u32(skb, IFLA_MASTER, upper_dev->ifindex)) ||
914 nla_put_u8(skb, IFLA_CARRIER, netif_carrier_ok(dev)) ||
912 (dev->qdisc && 915 (dev->qdisc &&
913 nla_put_string(skb, IFLA_QDISC, dev->qdisc->ops->id)) || 916 nla_put_string(skb, IFLA_QDISC, dev->qdisc->ops->id)) ||
914 (dev->ifalias && 917 (dev->ifalias &&
@@ -1108,6 +1111,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
1108 [IFLA_MTU] = { .type = NLA_U32 }, 1111 [IFLA_MTU] = { .type = NLA_U32 },
1109 [IFLA_LINK] = { .type = NLA_U32 }, 1112 [IFLA_LINK] = { .type = NLA_U32 },
1110 [IFLA_MASTER] = { .type = NLA_U32 }, 1113 [IFLA_MASTER] = { .type = NLA_U32 },
1114 [IFLA_CARRIER] = { .type = NLA_U8 },
1111 [IFLA_TXQLEN] = { .type = NLA_U32 }, 1115 [IFLA_TXQLEN] = { .type = NLA_U32 },
1112 [IFLA_WEIGHT] = { .type = NLA_U32 }, 1116 [IFLA_WEIGHT] = { .type = NLA_U32 },
1113 [IFLA_OPERSTATE] = { .type = NLA_U8 }, 1117 [IFLA_OPERSTATE] = { .type = NLA_U8 },
@@ -1270,16 +1274,16 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr *attr)
1270 1274
1271static int do_set_master(struct net_device *dev, int ifindex) 1275static int do_set_master(struct net_device *dev, int ifindex)
1272{ 1276{
1273 struct net_device *master_dev; 1277 struct net_device *upper_dev = netdev_master_upper_dev_get(dev);
1274 const struct net_device_ops *ops; 1278 const struct net_device_ops *ops;
1275 int err; 1279 int err;
1276 1280
1277 if (dev->master) { 1281 if (upper_dev) {
1278 if (dev->master->ifindex == ifindex) 1282 if (upper_dev->ifindex == ifindex)
1279 return 0; 1283 return 0;
1280 ops = dev->master->netdev_ops; 1284 ops = upper_dev->netdev_ops;
1281 if (ops->ndo_del_slave) { 1285 if (ops->ndo_del_slave) {
1282 err = ops->ndo_del_slave(dev->master, dev); 1286 err = ops->ndo_del_slave(upper_dev, dev);
1283 if (err) 1287 if (err)
1284 return err; 1288 return err;
1285 } else { 1289 } else {
@@ -1288,12 +1292,12 @@ static int do_set_master(struct net_device *dev, int ifindex)
1288 } 1292 }
1289 1293
1290 if (ifindex) { 1294 if (ifindex) {
1291 master_dev = __dev_get_by_index(dev_net(dev), ifindex); 1295 upper_dev = __dev_get_by_index(dev_net(dev), ifindex);
1292 if (!master_dev) 1296 if (!upper_dev)
1293 return -EINVAL; 1297 return -EINVAL;
1294 ops = master_dev->netdev_ops; 1298 ops = upper_dev->netdev_ops;
1295 if (ops->ndo_add_slave) { 1299 if (ops->ndo_add_slave) {
1296 err = ops->ndo_add_slave(master_dev, dev); 1300 err = ops->ndo_add_slave(upper_dev, dev);
1297 if (err) 1301 if (err)
1298 return err; 1302 return err;
1299 } else { 1303 } else {
@@ -1307,7 +1311,6 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
1307 struct nlattr **tb, char *ifname, int modified) 1311 struct nlattr **tb, char *ifname, int modified)
1308{ 1312{
1309 const struct net_device_ops *ops = dev->netdev_ops; 1313 const struct net_device_ops *ops = dev->netdev_ops;
1310 int send_addr_notify = 0;
1311 int err; 1314 int err;
1312 1315
1313 if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD]) { 1316 if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD]) {
@@ -1360,16 +1363,6 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
1360 struct sockaddr *sa; 1363 struct sockaddr *sa;
1361 int len; 1364 int len;
1362 1365
1363 if (!ops->ndo_set_mac_address) {
1364 err = -EOPNOTSUPP;
1365 goto errout;
1366 }
1367
1368 if (!netif_device_present(dev)) {
1369 err = -ENODEV;
1370 goto errout;
1371 }
1372
1373 len = sizeof(sa_family_t) + dev->addr_len; 1366 len = sizeof(sa_family_t) + dev->addr_len;
1374 sa = kmalloc(len, GFP_KERNEL); 1367 sa = kmalloc(len, GFP_KERNEL);
1375 if (!sa) { 1368 if (!sa) {
@@ -1379,13 +1372,11 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
1379 sa->sa_family = dev->type; 1372 sa->sa_family = dev->type;
1380 memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]), 1373 memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]),
1381 dev->addr_len); 1374 dev->addr_len);
1382 err = ops->ndo_set_mac_address(dev, sa); 1375 err = dev_set_mac_address(dev, sa);
1383 kfree(sa); 1376 kfree(sa);
1384 if (err) 1377 if (err)
1385 goto errout; 1378 goto errout;
1386 send_addr_notify = 1;
1387 modified = 1; 1379 modified = 1;
1388 add_device_randomness(dev->dev_addr, dev->addr_len);
1389 } 1380 }
1390 1381
1391 if (tb[IFLA_MTU]) { 1382 if (tb[IFLA_MTU]) {
@@ -1422,7 +1413,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
1422 1413
1423 if (tb[IFLA_BROADCAST]) { 1414 if (tb[IFLA_BROADCAST]) {
1424 nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len); 1415 nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len);
1425 send_addr_notify = 1; 1416 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
1426 } 1417 }
1427 1418
1428 if (ifm->ifi_flags || ifm->ifi_change) { 1419 if (ifm->ifi_flags || ifm->ifi_change) {
@@ -1438,6 +1429,13 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
1438 modified = 1; 1429 modified = 1;
1439 } 1430 }
1440 1431
1432 if (tb[IFLA_CARRIER]) {
1433 err = dev_change_carrier(dev, nla_get_u8(tb[IFLA_CARRIER]));
1434 if (err)
1435 goto errout;
1436 modified = 1;
1437 }
1438
1441 if (tb[IFLA_TXQLEN]) 1439 if (tb[IFLA_TXQLEN])
1442 dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]); 1440 dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
1443 1441
@@ -1536,9 +1534,6 @@ errout:
1536 net_warn_ratelimited("A link change request failed with some changes committed already. Interface %s may have been left with an inconsistent configuration, please check.\n", 1534 net_warn_ratelimited("A link change request failed with some changes committed already. Interface %s may have been left with an inconsistent configuration, please check.\n",
1537 dev->name); 1535 dev->name);
1538 1536
1539 if (send_addr_notify)
1540 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
1541
1542 return err; 1537 return err;
1543} 1538}
1544 1539
@@ -1672,9 +1667,11 @@ struct net_device *rtnl_create_link(struct net *net,
1672 1667
1673 if (tb[IFLA_MTU]) 1668 if (tb[IFLA_MTU])
1674 dev->mtu = nla_get_u32(tb[IFLA_MTU]); 1669 dev->mtu = nla_get_u32(tb[IFLA_MTU]);
1675 if (tb[IFLA_ADDRESS]) 1670 if (tb[IFLA_ADDRESS]) {
1676 memcpy(dev->dev_addr, nla_data(tb[IFLA_ADDRESS]), 1671 memcpy(dev->dev_addr, nla_data(tb[IFLA_ADDRESS]),
1677 nla_len(tb[IFLA_ADDRESS])); 1672 nla_len(tb[IFLA_ADDRESS]));
1673 dev->addr_assign_type = NET_ADDR_SET;
1674 }
1678 if (tb[IFLA_BROADCAST]) 1675 if (tb[IFLA_BROADCAST])
1679 memcpy(dev->broadcast, nla_data(tb[IFLA_BROADCAST]), 1676 memcpy(dev->broadcast, nla_data(tb[IFLA_BROADCAST]),
1680 nla_len(tb[IFLA_BROADCAST])); 1677 nla_len(tb[IFLA_BROADCAST]));
@@ -1992,6 +1989,7 @@ errout:
1992 if (err < 0) 1989 if (err < 0)
1993 rtnl_set_sk_err(net, RTNLGRP_LINK, err); 1990 rtnl_set_sk_err(net, RTNLGRP_LINK, err);
1994} 1991}
1992EXPORT_SYMBOL(rtmsg_ifinfo);
1995 1993
1996static int nlmsg_populate_fdb_fill(struct sk_buff *skb, 1994static int nlmsg_populate_fdb_fill(struct sk_buff *skb,
1997 struct net_device *dev, 1995 struct net_device *dev,
@@ -2054,16 +2052,12 @@ errout:
2054static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 2052static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
2055{ 2053{
2056 struct net *net = sock_net(skb->sk); 2054 struct net *net = sock_net(skb->sk);
2057 struct net_device *master = NULL;
2058 struct ndmsg *ndm; 2055 struct ndmsg *ndm;
2059 struct nlattr *tb[NDA_MAX+1]; 2056 struct nlattr *tb[NDA_MAX+1];
2060 struct net_device *dev; 2057 struct net_device *dev;
2061 u8 *addr; 2058 u8 *addr;
2062 int err; 2059 int err;
2063 2060
2064 if (!capable(CAP_NET_ADMIN))
2065 return -EPERM;
2066
2067 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL); 2061 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
2068 if (err < 0) 2062 if (err < 0)
2069 return err; 2063 return err;
@@ -2096,10 +2090,10 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
2096 /* Support fdb on master device the net/bridge default case */ 2090 /* Support fdb on master device the net/bridge default case */
2097 if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) && 2091 if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) &&
2098 (dev->priv_flags & IFF_BRIDGE_PORT)) { 2092 (dev->priv_flags & IFF_BRIDGE_PORT)) {
2099 master = dev->master; 2093 struct net_device *br_dev = netdev_master_upper_dev_get(dev);
2100 err = master->netdev_ops->ndo_fdb_add(ndm, tb, 2094 const struct net_device_ops *ops = br_dev->netdev_ops;
2101 dev, addr, 2095
2102 nlh->nlmsg_flags); 2096 err = ops->ndo_fdb_add(ndm, tb, dev, addr, nlh->nlmsg_flags);
2103 if (err) 2097 if (err)
2104 goto out; 2098 goto out;
2105 else 2099 else
@@ -2125,7 +2119,7 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
2125{ 2119{
2126 struct net *net = sock_net(skb->sk); 2120 struct net *net = sock_net(skb->sk);
2127 struct ndmsg *ndm; 2121 struct ndmsg *ndm;
2128 struct nlattr *llattr; 2122 struct nlattr *tb[NDA_MAX+1];
2129 struct net_device *dev; 2123 struct net_device *dev;
2130 int err = -EINVAL; 2124 int err = -EINVAL;
2131 __u8 *addr; 2125 __u8 *addr;
@@ -2133,8 +2127,9 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
2133 if (!capable(CAP_NET_ADMIN)) 2127 if (!capable(CAP_NET_ADMIN))
2134 return -EPERM; 2128 return -EPERM;
2135 2129
2136 if (nlmsg_len(nlh) < sizeof(*ndm)) 2130 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
2137 return -EINVAL; 2131 if (err < 0)
2132 return err;
2138 2133
2139 ndm = nlmsg_data(nlh); 2134 ndm = nlmsg_data(nlh);
2140 if (ndm->ndm_ifindex == 0) { 2135 if (ndm->ndm_ifindex == 0) {
@@ -2148,22 +2143,27 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
2148 return -ENODEV; 2143 return -ENODEV;
2149 } 2144 }
2150 2145
2151 llattr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_LLADDR); 2146 if (!tb[NDA_LLADDR] || nla_len(tb[NDA_LLADDR]) != ETH_ALEN) {
2152 if (llattr == NULL || nla_len(llattr) != ETH_ALEN) { 2147 pr_info("PF_BRIDGE: RTM_DELNEIGH with invalid address\n");
2153 pr_info("PF_BRIGDE: RTM_DELNEIGH with invalid address\n"); 2148 return -EINVAL;
2149 }
2150
2151 addr = nla_data(tb[NDA_LLADDR]);
2152 if (!is_valid_ether_addr(addr)) {
2153 pr_info("PF_BRIDGE: RTM_DELNEIGH with invalid ether address\n");
2154 return -EINVAL; 2154 return -EINVAL;
2155 } 2155 }
2156 2156
2157 addr = nla_data(llattr);
2158 err = -EOPNOTSUPP; 2157 err = -EOPNOTSUPP;
2159 2158
2160 /* Support fdb on master device the net/bridge default case */ 2159 /* Support fdb on master device the net/bridge default case */
2161 if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) && 2160 if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) &&
2162 (dev->priv_flags & IFF_BRIDGE_PORT)) { 2161 (dev->priv_flags & IFF_BRIDGE_PORT)) {
2163 struct net_device *master = dev->master; 2162 struct net_device *br_dev = netdev_master_upper_dev_get(dev);
2163 const struct net_device_ops *ops = br_dev->netdev_ops;
2164 2164
2165 if (master->netdev_ops->ndo_fdb_del) 2165 if (ops->ndo_fdb_del)
2166 err = master->netdev_ops->ndo_fdb_del(ndm, dev, addr); 2166 err = ops->ndo_fdb_del(ndm, tb, dev, addr);
2167 2167
2168 if (err) 2168 if (err)
2169 goto out; 2169 goto out;
@@ -2173,7 +2173,7 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
2173 2173
2174 /* Embedded bridge, macvlan, and any other device support */ 2174 /* Embedded bridge, macvlan, and any other device support */
2175 if ((ndm->ndm_flags & NTF_SELF) && dev->netdev_ops->ndo_fdb_del) { 2175 if ((ndm->ndm_flags & NTF_SELF) && dev->netdev_ops->ndo_fdb_del) {
2176 err = dev->netdev_ops->ndo_fdb_del(ndm, dev, addr); 2176 err = dev->netdev_ops->ndo_fdb_del(ndm, tb, dev, addr);
2177 2177
2178 if (!err) { 2178 if (!err) {
2179 rtnl_fdb_notify(dev, addr, RTM_DELNEIGH); 2179 rtnl_fdb_notify(dev, addr, RTM_DELNEIGH);
@@ -2247,9 +2247,11 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
2247 rcu_read_lock(); 2247 rcu_read_lock();
2248 for_each_netdev_rcu(net, dev) { 2248 for_each_netdev_rcu(net, dev) {
2249 if (dev->priv_flags & IFF_BRIDGE_PORT) { 2249 if (dev->priv_flags & IFF_BRIDGE_PORT) {
2250 struct net_device *master = dev->master; 2250 struct net_device *br_dev;
2251 const struct net_device_ops *ops = master->netdev_ops; 2251 const struct net_device_ops *ops;
2252 2252
2253 br_dev = netdev_master_upper_dev_get(dev);
2254 ops = br_dev->netdev_ops;
2253 if (ops->ndo_fdb_dump) 2255 if (ops->ndo_fdb_dump)
2254 idx = ops->ndo_fdb_dump(skb, cb, dev, idx); 2256 idx = ops->ndo_fdb_dump(skb, cb, dev, idx);
2255 } 2257 }
@@ -2270,6 +2272,7 @@ int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
2270 struct ifinfomsg *ifm; 2272 struct ifinfomsg *ifm;
2271 struct nlattr *br_afspec; 2273 struct nlattr *br_afspec;
2272 u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN; 2274 u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
2275 struct net_device *br_dev = netdev_master_upper_dev_get(dev);
2273 2276
2274 nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*ifm), NLM_F_MULTI); 2277 nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*ifm), NLM_F_MULTI);
2275 if (nlh == NULL) 2278 if (nlh == NULL)
@@ -2287,8 +2290,8 @@ int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
2287 if (nla_put_string(skb, IFLA_IFNAME, dev->name) || 2290 if (nla_put_string(skb, IFLA_IFNAME, dev->name) ||
2288 nla_put_u32(skb, IFLA_MTU, dev->mtu) || 2291 nla_put_u32(skb, IFLA_MTU, dev->mtu) ||
2289 nla_put_u8(skb, IFLA_OPERSTATE, operstate) || 2292 nla_put_u8(skb, IFLA_OPERSTATE, operstate) ||
2290 (dev->master && 2293 (br_dev &&
2291 nla_put_u32(skb, IFLA_MASTER, dev->master->ifindex)) || 2294 nla_put_u32(skb, IFLA_MASTER, br_dev->ifindex)) ||
2292 (dev->addr_len && 2295 (dev->addr_len &&
2293 nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) || 2296 nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) ||
2294 (dev->ifindex != dev->iflink && 2297 (dev->ifindex != dev->iflink &&
@@ -2320,23 +2323,31 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
2320 int idx = 0; 2323 int idx = 0;
2321 u32 portid = NETLINK_CB(cb->skb).portid; 2324 u32 portid = NETLINK_CB(cb->skb).portid;
2322 u32 seq = cb->nlh->nlmsg_seq; 2325 u32 seq = cb->nlh->nlmsg_seq;
2326 struct nlattr *extfilt;
2327 u32 filter_mask = 0;
2328
2329 extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct rtgenmsg),
2330 IFLA_EXT_MASK);
2331 if (extfilt)
2332 filter_mask = nla_get_u32(extfilt);
2323 2333
2324 rcu_read_lock(); 2334 rcu_read_lock();
2325 for_each_netdev_rcu(net, dev) { 2335 for_each_netdev_rcu(net, dev) {
2326 const struct net_device_ops *ops = dev->netdev_ops; 2336 const struct net_device_ops *ops = dev->netdev_ops;
2327 struct net_device *master = dev->master; 2337 struct net_device *br_dev = netdev_master_upper_dev_get(dev);
2328 2338
2329 if (master && master->netdev_ops->ndo_bridge_getlink) { 2339 if (br_dev && br_dev->netdev_ops->ndo_bridge_getlink) {
2330 if (idx >= cb->args[0] && 2340 if (idx >= cb->args[0] &&
2331 master->netdev_ops->ndo_bridge_getlink( 2341 br_dev->netdev_ops->ndo_bridge_getlink(
2332 skb, portid, seq, dev) < 0) 2342 skb, portid, seq, dev, filter_mask) < 0)
2333 break; 2343 break;
2334 idx++; 2344 idx++;
2335 } 2345 }
2336 2346
2337 if (ops->ndo_bridge_getlink) { 2347 if (ops->ndo_bridge_getlink) {
2338 if (idx >= cb->args[0] && 2348 if (idx >= cb->args[0] &&
2339 ops->ndo_bridge_getlink(skb, portid, seq, dev) < 0) 2349 ops->ndo_bridge_getlink(skb, portid, seq, dev,
2350 filter_mask) < 0)
2340 break; 2351 break;
2341 idx++; 2352 idx++;
2342 } 2353 }
@@ -2365,7 +2376,7 @@ static inline size_t bridge_nlmsg_size(void)
2365static int rtnl_bridge_notify(struct net_device *dev, u16 flags) 2376static int rtnl_bridge_notify(struct net_device *dev, u16 flags)
2366{ 2377{
2367 struct net *net = dev_net(dev); 2378 struct net *net = dev_net(dev);
2368 struct net_device *master = dev->master; 2379 struct net_device *br_dev = netdev_master_upper_dev_get(dev);
2369 struct sk_buff *skb; 2380 struct sk_buff *skb;
2370 int err = -EOPNOTSUPP; 2381 int err = -EOPNOTSUPP;
2371 2382
@@ -2376,15 +2387,15 @@ static int rtnl_bridge_notify(struct net_device *dev, u16 flags)
2376 } 2387 }
2377 2388
2378 if ((!flags || (flags & BRIDGE_FLAGS_MASTER)) && 2389 if ((!flags || (flags & BRIDGE_FLAGS_MASTER)) &&
2379 master && master->netdev_ops->ndo_bridge_getlink) { 2390 br_dev && br_dev->netdev_ops->ndo_bridge_getlink) {
2380 err = master->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev); 2391 err = br_dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0);
2381 if (err < 0) 2392 if (err < 0)
2382 goto errout; 2393 goto errout;
2383 } 2394 }
2384 2395
2385 if ((flags & BRIDGE_FLAGS_SELF) && 2396 if ((flags & BRIDGE_FLAGS_SELF) &&
2386 dev->netdev_ops->ndo_bridge_getlink) { 2397 dev->netdev_ops->ndo_bridge_getlink) {
2387 err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev); 2398 err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0);
2388 if (err < 0) 2399 if (err < 0)
2389 goto errout; 2400 goto errout;
2390 } 2401 }
@@ -2436,13 +2447,14 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
2436 oflags = flags; 2447 oflags = flags;
2437 2448
2438 if (!flags || (flags & BRIDGE_FLAGS_MASTER)) { 2449 if (!flags || (flags & BRIDGE_FLAGS_MASTER)) {
2439 if (!dev->master || 2450 struct net_device *br_dev = netdev_master_upper_dev_get(dev);
2440 !dev->master->netdev_ops->ndo_bridge_setlink) { 2451
2452 if (!br_dev || !br_dev->netdev_ops->ndo_bridge_setlink) {
2441 err = -EOPNOTSUPP; 2453 err = -EOPNOTSUPP;
2442 goto out; 2454 goto out;
2443 } 2455 }
2444 2456
2445 err = dev->master->netdev_ops->ndo_bridge_setlink(dev, nlh); 2457 err = br_dev->netdev_ops->ndo_bridge_setlink(dev, nlh);
2446 if (err) 2458 if (err)
2447 goto out; 2459 goto out;
2448 2460
@@ -2468,6 +2480,77 @@ out:
2468 return err; 2480 return err;
2469} 2481}
2470 2482
2483static int rtnl_bridge_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,
2484 void *arg)
2485{
2486 struct net *net = sock_net(skb->sk);
2487 struct ifinfomsg *ifm;
2488 struct net_device *dev;
2489 struct nlattr *br_spec, *attr = NULL;
2490 int rem, err = -EOPNOTSUPP;
2491 u16 oflags, flags = 0;
2492 bool have_flags = false;
2493
2494 if (nlmsg_len(nlh) < sizeof(*ifm))
2495 return -EINVAL;
2496
2497 ifm = nlmsg_data(nlh);
2498 if (ifm->ifi_family != AF_BRIDGE)
2499 return -EPFNOSUPPORT;
2500
2501 dev = __dev_get_by_index(net, ifm->ifi_index);
2502 if (!dev) {
2503 pr_info("PF_BRIDGE: RTM_SETLINK with unknown ifindex\n");
2504 return -ENODEV;
2505 }
2506
2507 br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
2508 if (br_spec) {
2509 nla_for_each_nested(attr, br_spec, rem) {
2510 if (nla_type(attr) == IFLA_BRIDGE_FLAGS) {
2511 have_flags = true;
2512 flags = nla_get_u16(attr);
2513 break;
2514 }
2515 }
2516 }
2517
2518 oflags = flags;
2519
2520 if (!flags || (flags & BRIDGE_FLAGS_MASTER)) {
2521 struct net_device *br_dev = netdev_master_upper_dev_get(dev);
2522
2523 if (!br_dev || !br_dev->netdev_ops->ndo_bridge_dellink) {
2524 err = -EOPNOTSUPP;
2525 goto out;
2526 }
2527
2528 err = br_dev->netdev_ops->ndo_bridge_dellink(dev, nlh);
2529 if (err)
2530 goto out;
2531
2532 flags &= ~BRIDGE_FLAGS_MASTER;
2533 }
2534
2535 if ((flags & BRIDGE_FLAGS_SELF)) {
2536 if (!dev->netdev_ops->ndo_bridge_dellink)
2537 err = -EOPNOTSUPP;
2538 else
2539 err = dev->netdev_ops->ndo_bridge_dellink(dev, nlh);
2540
2541 if (!err)
2542 flags &= ~BRIDGE_FLAGS_SELF;
2543 }
2544
2545 if (have_flags)
2546 memcpy(nla_data(attr), &flags, sizeof(flags));
2547 /* Generate event to notify upper layer of bridge change */
2548 if (!err)
2549 err = rtnl_bridge_notify(dev, oflags);
2550out:
2551 return err;
2552}
2553
2471/* Protected by RTNL sempahore. */ 2554/* Protected by RTNL sempahore. */
2472static struct rtattr **rta_buf; 2555static struct rtattr **rta_buf;
2473static int rtattr_max; 2556static int rtattr_max;
@@ -2651,6 +2734,7 @@ void __init rtnetlink_init(void)
2651 rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, rtnl_fdb_dump, NULL); 2734 rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, rtnl_fdb_dump, NULL);
2652 2735
2653 rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, rtnl_bridge_getlink, NULL); 2736 rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, rtnl_bridge_getlink, NULL);
2737 rtnl_register(PF_BRIDGE, RTM_DELLINK, rtnl_bridge_dellink, NULL, NULL);
2654 rtnl_register(PF_BRIDGE, RTM_SETLINK, rtnl_bridge_setlink, NULL, NULL); 2738 rtnl_register(PF_BRIDGE, RTM_SETLINK, rtnl_bridge_setlink, NULL, NULL);
2655} 2739}
2656 2740