Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=0e06877c6fdbc67b1132be895f995acd1ff30135
Commit:     0e06877c6fdbc67b1132be895f995acd1ff30135
Parent:     2d85cba2b272a5201a60966a65a4f8c0bcc0bb71
Author:     Patrick McHardy <[EMAIL PROTECTED]>
AuthorDate: Wed Jul 11 19:42:31 2007 -0700
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Wed Jul 11 19:45:36 2007 -0700

    [RTNETLINK]: rtnl_link: allow specifying initial device address
    
    Drivers need to validate the initial addresses in their netlink attribute
    validation function or manually reject them if they can't support this.
    
    Signed-off-by: Patrick McHardy <[EMAIL PROTECTED]>
    Signed-off-by: David S. Miller <[EMAIL PROTECTED]>
---
 drivers/net/dummy.c      |   12 ++++++++++++
 drivers/net/ifb.c        |   12 ++++++++++++
 net/8021q/vlan.c         |    8 ++++++--
 net/8021q/vlan_netlink.c |    7 +++++++
 net/core/rtnetlink.c     |    9 +++++++--
 5 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 373ff70..756a6bc 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -84,9 +84,21 @@ static int dummy_xmit(struct sk_buff *skb, struct net_device 
*dev)
        return 0;
 }
 
+static int dummy_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+       if (tb[IFLA_ADDRESS]) {
+               if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
+                       return -EINVAL;
+               if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
+                       return -EADDRNOTAVAIL;
+       }
+       return 0;
+}
+
 static struct rtnl_link_ops dummy_link_ops __read_mostly = {
        .kind           = "dummy",
        .setup          = dummy_setup,
+       .validate       = dummy_validate,
 };
 
 /* Number of dummy devices to be set up by this module. */
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index c8e7c8f..f5c3598 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -221,10 +221,22 @@ static int ifb_open(struct net_device *dev)
        return 0;
 }
 
+static int ifb_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+       if (tb[IFLA_ADDRESS]) {
+               if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
+                       return -EINVAL;
+               if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
+                       return -EADDRNOTAVAIL;
+       }
+       return 0;
+}
+
 static struct rtnl_link_ops ifb_link_ops __read_mostly = {
        .kind           = "ifb",
        .priv_size      = sizeof(struct ifb_private),
        .setup          = ifb_setup,
+       .validate       = ifb_validate,
 };
 
 /* Number of ifb devices to be set up by this module. */
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 34c1d0b..abb9900 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -324,8 +324,10 @@ static int vlan_dev_init(struct net_device *dev)
                                          (1<<__LINK_STATE_DORMANT))) |
                      (1<<__LINK_STATE_PRESENT);
 
-       memcpy(dev->broadcast, real_dev->broadcast, real_dev->addr_len);
-       memcpy(dev->dev_addr, real_dev->dev_addr, real_dev->addr_len);
+       if (is_zero_ether_addr(dev->dev_addr))
+               memcpy(dev->dev_addr, real_dev->dev_addr, dev->addr_len);
+       if (is_zero_ether_addr(dev->broadcast))
+               memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len);
 
        if (real_dev->features & NETIF_F_HW_VLAN_TX) {
                dev->hard_header     = real_dev->hard_header;
@@ -373,6 +375,8 @@ void vlan_setup(struct net_device *new_dev)
        new_dev->set_multicast_list = vlan_dev_set_multicast_list;
        new_dev->destructor = free_netdev;
        new_dev->do_ioctl = vlan_dev_ioctl;
+
+       memset(new_dev->broadcast, 0, sizeof(ETH_ALEN));
 }
 
 static void vlan_transfer_operstate(const struct net_device *dev, struct 
net_device *vlandev)
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c
index 844c7e4..6cdd1e0 100644
--- a/net/8021q/vlan_netlink.c
+++ b/net/8021q/vlan_netlink.c
@@ -41,6 +41,13 @@ static int vlan_validate(struct nlattr *tb[], struct nlattr 
*data[])
        u16 id;
        int err;
 
+       if (tb[IFLA_ADDRESS]) {
+               if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
+                       return -EINVAL;
+               if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
+                       return -EADDRNOTAVAIL;
+       }
+
        if (!data)
                return -EINVAL;
 
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 7b6b163..864cbdf 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1032,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) {
@@ -1065,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])
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to