diff options
author | Thomas Habets <thomas@habets.se> | 2022-10-26 20:06:25 +0100 |
---|---|---|
committer | Thomas Habets <thomas@habets.se> | 2022-10-26 20:06:25 +0100 |
commit | daa6052f16336b55bfddda6b5f0a4f19da3b0477 (patch) | |
tree | 62e41cef0e8f16536215184c3435c39931b0499e | |
parent | d92ffebd7e534f0b003f94421e832880f7efc770 (diff) | |
download | arping-daa6052f16336b55bfddda6b5f0a4f19da3b0477.tar.gz |
Parse -VQCc strictly as num
-rw-r--r-- | src/arping.c | 45 | ||||
-rw-r--r-- | src/arping_test.c | 51 |
2 files changed, 91 insertions, 5 deletions
diff --git a/src/arping.c b/src/arping.c index 11739d7..a2717cd 100644 --- a/src/arping.c +++ b/src/arping.c @@ -238,6 +238,30 @@ int verbose = 0; /* Increase with -v */ /* Doesn't really need to be volatile, but doesn't hurt. */ static volatile sig_atomic_t time_to_die = 0; +static int +must_parse_int(const char* in, const char* what) +{ + if (!*in) { + fprintf(stderr, "arping: %s: value was empty\n", what); + exit(1); + } + char *endp = NULL; + errno = 0; + const long ret = strtol(in, &endp, 0); + if (errno) { + fprintf(stderr, "arping: %s: parsing <%s> as integer: %s\n", + what, in, strerror(errno)); + exit(1); + } + if (*endp) { + fprintf(stderr, + "arping: %s: failed parsing <%s> as integer\n", + what, in); + exit(1); + } + return ret; // TODO: range check. +} + static ssize_t xgetrandom(void *buf, const size_t buflen, const unsigned int flags) { @@ -1971,10 +1995,23 @@ arping_main(int argc, char **argv) opt_B = 1; break; case 'c': - maxcount = atoi(optarg); + maxcount = must_parse_int(optarg, "count (-c)"); + if (maxcount < 0) { + fprintf(stderr, + "arping: count (-c) must be >0. Got %d\n", + maxcount); + exit(1); + } break; case 'C': - max_replies = atoi(optarg); + max_replies = must_parse_int(optarg, + "max replies (-C)"); + if (max_replies < 0) { + fprintf(stderr, + "arping: max replies (-C) must be >0. Got %d\n", + max_replies); + exit(1); + } break; case 'd': finddup = 1; @@ -2022,7 +2059,7 @@ arping_main(int argc, char **argv) display = QUIET; break; case 'Q': - vlan_prio = atoi(optarg); + vlan_prio = must_parse_int(optarg, "802.1p prio (-Q)"); if (vlan_prio < 0 || vlan_prio > 7) { fprintf(stderr, "arping: 802.1p priority must be 0-7. It's %d\n", @@ -2065,7 +2102,7 @@ arping_main(int argc, char **argv) verbose++; break; case 'V': - vlan_tag = atoi(optarg); + vlan_tag = must_parse_int(optarg, "VLAN (-V)"); if (vlan_tag < 0 || vlan_tag > 4095) { fprintf(stderr, "arping: vlan tag must 0-4095. Is %d\n", diff --git a/src/arping_test.c b/src/arping_test.c index b00f626..9166c54 100644 --- a/src/arping_test.c +++ b/src/arping_test.c @@ -492,6 +492,52 @@ START_TEST(get_mac_addr_fail) } } END_TEST +START_TEST(badarg_maxcount_neg) +{ + char* args[] = { + "arping", + "-c", "-1", + "dummy", + NULL + }; + arping_main(sizeof(args)/sizeof(char*)-1, args); +} + +START_TEST(badarg_maxcount_nan) +{ + char* args[] = { + "arping", + "-c", "number", + "dummy", + NULL + }; + arping_main(sizeof(args)/sizeof(char*)-1, args); +} + +START_TEST(arg_maxcount_good) +{ + char* args[] = { + "arping", + "-c", "1", + "-h", // To exit cleanly. + "dummy", + NULL + }; + arping_main(sizeof(args)/sizeof(char*)-1, args); +} + +START_TEST(arg_maxcount_hex) +{ + char* args[] = { + "arping", + "-c", "0xa", + "-h", // To exit cleanly. + "dummy", + NULL + }; + arping_main(sizeof(args)/sizeof(char*)-1, args); +} + START_TEST(libnet_init_bad_nolo) { // It'll only try lo if named interface fails. @@ -547,13 +593,16 @@ arping_suite(void) SIGH_LIBCHECK(get_mac_addr_success); SIGH_LIBCHECK(get_mac_addr_fail); SIGH_LIBCHECK(libnet_init_good); - + SIGH_LIBCHECK(arg_maxcount_good); + SIGH_LIBCHECK(arg_maxcount_hex); #define SIGH_LIBCHECK_EXIT(tn) \ tc_core = tcase_create(#tn); \ tcase_add_exit_test(tc_core, tn, 1); \ suite_add_tcase(s, tc_core); + SIGH_LIBCHECK_EXIT(badarg_maxcount_neg); + SIGH_LIBCHECK_EXIT(badarg_maxcount_nan); SIGH_LIBCHECK_EXIT(libnet_init_bad_nolo); SIGH_LIBCHECK_EXIT(libnet_init_null_nolo_nonull); |