logo资料库

APR协议与局域网主机存活查询.doc

第1页 / 共5页
第2页 / 共5页
第3页 / 共5页
第4页 / 共5页
第5页 / 共5页
资料共5页,全文预览结束
ARP 协议与局域网主机存活查询
ARP 协议与局域网主机存活查询 ARP 是 Ethernet Address Resolution Protocol 的缩写,翻译为地址解析协议,这个协议, 在平时的编程中很少用到,尤其在编写普通的通信程序。但是这个协议,确实非常重要。它的主 要功能是提供 IP 地址到以太网地址的映射关系。我们知道,在以太局域网通信中,主要有两种 网络环境,一种是共享型,一种是交换型。但这两种通信方式,都是需要预先知道目标主机的 MAC 地址,也就是其以太网的物理地址,才能发送数据。只不过,共享型网络中的主机,通过 识别收到数据桢中 MAC 地址,来判断是不是自己的数据。而交换型的网络,虽然也有这个过程, 只不过有交换机事先进行了判断。 IP 地址的设计是为了广域网,也就是更大范围的网络,不受地域和时间的限制。而 MAC 地 址是为小范围网络设计的,收到地域的限制。IP 地址是 32 位,而 MAC 地址是 48 位的。从 IP 地址到 MAC 地址通过 ARP 协议来转换,从 MAC 地址到 IP 地址的转换是通过 RARP(逆向地址 解析协议)协议来进行的。RFC 826 是 ARP 规范的描述文档。感兴趣的可以去下载看看。 | | | ARP 分组的格式如下: +-------------------------------------------------+ | 以太网目的地址 (6 个字节) | +-------------------------------------------------+ | 以太网源地址 (6 个字节) | +-------------------------------------------------+ | 桢类型 (2 个字节) +-------------------------------------------------+ | 硬件类型 (2 个字节) +-------------------------------------------------+ | 协议类型 (2 个字节) +-------------------------------------------------+ | 硬件地址长度 (1 个字节) | +-------------------------------------------------+ | 协议地址长度 (1 个字节) | +-------------------------------------------------+ | op (2 个字节) +-------------------------------------------------+ | 发送端以太网地址 (6 个字节) | +-------------------------------------------------+ | 发送端的 IP 地址 (4 个字节) | +-------------------------------------------------+ | 目的以太网地址 (6 个字节) | +-------------------------------------------------+ | 目的 IP 地址 (4 个字节) | +-------------------------------------------------+ | 分组格式中,需要说明的是,以太网桢头中的目的地址为全是 1 的特殊地址,这是一个广播 地址,目的是为了所有以太网口都能收到该数据桢。也就是说 ARP 分组数据是一个广播包。 桢类型字段是固定值,为 0x0806。硬件类型表示硬件地址的类型,它的值为 1 表示以太网 地址。协议类型表示要映射的协议的地址类型,它的值 0x0800 表示 IP 地址。接下来两字定义
域,都是一个字节,分别表示两种协议地址的长度,因此可知,应该分别为 6 和 4。 op 字段为操作类型字段,用来表示这个数据包的操作类型。一个有四种类型,分别是 ARP 请 求包是 1,ARP 应答包是 2,RARP 请求包是 3,RARP 应答包是 4。因为 ARP 应答和请求的 分组格式是相同的,为了区分是应答还是请求,这个字段必须正确设置。 在 Window 环境下,用下面函数来实现这个功能。分别是: DWORD WINAPI SendARP( IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, PULONG PhyAddrLen ); 因为在以太网上的主机要想能够与其他主机通信,必须支持 ARP 协议,也就是说必须对 ARP 请求进行响应。因此,可以通过,这种手段来发现局域网中哪些 IP 地址已经被用了。下面就是 代码: // // Link with ws2_32.lib and iphlpapi.lib // #include #include #include #include #include "iphlpapi.h" #pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "IPHlpApi.Lib") #pragma comment(lib, "netapi32.Lib") BOOL GetArp(char *ip_name,char *mac_name); unsigned long GetLocalIP(char *ip_name); //------------------------------------------------------------ // // Main // // Do it all. // //------------------------------------------------------------
int main(int argc,char **argv) { WORD wVersionRequested; WSADATA wsaData; int err; unsigned long hostip = 0; struct in_addr ip; char mac[20]; char hostname[256]; // // Print banner // printf("\n\tSendArp v1.0 - scan IP and MAC\n"); printf("\tNsfocus - www.nsfocus.com\n"); printf("\tby David Zhou\n"); printf("\tDate : 2005/11/25\n\n"); wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return -1; } if(argc == 1) { hostip = GetLocalIP(NULL); ip.S_un.S_addr = hostip; printf("local ip: %s\n\n",inet_ntoa(ip)); for(int n=1;n<255;n++) { hostip &= 0x00FFFFFF; hostip |= (n<<24); ip.S_un.S_addr = hostip; memset(mac,0,20); if(NetbiosInfo(inet_ntoa(ip),hostname)) printf("%s == ",hostname); if(GetArp(inet_ntoa(ip),mac)) { printf("%s == > %s\n",inet_ntoa(ip),mac);
} else { printf("%s == > No Active\n",inet_ntoa(ip)); } } return 1; } // // // if(argc == 2) { //GetArp("192.168.5.212"); } else if(argc == 3) { } else { } return 0; } BOOL GetArp(char *ip_name,char *mac_name) { ipAddr; HRESULT hr; IPAddr ULONG pulMac[2]; ULONG ulLen; ipAddr = inet_addr (ip_name); memset (pulMac, 0xff, sizeof (pulMac)); ulLen = 6; hr = SendARP (ipAddr, 0, pulMac, &ulLen); if(ulLen <6) { //printf("No Active\n"); return FALSE;
} size_t i, j; char * szMac = new char[ulLen*3]; PBYTE pbHexMac = (PBYTE) pulMac; // // Convert the binary MAC address into human-readable // for (i = 0, j = 0; i < ulLen - 1; ++i) { } j += sprintf (szMac + j, "%02X:", pbHexMac[i]); sprintf (szMac + j, "%02X", pbHexMac[i]); sprintf(mac_name,"%s",szMac); delete [] szMac; return TRUE; } unsigned long GetLocalIP(char *ip_name) { BYTE *p; char temp[100]; struct hostent *hp; char ip[16]; if(gethostname(temp, sizeof(temp)) == 0) { if((hp =gethostbyname(temp))!=0) { p =(BYTE *)hp->h_addr; wsprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); } } else { return 0l; } return ((p[3]<<24)|(p[2]<<16)|(p[1]<<8)|p[0]); }
分享到:
收藏