LINUX 虛擬網卡tun例子

來源:互聯網
上載者:User

/**
 *  linux TUN 例子 代碼來至
 *  http://hi.baidu.com/zkheartboy/blog/item/e96acf33508e4a40ad4b5f88.html和
 *  http://blog.csdn.net/Z_man/archive/2009/05/26/4216530.aspx
 *  建立一個tun0的虛擬網卡進行通訊,程式關閉後將消失。
 *  ping 10.0.0.1
 *  Documentation/networking/tuntap.txt
 *  br_select.c bridge based on select system call.
 *  br_sigio.c  bridge based on async io and SIGIO signal.
 *  http://hi.baidu.com/zkheartboy/blog/item/e96acf33508e4a40ad4b5f88.html
 *  http://blogold.chinaunix.net/u3/114446/showart_2245279.html
 *  http://www.ibm.com/developerworks/cn/linux/l-tuntap/index.html
 */
#include <fcntl.h><br />#include <stdio.h><br />#include <string.h><br />#include <sys/socket.h><br />#include <sys/ioctl.h><br />#include <linux/if.h><br />#include <linux/if_tun.h><br />#include <sys/types.h><br />#include <errno.h><br />#include <net/route.h></p><p>/**<br /> * 啟用介面<br /> */<br />int interface_up(char *interface_name)<br />{<br /> int s;</p><p> if((s = socket(PF_INET,SOCK_STREAM,0)) < 0)<br /> {<br /> printf("Error create socket :%m/n", errno);<br /> return -1;<br /> }</p><p> struct ifreq ifr;<br /> strcpy(ifr.ifr_name,interface_name);</p><p> short flag;<br /> flag = IFF_UP;<br /> if(ioctl(s, SIOCGIFFLAGS, &ifr) < 0)<br /> {<br /> printf("Error up %s :%m/n",interface_name, errno);<br /> return -1;<br /> }</p><p> ifr.ifr_ifru.ifru_flags |= flag;</p><p> if(ioctl(s, SIOCSIFFLAGS, &ifr) < 0)<br /> {<br /> printf("Error up %s :%m/n",interface_name, errno);<br /> return -1;<br /> }</p><p> return 0;</p><p>}</p><p>/**<br /> * 設定介面ip地址<br /> */<br />int set_ipaddr(char *interface_name, char *ip)<br />{<br /> int s;</p><p> if((s = socket(PF_INET, SOCK_STREAM, 0)) < 0)<br /> {<br /> printf("Error up %s :%m/n",interface_name, errno);<br /> return -1;<br /> }</p><p> struct ifreq ifr;<br /> strcpy(ifr.ifr_name, interface_name);</p><p> struct sockaddr_in addr;<br /> bzero(&addr, sizeof(struct sockaddr_in));<br /> addr.sin_family = PF_INET;<br /> inet_aton(ip, &addr.sin_addr);</p><p> memcpy(&ifr.ifr_ifru.ifru_addr, &addr, sizeof(struct sockaddr_in));</p><p> if(ioctl(s, SIOCSIFADDR, &ifr) < 0)<br /> {<br /> printf("Error set %s ip :%m/n",interface_name, errno);<br /> return -1;<br /> }</p><p> return 0;<br />}</p><p>/**<br /> * 建立介面<br /> */<br />int tun_create(char *dev, int flags)<br />{<br /> struct ifreq ifr;<br /> int fd, err;</p><p> if ((fd = open("/dev/net/tun", O_RDWR)) < 0)<br /> {<br /> printf("Error :%m/n", errno);<br /> return -1;<br /> }</p><p> memset(&ifr, 0, sizeof(ifr));<br /> ifr.ifr_flags |= flags;</p><p> if (*dev != '/0')<br /> {<br /> strncpy(ifr.ifr_name, dev, IFNAMSIZ);<br /> }</p><p> if ((err = ioctl(fd, TUNSETIFF, (void *)&ifr)) < 0)<br /> {<br /> printf("Error :%m/n", errno);<br /> close(fd);<br /> return -1;<br /> }</p><p> strcpy(dev, ifr.ifr_name);</p><p> return fd;<br />}</p><p>/**<br /> * 增加到10.0.0.1的路由<br /> * 同命令:route add 10.0.0.1 dev tun0<br /> */<br />int route_add(char * interface_name)<br />{<br /> int skfd;<br /> struct rtentry rt;</p><p> struct sockaddr_in dst;<br /> struct sockaddr_in gw;<br /> struct sockaddr_in genmask;</p><p> memset(&rt, 0, sizeof(rt));</p><p> genmask.sin_addr.s_addr = inet_addr("255.255.255.255");</p><p> bzero(&dst,sizeof(struct sockaddr_in));<br /> dst.sin_family = PF_INET;<br /> dst.sin_addr.s_addr = inet_addr("10.0.0.1");</p><p> rt.rt_metric = 0;<br /> rt.rt_dst = *(struct sockaddr*) &dst;<br /> rt.rt_genmask = *(struct sockaddr*) &genmask;</p><p> rt.rt_dev = interface_name;<br /> rt.rt_flags = RTF_UP | RTF_HOST ;</p><p> skfd = socket(AF_INET, SOCK_DGRAM, 0);<br /> if(ioctl(skfd, SIOCADDRT, &rt) < 0)<br /> {<br /> printf("Error route add :%m/n", errno);<br /> return -1;<br /> }<br />}<br />int main(int argc, char *argv[])<br />{<br /> int tun, ret;<br /> char tun_name[IFNAMSIZ];<br /> unsigned char buf[4096];<br /> unsigned char ip[4];</p><p> tun_name[0] = '/0';<br /> tun = tun_create(tun_name, IFF_TUN | IFF_NO_PI);<br /> if (tun < 0)<br /> {<br /> return 1;<br /> }<br /> printf("TUN name is %s/n", tun_name);</p><p> //啟用虛擬網卡增加到虛擬網卡的路由<br /> interface_up(tun_name);<br /> route_add(tun_name);</p><p> while (1) {</p><p> ret = read(tun, buf, sizeof(buf));<br /> printf("read %d bytes/n", ret);<br /> int i;<br /> for(i=0;i<ret;i++)<br /> {<br /> printf("%02x ",buf[i]);<br /> }<br /> printf("/n");<br /> if (ret < 0)<br /> break;<br /> memcpy(ip, &buf[12], 4);<br /> memcpy(&buf[12], &buf[16], 4);<br /> memcpy(&buf[16], ip, 4);<br /> buf[20] = 0;<br /> *((unsigned short*)&buf[22]) += 8;<br /> ret = write(tun, buf, ret);<br /> printf("write %d bytes/n", ret);<br /> }</p><p> return 0;<br />}

測試方法:

1 先編譯運行此程式,監聽資料的讀寫。

2 開啟另外一個終端,執行ping命令,就是本地發一個測試包到10.0.0.1

即可看到收到和接收的資料包IP包了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.