1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
/*
* cmd/ifctrstat.c
* Purpose: Display statistics about interfaces on the system
*
* Copyright (c) 2020 Adélie Software in the Public Benefit, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include <errno.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "libifupdown/libifupdown.h"
#include "cmd/multicall.h"
#include "cmd/ifctrstat-linux.h"
extern struct counter_desc { const char *name; const void *data; } avail_counters[];
extern int avail_counters_count;
static bool show_label = true;
static bool
counter_is_valid(const char *candidate)
{
for (int i = 0; i < avail_counters_count; i++)
{
if (strcasecmp(avail_counters[i].name, candidate) == 0)
return true;
}
return false;
}
static void
print_counter(const char *iface, const char *name, const char *value)
{
(void) iface;
if (show_label)
fprintf(stdout, "%s: %s\n", name, value);
else
fprintf(stdout, "%s\n", value);
}
static int
print_all_counters(const char *iface)
{
int code = EXIT_SUCCESS;
const char *res;
for (int i = 0; i < avail_counters_count; i++)
{
const char *ctr = avail_counters[i].name;
res = read_counter(iface, ctr);
if (!res)
{
fprintf(stderr, "%s: could not determine value of %s for interface %s: %s\n", argv0, ctr, iface, strerror(errno));
code = EXIT_FAILURE;
}
else
{
print_counter(iface, ctr, res);
}
}
return code;
}
static void
ifctrstat_list_counters(const char *opt_arg)
{
(void) opt_arg;
for (int i = 0; i < avail_counters_count; i++)
{
fprintf(stdout, "%s\n", avail_counters[i].name);
}
exit(EXIT_SUCCESS);
}
static void
ifctrstat_set_nolabel(const char *opt_arg)
{
(void) opt_arg;
show_label = false;
}
static int
ifctrstat_main(int argc, char *argv[])
{
if (optind >= argc)
generic_usage(self_applet, EXIT_FAILURE);
int idx = optind;
if (argc - idx == 0)
{
fprintf(stderr, "%s: interface required\n",
argv0);
return EXIT_FAILURE;
}
const char *iface = argv[idx++];
if (argc - idx == 0)
{
return print_all_counters(iface);
}
for (; idx < argc; idx++)
{
if (!counter_is_valid(argv[idx]))
{
fprintf(stderr, "%s: counter %s is not valid or not available\n", argv0, argv[idx]);
return EXIT_FAILURE;
}
errno = 0;
const char *res = read_counter(iface, argv[idx]);
if (!res)
{
fprintf(stderr, "%s: could not determine value of %s for interface %s: %s\n", argv0, argv[idx], iface, strerror(errno));
return EXIT_FAILURE;
}
print_counter(iface, argv[idx], res);
}
return EXIT_SUCCESS;
}
static struct if_option local_options[] = {
{'L', "list", NULL, "list available counters", false, ifctrstat_list_counters},
{'n', "no-label", NULL, "print value without counter label", false, ifctrstat_set_nolabel}
};
static struct if_option_group local_option_group = {
.desc = "Program-specific options",
.group_size = ARRAY_SIZE(local_options),
.group = local_options
};
struct if_applet ifctrstat_applet = {
.name = "ifctrstat",
.desc = "display statistics about an interface",
.main = ifctrstat_main,
.usage = "ifctrstat [options] <interface> <counter>\n ifctrstat [options] --list",
.manpage = "8 ifctrstat",
.groups = { &global_option_group, &local_option_group, NULL }
};
APPLET_REGISTER(ifctrstat_applet)
|