]> The Tcpdump Group git mirrors - tcpdump/commitdiff
from Will Drewry <will AT alum.bu.edu>
authorhannes <hannes>
Thu, 20 Oct 2005 07:43:51 +0000 (07:43 +0000)
committerhannes <hannes>
Thu, 20 Oct 2005 07:43:51 +0000 (07:43 +0000)
auto-rotate files after some times given with the G flag;

CREDITS
interface.h
netdissect.h
tcpdump.1
tcpdump.c

diff --git a/CREDITS b/CREDITS
index 2c0d2294b11bce34f05ee1ea9699693a817d9317..559572998efde83ab0e725b58341d16ac0c3db7e 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -131,6 +131,7 @@ Additional people who have contributed patches:
        Tony Li                         <[email protected]>
        Uns Lider                       <[email protected]>
        Wilbert de Graaf                <[email protected]>
+        Will Drewry                     <[email protected]>
        Yen Yen Lim
        Yoshifumi Nishida
 
index 55172679ab19dda035a54aaf8f2b402e0fa1979e..1190643add3d3e72628eeb312d4bb25f2ff61cc8 100644 (file)
@@ -18,7 +18,7 @@
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.262 2005-09-29 07:45:21 hannes Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.263 2005-10-20 07:43:51 hannes Exp $ (LBL)
  */
 
 #ifndef tcpdump_interface_h
@@ -353,6 +353,7 @@ extern netdissect_options *gndo;
 #define xflag gndo->ndo_xflag 
 #define Xflag gndo->ndo_Xflag 
 #define Cflag gndo->ndo_Cflag 
+#define Gflag gndo->ndo_Gflag 
 #define Aflag gndo->ndo_Aflag 
 #define suppress_default_print gndo->ndo_suppress_default_print
 #define packettype gndo->ndo_packettype
@@ -360,6 +361,8 @@ extern netdissect_options *gndo;
 #define Wflag gndo->ndo_Wflag
 #define WflagChars gndo->ndo_WflagChars
 #define Cflag_count gndo->ndo_Cflag_count
+#define Gflag_count gndo->ndo_Gflag_count
+#define Gflag_time gndo->ndo_Gflag_time 
 #define snaplen     gndo->ndo_snaplen
 #define snapend     gndo->ndo_snapend
 
