Skip to content

Commit 05c2828

Browse files
mstsirkindavem330
authored andcommitted
tun: export underlying socket
Tun device looks similar to a packet socket in that both pass complete frames from/to userspace. This patch fills in enough fields in the socket underlying tun driver to support sendmsg/recvmsg operations, and message flags MSG_TRUNC and MSG_DONTWAIT, and exports access to this socket to modules. Regular read/write behaviour is unchanged. This way, code using raw sockets to inject packets into a physical device, can support injecting packets into host network stack almost without modification. First user of this interface will be vhost virtualization accelerator. Signed-off-by: Michael S. Tsirkin <[email protected]> Acked-by: Herbert Xu <[email protected]> Acked-by: David S. Miller <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ad72c34 commit 05c2828

File tree

2 files changed

+96
-19
lines changed

2 files changed

+96
-19
lines changed

drivers/net/tun.c

Lines changed: 82 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file)
144144
err = 0;
145145
tfile->tun = tun;
146146
tun->tfile = tfile;
147+
tun->socket.file = file;
147148
dev_hold(tun->dev);
148149
sock_hold(tun->socket.sk);
149150
atomic_inc(&tfile->count);
@@ -158,6 +159,7 @@ static void __tun_detach(struct tun_struct *tun)
158159
/* Detach from net device */
159160
netif_tx_lock_bh(tun->dev);
160161
tun->tfile = NULL;
162+
tun->socket.file = NULL;
161163
netif_tx_unlock_bh(tun->dev);
162164

163165
/* Drop read queue */
@@ -387,7 +389,8 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
387389
/* Notify and wake up reader process */
388390
if (tun->flags & TUN_FASYNC)
389391
kill_fasync(&tun->fasync, SIGIO, POLL_IN);
390-
wake_up_interruptible(&tun->socket.wait);
392+
wake_up_interruptible_poll(&tun->socket.wait, POLLIN |
393+
POLLRDNORM | POLLRDBAND);
391394
return NETDEV_TX_OK;
392395

393396
drop:
@@ -743,42 +746,31 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
743746
len = min_t(int, skb->len, len);
744747

745748
skb_copy_datagram_const_iovec(skb, 0, iv, total, len);
746-
total += len;
749+
total += skb->len;
747750

748751
tun->dev->stats.tx_packets++;
749752
tun->dev->stats.tx_bytes += len;
750753

751754
return total;
752755
}
753756

