[Linux网络编程]ARP简单实例

一个简单的ARP实例。

先声明,本文是基于于一篇来自邹鑫的专栏的文章,地址如下:

http://blog.csdn.net/zouxinfox/archive/2008/10/25/3141323.aspx

山人根据自己的实际情况稍微改动一下代码,不过山人纯粹是用来学习的,没有干坏事。

 

下面的图片依然来自《TCP/IP详解》一书。

 

ARP分组格式

在前篇文章中,我们知道,一个ARP包(分组)除了以太网头部和ARP请求/应答字段外,还有18个字节的填充字段(山人根据PAD一词猜的),这样一个ARP包就有14+28+18=60字节(不相信的话,大家可以慢慢数一数每个字段的字节数)。下面我们将会看到,代码中就是分配了60字节的空间。

 

ARP头部结构体是这样的:

struct arphdr
  {
    unsigned short int ar_hrd;  /* Format of hardware address.  */
    unsigned short int ar_pro;  /* Format of protocol address.  */
    unsigned char ar_hln;  /* Length of hardware address.  */
    unsigned char ar_pln;  /* Length of protocol address.  */
    unsigned short int ar_op;  /* ARP opcode (command).  */
  };

(来自<net/if_arp.h>)

它其实就是“28字节ARP请求/应答”中前面的8个字节。

第一个成员表示硬件地址的格式,就是图中的“硬件类型”,它有如下这些:

#define ARPHRD_NETROM 0  /* From KA9Q: NET/ROM pseudo. */
#define ARPHRD_ETHER  1  /* Ethernet 10/100Mbps.  */
#define ARPHRD_EETHER 2  /* Experimental Ethernet.  */
#define ARPHRD_AX25 3  /* AX.25 Level 2.  */
#define ARPHRD_PRONET 4  /* PROnet token ring.  */
#define ARPHRD_CHAOS 5  /* Chaosnet.  */
#define ARPHRD_IEEE802 6  /* IEEE 802.2 Ethernet/TR/TB.  */
#define ARPHRD_ARCNET 7  /* ARCnet.  */
#define ARPHRD_APPLETLK 8  /* APPLEtalk.  */
#define ARPHRD_DLCI 15  /* Frame Relay DLCI.  */
#define ARPHRD_ATM 19  /* ATM.  */
#define ARPHRD_METRICOM 23  /* Metricom STRIP (new IANA id).  */
#define ARPHRD_IEEE1394 24  /* IEEE 1394 IPv4 - RFC 2734.  */
#define ARPHRD_EUI64  27  /* EUI-64.  */
#define ARPHRD_INFINIBAND 32  /* InfiniBand.  */

(同上)

其实第2个是以太网,在代码中使用它。

 

第二个成员表示协议类型,这里是ARP协议(一句必要的废话)。

最后一个成员表示操作类型,在<net/if_arp.h>是这样的:

/* ARP protocol opcodes. */
#define ARPOP_REQUEST 1  /* ARP request.  */
#define ARPOP_REPLY 2  /* ARP reply.  */
#define ARPOP_RREQUEST 3  /* RARP request.  */
#define ARPOP_RREPLY 4  /* RARP reply.  */
#define ARPOP_InREQUEST 8  /* InARP request.  */
#define ARPOP_InREPLY 9  /* InARP reply.  */
#define ARPOP_NAK 10  /* (ATM)ARP NAK.  */

其中就是ARP请求,ARP应答。

 

但是,光有这个结构体还是不行的,我们需要的是ARP包。

这个结构体是这样的:

struct ether_arp {
 struct arphdr ea_hdr;  /* fixed-size header */
 u_int8_t arp_sha[ETH_ALEN]; /* sender hardware address */
 u_int8_t arp_spa[4];  /* sender protocol address */
 u_int8_t arp_tha[ETH_ALEN]; /* target hardware address */
 u_int8_t arp_tpa[4];  /* target protocol address */
};
#define arp_hrd ea_hdr.ar_hrd
#define arp_pro ea_hdr.ar_pro
#define arp_hln ea_hdr.ar_hln
#define arp_pln ea_hdr.ar_pln
#define arp_op ea_hdr.ar_op
(来自<netinet/if_ether.h>)

它包含了ARP头部那个结构体,所以在程序中直接使用这个就可以了。这个结构体就是根据上面那个图来定义,没啥好说的。不过,这里要注意一下人家代码的技巧。它在下面定义一些宏,一开始我很不理解,后面才发现这种用法很好,值得学习。比如我们要赋值给ARP头部的op,可以这样

arp->ea_hdr->ar_op

也可以这样

arp->arp_op

(假设arp是ether_arp结构体的指针)。代码中就是使用后面那种方式的,比较简便。

 

废话讲完,该上菜了。下面给出代码

再次声明,代码非原创,链接地址见文章开头处。

在虚拟机Linux中测试,在物理机Windows系统中查看结果,网络连接为NAT8。

Linux系统,eth7,IP地址192.168.184.1.100,代码中的物理地址是瞎写的。

运行程序后,在Windows系统的的cmd命令行下输入arp -a,可以看到Linux系统中的MAC地址已经变为代码中的地址了。

限于环境及个人能力,不敢作太多测试。权当学习例子而已。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值