]> The Tcpdump Group git mirrors - tcpdump/blobdiff - tcpdump.c
OpenFlow: Have a function for each message type.
[tcpdump] / tcpdump.c
index 06d3d9b9d624758f5ba26703b08a1a61eb589347..658d8b34ec0124ebfc289f5edbe0a49089cd9d82 100644 (file)
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -124,6 +124,16 @@ The Regents of the University of California.  All rights reserved.\n";
 #include <grp.h>
 #endif /* _WIN32 */
 
+/*
+ * Pathname separator.
+ * Use this in pathnames, but do *not* use it in URLs.
+ */
+#ifdef _WIN32
+#define PATH_SEPARATOR '\\'
+#else
+#define PATH_SEPARATOR '/'
+#endif
+
 /* capabilities convenience library */
 /* If a code depends on HAVE_LIBCAP_NG, it depends also on HAVE_CAP_NG_H.
  * If HAVE_CAP_NG_H is not defined, undefine HAVE_LIBCAP_NG.
@@ -141,6 +151,7 @@ The Regents of the University of California.  All rights reserved.\n";
 #include <sys/sysctl.h>
 #endif /* __FreeBSD__ */
 
+#include "netdissect-stdinc.h"
 #include "netdissect.h"
 #include "interface.h"
 #include "addrtoname.h"
@@ -238,8 +249,8 @@ static NORETURN void exit_tcpdump(int);
 static void (*setsignal (int sig, void (*func)(int)))(int);
 static void cleanup(int);
 static void child_cleanup(int);
-static void print_version(void);
-static void print_usage(void);
+static void print_version(FILE *);
+static void print_usage(FILE *);
 #ifdef HAVE_PCAP_SET_TSTAMP_TYPE
 static NORETURN void show_tstamp_types_and_exit(pcap_t *, const char *device);
 #endif
@@ -831,7 +842,7 @@ MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars)
 {
         char *filename = malloc(PATH_MAX + 1);
         if (filename == NULL)
-            error("Makefilename: malloc");
+            error("%s: malloc", __func__);
 
         /* Process with strftime if Gflag is set. */
         if (Gflag != 0) {
@@ -839,7 +850,7 @@ MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars)
 
           /* Convert Gflag_time to a usable format */
           if ((local_tm = localtime(&Gflag_time)) == NULL) {
-                  error("MakeTimedFilename: localtime");
+                  error("%s: localtime", __func__);
           }
 
           /* There's no good way to detect an error in strftime since a return
@@ -1025,7 +1036,7 @@ copy_argv(char **argv)
 
        buf = (char *)malloc(len);
        if (buf == NULL)
-               error("copy_argv: malloc");
+               error("%s: malloc", __func__);
 
        p = argv;
        dst = buf;
@@ -1055,15 +1066,22 @@ read_infile(char *fname)
        int i, fd;
        ssize_t cc;
        char *cp;
-       struct stat buf;
+       our_statb buf;
 
        fd = open(fname, O_RDONLY|O_BINARY);
        if (fd < 0)
                error("can't open %s: %s", fname, pcap_strerror(errno));
 
-       if (fstat(fd, &buf) < 0)
+       if (our_fstat(fd, &buf) < 0)
                error("can't stat %s: %s", fname, pcap_strerror(errno));
 
+       /*
+        * Reject files whose size doesn't fit into an int; a filter
+        * *that* large will probably be too big.
+        */
+       if (buf.st_size > INT_MAX)
+               error("%s is too large", fname);
+
        cp = malloc((u_int)buf.st_size + 1);
        if (cp == NULL)
                error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1,
@@ -1072,7 +1090,8 @@ read_infile(char *fname)
        if (cc < 0)
                error("read %s: %s", fname, pcap_strerror(errno));
        if (cc != buf.st_size)
-               error("short read %s (%zd != %d)", fname, cc, (int)buf.st_size);
+               error("short read %s (%d != %d)", fname, (int) cc,
+                   (int)buf.st_size);
 
        close(fd);
        /* replace "# comment" with spaces */
@@ -1498,7 +1517,7 @@ main(int argc, char **argv)
        VFile = NULL;
        WFileName = NULL;
        dlt = -1;
-       if ((cp = strrchr(argv[0], '/')) != NULL)
+       if ((cp = strrchr(argv[0], PATH_SEPARATOR)) != NULL)
                ndo->program_name = program_name = cp + 1;
        else
                ndo->program_name = program_name = argv[0];
@@ -1622,13 +1641,13 @@ main(int argc, char **argv)
 
                        /* 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));
+                               error("%s: can't get current time: %s",
+                                   __func__, pcap_strerror(errno));
                        }
                        break;
 
                case 'h':
-                       print_usage();
+                       print_usage(stdout);
                        exit_tcpdump(S_SUCCESS);
                        break;
 
@@ -1870,7 +1889,7 @@ main(int argc, char **argv)
                        break;
 
                case OPTION_VERSION:
-                       print_version();
+                       print_version(stdout);
                        exit_tcpdump(S_SUCCESS);
                        break;
 
@@ -1918,7 +1937,7 @@ main(int argc, char **argv)
                        break;
 
                default:
-                       print_usage();
+                       print_usage(stderr);
                        exit_tcpdump(S_ERR_HOST_PROGRAM);
                        /* NOTREACHED */
                }
