Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best method to ping in c++ under linux?

Tags:

c++

linux

I have to call ping from c++ code.I'd like to easily read the output for further utilizations.

I have come up with two solutions:

  • use a fork and a pipe, redirect ping output to the pipe and then parse it
  • find a library suited for the purpose to use a ping(ip_addresss) function directly

I'd like the latter but i didn't find anything that was clearly a standard solution.

How would you do it ?

like image 860
nios Avatar asked Nov 24 '08 08:11

nios


People also ask

What is ping C command?

Some ping command options relevant to performance tuning are as follows: -c. Specifies the number of packets. This option is useful when you get an IP trace log. You can capture a minimum of ping packets.

Does Linux use ICMP for ping?

Introduction to Linux Ping. In the Linux ecosystem, the ping is used to check whether the host is reachable or not over the internet protocol. It is working on the ICMP protocol i.e. Internet Control Message Protocol.


3 Answers

From the educational point of view invoking an external binary is very inadvisable. Especially for a simple task such as sending an ICMP echo request, you should learn a bit of socket.

like image 155
Nicola Bonelli Avatar answered Sep 21 '22 12:09

Nicola Bonelli


#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip_icmp.h>


#define PACKETSIZE  64
struct packet
{
    struct icmphdr hdr;
    char msg[PACKETSIZE-sizeof(struct icmphdr)];
};

int pid=-1;
struct protoent *proto=NULL;
int cnt=1;

/*--------------------------------------------------------------------*/
/*--- checksum - standard 1s complement checksum                   ---*/
/*--------------------------------------------------------------------*/
unsigned short checksum(void *b, int len)
{
    unsigned short *buf = b;
    unsigned int sum=0;
    unsigned short result;

    for ( sum = 0; len > 1; len -= 2 )
        sum += *buf++;
    if ( len == 1 )
        sum += *(unsigned char*)buf;
    sum = (sum >> 16) + (sum & 0xFFFF);
    sum += (sum >> 16);
    result = ~sum;
    return result;
}


/*--------------------------------------------------------------------*/
/*--- ping - Create message and send it.                           ---*/
/*    return 0 is ping Ok, return 1 is ping not OK.                ---*/
/*--------------------------------------------------------------------*/
int ping(char *adress)
{
    const int val=255;
    int i, sd;
    struct packet pckt;
    struct sockaddr_in r_addr;
    int loop;
    struct hostent *hname;
    struct sockaddr_in addr_ping,*addr;

    pid = getpid();
    proto = getprotobyname("ICMP");
    hname = gethostbyname(adress);
    bzero(&addr_ping, sizeof(addr_ping));
    addr_ping.sin_family = hname->h_addrtype;
    addr_ping.sin_port = 0;
    addr_ping.sin_addr.s_addr = *(long*)hname->h_addr;

    addr = &addr_ping;

    sd = socket(PF_INET, SOCK_RAW, proto->p_proto);
    if ( sd < 0 )
    {
        perror("socket");
        return 1;
    }
    if ( setsockopt(sd, SOL_IP, IP_TTL, &val, sizeof(val)) != 0)
    {
        perror("Set TTL option");
        return 1;
    }
    if ( fcntl(sd, F_SETFL, O_NONBLOCK) != 0 )
    {
        perror("Request nonblocking I/O");
        return 1;
    }

    for (loop=0;loop < 10; loop++)
    {

        int len=sizeof(r_addr);

        if ( recvfrom(sd, &pckt, sizeof(pckt), 0, (struct sockaddr*)&r_addr, &len) > 0 )
        {
            return 0;
        }

        bzero(&pckt, sizeof(pckt));
        pckt.hdr.type = ICMP_ECHO;
        pckt.hdr.un.echo.id = pid;
        for ( i = 0; i < sizeof(pckt.msg)-1; i++ )
            pckt.msg[i] = i+'0';
        pckt.msg[i] = 0;
        pckt.hdr.un.echo.sequence = cnt++;
        pckt.hdr.checksum = checksum(&pckt, sizeof(pckt));
        if ( sendto(sd, &pckt, sizeof(pckt), 0, (struct sockaddr*)addr, sizeof(*addr)) <= 0 )
            perror("sendto");

        usleep(300000);

    }

    return 1;
}

/*--------------------------------------------------------------------*/
/*--- main - look up host and start ping processes.                ---*/
/*--------------------------------------------------------------------*/
int main(int argc, char *argv[])
{

    if (ping("www.google.com"))
        printf("Ping is not OK. \n");
    else
        printf("Ping is OK. \n");


    return 0;
}
like image 35
omeraygor Avatar answered Sep 20 '22 12:09

omeraygor


I would go with your first option. Linux is built around the concept of having small, specialized apps which do one thing really well, communicating with pipes. Your app shouldn't include a library to implement ping, since there is already a built-in command to do it, and it works very well!

like image 45
e.James Avatar answered Sep 21 '22 12:09

e.James