在一个多平台项目中,我使用pcap获取所有网络接口的列表,打开每个接口(用户无法选择使用哪些接口)和发送/接收数据包(以太网类型0x88e1 / HomePlugAV)。这在Windows和Mac OS X上运行良好,但有时在Mac OS X上pcap_sendpacket
在networksetup -listallhardwareports
列为“硬件端口:Thunderbolt 1”的接口上运行一段时间后失败。错误是:
发送:没有可用的缓冲区空间
在机器启动后运行程序时,错误发生需要一些时间。当错误发生一次并且我停止我的程序时,当我重新启动程序而不重新启动计算机时会立即发生错误。
ifconfig -v en9:
en9: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500 index 8
eflags=80<TXSTART>
options=60<TSO4,TSO6>
ether b2:00:1e:94:9b:c1
media: autoselect <full-duplex>
status: inactive
type: Ethernet
scheduler: QFQ
networksetup -listallhardwareports(仅相关部分):
Hardware Port: Thunderbolt 1
Device: en9
Ethernet Address: b2:00:1e:94:9b:c1
测试表明,在OS X 10.9上,接口最初没有启动,但在OS X 10.9.2和10.9.3上,接口启动后启动并运行。
在OS X 10.9上ifconfig最初说:
en5: flags=8822<BROADCAST,SMART,SIMPLEX,MULTICAST> mtu 1500 index 8
{1}后问题行为在OS X 10.9上是相同的。
ifconfig en5 up
在Thunderbolt适配器上失败?答案 0 :(得分:2)
作为一种解决方法,你可以忽略&#34; Thunderbolt 1&#34;接口:
#include <stdio.h>
#include <pcap/pcap.h>
#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SCNetworkConfiguration.h>
const char thunderbolt[] = "Thunderbolt 1";
// Build with -framework CoreFoundation -framework SystemConfiguration
int main(int argc, char * argv[])
{
// See: https://opensource.apple.com/source/configd/configd-596.13/SystemConfiguration.fproj/SCNetworkInterface.c
// get Ethernet, Firewire, Thunderbolt, and AirPort interfaces
CFArrayRef niArrayRef = SCNetworkInterfaceCopyAll();
// Find out the thunderbolt iface
char thunderboltInterface[4] = "";
if(niArrayRef) {
CFIndex cnt = CFArrayGetCount(niArrayRef);
for(CFIndex idx = 0; idx < cnt; ++idx) {
SCNetworkInterfaceRef tSCNetworkInterfaceRef = (SCNetworkInterfaceRef)CFArrayGetValueAtIndex(niArrayRef, idx);
if(tSCNetworkInterfaceRef) {
CFStringRef BSDName = SCNetworkInterfaceGetBSDName(tSCNetworkInterfaceRef);
const char * interfaceName = (BSDName == NULL) ? "none" : CFStringGetCStringPtr(BSDName, kCFStringEncodingUTF8);
CFStringRef localizedDisplayName = SCNetworkInterfaceGetLocalizedDisplayName(tSCNetworkInterfaceRef);
const char * interfaceType = (localizedDisplayName == NULL) ? "none" : CFStringGetCStringPtr(localizedDisplayName, kCFStringEncodingUTF8);
printf("%s : %s\n", interfaceName, interfaceType);
if(strcmp(interfaceType, thunderbolt) == 0) {
// Make a copy this time
CFStringGetCString(BSDName, thunderboltInterface, sizeof(thunderboltInterface), kCFStringEncodingUTF8);
}
}
}
}
printf("%s => %s\n", thunderbolt, thunderboltInterface);
CFRelease(niArrayRef);
return 0;
}
答案 1 :(得分:1)
我在猜测
在机器启动后运行程序时,错误发生需要一些时间。当错误发生一次并且我停止我的程序时,当我重新启动程序而不重新启动计算机时会立即发生错误。
这里可能发生的是接口处于非活动状态,因此不会传输给它发送的数据包(并释放它们的mbuf),和 aren'丢弃,但是,只是留在接口的队列中进行传输。最终队列填满或尝试为数据包分配一些资源失败,并且接口的驱动程序返回ENOBUFS错误。
这可以说是OS X的错误。
这
在一个多平台项目中,我使用pcap获取所有网络接口的列表,打开每个接口(用户无法选择使用哪些接口)和发送/接收数据包(以太网类型0x88e1 / HomePlugAV)。
我怀疑你没有发送所有接口;并非所有接口都具有具有以太网类型字段的链路层标头类型 - 例如,lo0
没有。
如果您正在构建以太网数据包,则只需要发送具有pcap_datalink()
的链路层标头类型(由DLT_EN10MB
返回)的接口(“10MB”是历史工件;它指的是除了旧的实验性3MB Xerox以太网之外的所有以太网类型,它们具有不同的链路层头。)
你可能也不想打扰那些在某种意义上不“活跃”的界面(除了“up up”之外的某种意义);遗憾的是,没有与平台无关的API来确定这一点,所以你将不得不在这里使用#ifdefs。这可能会排除数据包堆积不存在的接口,并最终导致ENOBUFS错误。