Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.sbin/npf/npfd Add log validation



details:   https://anonhg.NetBSD.org/src/rev/d5ffe523a3bd
branches:  trunk
changeset: 820305:d5ffe523a3bd
user:      christos <christos%NetBSD.org@localhost>
date:      Fri Jan 06 19:20:24 2017 +0000

description:
Add log validation

diffstat:

 usr.sbin/npf/npfd/Makefile   |    4 +-
 usr.sbin/npf/npfd/npfd.c     |   24 ++++-
 usr.sbin/npf/npfd/npfd.h     |    4 +-
 usr.sbin/npf/npfd/npfd_log.c |  173 ++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 185 insertions(+), 20 deletions(-)

diffs (truncated from 350 to 300 lines):

diff -r 2fa4e5b7b330 -r d5ffe523a3bd usr.sbin/npf/npfd/Makefile
--- a/usr.sbin/npf/npfd/Makefile        Fri Jan 06 17:26:41 2017 +0000
+++ b/usr.sbin/npf/npfd/Makefile        Fri Jan 06 19:20:24 2017 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.3 2016/12/30 19:55:46 christos Exp $
+# $NetBSD: Makefile,v 1.4 2017/01/06 19:20:24 christos Exp $
 #
 # Public Domain
 #
@@ -6,7 +6,7 @@
 NOMAN=
 PROG=          npfd
 
-#DBG=-g
+DBG=-g
 SRCS=          npfd.c npfd_log.c
 CPPFLAGS+=     -I${.CURDIR}
 
