国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
虛擬網(wǎng)卡tun/tap驅(qū)動(dòng)程序設(shè)計(jì)原理 - 空間

虛擬網(wǎng)卡 TUN/TAP 驅(qū)動(dòng)程序設(shè)計(jì)原理

麻利輝
研究生, 電子科技大學(xué)計(jì)算機(jī)學(xué)院研究生部
2004 年 11 月

本文將介紹 TUN/TAP 驅(qū)動(dòng)的使用并分析虛擬網(wǎng)卡 TUN/TAP 驅(qū)動(dòng)程序在 Linux 環(huán)境下的設(shè)計(jì)思路。

簡(jiǎn)介
虛擬網(wǎng)卡Tun/tap驅(qū)動(dòng)是一個(gè)開(kāi)源項(xiàng)目,支持很多的類(lèi)UNIX平臺(tái),OpenVPN和Vtun都是基于它實(shí)現(xiàn)隧道包封裝。本文將介紹tun/tap驅(qū)動(dòng)的使用并分析虛擬網(wǎng)卡tun/tap驅(qū)動(dòng)程序在linux環(huán)境下的設(shè)計(jì)思路。

tun/tap驅(qū)動(dòng)程序?qū)崿F(xiàn)了虛擬網(wǎng)卡的功能,tun表示虛擬的是點(diǎn)對(duì)點(diǎn)設(shè)備,tap表示虛擬的是以太網(wǎng)設(shè)備,這兩種設(shè)備針對(duì)網(wǎng)絡(luò)包實(shí)施不同的封裝。利用tun/tap驅(qū)動(dòng),可以將tcp/ip協(xié)議棧處理好的網(wǎng)絡(luò)分包傳給任何一個(gè)使用tun/tap驅(qū)動(dòng)的進(jìn)程,由進(jìn)程重新處理后再發(fā)到物理鏈路中。開(kāi)源項(xiàng)目openvpn( http://openvpn.sourceforge.net)和Vtun( http://vtun.sourceforge.net)都是利用tun/tap驅(qū)動(dòng)實(shí)現(xiàn)的隧道封裝。

使用tun/tap驅(qū)動(dòng)
在linux 2.4內(nèi)核版本及以后版本中,tun/tap驅(qū)動(dòng)是作為系統(tǒng)默認(rèn)預(yù)先編譯進(jìn)內(nèi)核中的。在使用之前,確保已經(jīng)裝載了tun/tap模塊并建立設(shè)備文件:


#modprobe tun#mknod /dev/net/tun c 10 200

參數(shù)c表示是字符設(shè)備, 10和200分別是主設(shè)備號(hào)和次設(shè)備號(hào)。

這樣,我們就可以在程序中使用該驅(qū)動(dòng)了。

使用tun/tap設(shè)備的示例程序(摘自openvpn開(kāi)源項(xiàng)目 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)) < 0) //創(chuàng)建描述符    msg (M_ERR, "Cannot open TUN/TAP dev %s", device);  memset (&ifr, 0, sizeof (ifr));  ifr.ifr_flags = IFF_NO_PI;  if (!strncmp (dev, "tun", 3)) {        ifr.ifr_flags |= IFF_TUN;   }  else if (!strncmp (dev, "tap", 3)) {      ifr.ifr_flags |= IFF_TAP;    }  else {    msg (M_FATAL, "I don‘t recognize device %s as a TUN or TAP device",dev);    }  if (strlen (dev) > 3)		/* unit number specified? */    strncpy (ifr.ifr_name, dev, IFNAMSIZ);  if (ioctl (fd, TUNSETIFF, (void *) &ifr) < 0) //打開(kāi)虛擬網(wǎng)卡    msg (M_ERR, "Cannot ioctl TUNSETIFF %s", dev);  set_nonblock (fd);  msg (M_INFO, "TUN/TAP device %s opened", ifr.ifr_name);  strncpynt (actual, ifr.ifr_name, size);  return fd;}

調(diào)用上述函數(shù)后,就可以在shell命令行下使用ifconfig 命令配置虛擬網(wǎng)卡了,通過(guò)生成的字符設(shè)備描述符,在程序中使用read和write函數(shù)就可以讀取或者發(fā)送給虛擬的網(wǎng)卡數(shù)據(jù)了。

Tun/tap驅(qū)動(dòng)程序工作原理
做為虛擬網(wǎng)卡驅(qū)動(dòng),Tun/tap驅(qū)動(dòng)程序的數(shù)據(jù)接收和發(fā)送并不直接和真實(shí)網(wǎng)卡打交道,而是通過(guò)用戶(hù)態(tài)來(lái)轉(zhuǎn)交。在linux下,要實(shí)現(xiàn)核心態(tài)和用戶(hù)態(tài)數(shù)據(jù)的交互,有多種方式:可以通用socket創(chuàng)建特殊套接字,利用套接字實(shí)現(xiàn)數(shù)據(jù)交互;通過(guò)proc文件系統(tǒng)創(chuàng)建文件來(lái)進(jìn)行數(shù)據(jù)交互;還可以使用設(shè)備文件的方式,訪問(wèn)設(shè)備文件會(huì)調(diào)用設(shè)備驅(qū)動(dòng)相應(yīng)的例程,設(shè)備驅(qū)動(dòng)本身就是核心態(tài)和用戶(hù)態(tài)的一個(gè)接口,Tun/tap驅(qū)動(dòng)就是利用設(shè)備文件實(shí)現(xiàn)用戶(hù)態(tài)和核心態(tài)的數(shù)據(jù)交互。

