]> The Tcpdump Group git mirrors - tcpdump/blobdiff - tcpdump.c
- add the -ttttt timestamp option which prints the time difference
[tcpdump] / tcpdump.c
index 9be35c297807abb7a4bab44b64c050a0111e6130..116f3daa7abdc1c06465cb46c1badaaec720edaa 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.252 2005-01-27 10:17:59 hannes Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.265 2005-12-13 08:37:22 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 */
 
@@ -226,8 +222,44 @@ static struct printer printers[] = {
 #ifdef DLT_JUNIPER_ATM2
        { juniper_atm2_print,   DLT_JUNIPER_ATM2 },
 #endif
+#ifdef DLT_JUNIPER_MFR
+       { juniper_mfr_print,    DLT_JUNIPER_MFR },
+#endif
 #ifdef DLT_JUNIPER_MLFR
        { juniper_mlfr_print,   DLT_JUNIPER_MLFR },
+#endif
+#ifdef DLT_JUNIPER_MLPPP
+       { juniper_mlppp_print,  DLT_JUNIPER_MLPPP },
+#endif
+#ifdef DLT_JUNIPER_PPPOE
+       { juniper_pppoe_print,  DLT_JUNIPER_PPPOE },
+#endif
+#ifdef DLT_JUNIPER_PPPOE_ATM
+       { juniper_pppoe_atm_print, DLT_JUNIPER_PPPOE_ATM },
+#endif
+#ifdef DLT_JUNIPER_GGSN
+       { juniper_ggsn_print,   DLT_JUNIPER_GGSN },
+#endif
+#ifdef DLT_JUNIPER_ES
+       { juniper_es_print,     DLT_JUNIPER_ES },
+#endif
+#ifdef DLT_JUNIPER_MONITOR
+       { juniper_monitor_print, DLT_JUNIPER_MONITOR },
+#endif
+#ifdef DLT_JUNIPER_SERVICES
+       { juniper_services_print, DLT_JUNIPER_SERVICES },
+#endif
+#ifdef DLT_JUNIPER_ETHER
+       { juniper_ether_print, DLT_JUNIPER_ETHER },
+#endif
+#ifdef DLT_JUNIPER_PPP
+       { juniper_ppp_print, DLT_JUNIPER_PPP },
+#endif
+#ifdef DLT_JUNIPER_FRELAY
+       { juniper_frelay_print, DLT_JUNIPER_FRELAY },
+#endif
+#ifdef DLT_JUNIPER_CHDLC
+       { juniper_chdlc_print, DLT_JUNIPER_CHDLC },
 #endif
        { NULL,                 0 },
 };
@@ -384,10 +416,32 @@ 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);
+        free(filename);
 }
 
 static int tcpdump_printf(netdissect_options *ndo _U_,
@@ -460,7 +514,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':
@@ -468,8 +522,6 @@ main(int argc, char **argv)
                        break;
 
                case 'A':
-                       ++xflag;
-                       ++Xflag;
                        ++Aflag;
                        break;
 
@@ -536,6 +588,21 @@ main(int argc, char **argv)
                        infile = optarg;
                        break;
 
+               case 'G':
+                       Gflag = atoi(optarg);
+                       if (Gflag < 0)
+                               error("invalid number of seconds %s", optarg);
+
+                        /* We will create one file initially. */
+                        Gflag_count = 0;
+
+                       /* Grab the current time for rotation use. */
+                       if ((Gflag_time = time(NULL)) == (time_t)-1) {
+                               error("main: can't get current time: %s",
+                                   pcap_strerror(errno));
+                       }
+                       break;
+
                case 'i':
                        if (optarg[0] == '0' && optarg[1] == 0)
                                error("Invalid adapter index");
@@ -602,9 +669,9 @@ main(int argc, char **argv)
 
                case 'm':
 #ifdef LIBSMI
-                       if (smiLoadModule(optarg) == 0) {
+                       if (smiLoadModule(optarg) == 0) {
                                error("could not load MIB module %s", optarg);
-                       }
+                       }
                        sflag = 1;
 #else
                        (void)fprintf(stderr, "%s: ignoring option `-m %s' ",
@@ -631,6 +698,7 @@ main(int argc, char **argv)
 
                case 'q':
                        ++qflag;
+                       ++suppress_default_print;
                        break;
 
                case 'r':
@@ -711,10 +779,12 @@ main(int argc, char **argv)
 
                case 'x':
                        ++xflag;
+                       ++suppress_default_print;
                        break;
 
                case 'X':
                        ++Xflag;
+                       ++suppress_default_print;
                        break;
 
                case 'y':
@@ -764,10 +834,11 @@ main(int argc, char **argv)
        case 1: /* No time stamp */
        case 2: /* Unix timeval style */
        case 3: /* Microseconds since previous packet */
+        case 5: /* Microseconds since first packet */
                break;
 
        default: /* Not supported */
-               error("only -t, -tt, -ttt, and -tttt are supported");
+               error("only -t, -tt, -ttt, -tttt and -ttttt are supported");
                break;
        }
 
@@ -879,7 +950,7 @@ main(int argc, char **argv)
                        }
 #endif
                        (void)fprintf(stderr, "%s: data link type %s\n",
-                                     program_name, gndo->ndo_dltname);
+                                     program_name, gndo->ndo_dltname);
                        (void)fflush(stderr);
                }
                i = pcap_snapshot(pd);
