add winpcap 4.0.2 from url http://www.winpcap.org/
[natblaster.git] / winpcap / Examples-pcap / winpcap_stress / winpcap_stress.c
blob0a8501b521e05da8b75a380ae52e6fcb69d7b5dc
1 /*============================================================================*
2 * FILE: winpcap_stress.c
3 *============================================================================*
5 * COPYRIGHT (C) 2006 BY
6 * CACE TECHNOLOGIES, INC., DAVIS, CALIFORNIA
7 * ALL RIGHTS RESERVED.
9 * THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND
10 * COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH
11 * THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY
12 * OTHER COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE
13 * AVAILABLE TO ANY OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE
14 * SOFTWARE IS HEREBY TRANSFERRED.
16 * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT
17 * NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY CACE TECNOLOGIES
19 *===========================================================================*
21 * This program is a generic "stress test" for winpcap. It creates several threads
22 * each of which opens an adapter, captures some packets and then closes it.
23 * The user can specify:
25 * - the number of threads
26 * - the number of read operations that every thread performs before exiting
28 * The program prints statistics before exiting.
30 *===========================================================================*/
32 /////////////////////////////////////////////////////////////////////
33 // Program parameters
34 /////////////////////////////////////////////////////////////////////
35 #undef STRESS_AIRPCAP_TRANSMISSION
36 #define NUM_THREADS 16
37 #define MAX_NUM_READS 500
38 #define MAX_NUM_WRITES 10000
40 #define WRITES_FREQUENCY 2 // This constant specifies how often a thread will transmit instead of receiving
41 // packets.
42 // - 0 means no Tx threads
43 // - 1 means all threads are Tx
44 // - 2 means that 1 thread every 2 is Tx
45 // - 3 means that 1 thread every 3 is Tx
46 // ...and so on
48 #undef INJECT_FILTERS
50 /////////////////////////////////////////////////////////////////////
52 #include <stdlib.h>
53 #include <stdio.h>
54 #include <signal.h>
56 #include <pcap.h>
58 #ifdef STRESS_AIRPCAP_TRANSMISSION
59 #include <airpcap.h>
60 #endif
62 #define LINE_LEN 16
65 #define FILTER "ether[80:1] < 128 || ether[81:1] > 127 || ether[82:1] < 180 || ether[83:1] > 181" \
66 "|| ether[84:1] < 128 || ether[85:1] > 127 || ether[86:1] < 180 || ether[87:1] > 181" \
67 "|| ether[88:1] < 128 || ether[89:1] > 127 || ether[90:1] < 180 || ether[91:1] > 181" \
68 "|| ether[92:1] < 128 || ether[93:1] > 127 || ether[94:1] < 180 || ether[95:1] > 181" \
69 "|| ether[96:1] < 128 || ether[97:1] > 127 || ether[98:1] < 180 || ether[99:1] > 181" \
70 "|| ether[100:1] < 128 || ether[101:1] > 127 || ether[102:1] < 180 || ether[103:1] > 181" \
71 "|| ether[104:1] < 128 || ether[105:1] > 127 || ether[106:1] < 180 || ether[107:1] > 181" \
72 "|| ether[108:1] < 128 || ether[109:1] > 127 || ether[110:1] < 180 || ether[111:1] > 181" \
75 u_int n_iterations = 0;
76 u_int n_packets = 0;
77 u_int n_timeouts = 0;
78 u_int n_open_errors = 0;
79 u_int n_read_errors = 0;
80 u_int n_write_errors = 0;
81 u_int n_findalldevs_errors = 0;
82 u_int n_setfilters = 0;
83 u_int thread_id = 0;
85 CRITICAL_SECTION print_cs;
87 #define MAX_TX_PACKET_SIZE 1604
88 u_char pkt_to_send[MAX_TX_PACKET_SIZE];
91 /////////////////////////////////////////////////////////////////////
92 // Radiotap header. Used for 802.11 transmission
93 /////////////////////////////////////////////////////////////////////
95 #ifndef __MINGW32__
96 #pragma pack(push)
97 #pragma pack(1)
98 #endif // __MINGW32__
99 typedef struct _tx_ieee80211_radiotap_header
101 u_int8_t it_version;
102 u_int8_t it_pad;
103 u_int16_t it_len;
104 u_int32_t it_present;
105 u_int8_t it_rate;
107 #ifdef __MINGW32__
108 __attribute__((__packed__))
109 #endif // __MINGW32__
110 tx_ieee80211_radiotap_header;
111 #ifndef __MINGW32__
112 #pragma pack(pop)
113 #endif // __MINGW32__
115 /////////////////////////////////////////////////////////////////////
116 // Table of legal radiotap Tx rates
117 /////////////////////////////////////////////////////////////////////
118 UCHAR TxRateInfoTable[] =
134 /////////////////////////////////////////////////////////////////////
136 void usage()
138 printf("winpcap_stress: utility that stresses winpcap by opening and capturing from multiple adapters at the same time.\n");
139 printf(" Usage: winpcap_stress <nthreads> <adapter_substring_to_match>\n\n"
140 " Examples:\n"
141 " winpcap_stress\n"
142 " winpcap_stress 10\n\n"
143 " winpcap_stress 10 \\Device\\NPF_{ \n");
146 /////////////////////////////////////////////////////////////////////
148 void sigh(int val)
150 EnterCriticalSection(&print_cs);
152 printf("\nNumber of iterations:\t\t%u\n", n_iterations);
153 printf("Number of packets captured:\t\t%u\n", n_packets);
154 printf("Number of read timeouts:\t\t%u\n", n_timeouts);
155 printf("Number of open errors:\t\t%u\n", n_open_errors);
156 printf("Number of read errors:\t\t%u\n", n_read_errors);
157 printf("Number of setfilters:\t\t%u\n", n_setfilters);
160 // Note: we don't release the critical section on purpose, so the user doesn't
161 // get crappy input when he presses CTRL+C
163 exit(0);
168 /////////////////////////////////////////////////////////////////////
170 DWORD WINAPI pcap_thread(LPVOID arg)
172 pcap_t *fp;
173 char* AdName = (char*)arg;
174 char errbuf[PCAP_ERRBUF_SIZE];
175 int res;
176 struct pcap_pkthdr *header;
177 const u_char *pkt_data;
178 u_int i;
179 u_int n_reads, n_writes;
180 #ifdef INJECT_FILTERS
181 struct bpf_program fcode;
182 int compile_result;
183 #endif
184 #ifdef STRESS_AIRPCAP_TRANSMISSION
185 PAirpcapHandle airpcap_handle;
186 tx_ieee80211_radiotap_header *radio_header;
187 #endif
188 u_int rate_index;
190 srand( (unsigned)time( NULL ) );
193 // Open the adapter
195 if((fp = pcap_open_live(AdName,
196 65535,
197 0, // promiscuous mode
198 1, // read timeout
199 errbuf)) == NULL)
201 EnterCriticalSection(&print_cs);
202 fprintf(stderr,"\nError opening adapter (%s)\n", errbuf);
203 LeaveCriticalSection(&print_cs);
204 n_open_errors++;
205 return -1;
209 // Decide if this is going to be a read or write thread
212 if((WRITES_FREQUENCY != 0) && ((thread_id++) % WRITES_FREQUENCY == 0))
215 // Write thread
217 if(MAX_NUM_WRITES)
219 n_writes = rand() % MAX_NUM_READS;
221 else
223 n_writes = 0;
227 // Get the airpcap handle so we can change wireless-specific settings
229 #ifdef STRESS_AIRPCAP_TRANSMISSION
230 airpcap_handle = pcap_get_airpcap_handle(fp);
232 if(airpcap_handle != NULL)
235 // Configure the AirPcap adapter
238 // Tell the adapter that the packets we'll send don't include the FCS
239 if(!AirpcapSetFcsPresence(airpcap_handle, FALSE))
241 printf("Error setting the Fcs presence: %s\n", AirpcapGetLastError(airpcap_handle));
242 pcap_close(fp);
243 return -1;
247 // Set the link layer to 802.11 + radiotap
249 if(!AirpcapSetLinkType(airpcap_handle, AIRPCAP_LT_802_11_PLUS_RADIO))
251 printf("Error setting the link layer: %s\n", AirpcapGetLastError(airpcap_handle));
252 pcap_close(fp);
253 return -1;
257 // Create the radiotap header
259 radio_header = (tx_ieee80211_radiotap_header*)pkt_to_send;
260 radio_header->it_version = 0;
261 radio_header->it_pad = 0;
262 radio_header->it_len = sizeof(tx_ieee80211_radiotap_header);
263 radio_header->it_present = 1 << 2; // bit 2 is the rate
264 rate_index = 18/*rand() % (sizeof(TxRateInfoTable) / sizeof(TxRateInfoTable[0]))*/;
265 radio_header->it_rate = 18/*TxRateInfoTable[rate_index]*/;
267 #endif
268 for(i = 0; i < n_writes; i++)
270 if(pcap_sendpacket(fp, pkt_to_send, (rand() % MAX_TX_PACKET_SIZE) + 10) != 0)
272 // EnterCriticalSection(&print_cs);
273 // printf("Write Error: %s\n", pcap_geterr(fp));
274 // LeaveCriticalSection(&print_cs);
275 n_write_errors++;
279 else
283 // Read Thread
285 if(MAX_NUM_READS)
287 n_reads = rand() % MAX_NUM_READS;
289 else
291 n_reads = 0;
294 for(i = 0; i < n_reads; i++)
296 res = pcap_next_ex(fp, &header, &pkt_data);
298 if(res < 0)
300 break;
303 #ifdef INJECT_FILTERS
305 EnterCriticalSection(&print_cs);
306 compile_result = pcap_compile(fp, &fcode, FILTER, 1, 0xFFFFFFFF);
307 LeaveCriticalSection(&print_cs);
311 //compile the filter
312 if( compile_result < 0)
314 fprintf(stderr,"Error compiling filter: wrong syntax.\n");
316 else
318 //set the filterf
319 if(pcap_setfilter(fp, &fcode)<0)
321 fprintf(stderr,"Error setting the filter\n");
323 else
325 InterlockedIncrement(&n_setfilters);
327 pcap_freecode(&fcode);
329 #endif
331 if(res == 0)
333 // Timeout elapsed
334 n_timeouts++;
335 continue;
339 // print pkt timestamp and pkt len
340 n_packets++;
343 if(res == -1)
345 EnterCriticalSection(&print_cs);
346 printf("Read error: %s\n", pcap_geterr(fp));
347 LeaveCriticalSection(&print_cs);
348 n_read_errors++;
352 pcap_close(fp);
354 return 1;
357 /////////////////////////////////////////////////////////////////////
358 /////////////////////////////////////////////////////////////////////
360 int main(int argc, char **argv)
362 pcap_if_t *alldevs, *d;
363 u_int i;
364 char errbuf[PCAP_ERRBUF_SIZE];
365 u_int n_threads;
366 HANDLE* hThreads;
367 char* string_to_match;
368 DWORD WaitRes;
371 // Parse input
373 if(argc == 1)
375 n_threads = NUM_THREADS;
376 string_to_match = NULL;
378 else
379 if(argc == 2)
381 n_threads = atoi(argv[1]);
382 string_to_match = NULL;
384 else
385 if(argc == 3)
387 n_threads = atoi(argv[1]);
388 string_to_match = argv[2];
390 else
392 usage();
393 return 1;
397 // Init the Tx packet
399 for(i = 0; i < MAX_TX_PACKET_SIZE; i++)
401 pkt_to_send[i] = i & 0xff;
405 // Allocate storage for the threads list
407 hThreads = (HANDLE*)malloc(n_threads * sizeof(HANDLE));
408 if(!hThreads)
410 printf("Memeory allocation failure\n");
411 return -1;
414 memset(hThreads, 0, n_threads * sizeof(HANDLE));
416 signal(SIGINT, sigh);
417 InitializeCriticalSection(&print_cs);
420 // Scan the device list
422 if(pcap_findalldevs(&alldevs, errbuf) == -1)
424 EnterCriticalSection(&print_cs);
425 fprintf(stderr,"Error in pcap_findalldevs_ex: %s\n", errbuf);
426 LeaveCriticalSection(&print_cs);
427 n_findalldevs_errors++;
428 // continue;
429 return -1;
433 // Jump to the selected adapter
435 for(i = 0;;)
438 // Go through the list, feeding a thread with each adapter that contains our substring
440 for(d = alldevs; d; d = d->next)
442 if(string_to_match)
444 if(!strstr(d->name, string_to_match))
446 continue;
450 if(i == n_threads)
452 i= 0;
456 // Check if the thread is done
458 WaitRes = WaitForSingleObject(hThreads[i], 1);
460 if(WaitRes == WAIT_TIMEOUT)
463 // In case of timeout, we switch to the following thread
465 i++;
466 continue;
470 // Create the child thread
472 printf("Thread %u, %s 0x%x\n", i, d->name, WaitRes);
475 // Close the thread handle
477 if(hThreads[i])
479 CloseHandle(hThreads[i]);
482 hThreads[i] = CreateThread(NULL, 0, pcap_thread, d->name, 0, NULL);
484 if(hThreads[i] == NULL)
486 printf("error creating thread. Quitting\n");
487 sigh(42);
490 n_iterations++;
491 i++;
495 free(hThreads);
497 return 0;