和标准的uIP不同的是,tun2tap版本的uIP并不从虚拟网卡读取以太帧,而是从网络套接字读取以太帧,虚拟网卡只是tun2tap版本uIP的“上层”,这一点是和标准的uIP的unix/main.c逻辑完全相反的。以下就是新版的main逻辑代码:
int main(int argc, char **argv)
{
.......
// 设置本端的IP地址以及MAC,正常逻辑应该在获取虚拟IP地址以后再设置
uip_ipaddr(ipaddr, 1,2,3,5);
uip_sethostaddr(ipaddr);
uip_ipaddr(ipaddr, 1,2,3,4);
uip_setdraddr(ipaddr);
uip_ipaddr(ipaddr, 255,255,255,0);
uip_setnetmask(ipaddr);
... // 设置MAC地址
// 初始化和simpletun连接的套接字
net_init();
while(1) {
char raw_tun[UIP_BUFSIZE];
memset(uip_buf, 0, sizeof(uip_buf));
// 从套接字读取数据,要么为ARP,要么为IP
uip_len = net_read();
if(uip_len > 0) {
// 如果是IP的话,摘掉以太头送往TUN网卡
if(BUF->type == htons(UIP_ETHTYPE_IP)) {
char *buf2tun = BUF;
buf2tun += sizeof(struct uip_eth_hdr);
// 送往TUN虚拟网卡
tapdev_send(buf2tun, uip_len-sizeof(struct uip_eth_hdr));
// 如果是ARP的话,回复ARP请求或者...
} else if(BUF->type == htons(UIP_ETHTYPE_ARP)) {
// 处理ARP
uip_arp_arpin();
if(uip_len > 0) {
// 回复ARP
net_send();
}
}
} else if(timer_expired(&periodic_timer)) {
timer_reset(&periodic_timer);
for(i = 0; i < UIP_CONNS; i++) {
uip_periodic(i);
if(uip_len > 0) {
uip_arp_out();
net_send();
}
}
if(timer_expired(&arp_timer)) {
timer_reset(&arp_timer);
uip_arp_timer();
}
}
// 继续处理TAP网卡读出的数据,封装上以太帧头
memset(uip_buf, 0, sizeof(uip_buf));
uip_len = tapdev_read(raw_tun,
UIP_BUFSIZE);
if(uip_len > 0) {
memcpy(uip_buf+sizeof(struct uip_eth_hdr),
raw_tun,
uip_len);
// 要么请求ARP,要么直接发送数据
uip_arp_out();
net_send();
}
}
return 0;
}使用uIP将TUN网卡适配到TAP网卡-tun2tap,布布扣,bubuko.com
原文:http://blog.csdn.net/dog250/article/details/20281407