summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Habets <thomas@habets.se>2022-10-26 20:06:25 +0100
committerThomas Habets <thomas@habets.se>2022-10-26 20:06:25 +0100
commitdaa6052f16336b55bfddda6b5f0a4f19da3b0477 (patch)
tree62e41cef0e8f16536215184c3435c39931b0499e
parentd92ffebd7e534f0b003f94421e832880f7efc770 (diff)
downloadarping-daa6052f16336b55bfddda6b5f0a4f19da3b0477.tar.gz
Parse -VQCc strictly as num
-rw-r--r--src/arping.c45
-rw-r--r--src/arping_test.c51
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);