Angel.King.47
Angel.King.47

Reputation: 7994

Ping Function fails after 1020 tries

I have a program that needs to constantly ping a device

However this ping function fails exactlly after 1020 tries

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;
}

If i run the ping function twice it fails at exactly half 510. And the pattern is exact. Here is the output after the 1020 mark

socket: Too many open files 
ping returned -1

Im pretty bad at network programming but i dont even know where to begin for the above code.

Am i missing a close somewhere?

The ping function is taken from: http://www.linuxforums.org/forum/networking/60389-implementing-ping-c.html

Edit: Running Ubuntu 10.10, same issue on Fedora 13

Thanks

Upvotes: 2

Views: 752

Answers (3)

Marcus Borkenhagen
Marcus Borkenhagen

Reputation: 6656

When allocating resources you need to make sure to free them.

As unwind pointed out, you have to close sockets.

But you also need to free the allocated memory (malloc, line 40-ish).

You should consider using memcpy instead of bcopy.

Upvotes: 4

valdo
valdo

Reputation: 12943

Agree with "unwind".

Note that you run a function, not a program. Hence your process is still alive, and all the memory/resource leaks are not automatically freed.

As a general rule, if you see in the code a call to a socket function without the corresponding closesocket - this must always scratch your eyes!

Upvotes: 1

unwind
unwind

Reputation: 399813

Yes, you need to close the socket with close(s); before exiting the function.

Upvotes: 5

Related Questions