Winapi:发送arp回复

时间:2017-06-01 10:25:57

标签: c sockets winapi

我是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.谢谢。

0 个答案:

没有答案