index a25d8538e8d6be342c79a07cb05ed9be0e383edf..dfc03d3cae62b628cc76e840339dcd63e9a1ddde 100644 (file)
@@ -21,7 +21,7 @@
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * @(#) $Header: /tcpdump/master/tcpdump/netdissect.h,v 1.19 2005-09-29 07:45:22 hannes Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/netdissect.h,v 1.20 2005-10-20 07:43:51 hannes Exp $ (LBL)
  */
 
 #ifndef netdissect_h
@@ -106,6 +106,9 @@ struct netdissect_options {
 
   int ndo_Cflag;                /* rotate dump files after this many bytes */ 
   int ndo_Cflag_count;      /* Keep track of which file number we're writing */
+  int ndo_Gflag;            /* rotate dump files after this many seconds */
+  int ndo_Gflag_count;      /* number of files created with Gflag rotation */
+  time_t ndo_Gflag_time;    /* The last time_t the dump file was rotated. */
   int ndo_Wflag;          /* recycle output files after this number of files */
   int ndo_WflagChars;
   int ndo_suppress_default_print; /* don't use default_print() for unknown packet types */
index 1d00167fa787910a736f0354801b7fe11aa7cbfe..7d59b984aa752b537f965f7d113f5f6c11036e3d 100644 (file)
--- a/tcpdump.1
+++ b/tcpdump.1
@@ -1,4 +1,4 @@
-.\" @(#) $Header: /tcpdump/master/tcpdump/Attic/tcpdump.1,v 1.173 2005-09-05 09:14:15 guy Exp $ (LBL)
+.\" @(#) $Header: /tcpdump/master/tcpdump/Attic/tcpdump.1,v 1.174 2005-10-20 07:43:51 hannes Exp $ (LBL)
 .\"
 .\"    $NetBSD: tcpdump.8,v 1.9 2003/03/31 00:18:17 perry Exp $
 .\"
@@ -80,7 +80,7 @@ tcpdump \- dump traffic on a network
 [
 .B \-W
 .I filecount
-]
+] 
 .br
 .ti +8
 [
@@ -90,6 +90,10 @@ tcpdump \- dump traffic on a network
 .br
 .ti +8
 [
+.B \-G
+.I seconds
+]
+[
 .B \-y
 .I datalinktype
 ]
@@ -355,6 +359,19 @@ correctly.
 Use \fIfile\fP as input for the filter expression.
 An additional expression given on the command line is ignored.
 .TP
+.B \-G
+If specified, rotates the dump file specified with the
+.B \-w
+option every \fIrotate_seconds\fP. Savefiles will have the name specified by
+.B \-w
+which should include a time format as defined by
+.B strftime
+(3). If no time format is specified, each new file will overwrite the previous.
+.br
+If used in conjunction with the
+.B \-C
+option, filenames will take the form of `\fIfile\fP<count>'.
+.TP
 .B \-i
 Listen on \fIinterface\fP.
 If unspecified, \fItcpdump\fP searches the system interface list for the
@@ -543,6 +560,12 @@ from the beginning, thus creating a 'rotating' buffer.
 In addition, it will name
 the files with enough leading 0s to support the maximum number of
 files, allowing them to sort correctly.
+.br
+Used in conjunction with the 
+.I \-G
+option, this will limit the number of rotated dump files that get
+created exitting with status 0 when reaching the limit. If used with
+\-C as well, the behavior will result in cyclical files per timeslice.
 .TP
 .B \-x
 Print each packet (minus its link level header) in hex.
index ffa812123d3b5c622e9664f5b4455e9020a967cf..da385f60ed7217cf4259566a79d0bb04ceb7dfc6 100644 (file)
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -30,7 +30,7 @@ static const char copyright[] _U_ =
     "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
 The Regents of the University of California.  All rights reserved.\n";
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.261 2005-08-23 10:24:58 hannes Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.262 2005-10-20 07:43:52 hannes Exp $ (LBL)";
 #endif
 
 /*
@@ -79,17 +79,13 @@ extern int SIZE_BUF;
 #include "gmt2local.h"
 #include "pcap-missing.h"
 
+#ifndef NAME_MAX
+#define NAME_MAX 255
+#endif
+
 netdissect_options Gndo;
 netdissect_options *gndo = &Gndo;
 
-/*
- * Define the maximum number of files for the -C flag, and how many
- * characters can be added to a filename for the -C flag (which
- * should be enough to handle MAX_CFLAG - 1).
- */
-#define MAX_CFLAG      1000000
-#define MAX_CFLAG_CHARS        6
-
 int dflag;                     /* print filter code */
 int Lflag;                     /* list available data link types and exit */
 
@@ -420,10 +416,31 @@ getWflagChars(int x)
 static void
 MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars)
 {
+        char *filename = malloc(NAME_MAX + 1);
+
+        /* Process with strftime if Gflag is set. */
+        if (Gflag != 0) {
+          struct tm *local_tm;
+
+          /* Convert Gflag_time to a usable format */
+          if ((local_tm = localtime(&Gflag_time)) == NULL) {
+                  error("MakeTimedFilename: localtime");
+          }
+
+          /* There's no good way to detect an error in strftime since a return
+           * value of 0 isn't necessarily failure.
+           */
+          strftime(filename, NAME_MAX, orig_name, local_tm);
+        } else {
+          strncpy(filename, orig_name, NAME_MAX);
+        }
+
        if (cnt == 0 && max_chars == 0)
-               strcpy(buffer, orig_name);
+               strncpy(buffer, filename, NAME_MAX + 1);
        else
-               sprintf(buffer, "%s%0*d", orig_name, max_chars, cnt);
+               if (snprintf(buffer, NAME_MAX + 1, "%s%0*d", filename, max_chars, cnt) > NAME_MAX)
+                  /* Report an error if the filename is too large */
+                  error("too many output files or filename is too long (> %d)", NAME_MAX);
 }
 
 static int tcpdump_printf(netdissect_options *ndo _U_,
@@ -496,7 +513,7 @@ main(int argc, char **argv)
 
        opterr = 0;
        while (
-           (op = getopt(argc, argv, "aA" B_FLAG "c:C:d" D_FLAG "eE:fF:i:lLm:M:nNOpqr:Rs:StT:u" U_FLAG "vw:W:xXy:YZ:")) != -1)
+           (op = getopt(argc, argv, "aA" B_FLAG "c:C:d" D_FLAG "eE:fF:G:i:lLm:M:nNOpqr:Rs:StT:u" U_FLAG "vw:W:xXy:YZ:")) != -1)
                switch (op) {
 
                case 'a':
@@ -570,6 +587,22 @@ main(int argc, char **argv)
                        infile = optarg;
                        break;
 
+               case 'G':
+                       Gflag = atoi(optarg);
+                        /* We will create one file initially. */
+                        Gflag_count = 0;
+                        /* Grab the current time for rotation use. */
+                        {
+                         struct timeval t;
+                          if (gettimeofday(&t, NULL) != 0) {
+                                  error("main: gettimeofday");
+                          }
+                          Gflag_time = t.tv_sec;
+                        }
+                       if (Gflag < 0)
+                               error("invalid number of seconds %s", optarg);
+                       break;
+
                case 'i':
                        if (optarg[0] == '0' && optarg[1] == 0)
                                error("Invalid adapter index");
@@ -959,15 +992,22 @@ main(int argc, char **argv)
                error("%s", pcap_geterr(pd));
        if (WFileName) {
                pcap_dumper_t *p;
+                /* Do not exceed the default NAME_MAX for files. */
+               WFileNameAlt = (char *)malloc(NAME_MAX + 1);
 
-               WFileNameAlt = (char *)malloc(strlen(WFileName) + MAX_CFLAG_CHARS + 1);
                if (WFileNameAlt == NULL)
                        error("malloc of WFileNameAlt");
-               MakeFilename(WFileNameAlt, WFileName, 0, WflagChars);
+
+                /* We do not need numbering for dumpfiles if Cflag isn't set. */
+                if (Cflag != 0)
+                 MakeFilename(WFileNameAlt, WFileName, 0, WflagChars);
+                else
+                 MakeFilename(WFileNameAlt, WFileName, 0, 0);
+
                p = pcap_dump_open(pd, WFileNameAlt);
                if (p == NULL)
                        error("%s", pcap_geterr(pd));
-               if (Cflag != 0) {
+               if (Cflag != 0 || Gflag != 0) {
                        callback = dump_packet_and_trunc;
                        dumpinfo.WFileName = WFileName;
                        dumpinfo.pd = pd;
@@ -1159,12 +1199,68 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
 
        dump_info = (struct dump_info *)user;
 
+       /*
+         * XXX - this won't force the file to rotate on the specified time
+         * boundary, but it will rotate on the first packet received after the
+         * specified Gflag number of seconds. Note: if a Gflag time boundary
+         * and a Cflag size boundary coincide, the time rotation will occur
+         * first thereby cancelling the Cflag boundary (since the file should
+         * be 0).
+        */
+        if (Gflag != 0) {
+          /* Check if it is time to rotate */
+         struct timeval t;
+
+          /* Get the current time */
+          if (gettimeofday(&t, NULL) != 0) {
+                  error("dump_and_trunc_packet: gettimeofday");
+          }
+
+
+          /* If the time is greater than the specified window, rotate */
+          if (t.tv_sec - Gflag_time >= Gflag) {
+              /* Update the Gflag_time */
+              Gflag_time = t.tv_sec;
+              /* Update Gflag_count */
+              Gflag_count++;
+              /*
+               * Close the current file and open a new one.
+               */
+              pcap_dump_close(dump_info->p);
+
+              /* Check to see if we've exceeded the Wflag (when not using Cflag). */
+             if (Cflag == 0 && Wflag > 0 && Gflag_count >= Wflag) {
+               (void)fprintf(stderr, "Maximum file limit reached: %d\n", Wflag);
+               (void)fflush(stderr);
+                exit(0);
+                /* NOTREACHED */
+              }
+              /* Allocate space for max filename + \0. */
+              name = (char *)malloc(NAME_MAX + 1);
+              if (name == NULL)
+                      error("dump_packet_and_trunc: malloc");
+              /* This is always the first file in the Cflag rotation: e.g. 0
+               * We also don't need numbering if Cflag is not set.
+               */
+              if (Cflag != 0)
+                MakeFilename(name, dump_info->WFileName, 0, WflagChars);
+              else
+                MakeFilename(name, dump_info->WFileName, 0, 0);
+
+              dump_info->p = pcap_dump_open(dump_info->pd, name);
+              free(name);
+              if (dump_info->p == NULL)
+                      error("%s", pcap_geterr(pd));
+
+          }
+        }
+
        /*
         * XXX - this won't prevent capture files from getting
         * larger than Cflag - the last packet written to the
         * file could put it over Cflag.
         */
-       if (pcap_dump_ftell(dump_info->p) > Cflag) {
+       if (Cflag != 0 && pcap_dump_ftell(dump_info->p) > Cflag) {
                /*
                 * Close the current file and open a new one.
                 */
@@ -1173,11 +1269,8 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
                if (Wflag > 0) {
                        if (Cflag_count >= Wflag)
                                Cflag_count = 0;
-               } else {
-                       if (Cflag_count >= MAX_CFLAG)
-                               error("too many output files");
                }
-               name = (char *)malloc(strlen(dump_info->WFileName) + MAX_CFLAG_CHARS + 1);
+               name = (char *)malloc(NAME_MAX + 1);
                if (name == NULL)
                        error("dump_packet_and_trunc: malloc");
                MakeFilename(name, dump_info->WFileName, Cflag_count, WflagChars);
@@ -1408,9 +1501,9 @@ usage(void)
        (void)fprintf(stderr,
 "Usage: %s [-aAd" D_FLAG "eflLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [-c count] [ -C file_size ]\n", program_name);
        (void)fprintf(stderr,
-"\t\t[ -E algo:secret ] [ -F file ] [ -i interface ] [ -M secret ]\n");
+"\t\t[ -E algo:secret ] [ -F file ] [ -G seconds ] [ -i interface ]\n");
        (void)fprintf(stderr,
-"\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ -w file ]\n");
+"\t\t[ -M secret ] [ -r file ] [ -s snaplen ] [ -T type ] [ -w file ]\n");
        (void)fprintf(stderr,
 "\t\t[ -W filecount ] [ -y datalinktype ] [ -Z user ]\n");
        (void)fprintf(stderr,