home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / NETTOOLS.ZIP / PingThread.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-12-30  |  20.4 KB  |  1,029 lines

  1. // PingThread.cpp : implementation file
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "nettools.h"
  6. #include "PingParmList.h"
  7. #include "winsock.h"
  8. #include "ipexport.h"
  9. #include "PingThread.h"
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16. #ifdef _DEBUG
  17. #define new DEBUG_NEW
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. struct IPErrors
  23. {
  24.     CHAR   msg[30];
  25. };
  26.                   
  27.  
  28. struct IPErrors ErrorCodes[23] =
  29. {
  30.     {"OK"},
  31.     {"Buffer too small"},            
  32.     {"Dest Net Unreachable"},
  33.     {"Dest Host Unreachable"},
  34.     {"Dest Prot Unreachable"},
  35.     {"Dest Port Unreachable"},
  36.     {"No Resources"},
  37.     {"Bad IP Option"},
  38.     {"Hardware Error"},
  39.     {"Packet Too Big"},
  40.     {"Request Timed Out"},
  41.     {"Bad Request"},
  42.     {"Bad Route"},
  43.     {"TTL Expired Transit"},
  44.     {"TTL Expired Re-Assembly"},
  45.     {"Parameter Problem"},
  46.     {"Source Quench"},
  47.     {"Option Too Large"},
  48.     {"Bad Destination"},
  49.     {"Address Deleted"},
  50.     {"Spec MTU Change"},
  51.     {"MTU Change"},
  52.     {"Unload"}
  53. };
  54.     
  55.  
  56. //
  57. //  The Main Thread Procedure
  58. //
  59. UINT CPingThreadProc(LPVOID lparam)
  60. {
  61.     BOOL bPingThreadComplete;
  62.     CPingThreadParmList *lpPingParms;
  63.     CPingThread *mythread;
  64.  
  65.     lpPingParms = (CPingThreadParmList*)lparam;
  66.     mythread = (CPingThread*)lpPingParms->m_mythread;
  67.     
  68.     while (TRUE)
  69.     {
  70.  
  71.     
  72.         bPingThreadComplete = FALSE;
  73.  
  74.         // Wait until the main application thread asks this thread to do
  75.         // something.
  76.  
  77.         if (WaitForSingleObject(lpPingParms->m_hEventStartPing,
  78.                                 INFINITE) != WAIT_OBJECT_0)
  79.             break;
  80.  
  81.         // Exit the thread if the main application sets the "kill"
  82.         // event. The main application will set the "start event
  83.         // before setting the "kill" event.
  84.  
  85.         if (WaitForSingleObject(lpPingParms->m_hEventKillPing, 0)
  86.             == WAIT_OBJECT_0)
  87.             break; // Terminate this thread by existing the proc.
  88.  
  89.         // Reset event to indicate "not done", that is, in progress.
  90.         //ResetEvent(lpPingParms->m_hEventPingDone);
  91.  
  92.         // Run PING!!
  93.         if (lpPingParms->opt_tracert)
  94.             bPingThreadComplete = 
  95.                 mythread->RunTracert(lpPingParms);
  96.         else
  97.             bPingThreadComplete = 
  98.                 mythread->RunPing(lpPingParms);
  99.             
  100.  
  101.         // Set event to indicate that we're done (i.e., no longer in progres),
  102.         // even if perhaps interrupted by "kill" event.
  103.         SetEvent(lpPingParms->m_hEventPingDone);
  104.         
  105.         // tell main app we're done this request
  106.         ::PostMessage(lpPingParms->m_hwndNotifyPingDone,
  107.             WM_USER_PING_DONE, 0, (LONG)lpPingParms);
  108.     }
  109.  
  110.     // tell main app this thread has terminated.
  111.     SetEvent(lpPingParms->m_hEventPingDead);
  112.  
  113.     return 0;
  114.  
  115.         
  116.     
  117.  
  118.     
  119.     
  120. }
  121.  
  122. /////////////////////////////////////////////////////////////////////////////
  123. // CPingThread
  124.  
  125. IMPLEMENT_DYNCREATE(CPingThread, CWinThread)
  126.  
  127. CPingThread::CPingThread()
  128. {
  129. }
  130.  
  131. CPingThread::~CPingThread()
  132. {
  133. }
  134.  
  135. BOOL CPingThread::InitInstance()
  136. {
  137.     
  138.     // start winsock
  139.     WSADATA wsaData;
  140.     WORD version;
  141.     version = MAKEWORD(2,1);
  142.     if (WSAStartup(version,&wsaData))
  143.         return FALSE;
  144.     //
  145.     // load icmp dll
  146.     //
  147.     Icmpdll = LoadLibrary("ICMP.DLL");
  148.     if (Icmpdll == NULL)
  149.         return FALSE;
  150.  
  151.     IcmpCreateFile = 
  152.     (ICMPCREATEFILE) GetProcAddress(Icmpdll,"IcmpCreateFile");
  153.  
  154.     IcmpCloseHandle =
  155.     (ICMPCLOSEHANDLE) GetProcAddress(Icmpdll,"IcmpCloseHandle");
  156.  
  157.     IcmpSendEcho = 
  158.         (ICMPSENDECHO) GetProcAddress(Icmpdll,"IcmpSendEcho");
  159.  
  160.  
  161.  
  162.     
  163.     return TRUE;
  164. }
  165.  
  166.  
  167. BEGIN_MESSAGE_MAP(CPingThread, CWinThread)
  168.     //{{AFX_MSG_MAP(CPingThread)
  169.         // NOTE - the ClassWizard will add and remove mapping macros here.
  170.     //}}AFX_MSG_MAP
  171. END_MESSAGE_MAP()
  172.  
  173. /////////////////////////////////////////////////////////////////////////////
  174. // CPingThread message handlers
  175.  
  176.  
  177.  
  178. void CPingThread::Kill()
  179. {
  180.     bKill = TRUE;
  181.     
  182. }
  183.  
  184.  
  185. BOOL CPingThread::Start()
  186. {
  187.     BOOL rc = TRUE;
  188.     bKill = FALSE;
  189.     rc = CreateThread();
  190.     if (!rc)
  191.         return rc;
  192.  
  193.     rc = InitInstance();
  194.     if (!rc)
  195.         return rc;
  196.  
  197.     return rc;
  198.  
  199.  
  200. }
  201.  
  202. BOOL CPingThread::Running()
  203. {
  204.     DWORD Status;
  205.     ::GetExitCodeThread(m_hThread,&Status);
  206.     if (Status == STILL_ACTIVE)
  207.         return TRUE;
  208.     else
  209.         return FALSE;
  210.  
  211.  
  212. }
  213.  
  214. HANDLE CPingThread::Icmp_Open()
  215. {
  216.     HANDLE File;
  217.     File = (*IcmpCreateFile)();
  218.     if (File != INVALID_HANDLE_VALUE)
  219.         return File;
  220.     else
  221.     {
  222.         File = 0;
  223.         return File;
  224.     }
  225.  
  226. }
  227.  
  228. BOOL CPingThread::Icmp_Close(HANDLE h)
  229. {
  230.     BOOL rc;
  231.     rc = (*IcmpCloseHandle)(h);
  232.     return rc;
  233.  
  234. }
  235.  
  236. BOOL CPingThread::Icmp_Sendto(CPingThreadParmList *lppingvars,
  237.                               CHAR *OUTBuf,
  238.                               CHAR *INBuf,
  239.                               struct ipopt_info *lpIpopt,
  240.                               ULONG sendaddr,
  241.                               INT maxoutbuffsize,
  242.                               INT maxinbuffsize)
  243. {
  244.     u_short i;
  245.     char c;
  246.  
  247.     
  248.     //DWORD NumberOfEchoReplies;
  249.        memset(OUTBuf,0,maxoutbuffsize);
  250.     c=' ';   /* first char: space */
  251.     for (i=0;
  252.            ((i < (lppingvars->opt_packetlen_val)) && (i < maxoutbuffsize)); 
  253.         i++) 
  254.     {
  255.         OUTBuf[i] = c;
  256.         c++;
  257.         if (c > '~')    /* go up to ASCII 126, then back to 32 */
  258.             c= ' ';
  259.     }
  260.  
  261.     
  262.     
  263.     
  264.  
  265.     memset(INBuf,0,maxinbuffsize);
  266.     NumberOfEchoReplies = (*IcmpSendEcho)
  267.                         (PingSocket,sendaddr,OUTBuf,
  268.                          lppingvars->opt_packetlen_val,
  269.                          lpIpopt,
  270.                          INBuf,
  271.                          maxinbuffsize,
  272.                          lppingvars->opt_timeout_val);
  273.  
  274.     
  275.     
  276.     
  277.     return TRUE;
  278.     
  279.  
  280. }
  281.  
  282. BOOL CPingThread::Icmp_SetOpts(CPingThreadParmList *lppingvars,
  283.                                struct ipopt_info *lpIpopt,
  284.                                UCHAR *optdata,
  285.                                INT optsize)
  286. {
  287.     BOOL HaveOpts = FALSE;
  288.     int numrrdata;
  289.     
  290.     memset(lpIpopt,0,IPOPT_INFO_LEN);
  291.     
  292.     struct in_addr rr_inaddr;
  293.     UCHAR *routes;
  294.  
  295.     
  296.  
  297.  
  298.     if (lppingvars->opt_timeout_val == 0)  // Timeout value specified?
  299.     {
  300.         //set default timeout
  301.         lppingvars->opt_timeout_val = 5000;
  302.                 
  303.     }
  304.     
  305.     //
  306.     // the remaining options if set require us to set  
  307.     // a pointer to the options for the sendecho else
  308.     // the pointer should be set to null
  309.     //
  310.  
  311.     if (lppingvars->opt_ttl_val != 0)  // TTL value specified?
  312.     {
  313.         //set TTL if specified
  314.         lpIpopt->Ttl = lppingvars->opt_ttl_val;
  315.         HaveOpts = TRUE;
  316.         
  317.         
  318.     }
  319.     
  320.     
  321.     if (lppingvars->opt_tos_val != 0) // TOS value specified?
  322.     {
  323.         //set TOS if specified
  324.         lpIpopt->Tos = lppingvars->opt_tos_val;
  325.         if (lpIpopt->Ttl == 0)
  326.             lpIpopt->Ttl = 255;
  327.         HaveOpts = TRUE;
  328.         
  329.         
  330.     }
  331.  
  332.     if (lppingvars->opt_dontfragment) // dont Frag?
  333.     {
  334.         //set dont frag 
  335.         lpIpopt->Flags |= IP_FLAG_DF;
  336.         HaveOpts = TRUE;
  337.         
  338.         
  339.     }
  340.  
  341.  
  342.     if (lppingvars->opt_rroute_val != 0) // Record Route?
  343.     {
  344.         memset(optdata,0xff,optsize);        
  345.         memset(optdata,0,3+(4*lppingvars->opt_rroute_val));
  346.         optdata[IPOPT_OPTVAL] = IP_OPT_RR;
  347.         optdata[IPOPT_OLEN] = 3+(4*lppingvars->opt_rroute_val);
  348.         optdata[IPOPT_OFFSET] = IPOPT_MINOFF;
  349.         lpIpopt->OptionsData = optdata;
  350.         lpIpopt->OptionsSize = optdata[IPOPT_OLEN];
  351.         if (lpIpopt->Ttl == 0)
  352.             lpIpopt->Ttl = lppingvars->opt_rroute_val;
  353.         HaveOpts = TRUE;
  354.     }
  355.  
  356.     if (lppingvars->opt_timestamp_val != 0) // ts?
  357.     {
  358.         memset(optdata,0xff,optsize);        
  359.         memset(optdata,0,
  360.                4+(8*lppingvars->opt_timestamp_val));
  361.         optdata[IPOPT_OPTVAL] = IP_OPT_TS;
  362.         optdata[IPOPT_OLEN] = 4+(8*lppingvars->opt_timestamp_val);
  363.         optdata[IPOPT_OFFSET] = (IPOPT_MINOFF + 1);
  364.         optdata[IPOPT_TSFLAGS] = IP_OPT_TS_REGADDR;
  365.         lpIpopt->OptionsData = optdata;
  366.         lpIpopt->OptionsSize = optdata[IPOPT_OLEN];
  367.         if (lpIpopt->Ttl == 0)
  368.             lpIpopt->Ttl = 255;
  369.         HaveOpts = TRUE;
  370.  
  371.  
  372.     }
  373.     
  374.  
  375.     if (lppingvars->opt_rrloose || lppingvars->opt_rrstrict)
  376.     {
  377.         numrrdata = lppingvars->opt_rrdata.GetSize();
  378.         memset(optdata,0xff,optsize);        
  379.         memset(optdata,0,3+(4*numrrdata));
  380.         optdata[IPOPT_OLEN] = 3+(4*numrrdata);
  381.         optdata[IPOPT_OFFSET] = IPOPT_MINOFF;
  382.         routes =  optdata+3; 
  383.         for (int x = 0;x<numrrdata;x++)
  384.         {
  385.             GetAddr(lppingvars->opt_rrdata[x],&rr_inaddr);
  386.             *routes = rr_inaddr.s_net;
  387.             *(routes+1) = rr_inaddr.s_host;
  388.             *(routes+2) = rr_inaddr.s_lh;
  389.             *(routes+3) = rr_inaddr.s_impno;
  390.             routes += 4; 
  391.  
  392.         }
  393.         if (lppingvars->opt_rrloose)
  394.             optdata[IPOPT_OPTVAL] = IP_OPT_LSRR;
  395.         else
  396.             optdata[IPOPT_OPTVAL] = IP_OPT_SSRR;
  397.  
  398.         lpIpopt->Ttl = numrrdata;
  399.  
  400.         
  401.     }
  402.  
  403.  
  404.  
  405.  
  406.     if (!HaveOpts)
  407.         return FALSE;
  408.         
  409.         
  410.     return TRUE;
  411.  
  412. }
  413.  
  414. ULONG CPingThread::GetAddr(LPCTSTR szHost,struct in_addr *inaddr)
  415. {
  416.     LPHOSTENT lpstHost = NULL;
  417.     struct in_addr stinaddr;
  418.     u_long lAddr = INADDR_ANY;
  419.  
  420.     if (*szHost)
  421.     {
  422.         //lAddr = inet_addr(szHost);
  423.         stinaddr.s_addr = inet_addr(szHost);
  424.         if ((stinaddr.s_addr == INADDR_NONE) &&
  425.             (strcmp(szHost,"255.255.255.255")))
  426.         {
  427.             lpstHost = gethostbyname(szHost);
  428.             if (lpstHost)
  429.             {
  430.                 lAddr = *((u_long *) (lpstHost->h_addr));
  431.                 if (inaddr)
  432.                     inaddr->s_addr = *((u_long *) (lpstHost->h_addr));
  433.             }
  434.             else
  435.             {
  436.                 lAddr = INADDR_ANY;
  437.                 if (inaddr)
  438.                     inaddr->s_addr = INADDR_ANY;
  439.  
  440.             }
  441.         }
  442.         else
  443.         {
  444.             lAddr = stinaddr.s_addr;
  445.             if (inaddr)
  446.                 inaddr->s_addr = stinaddr.s_addr;
  447.  
  448.         }
  449.             
  450.     }
  451.     
  452.     return (lAddr);
  453.  
  454. }
  455.  
  456. BOOL CPingThread::RunPing(CPingThreadParmList *lppingvars)
  457. {
  458.     
  459.     BOOL Sendok;
  460.     struct ipopt_info IpoptInfo;
  461.     struct ipopt_info *lpIpoptInfo;
  462.     struct icmp_reply *EchoReply;
  463.     INT RRsize = 3+4*PING_NROUTES+1;
  464.     UCHAR RRSpace[3+4*PING_NROUTES+1];
  465.     
  466.     IPAddr SendToAddr;
  467.     CHAR achINBuf[PNGINBUFSIZE];
  468.     CHAR achOUTBuf[PNGOUTBUFSIZE];
  469.     
  470.     PingSocket = Icmp_Open();
  471.     if (PingSocket == 0)
  472.     {
  473.         PrintLine("Ping: Error - ICMP Open Failed",lppingvars);
  474.         return FALSE;
  475.     }
  476.  
  477.     SendToAddr = GetAddr(lppingvars->hostname);
  478.     EchoReply = (struct icmp_reply *)achINBuf;
  479.     EchoReply->RoundTripTime = 0xffffffff;
  480.  
  481.     lpIpoptInfo = &IpoptInfo; // point to ip options
  482.  
  483.     if (!Icmp_SetOpts(lppingvars,lpIpoptInfo,RRSpace,RRsize))
  484.         lpIpoptInfo = NULL;
  485.     
  486.     bKill = FALSE;
  487.     int numpacks;
  488.     numpacks = lppingvars->opt_numpackets_val;
  489.     
  490.     if (lppingvars->opt_interrupt)  // allow 100 pings no options
  491.     {
  492.         numpacks = 100;
  493.         lpIpoptInfo = NULL;
  494.     }
  495.  
  496.     for (int x = 0;x <= numpacks;x++)
  497.     {
  498.         if (bKill)
  499.         {
  500.             PrintLine("Ping Interrupted!",lppingvars);
  501.             return FALSE;
  502.         }
  503.         Sendok = Icmp_Sendto(lppingvars,achOUTBuf,achINBuf,
  504.                             lpIpoptInfo,SendToAddr,
  505.                             PNGOUTBUFSIZE,
  506.                             PNGINBUFSIZE);
  507.         
  508.         if (!ProcessReply(lppingvars,(struct icmp_reply *)achINBuf))
  509.         {
  510.     
  511.             Icmp_Close(PingSocket);
  512.             return FALSE;
  513.         }
  514.         
  515.     
  516.     }
  517.  
  518.  
  519.     
  520.     Icmp_Close(PingSocket);
  521.     return TRUE;
  522.  
  523. }
  524.  
  525. BOOL CPingThread::ProcessReply(CPingThreadParmList *lppingvars,
  526.                                struct icmp_reply *lpReply)
  527. {
  528.     struct in_addr convaddr;
  529.     struct hostent *resolve_addr;
  530.     CHAR *szTempName;
  531.     CHAR szHost[MAXHOSTSIZE];
  532.     CHAR szLBLine[LBLINESIZE];
  533.     UCHAR RETSpace[3+4*PING_NROUTES+1];
  534.  
  535.     int NumberOfAddresses;
  536.     UCHAR *routes;
  537.     u_long holdaddr,holdtime;
  538.     int x;
  539.     int count;
  540.  
  541.  
  542.     if (lpReply->Status != IP_SUCCESS)
  543.         
  544.         if (lpReply->Status == IP_REQ_TIMED_OUT)
  545.         {
  546.             PrintLine("Request Timed Out",lppingvars);
  547.             return TRUE;
  548.         }
  549.         else
  550.         if (lpReply->Status > IP_UNLOAD)
  551.         {
  552.             wsprintf(szLBLine,"Ping: Error - Status = %ld",
  553.                      lpReply->Status);
  554.             PrintLine(szLBLine,lppingvars);
  555.             return FALSE;
  556.         }
  557.         else
  558.         {
  559.             u_long errtab;
  560.             errtab = lpReply->Status - IP_STATUS_BASE;
  561.             wsprintf(szLBLine,"Ping: Error - Status = %ld %s",
  562.                 lpReply->Status,
  563.                 ErrorCodes[errtab].msg);
  564.             PrintLine(szLBLine,lppingvars);
  565.             return FALSE;
  566.         }
  567.     
  568.     
  569.     
  570.  
  571.     convaddr.s_addr = lpReply->Address;
  572.     szTempName = inet_ntoa(convaddr);
  573.     if (szTempName)
  574.         strcpy(szHost,szTempName);
  575.     else
  576.         strcpy(szHost,"Unknown Address");
  577.     
  578.     if (lppingvars->opt_resolve)
  579.     {
  580.         resolve_addr = gethostbyaddr((char*)&lpReply->Address,
  581.                                     4,AF_INET);
  582.         if (resolve_addr)
  583.             wsprintf(szLBLine,
  584.                 "Ping: Reply from %s [%s] Time %ld ms TTL %u Size %u",
  585.                 resolve_addr->h_name,
  586.                 szHost,
  587.                 lpReply->RoundTripTime,
  588.                 lpReply->Options.Ttl,
  589.                 lppingvars->opt_packetlen_val);
  590.         else
  591.             wsprintf(szLBLine,
  592.                 "Ping: Reply from %s [Unknown] Time %ld ms TTL %u Size %u",
  593.                 szHost,
  594.                 lpReply->RoundTripTime,
  595.                 lpReply->Options.Ttl,
  596.                 lppingvars->opt_packetlen_val);
  597.  
  598.     }
  599.     else
  600.     {
  601.         wsprintf(szLBLine,
  602.                 "Ping: Reply from %s Time %ld ms TTL %u Size %u",
  603.                 szHost,
  604.                 lpReply->RoundTripTime,
  605.                 lpReply->Options.Ttl,
  606.                 lppingvars->opt_packetlen_val);
  607.     }
  608.  
  609.     PrintLine(szLBLine,lppingvars);
  610.     
  611.     if (lppingvars->opt_rroute_val != 0) // Record Route?
  612.     {
  613.         count = (int)lpReply->Options.OptionsData[IPOPT_OLEN];
  614.         memset(RETSpace,0,sizeof(RETSpace));
  615.         for (x=0;x<count;x++)
  616.         {
  617.             RETSpace[x] = lpReply->Options.OptionsData[x];
  618.         }
  619.         if (RETSpace[IPOPT_OFFSET] > IPOPT_MINOFF)
  620.         {
  621.             NumberOfAddresses = 
  622.              ((RETSpace[IPOPT_OFFSET] - 4)
  623.                 / 4);
  624.             routes = RETSpace+3;
  625.             for(x=0;x<NumberOfAddresses;x++)
  626.             {
  627.                 // ensure holdaddr will remain in network 
  628.                 // order while the UCHAR data is converted
  629.                 // to u_long
  630.  
  631.                 holdaddr = (*routes<<24) | (*(routes+1)<<16) |
  632.                          (*(routes+2)<<8) | *(routes+3);
  633.                 holdaddr = ntohl(holdaddr);
  634.                 convaddr.s_addr = holdaddr;
  635.                 szTempName = inet_ntoa(convaddr);
  636.                 strcpy(szHost,szTempName);
  637.                 
  638.  
  639.                 if (lppingvars->opt_resolve)
  640.                 {
  641.                     resolve_addr = gethostbyaddr((char*)&holdaddr,
  642.                                                 4,AF_INET);
  643.                     if (resolve_addr)
  644.                         wsprintf(szLBLine,"Ping: Reply Route %s [%s]",
  645.                             resolve_addr->h_name,
  646.                             szHost);
  647.                     else
  648.                         wsprintf(szLBLine,"Ping: Reply Route %s [Unkown]",
  649.                             szHost);
  650.                 }
  651.                 else
  652.                 {
  653.                     wsprintf(szLBLine,"Ping: Reply Route %s",
  654.                                 szHost);
  655.                 }
  656.                 
  657.                 PrintLine(szLBLine,lppingvars);
  658.                 routes = routes + 4;
  659.             }
  660.         }
  661.         else
  662.         {
  663.             PrintLine("No Routes Recorded",lppingvars);
  664.         
  665.         }
  666.     }
  667.  
  668.     // timestamp option
  669.     if (lppingvars->opt_timestamp_val != 0) // Timestamp?
  670.     {
  671.         count = (int)lpReply->Options.OptionsData[IPOPT_OLEN];
  672.         memset(RETSpace,0,sizeof(RETSpace));
  673.         for (x=0;x<count;x++)
  674.         {
  675.             RETSpace[x] = lpReply->Options.OptionsData[x];
  676.         }
  677.         if (RETSpace[IPOPT_OFFSET] > IPOPT_MINOFF)
  678.         {
  679.             NumberOfAddresses = 
  680.              ((RETSpace[IPOPT_OFFSET] - 5)
  681.                 / 8);
  682.             routes = RETSpace+4;
  683.             for(x=0;x<NumberOfAddresses;x++)
  684.             {
  685.                 // ensure holdaddr will remain in network 
  686.                 // order while the UCHAR data is converted
  687.                 // to u_long
  688.  
  689.                 holdaddr = (*routes<<24) | (*(routes+1)<<16) |
  690.                          (*(routes+2)<<8) | *(routes+3);
  691.                 holdaddr = ntohl(holdaddr);
  692.                 convaddr.s_addr = holdaddr;
  693.                 szTempName = inet_ntoa(convaddr);
  694.                 strcpy(szHost,szTempName);
  695.                 holdtime = (*(routes+4)<<24) | (*(routes+5)<<16) |
  696.                          (*(routes+6)<<8) | *(routes+7);
  697.                 holdtime = ntohl(holdtime);
  698.                 if (lppingvars->opt_resolve)
  699.                 {
  700.                     resolve_addr = gethostbyaddr((char*)&holdaddr,
  701.                                                 4,AF_INET);
  702.                     if (resolve_addr)
  703.  
  704.                         wsprintf(szLBLine,
  705.                             "Ping:      Route %s [%s] TS %lu",
  706.                             resolve_addr->h_name,
  707.                             szHost,
  708.                             holdtime);
  709.                     else
  710.                         wsprintf(szLBLine,
  711.                             "Ping:      Route %s [Unknown] TS %lu",
  712.                             szHost,
  713.                             holdtime);
  714.                 }
  715.                 else
  716.                 {
  717.                     wsprintf(szLBLine,"Ping:      Route %s TS %lu",
  718.                             szHost,holdtime);
  719.                 }
  720.                 PrintLine(szLBLine,lppingvars);
  721.                 routes = routes + 4;
  722.             }
  723.         }
  724.         else
  725.         {
  726.             PrintLine("No Routes Recorded",lppingvars);
  727.             
  728.         }
  729.     }
  730.     
  731.     return TRUE;
  732.  
  733. }
  734.  
  735. void CPingThread::PrintLine(LPSTR szMsg,CPingThreadParmList *lppingvars)
  736. {
  737.     //CString m_errmsg;
  738.     //CHAR *pm_errmsg;
  739.     
  740.     //pm_errmsg = m_errmsg.GetBuffer(LBLINESIZE+1);
  741.     //strcpy(pm_errmsg,szMsg);
  742.     //m_errmsg.ReleaseBuffer();
  743.     //m_PingOutPut.Add(m_errmsg);
  744.     
  745.     ::SendMessage(lppingvars->m_hwndNotifyPingDone,
  746.                 WM_USER_PING_PRINT, 0, (LONG)szMsg);
  747.     
  748.     return;
  749.  
  750. }
  751.  
  752.  
  753. CPingThread::CPingThread(CPingThreadParmList *lpPingvars)
  754. {
  755.     //
  756.     // Init ourselves
  757.     //
  758.  
  759.     lpPingvars->m_mythread = this;
  760.     m_bAutoDelete = FALSE;
  761.     m_pThreadParams = lpPingvars;
  762.     m_pfnThreadProc = CPingThreadProc;
  763.  
  764.  
  765. }
  766.  
  767. BOOL CPingThread::RunTracert(CPingThreadParmList *lppingvars)
  768. {
  769.     BOOL Sendok;
  770.     UINT MaxTtl = 30;
  771.     UINT probecnt = 3;
  772.     struct hostent *resolve_addr;
  773.     CHAR szLBLine[LBLINESIZE];
  774.     ULONG Timestamp;
  775.     CHAR *szTempName;
  776.     CHAR szHost[MAXHOSTSIZE];
  777.     struct in_addr convaddr;
  778.     struct ipopt_info IpoptInfo;
  779.     struct ipopt_info *lpIpoptInfo;
  780.     struct icmp_reply *EchoReply;
  781.  
  782. // get rid of these below/
  783.     IPAddr SendToAddr;
  784.     CHAR achINBuf[PNGINBUFSIZE];
  785.     CHAR achOUTBuf[PNGOUTBUFSIZE];
  786.     
  787.     PingSocket = Icmp_Open();
  788.     if (PingSocket == 0)
  789.     {
  790.         PrintLine("Ping: Error - ICMP Open Failed",lppingvars);
  791.         return FALSE;
  792.     }
  793.  
  794.     SendToAddr = GetAddr(lppingvars->hostname);
  795.     EchoReply = (struct icmp_reply *)achINBuf;
  796.  
  797.     bKill = FALSE;
  798.     
  799.     
  800.  
  801.     lpIpoptInfo = &IpoptInfo;
  802.     memset(lpIpoptInfo,0,IPOPT_INFO_LEN);
  803.  
  804.     convaddr.s_addr = SendToAddr;
  805.  
  806.     // convert addr to dotted
  807.  
  808.     szTempName = inet_ntoa(convaddr);
  809.     if (szTempName)
  810.         strcpy(szHost,szTempName);
  811.     else
  812.         strcpy(szHost,"Unknown Address");
  813.  
  814.     // set ttl defaults or values
  815.     // set timeout defaults and values
  816.  
  817.     if (lppingvars->opt_timeout_val == 0)  // Timeout value specified?
  818.     {
  819.         //set default timeout
  820.         lppingvars->opt_timeout_val = 5000;
  821.                 
  822.     }
  823.     
  824.     if (lppingvars->opt_ttl_val == 0)  // Timeout value specified?
  825.     {
  826.         //set default timeout
  827.         lppingvars->opt_ttl_val = 30;
  828.  
  829.     }
  830.  
  831.     MaxTtl = lppingvars->opt_ttl_val;
  832.     // print the report header
  833.     if (lppingvars->opt_resolve)
  834.     {
  835.         resolve_addr = gethostbyaddr((char*)&SendToAddr,
  836.                                     4,AF_INET);
  837.         if (resolve_addr)
  838.             wsprintf(szLBLine,
  839.                 "Tracing: %s [%s] TTL %u Size %u",
  840.                 resolve_addr->h_name,
  841.                 szHost,
  842.                 MaxTtl,
  843.                 lppingvars->opt_packetlen_val);
  844.         else
  845.             wsprintf(szLBLine,
  846.                 "Tracing: %s [Unkown] TTL %u Size %u",
  847.                 lppingvars->hostname,
  848.                 MaxTtl,
  849.                 lppingvars->opt_packetlen_val);
  850.     }
  851.     else
  852.     {
  853.             wsprintf(szLBLine,
  854.                 "Tracing: %s TTL %u Size %u",
  855.                 lppingvars->hostname,
  856.                 MaxTtl,
  857.                 lppingvars->opt_packetlen_val);
  858.         
  859.     }
  860.     
  861.     PrintLine(szLBLine,lppingvars);
  862.     
  863.  
  864.                 
  865.     //
  866.     // ttl loop
  867.     //
  868.     for (INT x = 1;x <= lppingvars->opt_ttl_val;x++)
  869.     {
  870.         
  871.         lpIpoptInfo->Ttl = x;
  872.         //
  873.         // probe loop
  874.         //
  875.         for (UINT y = 1;y<=probecnt;y++)
  876.         {
  877.             if (bKill)
  878.             {
  879.                 PrintLine("Ping Interrupted!",lppingvars);
  880.                 return FALSE;
  881.             }
  882.  
  883.             Timestamp = GetTickCount();
  884.             Sendok = Icmp_Sendto(lppingvars,achOUTBuf,achINBuf,
  885.                             lpIpoptInfo,SendToAddr,
  886.                             PNGOUTBUFSIZE,
  887.                             PNGINBUFSIZE);
  888.             
  889.             
  890.             if (!TracertReply(lppingvars,
  891.                                 (struct icmp_reply *)achINBuf,
  892.                                 x,y,
  893.                                 Timestamp))
  894.             {
  895.                 Icmp_Close(PingSocket);
  896.                 return FALSE;
  897.             }
  898.             if (x > 1 && EchoReply->Address == SendToAddr && y == probecnt)
  899.             {
  900.                 x = MaxTtl + 1;
  901.             }
  902.         }
  903.     }
  904.     return TRUE;
  905.     
  906. }
  907.  
  908.  
  909. BOOL CPingThread::TracertReply(CPingThreadParmList *lppingvars,
  910.                                struct icmp_reply *lpReply,
  911.                                UINT ttl,
  912.                                UINT probe,
  913.                                ULONG Timestamp)
  914. {
  915.     
  916.     CHAR *szTempName;
  917.     CHAR szHost[MAXHOSTSIZE];
  918.     struct in_addr convaddr;
  919.     struct hostent *resolve_addr;
  920.     CHAR build_line[LBLINESIZE];
  921.     CHAR szLBLine[LBLINESIZE];
  922.     ULONG errtab;
  923.     ULONG RRTime;
  924.             
  925.     //
  926.     
  927.     RRTime = GetTickCount() - Timestamp;
  928.     if (lpReply->Status > IP_UNLOAD)
  929.     {
  930.         wsprintf(szLBLine,"Ping: Error - Status = %ld",
  931.                  lpReply->Status);
  932.         PrintLine(szLBLine,lppingvars);
  933.         return FALSE;
  934.     }
  935.     if (lpReply->Status != IP_SUCCESS)
  936.     {
  937.         if (!(lpReply->Status == IP_REQ_TIMED_OUT ||
  938.                                IP_TTL_EXPIRED_TRANSIT))
  939.     
  940.         {
  941.         
  942.             errtab = lpReply->Status - IP_STATUS_BASE;
  943.             wsprintf(szLBLine,"Ping: Error - Status = %ld %s",
  944.                 lpReply->Status,
  945.                 ErrorCodes[errtab].msg);
  946.             PrintLine(szLBLine,lppingvars);
  947.             return FALSE;
  948.         }
  949.     }
  950.  
  951.     
  952.  
  953.     wsprintf(szLBLine,
  954.             "    TTL = %u Probe = %u ",
  955.                 ttl,
  956.                 probe);
  957.  
  958.  
  959.     convaddr.s_addr = lpReply->Address;
  960.  
  961.     szTempName = inet_ntoa(convaddr);
  962.     if (szTempName)
  963.         strcpy(szHost,szTempName);
  964.     else
  965.         strcpy(szHost,"Unknown Address");
  966.  
  967.     if (lppingvars->opt_resolve)
  968.     {
  969.         resolve_addr = gethostbyaddr((char*)&lpReply->Address,
  970.                                     4,AF_INET);
  971.         if (resolve_addr)
  972.             wsprintf(build_line,
  973.                 "from %s [%s] ",
  974.                 resolve_addr->h_name,
  975.                 szHost);
  976.         else
  977.             wsprintf(build_line,
  978.                 "from %s [Unkown] ",
  979.                 szHost);
  980.  
  981.             
  982.     }
  983.     else
  984.     {
  985.         wsprintf(build_line,
  986.                 "from %s ",
  987.                 szHost);
  988.         
  989.     }
  990.  
  991.     
  992.         
  993.     strcat(szLBLine,build_line);
  994.     
  995.     if (lpReply->Status == IP_SUCCESS)
  996.     {
  997.         wsprintf(build_line,
  998.             "Time %ld ms ",
  999.             lpReply->RoundTripTime);
  1000.         strcat(szLBLine,build_line);
  1001.         
  1002.     }
  1003.     else
  1004.     {
  1005.         wsprintf(build_line,
  1006.             "Time %lu ms Timed Out",
  1007.             RRTime);
  1008.                
  1009.         strcat(szLBLine,build_line);
  1010.         //errtab = lpReply->Status;
  1011.         //errtab -= IP_STATUS_BASE;
  1012.         //strcat(szLBLine,
  1013.         //       ErrorCodes[errtab].msg);
  1014.         
  1015.     }
  1016.  
  1017.     PrintLine(szLBLine,lppingvars);
  1018.     return TRUE;
  1019.  
  1020. }
  1021.  
  1022. void CPingThread::CleanUp()
  1023. {
  1024.     FreeLibrary(Icmpdll);  // remove icmp dll
  1025.     WSACleanup();
  1026.     
  1027.  
  1028. }
  1029.