WinPcap programming (2), winpcap Programming
0.
The two methods of packet capture are described in detail this time.
(Recommended) Clear the ARP table. It is best to write a batch processing command by yourself. Faster.
1.0 packet capture procedure
The procedure is simple: first open the adapter list --> select an adapter --> go to the selected adapter location through a traversal table --> open a device --> Start packet capture.
Every step is a function. The steps are easy to follow.
First, understand a data type pcap/pcap_t. It represents an open device. It can be understood as an adapter (actually a descriptor of this adapter ). This struct is not transparent to users. It maintains its content through the functions provided by wpcap. dll.
Next, jump to your device that exists in WinPcap programming (1.
Then, open the function of the device:
Pcap_t * pcap_open (const char * source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth * auth, char * errbuf)View Code
Note:
The first parameter: source is the device we want to open. After we get all the devices, the source is d-> name. Cannot be NULL.
The second parameter: snaplen is the size of the captured data packet. 100 is the first 100B of the captured data packet, and 65536 is the largest. The entire packet is included.
Third Parameter: Flags is set to the hybrid mode (PCAP_OPENFLAG_PROMISCUOUS), that is, whether or not the packet is sent to me, I will capture it. In this way, all packets in the LAN can be captured.
Fourth parameter: read_timeout: Set the timeout time in milliseconds (1 s = 1000 ms ). When reading data on the adapter, no matter whether there are packets on the network, it will respond within read_timeout.
Setting 0 means no timeout. If no data packet arrives, the read operation will never return.
If it is set to-1, the read operation will return immediately no matter whether data packets arrive.
Fifth parameter: auth remote login information. If it is local, It is NULL;
Sixth parameter: error message of errbuf.
1.1 two packet capture methods:
1.1.1 use the callback function to capture packets
The callback function is used to process each captured package. Capture packets after processing (if num is set ).
Packet capture function:
Int pcap_loop (pcap_t * p, int cnt, pcap_handler callback, u_char * user)View Code
Note 0:
The first parameter: P is the enabled device.
The second parameter: cnt indicates the number of captures.
Third parameter: callback function pointer. Perform operations on captured data packets.
Fourth parameter: user information, generally NULL.
Function return value:
The returned value is 0, and cnt is captured.
The returned value is-1, and an error occurs.
The returned value is-2. Use pcap_breakloop () to end the loop.
Another method to capture packets using the callback function is pcap_dispatch ().
The difference is: pcap _ dispatch () returns (although not guaranteed) when the time-out time reaches (timeout expires), while pcap_loop () does not return the result only when the cnt packet is captured.
Therefore, pcap_loop () will block the use of the network in a short period of time. The pcap_dispatch () function is generally used in complex programs.
1.1.2 do not use callback Functions
Callback functions are good, but sometimes callback functions are not required, especially in multithreading.
I wrote it in C # + WPF. If I use a callback function, errors always occur. It should be a matter of hosting and non-hosting. After reading the source code of SharpPcap, it seems that there is no good solution.
[If you have a good solution, I hope you can provide it. Thank you .]
If you do not use the callback function to capture packets, the method is relatively simple. You can only capture one packet at a time and add a while () loop.
Int pcap_next_ex (pcap_t * p, struct pcap_pkthdr ** pkt_header, const u_char ** pkt_data)View Code
Note:
The first parameter is the enabled device.
The second parameter is some information added by WinPcap. (Timestamp, captured package length, actual package length ).
Third parameter: the actual data packet.
Function return value:
The returned value is 1, and the returned value is normal;
The returned value is 0. An invalid package is returned after the timeout;
The returned value is-1, and an error occurs;
The returned value is-2. Read EOF.
Source code:
# Define WIN32 # include "pcap. h "# include" winsock. h "# include" time. h "/* packet handler function prototype */void packet_handler (u_char * param, const struct pcap_pkthdr * header, const u_char * pkt_data); int main () {pcap_if_t * alldevs; pcap_if_t * d; int inum; int I = 0; pcap_t * adhandle; char errbuf [PCAP_ERRBUF_SIZE];/* get the list of local devices */if (Response (PCAP_SRC_IF_STRING, NULL, & alldevs, errbuf) =-1) {fprintf (Stderr, "Error in pcap_findalldevs: % s \ n", errbuf); exit (1) ;}/ * print the list */for (d = alldevs; d; d = d-> next) {printf ("% d. % s ", ++ I, d-> name); if (d-> description) printf (" (% s) \ n ", d-> description ); else printf ("(No description available) \ n");} if (I = 0) {printf ("\ nNo interfaces found! Make sure WinPcap is installed. \ n "); return-1;} printf (" Enter the interface number (1-% d): ", I); scanf_s (" % d ", & inum ); if (inum <1 | inum> I) {printf ("\ nInterface number out of range. \ n ");/* release the device list */pcap_freealldevs (alldevs); return-1;}/* jump to the selected adapter */for (d = alldevs, I = 0; I <inum-1; d = d-> next, I ++);/* Open the device */if (adhandle = pcap_open (d-> name, // device name 65536, // 65535 ensures that all content of each packet on different data link layers can be captured PCAP_OPENFLAG_PROMISCUOUS, // Mixed Mode 0, // The read timeout time is NULL, // remote machine verification errbuf // Error Buffer Pool) = NULL) {fprintf (stderr, "\ nUnable to open the adapter. % s is not supported by WinPcap \ n ", d-> name);/* release device list */pcap_freealldevs (alldevs); return-1 ;} printf ("\ nlistening on % s... \ n ", d-> description);/* release the device list */pcap_freealldevs (alldevs);/* start to capture */pcap_loop (adhandle, 30, packet_handler, NULL ); system ("pause"); return 0;}/* libpcap automatically calls this callback function */void packet_handler (u_char * param, const struct pcap_pkthdr * header, const u_char * pkt_data) {struct tm ltime = {0}; char timestr [16]; time_t local_ TV _sec; /* convert the timestamp into a recognizable format */local_ TV _sec = header-> ts. TV _sec; localtime_s (& ltime, & local_ TV _sec); strftime (timestr, sizeof timestr, "% H: % M: % S", & ltime); printf ("% s, %. 6d len: % d \ n ", timestr, header-> ts. TV _usec, header-> len );}Callback Function # define WIN32 # include "pcap. h "int main () {pcap_if_t * alldevs; pcap_if_t * d; int inum; int I = 0; pcap_t * adhandle; int res; char errbuf [PCAP_ERRBUF_SIZE]; struct tm ltime; char timestr [16]; struct pcap_pkthdr * header; const u_char * pkt_data; time_t local_ TV _sec; int j = 10; // only 10 packets are restricted./* obtain the list of local devices */if (pcap_findalldevs_ex (PCAP_SRC_IF_STRING, NULL, & alldevs, errbuf) =-1) {fprintf (stderr, "Err Or in pcap_findalldevs: % s \ n ", errbuf); exit (1);}/* print list */for (d = alldevs; d = d-> next) {printf ("% d. % s ", ++ I, d-> name); if (d-> description) printf (" (% s) \ n ", d-> description ); else printf ("(No description available) \ n");} if (I = 0) {printf ("\ nNo interfaces found! Make sure WinPcap is installed. \ n "); return-1;} printf (" Enter the interface number (1-% d): ", I); scanf_s (" % d ", & inum ); if (inum <1 | inum> I) {printf ("\ nInterface number out of range. \ n ");/* release the device list */pcap_freealldevs (alldevs); return-1;}/* jump to the selected adapter */for (d = alldevs, I = 0; I <inum-1; d = d-> next, I ++);/* Open the device */if (adhandle = pcap_open (d-> name, // device name 65536, // part of the data packet to be captured // 65535 ensure that all content of each data packet on different data link layers can be captured. PCAP_OPENFLAG_PROMISCUOUS, // mixed mode 1000, // the read timeout value is NULL, // errbuf for remote machine authentication // Error Buffer Pool) = NULL) {fprintf (stderr, "\ nUnable to open the adapter. % s is not supported by WinPcap \ n ", d-> name);/* release set list */pcap_freealldevs (alldevs); return-1 ;} printf ("\ nlistening on % s... \ n ", d-> description);/* release the device list */pcap_freealldevs (alldevs);/* get the data packet */while (res = pcap_next_ex (adhandle, & header, & pkt_data) >=0 & j> 0) {if (res = 0)/* timeout time to */continue; /* convert the timestamp into a recognizable format */local_ TV _sec = header-> ts. TV _sec; localtime_s (& ltime, & local_ TV _sec); strftime (timestr, sizeof timestr, "% H: % M: % S", & ltime); j --; printf ("% s, %. 6d len: % d \ n ", timestr, header-> ts. TV _usec, header-> len);} if (res =-1) {printf ("Error reading the packets: % s \ n", pcap_geterr (adhandle )); return-1;} system ("pause"); return 0 ;}Non-callback function