]> err.no Git - linux-2.6/blobdiff - net/core/rtnetlink.c
O_CLOEXEC for SCM_RIGHTS
[linux-2.6] / net / core / rtnetlink.c
index c25d23ba6d5d928923290761dc341633b93a8ae8..864cbdf31ed7f49b2ab73c44b1de818db70b505d 100644 (file)
@@ -97,13 +97,11 @@ int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len)
        return 0;
 }
 
-int rtattr_parse_nested_compat(struct rtattr *tb[], int maxattr,
-                              struct rtattr *rta, void **data, int len)
+int __rtattr_parse_nested_compat(struct rtattr *tb[], int maxattr,
+                                struct rtattr *rta, int len)
 {
        if (RTA_PAYLOAD(rta) < len)
                return -1;
-       *data = RTA_DATA(rta);
-
        if (RTA_PAYLOAD(rta) >= RTA_ALIGN(len) + sizeof(struct rtattr)) {
                rta = RTA_DATA(rta) + RTA_ALIGN(len);
                return rtattr_parse_nested(tb, maxattr, rta);
@@ -272,6 +270,9 @@ static LIST_HEAD(link_ops);
  */
 int __rtnl_link_register(struct rtnl_link_ops *ops)
 {
+       if (!ops->dellink)
+               ops->dellink = unregister_netdevice;
+
        list_add_tail(&ops->list, &link_ops);
        return 0;
 }
@@ -300,12 +301,16 @@ EXPORT_SYMBOL_GPL(rtnl_link_register);
  * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
  * @ops: struct rtnl_link_ops * to unregister
  *
- * The caller must hold the rtnl_mutex. This function should be used
- * by drivers that unregister devices during module unloading. It must
- * be called after unregistering the devices.
+ * The caller must hold the rtnl_mutex.
  */
 void __rtnl_link_unregister(struct rtnl_link_ops *ops)
 {
+       struct net_device *dev, *n;
+
+       for_each_netdev_safe(dev, n) {
+               if (dev->rtnl_link_ops == ops)
+                       ops->dellink(dev);
+       }
        list_del(&ops->list);
 }
 
@@ -1027,8 +1032,7 @@ replay:
 
                if (ifm->ifi_index || ifm->ifi_flags || ifm->ifi_change)
                        return -EOPNOTSUPP;
-               if (tb[IFLA_ADDRESS] || tb[IFLA_BROADCAST] || tb[IFLA_MAP] ||
-                   tb[IFLA_MASTER] || tb[IFLA_PROTINFO])
+               if (tb[IFLA_MAP] || tb[IFLA_MASTER] || tb[IFLA_PROTINFO])
                        return -EOPNOTSUPP;
 
                if (!ops) {
@@ -1060,6 +1064,12 @@ replay:
 
                if (tb[IFLA_MTU])
                        dev->mtu = nla_get_u32(tb[IFLA_MTU]);
+               if (tb[IFLA_ADDRESS])
+                       memcpy(dev->dev_addr, nla_data(tb[IFLA_ADDRESS]),
+                              nla_len(tb[IFLA_ADDRESS]));
+               if (tb[IFLA_BROADCAST])
+                       memcpy(dev->broadcast, nla_data(tb[IFLA_BROADCAST]),
+                              nla_len(tb[IFLA_BROADCAST]));
                if (tb[IFLA_TXQLEN])
                        dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
                if (tb[IFLA_WEIGHT])
@@ -1069,7 +1079,10 @@ replay:
                if (tb[IFLA_LINKMODE])
                        dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
 
-               err = ops->newlink(dev, tb, data);
+               if (ops->newlink)
+                       err = ops->newlink(dev, tb, data);
+               else
+                       err = register_netdevice(dev);
 err_free:
                if (err < 0)
                        free_netdev(dev);
@@ -1312,7 +1325,7 @@ void __init rtnetlink_init(void)
 EXPORT_SYMBOL(__rta_fill);
 EXPORT_SYMBOL(rtattr_strlcpy);
 EXPORT_SYMBOL(rtattr_parse);
-EXPORT_SYMBOL(rtattr_parse_nested_compat);
+EXPORT_SYMBOL(__rtattr_parse_nested_compat);
 EXPORT_SYMBOL(rtnetlink_put_metrics);
 EXPORT_SYMBOL(rtnl_lock);
 EXPORT_SYMBOL(rtnl_trylock);