aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/tun.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-04-27 09:26:46 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-04-27 09:26:46 -0700
commit15c54033964a943de7b0763efd3bd0ede7326395 (patch)
tree840b292612d1b5396d5bab5bde537a9013db3ceb /drivers/net/tun.c
parentad5da3cf39a5b11a198929be1f2644e17ecd767e (diff)
parent912a41a4ab935ce8c4308428ec13fc7f8b1f18f4 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (448 commits) [IPV4] nl_fib_lookup: Initialise res.r before fib_res_put(&res) [IPV6]: Fix thinko in ipv6_rthdr_rcv() changes. [IPV4]: Add multipath cached to feature-removal-schedule.txt [WIRELESS] cfg80211: Clarify locking comment. [WIRELESS] cfg80211: Fix locking in wiphy_new. [WEXT] net_device: Don't include wext bits if not required. [WEXT]: Misc code cleanups. [WEXT]: Reduce inline abuse. [WEXT]: Move EXPORT_SYMBOL statements where they belong. [WEXT]: Cleanup early ioctl call path. [WEXT]: Remove options. [WEXT]: Remove dead debug code. [WEXT]: Clean up how wext is called. [WEXT]: Move to net/wireless [AFS]: Eliminate cmpxchg() usage in vlocation code. [RXRPC]: Fix pointers passed to bitops. [RXRPC]: Remove bogus atomic_* overrides. [AFS]: Fix u64 printing in debug logging. [AFS]: Add "directory write" support. [AFS]: Implement the CB.InitCallBackState3 operation. ...
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r--drivers/net/tun.c46
1 files changed, 31 insertions, 15 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 5643d1e84ed..a2c6caaaae9 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -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;
}
@@ -254,11 +261,11 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv,
return -EFAULT;
}
- skb->dev = tun->dev;
switch (tun->flags & TUN_TYPE_MASK) {
case TUN_TUN_DEV:
- skb->mac.raw = skb->data;
+ skb_reset_mac_header(skb);
skb->protocol = pi.proto;
+ skb->dev = tun->dev;
break;
case TUN_TAP_DEV:
skb->protocol = eth_type_trans(skb, tun->dev);
@@ -386,8 +393,8 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
* - we are multicast promiscous.
* - we belong to the multicast group.
*/
- memcpy(addr, skb->data,
- min_t(size_t, sizeof addr, skb->len));
+ skb_copy_from_linear_data(skb, addr, min_t(size_t, sizeof addr,
+ skb->len));
bit_nr = ether_crc(sizeof addr, addr) >> 26;
if ((tun->if_flags & IFF_PROMISC) ||
memcmp(addr, tun->dev_addr, sizeof addr) == 0 ||
@@ -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