Find the answer to your Linux question:
Results 1 to 4 of 4
Hello Everyone, I'm trying to implement a mini ping. just test if another host is still up. The code I have so far only works if I ping my localhost ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Apr 2006
    Posts
    2

    Implementing ping in C++???


    Hello Everyone,

    I'm trying to implement a mini ping. just test if another host is still up. The code I have so far only works if I ping my localhost but nothing else. I don't know what I'm doing wrong.

    When I send an echo request to localhost, first I receive an echo request (strange!!) and the second time I receive the echo reply correctly. But when I echo any other host, I don't receive anything. Here is my code, Please HELP



    Code:
    #include <arpa/inet.h>
    #include <sys/types.h>
    #include <sys/param.h>
    #include <sys/socket.h>
    #include <sys/file.h>
    #include <sys/time.h>
    #include <netinet/in_systm.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <netinet/ip_icmp.h>
    //#include <netinet/ip_var.h>
    #include <netdb.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <ctype.h>
    //#include <errno.h>
    #include <string.h>
    #include <stdlib.h>
    #include <iostream>
    
    #define	DEFDATALEN	(64-8)	/* default data length */
    #define	MAXIPLEN	60
    #define	MAXICMPLEN	76
    #define	MAXPACKET	(65536 - 60 - 8)/* max packet size */
    
    int ping(string target)
    {
    
            int s, i, cc, packlen, datalen = DEFDATALEN;
    	struct hostent *hp;
    	struct sockaddr_in *to, *from;
    	struct protoent	*proto;
    	struct ip *ip;
    	u_char *packet, outpack[MAXPACKET];
    	char hnamebuf[MAXHOSTNAMELEN];
    	string hostname;
    	struct icmp *icp;
    	int ret, fromlen, hlen;
    	fd_set rfds;
    	struct timeval tv;
    	int retval;
    	struct timeval start, end;
    	int start_t, end_t;
    	bool cont = true;
    
    	to->sin_family = AF_INET;
    
    	// try to convert as dotted decimal address, else if that fails assume it's a hostname
    	to->sin_addr.s_addr = inet_addr(target.c_str());
    	if (to->sin_addr.s_addr != (u_int)-1)
    		hostname = target;
    	else 
    	{
    		hp = gethostbyname(target.c_str());
    		if (!hp)
    		{
    			cerr << "unknown host "<< target << endl;
    			return -1;
    		}
    		to->sin_family = hp->h_addrtype;
    		bcopy(hp->h_addr, (caddr_t)&to->sin_addr, hp->h_length);
    		strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1);
    		hostname = hnamebuf;
    	}
    	packlen = datalen + MAXIPLEN + MAXICMPLEN;
    	if ( (packet = (u_char *)malloc((u_int)packlen)) == NULL)
    	{
    		cerr << "malloc error\n";
    		return -1;
    	}
    
    	if ( (proto = getprotobyname("icmp")) == NULL)
    	{
    		cerr << "unknown protocol icmp" << endl;
    		return -1;
    	}
    
    	if ( (s = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0)
    	{
    		perror("socket");	/* probably not running as superuser */
    		return -1;
    	}
    
    	icp = (struct icmp *)outpack;
    	icp->icmp_type = ICMP_ECHO;
    	icp->icmp_code = 0;
    	icp->icmp_seq = 12345;	/* seq and id must be reflected */
    	icp->icmp_id = getpid();
    
    	cc = datalen + 8;
    
    	gettimeofday(&start, NULL);
    
    	i = sendto(s, (char *)outpack, cc, 0, (struct sockaddr*)to, (socklen_t)sizeof(struct sockaddr_in));
    	if (i < 0 || i != cc)
    	{
    		if (i < 0)
    			perror("sendto error");
    		cout << "wrote " << hostname << " " <<  cc << " chars, ret= " << i << endl;
    	}
    	
    	// Watch stdin (fd 0) to see when it has input.
    	FD_ZERO(&rfds);
    	FD_SET(s, &rfds);
    	// Wait up to one seconds.
    	tv.tv_sec = 1;
    	tv.tv_usec = 0;
    
    	while(cont)
    	{
    		retval = select(s+1, &rfds, NULL, NULL, &tv);
    		if (retval == -1)
    		{
    			perror("select()");
    			return -1;
    		}
    		else if (retval)
    		{
    			fromlen = sizeof(sockaddr_in);
    			if ( (ret = recvfrom(s, (char *)packet, packlen, 0,(struct sockaddr *)from, (socklen_t*)&fromlen)) < 0)
    			{
    				perror("recvfrom error");
    				return -1;
    			}
    
    			// Check the IP header
    			ip = (struct ip *)((char*)packet); 
    			hlen = sizeof( struct ip ); 
    			if (ret < (hlen + ICMP_MINLEN)) 
    			{ 
    				cerr << "packet too short (" << ret  << " bytes) from " << hostname << endl;;
    				return -1; 
    			} 
    
    			// Now the ICMP part 
    			icp = (struct icmp *)(packet + hlen); 
    			if (icp->icmp_type == ICMP_ECHOREPLY)
    			{
    				cout << "Recv: echo reply"<< endl;
    				if (icp->icmp_seq != 12345)
    				{
    					cout << "received sequence # " << icp->icmp_seq << endl;
    					continue;
    				}
    				if (icp->icmp_id != getpid())
    				{
    					cout << "received id " << icp->icmp_id << endl;
    					continue;
    				}
    				cont = false;
    			}
    			else
    			{
    				cout << "Recv: not an echo reply" << endl;
    				continue;
    			}
    	
    			gettimeofday(&end, NULL);
    			end_t = 1000000*(end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec);
    
    			if(end_t < 1)
    				end_t = 1;
    
    			cout << "Elapsed time = " << end_t << " usec" << endl;
    			return end_t;
    		}
    		else
    		{
    			cout << "No data within one seconds.\n";
    			return 0;
    		}
    	}
    }
    
    int main(int argc, char** argv)
    {
    	if (argc != 2)
    	{
    		cout << "Usage: ping hostname" << endl;
    		exit(1);
    	}
    	cout << "ping returned " << ping(argv[1]) << endl;
    	return 0;
    }

  2. #2
    Just Joined!
    Join Date
    May 2006
    Posts
    1
    Did you figure it out, what was wrong?

  3. #3
    Just Joined!
    Join Date
    Oct 2006
    Posts
    2

    This code work for me...

    Code:
    #include <arpa/inet.h>
    #include <sys/types.h>
    #include <sys/param.h>
    #include <sys/socket.h>
    #include <sys/file.h>
    #include <sys/time.h>
    
    #include <netinet/in_systm.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <netinet/ip_icmp.h>
    //#include <netinet/ip_var.h>
    #include <netdb.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <ctype.h>
    //#include <errno.h>
    #include <string.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <iostream>
    
    using namespace std;
    
    uint16_t in_cksum(uint16_t *addr, unsigned len);
    
    #define	DEFDATALEN	(64-ICMP_MINLEN)	/* default data length */
    #define	MAXIPLEN	60
    #define	MAXICMPLEN	76
    #define	MAXPACKET	(65536 - 60 - ICMP_MINLEN)/* max packet size */
    
    int ping(string target)
    {
    
            int s, i, cc, packlen, datalen = DEFDATALEN;
    	struct hostent *hp;
    	struct sockaddr_in to, from;
    	//struct protoent	*proto;
    	struct ip *ip;
    	u_char *packet, outpack[MAXPACKET];
    	char hnamebuf[MAXHOSTNAMELEN];
    	string hostname;
    	struct icmp *icp;
    	int ret, fromlen, hlen;
    	fd_set rfds;
    	struct timeval tv;
    	int retval;
    	struct timeval start, end;
    	int /*start_t, */end_t;
    	bool cont = true;
    
    	to.sin_family = AF_INET;
    
    	// try to convert as dotted decimal address, else if that fails assume it's a hostname
    	to.sin_addr.s_addr = inet_addr(target.c_str());
    	if (to.sin_addr.s_addr != (u_int)-1)
    		hostname = target;
    	else 
    	{
    		hp = gethostbyname(target.c_str());
    		if (!hp)
    		{
    			cerr << "unknown host "<< target << endl;
    			return -1;
    		}
    		to.sin_family = hp->h_addrtype;
    		bcopy(hp->h_addr, (caddr_t)&to.sin_addr, hp->h_length);
    		strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1);
    		hostname = hnamebuf;
    	}
    	packlen = datalen + MAXIPLEN + MAXICMPLEN;
    	if ( (packet = (u_char *)malloc((u_int)packlen)) == NULL)
    	{
    		cerr << "malloc error\n";
    		return -1;
    	}
    
    /*
    	if ( (proto = getprotobyname("icmp")) == NULL)
    	{
    		cerr << "unknown protocol icmp" << endl;
    		return -1;
    	}
    */
    	if ( (s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
    	{
    		perror("socket");	/* probably not running as superuser */
    		return -1;
    	}
    
    	icp = (struct icmp *)outpack;
    	icp->icmp_type = ICMP_ECHO;
    	icp->icmp_code = 0;
    	icp->icmp_cksum = 0;
    	icp->icmp_seq = 12345;	/* seq and id must be reflected */
    	icp->icmp_id = getpid();
    
    
    	cc = datalen + ICMP_MINLEN;
    	icp->icmp_cksum = in_cksum((unsigned short *)icp,cc);
    
    	gettimeofday(&start, NULL);
    
    	i = sendto(s, (char *)outpack, cc, 0, (struct sockaddr*)&to, (socklen_t)sizeof(struct sockaddr_in));
    	if (i < 0 || i != cc)
    	{
    		if (i < 0)
    			perror("sendto error");
    		cout << "wrote " << hostname << " " <<  cc << " chars, ret= " << i << endl;
    	}
    	
    	// Watch stdin (fd 0) to see when it has input.
    	FD_ZERO(&rfds);
    	FD_SET(s, &rfds);
    	// Wait up to one seconds.
    	tv.tv_sec = 1;
    	tv.tv_usec = 0;
    
    	while(cont)
    	{
    		retval = select(s+1, &rfds, NULL, NULL, &tv);
    		if (retval == -1)
    		{
    			perror("select()");
    			return -1;
    		}
    		else if (retval)
    		{
    			fromlen = sizeof(sockaddr_in);
    			if ( (ret = recvfrom(s, (char *)packet, packlen, 0,(struct sockaddr *)&from, (socklen_t*)&fromlen)) < 0)
    			{
    				perror("recvfrom error");
    				return -1;
    			}
    
    			// Check the IP header
    			ip = (struct ip *)((char*)packet); 
    			hlen = sizeof( struct ip ); 
    			if (ret < (hlen + ICMP_MINLEN)) 
    			{ 
    				cerr << "packet too short (" << ret  << " bytes) from " << hostname << endl;;
    				return -1; 
    			} 
    
    			// Now the ICMP part 
    			icp = (struct icmp *)(packet + hlen); 
    			if (icp->icmp_type == ICMP_ECHOREPLY)
    			{
    				cout << "Recv: echo reply"<< endl;
    				if (icp->icmp_seq != 12345)
    				{
    					cout << "received sequence # " << icp->icmp_seq << endl;
    					continue;
    				}
    				if (icp->icmp_id != getpid())
    				{
    					cout << "received id " << icp->icmp_id << endl;
    					continue;
    				}
    				cont = false;
    			}
    			else
    			{
    				cout << "Recv: not an echo reply" << endl;
    				continue;
    			}
    	
    			gettimeofday(&end, NULL);
    			end_t = 1000000*(end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec);
    
    			if(end_t < 1)
    				end_t = 1;
    
    			cout << "Elapsed time = " << end_t << " usec" << endl;
    			return end_t;
    		}
    		else
    		{
    			cout << "No data within one seconds.\n";
    			return 0;
    		}
    	}
    	return 0;
    }
    
    uint16_t in_cksum(uint16_t *addr, unsigned len)
    {
      uint16_t answer = 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.
       */
      uint32_t sum = 0;
      while (len > 1)  {
        sum += *addr++;
        len -= 2;
      }
    
      // mop up an odd byte, if necessary
      if (len == 1) {
        *(unsigned char *)&answer = *(unsigned char *)addr ;
        sum += answer;
      }
    
      // add back carry outs from top 16 bits to low 16 bits
      sum = (sum >> 16) + (sum & 0xffff); // add high 16 to low 16
      sum += (sum >> 16); // add carry
      answer = ~sum; // truncate to 16 bits
      return answer;
    }
    
    int main(int argc, char** argv)
    {
    	if (argc != 2)
    	{
    		cout << "Usage: ping hostname" << endl;
    		exit(1);
    	}
    	cout << "ping returned " << ping(argv[1]) << endl;
    	return 0;
    }

  4. $spacer_open
    $spacer_close
  5. #4
    Just Joined!
    Join Date
    Aug 2008
    Posts
    2
    I am working on trying it out. This has to go on a set top box so have to make a frew changes for our limited space concerns. Thanks for the example.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •