aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tun.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r--drivers/net/tun.c93
1 files changed, 70 insertions, 23 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index e470ae59d405..06a039414628 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -111,6 +111,7 @@ do { \
111#define TUN_FASYNC IFF_ATTACH_QUEUE 111#define TUN_FASYNC IFF_ATTACH_QUEUE
112/* High bits in flags field are unused. */ 112/* High bits in flags field are unused. */
113#define TUN_VNET_LE 0x80000000 113#define TUN_VNET_LE 0x80000000
114#define TUN_VNET_BE 0x40000000
114 115
115#define TUN_FEATURES (IFF_NO_PI | IFF_ONE_QUEUE | IFF_VNET_HDR | \ 116#define TUN_FEATURES (IFF_NO_PI | IFF_ONE_QUEUE | IFF_VNET_HDR | \
116 IFF_MULTI_QUEUE) 117 IFF_MULTI_QUEUE)
@@ -146,7 +147,6 @@ struct tun_file {
146 struct socket socket; 147 struct socket socket;
147 struct socket_wq wq; 148 struct socket_wq wq;
148 struct tun_struct __rcu *tun; 149 struct tun_struct __rcu *tun;
149 struct net *net;
150 struct fasync_struct *fasync; 150 struct fasync_struct *fasync;
151 /* only used for fasnyc */ 151 /* only used for fasnyc */
152 unsigned int flags; 152 unsigned int flags;
@@ -206,14 +206,68 @@ struct tun_struct {
206 u32 flow_count; 206 u32 flow_count;
207}; 207};
208 208
209#ifdef CONFIG_TUN_VNET_CROSS_LE
210static inline bool tun_legacy_is_little_endian(struct tun_struct *tun)
211{
212 return tun->flags & TUN_VNET_BE ? false :
213 virtio_legacy_is_little_endian();
214}
215
216static long tun_get_vnet_be(struct tun_struct *tun, int __user *argp)
217{
218 int be = !!(tun->flags & TUN_VNET_BE);
219
220 if (put_user(be, argp))
221 return -EFAULT;
222
223 return 0;
224}
225
226static long tun_set_vnet_be(struct tun_struct *tun, int __user *argp)
227{
228 int be;
229
230 if (get_user(be, argp))
231 return -EFAULT;
232
233 if (be)
234 tun->flags |= TUN_VNET_BE;
235 else
236 tun->flags &= ~TUN_VNET_BE;
237
238 return 0;
239}
240#else
241static inline bool tun_legacy_is_little_endian(struct tun_struct *tun)
242{
243 return virtio_legacy_is_little_endian();
244}
245
246static long tun_get_vnet_be(struct tun_struct *tun, int __user *argp)
247{
248 return -EINVAL;
249}
250
251static long tun_set_vnet_be(struct tun_struct *tun, int __user *argp)
252{
253 return -EINVAL;
254}
255#endif /* CONFIG_TUN_VNET_CROSS_LE */
256
257static inline bool tun_is_little_endian(struct tun_struct *tun)
258{
259 return tun->flags & TUN_VNET_LE ||
260 tun_legacy_is_little_endian(tun);
261}
262
209static inline u16 tun16_to_cpu(struct tun_struct *tun, __virtio16 val) 263static inline u16 tun16_to_cpu(struct tun_struct *tun, __virtio16 val)
210{ 264{
211 return __virtio16_to_cpu(tun->flags & TUN_VNET_LE, val); 265 return __virtio16_to_cpu(tun_is_little_endian(tun), val);
212} 266}
213 267
214static inline __virtio16 cpu_to_tun16(struct tun_struct *tun, u16 val) 268static inline __virtio16 cpu_to_tun16(struct tun_struct *tun, u16 val)
215{ 269{
216 return __cpu_to_virtio16(tun->flags & TUN_VNET_LE, val); 270 return __cpu_to_virtio16(tun_is_little_endian(tun), val);
217} 271}
218 272
219static inline u32 tun_hashfn(u32 rxhash) 273static inline u32 tun_hashfn(u32 rxhash)
@@ -493,10 +547,7 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
493 tun->dev->reg_state == NETREG_REGISTERED) 547 tun->dev->reg_state == NETREG_REGISTERED)
494 unregister_netdevice(tun->dev); 548 unregister_netdevice(tun->dev);
495 } 549 }
496 550 sock_put(&tfile->sk);
497 BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED,
498 &tfile->socket.flags));
499 sk_release_kernel(&tfile->sk);
500 } 551 }
501} 552}
502 553
@@ -1492,18 +1543,10 @@ out:
1492 return ret; 1543 return ret;
1493} 1544}
1494 1545
1495static int tun_release(struct socket *sock)
1496{
1497 if (sock->sk)
1498 sock_put(sock->sk);
1499 return 0;
1500}
1501
1502/* Ops structure to mimic raw sockets with tun */ 1546/* Ops structure to mimic raw sockets with tun */
1503static const struct proto_ops tun_socket_ops = { 1547static const struct proto_ops tun_socket_ops = {
1504 .sendmsg = tun_sendmsg, 1548 .sendmsg = tun_sendmsg,
1505 .recvmsg = tun_recvmsg, 1549 .recvmsg = tun_recvmsg,
1506 .release = tun_release,
1507}; 1550};
1508 1551
1509static struct proto tun_proto = { 1552static struct proto tun_proto = {
@@ -1865,7 +1908,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
1865 if (cmd == TUNSETIFF && !tun) { 1908 if (cmd == TUNSETIFF && !tun) {
1866 ifr.ifr_name[IFNAMSIZ-1] = '\0'; 1909 ifr.ifr_name[IFNAMSIZ-1] = '\0';
1867 1910
1868 ret = tun_set_iff(tfile->net, file, &ifr); 1911 ret = tun_set_iff(sock_net(&tfile->sk), file, &ifr);
1869 1912
1870 if (ret) 1913 if (ret)
1871 goto unlock; 1914 goto unlock;
@@ -2056,6 +2099,14 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
2056 tun->flags &= ~TUN_VNET_LE; 2099 tun->flags &= ~TUN_VNET_LE;
2057 break; 2100 break;
2058 2101
2102 case TUNGETVNETBE:
2103 ret = tun_get_vnet_be(tun, argp);
2104 break;
2105
2106 case TUNSETVNETBE:
2107 ret = tun_set_vnet_be(tun, argp);
2108 break;
2109
2059 case TUNATTACHFILTER: 2110 case TUNATTACHFILTER:
2060 /* Can be set only for TAPs */ 2111 /* Can be set only for TAPs */
2061 ret = -EINVAL; 2112 ret = -EINVAL;
@@ -2154,16 +2205,16 @@ out:
2154 2205
2155static int tun_chr_open(struct inode *inode, struct file * file) 2206static int tun_chr_open(struct inode *inode, struct file * file)
2156{ 2207{
2208 struct net *net = current->nsproxy->net_ns;
2157 struct tun_file *tfile; 2209 struct tun_file *tfile;
2158 2210
2159 DBG1(KERN_INFO, "tunX: tun_chr_open\n"); 2211 DBG1(KERN_INFO, "tunX: tun_chr_open\n");
2160 2212
2161 tfile = (struct tun_file *)sk_alloc(&init_net, AF_UNSPEC, GFP_KERNEL, 2213 tfile = (struct tun_file *)sk_alloc(net, AF_UNSPEC, GFP_KERNEL,
2162 &tun_proto); 2214 &tun_proto, 0);
2163 if (!tfile) 2215 if (!tfile)
2164 return -ENOMEM; 2216 return -ENOMEM;
2165 RCU_INIT_POINTER(tfile->tun, NULL); 2217 RCU_INIT_POINTER(tfile->tun, NULL);
2166 tfile->net = get_net(current->nsproxy->net_ns);
2167 tfile->flags = 0; 2218 tfile->flags = 0;
2168 tfile->ifindex = 0; 2219 tfile->ifindex = 0;
2169 2220
@@ -2174,13 +2225,11 @@ static int tun_chr_open(struct inode *inode, struct file * file)
2174 tfile->socket.ops = &tun_socket_ops; 2225 tfile->socket.ops = &tun_socket_ops;
2175 2226
2176 sock_init_data(&tfile->socket, &tfile->sk); 2227 sock_init_data(&tfile->socket, &tfile->sk);
2177 sk_change_net(&tfile->sk, tfile->net);
2178 2228
2179 tfile->sk.sk_write_space = tun_sock_write_space; 2229 tfile->sk.sk_write_space = tun_sock_write_space;
2180 tfile->sk.sk_sndbuf = INT_MAX; 2230 tfile->sk.sk_sndbuf = INT_MAX;
2181 2231
2182 file->private_data = tfile; 2232 file->private_data = tfile;
2183 set_bit(SOCK_EXTERNALLY_ALLOCATED, &tfile->socket.flags);
2184 INIT_LIST_HEAD(&tfile->next); 2233 INIT_LIST_HEAD(&tfile->next);
2185 2234
2186 sock_set_flag(&tfile->sk, SOCK_ZEROCOPY); 2235 sock_set_flag(&tfile->sk, SOCK_ZEROCOPY);
@@ -2191,10 +2240,8 @@ static int tun_chr_open(struct inode *inode, struct file * file)
2191static int tun_chr_close(struct inode *inode, struct file *file) 2240static int tun_chr_close(struct inode *inode, struct file *file)
2192{ 2241{
2193 struct tun_file *tfile = file->private_data; 2242 struct tun_file *tfile = file->private_data;
2194 struct net *net = tfile->net;
2195 2243
2196 tun_detach(tfile, true); 2244 tun_detach(tfile, true);
2197 put_net(net);
2198 2245
2199 return 0; 2246 return 0;
2200} 2247}