Skip to content

Commit 5f6bec5

Browse files
committed
ping: Print reply with wrong source with warning
5e052ad ("ping: discard packets with wrong source address") correctly hid replies with wrong source address to comply RFC 1122 (Section 3.2.1.3: "The IP source address in an ICMP Echo Reply MUST be the same as the specific-destination address"). This caused to hide reply when pinging Subnet-Router anycast address. Although it was fixed in the previous commit, relax this to admit the reply but print warning "DIFFERENT ADDRESS!". ping is diagnostic program, with insisting on RFC we force people to use tcpdump to see replies. Link: #371 Reviewed-by: Matteo Croce <mcroce@microsoft.com> Signed-off-by: Petr Vorel <pvorel@suse.cz>
1 parent 15a5e5c commit 5f6bec5

File tree

4 files changed

+21
-11
lines changed

4 files changed

+21
-11
lines changed

ping/ping.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,6 +1504,7 @@ int ping4_parse_reply(struct ping_rts *rts, struct socket_st *sock,
15041504
int reply_ttl;
15051505
uint8_t *opts, *tmp_ttl;
15061506
int olen;
1507+
int wrong_source = 0;
15071508

15081509
/* Check the IP header */
15091510
ip = (struct iphdr *)buf;
@@ -1544,15 +1545,16 @@ int ping4_parse_reply(struct ping_rts *rts, struct socket_st *sock,
15441545
csfailed = in_cksum((unsigned short *)icp, cc, 0);
15451546

15461547
if (icp->type == ICMP_ECHOREPLY) {
1547-
if (!rts->broadcast_pings && !rts->multicast &&
1548-
from->sin_addr.s_addr != rts->whereto.sin_addr.s_addr)
1549-
return 1;
15501548
if (!is_ours(rts, sock, icp->un.echo.id))
15511549
return 1; /* 'Twas not our ECHO */
1550+
1551+
if (!rts->broadcast_pings && !rts->multicast &&
1552+
from->sin_addr.s_addr != rts->whereto.sin_addr.s_addr)
1553+
wrong_source = 1;
15521554
if (gather_statistics(rts, (uint8_t *)icp, sizeof(*icp), cc,
15531555
ntohs(icp->un.echo.sequence),
15541556
reply_ttl, 0, tv, pr_addr(rts, from, sizeof *from),
1555-
pr_echo_reply, rts->multicast)) {
1557+
pr_echo_reply, rts->multicast, wrong_source)) {
15561558
fflush(stdout);
15571559
return 0;
15581560
}

ping/ping.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,8 @@ extern void common_options(int ch);
389389
extern int gather_statistics(struct ping_rts *rts, uint8_t *icmph, int icmplen,
390390
int cc, uint16_t seq, int hops,
391391
int csfailed, struct timeval *tv, char *from,
392-
void (*pr_reply)(uint8_t *ptr, int cc), int multicast);
392+
void (*pr_reply)(uint8_t *ptr, int cc), int multicast,
393+
int wrong_source);
393394
extern void print_timestamp(struct ping_rts *rts);
394395
void fill(struct ping_rts *rts, char *patp, unsigned char *packet, size_t packet_size);
395396

ping/ping6_common.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,7 @@ int ping6_parse_reply(struct ping_rts *rts, socket_st *sock,
803803
struct cmsghdr *c;
804804
struct icmp6_hdr *icmph;
805805
int hops = -1;
806+
int wrong_source = 0;
806807

807808
for (c = CMSG_FIRSTHDR(msg); c; c = CMSG_NXTHDR(msg, c)) {
808809
if (c->cmsg_level != IPPROTO_IPV6)
@@ -829,16 +830,18 @@ int ping6_parse_reply(struct ping_rts *rts, socket_st *sock,
829830
}
830831

831832
if (icmph->icmp6_type == ICMP6_ECHO_REPLY) {
832-
if (!rts->multicast && !rts->subnet_router_anycast &&
833-
memcmp(&from->sin6_addr.s6_addr, &rts->whereto6.sin6_addr.s6_addr, 16))
834-
return 1;
835833
if (!is_ours(rts, sock, icmph->icmp6_id))
836834
return 1;
835+
836+
if (!rts->multicast && !rts->subnet_router_anycast &&
837+
memcmp(&from->sin6_addr.s6_addr, &rts->whereto6.sin6_addr.s6_addr, 16))
838+
wrong_source = 1;
839+
837840
if (gather_statistics(rts, (uint8_t *)icmph, sizeof(*icmph), cc,
838841
ntohs(icmph->icmp6_seq),
839842
hops, 0, tv, pr_addr(rts, from, sizeof *from),
840843
pr_echo_reply,
841-
rts->multicast)) {
844+
rts->multicast, wrong_source)) {
842845
fflush(stdout);
843846
return 0;
844847
}
@@ -851,7 +854,7 @@ int ping6_parse_reply(struct ping_rts *rts, socket_st *sock,
851854
seq,
852855
hops, 0, tv, pr_addr(rts, from, sizeof *from),
853856
pr_niquery_reply,
854-
rts->multicast))
857+
rts->multicast, 0))
855858
return 0;
856859
} else {
857860
int nexthdr;

ping/ping_common.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,8 @@ int main_loop(struct ping_rts *rts, ping_func_set_st *fset, socket_st *sock,
711711
int gather_statistics(struct ping_rts *rts, uint8_t *icmph, int icmplen,
712712
int cc, uint16_t seq, int hops,
713713
int csfailed, struct timeval *tv, char *from,
714-
void (*pr_reply)(uint8_t *icmph, int cc), int multicast)
714+
void (*pr_reply)(uint8_t *icmph, int cc), int multicast,
715+
int wrong_source)
715716
{
716717
int dupflag = 0;
717718
long triptime = 0;
@@ -804,10 +805,13 @@ int gather_statistics(struct ping_rts *rts, uint8_t *icmph, int icmplen,
804805
printf(_(" time=%ld.%03ld ms"), triptime / 1000,
805806
triptime % 1000);
806807
}
808+
807809
if (dupflag && (!multicast || rts->opt_verbose))
808810
printf(_(" (DUP!)"));
809811
if (csfailed)
810812
printf(_(" (BAD CHECKSUM!)"));
813+
if (wrong_source)
814+
printf(_(" (DIFFERENT ADDRESS!)"));
811815

812816
/* check the data */
813817
cp = ((unsigned char *)ptr) + sizeof(struct timeval);

0 commit comments

Comments
 (0)