Module Name: src Committed By: christos Date: Fri Dec 30 19:55:46 UTC 2016
Modified Files: src/usr.sbin/npf/npfd: Makefile npfd.c npfd.h npfd_log.c Log Message: flesh this out more. To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/usr.sbin/npf/npfd/Makefile \ src/usr.sbin/npf/npfd/npfd.h cvs rdiff -u -r1.3 -r1.4 src/usr.sbin/npf/npfd/npfd.c \ src/usr.sbin/npf/npfd/npfd_log.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.sbin/npf/npfd/Makefile diff -u src/usr.sbin/npf/npfd/Makefile:1.2 src/usr.sbin/npf/npfd/Makefile:1.3 --- src/usr.sbin/npf/npfd/Makefile:1.2 Tue Dec 27 20:25:48 2016 +++ src/usr.sbin/npf/npfd/Makefile Fri Dec 30 14:55:46 2016 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.2 2016/12/28 01:25:48 christos Exp $ +# $NetBSD: Makefile,v 1.3 2016/12/30 19:55:46 christos Exp $ # # Public Domain # @@ -6,11 +6,12 @@ NOMAN= PROG= npfd +#DBG=-g SRCS= npfd.c npfd_log.c CPPFLAGS+= -I${.CURDIR} -LDADD+= -lnpf -lpcap -DPADD+= ${LIBNPF} ${LIBPCAP} +LDADD+= -lnpf -lpcap -lutil +DPADD+= ${LIBNPF} ${LIBPCAP} ${LIBUTIL} WARNS= 5 NOLINT= # disabled deliberately Index: src/usr.sbin/npf/npfd/npfd.h diff -u src/usr.sbin/npf/npfd/npfd.h:1.2 src/usr.sbin/npf/npfd/npfd.h:1.3 --- src/usr.sbin/npf/npfd/npfd.h:1.2 Tue Dec 27 20:25:48 2016 +++ src/usr.sbin/npf/npfd/npfd.h Fri Dec 30 14:55:46 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: npfd.h,v 1.2 2016/12/28 01:25:48 christos Exp $ */ +/* $NetBSD: npfd.h,v 1.3 2016/12/30 19:55:46 christos Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -42,12 +42,13 @@ struct npf_log; typedef struct npfd_log npfd_log_t; -npfd_log_t * npfd_log_create(unsigned); +npfd_log_t * npfd_log_create(const char *, const char *, int); void npfd_log_destroy(npfd_log_t *); int npfd_log_getsock(npfd_log_t *); -bool npfd_log_reopen(npfd_log_t *); +bool npfd_log_reopen(npfd_log_t *, bool); void npfd_log(npfd_log_t *); void npfd_log_stats(npfd_log_t *); +void npfd_log_flush(npfd_log_t *); #endif Index: src/usr.sbin/npf/npfd/npfd.c diff -u src/usr.sbin/npf/npfd/npfd.c:1.3 src/usr.sbin/npf/npfd/npfd.c:1.4 --- src/usr.sbin/npf/npfd/npfd.c:1.3 Tue Dec 27 22:02:54 2016 +++ src/usr.sbin/npf/npfd/npfd.c Fri Dec 30 14:55:46 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: npfd.c,v 1.3 2016/12/28 03:02:54 christos Exp $ */ +/* $NetBSD: npfd.c,v 1.4 2016/12/30 19:55:46 christos Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -30,9 +30,10 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: npfd.c,v 1.3 2016/12/28 03:02:54 christos Exp $"); +__RCSID("$NetBSD: npfd.c,v 1.4 2016/12/30 19:55:46 christos Exp $"); #include <stdio.h> +#include <string.h> #include <fcntl.h> #include <signal.h> #include <stdlib.h> @@ -42,6 +43,7 @@ __RCSID("$NetBSD: npfd.c,v 1.3 2016/12/2 #include <errno.h> #include <err.h> #include <syslog.h> +#include <util.h> #include <net/npf.h> @@ -70,33 +72,31 @@ npfd_getctl(void) } static void -npfd_event_loop(void) +npfd_event_loop(npfd_log_t *log, int delay) { struct pollfd pfd; - npfd_log_t *log; - log = npfd_log_create(0); - if (log == NULL) - exit(EXIT_FAILURE); pfd.fd = npfd_log_getsock(log); pfd.events = POLLHUP | POLLIN; while (!done) { if (hup) { hup = false; - npfd_log_reopen(log); + npfd_log_reopen(log, false); } if (stats) { stats = false; npfd_log_stats(log); + npfd_log_flush(log); } - switch (poll(&pfd, 1, 1000)) { + switch (poll(&pfd, 1, delay)) { case -1: if (errno == EINTR) continue; syslog(LOG_ERR, "poll failed: %m"); exit(EXIT_FAILURE); case 0: + npfd_log_flush(log); continue; default: npfd_log(log); @@ -115,7 +115,7 @@ sighandler(int sig) break; case SIGTERM: case SIGINT: - hup = true; + done = true; break; case SIGINFO: case SIGQUIT: @@ -123,38 +123,96 @@ sighandler(int sig) break; default: syslog(LOG_ERR, "Unhandled signal %d", sig); + break; } } +static __dead void +usage(void) +{ + fprintf(stderr, "Usage: %s [-D] [-d <delay>] [-i <interface>]" + " [-p <pidfile>] [-s <snaplen>] expression\n", getprogname()); + exit(EXIT_FAILURE); +} + +static char * +copyargs(int argc, char **argv) +{ + if (argc == 0) + return NULL; + + size_t len = 0, p = 0; + char *buf = NULL; + + for (int i = 0; i < argc; i++) { + size_t l = strlen(argv[i]); + if (p + l + 1 >= len) + buf = erealloc(buf, len = p + l + 1); + memcpy(buf + p, argv[i], l); + p += l; + buf[p++] = i == argc - 1 ? '\0' : ' '; + } + return buf; +} + int main(int argc, char **argv) { bool daemon_off = false; int ch; - while ((ch = getopt(argc, argv, "d")) != -1) { + int delay = 60 * 1000; + const char *iface = "npflog0"; + int snaplen = 116; + char *pidname = NULL; + + int fd = npfd_getctl(); + (void)close(fd); + + while ((ch = getopt(argc, argv, "Dd:i:p:s:")) != -1) { switch (ch) { - case 'd': + case 'D': daemon_off = true; break; + case 'd': + delay = atoi(optarg) * 1000; + break; + case 'i': + iface = optarg; + break; + case 'p': + pidname = optarg; + break; + case 's': + snaplen = atoi(optarg); + break; default: - fprintf(stderr, "Usage: %s [-d]\n", getprogname()); - exit(EXIT_FAILURE); + usage(); } } - int fd = npfd_getctl(); - (void)close(fd); - if (!daemon_off && daemon(0, 0) == -1) { - err(EXIT_FAILURE, "daemon"); + argc -= optind; + argv += optind; + + char *filter = copyargs(argc, argv); + + npfd_log_t *log = npfd_log_create(iface, filter, snaplen); + + if (!daemon_off) { + if (daemon(0, 0) == -1) + err(EXIT_FAILURE, "daemon"); + pidfile(pidname); } + openlog(argv[0], LOG_PID | LOG_NDELAY | LOG_CONS, LOG_DAEMON); signal(SIGHUP, sighandler); signal(SIGINT, sighandler); signal(SIGTERM, sighandler); signal(SIGINFO, sighandler); signal(SIGQUIT, sighandler); - npfd_event_loop(); + + npfd_event_loop(log, delay); + closelog(); return 0; Index: src/usr.sbin/npf/npfd/npfd_log.c diff -u src/usr.sbin/npf/npfd/npfd_log.c:1.3 src/usr.sbin/npf/npfd/npfd_log.c:1.4 --- src/usr.sbin/npf/npfd/npfd_log.c:1.3 Tue Dec 27 22:02:54 2016 +++ src/usr.sbin/npf/npfd/npfd_log.c Fri Dec 30 14:55:46 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: npfd_log.c,v 1.3 2016/12/28 03:02:54 christos Exp $ */ +/* $NetBSD: npfd_log.c,v 1.4 2016/12/30 19:55:46 christos Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -30,13 +30,14 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: npfd_log.c,v 1.3 2016/12/28 03:02:54 christos Exp $"); +__RCSID("$NetBSD: npfd_log.c,v 1.4 2016/12/30 19:55:46 christos Exp $"); #include <sys/types.h> #include <sys/param.h> #include <net/if.h> #include <stdio.h> +#include <err.h> #include <inttypes.h> #include <limits.h> #include <stdlib.h> @@ -54,52 +55,60 @@ struct npfd_log { pcap_dumper_t *dumper; }; +static void +npfd_log_setfilter(npfd_log_t *ctx, const char *filter) +{ + struct bpf_program bprog; + + if (pcap_compile(ctx->pcap, &bprog, filter, 1, 0) == -1) + errx(EXIT_FAILURE, "pcap_compile failed for `%s': %s", filter, + pcap_geterr(ctx->pcap)); + if (pcap_setfilter(ctx->pcap, &bprog) == -1) + errx(EXIT_FAILURE, "pcap_setfilter failed: %s", + pcap_geterr(ctx->pcap)); + pcap_freecode(&bprog); +} + npfd_log_t * -npfd_log_create(unsigned if_idx) +npfd_log_create(const char *ifname, const char *filter, int snaplen) { npfd_log_t *ctx; char errbuf[PCAP_ERRBUF_SIZE]; - if ((ctx = calloc(1, sizeof(*ctx))) == NULL) { - syslog(LOG_ERR, "malloc failed: %m"); - return NULL; - } + if ((ctx = calloc(1, sizeof(*ctx))) == NULL) + err(EXIT_FAILURE, "malloc failed"); /* * Open a live capture handle in non-blocking mode. */ - snprintf(ctx->ifname, sizeof(ctx->ifname), NPFD_NPFLOG "%u", if_idx); + snprintf(ctx->ifname, sizeof(ctx->ifname), "%s", ifname); ctx->pcap = pcap_create(ctx->ifname, errbuf); - if (ctx->pcap == NULL) { - syslog(LOG_ERR, "pcap_create failed: %s", errbuf); - goto err; - } - if (pcap_setnonblock(ctx->pcap, 1, errbuf) == -1) { - syslog(LOG_ERR, "pcap_setnonblock failed: %s", errbuf); - goto err; - } + if (ctx->pcap == NULL) + errx(EXIT_FAILURE, "pcap_create failed: %s", errbuf); - pcap_set_snaplen(ctx->pcap, 10240); + if (pcap_setnonblock(ctx->pcap, 1, errbuf) == -1) + errx(EXIT_FAILURE, "pcap_setnonblock failed: %s", errbuf); - if (pcap_activate(ctx->pcap) == -1) { - syslog(LOG_ERR, "pcap_activate failed: %s", + if (pcap_set_snaplen(ctx->pcap, snaplen) == -1) + errx(EXIT_FAILURE, "pcap_set_snaplen failed: %s", pcap_geterr(ctx->pcap)); - goto err; - } - snprintf(ctx->path, sizeof(ctx->path), "%s/%s%s", - NPFD_LOG_PATH, ctx->ifname, ".pcap"); - if (!npfd_log_reopen(ctx)) - goto err; + if (pcap_activate(ctx->pcap) == -1) + errx(EXIT_FAILURE, "pcap_activate failed: %s", + pcap_geterr(ctx->pcap)); + + if (filter) + npfd_log_setfilter(ctx, filter); + + snprintf(ctx->path, sizeof(ctx->path), NPFD_LOG_PATH "/%s.pcap", + ctx->ifname); + npfd_log_reopen(ctx, true); return ctx; -err: - npfd_log_destroy(ctx); - return NULL; } bool -npfd_log_reopen(npfd_log_t *ctx) +npfd_log_reopen(npfd_log_t *ctx, bool die) { if (ctx->dumper) pcap_dump_close(ctx->dumper); @@ -111,6 +120,9 @@ npfd_log_reopen(npfd_log_t *ctx) else ctx->dumper = pcap_dump_open(ctx->pcap, ctx->path); if (ctx->dumper == NULL) { + if (die) + errx(EXIT_FAILURE, "pcap_dump_open failed for `%s': %s", + ctx->path, pcap_geterr(ctx->pcap)); syslog(LOG_ERR, "pcap_dump_open failed for `%s': %s", ctx->path, pcap_geterr(ctx->pcap)); return false; @@ -135,6 +147,17 @@ npfd_log_getsock(npfd_log_t *ctx) } void +npfd_log_flush(npfd_log_t *ctx) +{ + if (!ctx->dumper) + return; + if (pcap_dump_flush(ctx->dumper) == -1) + syslog(LOG_ERR, "pcap_dump_flush failed for `%s': %m", + ctx->path); +} + + +void npfd_log(npfd_log_t *ctx) { pcap_dumper_t *dumper = ctx->dumper; @@ -152,6 +175,6 @@ npfd_log_stats(npfd_log_t *ctx) syslog(LOG_ERR, "pcap_stats failed: %s", pcap_geterr(pcap)); return; } - syslog(LOG_NOTICE, "packet statistics: %u received, %u dropped", - ps.ps_recv, ps.ps_drop); + syslog(LOG_INFO, "packet statistics: %s: %u received, %u dropped", + ctx->ifname, ps.ps_recv, ps.ps_drop); }