@@ -2400,7 +2419,7 @@ DIAG_ON_CLANG(assign-enum)
                }
                if (print) {
                        dlt = pcap_datalink(pd);
-                       ndo->ndo_if_printer = get_if_printer(ndo, dlt);
+                       ndo->ndo_if_printer = get_if_printer(dlt);
                        dumpinfo.ndo = ndo;
                } else
                        dumpinfo.ndo = NULL;
@@ -2411,7 +2430,7 @@ DIAG_ON_CLANG(assign-enum)
 #endif
        } else {
                dlt = pcap_datalink(pd);
-               ndo->ndo_if_printer = get_if_printer(ndo, dlt);
+               ndo->ndo_if_printer = get_if_printer(dlt);
                callback = print_packet;
                pcap_userdata = (u_char *)ndo;
        }
@@ -2428,11 +2447,14 @@ DIAG_ON_CLANG(assign-enum)
        (void)setsignal(SIGNAL_FLUSH_PCAP, flushpcap);
 #endif
 
-       if (ndo->ndo_vflag > 0 && WFileName && !print) {
+       if (ndo->ndo_vflag > 0 && WFileName && RFileName == NULL && !print) {
                /*
                 * 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.
+                * Except when reading from a file, because -r, -w and -v
+                * together used to make a corner case, in which pcap_loop()
+                * errored due to EINTR (see GH #155 for details).
                 */
 #ifdef _WIN32
                /*
@@ -2584,7 +2606,7 @@ DIAG_ON_CLANG(assign-enum)
                                         * the new DLT.
                                         */
                                        dlt = new_dlt;
-                                       ndo->ndo_if_printer = get_if_printer(ndo, dlt);
+                                       ndo->ndo_if_printer = get_if_printer(dlt);
                                        if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
                                                error("%s", pcap_geterr(pd));
                                }
@@ -2827,8 +2849,8 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
 
                /* 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));
+                       error("%s: can't get current_time: %s",
+                           __func__, pcap_strerror(errno));
                }
 
 
@@ -2969,7 +2991,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
                                free(dump_info->CurrentFileName);
                        dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1);
                        if (dump_info->CurrentFileName == NULL)
-                               error("dump_packet_and_trunc: malloc");
+                               error("%s: malloc", __func__);
                        MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars);
 #ifdef HAVE_LIBCAP_NG
                        capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE);
@@ -3107,7 +3129,7 @@ static void verbose_stats_dump(int sig _U_)
 
 USES_APPLE_DEPRECATED_API
 static void
-print_version(void)
+print_version(FILE *f)
 {
 #ifndef HAVE_PCAP_LIB_VERSION
   #ifdef HAVE_PCAP_VERSION
@@ -3118,61 +3140,61 @@ print_version(void)
 #endif /* HAVE_PCAP_LIB_VERSION */
        const char *smi_version_string;
 
-       (void)fprintf(stderr, "%s version " PACKAGE_VERSION "\n", program_name);
+       (void)fprintf(f, "%s version " PACKAGE_VERSION "\n", program_name);
 #ifdef HAVE_PCAP_LIB_VERSION
-       (void)fprintf(stderr, "%s\n", pcap_lib_version());
+       (void)fprintf(f, "%s\n", pcap_lib_version());
 #else /* HAVE_PCAP_LIB_VERSION */
-       (void)fprintf(stderr, "libpcap version %s\n", pcap_version);
+       (void)fprintf(f, "libpcap version %s\n", pcap_version);
 #endif /* HAVE_PCAP_LIB_VERSION */
 
 #if defined(HAVE_LIBCRYPTO) && defined(SSLEAY_VERSION)
-       (void)fprintf (stderr, "%s\n", SSLeay_version(SSLEAY_VERSION));
+       (void)fprintf (f, "%s\n", SSLeay_version(SSLEAY_VERSION));
 #endif
 
        smi_version_string = nd_smi_version_string();
        if (smi_version_string != NULL)
-               (void)fprintf (stderr, "SMI-library: %s\n", smi_version_string);
+               (void)fprintf (f, "SMI-library: %s\n", smi_version_string);
 
 #if defined(__SANITIZE_ADDRESS__)
-       (void)fprintf (stderr, "Compiled with AddressSanitizer/GCC.\n");
+       (void)fprintf (f, "Compiled with AddressSanitizer/GCC.\n");
 #elif defined(__has_feature)
 #  if __has_feature(address_sanitizer)
-       (void)fprintf (stderr, "Compiled with AddressSanitizer/Clang.\n");
+       (void)fprintf (f, "Compiled with AddressSanitizer/Clang.\n");
 #  elif __has_feature(memory_sanitizer)
-       (void)fprintf (stderr, "Compiled with MemorySanitizer/Clang.\n");
+       (void)fprintf (f, "Compiled with MemorySanitizer/Clang.\n");
 #  endif
 #endif /* __SANITIZE_ADDRESS__ or __has_feature */
 }
 USES_APPLE_RST
 
 static void
