From e88c3c1ac1ce7dbd4834fdddbeefaa066d60da10 Mon Sep 17 00:00:00 2001 From: Sami Kerola Date: Wed, 28 Aug 2019 20:50:00 +0100 Subject: ping: allow any package size to be defined by user If size is too large operating system will inform things did not work out. Addresses: https://github.com/iputils/iputils/issues/210 Signed-off-by: Sami Kerola --- ping.c | 21 ++++++++++++++------- ping.h | 7 +++---- ping6_common.c | 2 +- ping_common.c | 22 ++++++++++++---------- 4 files changed, 30 insertions(+), 22 deletions(-) diff --git a/ping.c b/ping.c index 95b782e..daef749 100644 --- a/ping.c +++ b/ping.c @@ -272,6 +272,7 @@ main(int argc, char **argv) socket_st sock4 = { .fd = -1 }; socket_st sock6 = { .fd = -1 }; char *target; + char *outpack_fill = NULL; atexit(close_stdout); limit_capabilities(); @@ -430,7 +431,9 @@ main(int argc, char **argv) break; case 'p': options |= F_PINGFILLED; - fill(optarg, outpack, sizeof(outpack)); + outpack_fill = strdup(optarg); + if (!outpack_fill) + error(2, errno, _("memory allocation failed")); break; case 'q': options |= F_QUIET; @@ -443,7 +446,7 @@ main(int argc, char **argv) options |= F_SO_DONTROUTE; break; case 's': - datalen = strtol_or_err(optarg, _("invalid argument"), 0, MAXPACKET - 8); + datalen = strtol_or_err(optarg, _("invalid argument"), 0, INT_MAX); break; case 'S': sndbuf = strtol_or_err(optarg, _("invalid argument"), 1, INT_MAX); @@ -489,6 +492,12 @@ main(int argc, char **argv) target = argv[argc - 1]; + outpack = malloc(datalen + 28); + if (!outpack) + error(2, errno, _("memory allocation failed")); + if (outpack_fill) + fill(outpack_fill, outpack, datalen); + /* Create sockets */ enable_capability_raw(); if (hints.ai_family != AF_INET6) @@ -539,6 +548,8 @@ main(int argc, char **argv) } freeaddrinfo(result); + free(outpack); + free(outpack_fill); return ret_val; } @@ -864,10 +875,6 @@ int ping4_run(int argc, char **argv, struct addrinfo *ai, socket_st *sock) error(2, errno, _("cannot set unicast time-to-live")); } - if (datalen > 0xFFFF - 8 - optlen - 20) - error(2, 0, _("packet size %d is too large. Maximum is %d"), - datalen, 0xFFFF - 8 - 20 - optlen); - if (datalen >= (int)sizeof(struct timeval)) /* can we time transfer */ timing = 1; packlen = datalen + MAXIPLEN + MAXICMPLEN; @@ -877,7 +884,7 @@ int ping4_run(int argc, char **argv, struct addrinfo *ai, socket_st *sock) printf(_("PING %s (%s) "), hostname, inet_ntoa(whereto.sin_addr)); if (device || (options & F_STRICTSOURCE)) printf(_("from %s %s: "), inet_ntoa(source.sin_addr), device ? device : ""); - printf(_("%d(%d) bytes of data.\n"), datalen, datalen + 8 + optlen + 20); + printf(_("%zu(%zu) bytes of data.\n"), datalen, datalen + 8 + optlen + 20); setup(sock); diff --git a/ping.h b/ping.h index 1d015ad..bf675bf 100644 --- a/ping.h +++ b/ping.h @@ -139,7 +139,7 @@ static inline bitmap_t rcvd_test(uint16_t seq) return A(bit) & B(bit); } -extern int datalen; +extern size_t datalen; extern char *hostname; extern int uid; extern int ident; /* process id to identify our packets */ @@ -298,7 +298,6 @@ typedef struct ping_func_set_st { void (*install_filter)(socket_st *); } ping_func_set_st; -#define MAXPACKET 128000 /* max packet size */ extern ping_func_set_st ping4_func_set; extern int pinger(ping_func_set_st *fset, socket_st *sock); @@ -314,10 +313,10 @@ extern int gather_statistics(uint8_t *ptr, int icmplen, int csfailed, struct timeval *tv, char *from, void (*pr_reply)(uint8_t *ptr, int cc), int multicast); extern void print_timestamp(void); -void fill(char *patp, unsigned char *packet, unsigned packet_size); +void fill(char *patp, unsigned char *packet, size_t packet_size); extern int mark; -extern unsigned char outpack[MAXPACKET]; +extern unsigned char *outpack; /* IPv6 */ diff --git a/ping6_common.c b/ping6_common.c index adce865..a38218c 100644 --- a/ping6_common.c +++ b/ping6_common.c @@ -837,7 +837,7 @@ int ping6_run(int argc, char **argv, struct addrinfo *ai, struct socket_st *sock printf(_("from %s %s: "), pr_addr(&source6, sizeof source6), device ? device : ""); options = saved_options; } - printf(_("%d data bytes\n"), datalen); + printf(_("%zu data bytes\n"), datalen); setup(sock); diff --git a/ping_common.c b/ping_common.c index e91d15c..7a1a3bf 100644 --- a/ping_common.c +++ b/ping_common.c @@ -45,7 +45,7 @@ int rtt; int rtt_addend; uint16_t acked; -unsigned char outpack[MAXPACKET]; +unsigned char *outpack; struct rcvd_table rcvd_tbl; /* counters */ @@ -84,7 +84,7 @@ double tsum; /* sum of all times, for doing average */ double tsum2; int pipesize = -1; -int datalen = DEFDATALEN; +size_t datalen = DEFDATALEN; char *hostname; int uid; @@ -249,7 +249,7 @@ void drop_capabilities(void) /* Fills all the outpack, excluding ICMP header, but _including_ * timestamp area with supplied pattern. */ -void fill(char *patp, unsigned char *packet, unsigned packet_size) +void fill(char *patp, unsigned char *packet, size_t packet_size) { int ii, jj; unsigned int pat[16]; @@ -271,8 +271,10 @@ void fill(char *patp, unsigned char *packet, unsigned packet_size) &pat[12], &pat[13], &pat[14], &pat[15]); if (ii > 0) { - unsigned kk; - for (kk = 0; kk <= packet_size - (8 + ii); kk += ii) + size_t kk; + size_t max = packet_size < (size_t)(8 + ii) ? 0 : packet_size - (8 + ii); + + for (kk = 0; kk <= max; kk += ii) for (jj = 0; jj < ii; ++jj) bp[jj + kk] = pat[jj]; } @@ -567,7 +569,7 @@ void setup(socket_st *sock) options |= F_FLOOD_POLL; if (!(options & F_PINGFILLED)) { - int i; + size_t i; unsigned char *p = outpack + 8; /* Do not forget about case of small datalen, fill timestamp area too! */ @@ -612,7 +614,7 @@ void setup(socket_st *sock) */ int contains_pattern_in_payload(uint8_t *ptr) { - int i; + size_t i; uint8_t *cp, *dp; /* check the data */ @@ -845,7 +847,7 @@ restamp: else write_stdout("\bC", 2); } else { - int i; + size_t i; uint8_t *cp, *dp; print_timestamp(); @@ -884,12 +886,12 @@ restamp: dp = &outpack[8 + sizeof(struct timeval)]; for (i = sizeof(struct timeval); i < datalen; ++i, ++cp, ++dp) { if (*cp != *dp) { - printf(_("\nwrong data byte #%d should be 0x%x but was 0x%x"), + printf(_("\nwrong data byte #%zu should be 0x%x but was 0x%x"), i, *dp, *cp); cp = (unsigned char *)ptr + sizeof(struct timeval); for (i = sizeof(struct timeval); i < datalen; ++i, ++cp) { if ((i % 32) == sizeof(struct timeval)) - printf("\n#%d\t", i); + printf("\n#%zu\t", i); printf("%x ", *cp); } break; -- cgit v1.2.1