Customized ping

- Add -u option to send UDP packets
- Don't print dots when flooding
- Don't require root user
This commit is contained in:
Jan Schär 2022-05-28 19:53:14 +02:00
parent 9db9053c97
commit 1beb079cb0
3 changed files with 19 additions and 16 deletions

View File

@ -275,6 +275,7 @@ main(int argc, char **argv)
.tmin = LONG_MAX, .tmin = LONG_MAX,
.pipesize = -1, .pipesize = -1,
.datalen = DEFDATALEN, .datalen = DEFDATALEN,
.protocol = IPPROTO_ICMP,
.screen_width = INT_MAX, .screen_width = INT_MAX,
#ifdef HAVE_LIBCAP #ifdef HAVE_LIBCAP
.cap_raw = CAP_NET_RAW, .cap_raw = CAP_NET_RAW,
@ -311,7 +312,7 @@ main(int argc, char **argv)
hints.ai_family = AF_INET6; hints.ai_family = AF_INET6;
/* Parse command line options */ /* Parse command line options */
while ((ch = getopt(argc, argv, "h?" "4bRT:" "6F:N:" "aABc:dDfi:I:l:Lm:M:nOp:qQ:rs:S:t:UvVw:W:")) != EOF) { while ((ch = getopt(argc, argv, "h?" "4bRT:" "6F:N:" "aABc:dDfi:I:l:Lm:M:nOp:qQ:rs:S:t:uUvVw:W:")) != EOF) {
switch(ch) { switch(ch) {
/* IPv4 specific options */ /* IPv4 specific options */
case '4': case '4':
@ -398,8 +399,6 @@ main(int argc, char **argv)
break; break;
case 'l': case 'l':
rts.preload = strtol_or_err(optarg, _("invalid argument"), 1, MAX_DUP_CHK); rts.preload = strtol_or_err(optarg, _("invalid argument"), 1, MAX_DUP_CHK);
if (rts.uid && rts.preload > 3)
error(2, 0, _("cannot set preload to value greater than 3: %d"), rts.preload);
break; break;
case 'L': case 'L':
rts.opt_noloop = 1; rts.opt_noloop = 1;
@ -456,6 +455,9 @@ main(int argc, char **argv)
rts.ttl = strtol_or_err(optarg, _("invalid argument"), 0, 255); rts.ttl = strtol_or_err(optarg, _("invalid argument"), 0, 255);
rts.opt_ttl = 1; rts.opt_ttl = 1;
break; break;
case 'u':
rts.protocol = IPPROTO_UDP;
break;
case 'U': case 'U':
rts.opt_latency = 1; rts.opt_latency = 1;
break; break;
@ -503,7 +505,7 @@ main(int argc, char **argv)
/* Create sockets */ /* Create sockets */
enable_capability_raw(); enable_capability_raw();
if (hints.ai_family != AF_INET6) if (hints.ai_family != AF_INET6)
create_socket(&rts, &sock4, AF_INET, hints.ai_socktype, IPPROTO_ICMP, create_socket(&rts, &sock4, AF_INET, hints.ai_socktype, rts.protocol,
hints.ai_family == AF_INET); hints.ai_family == AF_INET);
if (hints.ai_family != AF_INET) { if (hints.ai_family != AF_INET) {
create_socket(&rts, &sock6, AF_INET6, hints.ai_socktype, IPPROTO_ICMPV6, sock4.fd == -1); create_socket(&rts, &sock6, AF_INET6, hints.ai_socktype, IPPROTO_ICMPV6, sock4.fd == -1);
@ -676,6 +678,7 @@ int ping4_run(struct ping_rts *rts, int argc, char **argv, struct addrinfo *ai,
argc--; argc--;
argv++; argv++;
} }
rts->whereto.sin_port = htons(7);
if (rts->source.sin_addr.s_addr == 0) { if (rts->source.sin_addr.s_addr == 0) {
socklen_t alen; socklen_t alen;
@ -884,7 +887,9 @@ int ping4_run(struct ping_rts *rts, int argc, char **argv, struct addrinfo *ai,
printf(_("PING %s (%s) "), rts->hostname, inet_ntoa(rts->whereto.sin_addr)); printf(_("PING %s (%s) "), rts->hostname, inet_ntoa(rts->whereto.sin_addr));
if (rts->device || rts->opt_strictsource) if (rts->device || rts->opt_strictsource)
printf(_("from %s %s: "), inet_ntoa(rts->source.sin_addr), rts->device ? rts->device : ""); printf(_("from %s %s: "), inet_ntoa(rts->source.sin_addr), rts->device ? rts->device : "");
printf(_("%zu(%zu) bytes of data.\n"), rts->datalen, rts->datalen + 8 + rts->optlen + 20); int extralen = 0;
if (rts->protocol == IPPROTO_UDP) extralen = 8;
printf(_("%zu(%zu) bytes of data.\n"), rts->datalen, rts->datalen + 8 + rts->optlen + 20 + extralen);
setup(rts, sock); setup(rts, sock);
@ -1501,7 +1506,7 @@ int ping4_parse_reply(struct ping_rts *rts, struct socket_st *sock,
icp = (struct icmphdr *)(buf + hlen); icp = (struct icmphdr *)(buf + hlen);
csfailed = in_cksum((unsigned short *)icp, cc, 0); csfailed = in_cksum((unsigned short *)icp, cc, 0);
if (icp->type == ICMP_ECHOREPLY) { if (icp->type == ICMP_ECHOREPLY || icp->type == ICMP_ECHO) {
if (!is_ours(rts, sock, icp->un.echo.id)) if (!is_ours(rts, sock, icp->un.echo.id))
return 1; /* 'Twas not our ECHO */ return 1; /* 'Twas not our ECHO */

View File

@ -145,6 +145,7 @@ struct ping_rts {
struct rcvd_table rcvd_tbl; struct rcvd_table rcvd_tbl;
size_t datalen; size_t datalen;
int protocol;
char *hostname; char *hostname;
uid_t uid; uid_t uid;
int ident; /* random id to identify our packets */ int ident; /* random id to identify our packets */

View File

@ -356,9 +356,9 @@ resend:
if (!rts->opt_quiet && rts->opt_flood) { if (!rts->opt_quiet && rts->opt_flood) {
/* Very silly, but without this output with /* Very silly, but without this output with
* high preload or pipe size is very confusing. */ * high preload or pipe size is very confusing. */
if ((rts->preload < rts->screen_width && rts->pipesize < rts->screen_width) || // if ((rts->preload < rts->screen_width && rts->pipesize < rts->screen_width) ||
in_flight(rts) < rts->screen_width) // in_flight(rts) < rts->screen_width)
write_stdout(".", 1); // write_stdout(".", 1);
} }
return rts->interval - tokens; return rts->interval - tokens;
} }
@ -476,9 +476,6 @@ void setup(struct ping_rts *rts, socket_st *sock)
if (rts->opt_flood && !rts->opt_interval) if (rts->opt_flood && !rts->opt_interval)
rts->interval = 0; rts->interval = 0;
if (rts->uid && rts->interval < MINUSERINTERVAL)
error(2, 0, _("cannot flood; minimal interval allowed for user is %dms"), MINUSERINTERVAL);
if (rts->interval >= INT_MAX / rts->preload) if (rts->interval >= INT_MAX / rts->preload)
error(2, 0, _("illegal preload and/or interval: %d"), rts->interval); error(2, 0, _("illegal preload and/or interval: %d"), rts->interval);
@ -777,10 +774,10 @@ restamp:
return 1; return 1;
if (rts->opt_flood) { if (rts->opt_flood) {
if (!csfailed) // if (!csfailed)
write_stdout("\b \b", 3); // write_stdout("\b \b", 3);
else // else
write_stdout("\bC", 2); // write_stdout("\bC", 2);
} else { } else {
size_t i; size_t i;
uint8_t *cp, *dp; uint8_t *cp, *dp;