diff options
author | Jeff Garzik <jgarzik@redhat.com> | 2007-10-23 23:19:37 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-24 00:27:50 -0400 |
commit | bada339ba24dee9e143bfb42e1dc61f146619846 (patch) | |
tree | 69e14af15764a1b38d61cd1f0b55560e45779f23 | |
parent | c9927c2bf4f45bb85e8b502ab3fb79ad6483c244 (diff) |
[NET]: Validate device addr prior to interface-up
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/netdevice.h | 2 | ||||
-rw-r--r-- | net/core/dev.c | 14 | ||||
-rw-r--r-- | net/ethernet/eth.c | 9 |
3 files changed, 20 insertions, 5 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index c4de536cefa3..811024e311bd 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -669,6 +669,8 @@ struct net_device | |||
669 | #define HAVE_SET_MAC_ADDR | 669 | #define HAVE_SET_MAC_ADDR |
670 | int (*set_mac_address)(struct net_device *dev, | 670 | int (*set_mac_address)(struct net_device *dev, |
671 | void *addr); | 671 | void *addr); |
672 | #define HAVE_VALIDATE_ADDR | ||
673 | int (*validate_addr)(struct net_device *dev); | ||
672 | #define HAVE_PRIVATE_IOCTL | 674 | #define HAVE_PRIVATE_IOCTL |
673 | int (*do_ioctl)(struct net_device *dev, | 675 | int (*do_ioctl)(struct net_device *dev, |
674 | struct ifreq *ifr, int cmd); | 676 | struct ifreq *ifr, int cmd); |
diff --git a/net/core/dev.c b/net/core/dev.c index 872658927e47..f861555cc525 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -1007,17 +1007,20 @@ int dev_open(struct net_device *dev) | |||
1007 | * Call device private open method | 1007 | * Call device private open method |
1008 | */ | 1008 | */ |
1009 | set_bit(__LINK_STATE_START, &dev->state); | 1009 | set_bit(__LINK_STATE_START, &dev->state); |
1010 | if (dev->open) { | 1010 | |
1011 | if (dev->validate_addr) | ||
1012 | ret = dev->validate_addr(dev); | ||
1013 | |||
1014 | if (!ret && dev->open) | ||
1011 | ret = dev->open(dev); | 1015 | ret = dev->open(dev); |
1012 | if (ret) | ||
1013 | clear_bit(__LINK_STATE_START, &dev->state); | ||
1014 | } | ||
1015 | 1016 | ||
1016 | /* | 1017 | /* |
1017 | * If it went open OK then: | 1018 | * If it went open OK then: |
1018 | */ | 1019 | */ |
1019 | 1020 | ||
1020 | if (!ret) { | 1021 | if (ret) |
1022 | clear_bit(__LINK_STATE_START, &dev->state); | ||
1023 | else { | ||
1021 | /* | 1024 | /* |
1022 | * Set the flags. | 1025 | * Set the flags. |
1023 | */ | 1026 | */ |
@@ -1038,6 +1041,7 @@ int dev_open(struct net_device *dev) | |||
1038 | */ | 1041 | */ |
1039 | call_netdevice_notifiers(NETDEV_UP, dev); | 1042 | call_netdevice_notifiers(NETDEV_UP, dev); |
1040 | } | 1043 | } |
1044 | |||
1041 | return ret; | 1045 | return ret; |
1042 | } | 1046 | } |
1043 | 1047 | ||
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index ed8a3d49487d..6b2e454ae313 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c | |||
@@ -298,6 +298,14 @@ static int eth_change_mtu(struct net_device *dev, int new_mtu) | |||
298 | return 0; | 298 | return 0; |
299 | } | 299 | } |
300 | 300 | ||
301 | static int eth_validate_addr(struct net_device *dev) | ||
302 | { | ||
303 | if (!is_valid_ether_addr(dev->dev_addr)) | ||
304 | return -EINVAL; | ||
305 | |||
306 | return 0; | ||
307 | } | ||
308 | |||
301 | const struct header_ops eth_header_ops ____cacheline_aligned = { | 309 | const struct header_ops eth_header_ops ____cacheline_aligned = { |
302 | .create = eth_header, | 310 | .create = eth_header, |
303 | .parse = eth_header_parse, | 311 | .parse = eth_header_parse, |
@@ -317,6 +325,7 @@ void ether_setup(struct net_device *dev) | |||
317 | 325 | ||
318 | dev->change_mtu = eth_change_mtu; | 326 | dev->change_mtu = eth_change_mtu; |
319 | dev->set_mac_address = eth_mac_addr; | 327 | dev->set_mac_address = eth_mac_addr; |
328 | dev->validate_addr = eth_validate_addr; | ||
320 | 329 | ||
321 | dev->type = ARPHRD_ETHER; | 330 | dev->type = ARPHRD_ETHER; |
322 | dev->hard_header_len = ETH_HLEN; | 331 | dev->hard_header_len = ETH_HLEN; |