@@ -922,15 +993,23 @@ 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);
+               free(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;
@@ -1122,12 +1201,74 @@ 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 */
+               time_t t;
+
+               /* Get the current time */
+               if ((t = time(NULL)) == (time_t)-1) {
+                       error("dump_and_trunc_packet: can't get current_time: %s",
+                           pcap_strerror(errno));
+               }
+
+
+               /* If the time is greater than the specified window, rotate */
+               if (t - Gflag_time >= Gflag) {
+                       /* Update the Gflag_time */
+                       Gflag_time = t;
+                       /* 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);
+                               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 (ftell((FILE *)dump_info->p) > Cflag) {
+       if (Cflag != 0 && pcap_dump_ftell(dump_info->p) > Cflag) {
                /*
                 * Close the current file and open a new one.
                 */
@@ -1136,11 +1277,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);
@@ -1200,9 +1338,28 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
        snapend = sp + h->caplen;
 
        hdrlen = (*print_info->printer)(h, sp);
-       if (xflag) {
+       if (Xflag) {
+               /*
+                * Print the raw packet data in hex and ASCII.
+                */
+               if (Xflag > 1) {
+                       /*
+                        * Include the link-layer header.
+                        */
+                       hex_and_ascii_print("\n\t", sp, h->caplen);
+               } else {
+                       /*
+                        * Don't include the link-layer header - and if
+                        * we have nothing past the link-layer header,
+                        * print nothing.
+                        */
+                       if (h->caplen > hdrlen)
+                               hex_and_ascii_print("\n\t", sp + hdrlen,
+                                   h->caplen - hdrlen);
+               }
+       } else if (xflag) {
                /*
-                * Print the raw packet data.
+                * Print the raw packet data in hex.
                 */
                if (xflag > 1) {
                        /*
@@ -1219,15 +1376,15 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
                                hex_print("\n\t", sp + hdrlen,
                                    h->caplen - hdrlen);
                }
-       } else if (Xflag) {
+       } else if (Aflag) {
                /*
-                * Print the raw packet data.
+                * Print the raw packet data in ASCII.
                 */
-               if (Xflag > 1) {
+               if (Aflag > 1) {
                        /*
                         * Include the link-layer header.
                         */
-                       ascii_print("\n\t", sp, h->caplen);
+                       ascii_print(sp, h->caplen);
                } else {
                        /*
                         * Don't include the link-layer header - and if
@@ -1235,8 +1392,7 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
                         * print nothing.
                         */
                        if (h->caplen > hdrlen)
-                               ascii_print("\n\t", sp + hdrlen,
-                                   h->caplen - hdrlen);
+                               ascii_print(sp + hdrlen, h->caplen - hdrlen);
                }
        }
 
@@ -1275,12 +1431,12 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
 #endif
 
 /*
- * By default, print the specified data out in hex.
+ * By default, print the specified data out in hex and ASCII.
  */
 static void
 ndo_default_print(netdissect_options *ndo _U_, const u_char *bp, u_int length)
 {
-       ascii_print("\n\t", bp, length); /* pass on lf and identation string */
+       hex_and_ascii_print("\n\t", bp, length); /* pass on lf and identation string */
 }
 
 void
@@ -1304,7 +1460,7 @@ RETSIGTYPE requestinfo(int signo _U_)
  */
 #ifdef USE_WIN32_MM_TIMER
 void CALLBACK verbose_stats_dump (UINT timer_id _U_, UINT msg _U_, DWORD_PTR arg _U_,
-                                  DWORD_PTR dw1 _U_, DWORD_PTR dw2 _U_)
+                                 DWORD_PTR dw1 _U_, DWORD_PTR dw2 _U_)
 {
        struct pcap_stat stat;
 
@@ -1353,9 +1509,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,