從結(jié)構(gòu)上來(lái)說(shuō),Tun/tap驅(qū)動(dòng)并不單純是實(shí)現(xiàn)網(wǎng)卡驅(qū)動(dòng),同時(shí)它還實(shí)現(xiàn)了字符設(shè)備驅(qū)動(dòng)部分。以字符設(shè)備的方式連接用戶(hù)態(tài)和核心態(tài)。下面是示意圖:


Tun/tap驅(qū)動(dòng)程序中包含兩個(gè)部分,一部分是字符設(shè)備驅(qū)動(dòng),還有一部分是網(wǎng)卡驅(qū)動(dòng)部分。利用網(wǎng)卡驅(qū)動(dòng)部分接收來(lái)自TCP/IP協(xié)議棧的網(wǎng)絡(luò)分包并發(fā)送或者反過(guò)來(lái)將接收到的網(wǎng)絡(luò)分包傳給協(xié)議棧處理,而字符驅(qū)動(dòng)部分則將網(wǎng)絡(luò)分包在內(nèi)核與用戶(hù)態(tài)之間傳送,模擬物理鏈路的數(shù)據(jù)接收和發(fā)送。Tun/tap驅(qū)動(dòng)很好的實(shí)現(xiàn)了兩種驅(qū)動(dòng)的結(jié)合。

下面是定義的tun/tap設(shè)備結(jié)構(gòu):


struct tun_struct {	char 			name[8]; //設(shè)備名	unsigned long 		flags; //區(qū)分tun和tap設(shè)備	struct fasync_struct    *fasync; //文件異步通知結(jié)構(gòu)	wait_queue_head_t 	read_wait; //等待隊(duì)列	struct net_device	dev;  //linux 抽象網(wǎng)絡(luò)設(shè)備結(jié)構(gòu)	struct sk_buff_head 	txq; //網(wǎng)絡(luò)緩沖區(qū)隊(duì)列    struct net_device_stats	stats; //網(wǎng)卡狀態(tài)信息結(jié)構(gòu)};

struct net_device結(jié)構(gòu)是linux內(nèi)核提供的統(tǒng)一網(wǎng)絡(luò)設(shè)備結(jié)構(gòu),定義了系統(tǒng)統(tǒng)一的訪問(wèn)接口。

Tun/tap驅(qū)動(dòng)中實(shí)現(xiàn)的網(wǎng)卡驅(qū)動(dòng)的處理例程:

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);//數(shù)據(jù)包發(fā)送例程
static void tun_net_mclist(struct net_device *dev);//設(shè)置多點(diǎn)傳輸?shù)牡刂锋湵?
static struct net_device_stats *tun_net_stats(struct net_device *dev);//當(dāng)一個(gè)應(yīng)用程序需要知道網(wǎng)絡(luò)接口的一些統(tǒng)計(jì)數(shù)據(jù)時(shí),可調(diào)用該函數(shù),如ifconfig、netstat等。
int tun_net_init(struct net_device *dev);//網(wǎng)絡(luò)設(shè)備初始例程

字符設(shè)備部分:

在Linux中,字符設(shè)備和塊設(shè)備統(tǒng)一以文件的方式訪問(wèn),訪問(wèn)它們的接口是統(tǒng)一的,都是使用open()函數(shù)打開(kāi)設(shè)備文件或普通文件,用read()和write()函數(shù)實(shí)現(xiàn)讀寫(xiě)文件等等。Tun/tap驅(qū)動(dòng)定義的字符設(shè)備的訪問(wèn)接口如下:

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
};

在內(nèi)核中利用misc_register() 函數(shù)將該驅(qū)動(dòng)注冊(cè)為非標(biāo)準(zhǔn)字符設(shè)備驅(qū)動(dòng),提供字符設(shè)備具有的各種程序接口。代碼摘自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;}

當(dāng)打開(kāi)一個(gè)tun/tap設(shè)備時(shí),open 函數(shù)將調(diào)用tun_chr_open()函數(shù),其中將完成一些重要的初始化過(guò)程,包括設(shè)置網(wǎng)卡驅(qū)動(dòng)部分的初始化函數(shù)以及網(wǎng)絡(luò)緩沖區(qū)鏈表的初始化和等待隊(duì)列的初始化。Tun/tap驅(qū)動(dòng)中網(wǎng)卡的注冊(cè)被嵌入了字符驅(qū)動(dòng)的ioctl例程中,它是通過(guò)對(duì)字符設(shè)備文件描述符利用自定義的ioctl設(shè)置標(biāo)志TUNSETIFF完成網(wǎng)卡的注冊(cè)的。下面是函數(shù)調(diào)用關(guān)系示意圖:


