]> err.no Git - linux-2.6/blobdiff - net/core/rtnetlink.c
[PKTGEN]: Add missing KERN_* tags to printk()s.
[linux-2.6] / net / core / rtnetlink.c
index 06c0c5afabf0a141239929ec9a35e8dba4a27dc2..06eccca8cb5d305e0a6d2750e724cc65f0666235 100644 (file)
@@ -97,6 +97,19 @@ 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, int len)
+{
+       if (RTA_PAYLOAD(rta) < len)
+               return -1;
+       if (RTA_PAYLOAD(rta) >= RTA_ALIGN(len) + sizeof(struct rtattr)) {
+               rta = RTA_DATA(rta) + RTA_ALIGN(len);
+               return rtattr_parse_nested(tb, maxattr, rta);
+       }
+       memset(tb, 0, sizeof(struct rtattr *) * maxattr);
+       return 0;
+}
+
 static struct rtnl_link *rtnl_msg_handlers[NPROTO];
 
 static inline int rtm_msgindex(int msgtype)
@@ -257,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;
 }
@@ -285,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);
 }
 
@@ -1012,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) {
@@ -1045,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])
@@ -1054,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);
@@ -1297,6 +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(rtnetlink_put_metrics);
 EXPORT_SYMBOL(rtnl_lock);
 EXPORT_SYMBOL(rtnl_trylock);