From e95025ed93886dc854c2c92a2d2812cb51abf4ed Mon Sep 17 00:00:00 2001 From: Kristof Provost Date: Thu, 25 Jan 2024 17:37:51 +0100 Subject: [PATCH] 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") --- sbin/pflowctl/pflowctl.8 | 5 +++- sbin/pflowctl/pflowctl.c | 52 +++++++++++++++++++++++++++++++++++----- sys/net/pflow.h | 3 ++- sys/netpfil/pf/pflow.c | 1 + 4 files changed, 53 insertions(+), 8 deletions(-) diff --git a/sbin/pflowctl/pflowctl.8 b/sbin/pflowctl/pflowctl.8 index 446679486db6..8c4142f31396 100644 --- a/sbin/pflowctl/pflowctl.8 +++ b/sbin/pflowctl/pflowctl.8 @@ -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 diff --git a/sbin/pflowctl/pflowctl.c b/sbin/pflowctl/pflowctl.c index e5dd3df7e6a7..f6ca8980db1b 100644 --- a/sbin/pflowctl/pflowctl.c +++ b/sbin/pflowctl/pflowctl.c @@ -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); } diff --git a/sys/net/pflow.h b/sys/net/pflow.h index 4c194e14e001..ee747d1a6a46 100644 --- a/sys/net/pflow.h +++ b/sys/net/pflow.h @@ -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 { diff --git a/sys/netpfil/pf/pflow.c b/sys/netpfil/pf/pflow.c index 17a68e0d9e57..f3dba7687d05 100644 --- a/sys/netpfil/pf/pflow.c +++ b/sys/netpfil/pf/pflow.c @@ -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);