Add some very preliminary npfd(8) code.

This commit is contained in:
rmind 2016-12-27 22:20:00 +00:00
parent 77ce73405e
commit 61e84d3fc1
4 changed files with 324 additions and 0 deletions

View File

@ -0,0 +1,17 @@
# $NetBSD: Makefile,v 1.1 2016/12/27 22:20:00 rmind Exp $
#
# Public Domain
#
PROG= npfd
SRCS= npfd.c
CPPFLAGS+= -I${.CURDIR}
LDADD+= -lnpf -lpcap
DPADD+= ${LIBNPF} ${LIBPCAP}
WARNS= 5
NOLINT= # disabled deliberately
.include <bsd.prog.mk>

127
usr.sbin/npf/npfd/npfd.c Normal file
View File

@ -0,0 +1,127 @@
/* $NetBSD: npfd.c,v 1.1 2016/12/27 22:20:00 rmind Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Mindaugas Rasiukevicius.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: npfd.c,v 1.1 2016/12/27 22:20:00 rmind Exp $");
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <syslog.h>
#include "npfd.h"
static volatile sig_atomic_t hup = false;
int
npfd_getctl(void)
{
int fd;
fd = open(NPF_DEV_PATH, O_RDONLY);
if (fd == -1) {
err(EXIT_FAILURE, "cannot open '%s'", NPF_DEV_PATH);
}
if (ioctl(fd, IOC_NPF_VERSION, &ver) == -1) {
err(EXIT_FAILURE, "ioctl(IOC_NPF_VERSION)");
}
if (ver != NPF_VERSION) {
errx(EXIT_FAILURE,
"incompatible NPF interface version (%d, kernel %d)\n"
"Hint: update userland?", NPF_VERSION, ver);
}
return fd;
}
static void
npfd_event_loop(void)
{
int fds[8], fd, nfds = 0, maxfd = 0;
fd_set rfds;
FD_ZERO(&rfds);
fd = npfd_log_create(0)
fds[nfds++] = fd;
FD_SET(fd, &rfds);
for (int i = 0; i < nfds; i++) {
maxfd = MAX(maxfd, fds[i] + 1);
}
while (!done) {
if ((ret = select(maxfd, &rfds, NULL, NULL, NULL)) == -1) {
syslog(LOG_ERR, "select failed: %m");
err(EXIT_FAILURE, "select");
}
if (hup) {
hup = false;
}
for (fd = 0; fd < maxfd; fd++) {
// TODO
}
}
}
static void
sighup_handler(int sig)
{
hup = true;
}
int
main(int argc, char **argv)
{
bool daemon_off = false;
int ch;
while ((ch = getopt(argc, argv, "d")) != -1) {
switch (ch) {
case 'd':
daemon_off = true;
break;
default:
errx(EXIT_FAILURE, "usage:\n\t%s [ -d ]", argv[0]);
}
}
openlog(argv[0], LOG_PID | LOG_NDELAY | LOG_CONS, LOG_DAEMON);
if (!daemon_off && daemon(0, 0) == -1) {
syslog(LOG_ERR, "daemon failed: %m");
err(EXIT_FAILURE, "daemon");
}
signal(SIGHUP, sighup_handler);
npfd_event_loop();
closelog();
return 0;
}

49
usr.sbin/npf/npfd/npfd.h Normal file
View File

@ -0,0 +1,49 @@
/* $NetBSD: npfd.h,v 1.1 2016/12/27 22:20:00 rmind Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Mindaugas Rasiukevicius.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _NPFD_H_
#define _NPFD_H_
#define PCAP_NPACKETS 1024
#define NPFD_LOG_PATH "/var/log"
#define NPFD_NPFLOG "npflog"
#define NPFD_NPFLOG_LEN (sizeof(NPFD_NPFLOG) - 1)
struct npf_log;
typedef struct npfd_log npfd_log_t;
npfd_log_t * npfd_log_create(unsigned);
void npfd_log_destroy(npfd_log_t *);
int npfd_log_getsock(npfd_log_t *);
void npfd_log(npfd_log_t *);
#endif

View File

@ -0,0 +1,131 @@
/* $NetBSD: npfd_log.c,v 1.1 2016/12/27 22:20:00 rmind Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Mindaugas Rasiukevicius.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: npfd_log.c,v 1.1 2016/12/27 22:20:00 rmind Exp $");
#include <stdio.h>
#include <inttypes.h>
#include <limits.h>
#include <pcap/pcap.h>
struct npfd_log {
pcap_t * pcap;
pcap_dumper_t * dumper;
};
npfd_log_t *
npfd_log_create(unsigned if_idx)
{
npfd_log_t *ctx;
char errbuf[PCAP_ERRBUF_SIZE];
char ifname[IFNAMSIZ], path[PATH_MAX];
FILE *fp;
if ((ctx = calloc(1, sizeof(npfd_log_t))) == NULL) {
syslog(LOG_ERR, "malloc failed: %m");
return NULL;
}
/*
* Open a live capture handle in non-blocking mode.
*/
snprintf(ifname, sizeof(ifname), NPFD_NPFLOG "%u", if_idx);
pcap = pcap_create(ifname, errbuf);
if ((ctx->pcap = pcap) == NULL) {
syslog(LOG_ERR, "pcap_create failed: %s", errbuf);
goto err;
}
if (pcap_setnonblock(pcap, 1, errbuf) == -1) {
syslog(LOG_ERR, "pcap_setnonblock failed: %s", errbuf);
goto err;
}
pcap_set_snaplen(pcap, snaplen);
/*
* Open a log file to write for a given interface and dump there.
*/
snprintf(path, sizeof(path), "%s/%s%s", NPFD_LOG_PATH, ifname, ".pcap");
if ((fp = fopen(path, "w")) == NULL) {
syslog(LOG_ERR, "open failed: %m");
goto err;
}
if ((ctx->dumper = pcap_dump_fopen(pcap, fp)) == NULL) {
syslog(LOG_ERR, "pcap_dump_fopen failed: %s", errbuf);
goto err;
}
return ctx;
err:
if (!ctx->dumper && fp) {
fclose(fp);
}
npfd_log_destroy(ctx);
return NULL;
}
void
npfd_log_destroy(npfd_log_t *ctx)
{
if (ctx->dumper)
pcap_dump_close(ctx->dumper);
if (ctx->pcap)
pcap_close(ctx->pcap);
free(ctx);
}
int
npfd_log_getsock(npfd_log_t *ctx)
{
return pcap_get_selectable_fd(ctx->pcap);
}
void
npfd_log(npfd_log_t *ctx)
{
pcap_dumper_t *dumper = ctx->dumper;
pcap_dispatch(ctx->pcap, PCAP_NPACKETS, pcap_dump, (uint8_t *)dumper);
}
void
npfd_log_stats(npfd_log_t *ctx)
{
pcap_t *pcap = ctx->pcap;
struct pcap_stat ps;
if (pcap_stats(pcap, &ps) == -1)
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);
}