diff --git a/src/fping.c b/src/fping.c index 4304531..233e85b 100644 --- a/src/fping.c +++ b/src/fping.c @@ -260,11 +260,13 @@ char* prog; int ident4 = 0; /* our icmp identity field */ int ident6 = 0; int socket4 = -1; +int socktype4 = -1; int using_sock_dgram4 = 0; #ifndef IPV6 int hints_ai_family = AF_INET; #else int socket6 = -1; +int socktype6 = -1; int hints_ai_family = AF_UNSPEC; #endif @@ -406,9 +408,16 @@ int main(int argc, char** argv) usage(0); } - socket4 = open_ping_socket_ipv4(&using_sock_dgram4); + socket4 = open_ping_socket_ipv4(&socktype4); +#ifdef __linux__ + /* We only treat SOCK_DGRAM differently on Linux, where the IPv4 header + * structure is missing in the message. + */ + using_sock_dgram4 = (socktype4 == SOCK_DGRAM); +#endif + #ifdef IPV6 - socket6 = open_ping_socket_ipv6(); + socket6 = open_ping_socket_ipv6(&socktype6); /* if called (sym-linked) via 'fping6', imply '-6' * for backward compatibility */ if (strstr(prog, "fping6")) { @@ -428,7 +437,7 @@ int main(int argc, char** argv) } optparse_init(&optparse_state, argv); - ident4 = ident6 = getpid() & 0xFFFF; + ident4 = ident6 = htons(getpid() & 0xFFFF); verbose_flag = 1; backoff_flag = 1; opterr = 1; @@ -1023,11 +1032,11 @@ int main(int argc, char** argv) } if (socket4 >= 0) { - socket_set_src_addr_ipv4(socket4, &src_addr, &ident4); + socket_set_src_addr_ipv4(socket4, &src_addr, (socktype4 == SOCK_DGRAM) ? &ident4 : NULL); } #ifdef IPV6 if (socket6 >= 0) { - socket_set_src_addr_ipv6(socket6, &src_addr6, &ident6); + socket_set_src_addr_ipv6(socket6, &src_addr6, (socktype6 == SOCK_DGRAM) ? &ident6 : NULL); } #endif diff --git a/src/fping.h b/src/fping.h index 6c2a84b..bb99f60 100644 --- a/src/fping.h +++ b/src/fping.h @@ -14,12 +14,12 @@ int in_cksum( unsigned short *p, int n ); extern int random_data_flag; /* socket.c */ -int open_ping_socket_ipv4(int *using_sock_dgram); +int open_ping_socket_ipv4(int *socktype); void init_ping_buffer_ipv4(size_t ping_data_size); void socket_set_src_addr_ipv4(int s, struct in_addr *src_addr, int *ident); int socket_sendto_ping_ipv4(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq, uint16_t icmp_id); #ifdef IPV6 -int open_ping_socket_ipv6(); +int open_ping_socket_ipv6(int *socktype); void init_ping_buffer_ipv6(size_t ping_data_size); void socket_set_src_addr_ipv6(int s, struct in6_addr *src_addr, int *ident); int socket_sendto_ping_ipv6(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq, uint16_t icmp_id); diff --git a/src/socket4.c b/src/socket4.c index 9787a9f..d7c4ae3 100644 --- a/src/socket4.c +++ b/src/socket4.c @@ -47,7 +47,7 @@ char* ping_buffer_ipv4 = 0; size_t ping_pkt_size_ipv4; -int open_ping_socket_ipv4(int *using_sock_dgram) +int open_ping_socket_ipv4(int *socktype) { struct protoent* proto; int s; @@ -56,23 +56,16 @@ int open_ping_socket_ipv4(int *using_sock_dgram) if ((proto = getprotobyname("icmp")) == NULL) crash_and_burn("icmp: unknown protocol"); - *using_sock_dgram = 0; - /* create raw socket for ICMP calls (ping) */ - s = socket(AF_INET, SOCK_RAW, proto->p_proto); + *socktype = SOCK_RAW; + s = socket(AF_INET, *socktype, 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); + *socktype = SOCK_DGRAM; + s = socket(AF_INET, *socktype, proto->p_proto); if (s < 0) { return -1; } - -#ifdef __linux__ - /* We only treat SOCK_DGRAM differently on Linux, where the IPv4 header - * structure is missing in the message. - */ - *using_sock_dgram = 1; -#endif } /* Make sure that we use non-blocking IO */ @@ -109,12 +102,14 @@ void socket_set_src_addr_ipv4(int s, struct in_addr* src_addr, int *ident) if (bind(s, (struct sockaddr*)&sa, len) < 0) errno_crash_and_burn("cannot bind source address"); - memset(&sa, 0, len); - if (getsockname(s, (struct sockaddr *)&sa, &len) < 0) - errno_crash_and_burn("can't get ICMP socket identity"); + if (ident) { + memset(&sa, 0, len); + if (getsockname(s, (struct sockaddr *)&sa, &len) < 0) + errno_crash_and_burn("can't get ICMP socket identity"); - if (sa.sin_port) - *ident = sa.sin_port; + if (sa.sin_port) + *ident = sa.sin_port; + } } unsigned short calcsum(unsigned short* buffer, int length) diff --git a/src/socket6.c b/src/socket6.c index 433e0e0..9ba42a3 100644 --- a/src/socket6.c +++ b/src/socket6.c @@ -46,7 +46,7 @@ char* ping_buffer_ipv6 = 0; size_t ping_pkt_size_ipv6; -int open_ping_socket_ipv6() +int open_ping_socket_ipv6(int *socktype) { struct protoent* proto; int s; @@ -56,10 +56,12 @@ int open_ping_socket_ipv6() crash_and_burn("icmp: unknown protocol"); /* create raw socket for ICMP calls (ping) */ - s = socket(AF_INET6, SOCK_RAW, proto->p_proto); + *socktype = SOCK_RAW; + s = socket(AF_INET6, *socktype, proto->p_proto); if (s < 0) { /* try non-privileged icmp (works on Mac OSX without privileges, for example) */ - s = socket(AF_INET6, SOCK_DGRAM, proto->p_proto); + *socktype = SOCK_DGRAM; + s = socket(AF_INET6, *socktype, proto->p_proto); if (s < 0) { return -1; } @@ -99,12 +101,14 @@ void socket_set_src_addr_ipv6(int s, struct in6_addr* src_addr, int *ident) if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0) errno_crash_and_burn("cannot bind source address"); - memset(&sa, 0, len); - if (getsockname(s, (struct sockaddr *)&sa, &len) < 0) - errno_crash_and_burn("can't get ICMP socket identity"); + if (ident) { + memset(&sa, 0, len); + if (getsockname(s, (struct sockaddr *)&sa, &len) < 0) + errno_crash_and_burn("can't get ICMP socket identity"); - if (sa.sin6_port) - *ident = sa.sin6_port; + if (sa.sin6_port) + *ident = sa.sin6_port; + } } int socket_sendto_ping_ipv6(int s, struct sockaddr* saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr)