🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.internet.socket
Article #4947

Re: Check for alive status of a TCPIP computer

#4947
From: PaoloItaly
Date: Fri, 19 Nov 2004 11:29
282 lines
7161 bytes
Not tested...

//
// PING.C -- Ping program using ICMP and RAW Sockets
//

#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>

#include "ping.h"

// Internal Functions
void Ping(LPCSTR pstrHost);
void ReportError(LPCSTR pstrFrom);
int  WaitForEchoReply(SOCKET s);
u_short in_cksum(u_short *addr, int len);

// ICMP Echo Request/Reply functions
int  SendEchoRequest(SOCKET, LPSOCKADDR_IN);
DWORD RecvEchoReply(SOCKET, LPSOCKADDR_IN, u_char *);


// main()
void main(int argc, char **argv)
{
    WSADATA wsaData;
    WORD wVersionRequested = MAKEWORD(1,1);
    int nRet;

 // Check arguments
    if (argc != 2)
    {
  fprintf(stderr,"\nUsage: ping hostname\n");
  return;
    }

 // Init WinSock
    nRet = WSAStartup(wVersionRequested, &wsaData);
    if (nRet)
    {
  fprintf(stderr,"\nError initializing WinSock\n");
  return;
    }

 // Check version
 if (wsaData.wVersion != wVersionRequested)
 {
  fprintf(stderr,"\nWinSock version not supported\n");
  return;
 }

 // Go do the ping
 Ping(argv[1]);

 // Free WinSock
    WSACleanup();
}


// Ping()
// Calls SendEchoRequest() and
// RecvEchoReply() and prints results
void Ping(LPCSTR pstrHost)
{
 SOCKET   rawSocket;
 LPHOSTENT lpHost;
 struct    sockaddr_in saDest;
 struct    sockaddr_in saSrc;
 DWORD   dwTimeSent;
 DWORD   dwElapsed;
 u_char    cTTL;
 int       nLoop;
 int       nRet;

 // Create a Raw socket
 rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
 if (rawSocket == SOCKET_ERROR)
 {
  ReportError("socket()");
  return;
 }

 // Lookup host
 lpHost = gethostbyname(pstrHost);
 if (lpHost == NULL)
 {
  fprintf(stderr,"\nHost not found: %s\n", pstrHost);
  return;
 }

 // Setup destination socket address
 saDest.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr));
 saDest.sin_family = AF_INET;
 saDest.sin_port = 0;

 // Tell the user what we're doing
 printf("\nPinging %s [%s] with %d bytes of data:\n",
    pstrHost,
    inet_ntoa(saDest.sin_addr),
    REQ_DATASIZE);

 // Ping multiple times
 for (nLoop = 0; nLoop < 4; nLoop++)
 {
  // Send ICMP echo request
  SendEchoRequest(rawSocket, &saDest);

  // Use select() to wait for data to be received
  nRet = WaitForEchoReply(rawSocket);
  if (nRet == SOCKET_ERROR)
  {
   ReportError("select()");
   break;
  }
  if (!nRet)
  {
   printf("\nTimeOut");
   break;
  }

  // Receive reply
  dwTimeSent = RecvEchoReply(rawSocket, &saSrc, &cTTL);

  // Calculate elapsed time
  dwElapsed = GetTickCount() - dwTimeSent;
  printf("\nReply from: %s: bytes=%d time=%ldms TTL=%d",
               inet_ntoa(saSrc.sin_addr),
      REQ_DATASIZE,
               dwElapsed,
               cTTL);
 }
 printf("\n");
 nRet = closesocket(rawSocket);
 if (nRet == SOCKET_ERROR)
  ReportError("closesocket()");
}


// SendEchoRequest()
// Fill in echo request header
// and send to destination
int SendEchoRequest(SOCKET s,LPSOCKADDR_IN lpstToAddr)
{
 static ECHOREQUEST echoReq;
 static nId = 1;
 static nSeq = 1;
 int nRet;

 // Fill in echo request
 echoReq.icmpHdr.Type  = ICMP_ECHOREQ;
 echoReq.icmpHdr.Code  = 0;
 echoReq.icmpHdr.Checksum = 0;
 echoReq.icmpHdr.ID   = nId++;
 echoReq.icmpHdr.Seq   = nSeq++;

 // Fill in some data to send
 for (nRet = 0; nRet < REQ_DATASIZE; nRet++)
  echoReq.cData[nRet] = ' '+nRet;

 // Save tick count when sent
 echoReq.dwTime    = GetTickCount();

 // Put data in packet and compute checksum
 echoReq.icmpHdr.Checksum = in_cksum((u_short *)&echoReq,
sizeof(ECHOREQUEST));

 // Send the echo request
 nRet = sendto(s,      /* socket */
     (LPSTR)&echoReq,   /* buffer */
     sizeof(ECHOREQUEST),
     0,       /* flags */
     (LPSOCKADDR)lpstToAddr, /* destination */
     sizeof(SOCKADDR_IN));   /* address length */

 if (nRet == SOCKET_ERROR)
  ReportError("sendto()");
 return (nRet);
}


