In college, I have always wanted to write a local area network IP to view tools to query the IP address of a LAN for use. After more than a year, this network gadget has not had time to write. At that time, because the level was limited, it didn't have this time at the end of August, so I spent a week to do this, I finally finished. Some of them will write out and share it. This article is suitable for friends who have some programming based on TCP / IP protocols.
Non-technical articles (friends who care technology directly)
First, why do you want to write this thing?
When the third semester, the dormitory building campus network, everyone is extremely excited, but the problem is coming. In my dormitory, there are 6 floors, more than 400 computers (possibly there may be more), and only one Class C IP segment, 254 IP addresses, the gateway accounts for one, so IP compets is unavoidable . Everyone's distress comes from this, and the story begins.
The author has seen some online books, so I know some practices. The first way is to get up early to occupy an IP (turn off the light at night). Then the problem later is that you can change the IP settings, but you don't know those IPs that are not used by other machines. WINDOW2000 can dynamically, there is no need to restart, WinXP is stronger, and the repair can be recovered. Of course, you have to manually, sometimes you suddenly crazy in restarting, IP is no longer you! Haha, you are dizzy!
Of course, you can view this if the ping command is one, and there are some similar tools. The ping command is less reliable, a one of the ping, very wasting time, no timeliness. And the software such as Tianwang firewall can set up without responding. So this way does not pass, look at others to go online, set up an IP conflict, really depressed. If there is something that can be accurately viewed how good the LAN's IP usage! I was searching online for a long time, I found a program for viewing IP based on UDP protocols, and source code. The effect is much changed, it uses a separate thread to send, use Socket Accept, the shortcomings are that the Tianwang can mask it. At that time, I thought this problem, the only unchanged each machine is the physical address of the NIC, which is the MAC address. What mechanism is used to implement the IP address to the Mac map, this is the basic problem of communication! Because of the reasons for the network protocol, then see many kinds of information, including the English document of RFC, use the agent to find foreign countries, this document introduces a variety of standards, and various agreements. I know some knowledge of ARP (Address Resolution Protocol, address resolution protocol), and later introduce this protocol.
Not long, there is really such a small software. It is said that it is a VC master of this building. It is only necessary to enter a query, such as 202.4.151.1-202.4.151.254, which will quickly query the IP address. At that time, I couldn't see the source code and admired for a long time. One thing can be affirmed, it is using the ARP protocol and uses multiple threads. At that time, only some network protocols were known, and there were no WINSOCK procedures, and multi-threads were very weak. So can't write it, but I thought that there was an opportunity to write a similar gadget.
Second, the hand preparation
Time flies, then the examineers, do graduation design, work, and replace their work ... from the mechanical design back to software development. Overtime, study, study, overtime ... The days are really fast. Later, I finally took another rest. "Walk-in-Shallow MFC" "Windows Core Programming" "Windows Network Programming Technology" took a long time, gradually realizing something, multithreading is also familiar with a lot. In particular, a project involved UDP multi-point transmission. At that time, the Socket was deeply seen, debugging several sample programs, and familiar with this Socket model. I feel enough knowledge to write this thing. But I haven't thought about the specific ideas, so I went online search (there was more than the predecessor, not a repetitive thing), found a few articles about ARP, the following references are there in it of. At the same time, it also begins to contact the Row Socket, study the Sniffer (嗅). At that time, when I took it, when I didn't know how to handle the MAC address of the corresponding IP address, I can only return to the ARP protocol, and the upper protocol must be established on the basis of the next protocol! Row Socket Although the original, only Can go to the network layer, and the ARP protocol works in the link layer because it can only be a MAC address in the network cable or device, and it is not a physical layer. At this point, it is just watching the WinPCAP package help document, which has already packaged the operation of the device, which can directly send the link layer package. Use it to send all the upper bags, and the network protocol itself is finally transmitted, and finally the laminate package will be packaged. To put it bluntly, as long as you understand various bag formats, you can implement the features of the ISO / OSI's various protocol layers! OK, this thing can meet the requirements, Winpcap also knows a lot, you can do it.
Third, encoding
For use, please refer to the help documentation, Web format, no index (MSDN). There are not many content, and the knowledge is much. The author did not have a thorough study, the code involved, there is a more detailed note. First, refer to "Hand Teaching you to play the ARP package", the author provides detailed code, and it is also very detailed, so I don't spend much time. However, the author's project is written in VS2003, but not says from which Window version is passed, it is estimated that the Win2000 is converted to the VC6 project, but there is no mention of the ARP buffer enclosure on WinXP. This problem has been plagued for two days, and finally discovered the previously downloaded article "Talking about calling the WinPCAP Drive Write ARP Multifunction Tool" "There is a function of sending and receiving the ARP package. It is very close to me. The code is a console project that must be transformed into an MFC app. This is not very difficult. Simplely designed interface, some of the time is a matter of time. It took a week before and after a week without your own computer progress.
The above is an experience, and the implementation of the specific procedure is in the technical articles. Ok, technical articles! !
Speech is correct, book back to the topic!
Technical articles
An ARP Protocol Introduction
The principles are organized from "Teaching you to play ARP package"
working principle
Ethernet equipment such as NIC has its own world's unique MAC address, which is to transmit Ethernet data packets with a MAC address. They cannot identify IP addresses in the IP package. The actual network card will be submitted to the protocol stack. Buffer, become a link layer, and then separate the package of the IP layer, and then separate TCP or UDP .... Just like peeling bamboo shoots, the sending package is the opposite process.
We need an agreement to establish a corresponding relationship with the MAC address when performing IP communication in Ethernet, so that the IP packet can be sent to a certain place. This is the ARP (Address Resolution Protocol, address resolution protocol). Tell this, we can enter in the command line window.
ARP -A
Look at the effect, similar to such entries
210.118.45.100 00-0B
-5f
-E6-C5-D7 Dynamic
It is the correspondence of the IP address and the MAC address stored in our computer. The Dynamic represents an entry that is temporarily stored in the ARP cache. After a while, it will be deleted (different from different operating systems).
In this way, as our computer is in communication with a machine, such as 210.118.45.1, it will first check the ARP cache, find if there is a corresponding ARP entry, if not, it will send ARP request to this Ethernet Bao Guangxown inquiry 210.118.45.1 corresponds to the corresponding MAC address, of course, each computer will receive this request package, but they find 210.118.45.1 Notself, will not make the corresponding, and 210.118.45.1 will give us The computer replies an ARP answer package, tells us that its MAC address is XX-XX-XX-XX-XX-XX, so our computer's ARP cache will refresh it accordingly, more this:
210.118.45.1 XX-XX-XX-XX-XX-XX Dynamic
Why do you have such an ARP cache? Imagine if there is no cache, we have to send a broadcast query address every IP package, isn't it a waste of bandwidth and waste?
Our network devices cannot identify the authenticity of the ARP package, and it is also impossible to identify that basic agreed is fake and will bring disasters. If we send a packet according to the format of the ARP, as long as the information valid computer will respond according to the content in the package.
This is also the basis for the reliable communication of Ethernet, but if I can manipulate the network card device to send data and master the format, I can do some deception and mess. Of course, the author is only theoretical analysis, and does not advocate the reader to do.
ARP package format
An ARP package is divided into two parts, the front one is a physical frame head or Etherhead, and one is an ARP frame or ARP-FRAME.
First, the physical frame head will exist in front of any protocol packet, we call DLC Header because this frame head is constructed in the data link layer, and its main content is the physical address of both parties, so that Hardware device identification.
DLC Header
Field
BYTE
Defaults
Note
Receiver Mac
6
In broadcast, for FF-FF-FF-FF-FF-FF
Sender Mac
6
EtherType
2
0x0806
0x0806 is the type value of the ARP frame
Figure 1 Physical frame head format
Figure 1 shows the format of the physical frame header we need to fill, we can see that we need to fill the physical address of the sender and the receiving end, is it simple?
Let's take a look at the format of the ARP frame.
ARP FRAME
Field
BYTE
Defaults
Note
Hardware type
2
0x1
Ethernet type value
Upper layer protocol type
2
0x0800
The upper protocol is an IP protocol
MAC address length
1
0x6
Ethernet MAC address length is 6
IP address length
1
0x4
IP address length is 4
Operate code
2
0x1 represents the ARP request package, 0x2 indicates a response package
Sender Mac
6
Sender IP
4
Acceptor Mac
6
Acceptor IP
4
Data input
18
Because the minimum length of the physical frame is 64 bytes, the front 42 bytes plus 4 CRC check bytes, 18 bytes
We can see that we need to fill the same Mac, IP, plus one 1 or 2 opcode. Fill of ARP package
1) Request package fill:
For example, our computer MAC address is AA-AA-AA-AA-AA-AA, IP is 192.168.0.1
We want to query 192.168.0.99 MAC address, what should I do?
First fill the DLC header, learn from the previous learning, we want to know that a computer corresponding to the MAC address is to send broadcasts to the whole network, so the receiver MAC is definitely fffffffffffffff, the sender Mac is of course himself, so our DLC header is filling, as shown in the figure, bold is the value we want to manually entered (of course, the program I compare the program, will automatically fill in some fields according to the ARP package type you choose, you know ^ _ ^).
DLC Header
Field
BYTE
Fill
Receiver Mac
6
Ffffffffffffff
Sender Mac
6
Aaaaaaaaaaaaaaaaaa
EtherType
2
0x0806
Figure 3 ARP request package DLC Header content
Next is the ARP frame, the operand requested the package is of course 1. The sender's Mac and IP are of course filled in our own. Then pay attention to the receiver IP here, the IP address we have to query is 192.168.0.99, and the Turmy Mac fills in any value, it does not work, so, as shown,
ARP FRAME
Field
BYTE
Fill
Hardware type
2
1
Upper layer protocol type
2
0x0800
MAC address length
1
6
IP address length
1
4
Operate code
2
1
Sender Mac
6
Aaaaaaaaaaaaaaaaaa
Sender IP
4
192.168.0.1
Receiver Mac
6
Arbitrary value xxxxxxxxxxx
Receiver IP
4
192.168.0.99
Data input
18
0
Figure 4 Content of ARP frame in ARP request package
If we construct a such a package, if there is 192.168.0.99 and is active, we will immediately receive a 192.168.0.0.0.0.0.99 a response package, we can check our ARP cache list, isn't it A entry similar to this:
192.168.0.99 BB-BB-BB-BB-BB-BB
Is it very magical? Let's take a look at the constructor of the ARP response package:
Response package fill
With the detailed explanation of the previous, you will definitely say that the fill method of the bag is coming, so I will not say it, and the column is fine.
For example, send an ARP response package 192.168.0.99 (Mac to BB-BB-BB-BB-BB), telling it that our MAC address is AA-AA-AA-AA-AA-AA, which is like this to fill Various fields
DLC Header
Field
BYTE
Fill
Receiver Mac
6
Bbbbbbbbbbbbb
Sender Mac
6
Aaaaaaaaaaaaaaaaaa
EtherType
2
0x0806
Figure 5 ARP response package DLC Header content
ARP FRAME
Field
BYTE
Fill
Hardware type
2
1
Upper layer protocol type
2
0800
MAC address length
1
6
IP address length
1
4
Operate code
2
2
Sender Mac
6
Aaaaaaaaaaaaaaaaaa
Sender IP
4
192.168.0.1
Receiver Mac
6
Bbbbbbbbbbbbb
Receiver IP
4
192.168.0.99
Data input
18
0
Figure 6 Content of ARP frame in ARP response package
This will have more address mappings about our 192.168.0.1 in the ARP cache of 192.168.0.99. It's better to be programmed:
Second, the specific implementation of programming
By analyzing, the following is important, and then each function is closely packaged in a function.
1 NIC enumeration, setting and buffer allocation;
2 Fill and send an ARP package;
3 Listening Threading (SNIFFER);
4 parse the ARP package;
5 get the native IP MAC address;
6 Send a coordination of threads and accepting threads;
As for how to display IP and MAC information, please refer to the source code.
In order to more conveniently call the WinPCap library function, the author encapsulates a CWINPCAP class. Several key points of the code, please refer to the attached source code:
1 network card enumeration, setting and buffer allocation
// Success Return 0
INT CWINPCAP :: OpenPCAP ()
{
Wchar BUF [1024];
Ulong buffs;
Int res, i = 0;
Memset (void *) Adapterlist, 0, sizeof (adapterlist);
Res = packetgetadapternames ((char *) BUF, & bufsize); // enumerate NIC
IF (res == 0)
{
Return -1;
}
Wchar * p1, * p2;
P1 = P2 = BUF;
While (* p1! = '/ 0') || (* (p1 - 1)! = '/ 0'))
{
IF (* p1 == '/ 0')
{
Memcpy (AdapterList [i], p2, 2 * (p1 - p2));
P2 = p1 1;
i ;
}
P1 ;
}
m_iadapternum = i;
m_iseladapter = i - 1;
// Open the last network card, the PC is generally a network card
m_lpadapter = packetopenadapter ((char *) AdapterList m_iseLadapter * 1024)));
IF (m_lpadapter == null || (m_lpadapter-> hfile == invalid_handle_value))
{
Return -1;
}
// Assign Sender package space
M_LPCKETSENDER = packetallocatepacket ();
IF (M_LPPACKETSENDER == NULL)
Return -1;
Return 0;
}
2 How to fill and send an ARP package
The first is the packet format definition of the package
// Ether (DLC) HEADER
Typedef struct ethdr
{
Unsigned char eh_dst [6]; // Ethernet's MAC address
Unsigned char eh_src [6]; // Ethernet source MAC address
UNSIGNED SHORT EH_TYPE; // Frame Type
} Ethdr, * pethdr;
// ARP packet format
Typedef struct arphdr
{
Unsigned short arp_hdr; // hardware type
UNSIGNED SHORT ARP_PRO; / / Protocol Type
Unsigned char arp_hln; / / hardware address length
Unsigned char ARP_PLN; // Protocol Address Length Unsigned Short ARP_OPT; // ARP / RARP
Unsigned char arp_sha [6]; // sender address
Unsigned long arp_spa; // sender IP address
Unsigned char arp_tha [6]; // recipient address
Unsigned long ARP_TPA; // Receiver IP Address
Arphdr, * PARPHDR;
Next, it is filled and sent an ARP request package.
/ ************************************************** *******************
Function for sending thread calls, send an ARP request package
parameter
IPCur target IP address
IPMine native IP address
Mac [] NIC MAC address
*********************************************************** ****************** /
INT CWINPCAP :: Sender (Ulong IPCur, Ulong IPMine, Byte Mac "
{
Char pbufsend [1024];
Ethdr eth;
Arphdr ARP;
// Fill The ARP Request Packets.
INT I;
FOR (i = 0; i <6; i )
{
Eth.eH_DST [I] = 0xFF;
ARP.ARP_THA [I] = 0x00;
}
// {Pack DLC head and ARP header
Eth.e_type = HTONS (Eth_arp);
Memcpy (eth.e_src, mac, 6);
Arp.arp_hdr = htons (arp_hardware);
Arp.arp_pro = htons (eth_ip);
Arp.arp_hln = 6;
Arp.arp_pln = 4;
Arp.arp_opt = htons (arp_request);
Memcpy (arp.arp_sha, mac, 6);
Arp.arp_spa = HTONL (IPMINE);
Arp.arp_tpa = HTONL (IPCur);
//}
MEMSET (Pbufsend, 0, SizeOf (Pbufsend);
Memcpy (Pbufsend, ð, SIZEOF (ETH));
/ / Assembly full ARP package
Memcpy (Pbufsend SizeOf (Eth), & ARP, SIZEOF (ARP));
PacketinitPacket (M_LPPACKETSENDER, PBUFSEND, SIZEOF (Eth) SizeOf (ARP));
IF (packetsendpacket (m_lpadapter, m_lpppacketsender, true) == false)
{
Return -1;
}
Return 0;
}
3 Listening Threading (SNIFFER);
A function actually implemented by thread correspondence:
Int cwinpcap :: sniff ()
{
Static CiPfluxdlg * PDLG = (CIPFLUXDLG *) AFXGETMAINWND ();
Char recvbuf [1024 * 250];
DWORD RES = 0;
// {Initialization Net Card, set to mix mode NDIS_PACKET_TYPE_PROMISCUOSCUOS
IF (PacketSethWFilter (m_lpadapter, ndis_packet_type_promiscuous) == false) {
// Printf ("Warning: Unable to set the adapter to promiscuous mode / n");
}
IF (PacketSetBuff (M_Lpadapter, 500 * 1024) == false)
{
// Printf ("PacketSetBuff Error:% D / N", getLastError ());
Return -1;
}
IF (PacketsetReadTimeout (M_LPadapter, 1) == FALSE)
{
// Printf ("Warning: Unable to set the timeout / n");
}
IF ((M_LPPACKETRECEIVER = PacketAllocatePacket ()) == false)
{
// Printf ("PacketAllocatePacket Receive Error:% D / N", getLastError ());
Return -1;
}
PacketinitPacket (M_LPPACKETRECEIVER, (CHAR *) Recvbuf, Sizeof (Recvbuf));
//}
// {accept package
DO
{
IF (PacketReceivePacket (M_LPADAPTER, M_LPPACKETRECEIVER, TRUE) == false)
{
IF (getLastError () == 6)
Return 0;
Return -1;
}
GetData (m_lppacketReceiver; // Analysis of the package
IF (PDLG-> m_bstop == true)
Break;
WHILE (1);
//}
ResetEvent (PDLG-> M_HEVENT); // Auxiliary function
Return 0;
}
4 parsing the ARP response package
/ ************************************************** *******************
Features to extract and resolve the ARP package from the received package
parameter
Buffer pointer of the package accepted by the LP network card
*********************************************************** ****************** /
Void CWINPCAP :: getData (LPPACKET LP)
{
Ulong uloffset = 0, ulbytessrecept;
Char * buf = NULL;
Char * pchar, * PBASE
Struct bpf_hdr * phdr = null;
Struct SockAddr_in sin;
Ethdr * Pether;
Arphdr * Parp;
// iphdr * piphdr;
CSTRING STRIP, STRMAC;
Static CiPfluxdlg * PDLG = (CIPFLUXDLG *) AFXGETMAINWND ();
BUF = (char *) lp-> buffer;
UlbytesReceived = lp-> ulbytesreceived;
While (uloffset { PHDR = (Struct BPF_HDR *) (BUF ULOFFSET); ULOFFSET = phDr-> bh_hdrlen; PCHAR = (char *) (BUF ULOFFSET); PBASE = PCHAR; ULOFFSET = packet_wordalign (uloffset phdr-> bh_caplen); PETHER = (Pthdr) PCHAR; Parp = (ParphDR) (Pchar SizeOf (Ethdr)); // Receive ARP Reply Packets Which Contain IP Address and Relative Mac Address // is affected by the ARP response package, contains IP addresses and related MAC addresses IF (Pether-> EH_TYPE == Htons (Eth_arp) && Parp-> ARP_OPT == Htons (ARP_REPLY)) { Sin.sin_addr.s_addr = parp-> arp_spa; Strip.format ("% - 16s", inet_ntoa (sin.sin_addr); CString Str; Str.Format ("% 02x", Pether-> EH_SRC [0]); STRMAC = STR; For (INT I = 1; i <6; i ) { Str.Format ("-% 02x", Pether-> EH_SRC [I]); STRMAC = STR; } PDLG-> ShowSearch (Strip, STRMAC); SetEvent (pdlg-> m_hevent); } } } 5 get the native IP address and MAC address WinPCAP functions are not taken in the project to obtain MAC addresses, but use very useful IPHELP library functions DWORD WinAPI GetAdaptersInfo (Pip_Adapter_Info PadapterInfo, Pulong Poutbufflen); / ************************************************** ********************** Function to get the IP address of this unit, physical address, involved parameter SIN IP address STRMAC MAC Address 16 Mac [] MAC address byte expression *********************************************************** ********************* / Void cwinpcap :: getNetInfo (SockAddr_in & sin, cstring & struct, byte mac " { PIP_ADAPTER_INFO PADAPTERINFO = NULL; CHAR CH; Long sizeInfo; Ulong size = 0; INT RES = 0; SIZEINFO = SizeOf (M_NetInfo); IF (m_lpadapter) { // get an IP address first Res = PacketgetNetinfoEx (AdapterList [m_iseladapter], & m_netinfo, & sizeinfo; IF (RES) { SIN = * (Struct SockAddr_in *) & m_netinfo.ipaddress; } Else { STRMAC = "FF-FF-FF-FF-FF-FF"; } // Try to get AdapterInfo, Size returns the size of the required buffer res = getadaptersInfo ((pip_adapter_info) & ch, & size); IF (res == error_buffer_overflow) { PadapterInfo = (pip_adapter_info) malloc (sizeof (ip_adapter_info); Res = GetAdaptersInfo (PadapterInfo, & size); IF (res == 0) { CString Str; BYTE * PCH = PadapterInfo-> address; // Export MAC address 16-based expression Memcpy (Mac, PCH, 6); For (int i = 0; i <6; i ) { IF (i) STRMAC = "-"; Str.Format ("% 02x", * (PCH I)); STRMAC = STR; } } Free (PadapterInfo); } } } 6 Send a coordination of threads and accepting threads Just a simple multiple send threads, a listening thread. There is no synchronous problem. Void Cipfluxdlg :: OnbtnStart () { INT NTOTAL = 0; Ulong ipfirst, IPLAST; Ulong ulstartip = 0; m_bstop = false; Static bool binit = false; m_ipfirst.getaddress (ipfirst); m_iplast.getaddress (IPLAST); NTOTAL = IPLAST - IPFirst 1; m_lstip.deleteallItems (); Getdlgitem (IDC_BTN_START) -> EnableWindow (FALSE); / / Generate a listening thread IF (binit == false) { M_Hsniffer = AFXBEGINTHREAD (_TFuncReceiver, (void *) this); Binit = True; } SLEEP (300); m_ipfirst.getaddress (Ulstartip); For (int i = 0; i { m_ipcur = ulstartip i; M_Hsender = AFXBEGINTHREAD (_TFunc Shender, (void *); // Waiting for the last thread to end WaitForsingleObject (m_hsender, infinite); } m_bstop = true; Getdlgitem (IDC_BTN_START) -> EnableWindow (TRUE); } Fourth, summary The above code is clear, the code annotation is more detailed, the list of the columns has been 60%, the project is not big. Readers with high programming can even make similar procedures quickly! Of course, there are still some shortcomings such as: I can't ask for a request ARP package and immediately resolve it, and then send the next one, but it is similar to all sent it. Instead, Release mode has unforeseen abnormalities, and multi-threaded exception processing needs to be in-depth. WinXP / VC6.0 is compiled through, WinXP and Win2000 are running normally. Additional information: ARP Principle Description The part of "Hand-handed you to play ARP package" is for reading, this article is different from the other two articles, and readers can compare themselves. Welcome to ARP Welcome to readers to discuss. Regarding how WinPCAP is used, and the problem of compiling is no longer discussed. Please take a closer look at the WinPCAP development package help, the two articles referenced. postscript: From the protocol principle to the code implementation, from Row Socket to WinPCAP ... As long as you understand the rules you can write some similar utilities. I hope the reader can gain something! Reference article, information: "Hand teaches you to play ARP package" http://blog.9cbs.net/piggyXP/- PiggyXP- 5/31/2004 11:40:00 AM Series Articles "TCP-IP Details 1: Agreement ARP chapter, volume 2: 021.pdf" "Talk about calling WinPCAP Drive Write ARP Multi-Delivery Tool" { Author: Too2y [original] E-mail: Too2y@safechina.net Homepage: http://www.safechina.net/ Date: 11-9-2002 }