]> The Tcpdump Group git mirrors - tcpdump/blobdiff - tcpdump.c
It is once per second, not every 10 seconds.
[tcpdump] / tcpdump.c
index 86ccc50c9c27139aa2bb03a09159e1a782d52215..520d69f7d5f17c346787f030ce767a63519c1ba1 100644 (file)
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -140,7 +140,11 @@ The Regents of the University of California.  All rights reserved.\n";
 #endif
 
 static int Bflag;                      /* buffer size */
+#ifdef HAVE_PCAP_FTELL64
+static int64_t Cflag;                  /* rotate dump files after this many bytes */
+#else
 static long Cflag;                     /* rotate dump files after this many bytes */
+#endif
 static int Cflag_count;                        /* Keep track of which file number we're writing */
 static int Dflag;                      /* list available devices and exit */
 /*
@@ -185,17 +189,17 @@ cap_channel_t *capdns;
 #endif
 
 /* Forwards */
-static void error(FORMAT_STRING(const char *), ...) NORETURN PRINTFLIKE(1, 2);
+static NORETURN void error(FORMAT_STRING(const char *), ...) PRINTFLIKE(1, 2);
 static void warning(FORMAT_STRING(const char *), ...) PRINTFLIKE(1, 2);
-static void exit_tcpdump(int) NORETURN;
+static NORETURN void exit_tcpdump(int);
 static RETSIGTYPE cleanup(int);
 static RETSIGTYPE child_cleanup(int);
 static void print_version(void);
 static void print_usage(void);
-static void show_tstamp_types_and_exit(pcap_t *, const char *device) NORETURN;
-static void show_dlts_and_exit(pcap_t *, const char *device) NORETURN;
+static NORETURN void show_tstamp_types_and_exit(pcap_t *, const char *device);
+static NORETURN void show_dlts_and_exit(pcap_t *, const char *device);
 #ifdef HAVE_PCAP_FINDALLDEVS
-static void show_devices_and_exit (void) NORETURN;
+static NORETURN void show_devices_and_exit(void);
 #endif
 
 static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
