HOST_ENTRY* ev_last;
char* prog;
-int ident; /* our pid */
+int ident4 = 0; /* our icmp identity field */
int socket4 = -1;
#ifndef IPV6
int hints_ai_family = AF_INET;
#else
+int ident6 = 0;
int socket6 = -1;
int hints_ai_family = AF_UNSPEC;
#endif
}
#endif
+ memset(&src_addr, 0, sizeof(src_addr));
+#ifdef IPV6
+ memset(&src_addr6, 0, sizeof(src_addr6));
+#endif
+
if ((uid = getuid())) {
/* drop privileges */
if (setuid(getuid()) == -1)
}
optparse_init(&optparse_state, argv);
- ident = getpid() & 0xFFFF;
+ ident4 = ident6 = getpid() & 0xFFFF;
verbose_flag = 1;
backoff_flag = 1;
opterr = 1;
exit(num_noaddress ? 2 : 1);
}
- if (src_addr_set && socket4 >= 0) {
- socket_set_src_addr_ipv4(socket4, &src_addr);
+ if (socket4 >= 0) {
+ socket_set_src_addr_ipv4(socket4, &src_addr, &ident4);
}
#ifdef IPV6
- if (src_addr6_set && socket6 >= 0) {
- socket_set_src_addr_ipv6(socket6, &src_addr6);
+ if (socket6 >= 0) {
+ socket_set_src_addr_ipv6(socket6, &src_addr6, &ident6);
}
#endif
#endif /* DEBUG || _DEBUG */
if (h->saddr.ss_family == AF_INET && socket4 >= 0) {
- n = socket_sendto_ping_ipv4(socket4, (struct sockaddr*)&h->saddr, h->saddr_len, myseq, ident);
+ n = socket_sendto_ping_ipv4(socket4, (struct sockaddr*)&h->saddr, h->saddr_len, myseq, ident4);
}
#ifdef IPV6
else if (h->saddr.ss_family == AF_INET6 && socket6 >= 0) {
- n = socket_sendto_ping_ipv6(socket6, (struct sockaddr*)&h->saddr, h->saddr_len, myseq, ident);
+ n = socket_sendto_ping_ipv6(socket6, (struct sockaddr*)&h->saddr, h->saddr_len, myseq, ident6);
}
#endif
else {
sent_icmp = (struct icmp*)(reply_buf + hlen + ICMP_MINLEN + sizeof(struct ip));
- if (sent_icmp->icmp_type != ICMP_ECHO || ntohs(sent_icmp->icmp_id) != ident) {
+ if (sent_icmp->icmp_type != ICMP_ECHO || sent_icmp->icmp_id != ident4) {
/* not caused by us */
return 0;
}
return 0;
}
- *id = ntohs(icp->icmp_id);
+ *id = icp->icmp_id;
*seq = ntohs(icp->icmp_seq);
return 1;
sent_icmp = (struct icmp6_hdr*)(reply_buf + sizeof(struct icmp6_hdr) + sizeof(struct ip));
- if (sent_icmp->icmp6_type != ICMP_ECHO || ntohs(sent_icmp->icmp6_id) != ident) {
+ if (sent_icmp->icmp6_type != ICMP_ECHO || sent_icmp->icmp6_id != ident6) {
/* not caused by us */
return 0;
}
return 0;
}
- *id = ntohs(icp->icmp6_id);
+ *id = icp->icmp6_id;
*seq = ntohs(icp->icmp6_seq);
return 1;
&seq)) {
return 1;
}
+ if (id != ident4) {
+ return 1; /* packet received, but not the one we are looking for! */
+ }
}
#ifdef IPV6
else if (response_addr.ss_family == AF_INET6) {
&seq)) {
return 1;
}
+ if (id != ident6) {
+ return 1; /* packet received, but not the one we are looking for! */
+ }
}
#endif
else {
return 1;
}
- if (id != ident) {
- return 1; /* packet received, but not the one we are looking for! */
- }
-
seqmap_value = seqmap_fetch(seq, ¤t_time);
if (seqmap_value == NULL) {
return 1;
/* socket.c */
int open_ping_socket_ipv4();
void init_ping_buffer_ipv4(size_t ping_data_size);
-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, 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();
void init_ping_buffer_ipv6(size_t ping_data_size);
-void socket_set_src_addr_ipv6(int s, struct in6_addr *src_addr);
+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);
#endif
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, int *ident)
{
struct sockaddr_in sa;
- memset(&sa, 0, sizeof(sa));
+ socklen_t len = sizeof(sa);
+
+ memset(&sa, 0, len);
sa.sin_family = AF_INET;
sa.sin_addr = *src_addr;
-
- if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0)
+ 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 (sa.sin_port)
+ *ident = sa.sin_port;
}
unsigned short calcsum(unsigned short* buffer, int length)
icp->icmp_code = 0;
icp->icmp_cksum = 0;
icp->icmp_seq = htons(icmp_seq_nr);
- icp->icmp_id = htons(icmp_id_nr);
+ icp->icmp_id = icmp_id_nr;
if (random_data_flag) {
for (n = ((char*)&icp->icmp_data - (char*)icp); n < ping_pkt_size_ipv4; ++n) {
crash_and_burn("can't malloc ping packet");
}
-void socket_set_src_addr_ipv6(int s, struct in6_addr* src_addr)
+void socket_set_src_addr_ipv6(int s, struct in6_addr* src_addr, int *ident)
{
struct sockaddr_in6 sa;
+ socklen_t len = sizeof(sa);
+
memset(&sa, 0, sizeof(sa));
sa.sin6_family = AF_INET6;
sa.sin6_addr = *src_addr;
-
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 (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)
icp->icmp6_type = ICMP6_ECHO_REQUEST;
icp->icmp6_code = 0;
icp->icmp6_seq = htons(icmp_seq_nr);
- icp->icmp6_id = htons(icmp_id_nr);
+ icp->icmp6_id = icmp_id_nr;
if (random_data_flag) {
for (n = sizeof(struct icmp6_hdr); n < ping_pkt_size_ipv6; ++n) {