From owner-freebsd-ipfw@FreeBSD.ORG Mon Dec 17 11:06:59 2007 Return-Path: Delivered-To: freebsd-ipfw@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5C8DE16A5C3 for ; Mon, 17 Dec 2007 11:06:59 +0000 (UTC) (envelope-from owner-bugmaster@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 5DD2313C442 for ; Mon, 17 Dec 2007 11:06:59 +0000 (UTC) (envelope-from owner-bugmaster@FreeBSD.org) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.2/8.14.2) with ESMTP id lBHB6x6W088251 for ; Mon, 17 Dec 2007 11:06:59 GMT (envelope-from owner-bugmaster@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.2/8.14.1/Submit) id lBHB6wdG088247 for freebsd-ipfw@FreeBSD.org; Mon, 17 Dec 2007 11:06:58 GMT (envelope-from owner-bugmaster@FreeBSD.org) Date: Mon, 17 Dec 2007 11:06:58 GMT Message-Id: <200712171106.lBHB6wdG088247@freefall.freebsd.org> X-Authentication-Warning: freefall.freebsd.org: gnats set sender to owner-bugmaster@FreeBSD.org using -f From: FreeBSD bugmaster To: freebsd-ipfw@FreeBSD.org Cc: Subject: Current problem reports assigned to freebsd-ipfw@FreeBSD.org X-BeenThere: freebsd-ipfw@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: IPFW Technical Discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 17 Dec 2007 11:06:59 -0000 Current FreeBSD problem reports Critical problems Serious problems S Tracker Resp. Description -------------------------------------------------------------------------------- o kern/51274 ipfw [ipfw] [patch] ipfw2 create dynamic rules with parent o kern/73910 ipfw [ipfw] serious bug on forwarding of packets after NAT o kern/74104 ipfw [ipfw] ipfw2/1 conflict not detected or reported, manp o kern/88659 ipfw [modules] ipfw and ip6fw do not work properly as modul o kern/93300 ipfw [ipfw] ipfw pipe lost packets o kern/95084 ipfw [ipfw] [patch] IPFW2 ignores "recv/xmit/via any" (IPFW o kern/97504 ipfw [ipfw] IPFW Rules bug o kern/97951 ipfw [ipfw] [patch] ipfw does not tie interface details to o kern/98831 ipfw [ipfw] ipfw has UDP hickups o kern/102471 ipfw [ipfw] [patch] add tos and dscp support o kern/103454 ipfw [ipfw] [patch] add a facility to modify DF bit of the o kern/106534 ipfw [ipfw] [panic] ipfw + dummynet o kern/112708 ipfw ipfw is seems to be broken to limit number of connecti o kern/117234 ipfw [ipfw] [patch] ipfw send_pkt() and ipfw_tick() don't s 14 problems total. Non-critical problems S Tracker Resp. Description -------------------------------------------------------------------------------- a kern/26534 ipfw [ipfw] Add an option to ipfw to log gid/uid of who cau o kern/46159 ipfw [ipfw] [patch] ipfw dynamic rules lifetime feature o kern/48172 ipfw [ipfw] [patch] ipfw does not log size and flags o bin/50749 ipfw [ipfw] [patch] ipfw2 incorrectly parses ports and port o kern/55984 ipfw [ipfw] [patch] time based firewalling support for ipfw o kern/60719 ipfw [ipfw] Headerless fragments generate cryptic error mes o kern/69963 ipfw [ipfw] install_state warning about already existing en o kern/71366 ipfw [ipfw] "ipfw fwd" sometimes rewrites destination mac a o kern/72987 ipfw [ipfw] ipfw/dummynet pipe/queue 'queue [BYTES]KBytes ( o kern/73276 ipfw [ipfw] [patch] ipfw2 vulnerability (parser error) o bin/78785 ipfw [ipfw] [patch] ipfw verbosity locks machine if /etc/rc o kern/80642 ipfw [ipfw] [patch] ipfw small patch - new RULE OPTION o kern/82724 ipfw [ipfw] [patch] Add setnexthop and defaultroute feature o kern/86957 ipfw [ipfw] [patch] ipfw mac logging o kern/87032 ipfw [ipfw] [patch] ipfw ioctl interface implementation o kern/91847 ipfw [ipfw] ipfw with vlanX as the device o kern/103328 ipfw [ipfw] sugestions about ipfw table o kern/104682 ipfw [ipfw] [patch] Some minor language consistency fixes a o bin/104921 ipfw [patch] ipfw(8) sometimes treats ipv6 input as ipv4 (a o kern/105330 ipfw [ipfw] [patch] ipfw (dummynet) does not allow to set q o kern/107305 ipfw [ipfw] ipfw fwd doesn't seem to work o kern/111713 ipfw [dummynet] Too few dummynet queue slots o kern/112561 ipfw [ipfw] ipfw fwd does not work with some TCP packets p kern/113388 ipfw [ipfw][patch] Addition actions with rules within speci o bin/113803 ipfw [patch] bin/ipfw.8 - don't get bitten by the fwd rule o bin/115172 ipfw [patch] ipfw(8) list show some rules with a wrong form p kern/115755 ipfw [ipfw][patch] unify message and add a rule number wher o kern/116009 ipfw [ipfw] [patch] Ignore errors when loading ruleset from 28 problems total. From owner-freebsd-ipfw@FreeBSD.ORG Tue Dec 18 09:51:30 2007 Return-Path: Delivered-To: freebsd-ipfw@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id E231416A475; Tue, 18 Dec 2007 09:51:30 +0000 (UTC) (envelope-from vadim_nuclight@mail.ru) Received: from mx4.mail.ru (fallback.mail.ru [194.67.57.14]) by mx1.freebsd.org (Postfix) with ESMTP id D09A213C4EC; Tue, 18 Dec 2007 09:51:29 +0000 (UTC) (envelope-from vadim_nuclight@mail.ru) Received: from mx30.mail.ru (mx30.mail.ru [194.67.23.238]) by mx4.mail.ru (mPOP.Fallback_MX) with ESMTP id 9A14A10B366A; Tue, 18 Dec 2007 12:20:53 +0300 (MSK) Received: from [78.140.2.237] (port=26518 helo=nuclight.avtf.net) by mx30.mail.ru with esmtp id 1J4Yd9-000FkY-00; Tue, 18 Dec 2007 12:20:51 +0300 Date: Tue, 18 Dec 2007 15:20:48 +0600 To: "freebsd-ipfw@freebsd.org" , "freebsd-current@freebsd.org" , "freebsd-net@freebsd.org" , "freebsd-stable@freebsd.org" From: "Vadim Goncharov" Organization: AVTF TPU Hostel Content-Type: multipart/mixed; boundary=----------2UNlkgEOncIwckbiXYzy0f MIME-Version: 1.0 Message-ID: User-Agent: Opera M2/7.54 (Win32, build 3865) Cc: maxim@freebsd.org, mlaier@freebsd.org, phk@freebsd.org Subject: [PATCH] ipfwpcap(8) X-BeenThere: freebsd-ipfw@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: IPFW Technical Discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 18 Dec 2007 09:51:31 -0000 ------------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 + * - signals and daemonizing rewritten + * - style(9) reformat, more sysexits(3) and other cleanups + * - enabled own alarm sending, changed options and updated man page */ +#include +#include +#include /* For MAXPATHLEN */ +#include +#include + +#include +#include /* For IP_MAXPACKET */ +#include /* For IP_MAXPACKET */ + #include #include #include #include #include #include -#include -#include -#include /* for MAXPATHLEN */ -#include -#include - -#include /* for IP_MAXPACKET */ -#include /* for IP_MAXPACKET */ +#include /* XXX normally defined in config.h */ -#define HAVE_STRLCPY 1 -#define HAVE_SNPRINTF 1 -#define HAVE_VSNPRINTF 1 -#include /* see pcap(3) and /usr/src/contrib/libpcap/. */ +#define HAVE_STRLCPY 1 +#define HAVE_SNPRINTF 1 +#define HAVE_VSNPRINTF 1 +#include /* 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-- From owner-freebsd-ipfw@FreeBSD.ORG Tue Dec 18 11:52:23 2007 Return-Path: Delivered-To: freebsd-ipfw@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id A87A116A473 for ; Tue, 18 Dec 2007 11:52:23 +0000 (UTC) (envelope-from vadimnuclight@tpu.ru) Received: from relay1.tpu.ru (relay1.tpu.ru [213.183.112.102]) by mx1.freebsd.org (Postfix) with ESMTP id 2DFF913C4D1 for ; Tue, 18 Dec 2007 11:52:21 +0000 (UTC) (envelope-from vadimnuclight@tpu.ru) Received: from localhost (localhost.localdomain [127.0.0.1]) by relay1.tpu.ru (Postfix) with ESMTP id 342DD1045DC; Tue, 18 Dec 2007 17:52:19 +0600 (NOVT) X-Virus-Scanned: amavisd-new at tpu.ru Received: from relay1.tpu.ru ([127.0.0.1]) by localhost (relay1.tpu.ru [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ECq9l8TNcU15; Tue, 18 Dec 2007 17:52:15 +0600 (NOVT) Received: from mail.main.tpu.ru (mail.main.tpu.ru [10.0.0.3]) by relay1.tpu.ru (Postfix) with ESMTP id A2BE2104605; Tue, 18 Dec 2007 17:52:15 +0600 (NOVT) Received: from mail.tpu.ru ([213.183.112.105]) by mail.main.tpu.ru with Microsoft SMTPSVC(6.0.3790.3959); Tue, 18 Dec 2007 17:52:15 +0600 Received: from nuclight.avtf.net ([78.140.2.237]) by mail.tpu.ru over TLS secured channel with Microsoft SMTPSVC(6.0.3790.3959); Tue, 18 Dec 2007 17:52:15 +0600 Date: Tue, 18 Dec 2007 17:52:11 +0600 To: "Sergey Matveychuk" References: <4767AD27.8070901@FreeBSD.org> From: "Vadim Goncharov" Organization: AVTF TPU Hostel Content-Type: multipart/mixed; boundary=----------GJeOyVu3xITaB9Flyz9pX0 MIME-Version: 1.0 Message-ID: In-Reply-To: <4767AD27.8070901@FreeBSD.org> User-Agent: Opera M2/7.54 (Win32, build 3865) X-OriginalArrivalTime: 18 Dec 2007 11:52:15.0158 (UTC) FILETIME=[6ED1DD60:01C8416C] Cc: maxim@freebsd.org, mlaier@freebsd.org, "freebsd-stable@freebsd.org" , "freebsd-net@freebsd.org" , "freebsd-ipfw@freebsd.org" , "freebsd-current@freebsd.org" , phk@freebsd.org Subject: Re: [PATCH] ipfwpcap(8) X-BeenThere: freebsd-ipfw@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: IPFW Technical Discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 18 Dec 2007 11:52:23 -0000 ------------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 + * - signals and daemonizing rewritten + * - style(9) reformat, more sysexits(3) and other cleanups + * - enabled own alarm sending, changed options and updated man page */ +#include +#include +#include /* For MAXPATHLEN */ +#include +#include + +#include +#include /* For IP_MAXPACKET */ +#include /* For IP_MAXPACKET */ + #include #include #include #include #include #include -#include -#include -#include /* for MAXPATHLEN */ -#include -#include - -#include /* for IP_MAXPACKET */ -#include /* for IP_MAXPACKET */ +#include /* XXX normally defined in config.h */ -#define HAVE_STRLCPY 1 -#define HAVE_SNPRINTF 1 -#define HAVE_VSNPRINTF 1 -#include /* see pcap(3) and /usr/src/contrib/libpcap/. */ +#define HAVE_STRLCPY 1 +#define HAVE_SNPRINTF 1 +#define HAVE_VSNPRINTF 1 +#include /* 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-- From owner-freebsd-ipfw@FreeBSD.ORG Tue Dec 18 11:59:12 2007 Return-Path: Delivered-To: freebsd-ipfw@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7DCB316A580; Tue, 18 Dec 2007 11:59:12 +0000 (UTC) (envelope-from sem@FreeBSD.org) Received: from mail.ciam.ru (ns.ciam.ru [213.247.195.75]) by mx1.freebsd.org (Postfix) with ESMTP id 22B2413C442; Tue, 18 Dec 2007 11:59:12 +0000 (UTC) (envelope-from sem@FreeBSD.org) Received: from dhcp250-210.yandex.ru ([87.250.250.210]) by mail.ciam.ru with esmtpa (Exim 4.x) id 1J4aY9-0006g8-Cu; Tue, 18 Dec 2007 14:23:49 +0300 Message-ID: <4767AD27.8070901@FreeBSD.org> Date: Tue, 18 Dec 2007 14:21:11 +0300 From: Sergey Matveychuk User-Agent: Thunderbird 2.0.0.9 (Windows/20071031) MIME-Version: 1.0 To: Vadim Goncharov References: In-Reply-To: Content-Type: text/plain; charset=KOI8-R; format=flowed Content-Transfer-Encoding: 7bit Cc: maxim@freebsd.org, mlaier@freebsd.org, "freebsd-stable@freebsd.org" , "freebsd-net@freebsd.org" , "freebsd-ipfw@freebsd.org" , "freebsd-current@freebsd.org" , phk@freebsd.org Subject: Re: [PATCH] ipfwpcap(8) X-BeenThere: freebsd-ipfw@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: IPFW Technical Discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 18 Dec 2007 11:59:12 -0000 Vadim Goncharov wrote: > 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, Unfortunately too old to apply. And using of pidfile_* functions from libutil is preferable IMHO. -- Dixi. Sem.