Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 18 Dec 2007 15:20:48 +0600
From:      "Vadim Goncharov" <vadim_nuclight@mail.ru>
To:        "freebsd-ipfw@freebsd.org" <freebsd-ipfw@freebsd.org>, "freebsd-current@freebsd.org" <freebsd-current@freebsd.org>, "freebsd-net@freebsd.org" <freebsd-net@freebsd.org>, "freebsd-stable@freebsd.org" <freebsd-stable@freebsd.org>
Cc:        maxim@freebsd.org, mlaier@freebsd.org
Subject:   [PATCH] ipfwpcap(8)
Message-ID:  <opt3ixkyux17d6mn@nuclight.avtf.net>

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

Hi,

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, some  
of which were already present in pflogd(8) counterpart. Patched version  
were tested in about to 200 parallel processes, on both 5.5 and 6.2 for  
half a year, without any bugs.

If possible, could it be committed to ongoing 7.0-RELEASE ? It would be  
nice to not break POLA after release is being stable and widely available  
(some option meaning were changed (to be more consistent with pflogd and  
overall FreeBSD-ish, though), but I forgot to post it earlier, before  
7.0-STABLE fork, sorry). Please.

List of changes:

1. Program now daemonizes itself by defaul, and -d option not only enables  
debug, but cancels daemonizing too.
2. Log is now re-opened on SIGHUP; if log pathname was not absolute, will  
not do chdir("/") after daemonizing.
3. Log is now flushed on SIGALRM, new option -i can be used to specify  
flush interval (using alarm(3)), default is 60 seconds.
4. Added option -z, which resets log-limiting counters to zero on each log  
re-open.
5. Added pid-file checking - if exists, check if process with it's value  
still exists (ignore signal 0 ourselves), if not, rewrite stale pid-file  
and begin working.
6. Signal handlers now do only variable setting, all work is done in main  
loop, changed from for(;;) to while(!quit).
7. Minor changes - less global variables, changed strcpy() -> strlcpy(),  
added some macros, less output from usage (as we now have manpage), most  
exit codes changed from custom ones to sysexits(3).
8. More style(9), and new features are documented in man page, some old  
statements in man were made more detailed.

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

--- ipfwpcap.c.orig	Sat Nov 11 05:22:06 2006
+++ 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: /repoman/r/ncvs/src/usr.sbin/ipfwpcap/ipfwpcap.c,v 1.2 2006/09/04 19:30:44 sam 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)
+{
+	do_flush = 1;
+	alarm(flush_interval);
+}
+
+void 
+reopen_log(int sighup)
 {
-	(void) unlink(pidfile);
-	exit(sig);
+	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,93 +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);
-
-	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:
@@ -194,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;
 
@@ -214,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

------------2UNlkgEOncIwckbiXYzy0f--




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