// RecvEchoReply()
// Receive incoming data
// and parse out fields
DWORD RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL)
{
 ECHOREPLY echoReply;
 int nRet;
 int nAddrLen = sizeof(struct sockaddr_in);

 // Receive the echo reply
 nRet = recvfrom(s,     // socket
     (LPSTR)&echoReply, // buffer
     sizeof(ECHOREPLY), // size of buffer
     0,     // flags
     (LPSOCKADDR)lpsaFrom, // From address
     &nAddrLen);   // pointer to address len

 // Check return value
 if (nRet == SOCKET_ERROR)
  ReportError("recvfrom()");

 // return time sent and IP TTL
 *pTTL = echoReply.ipHdr.TTL;
 return(echoReply.echoRequest.dwTime);
}

// What happened?
void ReportError(LPCSTR pWhere)
{
 fprintf(stderr,"\n%s error: %d\n",
  WSAGetLastError());
}


// WaitForEchoReply()
// Use select() to determine when
// data is waiting to be read
int WaitForEchoReply(SOCKET s)
{
 struct timeval Timeout;
 fd_set readfds;

 readfds.fd_count = 1;
 readfds.fd_array[0] = s;
 Timeout.tv_sec = 5;
    Timeout.tv_usec = 0;

 return(select(1, &readfds, NULL, NULL, &Timeout));
}


//
// Mike Muuss' in_cksum() function
// and his comments from the original
// ping program
//
// * Author -
// * Mike Muuss
// * U. S. Army Ballistic Research Laboratory
// * December, 1983

/*
 *   I N _ C K S U M
 *
 * Checksum routine for Internet Protocol family headers (C Version)
 *
 */
u_short in_cksum(u_short *addr, int len)
{
 register int nleft = len;
 register u_short *w = addr;
 register u_short answer;
 register int sum = 0;

 /*
  *  Our algorithm is simple, using a 32 bit accumulator (sum),
  *  we add sequential 16 bit words to it, and at the end, fold
  *  back all the carry bits from the top 16 bits into the lower
  *  16 bits.
  */
 while( nleft > 1 )  {
  sum += *w++;
  nleft -= 2;
 }

 /* mop up an odd byte, if necessary */
 if( nleft == 1 ) {
  u_short u = 0;

  *(u_char *)(&u) = *(u_char *)w ;
  sum += u;
 }

 /*
  * add back carry outs from top 16 bits to low 16 bits
  */
 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
 sum += (sum >> 16);   /* add carry */
 answer = ~sum;    /* truncate to 16 bits */
 return (answer);
}
Technical Details
Message-ID: <419dd94f@newsgroups.borland.com>
Path: arc1-ca.pugleaf.net!g2news1.google.com!news2.google.com!proxad.net!213.200.89.82.MISMATCH!tiscali!newsfeed1.ip.tiscali.net!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail
References: <cnfa3m$5vd$04$1@news.t-online.com> <cnkjuq$jdg$02$1@news.t-online.com>

Show Full Headers
Complete Article Headers
X-Google-Thread: 11508e,b1ce8267f0044ee3
X-Google-Attributes: gid11508e,public
X-Google-Language: ENGLISH,ASCII-7-bit
From: "PaoloItaly" <paolot@FAKETHESPAMMERsirius-es.it>
Newsgroups: borland.public.cppbuilder.internet.socket
References: <cnfa3m$5vd$04$1@news.t-online.com> <cnkjuq$jdg$02$1@news.t-online.com>
Subject: Re: Check for alive status of a TCPIP computer
Date: Fri, 19 Nov 2004 12:29:53 +0100
Lines: 284
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 6.00.2800.1437
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441
NNTP-Posting-Host: 85.32.246.173
Message-ID: <419dd94f@newsgroups.borland.com>
X-Trace: newsgroups.borland.com 1100863823 85.32.246.173 (19 Nov 2004 03:30:23 -0700)
Path: arc1-ca.pugleaf.net!g2news1.google.com!news2.google.com!proxad.net!213.200.89.82.MISMATCH!tiscali!newsfeed1.ip.tiscali.net!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail