创建TAP设备失败:IOCTL调用返回文件描述符状态异常
解决TUN/TAP设备创建时的IOCTL错误
错误原因分析
- 错误的IOCTL命令码:最初代码中使用
'T'作为ioctl命令,这完全不符合TUN/TAP设备的要求,正确的命令应该是TUNSETIFF——这是内核定义的用于配置tuntap设备的标准命令码,使用错误的命令码会直接导致"File descriptor in bad state"错误。 - 非法的设备名称:替换为
TUNSETIFF后出现"Invalid argument",核心问题是你传入的设备名"my tuntap"包含空格,Linux网络接口名称不允许包含空格,且必须符合命名规范(通常由字母、数字和下划线组成,长度不超过15个字符,因为IFNAMSIZ为16,包含字符串终止符)。
修复后的代码
#include <stdio.h> #include <string.h> #include <linux/if.h> #include <linux/if_tun.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> int tun_alloc(char *dev) { struct ifreq ifr; int fd, err; if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) { puts("Failed to open TAP device"); return -1; } memset(&ifr, 0, sizeof(ifr)); /* Flags: IFF_TUN - TUN device (no Ethernet headers) * IFF_TAP - TAP device * * IFF_NO_PI - Do not provide packet information */ ifr.ifr_flags = IFF_TAP | IFF_NO_PI; if(*dev) { strncpy(ifr.ifr_name, dev, IFNAMSIZ-1); // 预留字符串终止符位置 ifr.ifr_name[IFNAMSIZ-1] = '\0'; // 确保字符串正确终止 } if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) { perror("IOCTL call failed"); close(fd); return err; } strcpy(dev, ifr.ifr_name); return fd; } int main(void) { char dev_name[] = "mytap0"; // 无空格的合法设备名 int fd = tun_alloc(dev_name); if (fd < 0) { return -1; } printf("Created TAP device: %s\n", dev_name); getchar(); close(fd); return 0; }
运行注意事项
- 必须以root权限运行(使用
sudo),因为创建TUN/TAP设备需要系统特权 - 设备名要符合Linux网络接口命名规则:不能包含空格、特殊字符,长度不超过15个字符
- 编译时无需额外依赖,直接用
gcc tun.c -o tun编译即可
内容的提问来源于stack exchange,提问作者nee
相关产品推荐
相关产品推荐

