Linux下向TAP/TUN设备写入数据包时出现errno 5错误的原因排查
关于Linux TAP/TUN设备写入数据包返回errno 5(EIO)的问题解答
首先明确:errno 5对应的是EIO(输入/输出错误),这是内核在告诉你它无法处理当前的写操作请求。下面针对你的两个问题逐一分析:
1. 向TAP设备写入数据包出现errno 5的可能原因
TAP是二层虚拟以太网设备,它只接受符合二层以太网规范的数据包,出现EIO通常是以下原因:
- 设备未激活:TAP设备默认是down状态,必须先通过
ip link set dev <tap-dev> up命令激活,否则内核会拒绝任何写入操作。 - 数据包格式不符合要求:TAP期望接收完整的二层以太网帧(包含6字节目的MAC、6字节源MAC、2字节帧类型,再加上 payload)。如果写入的是三层IP包、格式残缺的帧,或者帧长度不符合以太网规范(小于64字节或大于1500字节),内核会直接返回EIO。
- 网络命名空间不匹配:如果你的程序所在的网络命名空间和TAP设备不在同一个空间,写操作会失败。可以用
ip link show查看当前命名空间下的设备列表,确认TAP设备可见。 - 内核/驱动异常:极少数情况下是
tun模块加载异常或内核bug,尝试重新加载模块:modprobe -r tun && modprobe tun,或者升级内核版本排查。
2. 向TUN设备写入BOOTP请求返回errno 5的具体分析
结合你提供的数据包和描述(能写入ARP回复、已用root权限、校验和正确),核心问题大概率出在TUN设备的数据包格式要求上:
TUN是三层虚拟IP设备,它只处理纯三层IP数据包(没有以太网头部),而你提供的数据包是完整的二层以太网帧(开头是广播MAC地址ff.ff.ff.ff.ff.ff,接着是源MAC和帧类型)——这完全不符合TUN设备的接收规范,内核直接拒绝并返回EIO。
补充排查点:
- 为什么ARP回复能成功?ARP是二层协议,正常情况下TUN设备根本无法处理ARP数据包。这说明你可能混淆了TUN和TAP设备:要么是你误将TAP设备当成了TUN,要么是创建TUN设备时错误使用了
IFF_TAP标志(实际创建了TAP设备)。可以用ip link show <your-dev>确认:TAP设备会显示ether(MAC地址),而TUN设备没有MAC地址,只显示inet(IP地址)。 - 如果确实是TUN设备,还要注意默认情况下TUN设备要求写入的数据包带4字节TUN包头(前2字节是flags,后2字节是协议类型,比如
0x0800对应IP),再加上纯IP数据包。如果直接写入无包头的IP包,也会返回EIO。你可以在创建TUN设备时添加IFF_NO_PI标志,关闭包头要求,直接写入纯IP包。
解决建议:
- 先确认设备类型:用
ip link show检查你的设备到底是TUN还是TAP。 - 如果是TUN设备:提取数据包中的纯IP部分(从你的数据包里
45.00开始的字节),如果没有设置IFF_NO_PI,要先加上4字节TUN包头再写入;如果设置了IFF_NO_PI,直接写入纯IP包即可。 - 如果是TAP设备:检查BOOTP帧的格式是否合法(比如帧长度是否在64-1500字节之间,帧类型是否正确为
0x0800对应IP),排除帧格式问题。
内容的提问来源于stack exchange,提问作者EnTaroAdun
相关产品推荐
相关产品推荐

