You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

创建TAP设备失败:IOCTL调用返回文件描述符状态异常

解决TUN/TAP设备创建时的IOCTL错误

错误原因分析

  1. 错误的IOCTL命令码:最初代码中使用'T'作为ioctl命令,这完全不符合TUN/TAP设备的要求,正确的命令应该是TUNSETIFF——这是内核定义的用于配置tuntap设备的标准命令码,使用错误的命令码会直接导致"File descriptor in bad state"错误。
  2. 非法的设备名称:替换为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 14:57:28