Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 18 Dec 2007 17:52:11 +0600
From:      "Vadim Goncharov" <vadimnuclight@tpu.ru>
To:        "Sergey Matveychuk" <sem@freebsd.org>
Cc:        maxim@freebsd.org, mlaier@freebsd.org, "freebsd-stable@freebsd.org" <freebsd-stable@freebsd.org>, "freebsd-net@freebsd.org" <freebsd-net@freebsd.org>, "freebsd-ipfw@freebsd.org" <freebsd-ipfw@freebsd.org>, "freebsd-current@freebsd.org" <freebsd-current@freebsd.org>
Subject:   Re: [PATCH] ipfwpcap(8)
Message-ID:  <opt3i4k9zg4fjv08@nuclight.avtf.net>
In-Reply-To: <4767AD27.8070901@FreeBSD.org>
References:  <opt3ixkyux17d6mn@nuclight.avtf.net> <4767AD27.8070901@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
------------GJeOyVu3xITaB9Flyz9pX0
Content-Type: text/plain; format=flowed; delsp=yes; charset=koi8-r
Content-Transfer-Encoding: 8bit

18.12.07 @ 17:21 Sergey Matveychuk wrote:

>>  I've recently found a patch (also available at  
>> http://antigreen.org/vadim/freebsd/ipfwpcap/) made by me and my friend  
>> in January to ipfwpcap(8) introduced in 7.0. Now it have more features,
>
> Unfortunately too old to apply.

