aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2010-02-13 20:01:10 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-17 19:35:17 -0500
commit99405162598176e830d17ae6d4f3d9e070ad900c (patch)
tree41a23acd64d3f18de729c2abadc98f7c4687aa45
parent5ff3f073670b544a9c0547cc6fef1f7eed5762ed (diff)
tun: socket filter support
This patch adds Linux Socket Filter support to tun driver. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/tun.c26
-rw-r--r--include/linux/if_tun.h3
2 files changed, 29 insertions, 0 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 5adb3d150552..ce1efa4c0b0d 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -61,6 +61,7 @@
61#include <linux/crc32.h> 61#include <linux/crc32.h>
62#include <linux/nsproxy.h> 62#include <linux/nsproxy.h>
63#include <linux/virtio_net.h> 63#include <linux/virtio_net.h>
64#include <linux/rcupdate.h>
64#include <net/net_namespace.h> 65#include <net/net_namespace.h>
65#include <net/netns/generic.h> 66#include <net/netns/generic.h>
66#include <net/rtnetlink.h> 67#include <net/rtnetlink.h>
@@ -366,6 +367,10 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
366 if (!check_filter(&tun->txflt, skb)) 367 if (!check_filter(&tun->txflt, skb))
367 goto drop; 368 goto drop;
368 369
370 if (tun->socket.sk->sk_filter &&
371 sk_filter(tun->socket.sk, skb))
372 goto drop;
373
369 if (skb_queue_len(&tun->socket.sk->sk_receive_queue) >= dev->tx_queue_len) { 374 if (skb_queue_len(&tun->socket.sk->sk_receive_queue) >= dev->tx_queue_len) {
370 if (!(tun->flags & TUN_ONE_QUEUE)) { 375 if (!(tun->flags & TUN_ONE_QUEUE)) {
371 /* Normal queueing mode. */ 376 /* Normal queueing mode. */
@@ -1162,6 +1167,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
1162 struct tun_file *tfile = file->private_data; 1167 struct tun_file *tfile = file->private_data;
1163 struct tun_struct *tun; 1168 struct tun_struct *tun;
1164 void __user* argp = (void __user*)arg; 1169 void __user* argp = (void __user*)arg;
1170 struct sock_fprog fprog;
1165 struct ifreq ifr; 1171 struct ifreq ifr;
1166 int sndbuf; 1172 int sndbuf;
1167 int ret; 1173 int ret;
@@ -1309,6 +1315,26 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
1309 tun->socket.sk->sk_sndbuf = sndbuf; 1315 tun->socket.sk->sk_sndbuf = sndbuf;
1310 break; 1316 break;
1311 1317
1318 case TUNATTACHFILTER:
1319 /* Can be set only for TAPs */
1320 ret = -EINVAL;
1321 if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
1322 break;
1323 ret = -EFAULT;
1324 if (copy_from_user(&fprog, argp, sizeof(fprog)))
1325 break;
1326
1327 ret = sk_attach_filter(&fprog, tun->socket.sk);
1328 break;
1329
1330 case TUNDETACHFILTER:
1331 /* Can be set only for TAPs */
1332 ret = -EINVAL;
1333 if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
1334 break;
1335 ret = sk_detach_filter(tun->socket.sk);
1336 break;
1337
1312 default: 1338 default:
1313 ret = -EINVAL; 1339 ret = -EINVAL;
1314 break; 1340 break;
diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h
index 404abe00162c..1350a246893a 100644
--- a/include/linux/if_tun.h
+++ b/include/linux/if_tun.h
@@ -18,6 +18,7 @@
18 18
19#include <linux/types.h> 19#include <linux/types.h>
20#include <linux/if_ether.h> 20#include <linux/if_ether.h>
21#include <linux/filter.h>
21 22
22/* Read queue size */ 23/* Read queue size */
23#define TUN_READQ_SIZE 500 24#define TUN_READQ_SIZE 500
@@ -48,6 +49,8 @@
48#define TUNGETIFF _IOR('T', 210, unsigned int) 49#define TUNGETIFF _IOR('T', 210, unsigned int)
49#define TUNGETSNDBUF _IOR('T', 211, int) 50#define TUNGETSNDBUF _IOR('T', 211, int)
50#define TUNSETSNDBUF _IOW('T', 212, int) 51#define TUNSETSNDBUF _IOW('T', 212, int)
52#define TUNATTACHFILTER _IOW('T', 213, struct sock_fprog)
53#define TUNDETACHFILTER _IOW('T', 214, struct sock_fprog)
51 54
52/* TUNSETIFF ifr flags */ 55/* TUNSETIFF ifr flags */
53#define IFF_TUN 0x0001 56#define IFF_TUN 0x0001