-.\" @(#) $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 $
.\"
[
.B \-W
.I filecount
-]
+]
.br
.ti +8
[
.br
.ti +8
[
+.B \-G
+.I seconds
+]
+[
.B \-y
.I datalinktype
]
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
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.
"@(#) 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
/*
#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 */
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_,
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':
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");
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;
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.
*/
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);
(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,