我是Winapi的新手,目前正尝试使用原始套接字发送arp数据包。这是我的代码:
#include "winsock2.h"
#include "windows.h"
#include "time.h"
#include "stdio.h"
#include "ws2tcpip.h"
#include "conio.h"
#define ETH_HW_ADDR_LEN 6
#define IP_ADDR_LEN 4
#define ARP_FRAME_TYPE 0x0806
#define ETHER_HW_TYPE 1
#define IP_PROTO_TYPE 0x0800
#define OP_ARP_REPLY 2
struct arp_packet {
u_short hw_type; // Hardware type (HTYPE)
u_short prot_type; // Protocol type (PTYPE)
u_char hw_addr_size; // Hardware length (HLEN)
u_char prot_addr_size; // Protocol length (PLEN)
u_short op; // Operation
u_char sndr_hw_addr[ETH_HW_ADDR_LEN]; // Sender hardware address (SHA)
u_char sndr_ip_addr[IP_ADDR_LEN]; // Sender protocol address (SPA)
u_char rcpt_hw_addr[ETH_HW_ADDR_LEN]; // Target hardware address (THA)
u_char rcpt_ip_addr[IP_ADDR_LEN]; // Target protocol address (TPA)
};
void get_ip_addr( struct in_addr* in_addr, char* str ){
struct hostent *hostp;
in_addr->s_addr = inet_addr(str);
if ( in_addr->s_addr == -1 ){
if( (hostp = gethostbyname(str)))
{memcpy (in_addr, hostp->h_addr, hostp->h_length);}
else {
fprintf( stderr, "send_arp: unknown host [%s].\n", str ) ;
exit(1);
}
}
} ; // get_ip_addr
int main()
{
struct in_addr src_in_addr, targ_in_addr;
struct arp_packet pkt;
char *sender_mac = "AA-AA-AA-AA-AA-AA";
char *receiver_mac = "88-9F-FA-6E-64-3Q";
SOCKET s;
int optval;
hostent *server;
WSADATA wsock;
if (WSAStartup(MAKEWORD(2,2),&wsock) != 0)
{
fprintf(stderr,"WSAStartup() failed");
exit(EXIT_FAILURE);
}
printf("Initialised successfully.\n");
if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW))==SOCKET_ERROR)
{
printf("Creation of raw socket failed %d\n.", WSAGetLastError());
return 0;
}
printf("Raw TCP Socket Created successfully.\n");
if(setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&optval, sizeof(optval))==SOCKET_ERROR)
{
printf("failed to set socket in raw mode %d\n.", WSAGetLastError());
return 0;
}
printf("Successful.\n");
pkt.hw_type = htons(ETHER_HW_TYPE);
pkt.prot_type = htons(IP_PROTO_TYPE);
pkt.hw_addr_size = ETH_HW_ADDR_LEN;
pkt.prot_addr_size = IP_ADDR_LEN;
pkt.op = htons(OP_ARP_REPLY);
strcpy((char *)pkt.sndr_hw_addr, sender_mac);
strcpy((char *)pkt.rcpt_hw_addr, receiver_mac);
get_ip_addr( &src_in_addr, "192.168.1.53");
get_ip_addr( &targ_in_addr, "192.168.1.113");
memcpy( pkt.sndr_ip_addr, &src_in_addr, IP_ADDR_LEN);
memcpy( pkt.rcpt_ip_addr, &targ_in_addr, IP_ADDR_LEN);
if((sendto(s , (const char* )&pkt , sizeof(pkt), 0, 0, 0))==SOCKET_ERROR)
{
printf("Error sending Packet : %d\n", WSAGetLastError());
}
return 0;
}
由于这仅用于教育目的,我硬编码MAC和IP地址正如您所见,我试图将ARP回复发送到某个IP地址。
我使用cygwin
编译,输出是:
$ ./test.exe
Initialised successfully.
Raw TCP Socket Created successfully.
Successful.
Error sending Packet : 10057
我已经搜索过,10057
表示Socket is not connected.
但我不知道为什么我会收到此错误。然后我决定将sendto
函数更改为:
SOCKADDR_IN dest;
if((sendto(s , (const char* )&pkt , sizeof(pkt), 0, (SOCKADDR *)&dest, sizeof(dest)))==SOCKET_ERROR)
只是为了看看会发生什么,我仍然有错误,但它是不同的10047
。这意味着Address family not supported by protocol family.
但是在msdn文档中,我已经看到This is a possible value when the af parameter is AF_UNSPEC, AF_INET, or AF_INET6 and the type parameter is SOCK_RAW or unspecified
我正在使用Windows 7.谢谢。