Mislooked that, sorry. But revision 1.3 differs only with line signal  
(SIGINT, ...); - which my patch also includes. I've attached patch against  
current revision 1.3 (use it instead of original letter's one).

> And using of pidfile_* functions from libutil is preferable IMHO.

Surely, but I think that should be another commit, as not a user-visible  
change.

-- 
WBR, Vadim Goncharov
------------GJeOyVu3xITaB9Flyz9pX0
Content-Disposition: attachment; filename=ipfwpcap.patch
Content-Type: application/octet-stream; name=ipfwpcap.patch
Content-Transfer-Encoding: 8bit

--- ipfwpcap.c.1.3	Tue Dec 18 17:35:14 2007
+++ ipfwpcap.c	Tue Dec 19 08:30:00 2006
@@ -1,95 +1,120 @@
+/*-
+ * Copyright (c) 2004 University of Toronto. All rights reserved.
+ * Anyone may use or copy this software except that this copyright
+ * notice remain intact and that credit is given where it is due.
+ * The University of Toronto and the author make no warranty and
+ * accept no liability for this software.
+ *
+ * $FreeBSD: /repoman/r/ncvs/src/usr.sbin/ipfwpcap/ipfwpcap.c,v 1.2 2006/09/04 19:30:44 sam Exp $
+ */
+
 /*
- * copy diverted (or tee'd) packets to a file in 'tcpdump' format
+ * Copy diverted (or tee'd) packets to a file in 'tcpdump' format
  * (ie. this uses the '-lpcap' routines).
  *
- * example usage:
- *	# ipfwpcap -r 8091 divt.log &
+ * Example usage:
+ *	# ipfwpcap -r 8091 divt.log
  *	# ipfw add 2864 divert 8091 ip from 128.432.53.82 to any
  *	# ipfw add 2864 divert 8091 ip from any to 128.432.53.82
  *
  *   the resulting dump file can be read with ...
  *	# tcpdump -nX -r divt.log
- */
-/*
- * Written by P Kern { pkern [AT] cns.utoronto.ca }
  *
- * Copyright (c) 2004 University of Toronto. All rights reserved.
- * Anyone may use or copy this software except that this copyright
- * notice remain intact and that credit is given where it is due.
- * The University of Toronto and the author make no warranty and
- * accept no liability for this software.
- *
- * From: Header: /local/src/local.lib/SRC/ipfwpcap/RCS/ipfwpcap.c,v 1.4 2004/01/15 16:19:07 pkern Exp
- *
- * $FreeBSD: src/usr.sbin/ipfwpcap/ipfwpcap.c,v 1.3 2007/10/12 14:57:39 csjp Exp $
+ * Written by P Kern { pkern [AT] cns.utoronto.ca }
+ * Adopted by V Pavluk (vladvic_r@mail.ru)
+ *  - changed sighup handler to reopen log file
+ *  - added sigalrm handler to flush data
+ *  - some of exit() codes changed to sysexits(3)
+ * Major code reworking by Vadim Goncharov <vadimnuclight@tpu.ru>
+ *  - signals and daemonizing rewritten
+ *  - style(9) reformat, more sysexits(3) and other cleanups
+ *  - enabled own alarm sending, changed options and updated man page
  */
 
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/param.h>		/* For MAXPATHLEN */
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>	/* For IP_MAXPACKET */
+#include <netinet/ip.h>		/* For IP_MAXPACKET */
+
 #include <stdio.h>
 #include <errno.h>
 #include <paths.h>
 #include <fcntl.h>
 #include <signal.h>
 #include <unistd.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/param.h>		/* for MAXPATHLEN */
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-#include <netinet/in_systm.h>	/* for IP_MAXPACKET */
-#include <netinet/ip.h>		/* for IP_MAXPACKET */
+#include <sysexits.h>
 
 /* XXX normally defined in config.h */
-#define HAVE_STRLCPY 1
-#define HAVE_SNPRINTF 1
-#define HAVE_VSNPRINTF 1
-#include <pcap-int.h>	/* see pcap(3) and /usr/src/contrib/libpcap/. */
+#define HAVE_STRLCPY 	1
+#define HAVE_SNPRINTF 	1
+#define HAVE_VSNPRINTF 	1
+#include <pcap-int.h>		/* See pcap(3) and /usr/src/contrib/libpcap/. */
 
 #ifdef IP_MAXPACKET
-#define BUFMAX	IP_MAXPACKET
+#define BUFMAX		IP_MAXPACKET
 #else
-#define BUFMAX	65535
+#define BUFMAX		65535
 #endif
 
 #ifndef MAXPATHLEN
 #define MAXPATHLEN	1024
 #endif
 
-static int debug = 0;
-static int reflect = 0;		/* 1 == write packet back to socket. */
+#define MAXPIDLEN	9	/* Max decimal pid length in characters. */
+#define DEFINTERVAL	60	/* How often to do flush (in seconds). */
 
-static ssize_t totbytes = 0, maxbytes = 0;
-static ssize_t totpkts = 0, maxpkts = 0;
+static char *prog = NULL;
+static char pidfile[MAXPATHLEN] = { '\0' };
 
-char *prog = NULL;
-char pidfile[MAXPATHLEN] = { '\0' };
+static int quit = 0;		/* Is it time to exit? */
+static int do_flush = 0;	/* Time to flush log. */
+static int do_reopen = 0;	/* Time for log rotating. */
+static int flush_interval = DEFINTERVAL;
 
 /*
- * tidy up.
+ * Tidy up macro.
  */
-void
-quit(sig)
-int sig;
+#define QUIT(code) do {							\
+	pcap_dump_flush(dp);						\
+	(void)unlink(pidfile);						\
+	exit(code);							\
+} while(0);
+
+void 
+quit_sig(int sig)
+{
+	quit = 1;
+}
+
+void 
+flush_log(int sigalrm)
 {
-	(void) unlink(pidfile);
-	exit(sig);
+	do_flush = 1;
+	alarm(flush_interval);
+}
+
+void 
+reopen_log(int sighup)
+{
+	do_reopen = 1;
 }
 
 /*
- * do the "paper work"
- *	- save my own pid in /var/run/$0.{port#}.pid
+ * Do the "paper work".
+ *  - fork and detach from terminal, if needed.
+ *  - save my own pid in /var/run/$0.{port#}.pid.
  */
-okay(pn)
-int pn;
+void 
+okay(int pn, int detach, int nochdir)
 {
-	FILE *fp;
-	int fd, numlen, n;
-	char *p, numbuf[80];
-
-	numlen = sizeof(numbuf);
-	bzero(numbuf, numlen);
-	snprintf(numbuf, numlen-1, "%ld\n", getpid());
-	numlen = strlen(numbuf);
+	int pf;
+	char *p, strpid[MAXPIDLEN + 1];
+	pid_t pid;
 
 	if (pidfile[0] == '\0') {
 		p = (char *)rindex(prog, '/');
@@ -99,94 +124,158 @@
 			"%s%s.%d.pid", _PATH_VARRUN, p, pn);
 	}
 
