diff options
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r-- | drivers/net/tun.c | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 4d461595406d..a2c6caaaae93 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -18,6 +18,10 @@ | |||
18 | /* | 18 | /* |
19 | * Changes: | 19 | * Changes: |
20 | * | 20 | * |
21 | * Brian Braunstein <linuxkernel@bristyle.com> 2007/03/23 | ||
22 | * Fixed hw address handling. Now net_device.dev_addr is kept consistent | ||
23 | * with tun.dev_addr when the address is set by this module. | ||
24 | * | ||
21 | * Mike Kershaw <dragorn@kismetwireless.net> 2005/08/14 | 25 | * Mike Kershaw <dragorn@kismetwireless.net> 2005/08/14 |
22 | * Add TUNSETLINK ioctl to set the link encapsulation | 26 | * Add TUNSETLINK ioctl to set the link encapsulation |
23 | * | 27 | * |
@@ -196,7 +200,10 @@ static void tun_net_init(struct net_device *dev) | |||
196 | dev->set_multicast_list = tun_net_mclist; | 200 | dev->set_multicast_list = tun_net_mclist; |
197 | 201 | ||
198 | ether_setup(dev); | 202 | ether_setup(dev); |
199 | random_ether_addr(dev->dev_addr); | 203 | |
204 | /* random address already created for us by tun_set_iff, use it */ | ||
205 | memcpy(dev->dev_addr, tun->dev_addr, min(sizeof(tun->dev_addr), sizeof(dev->dev_addr)) ); | ||
206 | |||
200 | dev->tx_queue_len = TUN_READQ_SIZE; /* We prefer our own queue length */ | 207 | dev->tx_queue_len = TUN_READQ_SIZE; /* We prefer our own queue length */ |
201 | break; | 208 | break; |
202 | } | 209 | } |
@@ -636,6 +643,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, | |||
636 | return 0; | 643 | return 0; |
637 | 644 | ||
638 | case SIOCGIFHWADDR: | 645 | case SIOCGIFHWADDR: |
646 | /* Note: the actual net device's address may be different */ | ||
639 | memcpy(ifr.ifr_hwaddr.sa_data, tun->dev_addr, | 647 | memcpy(ifr.ifr_hwaddr.sa_data, tun->dev_addr, |
640 | min(sizeof ifr.ifr_hwaddr.sa_data, sizeof tun->dev_addr)); | 648 | min(sizeof ifr.ifr_hwaddr.sa_data, sizeof tun->dev_addr)); |
641 | if (copy_to_user( argp, &ifr, sizeof ifr)) | 649 | if (copy_to_user( argp, &ifr, sizeof ifr)) |
@@ -643,16 +651,24 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, | |||
643 | return 0; | 651 | return 0; |
644 | 652 | ||
645 | case SIOCSIFHWADDR: | 653 | case SIOCSIFHWADDR: |
646 | /** Set the character device's hardware address. This is used when | 654 | { |
647 | * filtering packets being sent from the network device to the character | 655 | /* try to set the actual net device's hw address */ |
648 | * device. */ | 656 | int ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr); |
649 | memcpy(tun->dev_addr, ifr.ifr_hwaddr.sa_data, | 657 | |
650 | min(sizeof ifr.ifr_hwaddr.sa_data, sizeof tun->dev_addr)); | 658 | if (ret == 0) { |
651 | DBG(KERN_DEBUG "%s: set hardware address: %x:%x:%x:%x:%x:%x\n", | 659 | /** Set the character device's hardware address. This is used when |
652 | tun->dev->name, | 660 | * filtering packets being sent from the network device to the character |
653 | tun->dev_addr[0], tun->dev_addr[1], tun->dev_addr[2], | 661 | * device. */ |
654 | tun->dev_addr[3], tun->dev_addr[4], tun->dev_addr[5]); | 662 | memcpy(tun->dev_addr, ifr.ifr_hwaddr.sa_data, |
655 | return 0; | 663 | min(sizeof ifr.ifr_hwaddr.sa_data, sizeof tun->dev_addr)); |
664 | DBG(KERN_DEBUG "%s: set hardware address: %x:%x:%x:%x:%x:%x\n", | ||
665 | tun->dev->name, | ||
666 | tun->dev_addr[0], tun->dev_addr[1], tun->dev_addr[2], | ||
667 | tun->dev_addr[3], tun->dev_addr[4], tun->dev_addr[5]); | ||
668 | } | ||
669 | |||
670 | return ret; | ||
671 | } | ||
656 | 672 | ||
657 | case SIOCADDMULTI: | 673 | case SIOCADDMULTI: |
658 | /** Add the specified group to the character device's multicast filter | 674 | /** Add the specified group to the character device's multicast filter |