TUN/TAP

38 篇文章 3 订阅

   In computer networking , TUN and TAP are virtual network kernel devices. They are network devices that are supported entirely in software, which is different from ordinary network devices that are backed up by hardware network adapters .

    TAP (as in network tap ) simulates an Ethernet device and it operates with layer 2 packets such as Ethernet frames.     

   TUN (as in network TUNnel) simulates a network layer device and it operates with layer 3 packets such as IP packets. TAP is used to create a network bridge , while TUN is used with routing .

     Packets sent by an operating system via a TUN/TAP device are delivered to a user-space program that attaches itself to the device. A user-space program may also pass packets into a TUN/TAP device. In this case TUN/TAP device delivers (or "injects") these packets to the operating system network stack thus emulating their reception from an external source.

 

虚拟网卡Tun/tap驱动是一个开源项目,支持很多的类UNIX平台,OpenVPN和Vtun都是基于它实现隧道包封装。本文将介绍tun/tap驱动的使用并分析虚拟网卡tun/tap驱动程序在linux环境下的设计思路。
tun/tap 驱动程序实现了虚拟网卡的功能,tun表示虚拟的是点对点设备,tap表示虚拟的是以太网设备,这两种设备针对网络包实施不同的封装。利用tun/tap 驱动,可以将tcp/ip协议栈处理好的网络分包传给任何一个使用tun/tap驱动的进程,由进程重新处理后再发到物理链路中。开源项目 openvpn(
http://openvpn.sourceforge.net
)和Vtun(
http://vtun.sourceforge.net
)都是利用tun/tap驱动实现的隧道封装。


使用tun/tap驱动
在linux 2.4内核版本及以后版本中,tun/tap驱动是作为系统默认预先编译进内核中的。在使用之前,确保已经装载了tun/tap模块并建立设备文件:
#modprobe tun
#mknod /dev/net/tun c 10 200
参数c表示是字符设备, 10和200分别是主设备号和次设备号。
这样,我们就可以在程序中使用该驱动了。
使用tun/tap设备的示例程序(摘自openvpn开源项目
http://openvpn.sourceforge.net
,tun.c文件)
int open_tun (const char *dev, char *actual, int size)
{
struct ifreq ifr;
int fd;
char *device = "/dev/net/tun";
if ((fd = open (device, O_RDWR)) 3) /* unit number specified? */
strncpy (ifr.ifr_name, dev, IFNAMSIZ);
if (ioctl (fd, TUNSETIFF, (void *) &ifr)
调用上述函数后,就可以在shell命令行下使用ifconfig 命令配置虚拟网卡了,通过生成的字符设备描述符,在程序中使用read和write函数就可以读取或者发送给虚拟的网卡数据了。


Tun/tap驱动程序工作原理
做 为虚拟网卡驱动,Tun/tap驱动程序的数据接收和发送并不直接和真实网卡打交道,而是通过用户态来转交。在linux下,要实现核心态和用户态数据的 交互,有多种方式:可以通用socket创建特殊套接字,利用套接字实现数据交互;通过proc文件系统创建文件来进行数据交互;还可以使用设备文件的方 式,访问设备文件会调用设备驱动相应的例程,设备驱动本身就是核心态和用户态的一个接口,Tun/tap驱动就是利用设备文件实现用户态和核心态的数据交 互。
从结构上来说,Tun/tap驱动并不单纯是实现网卡驱动,同时它还实现了字符设备驱动部分。以字符设备的方式连接用户态和核心态。下面是示意图:

Tun/tap 驱动程序中包含两个部分,一部分是字符设备驱动,还有一部分是网卡驱动部分。利用网卡驱动部分接收来自TCP/IP协议栈的网络分包并发送或者反过来将接 收到的网络分包传给协议栈处理,而字符驱动部分则将网络分包在内核与用户态之间传送,模拟物理链路的数据接收和发送。Tun/tap驱动很好的实现了两种 驱动的结合。
下面是定义的tun/tap设备结构:
struct tun_struct {
char name[8]; //设备名
unsigned long flags; //区分tun和tap设备
struct fasync_struct *fasync; //文件异步通知结构
wait_queue_head_t read_wait; //等待队列
struct net_device dev; //linux 抽象网络设备结构
struct sk_buff_head txq; //网络缓冲区队列
struct net_device_stats stats; //网卡状态信息结构
};
struct net_device结构是linux内核提供的统一网络设备结构,定义了系统统一的访问接口。
Tun/tap驱动中实现的网卡驱动的处理例程:
static int tun_net_open(struct net_device *dev);
static int tun_net_close(struct net_device *dev);
static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev);//数据包发送例程
static void tun_net_mclist(struct net_device *dev);//设置多点传输的地址链表
static struct net_device_stats *tun_net_stats(struct net_device *dev);//当一个应用程序需要知道网络接口的一些统计数据时,可调用该函数,如ifconfig、netstat等。
int tun_net_init(struct net_device *dev);//网络设备初始例程
字符设备部分:
在Linux中,字符设备和块设备统一以文件的方式访问,访问它们的接口是统一的,都是使用open()函数打开设备文件或普通文件,用read()和write()函数实现读写文件等等。Tun/tap驱动定义的字符设备的访问接口如下:
static struct file_operations tun_fops = {
owner: THIS_MODULE,
llseek: tun_chr_lseek,
read tun_chr_read,
write: tun_chr_write,
poll: tun_chr_poll,
ioctl: tun_chr_ioctl,
open: tun_chr_open,
release: tun_chr_close,
fasync: tun_chr_fasync
};
在内核中利用misc_register() 函数将该驱动注册为非标准字符设备驱动,提供字符设备具有的各种程序接口。代码摘自linux-2.4.20/linux-2.4.20/drivers/net/tun.c
static struct miscdevice tun_miscdev=
{
TUN_MINOR,
"net/tun",
&tun_fops
};
int __init tun_init(void)
{

if (misc_register(&tun_miscdev)) {
printk(KERN_ERR "tun: Can't register misc device %d/n", TUN_MINOR);
return -EIO;
}
return 0;
}
当 打开一个tun/tap设备时,open 函数将调用tun_chr_open()函数,其中将完成一些重要的初始化过程,包括设置网卡驱动部分的初始化函数以及网络缓冲区链表的初始化和等待队列 的初始化。Tun/tap驱动中网卡的注册被嵌入了字符驱动的ioctl例程中,它是通过对字符设备文件描述符利用自定义的ioctl设置标志 TUNSETIFF完成网卡的注册的。下面是函数调用关系示意图:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值