diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2001-08-21 22:29:15 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2001-08-21 22:29:15 +0000 |
commit | e5e30f2482ca9b096309bd325e8d49592595081a (patch) | |
tree | cb2c589f3477200dc0916b319d08546d1831c702 | |
parent | 7dff1ba21af594b36333ddcc34dd74fa7a195d14 (diff) |
pflogd; work by canacar@eee.metu.edu.tr and myself
-rw-r--r-- | sbin/Makefile | 5 | ||||
-rw-r--r-- | sbin/pflogd/Makefile | 10 | ||||
-rw-r--r-- | sbin/pflogd/pflogd.8 | 118 | ||||
-rw-r--r-- | sbin/pflogd/pflogd.c | 322 |
4 files changed, 453 insertions, 2 deletions
diff --git a/sbin/Makefile b/sbin/Makefile index 609cb283d1e..9cc773d607c 100644 --- a/sbin/Makefile +++ b/sbin/Makefile @@ -1,11 +1,12 @@ -# $OpenBSD: Makefile,v 1.61 2001/07/26 21:58:42 miod Exp $ +# $OpenBSD: Makefile,v 1.62 2001/08/21 22:29:14 deraadt Exp $ # Not ported: XNSrouted enpload scsiformat startslip # Missing: icheck SUBDIR= atactl badsect brconfig ccdconfig disklabel dmesg fsck ifconfig init \ iopctl ipsecadm isakmpd kbd lmccontrol mknod modload \ - modunload mount mountd ncheck_ffs nfsd nologin pfctl photurisd ping \ + modunload mount mountd ncheck_ffs nfsd nologin pfctl pflogd \ + photurisd ping \ quotacheck raidctl reboot route routed savecore scan_ffs scsi \ shutdown slattach startkey swapctl sysctl ttyflags umount diff --git a/sbin/pflogd/Makefile b/sbin/pflogd/Makefile new file mode 100644 index 00000000000..9ce0baf0f89 --- /dev/null +++ b/sbin/pflogd/Makefile @@ -0,0 +1,10 @@ +# $OpenBSD: Makefile,v 1.1 2001/08/21 22:29:14 deraadt Exp $ + +CFLAGS+=-Wall -Werror +LDADD+= -lpcap + +PROG= pflogd +SRCS= pflogd.c +MAN= pflogd.8 + +.include <bsd.prog.mk> diff --git a/sbin/pflogd/pflogd.8 b/sbin/pflogd/pflogd.8 new file mode 100644 index 00000000000..83e1fa30f92 --- /dev/null +++ b/sbin/pflogd/pflogd.8 @@ -0,0 +1,118 @@ +.\" $OpenBSD: pflogd.8,v 1.1 2001/08/21 22:29:14 deraadt Exp $ +.\" +.\" Copyright (c) 2001 Can Erkin Acar. All rights reserved. +.\" +.\" 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. +.\" 3. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +.\" +.Dd July 9, 2001 +.Dt PFLOGD 8 +.Os +.Sh NAME +.Nm pflogd +.Nd packet filter loging daemon +.Sh SYNOPSIS +.Nm pflogd +.Op Fl D +.Op Fl d Ar delay +.Op Fl f Ar filename +.Op Fl i Ar interface +.Op Fl s Ar snaplen +.Op Ar expression +.Sh DESCRIPTION +.Nm +is a background daemon which reads packets logged by +.Xr pf 8 +to a logging interface (normally +.Pa pflog0 ) +and writes the packets to a logfile (normally +.Pa /var/log/pflog ) +in +.Xr tcpdump 8 +binary format. +These logs can be reviewed later using the +.Ar -r +option of +.Xr tcpdump 8 . +.Pp +.Nm +closes and then re-opens the log file when it receives +.Va SIGHUP , +permitting +.Xr newsyslog 8 +to rotate logfiles automatically. +.Va SIGALRM +causes +.Nm +to flush the current logfile buffers to the disk, thus making the most +recent logs available. +The buffers are also flushed every +.Ar delay +seconds. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl d Ar delay +Time in seconds to delay between automatic flushes of the file. +This may be specified with a value between 5 and 3600 seconds. +If not specified, the default is 60 seconds. +.It Fl D +Debugging mode. +.Nm +does not disassociate from the controlling terminal. +.It Fl i Ar interface +Specify the interface from which +.Xr pf 8 +logs are read; the default is +.Ar pflog0 . +.It Fl f Ar filename +Log output filename. Default is +.Pa /var/log/pflog . +.It Fl s Ar snaplen +Analyze at most the first +.Ar snaplen +bytes of data from each packet rather than the default of 96. +The default of 96 is adequate for IP, ICMP, TCP, and UDP headers but may +truncate protocol information for other protocols. +.It Ar expression +selects which packets will be dumped, using the regular language of +.Xr tcpdump 8 . +.Sh FILES +.Bl -tag -width /var/run/pflogd.pid -compact +.It Pa /var/run/pflogd.pid +process ID of current +.It Pa /var/log/pflog +Default log file +.El +.Sh SEE ALSO +.Xr pcap 3 , +.Xr pf 4 , +.Xr pf.conf 5 , +.Xr tcpdump 8 , +.Xr newsyslog 8 +.Sh AUTHORS +Can Erkin Acar +.Sh HISTORY +The +.Nm +command appeared in +.Ox 3.0 . diff --git a/sbin/pflogd/pflogd.c b/sbin/pflogd/pflogd.c new file mode 100644 index 00000000000..85706235268 --- /dev/null +++ b/sbin/pflogd/pflogd.c @@ -0,0 +1,322 @@ +/* $OpenBSD: pflogd.c,v 1.1 2001/08/21 22:29:14 deraadt Exp $ */ + +/* + * Copyright (c) 2001 Theo de Raadt + * Copyright (c) 2001 Can Erkin Acar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDERS 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/types.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <pcap-int.h> +#include <pcap.h> +#include <syslog.h> +#include <signal.h> +#include <errno.h> +#include <stdarg.h> +#include <fcntl.h> +#include "util.h" + +#define DEF_SNAPLEN 96 /* default plus allow for larger header of pflog */ +#define PCAP_TO_MS 500 /* pcap read timeout (ms) */ +#define PCAP_NUM_PKTS 1000 /* max number of packets to process at each loop */ +#define PCAP_OPT_FIL 0 /* filter optimization */ +#define FLUSH_DELAY 60 /* flush delay */ + +#define PFLOGD_PID_FILE "/var/run/pflogd.pid" +#define PFLOGD_LOG_FILE "/var/log/pflog" +#define PFLOGD_DEFAULT_IF "pflog0" + +pcap_t *hpcap; +pcap_dumper_t *dpcap; + +int Debug = 0; +int snaplen = DEF_SNAPLEN; +int gotsig_close, gotsig_alrm, gotsig_hup; + +char *filename = PFLOGD_LOG_FILE; +char *interface = PFLOGD_DEFAULT_IF; +char *pidfile = PFLOGD_PID_FILE; +char *filter = 0; + +char errbuf[PCAP_ERRBUF_SIZE]; + +int log_debug = 0; +int delay = FLUSH_DELAY; + +char *copy_argv(char * const *argv); +void logmsg(int priority, const char *message, ...); + +char * +copy_argv(char * const *argv) +{ + int len = 0, n; + char *buf; + + if (argv == NULL) + return NULL; + + for (n = 0; argv[n]; n++) + len += strlen(argv[n])+1; + if (len <= 0) + return NULL; + + buf = malloc(len); + if (buf == NULL) + return NULL; + + strlcpy(buf, argv[0], len); + for (n = 1; argv[n]; n++) { + strlcat(buf, " ", len); + strlcat(buf, argv[n], len); + } + return buf; +} + +void +logmsg(int pri, const char *message, ...) +{ + va_list ap; + va_start(ap, message); + + if (log_debug) + vfprintf(stderr,message,ap); + else + vsyslog(pri,message,ap); + va_end(ap); +} + +void +usage(void) +{ + fprintf(stderr, "usage: pflogd [-a] [-i interface] [-f filename] "); + fprintf(stderr, "[-s snaplen] [tcpdump filter expression]\n"); + exit(1); +} + +void +sig_close(int signal) +{ + gotsig_close = 1; +} + +void +sig_hup(int signal) +{ + gotsig_hup = 1; +} + +void +sig_alrm(int signal) +{ + gotsig_alrm = 1; +} + +int +reset_dump(void) +{ + struct pcap_file_header hdr; + struct stat st; + FILE *fp; + + if (hpcap == NULL) + return 1; + if (dpcap) + pcap_dump_close(dpcap); + + /* + * Basically reimpliment pcap_dump_open() because it truncates + * files and duplicates headers and such. + */ + fp = fopen(filename, "a"); + if (fp == NULL) { + snprintf(hpcap->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", + filename, pcap_strerror(errno)); + logmsg(LOG_ERR, "Error: %s\n", pcap_geterr(hpcap)); + return 1; + } + if (fstat(fileno(fp), &st) == -1) { + snprintf(hpcap->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", + filename, pcap_strerror(errno)); + logmsg(LOG_ERR, "Error: %s\n", pcap_geterr(hpcap)); + return 1; + } + if (st.st_size == 0) + return (0); + +#define TCPDUMP_MAGIC 0xa1b2c3d4 + hdr.magic = TCPDUMP_MAGIC; + hdr.version_major = PCAP_VERSION_MAJOR; + hdr.version_minor = PCAP_VERSION_MINOR; + + hdr.thiszone = hpcap->tzoff; + hdr.snaplen = hpcap->snapshot; + hdr.sigfigs = 0; + hdr.linktype = hpcap->linktype; + + if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1) + return (-1); + return (0); +} + +int +main(int argc, char **argv) +{ + struct bpf_program bprog; + struct pcap_stat pstat; + int ch, np; + FILE *fp; + + while ((ch = getopt(argc, argv, "Dd:i:s:f:")) != -1) { + switch (ch) { + case 'D': + Debug = 1; + break; + case 'd': + delay = atoi(optarg); + if (delay < 5 || delay > 60*60) + usage(); + break; + case 'i': + interface = optarg; + break; + case 'f': + filename = optarg; + break; + case 's': + snaplen = atoi(optarg); + if (snaplen <= 0) + snaplen = DEF_SNAPLEN; + break; + default: + usage(); + } + + } + + log_debug = Debug; + argc -= optind; + argv += optind; + + if (!Debug) { + openlog("pflogd", LOG_PID | LOG_CONS, LOG_DAEMON); + if (daemon(0, 0)) { + logmsg(LOG_WARNING, "Failed to become deamon: %s", + strerror(errno)); + } + fp = fopen(pidfile, "w"); + if (fp != NULL) { + fprintf(fp, "%d\n", getpid()); + fclose(fp); + } + } + + signal(SIGTERM, sig_close); + signal(SIGINT, sig_close); + signal(SIGQUIT, sig_close); + signal(SIGALRM, sig_alrm); + signal(SIGHUP, sig_hup); + alarm(delay); + + if (argc) { + filter = copy_argv(argv); + if (filter == 0) + logmsg(LOG_NOTICE, "Failed to form filter expression"); + } + + hpcap = pcap_open_live(interface, snaplen, 1, PCAP_TO_MS, errbuf); + if (hpcap == NULL) { + logmsg(LOG_ERR, "Failed to initialize: %s\n",errbuf); + exit(1); + } + + if (filter) { + if (pcap_compile(hpcap, &bprog, filter, PCAP_OPT_FIL, 0) < 0) + logmsg(LOG_WARNING, "%s", pcap_geterr(hpcap)); + else if (pcap_setfilter(hpcap, &bprog) < 0) + logmsg(LOG_WARNING, "%s", pcap_geterr(hpcap)); + } + + if (pcap_datalink(hpcap) != DLT_PFLOG) { + logmsg(LOG_ERR, "Invalid datalink type\n"); + pcap_close(hpcap); + exit(1); + } + + if (reset_dump()) { + logmsg(LOG_ERR, "Failed to open log file %s\n", filename); + pcap_close(hpcap); + exit(1); + } + + logmsg(LOG_NOTICE, "Listening on %s, logging to %s, snaplen %d\n", + interface, filename, snaplen); + + while (1) { + np = pcap_dispatch(hpcap, PCAP_NUM_PKTS, pcap_dump, (u_char *)dpcap); + if (np < 0) + logmsg(LOG_NOTICE, "%s\n",pcap_geterr(hpcap)); + + if (gotsig_close) + break; + if (gotsig_hup) { + if (reset_dump()) { + logmsg(LOG_ERR, "Failed to open log file!\n"); + break; + } + logmsg(LOG_NOTICE, "Reopened logfile\n"); + gotsig_hup = 0; + } + + if (gotsig_alrm) { + if (dpcap) + fflush((FILE *)dpcap); /* XXX */ + gotsig_alrm = 0; + alarm(delay); + } + } + + logmsg(LOG_NOTICE, "Exiting due to signal\n"); + if (dpcap) + pcap_dump_close(dpcap); + + if (pcap_stats(hpcap, &pstat) < 0) + logmsg(LOG_WARNING, "Reading stats: %s\n", pcap_geterr(hpcap)); + else + logmsg(LOG_NOTICE, "%d packets received, %d dropped\n", + pstat.ps_recv, pstat.ps_drop); + + pcap_close(hpcap); + if (!Debug) + closelog(); + return 0; +} |