|
|
|
@ -30,39 +30,39 @@
|
|
|
|
|
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "fping.h"
|
|
|
|
|
#include "config.h"
|
|
|
|
|
#include "fping.h"
|
|
|
|
|
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <netdb.h>
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
#include <netinet/ip.h>
|
|
|
|
|
#include <netinet/in_systm.h>
|
|
|
|
|
#include <netinet/ip.h>
|
|
|
|
|
#include <netinet/ip_icmp.h>
|
|
|
|
|
#include <netdb.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
|
|
|
|
|
char *ping_buffer_ipv4 = 0;
|
|
|
|
|
char* ping_buffer_ipv4 = 0;
|
|
|
|
|
size_t ping_pkt_size_ipv4;
|
|
|
|
|
|
|
|
|
|
int open_ping_socket_ipv4()
|
|
|
|
|
{
|
|
|
|
|
struct protoent *proto;
|
|
|
|
|
struct protoent* proto;
|
|
|
|
|
int s;
|
|
|
|
|
|
|
|
|
|
/* confirm that ICMP is available on this machine */
|
|
|
|
|
if( ( proto = getprotobyname( "icmp" ) ) == NULL )
|
|
|
|
|
crash_and_burn( "icmp: unknown protocol" );
|
|
|
|
|
if ((proto = getprotobyname("icmp")) == NULL)
|
|
|
|
|
crash_and_burn("icmp: unknown protocol");
|
|
|
|
|
|
|
|
|
|
/* create raw socket for ICMP calls (ping) */
|
|
|
|
|
s = socket( AF_INET, SOCK_RAW, proto->p_proto );
|
|
|
|
|
if( s < 0 ) {
|
|
|
|
|
s = socket(AF_INET, SOCK_RAW, proto->p_proto);
|
|
|
|
|
if (s < 0) {
|
|
|
|
|
/* try non-privileged icmp (works on Mac OSX without privileges, for example) */
|
|
|
|
|
s = socket( AF_INET, SOCK_DGRAM, proto->p_proto );
|
|
|
|
|
if( s < 0 ) {
|
|
|
|
|
errno_crash_and_burn( "can't create socket (must run as root?)" );
|
|
|
|
|
s = socket(AF_INET, SOCK_DGRAM, proto->p_proto);
|
|
|
|
|
if (s < 0) {
|
|
|
|
|
errno_crash_and_burn("can't create socket (must run as root?)");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -70,10 +70,10 @@ int open_ping_socket_ipv4()
|
|
|
|
|
{
|
|
|
|
|
int flags;
|
|
|
|
|
|
|
|
|
|
if((flags = fcntl(s, F_GETFL, 0)) < 0)
|
|
|
|
|
if ((flags = fcntl(s, F_GETFL, 0)) < 0)
|
|
|
|
|
perror("fcntl");
|
|
|
|
|
|
|
|
|
|
if(fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0)
|
|
|
|
|
if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0)
|
|
|
|
|
perror("fcntl");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -84,45 +84,45 @@ void init_ping_buffer_ipv4(size_t ping_data_size)
|
|
|
|
|
{
|
|
|
|
|
/* allocate ping buffer */
|
|
|
|
|
ping_pkt_size_ipv4 = ping_data_size + ICMP_MINLEN;
|
|
|
|
|
ping_buffer_ipv4 = (char *) calloc(1, ping_pkt_size_ipv4);
|
|
|
|
|
if(!ping_buffer_ipv4)
|
|
|
|
|
crash_and_burn( "can't malloc ping packet" );
|
|
|
|
|
ping_buffer_ipv4 = (char*)calloc(1, ping_pkt_size_ipv4);
|
|
|
|
|
if (!ping_buffer_ipv4)
|
|
|
|
|
crash_and_burn("can't malloc ping packet");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void socket_set_src_addr_ipv4(int s, struct in_addr *src_addr)
|
|
|
|
|
void socket_set_src_addr_ipv4(int s, struct in_addr* src_addr)
|
|
|
|
|
{
|
|
|
|
|
struct sockaddr_in sa;
|
|
|
|
|
memset( &sa, 0, sizeof( sa ) );
|
|
|
|
|
memset(&sa, 0, sizeof(sa));
|
|
|
|
|
sa.sin_family = AF_INET;
|
|
|
|
|
sa.sin_addr = *src_addr;
|
|
|
|
|
|
|
|
|
|
if ( bind( s, (struct sockaddr *)&sa, sizeof( sa ) ) < 0 )
|
|
|
|
|
errno_crash_and_burn( "cannot bind source address" );
|
|
|
|
|
if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0)
|
|
|
|
|
errno_crash_and_burn("cannot bind source address");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned short calcsum(unsigned short *buffer, int length)
|
|
|
|
|
unsigned short calcsum(unsigned short* buffer, int length)
|
|
|
|
|
{
|
|
|
|
|
unsigned long sum;
|
|
|
|
|
|
|
|
|
|
/* initialize sum to zero and loop until length (in words) is 0 */
|
|
|
|
|
for (sum=0; length>1; length-=2) /* sizeof() returns number of bytes, we're interested in number of words */
|
|
|
|
|
sum += *buffer++; /* add 1 word of buffer to sum and proceed to the next */
|
|
|
|
|
for (sum = 0; length > 1; length -= 2) /* sizeof() returns number of bytes, we're interested in number of words */
|
|
|
|
|
sum += *buffer++; /* add 1 word of buffer to sum and proceed to the next */
|
|
|
|
|
|
|
|
|
|
/* we may have an extra byte */
|
|
|
|
|
if (length==1)
|
|
|
|
|
sum += (char)*buffer;
|
|
|
|
|
if (length == 1)
|
|
|
|
|
sum += (char)*buffer;
|
|
|
|
|
|
|
|
|
|
sum = (sum >> 16) + (sum & 0xFFFF); /* add high 16 to low 16 */
|
|
|
|
|
sum += (sum >> 16); /* add carry */
|
|
|
|
|
sum += (sum >> 16); /* add carry */
|
|
|
|
|
return ~sum;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int socket_sendto_ping_ipv4(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr)
|
|
|
|
|
int socket_sendto_ping_ipv4(int s, struct sockaddr* saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr)
|
|
|
|
|
{
|
|
|
|
|
struct icmp *icp;
|
|
|
|
|
struct icmp* icp;
|
|
|
|
|
int n;
|
|
|
|
|
|
|
|
|
|
icp = (struct icmp *) ping_buffer_ipv4;
|
|
|
|
|
icp = (struct icmp*)ping_buffer_ipv4;
|
|
|
|
|
|
|
|
|
|
icp->icmp_type = ICMP_ECHO;
|
|
|
|
|
icp->icmp_code = 0;
|
|
|
|
@ -131,12 +131,12 @@ int socket_sendto_ping_ipv4(int s, struct sockaddr *saddr, socklen_t saddr_len,
|
|
|
|
|
icp->icmp_id = htons(icmp_id_nr);
|
|
|
|
|
|
|
|
|
|
if (random_data_flag) {
|
|
|
|
|
for (n = ((char*)&icp->icmp_data - (char *)icp); n < ping_pkt_size_ipv4; ++n) {
|
|
|
|
|
for (n = ((char*)&icp->icmp_data - (char*)icp); n < ping_pkt_size_ipv4; ++n) {
|
|
|
|
|
ping_buffer_ipv4[n] = random() & 0xFF;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
icp->icmp_cksum = calcsum((unsigned short *) icp, ping_pkt_size_ipv4);
|
|
|
|
|
icp->icmp_cksum = calcsum((unsigned short*)icp, ping_pkt_size_ipv4);
|
|
|
|
|
|
|
|
|
|
n = sendto(s, icp, ping_pkt_size_ipv4, 0, saddr, saddr_len);
|
|
|
|
|
|
|
|
|
|