[Winpcap-users] Possible Culprits of Packet Disappearance
Denis Kourktchan
dennis.kg at gmail.com
Fri Jul 31 22:40:55 PDT 2009
Hi Everybody!
Thanks for reading my post. I have somewhat of a multi-layered problem. I am
using winpcap to capture UDP broadcast messages on my network in promiscuous
mode. All captured packets are sent to a program level filter (i.e. the
winpcap's filtering capabilities are not used, all code is included at the
end of this post) in a separate thread. I have been using my current setup
for some time now but then I started noticing missing messages, A LOT of
them. I am by no means an expert programmer ( I picked up C++ thru online
tutorial a year ago ) so I am at a loss as to why I am losing the packets.
So far I have a few suspicions:
1. Messages are not queued in the thread that runs the
pcap_dispatch() or pcap_loop() so perhaps if the computer is having a hiccup
there might be a drop of packets post capture.
2. The packets are filtered out elsewhere in the program before they
hit the destination function.
I would appreciate any and all feedback on my code and possible problems,
like I said I am not expert so please chew it up as much as possible.
I have conducted several tests to provide you with extra information:
1. The same code ran on 4 different PC on the same network and
produced 4 different results.
2. Three instances of the same code ran on the same computer on the
same network and produced 3 different results.
3. A number of variations of buffer sizes and function choices (_loop
vs. _dispatch vs. _next_ex) produced different results on the same computer.
4. An application that the messages were intended for actually
receives the messages fine while my program does not.
5. The packets seem to entirely stop coming in at random times.
Thank you in advance for your help,
- Dennis
My specs are:
OS:
WinXP SP3
Compiler :
Microsoft Visual Studio 2005
Version 8.0.50727.762
Microsoft Visual C++ 2005 SP1
Pcap:
V3.1 And later V4.1beta5
Here is my code:
THIS IS THE FIRST FUNCTION LAUNCHED WHEN "GO BUTTON" is hit, it does the
"background" winpcap stuff and before launching a separate thread to process
the captured packets.
int CForReal::Go(int adapter)
{
(*m_mainDlg->m_debugOf) << endl << " GO BUTTON IS HIT " << endl;
string cmdLineStr;
for (int i=0; m_lpCmdLine[i] != 0; ++i)
{
cmdLineStr = cmdLineStr + (char)(m_lpCmdLine[i]);
}
if (cmdLineStr.length() != 0)
{
//AfxBeginThread(WorkerThreadOldDataProc, NULL);
}
else
{
(*m_mainDlg->m_debugOf) << endl << " GO BUTTON IS HIT ,
LAUNCHING LIVE VERSION " << endl;
// IF Command Line is empty launch Live Version, Lauch WinPCap
pcap_if_t *alldevs;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_if_t *d;
int i;
pcap_t *adhandle;
u_int netmask;
struct bpf_program fcode;
char packet_filter[] = "ip and udp or tcp";
/* Retrieve the device list */
if(pcap_findalldevs(&alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
exit(1);
}
/* Jump to the selected adapter */
for(d=alldevs, i=0; i< adapter ;d=d->next, i++);
printf("\nBefore pcap_open_live\n");
/* Open the adapter */
if ((adhandle= pcap_open_live(d->name, // name of the device
65536, //
portion of the packet to capture.
//
65536 grants that the whole packet will be captured on all the MACs.
1, //
promiscuous mode (nonzero means promiscuous)
500, // read
timeout
errbuf //
error buffer
)) == NULL)
{
fprintf(stderr,"\nUnable to open the adapter. %s is not
supported by WinPcap\n");
/* Free the device list */
pcap_freealldevs(alldevs);
return -1;
}
if (pcap_setbuff(adhandle, 41943040) != 0)
{
fprintf(stderr,"\nUnable to expand the buffer size. %s is
not supported by WinPcap\n");
/* Free the device list */
pcap_freealldevs(alldevs);
return -1;
}
printf("\nBefore pcap_datalink\n");
/* Check the link layer. We support only Ethernet for
simplicity. */
if(pcap_datalink(adhandle) != DLT_EN10MB)
{
fprintf(stderr,"\nThis program works only on Ethernet
networks.\n");
/* Free the device list */
pcap_freealldevs(alldevs);
return -1;
}
if(d->addresses != NULL)
/* Retrieve the mask of the first address of the interface
*/
netmask=((struct sockaddr_in
*)(d->addresses->netmask))->sin_addr.S_un.S_addr;
else
/* If the interface is without addresses we suppose to be
in a C class network */
netmask=0xffffff;
printf("\nBefore pcap_compile\n");
//compile the filter
if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0
)
{
fprintf(stderr,"\nUnable to compile the packet filter.
Check the syntax.\n");
/* Free the device list */
pcap_freealldevs(alldevs);
return -1;
}
printf("\nBefore pcap_setfilter\n");
//set the filter
if (pcap_setfilter(adhandle, &fcode)<0)
{
fprintf(stderr,"\nError setting the filter.\n");
/* Free the device list */
pcap_freealldevs(alldevs);
return -1;
}
printf("\nlistening on %s...\n", d->description);
/* At this point, we don't need any more the device list. Free
it */
pcap_freealldevs(alldevs);
printf("\nBefore pcap_loop\n");
/* start the capture */
theApp.m_adhandle = adhandle;
///!!!4!!! Launches a LIVE READER
AfxBeginThread(WorkerThreadProc, NULL);
}
return 0;
}
THIS is the function launching pcap_loop:
UINT WorkerThreadProc( LPVOID Param ) {
pcap_loop(theApp.m_adhandle, 0, packet_handler, NULL);
}
The packet_handler()
void CMainDlg::packet_handler(u_char *param, const struct pcap_pkthdr
*header, const u_char *pkt_data)
{
//struct tm *ltime;
//char timestr[16];
ip_header *ih;
udp_header *uh;
u_int ip_len;
u_short sport,dport;
//u_int gg;
//u_char letter;
/* convert the timestamp to readable format */
//ltime=localtime(&header->ts.tv_sec);
//strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
/* print timestamp and length of the packet */
//printf("%d.%.6d len:%d ", header->ts.tv_sec, header->ts.tv_usec,
header->len);
/* retireve the position of the ip header */
ih = (ip_header *) (pkt_data +
14); //length of ethernet header
/* retireve the position of the udp header */
ip_len = (ih->ver_ihl & 0xf) * 4;
uh = (udp_header *) ((u_char*)ih + ip_len);
/* convert from network byte order to host byte order */
sport = ntohs( uh->sport );
dport = ntohs( uh->dport );
// FIRST possible reason to lose packets (ih->proto mess up)
if (ih->proto == 6) { // TCP
//unsigned int jjj = sizeof(tcp_Header);
u_char * data_start = ((u_char *) uh) + 20;
u_short data_length = header->len - ( (u_char *)uh - pkt_data) -
20;
if (data_start[0] == 'G' &&
data_start[1] == 'I' &&
data_start[2] == 'O' &&
data_start[3] == 'P'
)
{
// AnalyzeGiop(data_start, data_length);
}
} else { // UDP
u_char * data_start = ((u_char *) uh) + 8;
u_short data_length = header->len - ( (u_char *)uh - pkt_data) -
8;
if (dport == 3874)
{
HandleConfirmationPacket(data_start, data_length);
}
// SECOND possible reason for packet loss dport mess up
else if (dport == 1874)
{
//*m_debugOf << "Before Handling UDP 1874" << endl;
data_start = ((u_char *) data_start) + 24;
data_length = data_length - 24;
if (data_length > 1 && data_start[0] == 0x78 &&
data_start[1] == 0x9c)
{
unsigned char decompressed_data_start[30000];
unsigned short decompressed_data_length;
//*m_debugOf << "Before DecompressPacket" << endl;
int ret = DecompressPacket(data_start, data_length,
decompressed_data_start, &decompressed_data_length);
if (ret != Z_OK)
{
*m_debugOf << "Decompression error!!!!!!!!!
code: " << ret << endl;
}
//*m_debugOf << "After DecompressPacket" << endl;
HandlePacket(decompressed_data_start,
decompressed_data_length);
}
else
{
HandlePacket(data_start, data_length);
}
//*m_debugOf << "After Handling UDP 1874" << endl;
}
}
}
And Last but not least before the function before the final destination:
void CMainDlg::HandlePacket(u_char * data_start, u_short data_length)
{
deque<string *> * list = new deque<string *>();
string * str = new string();
for (u_int gg=3; gg < data_length ; ++gg) {
u_char letter = *(data_start + gg);
if (letter == 0 || letter == 0x1e) {
if (str->length() > 0) {
list->push_back(str);
str = new string();
}
} else {
str->push_back(letter);
printf("%c", letter < 32 || letter >=0x80 ? '.' : letter);
}
}
delete str;
deque<string *>::const_iterator it;
for (it = list->begin(); it != list->end(); ++it) {
ProcessStockInfo(*it); //this is the destination function
}
for (it = list->begin(); it != list->end(); ++it) {
delete *it;
}
delete list;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.winpcap.org/pipermail/winpcap-users/attachments/20090801/df1efd20/attachment-0001.htm
More information about the Winpcap-users
mailing list