Welcome to Linux Forums! With a comprehensive Linux Forum, information on various types of Linux software and many Linux Reviews articles, we have all the knowledge you need a click away, or accessible via our knowledgeable members.
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;
}
A Complete Beginner's Manual for Ubuntu 10.04 (Lucid Lynx)
Getting Started with Ubuntu 10.04 (Lucid Lynx) is a comprehensive beginners guide for the Ubuntu operating system; it features comprehensive guides, How Tos and information on anything you need to know after first installing Ubuntu. subscribe
The Incredible Guide to NEW Ubuntu (Karmic Koala)
There are a lot of people still stuck with Windows because it's the ‘easier alternative'. Linux is both cheaper and more versatile than Microsoft's operating system, but the learning curve has frightened off many people. subscribe
The GNU/Linux Advanced Administration
The GNU/Linux systems have reached an important level of maturity, allowing to integrate them in almost any kind of work environment, from a desktop PC to the sever facilities of a big company. subscribe
A Newbie's Getting Started Guide to Linux
Learn the basics of the Linux operating systems. Get to know what it is all about, and familiarize yourself with the practical side. Basically, if you're a complete Linux newbie and looking for a quick and easy guide to get you started this is it. subscribe