diff -r 2fa4e5b7b330 -r d5ffe523a3bd usr.sbin/npf/npfd/npfd.c
--- a/usr.sbin/npf/npfd/npfd.c  Fri Jan 06 17:26:41 2017 +0000
+++ b/usr.sbin/npf/npfd/npfd.c  Fri Jan 06 19:20:24 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npfd.c,v 1.4 2016/12/30 19:55:46 christos Exp $        */
+/*     $NetBSD: npfd.c,v 1.5 2017/01/06 19:20:24 christos Exp $        */
 
 /*-
  * Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: npfd.c,v 1.4 2016/12/30 19:55:46 christos Exp $");
+__RCSID("$NetBSD: npfd.c,v 1.5 2017/01/06 19:20:24 christos Exp $");
 
 #include <stdio.h>
 #include <string.h>
@@ -49,7 +49,7 @@
 
 #include "npfd.h"
 
-static volatile sig_atomic_t hup, stats, done;
+static volatile sig_atomic_t hup, stats, done, flush;
 
 static int
 npfd_getctl(void)
@@ -87,6 +87,9 @@
                if (stats) {
                        stats = false;
                        npfd_log_stats(log);
+               }
+               if (flush) {
+                       flush = false;
                        npfd_log_flush(log);
                }
                switch (poll(&pfd, 1, delay)) {
@@ -118,9 +121,11 @@
                done = true;
                break;
        case SIGINFO:
-       case SIGQUIT:
                stats = true;
                break;
+       case SIGALRM:
+               flush = true;
+               break;
        default:
                syslog(LOG_ERR, "Unhandled signal %d", sig);
                break;
@@ -131,7 +136,8 @@
 usage(void)
 {
        fprintf(stderr, "Usage: %s [-D] [-d <delay>] [-i <interface>]"
-           " [-p <pidfile>] [-s <snaplen>] expression\n", getprogname());
+           " [-f <filename>] [-p <pidfile>] [-s <snaplen>] expression\n",
+           getprogname());
        exit(EXIT_FAILURE);
 }
 
@@ -165,11 +171,12 @@
        const char *iface = "npflog0";
        int snaplen = 116;
        char *pidname = NULL;
+       char *filename = NULL;
 
        int fd = npfd_getctl();
        (void)close(fd);
 
-       while ((ch = getopt(argc, argv, "Dd:i:p:s:")) != -1) {
+       while ((ch = getopt(argc, argv, "Dd:f:i:p:s:")) != -1) {
                switch (ch) {
                case 'D':
                        daemon_off = true;
@@ -177,6 +184,9 @@
                case 'd':
                        delay = atoi(optarg) * 1000;
                        break;
+               case 'f':
+                       filename = optarg;
+                       break;
                case 'i':
                        iface = optarg;
                        break;
@@ -196,7 +206,7 @@
 
        char *filter = copyargs(argc, argv);
 
-       npfd_log_t *log = npfd_log_create(iface, filter, snaplen);
+       npfd_log_t *log = npfd_log_create(filename, iface, filter, snaplen);
 
        if (!daemon_off) {
                if (daemon(0, 0) == -1)
diff -r 2fa4e5b7b330 -r d5ffe523a3bd usr.sbin/npf/npfd/npfd.h
--- a/usr.sbin/npf/npfd/npfd.h  Fri Jan 06 17:26:41 2017 +0000
+++ b/usr.sbin/npf/npfd/npfd.h  Fri Jan 06 19:20:24 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npfd.h,v 1.3 2016/12/30 19:55:46 christos Exp $        */
+/*     $NetBSD: npfd.h,v 1.4 2017/01/06 19:20:24 christos Exp $        */
 
 /*-
  * Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -42,7 +42,7 @@
 struct npf_log;
 typedef struct npfd_log npfd_log_t;
 
-npfd_log_t *   npfd_log_create(const char *, const char *, int);
+npfd_log_t *   npfd_log_create(const char *, 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);
diff -r 2fa4e5b7b330 -r d5ffe523a3bd usr.sbin/npf/npfd/npfd_log.c
--- a/usr.sbin/npf/npfd/npfd_log.c      Fri Jan 06 17:26:41 2017 +0000
+++ b/usr.sbin/npf/npfd/npfd_log.c      Fri Jan 06 19:20:24 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npfd_log.c,v 1.5 2017/01/05 16:23:31 christos Exp $    */
+/*     $NetBSD: npfd_log.c,v 1.6 2017/01/06 19:20:24 christos Exp $    */
 
 /*-
  * Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -30,10 +30,12 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: npfd_log.c,v 1.5 2017/01/05 16:23:31 christos Exp $");
+__RCSID("$NetBSD: npfd_log.c,v 1.6 2017/01/06 19:20:24 christos Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
+#include <sys/stat.h>
+
 #include <net/if.h>
 
 #include <stdio.h>
@@ -69,8 +71,138 @@
        pcap_freecode(&bprog);
 }
 
+static FILE *
+npfd_log_gethdr(npfd_log_t *ctx, struct pcap_file_header*hdr)
+{
+       FILE *fp = fopen(ctx->path, "r");
+
+       hdr->magic = 0;
+       if (fp == NULL)
+               return NULL;
+
+#define TCPDUMP_MAGIC 0xa1b2c3d4
+
+       switch (fread(hdr, sizeof(*hdr), 1, fp)) {
+       case 0:
+               hdr->magic = 0;
+               fclose(fp);
+               return NULL;
+       case 1:
+               if (hdr->magic != TCPDUMP_MAGIC ||
+                   hdr->version_major != PCAP_VERSION_MAJOR ||
+                   hdr->version_minor != PCAP_VERSION_MINOR)
+                       goto out;
+               break;
+       default:
+               goto out;
+       }
+
+       return fp;
+out:
+       fclose(fp);
+       hdr->magic = -1;
+       return NULL;
+}
+
+static int
+npfd_log_getsnaplen(npfd_log_t *ctx)
+{
+       struct pcap_file_header hdr;
+       FILE *fp = npfd_log_gethdr(ctx, &hdr);
+       if (fp == NULL)
+               return hdr.magic == (uint32_t)-1 ? -1 : 0;
+       fclose(fp);
+       return hdr.snaplen;
+}
+
+static int
+npfd_log_validate(npfd_log_t *ctx)
+{
+       struct pcap_file_header hdr;
+       FILE *fp = npfd_log_gethdr(ctx, &hdr);
+       size_t o, no;
+
+       if (fp == NULL) {
+               if (hdr.magic == 0)
+                       return 0;
+               goto rename;
+       }
+
+       struct stat st;
+       if (fstat(fileno(fp), &st) == -1)
+               goto rename;
+
+       size_t count = 0;
+       for (o = sizeof(hdr);; count++) {
+               struct {
+                       uint32_t sec;
+                       uint32_t usec;
+                       uint32_t caplen;
+                       uint32_t len;
+               } pkt;
+               switch (fread(&pkt, sizeof(pkt), 1, fp)) {
+               case 0:
+                       syslog(LOG_INFO, "%zu packets read from `%s'", count,
+                           ctx->path);
+                       fclose(fp);
+                       return hdr.snaplen;
+               case 1:
+                       no = o + sizeof(pkt) + pkt.caplen;
+                       if (pkt.caplen > hdr.snaplen)
+                               goto fix;
+                       if (no > (size_t)st.st_size)
+                               goto fix;
+                       if (fseeko(fp, pkt.caplen, SEEK_CUR) != 0)
+                               goto fix;
+                       o = no;
+                       break;
+               default:
+                       goto fix;
+               }
+       }
+
+fix:
+       fclose(fp);
+       no = st.st_size - o;
+       syslog(LOG_INFO, "%zu packets read from `%s', %zu extra bytes",
+           count, ctx->path, no);
+       if (no < 10240) {
+               syslog(LOG_WARNING,
+                   "Incomplete last packet in `%s', truncating",
+                   ctx->path);
+               if (truncate(ctx->path, o) == -1) {
+                       syslog(LOG_ERR, "Cannot truncate `%s': %m", ctx->path);
+                       goto rename;
+               }
+       } else {
+               syslog(LOG_ERR, "Corrupt file `%s'", ctx->path);
+               goto rename;
+       }
+       fclose(fp);
+       return hdr.snaplen;
+rename:
+       fclose(fp);
+       char tmp[MAXPATHLEN];
+       snprintf(tmp, sizeof(tmp), "%s.XXXXXX", ctx->path);
+       int fd;
+       if ((fd = mkstemp(tmp)) == -1) {
+               syslog(LOG_ERR, "Can't make temp file `%s': %m", tmp);
+               return -1;
+       }
+       close(fd);
+       if (rename(ctx->path, tmp) == -1) {
+               syslog(LOG_ERR, "Can't rename `%s' to `%s': %m",
+                   ctx->path, tmp);
+               return -1;
+       }
+       syslog(LOG_ERR, "Renamed to `%s'", tmp);
+       return 0;
+}
+       
+
 npfd_log_t *
-npfd_log_create(const char *ifname, const char *filter, int snaplen)
+npfd_log_create(const char *filename, const char *ifname, const char *filter,
+    int snaplen)
 {
        npfd_log_t *ctx;
        char errbuf[PCAP_ERRBUF_SIZE];
@@ -89,6 +221,22 @@
        if (pcap_setnonblock(ctx->pcap, 1, errbuf) == -1)
                errx(EXIT_FAILURE, "pcap_setnonblock failed: %s", errbuf);
 
+       if (filename == NULL)
+               snprintf(ctx->path, sizeof(ctx->path), NPFD_LOG_PATH "/%s.pcap",
+                   ctx->ifname);
+       else



Home | Main Index | Thread Index | Old Index