579 |
|
|
580 |
/** |
/** |
581 |
* Create a ICMP socket against hostname, send echo and wait for response. |
* Create a ICMP socket against hostname, send echo and wait for response. |
582 |
|
* The 'count' echo requests is send and we expect at least one reply. |
583 |
* @param hostname The host to open a socket at |
* @param hostname The host to open a socket at |
584 |
* @param timeout If response will not come within timeout seconds abort |
* @param timeout If response will not come within timeout seconds abort |
585 |
|
* @param count How many pings to send |
586 |
* @return response time on succes, -1 on error |
* @return response time on succes, -1 on error |
587 |
*/ |
*/ |
588 |
double icmp_echo(const char *hostname, int timeout) { |
double icmp_echo(const char *hostname, int timeout, int count) { |
589 |
|
|
590 |
struct hostent *hp; |
struct hostent *hp; |
591 |
struct sockaddr_in sin; |
struct sockaddr_in sin; |
593 |
#ifdef HAVE_SOL_IP |
#ifdef HAVE_SOL_IP |
594 |
struct iphdr *iphdrin; |
struct iphdr *iphdrin; |
595 |
struct icmphdr *icmphdrin= NULL; |
struct icmphdr *icmphdrin= NULL; |
596 |
struct icmphdr *icmphdrout= NULL; |
struct icmphdr *icmphdrout[count]; |
597 |
#else |
#else |
598 |
struct ip *iphdrin; |
struct ip *iphdrin; |
599 |
struct icmp *icmphdrin= NULL; |
struct icmp *icmphdrin= NULL; |
600 |
struct icmp *icmphdrout= NULL; |
struct icmp *icmphdrout[count]; |
601 |
#endif |
#endif |
602 |
size_t size; |
size_t size; |
603 |
fd_set rset; |
fd_set rset; |
604 |
|
int i; |
605 |
int s; |
int s; |
606 |
int n= 0; |
int n= 0; |
607 |
int sol_ip; |
int sol_ip; |
608 |
unsigned ttl= 255; |
unsigned ttl= 255; |
609 |
char buf[STRLEN]; |
char buf[STRLEN]; |
610 |
struct timeval tv; |
struct timeval tv; |
611 |
struct timeval t1; |
struct timeval t1[count]; |
612 |
struct timeval t2; |
struct timeval t2; |
613 |
double response= -1; |
double response= -1; |
614 |
|
|
638 |
tv.tv_sec= timeout; |
tv.tv_sec= timeout; |
639 |
tv.tv_usec= 0; |
tv.tv_usec= 0; |
640 |
|
|
641 |
NEW(icmphdrout); |
for(i=0; i<count; i++) { |
642 |
|
NEW(icmphdrout[i]); |
643 |
#ifdef HAVE_SOL_IP |
#ifdef HAVE_SOL_IP |
644 |
icmphdrout->code= 0; |
icmphdrout[i]->code= 0; |
645 |
icmphdrout->type= ICMP_ECHO; |
icmphdrout[i]->type= ICMP_ECHO; |
646 |
icmphdrout->un.echo.id= getpid(); |
icmphdrout[i]->un.echo.id= getpid(); |
647 |
icmphdrout->un.echo.sequence= 0; |
icmphdrout[i]->un.echo.sequence= i; |
648 |
icmphdrout->checksum= checksum_ip((unsigned char *)icmphdrout, ICMP_SIZE); |
icmphdrout[i]->checksum= checksum_ip((unsigned char *)icmphdrout[i], ICMP_SIZE); |
649 |
#else |
#else |
650 |
icmphdrout->icmp_code= 0; |
icmphdrout[i]->icmp_code= 0; |
651 |
icmphdrout->icmp_type= ICMP_ECHO; |
icmphdrout[i]->icmp_type= ICMP_ECHO; |
652 |
icmphdrout->icmp_id= getpid(); |
icmphdrout[i]->icmp_id= getpid(); |
653 |
icmphdrout->icmp_seq= 0; |
icmphdrout[i]->icmp_seq= i; |
654 |
icmphdrout->icmp_cksum= checksum_ip((unsigned char *)icmphdrout, ICMP_SIZE); |
icmphdrout[i]->icmp_cksum= checksum_ip((unsigned char *)icmphdrout[i], ICMP_SIZE); |
655 |
#endif |
#endif |
656 |
sout.sin_family= AF_INET; |
sout.sin_family= AF_INET; |
657 |
sout.sin_port= 0; |
sout.sin_port= 0; |
658 |
memcpy(&sout.sin_addr, hp->h_addr, hp->h_length); |
memcpy(&sout.sin_addr, hp->h_addr, hp->h_length); |
659 |
|
|
660 |
/* Get time of connection attempt beginning */ |
/* Get time of particular connection attempt beginning */ |
661 |
gettimeofday(&t1, NULL); |
gettimeofday(&t1[i], NULL); |
662 |
|
|
663 |
do { |
do { |
664 |
n= sendto(s, (char *)icmphdrout, ICMP_SIZE, 0, |
n= sendto(s, (char *)icmphdrout[i], ICMP_SIZE, 0, |
665 |
(struct sockaddr *)&sout, sizeof(struct sockaddr)); |
(struct sockaddr *)&sout, sizeof(struct sockaddr)); |
666 |
} while(n == -1 && errno == EINTR); |
} while(n == -1 && errno == EINTR); |
667 |
|
} |
668 |
|
|
669 |
do { |
do { |
670 |
|
|
685 |
} while(n == -1 && errno == EINTR); |
} while(n == -1 && errno == EINTR); |
686 |
|
|
687 |
if(n < 0) |
if(n < 0) |
688 |
goto error; |
goto error; |
689 |
|
|
690 |
|
for(i=0; i<count; i++) { |
691 |
#ifdef HAVE_SOL_IP |
#ifdef HAVE_SOL_IP |
692 |
iphdrin= (struct iphdr *)buf; |
iphdrin= (struct iphdr *)buf; |
693 |
icmphdrin= (struct icmphdr *)(buf + iphdrin->ihl * 4); |
icmphdrin= (struct icmphdr *)(buf + iphdrin->ihl * 4); |
694 |
if( (icmphdrin->un.echo.id == icmphdrout->un.echo.id) && |
if( (icmphdrin->un.echo.id == icmphdrout[i]->un.echo.id) && |
695 |
(icmphdrin->type == ICMP_ECHOREPLY) && |
(icmphdrin->type == ICMP_ECHOREPLY) && |
696 |
(icmphdrin->un.echo.sequence == icmphdrout->un.echo.sequence) ) { |
(icmphdrin->un.echo.sequence == icmphdrout[i]->un.echo.sequence) ) { |
697 |
#else |
#else |
698 |
iphdrin= (struct ip *)buf; |
iphdrin= (struct ip *)buf; |
699 |
icmphdrin= (struct icmp *)(buf + iphdrin->ip_hl * 4); |
icmphdrin= (struct icmp *)(buf + iphdrin->ip_hl * 4); |
700 |
if( (icmphdrin->icmp_id == icmphdrout->icmp_id) && |
if( (icmphdrin->icmp_id == icmphdrout[i]->icmp_id) && |
701 |
(icmphdrin->icmp_type == ICMP_ECHOREPLY) && |
(icmphdrin->icmp_type == ICMP_ECHOREPLY) && |
702 |
(icmphdrin->icmp_seq == icmphdrout->icmp_seq) ) { |
(icmphdrin->icmp_seq == icmphdrout[i]->icmp_seq) ) { |
703 |
#endif |
#endif |
704 |
|
|
705 |
/* Get time of connection attempt finish */ |
/* Get time of connection attempt finish */ |
706 |
gettimeofday(&t2, NULL); |
gettimeofday(&t2, NULL); |
707 |
|
|
708 |
/* Get the response time */ |
/* Get the response time */ |
709 |
response= (double)(t2.tv_sec - t1.tv_sec) + |
response= (double)(t2.tv_sec - t1[i].tv_sec) + |
710 |
(double)(t2.tv_usec - t1.tv_usec)/1000000; |
(double)(t2.tv_usec - t1[i].tv_usec)/1000000; |
|
break; |
|
711 |
|
|
712 |
|
goto done; |
713 |
|
} |
714 |
} |
} |
|
|
|
715 |
} while(TRUE); |
} while(TRUE); |
716 |
|
|
717 |
error: |
error: |
718 |
FREE(icmphdrout); |
done: |
719 |
|
for(i=0; i<count; i++) { |
720 |
|
FREE(icmphdrout[i]); |
721 |
|
} |
722 |
close_socket(s); |
close_socket(s); |
723 |
|
|
724 |
return response; |
return response; |