-	fd = open(pidfile, O_WRONLY|O_CREAT|O_EXCL, 0644);
-	if (fd < 0) { perror(pidfile); exit(21); }
+	pf = open(pidfile, O_WRONLY | O_CREAT | O_EXCL | O_EXLOCK, 0644);
 
-        siginterrupt(SIGTERM, 1);
-        siginterrupt(SIGHUP, 1);
-        signal (SIGTERM, quit);
-        signal (SIGHUP, quit);
-        signal (SIGINT, quit);
-
-	n = write(fd, numbuf, numlen);
-	if (n < 0) { perror(pidfile); quit(23); }
-	(void) close(fd);
+	/*
+	 * We couldn't create pid file
+	 */
+	if (pf == -1) {
+		if (errno == EEXIST) {
+			/*
+			 * If it is because it's already exists
+			 */
+			bzero(strpid, MAXPIDLEN + 1);
+			fprintf(stderr, "PID file already exists!\n");
+
+			/*
+			 * Try to read the PID stored in the existing file
+			 */
+			pf = open(pidfile, O_RDONLY);
+			if (pf == -1) {
+				perror("Error opening PID file for reading");
+				exit(EX_IOERR);
+			}
+			if (read(pf, strpid, MAXPIDLEN) < 0) {
+				perror("Error reading PID file");
+				exit(EX_IOERR);
+			}
+			pid = atol(strpid);
+			close(pf);
+
+			/*
+			 * We found PID, try to determine, whether process
+			 * is running
+			 */
+			if (kill(pid, 0) == 0) {
+				/*
+				 * Signal is delivered, though process with
+				 * such PID exists
+				 */
+				fprintf(stderr, "%s already running with PID=%d, exiting...\n", prog, pid);
+				exit(1);
+			} else {
+				/*
+				 * It seems, like the process is killed, so
+				 * we can proceed...
+				 */
+				fprintf(stderr, "Stale PID file, overwriting...\n");
+				pf = open(pidfile, O_WRONLY | O_TRUNC | O_EXLOCK);
+				if (pf == -1) {
+					perror("Error opening PID file for writing");
+					exit(EX_IOERR);
+				}
+			}
+		} else {
+			perror("Error creating PID file");
+			exit(EX_IOERR);
+		}
+	}
+
+	if (detach) {
+		if (daemon(nochdir, 0) != 0) {
+			close(pf);
+			(void)unlink(pidfile);
+			perror("daemon");
+			exit(EX_OSERR);
+		}
+	}
+
+	/*
+	 * Set signal handlers and system behaviour.  This must be done
+	 * before saving PID to prevent small, but possible race condition
+	 * when another instance failed to create PID, reads it and tries
+	 * to send signal to us.
+	 */
+	siginterrupt(SIGTERM, 1);
+	siginterrupt(SIGHUP, 1);
+
+	/* Ignore 0th signal, or process may be killed with it by default... */
+	signal(0, SIG_IGN);
+	signal(SIGINT, quit_sig);
+	signal(SIGTERM, quit_sig);
+	signal(SIGHUP, reopen_log);
+	signal(SIGALRM, flush_log);
+
+	/* Save our PID to pidfile. */
+	bzero(strpid, MAXPIDLEN + 1);
+	snprintf(strpid, MAXPIDLEN, "%ld\n", getpid());
+	if (write(pf, strpid, strlen(strpid)) < 0) {
+		perror("Error writing PID file");
+		exit(EX_IOERR);
+	}
+	close(pf);
 }
 
+void 
 usage()
 {
-	fprintf(stderr, "\
-\n\
-usage:\n\
-    %s [-dr] [-b maxbytes] [-p maxpkts] [-P pidfile] portnum dumpfile\n\
-\n\
-where:\n\
-	'-d'  = enable debugging messages.\n\
-	'-r'  = reflect. write packets back to the divert socket.\n\
-		(ie. simulate the original intent of \"ipfw tee\").\n\
-	'-rr' = indicate that it is okay to quit if packet-count or\n\
-		byte-count limits are reached (see the NOTE below\n\
-		about what this implies).\n\
-	'-b bytcnt'   = stop dumping after {bytcnt} bytes.\n\
-	'-p pktcnt'   = stop dumping after {pktcnt} packets.\n\
-	'-P pidfile'  = alternate file to store the PID\n\
-			(default: /var/run/%s.{portnum}.pid).\n\
-\n\
-	portnum  = divert(4) socket port number.\n\
-	dumpfile = file to write captured packets (tcpdump format).\n\
-		   (specify '-' to write packets to stdout).\n\
-\n\
-", prog, prog);
-
-	fprintf(stderr, "\
-The '-r' option should not be necessary, but because \"ipfw tee\" is broken\n\
-(see BUGS in ipfw(8) for details) this feature can be used along with\n\
-an \"ipfw divert\" rule to simulate the original intent of \"ipfw tee\".\n\
-\n\
-NOTE: With an \"ipfw divert\" rule, diverted packets will silently\n\
-      disappear if there is nothing listening to the divert socket.\n\
-\n\
-");
-	exit(-1);
+	fprintf(stderr,
+	    "usage: %s [-dz] [-r | -rr] [-i flush_interval] [-b maxbytes] [-p maxpkts] [-P pidfile] portnum dumpfile\n",
+	    prog);
+
+	exit(EX_USAGE);
 }
 
