pflow: show socket status in verbose mode

Introduce a verbose output mode to pflowctl, and expose the status of
the socket to userspace. This can be helpful in debugging configuration
errors.

Sponsored by:	Rubicon Communications, LLC ("Netgate")
This commit is contained in:
Kristof Provost 2024-01-25 17:37:51 +01:00
parent b8a484ec34
commit e95025ed93
4 changed files with 53 additions and 8 deletions

View file

@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: January 08 2024 $
.Dd $Mdocdate: January 25 2024 $
.Dt PFLOWCTL 8
.Os
.Sh NAME
@ -24,6 +24,7 @@
.Sh SYNOPSIS
.Nm pflowctl
.Bk -words
.Op Fl v
.Op Fl lc
.Op Fl d Ar id
.Op Fl s Ar id ...
@ -40,6 +41,8 @@ The
utility provides several commands.
The options are as follows:
.Bl -tag -width Ds
.It Fl v
Produce verbose output.
.It Fl c
Create a new
.Xr pflow 4

View file

@ -47,13 +47,15 @@
static int get(int id);
static bool verbose = false;
extern char *__progname;
static void
usage(void)
{
fprintf(stderr,
"usage: %s [-lc] [-d id] [-s id ...]\n",
"usage: %s [-lc] [-d id] [-s id ...] [-v]\n",
__progname);
exit(1);
@ -253,6 +255,7 @@ struct pflowctl_get {
struct pflowctl_sockaddr src;
struct pflowctl_sockaddr dst;
uint32_t obs_dom;
uint8_t so_status;
};
#define _IN(_field) offsetof(struct genlmsghdr, _field)
#define _OUT(_field) offsetof(struct pflowctl_get, _field)
@ -262,6 +265,7 @@ static struct snl_attr_parser ap_get[] = {
{ .type = PFLOWNL_GET_SRC, .off = _OUT(src), .arg = &sockaddr_parser, .cb = snl_attr_get_nested },
{ .type = PFLOWNL_GET_DST, .off = _OUT(dst), .arg = &sockaddr_parser, .cb = snl_attr_get_nested },
{ .type = PFLOWNL_GET_OBSERVATION_DOMAIN, .off = _OUT(obs_dom), .cb = snl_attr_get_uint32 },
{ .type = PFLOWNL_GET_SOCKET_STATUS, .off = _OUT(so_status), .cb = snl_attr_get_uint8 },
};
static struct snl_field_parser fp_get[] = {};
#undef _IN
@ -344,6 +348,10 @@ get(int id)
print_sockaddr(" src ", &g.src.storage);
print_sockaddr(" dst ", &g.dst.storage);
printf("\n");
if (verbose) {
printf("\tsocket: %s\n",
g.so_status ? "connected" : "disconnected");
}
}
if (e.error)
@ -533,10 +541,20 @@ static const struct snl_hdr_parser *all_parsers[] = {
&get_parser,
};
enum pflowctl_op_t {
OP_HELP,
OP_LIST,
OP_CREATE,
OP_DELETE,
OP_SET,
};
int
main(int argc, char *argv[])
{
int ch;
enum pflowctl_op_t op = OP_HELP;
char **set_args = NULL;
size_t set_arg_count = 0;
SNL_VERIFY_PARSERS(all_parsers);
@ -544,18 +562,40 @@ main(int argc, char *argv[])
usage();
while ((ch = getopt(argc, argv,
"lcd:s:")) != -1) {
"lcd:s:v")) != -1) {
switch (ch) {
case 'l':
return (list());
op = OP_LIST;
break;
case 'c':
return (create());
op = OP_CREATE;
break;
case 'd':
return (del(optarg));
op = OP_DELETE;
break;
case 's':
return (set(optarg, argc - optind, argv + optind));
op = OP_SET;
set_arg_count = argc - optind;
set_args = argv + optind;
case 'v':
verbose = true;
break;
}
}
switch (op) {
case OP_LIST:
return (list());
case OP_CREATE:
return (create());
case OP_DELETE:
return (del(optarg));
case OP_SET:
return (set(optarg, set_arg_count, set_args));
case OP_HELP:
usage();
break;
}
return (0);
}

View file

@ -362,7 +362,8 @@ enum pflow_get_type_t {
PFLOWNL_GET_VERSION = 2, /* u16 */
PFLOWNL_GET_SRC = 3, /* struct sockaddr_storage */
PFLOWNL_GET_DST = 4, /* struct sockaddr_storage */
PFLOWNL_GET_OBSERVATION_DOMAIN = 5, /* u32 */
PFLOWNL_GET_OBSERVATION_DOMAIN = 5, /* u32 */
PFLOWNL_GET_SOCKET_STATUS = 6, /* u8 */
};
enum pflow_set_type_t {

View file

@ -1485,6 +1485,7 @@ pflow_nl_get(struct nlmsghdr *hdr, struct nl_pstate *npt)
nlattr_add_sockaddr(nw, PFLOWNL_GET_DST, sc->sc_flowdst);
nlattr_add_u32(nw, PFLOWNL_GET_OBSERVATION_DOMAIN,
sc->sc_observation_dom);
nlattr_add_u8(nw, PFLOWNL_GET_SOCKET_STATUS, sc->so != NULL);
if (! nlmsg_end(nw)) {
nlmsg_abort(nw);