1、使用ARP协议获取局域网内部活动主机物理地址的程序实现C+广工计算机网络课程设计课 程 设 计 课程名称 计算机网络 _题目名称_学生学院_计算机学院_专业班级_ 学 号 学生姓名 指导教师_ _ _ _ _2013 年 1 月 11 日计算机网络课程设计一、设计题目使用ARP协议获取局域网内部活动主机物理地址的程序实现(C+)二、已知技术参数和设计要求1.已知参数:选择适当的网络适配器,以绑定Winpcap。2.设计要求: 2.1协议实现需要哪些数据帧?注意要数据帧的定义要符合公共标准。2.2如何实现实现数据帧的发送?2.3如何接收及解析目的主机的响应数据帧?2.4如何显示ARP协议的执行结
2、果?3. C+环境为Visual C+三、设计内容与步骤1.熟悉ARP协议的工作原理;2.熟悉ARP协议相关数据帧结构;3.构造ARP请求数据帧;4.使用Winpcap相关函数实现数据帧的发送;5.接收及解析目的主机的响应数据帧;6.获得IP地址与MAC地址的对应关系并显示;7.课程设计任务说明书。四、课程设计中涉及的网络基本理论简介:(1) 在网际协议中定义的是因特网的IP地址,但在实际进行通信时,物理层不能识别IP地址只能识别物理地址。因此,需在IP地址与物理地址之间建立映射关系,地址之间的这种映射称为地址解析。(2) 以太网网络中的物理地址即网卡的序列号。IEEE规定网卡序列号为6个字节
3、(48位),前三个字节为厂商代号,由于厂商向IEEE注册登记申请,后3个字节为网卡的流水号。(3) 地址解析包括从IP地址到物理地址的映射和从物理地址到IP地址的映射。TCP/IP协议组提供了两个映射协议:地址解析协议ARP和逆向地址解析协议RARP。ARP用于从IP地址到物理地址的映射,RARP用于从物理地址到IP地址的映射。(4) 地址解析协议的ARP的工作原理:假定在一个物理网络上,A(源主机)要与D(目的主机)进行通信,但是不知道D的物理地址。 A利用ARP协议工作的过程如下: A广播一个ARP请求报文,请求IP地址为IPD的主机回答其物理地址。网上所有主机都能收到该ARP请求,并将本
4、机IP地址与请求的IP地址比较,D主机识别出自己的地址IPD,并作出回应,通报自己的物理地址。A收到这个ARP回应包后,就可以与D进行通信。为了提高效率,ARP协议使用了高速缓存技术。在每台使用ARP的主机中,都保留了一个专用的内存区,一收到ARP应答,主机就将获得的IP地址和物理地址存入缓存。以后每次要发送报文时,首先到缓存中查找有无相应的项,若找不到,再利用ARP进行地址解析。由于多数网络通信都要连续发送多个报文,所以高速缓存大大提高ARP的效率。在ARP请求报文中还放入源主机的“IP地址物理地址”的地址对,源主机在广播ARP请求时,网络上所有主机都可以知道该源主机的“IP地址物理地址”的
5、地址对并将其存入自己的缓存。在新主机入网时,令其主动广播其地址映射,以减少其他主机进行ARP请求。(5) 网卡具有如下的几种工作模式:广播模式(Broad Cast Model):它的物理地址(目的地址)地址是 0Xfff fff 的帧为广播帧,工作在广播模式的网卡接收广播帧。多播传送(MultiCast Model):多播传送地址作为目的物理地址的帧可以被组内的其它主机同时接收,而组外主机却接收不到。但是,如果将网 卡设置为多播传送模式,它可以接收所有的多播传送帧,而不论它是不是组内成员。直接模式(Direct Model):工作在直接模式下的网卡只接收目地址是自己 Mac地址的帧。混杂模式
6、(Promiscuous Model):工作在混杂模式下的网卡接收所有的流过网卡的帧,信包捕获程序就是在这种模式下运行的。(6) ARP帧的数据结构表达方式: 以太网帧头中的前两个字段是以太网的目的地址和源地址。目的地址为全1时为广播地址。 两个字节长的以太网帧类型表示后面数据的类型。对于ARP请求或应答来说,该字段的值为0X0806. 硬件类型字段:指明了发送方想知道的硬件地址的类型,以太网的值为1; 应该是接收方;什么硬件,这和以太网有关系吗 协议类型字段:表示要映射的协议地址类型,IP为0X0800; 硬件地址长度和协议地址长度:指明了硬件地址和高层协议地址的长度,这样ARP帧就可以在任
7、意硬件和任意协议的网络中使用。对于以太网上IP地址的ARP请求或应答来说,它们的值分别为6和4;操作字段:用来表示这个报文的类型,ARP请求为1,ARP响应为2,RARP请求为3,RARP响应为4;发送端的以太网地址:源主机硬件地址,6个字节;发送端IP地址:发送端的协议地址(IP地址),4个字节;目的以太网地址:目的端硬件地址,6个字节;目的IP地址:目的端的协议地址(IP地址),4个字节六、运行结果:打开页面:选择网卡1:获取到的结果:七、代码分析:#include #include #include pcap.h#include Packet32.h#pragma pack(1) /按一
8、个字节内存对齐#define IPTOSBUFFERS 12#define ETH_ARP 0x0806 /以太网帧类型表示后面数据的类型,对于ARP请求或应答来说,该字段的值为x0806#define ARP_HARDWARE 1 /硬件类型字段值为表示以太网地址#define ETH_IP 0x0800 /协议类型字段表示要映射的协议地址类型值为x0800表示IP地址#define ARP_REQUEST 1#define ARP_REPLY 2#define HOSTNUM 255/* packet handler 函数原型*/void packet_handler(u_char *pa
9、ram, const struct pcap_pkthdr *header, const u_char *pkt_data);/ 函数原型void ifget(pcap_if_t *d,char *ip_addr,char *ip_netmask);char *iptos(u_long in);char* ip6tos(struct sockaddr *sockaddr, char *address, int addrlen);int SendArp(pcap_t *adhandle,char *ip,unsigned char *mac);int GetSelfMac(pcap_t *adh
10、andle,const char *ip_addr,unsigned char *ip_mac);DWORD WINAPI SendArpPacket(LPVOID lpParameter);DWORD WINAPI GetLivePC(LPVOID lpParameter);/28字节ARP帧结构struct arp_head unsigned short hardware_type; /硬件类型 unsigned short protocol_type; /协议类型 unsigned char hardware_add_len; /硬件地址长度 unsigned char protocol
11、_add_len; /协议地址长度 unsigned short operation_field; /操作字段 unsigned char source_mac_add6; /源mac地址 unsigned long source_ip_add; /源ip地址 unsigned char dest_mac_add6; /目的mac地址 unsigned long dest_ip_add; /目的ip地址;/14字节以太网帧结构struct ethernet_head unsigned char dest_mac_add6; /目的mac地址 unsigned char source_mac_a
12、dd6; /源mac地址 unsigned short type; /帧类型;/arp最终包结构struct arp_packet struct ethernet_head ed; struct arp_head ah;struct sparam pcap_t *adhandle; char *ip; unsigned char *mac; char *netmask;struct gparam pcap_t *adhandle;bool flag;struct sparam sp;struct gparam gp;int main() pcap_if_t *alldevs; pcap_if_
13、t *d; int inum; int i=0; pcap_t *adhandle; char errbufPCAP_ERRBUF_SIZE; char *ip_addr; char *ip_netmask; unsigned char *ip_mac; HANDLE sendthread; HANDLE recvthread; ip_addr=(char *)malloc(sizeof(char)*16);/申请内存存放IP地址 if(ip_addr=NULL) printf(申请内存存放IP地址失败!n); return -1; ip_netmask=(char *)malloc(size
14、of(char)*16);/申请内存存放NETMASK地址 if(ip_netmask=NULL) printf(申请内存存放NETMASK地址失败!n); return -1; ip_mac=(unsigned char *)malloc(sizeof(unsigned char)*6);/申请内存存放MAC地址 if(ip_mac=NULL) printf(申请内存存放MAC地址失败!n); return -1; /* 获取本机设备列表*/ if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) = -1) f
15、printf(stderr,Error in pcap_findalldevs: %sn, errbuf); exit(1); /* 打印列表*/ printf(本机网卡列表:n); for(d=alldevs; d; d=d-next) printf(%d) %sn, +i, d-name); if (d-description) printf( (%s)n, d-description); else printf( (No description available)n); if(i=0) printf(n找不到网卡!请确认是否已安装WinPcap.n); return -1; print
16、f(n); printf(请选择要打开的网卡号(1-%d):,i); scanf(%d, &inum); if(inum i) printf(n该网卡号超过现有网卡数!请按任意键退出n); getchar(); getchar(); /* 释放设备列表*/ pcap_freealldevs(alldevs); return -1; /* 跳转到选中的适配器*/ for(d=alldevs, i=0; inext, i+); /* 打开设备*/ if ( (adhandle= pcap_open(d-name, / 设备名 65536, / 65535保证能捕获到不同数据链路层上的每个数据包的全
17、部内容 PCAP_OPENFLAG_PROMISCUOUS, / 混杂模式 1000, / 读取超时时间 NULL, / 远程机器验证 errbuf / 错误缓冲池 ) ) = NULL) fprintf(stderr,n无法读取该适配器. 适配器%s 不被WinPcap支持n, d-name); /* 释放设备列表*/ pcap_freealldevs(alldevs); return -1; ifget(d,ip_addr,ip_netmask);/获取所选网卡的基本信息-掩码-IP地址 GetSelfMac(adhandle,ip_addr,ip_mac);/输入网卡设备句柄网卡设备ip
18、地址获取该设备的MAC地址 sp.adhandle=adhandle; sp.ip=ip_addr; sp.mac=ip_mac; mask=ip_netmask; gp.adhandle=adhandle; sendthread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)SendArpPacket,&sp,0,NULL); recvthread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)GetLivePC,&gp,0,NULL); printf(nlistening on 网卡%d .n,inum);
19、 /* 释放设备列表*/ pcap_freealldevs(alldevs); getchar(); getchar(); return 0;/* 获取可用信息*/void ifget(pcap_if_t *d,char *ip_addr,char *ip_netmask) pcap_addr_t *a; char ip6str128; /* IP addresses */ for(a=d-addresses;a;a=a-next) switch(a-addr-sa_family) case AF_INET: if (a-addr) char *ipstr; ipstr=iptos(struc
20、t sockaddr_in *)a-addr)-sin_addr.s_addr);/*ip_addr memcpy(ip_addr,ipstr,16); if (a-netmask) char *netmaskstr; netmaskstr=iptos(struct sockaddr_in *)a-netmask)-sin_addr.s_addr); memcpy(ip_netmask,netmaskstr,16); case AF_INET6: break; /* 将数字类型的IP地址转换成字符串类型的*/char *iptos(u_long in) static char outputIP
21、TOSBUFFERS3*4+3+1; static short which; u_char *p; p = (u_char *)∈ which = (which + 1 = IPTOSBUFFERS ? 0 : which + 1); sprintf(outputwhich, %d.%d.%d.%d, p0, p1, p2, p3); return outputwhich;char* ip6tos(struct sockaddr *sockaddr, char *address, int addrlen) socklen_t sockaddrlen;#ifdef WIN32 sockad
22、drlen = sizeof(struct sockaddr_in6);#else sockaddrlen = sizeof(struct sockaddr_storage);#endif if(getnameinfo(sockaddr, sockaddrlen, address, addrlen, NULL, 0, NI_NUMERICHOST) != 0) address = NULL; return address;/* 获取自己主机的MAC地址 */int GetSelfMac(pcap_t *adhandle,const char *ip_addr,unsigned char *ip
23、_mac) unsigned char sendbuf42;/arp包结构大小 int i = -1; int res; struct ethernet_head eh; struct arp_head ah; struct pcap_pkthdr * pkt_header; const u_char * pkt_data; memset(eh.dest_mac_add,0xff,6);/目的地址为全为广播地址 memset(eh.source_mac_add,0x0f,6); memset(ah.source_mac_add,0x0f,6); memset(ah.dest_mac_add,0
24、x00,6); eh.type = htons(ETH_ARP); ah.hardware_type = htons(ARP_HARDWARE); ah.protocol_type = htons(ETH_IP); ah.hardware_add_len = 6; ah.protocol_add_len = 4; ah.source_ip_add = inet_addr(100.100.100.100); /随便设的请求方ip ah.operation_field = htons(ARP_REQUEST); ah.dest_ip_add=inet_addr(ip_addr); memset(s
25、endbuf,0,sizeof(sendbuf); memcpy(sendbuf,&eh,sizeof(eh); memcpy(sendbuf+sizeof(eh),&ah,sizeof(ah); if(pcap_sendpacket(adhandle,sendbuf,42)=0) printf(nPacketSend succeedn); else printf(PacketSendPacket in getmine Error: %dn,GetLastError(); return 0; while(res = pcap_next_ex(adhandle,&pkt_header,&pkt_
26、data) = 0) if(*(unsigned short *)(pkt_data+12) = htons(ETH_ARP)& *(unsigned short*)(pkt_data+20) = htons(ARP_REPLY)& *(unsigned long*)(pkt_data+38) = inet_addr(100.100.100.100) for(i=0; iadhandle; char *ip=spara-ip; unsigned char *mac=spara-mac; char *netmask=spara-netmask; printf(ip_mac:%02x-%02x-%
27、02x-%02x-%02x-%02xn,mac0,mac1,mac2,mac3,mac4,mac5); printf(自身的IP地址为:%sn,ip); printf(地址掩码NETMASK为:%sn,netmask); printf(n); unsigned char sendbuf42;/arp包结构大小 struct ethernet_head eh; struct arp_head ah; memset(eh.dest_mac_add,0xff,6);/目的地址为全为广播地址 memcpy(eh.source_mac_add,mac,6); memcpy(ah.source_mac_a
28、dd,mac,6); memset(ah.dest_mac_add,0x00,6); eh.type = htons(ETH_ARP); ah.hardware_type = htons(ARP_HARDWARE); ah.protocol_type = htons(ETH_IP); ah.hardware_add_len = 6; ah.protocol_add_len = 4; ah.source_ip_add = inet_addr(ip); /请求方的IP地址为自身的IP地址 ah.operation_field = htons(ARP_REQUEST); /向局域网内广播发送arp包 unsigned long myip=inet_addr(ip); unsigned long mynetmask=inet_addr(netmask); unsigned long hisip=h
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1