-main(ac, av)
-int ac;
-char *av[];
+main(int argc, char *argv[])
 {
 	int r, sd, portnum, l;
-        struct sockaddr_in sin;
-	int errflg = 0;
+	struct sockaddr_in sin;
+	int errflg = 0, zeroize = 0;
 
 	int nfd;
 	fd_set rds;
 
 	ssize_t nr;
 
-	char *dumpf, buf[BUFMAX];
+	char buf[BUFMAX];
+
+	int debug = 0;
+	int reflect = 0;		/* 1 == write packet back to socket. */
+
+	ssize_t totbytes = 0, maxbytes = 0;
+	ssize_t totpkts = 0, maxpkts = 0;
 
-	pcap_t *p;
-	pcap_dumper_t *dp;
 	struct pcap_pkthdr phd;
+	pcap_t 		*p;
+	pcap_dumper_t	*dp;		/* Global, as signal handlers may want it. */
+	char		*dumpf;
 
-	prog = av[0];
+	prog = argv[0];
 
-	while ((r = getopt(ac, av, "drb:p:P:")) != -1) {
+	while ((r = getopt(argc, argv, "drzb:i:p:P:")) != -1) {
 		switch (r) {
 		case 'd':
-			debug++;
+			debug = 1;
 			break;
 		case 'r':
 			reflect++;
 			break;
+		case 'i':
+			flush_interval = atoi(optarg);
+			if ((flush_interval < 5) || (flush_interval > 3600))
+				flush_interval = DEFINTERVAL;
+			break;
 		case 'b':
-			maxbytes = (ssize_t) atol(optarg);
+			maxbytes = (ssize_t)atol(optarg);
 			break;
 		case 'p':
-			maxpkts = (ssize_t) atoi(optarg);
+			maxpkts = (ssize_t)atoi(optarg);
+			break;
+		case 'z':
+			zeroize = 1;
 			break;
 		case 'P':
-			strcpy(pidfile, optarg);
+			strlcpy(pidfile, optarg, sizeof(pidfile));
 			break;
 		case '?':
 		default:
@@ -195,17 +284,18 @@
 		}
 	}
 
-	if ((ac - optind) != 2 || errflg)
+	if (((argc - optind) != 2) || errflg)
 		usage();
 
-	portnum = atoi(av[optind++]);
-	dumpf = av[optind];
+	portnum = atoi(argv[optind++]);
+	dumpf = argv[optind];
 
-if (debug) fprintf(stderr, "bind to %d.\ndump to '%s'.\n", portnum, dumpf);
+	if (debug)
+		fprintf(stderr, "bind to %d.\ndump to '%s'.\n", portnum, dumpf);
 
 	if ((r = socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT)) == -1) {
 		perror("socket(DIVERT)");
-		exit(2);
+		exit(EX_OSERR);
 	}
 	sd = r;
 
@@ -215,92 +305,136 @@
 
 	if (bind(sd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
 		perror("bind(divert)");
-		exit(3);
+		exit(EX_OSERR);
 	}
 
 	p = pcap_open_dead(DLT_RAW, BUFMAX);
 	dp = pcap_dump_open(p, dumpf);
 	if (dp == NULL) {
 		pcap_perror(p, dumpf);
-		exit(4);
+		exit(EX_OSFILE);
 	}
+	
+	/*
+	 * We will not chdir() to root directory if user specified
+	 * non-absolute pathname to logfile, because in this case
+	 * logfile will be created in another directory after first
+	 * reopening on SIGHUP.
+	 */
+	okay(portnum, !debug, dumpf[0] == '/' ? 0 : 1);
 
-	okay(portnum);
+	alarm(flush_interval);		/* Start timer. */
 
 	nfd = sd + 1;
-	for (;;) {
+	while (!quit) {
+		/*
+		 * Handle signal actions on next iteration after select()'s EINTR.
+		 */
+		if (do_flush) {
+			if (debug)
+				fprintf(stderr, "Flushing log.\n");
+			pcap_dump_flush(dp);
+			do_flush = 0;
+		}
+
+		if (do_reopen) {
+			if (debug)
+				fprintf(stderr, "Reopening log.\n");
+			pcap_dump_close(dp);
+			dp = pcap_dump_open(p, dumpf);
+			if (zeroize) {
+				totbytes = 0;
+				totpkts = 0;
+			}
+			do_reopen = 0;
+		}
+
+		/* Prepare for select(). */
 		FD_ZERO(&rds);
 		FD_SET(sd, &rds);
 
 		r = select(nfd, &rds, NULL, NULL, NULL);
 		if (r == -1) {
-			if (errno == EINTR) continue;
+			if (errno == EINTR)
+				continue;
 			perror("select");
-			quit(11);
+			QUIT(EX_OSERR);
 		}
-
 		if (!FD_ISSET(sd, &rds))
-			/* hmm. no work. */
-			continue;
+			continue;		/* Hmm. No work. */
 
 		/*
-		 * use recvfrom(3 and sendto(3) as in natd(8).
-		 * see /usr/src/sbin/natd/natd.c
-		 * see ipfw(8) about using 'divert' and 'tee'.
+		 * Use recvfrom(3 and sendto(3) as in natd(8).
+		 * See /usr/src/sbin/natd/natd.c.
+		 * See ipfw(8) about using 'divert' and 'tee'.
 		 */
 
 		/*
-		 * read packet.
+		 * Read packet.
 		 */
 		l = sizeof(sin);
 		nr = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr *)&sin, &l);
-if (debug) fprintf(stderr, "recvfrom(%d) = %d (%d)\n", sd, nr, l);
-		if (nr < 0 && errno != EINTR) {
+
+		if (debug)
+			fprintf(stderr, "recvfrom(%d) = %d (%d)\n", sd, nr, l);
+
+		if ((nr < 0) && (errno != EINTR)) {
 			perror("recvfrom(sd)");
-			quit(12);
+			QUIT(EX_IOERR);
 		}
-		if (nr <= 0) continue;
+		if (nr <= 0)
+			continue;
 
-		if (reflect) {
+		if (reflect > 0) {
 			/*
-			 * write packet back so it can continue
-			 * being processed by any further IPFW rules.
+			 * Write packet back so it can continue being
+			 * processed by any further IPFW rules.
 			 */
 			l = sizeof(sin);
 			r = sendto(sd, buf, nr, 0, (struct sockaddr *)&sin, l);
-if (debug) fprintf(stderr, "  sendto(%d) = %d\n", sd, r);
-			if (r < 0) { perror("sendto(sd)"); quit(13); }
+			if (debug)
+				fprintf(stderr, "sendto(%d) = %d\n", sd, r);
+			if (r < 0) {
+				perror("sendto(sd)");
+				QUIT(EX_IOERR);
+			}
 		}
 
 		/*
-		 * check maximums, if any.
-		 * but don't quit if must continue reflecting packets.
+		 * Check maximums, if any. But don't quit if must continue
+		 * reflecting packets. However, it's ok to exit when
+		 * reflect > 1.
 		 */
 		if (maxpkts) {
 			totpkts++;
 			if (totpkts > maxpkts) {
-				if (reflect == 1) continue;
-				quit(0);
+				if (reflect == 1)
+					continue;
+				QUIT(EX_OK);
 			}
 		}
 		if (maxbytes) {
 			totbytes += nr;
 			if (totbytes > maxbytes) {
-				if (reflect == 1) continue;
-				quit(0);
+				if (reflect == 1)
+					continue;
+				QUIT(EX_OK);
 			}
 		}
 
 		/*
-		 * save packet in tcpdump(1) format. see pcap(3).
-		 * divert packets are fully assembled. see ipfw(8).
+		 * Save packet in tcpdump(1) format. See pcap(3). Divert
+		 * packets are fully assembled, see ipfw(8).
 		 */
-		(void) gettimeofday(&(phd.ts), NULL);
+		(void)gettimeofday(&(phd.ts), NULL);
 		phd.caplen = phd.len = nr;
 		pcap_dump((u_char *)dp, &phd, buf);
-		if (ferror((FILE *)dp)) { perror(dumpf); quit(14); }
-		(void) fflush((FILE *)dp);
+		if (ferror((FILE *)dp)) {
+			perror(dumpf);
+			QUIT(EX_IOERR);
+		}
+
 	}
 
-	quit(0);
+	QUIT(EX_OK);
 }
--- ipfwpcap.8.orig	Sat Nov 11 05:08:21 2006
+++ ipfwpcap.8	Thu Dec 21 09:04:28 2006
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD: /repoman/r/ncvs/src/usr.sbin/ipfwpcap/ipfwpcap.8,v 1.3 2006/09/30 19:07:03 ru Exp $
 .\"
-.Dd May 22, 2006
+.Dd Dec 20, 2006
 .Dt IPFWPCAP 8
 .Os
 .Sh NAME
@@ -32,7 +32,9 @@
 .Nd "copy diverted packets to a file in tcpdump format"
 .Sh SYNOPSIS
 .Nm
-.Op Fl dr
+.Op Fl dz
+.Op Fl r | rr
+.Op Fl i Ar flush_interval
 .Op Fl b Ar maxbytes
 .Op Fl p Ar maxpkts
 .Op Fl P Ar pidfile
@@ -48,19 +50,44 @@
 .Xr ipfw 8
 to a port on which
 .Nm
-listens.
+daemon listens.
 The packets are then dropped unless
 .Fl r
 is used.
 .Pp
+.Nm
+closes and then re-opens the dump file when it receives
+.Dv SIGHUP ,
+permitting
+.Xr newsyslog 8
+to rotate dump logfiles automatically.
+Note that already existing file will be truncated on open or re-open.
+Receiving
+.Dv 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 flush_interval
+seconds.
+.Pp
 The options are as follows:
 .Bl -tag -width indent
 .It Fl d
-Turns on extra debugging messages.
+Turns on debugging messages and prevents
+.Nm
+from making itself a background daemon.
 .It Fl r
 Writes packets back to the
 .Xr divert 4
 socket.
+This option can be used to reflect packets back to
+.Xr ipfw 8
+if you for some reasons want to use
+.Dq divert
+rule action instead of usually more suitable
+.Dq tee .
 .It Fl rr
 Indicates that it is okay to quit if
 .Ar maxbytes
@@ -74,6 +101,17 @@
 Stop dumping after
 .Ar maxbytes
 bytes.
+Note that size of resulting
+.Ar dumpfile
+will be greater than
+.Ar maxbytes
+because
+.Xr pcap 3
+stores additional headers for each packet in the file.
+.It Fl i Ar flush_interval
+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 p Ar maxpkts
 Stop dumping after
 .Ar maxpkt
@@ -81,7 +119,10 @@
 .It Fl P Ar pidfile
 File to store PID number in.
 Default is
-.Pa /var/run/ipwfpcap.portnr.pid .
+.Pa /var/run/ipwfpcap. Ns Ao Ar portnum Ac Ns Pa .pid .
+.It Fl z
+Reset byte and packet counters to zero after each reopening of the
+.Ar dumpfile .
 .El
 .Pp
 The
@@ -98,7 +139,7 @@
 .Sh EXIT STATUS
 .Ex -std
 .Sh EXAMPLES
-.Dl "ipfwpcap -r 8091 divt.log &"
+.Dl "ipfwpcap -r 8091 divt.log"
 .Pp
 Starts
 .Nm
@@ -117,12 +158,13 @@
 .Xr tcpdump 1 ,
 .Xr pcap 3 ,
 .Xr divert 4 ,
-.Xr ipfw 8
+.Xr ipfw 8 ,
+.Xr pflogd 8
 .Sh HISTORY
 The
 .Nm
 utility first appeared in
-.Fx 7.0 .
+.Fx 6.3 .
 .Sh AUTHORS
 .An -nosplit
 .Nm

------------GJeOyVu3xITaB9Flyz9pX0--




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?opt3i4k9zg4fjv08>