754-
static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
755-
unsigned long count, loff_t pos)
757+
static ssize_t tun_do_read(struct tun_struct *tun,
758+
struct kiocb *iocb, const struct iovec *iv,
759+
ssize_t len, int noblock)
756760
{
757-
struct file *file = iocb->ki_filp;
758-
struct tun_file *tfile = file->private_data;
759-
struct tun_struct *tun = __tun_get(tfile);
760761
DECLARE_WAITQUEUE(wait, current);
761762
struct sk_buff *skb;
762-
ssize_t len, ret = 0;
763-
764-
if (!tun)
765-
return -EBADFD;
763+
ssize_t ret = 0;
766764

767765
DBG(KERN_INFO "%s: tun_chr_read\n", tun->dev->name);
768766

769-
len = iov_length(iv, count);
770-
if (len < 0) {
771-
ret = -EINVAL;
772-
goto out;
773-
}
774-
775767
add_wait_queue(&tun->socket.wait, &wait);
776768
while (len) {
777769
current->state = TASK_INTERRUPTIBLE;
778770

779771
/* Read frames from the queue */
780772
if (!(skb=skb_dequeue(&tun->socket.sk->sk_receive_queue))) {
781-
if (file->f_flags & O_NONBLOCK) {
773+
if (noblock) {
782774
ret = -EAGAIN;
783775
break;
784776
}
@@ -805,6 +797,27 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
805797
current->state = TASK_RUNNING;
806798
remove_wait_queue(&tun->socket.wait, &wait);
807799

800+
return ret;
801+
}
802+
803+
static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
804+
unsigned long count, loff_t pos)
805+
{
806+
struct file *file = iocb->ki_filp;
807+
struct tun_file *tfile = file->private_data;
808+
struct tun_struct *tun = __tun_get(tfile);
809+
ssize_t len, ret;
810+
811+
if (!tun)
812+
return -EBADFD;
813+
len = iov_length(iv, count);
814+
if (len < 0) {
815+
ret = -EINVAL;
816+
goto out;
817+
}
818+
819+
ret = tun_do_read(tun, iocb, iv, len, file->f_flags & O_NONBLOCK);
820+
ret = min_t(ssize_t, ret, len);
808821
out:
809822
tun_put(tun);
810823
return ret;
@@ -847,7 +860,8 @@ static void tun_sock_write_space(struct sock *sk)
847860
return;
848861

849862
if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
850-
wake_up_interruptible_sync(sk->sk_sleep);
863+
wake_up_interruptible_sync_poll(sk->sk_sleep, POLLOUT |
864+
POLLWRNORM | POLLWRBAND);
851865

852866
tun = tun_sk(sk)->tun;
853867
kill_fasync(&tun->fasync, SIGIO, POLL_OUT);
@@ -858,6 +872,37 @@ static void tun_sock_destruct(struct sock *sk)
858872
free_netdev(tun_sk(sk)->tun->dev);
859873
}
860874

875+
static int tun_sendmsg(struct kiocb *iocb, struct socket *sock,
876+
struct msghdr *m, size_t total_len)
877+
{
878+
struct tun_struct *tun = container_of(sock, struct tun_struct, socket);
879+
return tun_get_user(tun, m->msg_iov, total_len,
880+
m->msg_flags & MSG_DONTWAIT);
881+
}
882+
883+
static int tun_recvmsg(struct kiocb *iocb, struct socket *sock,
884+
struct msghdr *m, size_t total_len,
885+
int flags)
886+
{
887+
struct tun_struct *tun = container_of(sock, struct tun_struct, socket);
888+
int ret;
889+
if (flags & ~(MSG_DONTWAIT|MSG_TRUNC))
890+
return -EINVAL;
891+
ret = tun_do_read(tun, iocb, m->msg_iov, total_len,
892+
flags & MSG_DONTWAIT);
893+
if (ret > total_len) {
894+
m->msg_flags |= MSG_TRUNC;
895+
ret = flags & MSG_TRUNC ? ret : total_len;
896+
}
897+
return ret;
898+
}
899+
900+
/* Ops structure to mimic raw sockets with tun */
901+
static const struct proto_ops tun_socket_ops = {
902+
.sendmsg = tun_sendmsg,
903+
.recvmsg = tun_recvmsg,
904+
};
905+
861906
static struct proto tun_proto = {
862907
.name = "tun",
863908
.owner = THIS_MODULE,
@@ -986,6 +1031,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
9861031
goto err_free_dev;
9871032

9881033
init_waitqueue_head(&tun->socket.wait);
1034+
tun->socket.ops = &tun_socket_ops;
9891035
sock_init_data(&tun->socket, sk);
9901036
sk->sk_write_space = tun_sock_write_space;
9911037
sk->sk_sndbuf = INT_MAX;
@@ -1525,6 +1571,23 @@ static void tun_cleanup(void)
15251571
rtnl_link_unregister(&tun_link_ops);
15261572
}
15271573

1574+
/* Get an underlying socket object from tun file. Returns error unless file is
1575+
* attached to a device. The returned object works like a packet socket, it
1576+
* can be used for sock_sendmsg/sock_recvmsg. The caller is responsible for
1577+
* holding a reference to the file for as long as the socket is in use. */
1578+
struct socket *tun_get_socket(struct file *file)
1579+
{
1580+
struct tun_struct *tun;
1581+
if (file->f_op != &tun_fops)
1582+
return ERR_PTR(-EINVAL);
1583+
tun = tun_get(file);
1584+
if (!tun)
1585+
return ERR_PTR(-EBADFD);
1586+
tun_put(tun);
1587+
return &tun->socket;
1588+
}
1589+
EXPORT_SYMBOL_GPL(tun_get_socket);
1590+
15281591
module_init(tun_init);
15291592
module_exit(tun_cleanup);
15301593
MODULE_DESCRIPTION(DRV_DESCRIPTION);

include/linux/if_tun.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,18 @@ struct tun_filter {
8686
__u8 addr[0][ETH_ALEN];
8787
};
8888

89+
#ifdef __KERNEL__
90+
#if defined(CONFIG_TUN) || defined(CONFIG_TUN_MODULE)
91+
struct socket *tun_get_socket(struct file *);
92+
#else
93+
#include <linux/err.h>
94+
#include <linux/errno.h>
95+
struct file;
96+
struct socket;
97+
static inline struct socket *tun_get_socket(struct file *f)
98+
{
99+
return ERR_PTR(-EINVAL);
100+
}
101+
#endif /* CONFIG_TUN */
102+
#endif /* __KERNEL__ */
89103
#endif /* __IF_TUN_H */

0 commit comments

Comments
 (0)