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
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")) {
}
optparse_init(&optparse_state, argv);
- ident4 = ident6 = getpid() & 0xFFFF;
+ ident4 = ident6 = htons(getpid() & 0xFFFF);
verbose_flag = 1;
backoff_flag = 1;
opterr = 1;
}
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
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);
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;
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 */
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)
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;
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;
}
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)