使用ioctl()函數(shù)操作字符設(shè)備文件描述符,將調(diào)用字符設(shè)備中tun_chr_ioctl 來(lái)設(shè)置已經(jīng)open好的tun/tap設(shè)備,如果設(shè)置標(biāo)志為T(mén)UNSETIFF,則調(diào)用tun_set_iff() 函數(shù),此函數(shù)將完成很重要的一步操作,就是對(duì)網(wǎng)卡驅(qū)動(dòng)進(jìn)行注冊(cè)register_netdev(&tun->dev),網(wǎng)卡驅(qū)動(dòng)的各個(gè)處理例程的掛接在open操作時(shí)由tun_chr_open()函數(shù)初始化好了。

Tun/tap設(shè)備的工作過(guò)程:

Tun/tap設(shè)備提供的虛擬網(wǎng)卡驅(qū)動(dòng),從tcp/ip協(xié)議棧的角度而言,它與真實(shí)網(wǎng)卡驅(qū)動(dòng)并沒(méi)有區(qū)別。從驅(qū)動(dòng)程序的角度來(lái)說(shuō),它與真實(shí)網(wǎng)卡的不同表現(xiàn)在tun/tap設(shè)備獲取的數(shù)據(jù)不是來(lái)自物理鏈路,而是來(lái)自用戶(hù)區(qū),Tun/tap設(shè)備驅(qū)動(dòng)通過(guò)字符設(shè)備文件來(lái)實(shí)現(xiàn)數(shù)據(jù)從用戶(hù)區(qū)的獲取。發(fā)送數(shù)據(jù)時(shí)tun/tap設(shè)備也不是發(fā)送到物理鏈路,而是通過(guò)字符設(shè)備發(fā)送至用戶(hù)區(qū),再由用戶(hù)區(qū)程序通過(guò)其他渠道發(fā)送。

發(fā)送過(guò)程:

使用tun/tap網(wǎng)卡的程序經(jīng)過(guò)協(xié)議棧把數(shù)據(jù)傳送給驅(qū)動(dòng)程序,驅(qū)動(dòng)程序調(diào)用注冊(cè)好的hard_start_xmit函數(shù)發(fā)送,hard_start_xmit函數(shù)又會(huì)調(diào)用tun_net_xmit函數(shù),其中skb將會(huì)被加入skb鏈表,然后喚醒被阻塞的使用tun/tap設(shè)備字符驅(qū)動(dòng)讀數(shù)據(jù)的進(jìn)程,接著tun/tap設(shè)備的字符驅(qū)動(dòng)部分調(diào)用其tun_chr_read()過(guò)程讀取skb鏈表,并將每一個(gè)讀到的skb發(fā)往用戶(hù)區(qū),完成虛擬網(wǎng)卡的數(shù)據(jù)發(fā)送。

接收數(shù)據(jù)的過(guò)程:

當(dāng)我們使用write()系統(tǒng)調(diào)用向tun/tap設(shè)備的字符設(shè)備文件寫(xiě)入數(shù)據(jù)時(shí),tun_chr_write函數(shù)將被調(diào)用,它使用tun_get_user從用戶(hù)區(qū)接受數(shù)據(jù),其中將數(shù)據(jù)存入skb中,然后調(diào)用關(guān)鍵的函數(shù)netif_rx(skb) 將skb送給tcp/ip協(xié)議棧處理,完成虛擬網(wǎng)卡的數(shù)據(jù)接收。


小結(jié)
tun/tap驅(qū)動(dòng)很巧妙的將字符驅(qū)動(dòng)和網(wǎng)卡驅(qū)動(dòng)糅合在一起,本文重點(diǎn)分析兩種驅(qū)動(dòng)之間的銜接,具體的驅(qū)動(dòng)處理細(xì)節(jié)沒(méi)有一一列出,請(qǐng)讀者參考相關(guān)文檔。

參考資料

關(guān)于作者
麻利輝 電子科技大學(xué)計(jì)算機(jī)學(xué)院2003級(jí)研究生,研究方向?yàn)榫W(wǎng)絡(luò)安全,對(duì)網(wǎng)絡(luò)安全的各種技術(shù)都有著濃厚的興趣,主要研究方向?yàn)榉阑饓夹g(shù)和攻擊技術(shù)。長(zhǎng)期在linux下從事軟件開(kāi)發(fā),您可以通過(guò)電子郵件 mlhdyx@21cn.com和他取得聯(lián)系。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶(hù)發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
4
SolusVM普通用戶(hù)教程之
Linux虛擬網(wǎng)絡(luò)設(shè)備之tun/tap
網(wǎng)卡驅(qū)動(dòng)注冊(cè)到PCI總線這一過(guò)程的分析
USB 3G網(wǎng)卡驅(qū)動(dòng)流程
User-mode Linux (簡(jiǎn)體中文) - ArchWiki
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服