-print_usage(void)
+print_usage(FILE *f)
 {
-       print_version();
-       (void)fprintf(stderr,
+       print_version(f);
+       (void)fprintf(f,
 "Usage: %s [-Abd" D_FLAG "efhH" I_FLAG J_FLAG "KlLnNOpqStu" U_FLAG "vxX#]" B_FLAG_USAGE " [ -c count ] [--count]\n", program_name);
-       (void)fprintf(stderr,
+       (void)fprintf(f,
 "\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n");
-       (void)fprintf(stderr,
+       (void)fprintf(f,
 "\t\t[ -i interface ]" IMMEDIATE_MODE_USAGE j_FLAG_USAGE "\n");
 #ifdef HAVE_PCAP_FINDALLDEVS_EX
-       (void)fprintf(stderr,
+       (void)fprintf(f,
 "\t\t" LIST_REMOTE_INTERFACES_USAGE "\n");
 #endif
 #ifdef USE_LIBSMI
-       (void)fprintf(stderr,
+       (void)fprintf(f,
 "\t\t" m_FLAG_USAGE "\n");
 #endif
-       (void)fprintf(stderr,
+       (void)fprintf(f,
 "\t\t[ -M secret ] [ --number ] [ --print ]" Q_FLAG_USAGE "\n");
-       (void)fprintf(stderr,
+       (void)fprintf(f,
 "\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ --version ]\n");
-       (void)fprintf(stderr,
+       (void)fprintf(f,
 "\t\t[ -V file ] [ -w file ] [ -W filecount ] [ -y datalinktype ]\n");
 #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
-       (void)fprintf(stderr,
+       (void)fprintf(f,
 "\t\t[ --time-stamp-precision precision ] [ --micro ] [ --nano ]\n");
 #endif
-       (void)fprintf(stderr,
+       (void)fprintf(f,
 "\t\t[ -z postrotate-command ] [ -Z user ] [ expression ]\n");
 }