ARP请求.docx
- 文档编号:5728102
- 上传时间:2022-12-31
- 格式:DOCX
- 页数:10
- 大小:40.99KB
ARP请求.docx
《ARP请求.docx》由会员分享,可在线阅读,更多相关《ARP请求.docx(10页珍藏版)》请在冰豆网上搜索。
ARP请求
从下面的文章我们了解到,对于一个设备用的ARP协议而言,重要的东西包括三方面:
1.一个本地的IP与MAC地址的缓存表.以有对应的更新和查询操作.
2.一个发送ARP请求的函数.
3.一个处理ARP回复的函数.
下面我们来看uIP中是如何实现的(代码见uip_arp.c:
首先,定义一个缓存表的数据结构,99行起:
structarp_entry{
u16_tipaddr[2];
structuip_eth_addrethaddr;
u8_ttime;
};
只有三个项,很简单
第一项是ip地址,16*2=4*8位的,保存四个八位组.
第二项是MAC地址.
第三项是缓存更新时间.
下来是ARP请求发送函数:
/*-----------------------------------------------------------------------------------*/
/**
*PrependEthernetheadertoanoutboundIPpacketandseeifweneed
*tosendoutanARPrequest.
*为传出的IP包添加以太网头并看是否需要发送ARP请求.
*ThisfunctionshouldbecalledbeforesendingoutanIPpacket.The
*functionchecksthedestinationIPaddressoftheIPpackettosee
*whatEthernetMACaddressthatshouldbeusedasadestinationMAC
*addressontheEthernet.
*此函数应该在发送IP包时调用,它会检查IP包的目的IP地址,看看以太网应该使用什么目的MAC地址.
*IfthedestinationIPaddressisinthelocalnetwork(determined
*bylogicalANDingofnetmaskandourIPaddress),thefunction
*checkstheARPcachetoseeifanentryforthedestinationIP
*addressisfound.Ifso,anEthernetheaderisprependedandthe
*functionreturns.IfnoARPcacheentryisfoundforthe
*destinationIPaddress,thepacketintheuip_buf[]isreplacedby
*anARPrequestpacketfortheIPaddress.TheIPpacketisdropped
*anditisassumedthattheyhigherlevelprotocols(e.g.,TCP)
*eventuallywillretransmitthedroppedpacket.
*如果目的IP地址是在局域网中(由IP地址与子网掩码的与逻辑决定),函数就会从ARP缓存表中查找有
*无对应项.若有,就取对应的MAC地址,加上以太网头,并返回,否则uip_buf[]中的数据包会被替换成一个
*目的IP在址的ARP请求.原来的IP包会被简单的仍掉,此函数假设高层协议(如TCP)会最终重传扔掉的包.
*IfthedestinationIPaddressisnotonthelocalnetwork,theIP
*addressofthedefaultrouterisusedinstead.
*如果目标IP地址并非一个局域网IP,则会使用默认路由的IP地址.
*Whenthefunctionreturns,apacketispresentintheuip_buf[]
*buffer,andthelengthofthepacketisintheglobalvariable
*uip_len.函数返回时,uip_buf[]中已经有了一个包,其长度由uip_len指定.
*/
/*-----------------------------------------------------------------------------------*/
void
uip_arp_out(void)
{
structarp_entry*tabptr;
/*FindthedestinationIPaddressintheARPtableandconstruct
theEthernetheader.IfthedestinationIPaddresisn'tonthe
localnetwork,weusethedefaultrouter'sIPaddressinstead.
//在ARP表中找到目的IP地址,构成以太网头.如果目的IP地址不在局域网中,则使用默认路由的IP.
IfnotARPtableentryisfound,weoverwritetheoriginalIP
packetwithanARPrequestfortheIPaddress.*/
//如果ARP表中找不到,则将原来的IP包替换成一个ARP请求.
/*Firstcheckifdestinationisalocalbroadcast.首先检查目标是不是广播*/
if(uip_ipaddr_cmp(IPBUF->destipaddr,broadcast_ipaddr)){
memcpy(IPBUF->ethhdr.dest.addr,broadcast_ethaddr.addr,6);
}else{
/*Checkifthedestinationaddressisonthelocalnetwork.检查目标地址是否在局域网内*/
if(!
uip_ipaddr_maskcmp(IPBUF->destipaddr,uip_hostaddr,uip_netmask)){
/*Destinationaddresswasnotonthelocalnetwork,soweneedto
usethedefaultrouter'sIPaddressinsteadofthedestination
addresswhendeterminingtheMACaddress.目的地址不在局域网内,所以保用默认路由器的地址来确在MAC地址*/
uip_ipaddr_copy(ipaddr,uip_draddr);
}else{
/*Else,weusethedestinationIPaddress.否则,使用目标IP地址*/
uip_ipaddr_copy(ipaddr,IPBUF->destipaddr);
}
for(i=0;i tabptr=&arp_table; if(uip_ipaddr_cmp(ipaddr,tabptr->ipaddr)){ break; } } if(i==UIP_ARPTAB_SIZE){ /*ThedestinationaddresswasnotinourARPtable,sowe overwritetheIPpacketwithanARPrequest.如果遍历到头没找到,将原IP包替换为ARP请求并返回*/ memset(BUF->ethhdr.dest.addr,0xff,6); memset(BUF->dhwaddr.addr,0x00,6); memcpy(BUF->ethhdr.src.addr,uip_ethaddr.addr,6); memcpy(BUF->shwaddr.addr,uip_ethaddr.addr,6); uip_ipaddr_copy(BUF->dipaddr,ipaddr); uip_ipaddr_copy(BUF->sipaddr,uip_hostaddr); BUF->opcode=HTONS(ARP_REQUEST);/*ARPrequest.*/ BUF->hwtype=HTONS(ARP_HWTYPE_ETH); BUF->protocol=HTONS(UIP_ETHTYPE_IP); BUF->hwlen=6; BUF->protolen=4; BUF->ethhdr.type=HTONS(UIP_ETHTYPE_ARP); uip_appdata=&uip_buf[UIP_TCPIP_HLEN+UIP_LLH_LEN]; uip_len=sizeof(structarp_hdr); return; } /*Buildanethernetheader.如果是在局域网中,且在ARP缓存中找到了(如果没找到进行不到这一步,在上面就返回了),则构建以太网头*/ memcpy(IPBUF->ethhdr.dest.addr,tabptr->ethaddr.addr,6); } memcpy(IPBUF->ethhdr.src.addr,uip_ethaddr.addr,6); IPBUF->ethhdr.type=HTONS(UIP_ETHTYPE_IP); uip_len+=sizeof(structuip_eth_hdr); } 以上内容自325行起.下面再总结一下其基本顺序: 用IPBUF->ethhdr.dest.addr来存储目的IP地址,它有可能是局域网内一主机,也可能是路由器(如果是发往外网,即原来的目的IP不在局域网内),还有可能是广播专用的MAC: broadcast_ethaddr.addr. 先看是不是在广播: 如果是广播,将IPBUF->ethhdr.dest.addr设为广播MAC. 再看是不是在局域网内: 如果不是,则将IPBUF->ethhdr.dest.addr设为路由器MAC. 如果在局域网内,查看是否已经存在于ARP缓存表中: 如果不在,将要发送的换成ARP请求,返回. 如果已存在,则查找使用查找到的MAC地址为IP包添加以太网头. 这里还要解释一些细节问题,主要是: 1.如何在IP包上添加以太网头 2.如果将IP包替换成ARP请求,ARP请求的格式是什么. 3.广播地址 将IP包替换成ARP请求部分代码(实际上IP包是放在uip_buf[]里的,这里只是将uip_buf[]填充上ARP请求即可),于uip_arp.c的388行: 1./*ThedestinationaddresswasnotinourARPtable,sowe 2. overwritetheIPpacketwithanARPrequest.*/ 3. 4. memset(BUF->ethhdr.dest.addr,0xff,6); 5. memset(BUF->dhwaddr.addr,0x00,6); 6. memcpy(BUF->ethhdr.src.addr,uip_ethaddr.addr,6); 7. memcpy(BUF->shwaddr.addr,uip_ethaddr.addr,6); 8. 9. uip_ipaddr_copy(BUF->dipaddr,ipaddr); 10. uip_ipaddr_copy(BUF->sipaddr,uip_hostaddr); 11. BUF->opcode=HTONS(ARP_REQUEST);/*ARPrequest.*/ 12. BUF->hwtype=HTONS(ARP_HWTYPE_ETH); 13. BUF->protocol=HTONS(UIP_ETHTYPE_IP); 14. BUF->hwlen=6; 15. BUF->protolen=4; 16. BUF->ethhdr.type=HTONS(UIP_ETHTYPE_ARP); 17. uip_appdata=&uip_buf[UIP_TCPIP_HLEN+UIP_LLH_LEN]; 18. 19. uip_len=sizeof(structarp_hdr); 20. return; 复制代码 首先解释这里的BUF(于uip_arp.c的116行): 1.#defineBUF((structarp_hdr*)&uip_buf[0]) 复制代码 可见这里的BUF就是uip_buf[],只不过这里将它取做一个structarp_hdr的结构体: 1.structarp_hdr{ 2. structuip_eth_hdrethhdr; 3. u16_thwtype; //硬件类型 4. u16_tprotocol;//协议类型 5. u8_thwlen; 6. u8_tprotolen; 7. u16_topcode; //操作码 8. structuip_eth_addrshwaddr;//源以太网地址 9. u16_tsipaddr[2];//源IP地址 10. structuip_eth_addrdhwaddr;//目的以太网地址 11. u16_tdipaddr[2];//目的IP地址 12.}; 复制代码 这里需要了解一下ARP的帧格式(【相关资料】ARP分组格式(帧格式,报文格式)): 1.structuip_eth_hdr{ 2.structuip_eth_addrdest; 3.structuip_eth_addrsrc; 4.u16_ttype; 5.}; 复制代码 这是arp_hdr的第一个成员ethhdr的类型定义,对应图片中的前三项: 6+6+2,目的以太网地址,源以太网地址,2字节数据类型(ARP请求和应答为0x0806). structarp_hdr的第二个成员u16_thwtype,对应图片中第三项,2字节硬件类型(值为1表示以太网). structarp_hdr的第三个成员u16_tprotocol,对应图片中第四项,2字节要映射的协议地址类型(ip地址为0x0800). structarp_hdr的第四个成员u8_thwlen,对应图片中第五项,1字节硬件地址长度(对MAC地址来说为6). structarp_hdr的第五个成员u8_tprotolen,对应图片中第六项,1字节协议地址长度(对IP地址来说为4). structarp_hdr的第六个成员u16_topcode,对应图片中第七项,2字节操作码(1ARP请求,2ARP应答,3RARP请求,4RARP应答,必须字段). structarp_hdr的第七个成员structuip_eth_addrshwaddr,对应图片中第八项,6字节源以太网地址. structarp_hdr的第八个成员u16_tsipaddr[2];,对应图片中第九项,2字节源IP地址. structarp_hdr的第九个成员structuip_eth_addrdhwaddr,对应图片中第十项,6字节目标以太网地址. structarp_hdr的第十个成员u16_tdipaddr[2];,对应图片中第十一项,2字节目标IP地址. 上面绿色的表示已经详解的,红字的表示要进一步说明的. 这就是一个ARP帧的结构,可以看到,里面的源和目的以太网地址都是重复的. 我们再看函数中的代码: 1.memset(BUF->ethhdr.dest.addr,0xff,6); 2.memset(BUF->dhwaddr.addr,0x00,6); 3.memcpy(BUF->ethhdr.src.addr,uip_ethaddr.addr,6); 4.memcpy(BUF->shwaddr.addr,uip_ethaddr.addr,6); 复制代码 这里四个memset,重复的源和目的以太网地址一起设置了,四个memset对应图片中的1,10,2,8项.但是: 对1和10两项,都是源以太网地址,但置的值是不同的,分别为0xff*6和0x00*6.为什么会这样呢? 因为他们的用处不一样,见: 【相关资料】ARP分组格式(帧格式,报文格式) 6+6–以太网的源地址和目的地址,目的地址为全1的为广播地址 注意这里说,目的地址为全为1的广播地址.什么意思? 当你发送一个ARP请求是,你是想知道一个IP对应的以太网地址(即MAC地址),但是你现在不知道目的主机的以太网地址,你问谁啊? 不知道问谁,这种情况下,只能是广播一下了,0xff*6就是广播地址. 从图片中可以看到,ARP包是分成两部分的,前6+6+2叫做"以太网首部",它的意义就是"分组是从谁(源地址)发给谁(目的地址)的什么类型(帧类型,请求和应答为0x0806)",第二部分则是内容. 来看这个例子: 请求帧如下(为了清晰在每行的前面加了字节计数,每行16个字节): 以太网首部(14字节) 0000: ffffffffffff00055d6158a80806 ARP帧(28字节) 0000: 0001 0010: 08000604000100055d6158a8c0a80037 0020: 000000000000c0a80002 填充位(18字节) 0020: 007731d25010 0030: fd7841d30000000000000000 以太网首部: 目的主机采用广播地址,源主机的MAC地址是00: 05: 5d: 61: 58: a8,上层协议类型0x0806表示ARP。 ARP帧: 硬件类型0x0001表示以太网, 协议类型0x0800表示IP协议, 硬件地址(MAC地址)长度为6, 协议地址(IP地址)长度为4, op为0x0001表示请求目的主机的MAC地址, 源主机MAC地址为00: 05: 5d: 61: 58: a8,源主机IP地址为c0a80037(192.168.0.55), 目的主机MAC地址全0待填写,目的主机IP地址为c0a80002(192.168.0.2)。 由于以太网规定最小数据长度为46字节,ARP帧长度只有28字节,因此有18字节填充位,填充位的内容没有定义,与具体实现相关。 上面是一个ARP请求,它由MAC地址为00: 05: 5d: 61: 58: a8,IP地址为c0a80037(192.168.0.55)的主机发出,将"以太网首部"的源太网地址设为自己的MAC地址,目的以太网址设为全1,即广播.将最后四项中的源以太网地址和IP地址分别设为自己的MAC地址和IP地址,将目的IP地址,设为自己想到查询的IP地址,将目的以太网地址设为全0. 应答帧如下: 以太网首部 0000: 00055d6158a800055da1b8400806 ARP帧 0000: 0001 0010: 08000604000200055da1b840c0a80002 0020: 00055d6158a8c0a80037 填充位 0020: 007731d25010 0030: fd7841d30000000000000000 以太网首部: 目的主机的MAC地址是00: 05: 5d: 61: 58: a8,源主机的MAC地址是00: 05: 5d: a1: b8: 40,上层协议类型0x0806表示ARP。 ARP帧: 硬件类型0x0001表示以太网, 协议类型0x0800表示IP协议 硬件地址(MAC地址)长度为6, 协议地址(IP地址)长度为4, op为0x0002表示应答, 源主机MAC地址为00: 05: 5d: a1: b8: 40,源主机IP地址为c0a80002(192.168.0.2), 目的主机MAC地址为00: 05: 5d: 61: 58: a8,目的主机IP地址为c0a80037(192.168.0.55)。 上面是一个针对前面的ARP请求的应答,应答者是MAC地址为00: 05: 5d: a1: b8: 40,IP地址为c0a80002(192.168.0.2)的主机. 它将应答中的源主机地址设为自己的MAC地址,目的主机地址设为发出请求的主机的MAC地址. 将最后四项中的源主机地址和IP地址设为自己的MAC地址和IP地址,目的主机地址和IP地址设为发出请求的主机的MAC地址和IP地址. 可见,一个ARP的请求的应答帧很多域的值都是固定的,只有: ∙以太网首部6+6(目的MAC,源MAC) ∙最后四项6+4+6+4(源MAC,源IP,目的MAC,目的IP) ∙opcode(1ARP请求,2ARP应答,3RARP请求,4RARP应答,必须字段) 需要按需填写.其中不知道的真全0,ARP请求的目的MAC在以太网首部为广播MAC,即全0. 按着看函数: 1.uip_ipaddr_copy(BUF->dipaddr,ipaddr); 2.uip_ipaddr_copy(BUF->sipaddr,uip_hostaddr); 3.BUF->opcode=HTONS(ARP_REQUEST);/*ARPrequest.*/ 4.BUF->hwtype=HTONS(ARP_HWTYPE_ETH); 5.BUF->protoco
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ARP 请求