From 3258f8edb43b196f6717fa44ae0b0535bfac73a6 Mon Sep 17 00:00:00 2001 From: Petr Vorel Date: Wed, 7 Aug 2024 17:13:01 +0200 Subject: [PATCH] ping: Limit -s max. value Max value for ping -s option cannot be higher than maximum IPv4/v6 packet size, which is 65535. More precisely, the value should respect maximum IPv4/v6 ICMP data length. Use the higher value unless user chose the protocol. Fixes: https://github.com/iputils/iputils/issues/542 Reported-by: mimicria Signed-off-by: Petr Vorel --- ping/ping.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/ping/ping.c b/ping/ping.c index f1ffbb0e..963f3699 100644 --- a/ping/ping.c +++ b/ping/ping.c @@ -59,6 +59,7 @@ #include #include #include +#include /* FIXME: global_rts will be removed in future */ struct ping_rts *global_rts; @@ -84,6 +85,12 @@ ping_func_set_st ping4_func_set = { #define NROUTES 9 /* number of record route slots */ #define TOS_MAX 255 /* 8-bit TOS field */ +/* max. IPv4 packet size - IPv4 header size - ICMP header size */ +#define ICMP_MAX_DATALEN (65535 - IPV4_HEADER_MINLEN - ICMP_HEADER_MINLEN) + +/* max. IPv6 payload size) - ICMPv6 Echo Reply Header */ +#define ICMPV6_MAX_DATALEN (65535 - sizeof (struct icmp6_hdr)) + #define CASE_TYPE(x) case x: return #x; static char *str_family(int family) @@ -338,6 +345,9 @@ main(int argc, char **argv) .ni.query = -1, .ni.subject_type = -1, }; + + size_t max_s = MAX(ICMP_MAX_DATALEN, ICMPV6_MAX_DATALEN); + /* FIXME: global_rts will be removed in future */ global_rts = &rts; @@ -531,7 +541,7 @@ main(int argc, char **argv) rts.opt_so_dontroute = 1; break; case 's': - rts.datalen = strtol_or_err(optarg, _("invalid argument"), 0, INT_MAX); + rts.datalen = strtol_or_err(optarg, _("invalid argument"), 0, max_s); break; case 'S': rts.sndbuf = strtol_or_err(optarg, _("invalid argument"), 1, INT_MAX); @@ -626,6 +636,19 @@ main(int argc, char **argv) hints.ai_family = AF_INET; } + switch (hints.ai_family) { + case AF_INET: + max_s = ICMP_MAX_DATALEN; + break; + case AF_INET6: + max_s = ICMPV6_MAX_DATALEN; + break; + } + + if (rts.datalen > max_s) + error(EXIT_FAILURE, 0, "invalid -s value: '%ld': out of range: %d <= value <= %ld", + rts.datalen, 0, max_s); + if (rts.opt_verbose) error(0, 0, "sock4.fd: %d (socktype: %s), sock6.fd: %d (socktype: %s)," " hints.ai_family: %s\n",