日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

TUN/TAP设备浅析(二) -- TUN/TAP的编程

發布時間:2023/12/10 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 TUN/TAP设备浅析(二) -- TUN/TAP的编程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這篇文章想詳細闡述一下有關于 TUN/TAP 設備的編程。

其實關于這兩種設備的編程,基本上屬于八股文,大家一般都這么干。

啟動設備之前

有的linux 并沒有將tun 模塊編譯到內核之中,所以,我們要做的第一件事情就是檢查我們的系統是否支持 TUN/TAP 。具體如何檢查和解決,請查看這里http://blog.csdn.net/lishuhuakai/article/details/70305543,這篇文章就不再贅述。

光有tun 模塊還不夠,我們還要創建上篇文章中所提到的文件,運行命令:

% sudo mknod /dev/net/tun c 10 200 # c表示為字符設備,10和200分別是主設備號和次設備號

這樣,你到 /dev/net/ 目錄下就可以看到一個名稱為 tun 的文件了。當然這里的 tun 可以改成任意的你喜歡的名稱。

啟動設備

對于TUN設備,我們一般這樣來初始化:

int tun_alloc(char dev[IFNAMSIZ]) // dev數組用于存儲設備的名稱 {struct ifreq ifr;int fd, err;if ((fd = open("/dev/net/tun", O_RDWR)) < 0) { // 打開文件perror("open");return -1;}bzero(&ifr, sizeof(ifr));/* Flags : IFF_TUN - TUN設備* IFF_TAP - TAP設備* IFF_NO_PI - 不需要提供包的信息*/ifr.ifr_flags = IFF_TUN | IFF_NO_PI; // tun設備不包含以太網頭部,而tap包含,僅此而已if (*dev) {strncpy(ifr.ifr_name, dev, IFNAMSIZ); }if ((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0) { // 打開設備perror("ioctl TUNSETIFF");close(fd);return err;}// 一旦設備開啟成功,系統會給設備分配一個名稱對于tun設備,一般為tunX,X為從0開始的編號,對于tap設備// 一般為tapX,X為從0開始的編號strcpy(dev, ifr.ifr_name); // 拷貝設備的名稱至dev中return fd; }

如果我們想啟動一個TAP 設備的話,很簡單,將上面的ifr.ifr_flags = IFF_TUN | IFF_NO_PI;改為ifr.ifr_flags = IFF_TAP | IFF_NO_PI;即可,那么我們就啟動了一個 TAP 設備。

設定網絡地址

上面的代碼打開了文件,并且返回了文件的描述符,但是還不夠,對于一張網卡來說,我們還要給其配置網絡地址,有時候甚至是路由信息,網卡才能夠正常地工作。

一旦虛擬的 TUN/TAP 設備啟動成功,我們便可以通過命令來給其設定地址。

我來舉個例子,以一個 TAP 設備為例:

% sudo ip link set dev tap0 up # 啟動tap0網卡,雖然網卡已經啟動,但是此時使用ipconfig命令并不能看到tap0這個設備,因為我們還沒有給其配置ip地址% sudo ip address add dev tap0 10.0.1.5/24 # 給tap0設置ip地址% ifconfig # 此時在ifconfig命令下已經可以看到tap0設備了 tap0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 10.0.1.5 netmask 255.255.255.0 broadcast 0.0.0.0inet6 fe80::1872:80ff:fe20:46e2 prefixlen 64 scopeid 0x20<link>ether 1a:72:80:20:46:e2 txqueuelen 1000 (Ethernet)RX packets 0 bytes 0 (0.0 B)RX errors 0 dropped 0 overruns 0 frame 0TX packets 0 bytes 0 (0.0 B)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0% ip route show # 顯示所有的路由信息 default via 192.168.140.2 dev ens33 proto static metric 100 10.0.0.0/24 dev ens39 proto kernel scope link src 10.0.0.130 metric 100 10.0.1.0/24 dev tap0 proto kernel scope link src 10.0.1.5 # 給網卡設定ip后,系統自動添加了路由 192.168.140.0/24 dev ens33 proto kernel scope link src 192.168.140.133 metric 100

通過手動敲命令的方式來配置 tap0 設備,略顯麻煩,其實我們可以直接在程序中調用 system 函數:

int run_cmd(char *cmd, ...) {va_list ap;char buf[CMDBUFLEN];va_start(ap, cmd);vsnprintf(buf, CMDBUFLEN, cmd, ap);va_end(ap);if (debug) { // DEBUG模式下輸出信息printf("EXEC: %s\n", buf);}return system(buf); }

將上面的命令直接傳遞給 run_cmd 函數即可.

當然,如果你不喜歡這種方式,我們自然還可以有其他的方法,比如說使用下面的函數:

int set_stack_attribute(char *dev) {struct ifreq ifr;struct sockaddr_in addr;int sockfd, err = -1;bzero(&addr, sizeof(addr));addr.sin_family = AF_INET;inet_pton(AF_INET, tapaddr, &addr.sin_addr);bzero(&ifr, sizeof(ifr));strcpy(ifr.ifr_name, dev);bcopy(&addr, &ifr.ifr_addr, sizeof(addr));sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0) {perror("socket");return -1;}// ifconfig tap0 10.0.1.5 #設定ip地址if ((err = ioctl(sockfd, SIOCSIFADDR, (void *)&ifr)) < 0) {perror("ioctl SIOSIFADDR");goto done;}/* 獲得接口的標志 */if ((err = ioctl(sockfd, SIOCGIFFLAGS, (void *)&ifr)) < 0) {perror("ioctl SIOCGIFADDR");goto done;}/* 設置接口的標志 */ifr.ifr_flags |= IFF_UP;// ifup tap0 #啟動設備if ((err = ioctl(sockfd, SIOCSIFFLAGS, (void *)&ifr)) < 0) {perror("ioctl SIOCSIFFLAGS");goto done;}inet_pton(AF_INET, "255.255.255.0", &addr.sin_addr);bcopy(&addr, &ifr.ifr_netmask, sizeof(addr));// ifconfig tap0 10.0.1.5/24 #設定子網掩碼if ((err = ioctl(sockfd, SIOCSIFNETMASK, (void *) &ifr)) < 0) {perror("ioctl SIOCSIFNETMASK");goto done;}done:close(sockfd);return err; }

上面的函數主要干的事情和上面的命令大致相同。

收發數據

收發數據非常簡單,每次讀取返回的文件描述符即可接收數據,沒有數據到來時,會一直阻塞在哪里,當然,你也可以玩一下非阻塞 IO,然后想要發送數據的話,只需要將數據寫入到該文件描述符對應的文件中即可。



作者:Yihulee
鏈接:https://www.jianshu.com/p/ab91f7cd98cd
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

總結

以上是生活随笔為你收集整理的TUN/TAP设备浅析(二) -- TUN/TAP的编程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。