[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