@@ -244,6 +248,7 @@ struct dump_info {
        char    *CurrentFileName;
        pcap_t  *pd;
        pcap_dumper_t *p;
+       netdissect_options *ndo;
 #ifdef HAVE_CAPSICUM
        int     dirfd;
 #endif
@@ -553,6 +558,7 @@ show_devices_and_exit (void)
 #define OPTION_VERSION         128
 #define OPTION_TSTAMP_PRECISION        129
 #define OPTION_IMMEDIATE_MODE  130
+#define OPTION_PRINT           131
 
 static const struct option longopts[] = {
 #if defined(HAVE_PCAP_CREATE) || defined(_WIN32)
@@ -592,6 +598,7 @@ static const struct option longopts[] = {
 #endif
        { "relinquish-privileges", required_argument, NULL, 'Z' },
        { "number", no_argument, NULL, '#' },
+       { "print", no_argument, NULL, OPTION_PRINT },
        { "version", no_argument, NULL, OPTION_VERSION },
        { NULL, 0, NULL, 0 }
 };
@@ -1175,9 +1182,10 @@ int
 main(int argc, char **argv)
 {
        register int cnt, op, i;
-       bpf_u_int32 localnet =, netmask = 0;
+       bpf_u_int32 localnet = 0, netmask = 0;
        int timezone_offset = 0;
        register char *cp, *infile, *cmdbuf, *device, *RFileName, *VFileName, *WFileName;
+       char *endp;
        pcap_handler callback;
        int dlt;
        const char *dlt_name;
@@ -1206,6 +1214,7 @@ main(int argc, char **argv)
        int Oflag = 1;                  /* run filter code optimizer */
        int yflag_dlt = -1;
        const char *yflag_dlt_name = NULL;
+       int print = 0;
 
        netdissect_options Ndo;
        netdissect_options *ndo = &Ndo;
@@ -1278,9 +1287,25 @@ main(int argc, char **argv)
                        break;
 
                case 'C':
-                       Cflag = atoi(optarg) * 1000000;
-                       if (Cflag <= 0)
+                       errno = 0;
+#ifdef HAVE_PCAP_FTELL64
+                       Cflag = strtoint64_t(optarg, &endp, 10);
+#else
+                       Cflag = strtol(optarg, &endp, 10);
+#endif
+                       if (endp == optarg || *endp != '\0' || errno != 0
+                           || Cflag <= 0)
                                error("invalid file size %s", optarg);
+                       /*
+                        * Will multiplying it by 1000000 overflow?
+                        */
+#ifdef HAVE_PCAP_FTELL64
+                       if (Cflag > INT64_T_CONSTANT(0x7fffffffffffffffU) / 1000000)
+#else
+                       if (Cflag > LONG_MAX / 1000000)
+#endif
+                               error("file size %s is too large", optarg);
+                       Cflag *= 1000000;
                        break;
 
                case 'd':
@@ -1582,6 +1607,10 @@ main(int argc, char **argv)
                        break;
 #endif
 
+               case OPTION_PRINT:
+                       print = 1;
+                       break;
+
                default:
                        print_usage();
                        exit_tcpdump(1);
@@ -1620,11 +1649,14 @@ main(int argc, char **argv)
 #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
        /*
         * If we're printing dissected packets to the standard output
-        * rather than saving raw packets to a file, and the standard
-        * output is a terminal, use immediate mode, as the user's
-        * probably expecting to see packets pop up immediately.
+        * and the standard output is a terminal, use immediate mode,
+        * as the user's probably expecting to see packets pop up
+        * immediately.
+        *
+        * XXX - set the timeout to a lower value, instead?  If so,
+        * what value would be appropriate?
         */
-       if (WFileName == NULL && isatty(1))
+       if ((WFileName == NULL || print) && isatty(1))
                immediate_mode = 1;
 #endif
 
@@ -1724,20 +1756,21 @@ main(int argc, char **argv)
                         * Find the list of interfaces, and pick
                         * the first interface.
                         */
-                       if (pcap_findalldevs(&devlist, ebuf) >= 0 &&
-                           devlist != NULL) {
-                               device = strdup(devlist->name);
-                               pcap_freealldevs(devlist);
-                       }
+                       if (pcap_findalldevs(&devlist, ebuf) == -1)
+                               error("%s", ebuf);
+                       if (devlist == NULL)
+                               error("no interfaces available for capture");
+                       device = strdup(devlist->name);
+                       pcap_freealldevs(devlist);
 #else /* HAVE_PCAP_FINDALLDEVS */
                        /*
                         * Use whatever interface pcap_lookupdev()
                         * chooses.
                         */
                        device = pcap_lookupdev(ebuf);
-#endif
                        if (device == NULL)
                                error("%s", ebuf);
+#endif
                }
 
                /*
@@ -2014,8 +2047,18 @@ main(int argc, char **argv)
                        pcap_userdata = (u_char *)&dumpinfo;
                } else {
                        callback = dump_packet;
-                       pcap_userdata = (u_char *)p;
+                       dumpinfo.WFileName = WFileName;
+                       dumpinfo.pd = pd;
+                       dumpinfo.p = p;
+                       pcap_userdata = (u_char *)&dumpinfo;
                }
+               if (print) {
+                       dlt = pcap_datalink(pd);
+                       ndo->ndo_if_printer = get_if_printer(ndo, dlt);
+                       dumpinfo.ndo = ndo;
+               } else
+                       dumpinfo.ndo = NULL;
+
 #ifdef HAVE_PCAP_DUMP_FLUSH
                if (Uflag)
                        pcap_dump_flush(p);
@@ -2036,11 +2079,11 @@ main(int argc, char **argv)
                (void)setsignal(SIGNAL_REQ_INFO, requestinfo);
 #endif
 
-       if (ndo->ndo_vflag > 0 && WFileName) {
+       if (ndo->ndo_vflag > 0 && WFileName && !print) {
                /*
-                * When capturing to a file, "-v" means tcpdump should,
-                * every 10 seconds, "v"erbosely report the number of
-                * packets captured.
+                * When capturing to a file, if "--print" wasn't specified,
+                *"-v" means tcpdump should, once per second,
+                * "v"erbosely report the number of packets captured.
                 */
 #ifdef USE_WIN32_MM_TIMER
                /* call verbose_stats_dump() each 1000 +/-100msec */
@@ -2485,7 +2528,17 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
         * file could put it over Cflag.
         */
        if (Cflag != 0) {
+#ifdef HAVE_PCAP_FTELL64
+               int64_t size = pcap_dump_ftell64(dump_info->p);
+#else
+               /*
+                * XXX - this only handles a Cflag value > 2^31-1 on
+                * LP64 platforms; to handle ILP32 (32-bit UN*X and
+                * Windows) or LLP64 (64-bit Windows) would require
+                * a version of libpcap with pcap_dump_ftell64().
+                */
                long size = pcap_dump_ftell(dump_info->p);
+#endif
 
                if (size == -1)
                        error("ftell fails on output file");
@@ -2556,6 +2609,9 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
                pcap_dump_flush(dump_info->p);
 #endif
 
+       if (dump_info->ndo != NULL)
+               pretty_print_packet(dump_info->ndo, h, sp, packets_captured);
+
        --infodelay;
        if (infoprint)
                info(0);
@@ -2564,16 +2620,23 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
 static void
 dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
 {
+       struct dump_info *dump_info;
+
        ++packets_captured;
 
        ++infodelay;
 
-       pcap_dump(user, h, sp);
+       dump_info = (struct dump_info *)user;
+
+       pcap_dump((u_char *)dump_info->p, h, sp);
 #ifdef HAVE_PCAP_DUMP_FLUSH
        if (Uflag)
-               pcap_dump_flush((pcap_dumper_t *)user);
+               pcap_dump_flush(dump_info->p);
 #endif
 
+       if (dump_info->ndo != NULL)
+               pretty_print_packet(dump_info->ndo, h, sp, packets_captured);
+
        --infodelay;
        if (infoprint)
                info(0);
@@ -2630,6 +2693,18 @@ RETSIGTYPE requestinfo(int signo _U_)
 }
 #endif
 
+static void
+print_packets_captured (void)
+{
+       static u_int prev_packets_captured, first = 1;
+
+       if (infodelay == 0 && (first || packets_captured != prev_packets_captured)) {
+               fprintf(stderr, "Got %u\r", packets_captured);
+               first = 0;
+               prev_packets_captured = packets_captured;
+       }
+}
+
 /*
  * Called once each second in verbose mode while dumping to file
  */
@@ -2637,14 +2712,12 @@ RETSIGTYPE requestinfo(int signo _U_)
 void CALLBACK verbose_stats_dump (UINT timer_id _U_, UINT msg _U_, DWORD_PTR arg _U_,
                                  DWORD_PTR dw1 _U_, DWORD_PTR dw2 _U_)
 {
-       if (infodelay == 0)
-               fprintf(stderr, "Got %u\r", packets_captured);
+       print_packets_captured();
 }
 #elif defined(HAVE_ALARM)
 static void verbose_stats_dump(int sig _U_)
 {
-       if (infodelay == 0)
-               fprintf(stderr, "Got %u\r", packets_captured);
+       print_packets_captured();
        alarm(1);
 }
 #endif
@@ -2708,14 +2781,17 @@ print_usage(void)
 "\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n");
        (void)fprintf(stderr,
 "\t\t[ -i interface ]" j_FLAG_USAGE " [ -M secret ] [ --number ]\n");
+       (void)fprintf(stderr,
+"\t\t[ --print ]");
 #ifdef HAVE_PCAP_SETDIRECTION
        (void)fprintf(stderr,
-"\t\t[ -Q in|out|inout ]\n");
+" [ -Q in|out|inout ]");
 #endif
        (void)fprintf(stderr,
-"\t\t[ -r file ] [ -s snaplen ] ");
+" [ -r file ] [ -s snaplen ]\n");
 #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
-       (void)fprintf(stderr, "[ --time-stamp-precision precision ]\n");
+       (void)fprintf(stderr,
+"\t\t[ --time-stamp-precision precision ]\n");
        (void)fprintf(stderr,
 "\t\t");
 #endif