在Windows中发送原始ARP回复数据包

3
我目前正在学习如何使用Windows原始套接字。
我创建了一个原始ARP回复帧(包括所有标头(以太网+ARP标头)),但当我使用sendto函数发送时,它失败并返回错误代码10047的SOCKET_ERROR。
我用于创建套接字的参数如下:
socket s = socket(AF_INET,SOCK_RAW,IPPROTO_RAW);

同时,我将套接字选项更改为以下内容:

int on=1;
setsockopt(s,IPPROTO_IP, 2,(char*)&on,sizeof(on));

(顺便说一句,“2”等于IP_HDRINCL,由于某种原因,Visual Studio无法识别它...)
我尝试按以下方式发送数据包:
socketaddr sa = { 0 };
int SentBytesCount = sendto(s, (char*)&arp_raw_msg,sizeof(Arp_Frame),0,&sa,sizeof(sa));

Arp_Frame是一个结构体,包括以太网头+ARP头+18字节的填充。

调用后,我发现SentBytesCount等于SOCKET_ERROR(-1),并且没有数据包被发送。

谢谢您的帮助!

1个回答

3
Winsock错误10047是WSAEAFNOSUPPORT

地址族不受协议族支持。

使用与请求的协议不兼容的地址。所有套接字都使用关联的地址族(例如,对于Internet协议,使用AF_INET)和通用协议类型(例如,SOCK_STREAM)创建。如果在socket调用中明确请求了不正确的协议或者在套接字中使用了错误家族的地址,例如在sendto中,则返回此错误。

您创建了一个AF_INET(IPv4)套接字,但在传递给sendto()时未传递包含IPv4地址和端口的有效sockaddr_in,因此出现错误。您传递了一个空的socketaddr(那是什么?)。
无论您使用哪个sockaddr_...结构与套接字一起使用,它都必须与套接字的地址族匹配,由socket()调用设置(在您的情况下,使用AF_INET,它使用sockaddr_in地址)。
sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr("destination IP address");
sa.sin_port = htons(Destination port number);

int SentBytesCount = sendto(s, (char*)&arp_raw_msg, sizeof(Arp_Frame), 0, (struct sockaddr*)&sa, sizeof(sa));

关于 IP_HDRINCL,它在ws2tcpip.h中定义。

谢谢!我没有使用它的原因是因为它是ARP回复,因此它是第二层协议,因此没有IP地址。那么,有没有办法在没有IP地址的情况下发送ARP回复? - Gal Kaptsenel
在其他平台上发送ARP数据包需要使用AF_PACKETsockaddr_ll来达到以太网层。WinSock不支持这些。我认为你根本无法使用WinSock发送原始以太网数据包,因为WinSock对SOCK_RAW的实现似乎无法低于IP层。在WinSock上的原始套接字比其他平台上的更加受限制。如果不能更换操作系统,则必须使用第三方数据包库,例如WinPCap - Remy Lebeau
很遗憾,无法切换操作系统,非常感谢!希望winpcap与winsock类似,这样我的工作就不会白费了。 - Gal Kaptsenel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接