11.4.8 使用SOCK_PACKET编写ARP请求程序的例子

11.4.8  使用SOCK_PACKET编写ARP请求程序的例子

本节利用SOCK_PACKET套接字进行ARP请求的程序设计,并给出代码的例子。

1ARP协议数据和结构

包含以太网头部数据的ARP协议数据结构如图11.16所示。

11.16  ARP协议的数据示意图

ARP的数据结构在头文件<linux/if_arp.h>中定义,代码如下:

 

struct arphdr

{

    __be16      ar_hrd;         /*硬件类型*/

    __be16      ar_pro;         /*协议类型*/

    unsigned char   ar_hln;     /*硬件地址长度*/

    unsigned char   ar_pln;     /*协议地址长度*/

    __be16      ar_op;          /*ARP操作码*/

};

 

对于以太网上的ARP请求包,上述成员的值如表11.6所示。

11.6  ARP在以太网上请求包的值和含义

   

   

ar_hrd

硬件类型

1

硬件地址为以太网接口

ar_pro

协议类型

0x0800

高层协议为IP协议

ar_hln

硬件地址长度

6

6字节,即MAC地址48

ar_pln

协议地址长度

4

IP协议地址长度为32

ar_op

ARP操作码

1

ARP请求

2.例子中的ARP数据结构

按照图11.16所示,定义如下以太网的ARP数据结构:

 

struct arppacket

{

    unsigned short  ar_hrd;                 /*硬件类型*/

    unsigned short  ar_pro;                 /*协议类型*/

    unsigned char   ar_hln;                 /*硬件地址长度*/

    unsigned char   ar_pln;                 /*协议地址长度*/

    unsigned short  ar_op;                  /*ARP操作码*/

    unsigned char   ar_sha[ETH_ALEN];       /*发送方MAC地址*/

    unsigned char   ar_sip[4];              /*发送方IP地址*/

    unsigned char   ar_tha[ETH_ALEN];       /*目的MAC地址*/

    unsigned char   ar_tip[4];              /*目的IP地址 */

};

3ARP请求的主程序代码

ARP请求包的构建包含了以太网头部部分、ARP头部部分、ARP的数据部分。其中特别要注意目的以太网地址,由于ARP的作用就是查找目的IP地址的MAC地址,所以目的以太网地址是未知的。而且需要在整个以太网上查找其IP地址,所以目的以太网地址是一个全为1的值,即为{0xFF,0xFF,0xFF ,0xFF ,0xFF ,0xFF}

 

01  #include <sys/socket.h>

02  #include <sys/ioctl.h>                  /*ioctl 命令*/

03  #include <Linux/if_ether.h>             /*ethhdr 结构*/

04  #include <net/if.h>                     /*ifreq 结构*/

05  #include <netinet/in.h>                 /*in_addr结构*/

06  #include <Linux/ip.h>                   /*iphdr 结构*/

07  #include <Linux/udp.h>                  /*udphdr 结构*/

08  #include <Linux/tcp.h>                  /*tcphdr 结构*/

09  struct arppacket

10  {

11      unsigned short  ar_hrd;             /*硬件类型*/

12      unsigned short  ar_pro;             /*协议类型*/

13      unsigned char   ar_hln;             /*硬件地址长度*/

14      unsigned char   ar_pln;             /*协议地址长度*/

15      unsigned short  ar_op;              /*ARP操作码*/

16      unsigned char   ar_sha[ETH_ALEN];   /*发送方MAC地址*/

17      unsigned char   ar_sip[4];          /*发送方IP地址*/

18      unsigned char   ar_tha[ETH_ALEN];   /*目的MAC地址*/

19      unsigned char   ar_tip[4];          /*目的IP地址*/

20 

21  };

22  int main(int argc, char*argv[])

23  {

24      char ef[ETH_FRAME_LEN];             /*以太帧缓冲区*/

25      struct ethhdr*p_ethhdr;             /*以太网头部指针*/

26      /*目的以太网地址*/

27      char eth_dest[ETH_ALEN]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};

28      /*源以太网地址*/

29      char eth_source[ETH_ALEN]={0x00,0x0C,0x29,0x73,0x9D,0x15};

30                                          /*目的IP地址*/

31      char eth_dest[4]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};

32      int n;     

33     

34      int fd;                              /*fd是套接口的描述符*/

35      fd = socket(AF_INET, SOCK_PACKET, htons(0x0003));

36     

37      /*使p_ethhdr指向以太网帧的帧头*/

38      p_ethhdr = (struct ethhdr*)ef;

39      /*复制目的以太网地址*/

40      memcpy(p_ethhdr->h_dest, eth_dest, ETH_ALEN);

41      /*复制源以太网地址*/

42      memcpy(p_ethhdr->h_source, eth_source, ETH_ALEN);

43      /*设置协议类型,以太网0x0806*/

44      p_ethhdr->h_proto = htons(0x0806);

45     

46      struct arppacket*p_arp;

47      p_arp = ef + ETH_HLEN;              /*定位ARP包地址*/

48      p_arp->ar_hrd = htons(0x1);         /*arp硬件类型*/

49      p_arp->ar_pro = htons(0x0800);      /*协议类型*/

50      p_arp->ar_hln = 6;                  /*硬件地址长度*/

51      p_arp->ar_pln = 4;                  /*IP地址长度*/

52      /*复制源以太网地址*/

53      memcpy(p_arp->ar_sha, eth_source, ETH_ALEN);

54      /*IP地址*/

55      (unsigned int*)p_arp->ar_sip = inet_addr("192.168.1.152");

56      /*复制目的以太网地址*/

57      memcpy(p_arp->ar_tha, eth_dest, ETH_ALEN);

58      /*目的IP地址*/

59      (unsigned int*)p_arp->ar_tip = inet_addr("192.168.1.1");   

60     

61      /*发送ARP请求8次,间隔1s*/

62      int i = 0;

63      for(i=0;i<8;i++){

64          n = write(fd, ef, ETH_FRAME_LEN);/*发送*/

65          sleep(1);                       /*等待1s*/

66      }

67

68      close(fd);

69      return 0;

70  }

 

上述代码分为如下步骤:

q      27行为目的MAC,全部为0xFF,表示在局域网进行广播。

q      29行为本机的MAC地址。

q      35行建立一个SOCK_PACKET类型的套接字文件描述符。

q      3760行用于构建ARP请求包,第38行用于定位以太网头部。

q      40行将目的以太网地址复制到以太网头部结构的成员h_dest中。

q      42行将源以太网地址复制到以太网头部结构的成员h_source中。

q      44行设置以太网的协议类型为0x0806,即ARP协议。

q      47行定位ARP地址。

q      4851行设置ARP头部成员的值,如表11.1所示。

q      53行复制源以太网地址,与第42行是一致的。

q      55行设置发送端的IP地址。

q      5759行分别复制了目的以太网地址和目的IP地址。其中目的以太网地址全为1的值。

q      6266行发送数据,期间间隔1s,共发送8次。

你可能感兴趣的:(数据结构,c,struct,socket)