|
@@ -18,6 +18,10 @@
|
|
|
/*
|
|
|
* Changes:
|
|
|
*
|
|
|
+ * Brian Braunstein <linuxkernel@bristyle.com> 2007/03/23
|
|
|
+ * Fixed hw address handling. Now net_device.dev_addr is kept consistent
|
|
|
+ * with tun.dev_addr when the address is set by this module.
|
|
|
+ *
|
|
|
* Mike Kershaw <dragorn@kismetwireless.net> 2005/08/14
|
|
|
* Add TUNSETLINK ioctl to set the link encapsulation
|
|
|
*
|
|
@@ -196,7 +200,10 @@ static void tun_net_init(struct net_device *dev)
|
|
|
dev->set_multicast_list = tun_net_mclist;
|
|
|
|
|
|
ether_setup(dev);
|
|
|
- random_ether_addr(dev->dev_addr);
|
|
|
+
|
|
|
+ /* random address already created for us by tun_set_iff, use it */
|
|
|
+ memcpy(dev->dev_addr, tun->dev_addr, min(sizeof(tun->dev_addr), sizeof(dev->dev_addr)) );
|
|
|
+
|
|
|
dev->tx_queue_len = TUN_READQ_SIZE; /* We prefer our own queue length */
|
|
|
break;
|
|
|
}
|
|
@@ -636,6 +643,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
|
|
|
return 0;
|
|
|
|
|
|
case SIOCGIFHWADDR:
|
|
|
+ /* Note: the actual net device's address may be different */
|
|
|
memcpy(ifr.ifr_hwaddr.sa_data, tun->dev_addr,
|
|
|
min(sizeof ifr.ifr_hwaddr.sa_data, sizeof tun->dev_addr));
|
|
|
if (copy_to_user( argp, &ifr, sizeof ifr))
|
|
@@ -643,16 +651,24 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
|
|
|
return 0;
|
|
|
|
|
|
case SIOCSIFHWADDR:
|
|
|
- /** Set the character device's hardware address. This is used when
|
|
|
- * filtering packets being sent from the network device to the character
|
|
|
- * device. */
|
|
|
- memcpy(tun->dev_addr, ifr.ifr_hwaddr.sa_data,
|
|
|
- min(sizeof ifr.ifr_hwaddr.sa_data, sizeof tun->dev_addr));
|
|
|
- DBG(KERN_DEBUG "%s: set hardware address: %x:%x:%x:%x:%x:%x\n",
|
|
|
- tun->dev->name,
|
|
|
- tun->dev_addr[0], tun->dev_addr[1], tun->dev_addr[2],
|
|
|
- tun->dev_addr[3], tun->dev_addr[4], tun->dev_addr[5]);
|
|
|
- return 0;
|
|
|
+ {
|
|
|
+ /* try to set the actual net device's hw address */
|
|
|
+ int ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr);
|
|
|
+
|
|
|
+ if (ret == 0) {
|
|
|
+ /** Set the character device's hardware address. This is used when
|
|
|
+ * filtering packets being sent from the network device to the character
|
|
|
+ * device. */
|
|
|
+ memcpy(tun->dev_addr, ifr.ifr_hwaddr.sa_data,
|
|
|
+ min(sizeof ifr.ifr_hwaddr.sa_data, sizeof tun->dev_addr));
|
|
|
+ DBG(KERN_DEBUG "%s: set hardware address: %x:%x:%x:%x:%x:%x\n",
|
|
|
+ tun->dev->name,
|
|
|
+ tun->dev_addr[0], tun->dev_addr[1], tun->dev_addr[2],
|
|
|
+ tun->dev_addr[3], tun->dev_addr[4], tun->dev_addr[5]);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
|
|
|
case SIOCADDMULTI:
|
|
|
/** Add the specified group to the character device's multicast filter
|