]> The Tcpdump Group git mirrors - tcpdump/blobdiff - tcpdump.c
Use the new debugging routines in libpcap.
[tcpdump] / tcpdump.c
index de0054ec29bb9c9741abfe32a861ceff6b2aac29..e0237061902a89817cd7866d5deaf97d0dc1a682 100644 (file)
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -130,7 +130,19 @@ The Regents of the University of California.  All rights reserved.\n";
 static int Cflag;                      /* rotate dump files after this many bytes */
 static int Cflag_count;                        /* Keep track of which file number we're writing */
 static int Dflag;                      /* list available devices and exit */
-static int dflag;                      /* print filter code */
+/*
+ * This is exported because, in some versions of libpcap, if libpcap
+ * is built with optimizer debugging code (which is *NOT* the default
+ * configuration!), the library *imports*(!) a variable named dflag,
+ * under the expectation that tcpdump is exporting it, to govern
+ * how much debugging information to print when optimizing
+ * the generated BPF code.
+ *
+ * This is a horrible hack; newer versions of libpcap don't import
+ * dflag but, instead, *if* built with optimizer debugging code,
+ * *export* a routine to set that flag.
+ */
+int dflag;                             /* print filter code */
 static int Gflag;                      /* rotate dump files after this many seconds */
 static int Gflag_count;                        /* number of files created with Gflag rotation */
 static time_t Gflag_time;              /* The last time_t the dump file was rotated. */
@@ -209,6 +221,57 @@ struct dump_info {
 #endif
 };
 
+#if defined(HAVE_PCAP_SET_PARSER_DEBUG)
+/*
+ * We have pcap_set_parser_debug() in libpcap; declare it (it's not declared
+ * by any libpcap header, because it's a special hack, only available if
+ * libpcap was configured to include it, and only intended for use by
+ * libpcap developers trying to debug the parser for filter expressions).
+ */
+#ifdef _WIN32
+__declspec(dllimport)
+#else /* _WIN32 */
+extern
+#endif /* _WIN32 */
+void pcap_set_parser_debug(int);
+#elif defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG)
+/*
+ * We don't have pcap_set_parser_debug() in libpcap, but we do have
+ * pcap_debug or yydebug.  Make a local version of pcap_set_parser_debug()
+ * to set the flag, and define HAVE_PCAP_SET_PARSER_DEBUG.
+ */
+static void
+pcap_set_parser_debug(int value)
+{
+#ifdef HAVE_PCAP_DEBUG
+       extern int pcap_debug;
+
+       pcap_debug = value;
+#else /* HAVE_PCAP_DEBUG */
+       extern int yydebug;
+
+       yydebug = value;
+#endif /* HAVE_PCAP_DEBUG */
+}
+
+#define HAVE_PCAP_SET_PARSER_DEBUG
+#endif
+
+#if defined(HAVE_PCAP_SET_OPTIMIZER_DEBUG)
+/*
+ * We have pcap_set_optimizer_debug() in libpcap; declare it (it's not declared
+ * by any libpcap header, because it's a special hack, only available if
+ * libpcap was configured to include it, and only intended for use by
+ * libpcap developers trying to debug the optimizer for filter expressions).
+ */
+#ifdef _WIN32
+__declspec(dllimport)
+#else /* _WIN32 */
+extern
+#endif /* _WIN32 */
+void pcap_set_optimizer_debug(int);
+#endif
+
 #ifdef HAVE_PCAP_SET_TSTAMP_TYPE
 static void
 show_tstamp_types_and_exit(const char *device)
@@ -453,7 +516,7 @@ static const struct option longopts[] = {
 #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
        { "immediate-mode", no_argument, NULL, OPTION_IMMEDIATE_MODE },
 #endif
-#if defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG)
+#ifdef HAVE_PCAP_SET_PARSER_DEBUG
        { "debug-filter-parser", no_argument, NULL, 'Y' },
 #endif
        { "relinquish-privileges", required_argument, NULL, 'Z' },
@@ -1104,30 +1167,20 @@ main(int argc, char **argv)
                                error("invalid data link type %s", yflag_dlt_name);
                        break;
 
-#if defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG)
+#ifdef HAVE_PCAP_SET_PARSER_DEBUG
                case 'Y':
                        {
                        /* Undocumented flag */
-#ifdef HAVE_PCAP_DEBUG
-                       extern int pcap_debug;
-                       pcap_debug = 1;
-#else
-                       extern int yydebug;
-                       yydebug = 1;
-#endif
+                       pcap_set_parser_debug(1);
                        }
                        break;
 #endif
                case 'z':
-                       zflag = strdup(optarg);
-                       if (zflag == NULL)
-                               error("Unable to allocate memory for -z argument");
+                       zflag = optarg;
                        break;
 
                case 'Z':
-                       username = strdup(optarg);
-                       if (username == NULL)
-                               error("Unable to allocate memory for -Z argument");
+                       username = optarg;
                        break;
 
                case '#':
@@ -1247,7 +1300,7 @@ main(int argc, char **argv)
                                VFile = fopen(VFileName, "r");
 
                        if (VFile == NULL)
-                               error("Unable to open file: %s\n", strerror(errno));
+                               error("Unable to open file: %s\n", pcap_strerror(errno));
 
                        ret = get_next_file(VFile, VFileLine);
                        if (!ret)
@@ -1480,12 +1533,16 @@ main(int argc, char **argv)
        else
                cmdbuf = copy_argv(&argv[optind]);
 
+#ifdef HAVE_PCAP_SET_OPTIMIZER_DEBUG
+       pcap_set_optimizer_debug(dflag);
+#endif
        if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
                error("%s", pcap_geterr(pd));
        if (dflag) {
                bpf_dump(&fcode, dflag);
                pcap_close(pd);
                free(cmdbuf);
+               pcap_freecode(&fcode);
                exit(0);
        }
        init_print(ndo, localnet, netmask, timezone_offset);
@@ -1555,7 +1612,7 @@ main(int argc, char **argv)
                error("%s", pcap_geterr(pd));
 #ifdef HAVE_CAPSICUM
        if (RFileName == NULL && VFileName == NULL) {
-               static const unsigned long cmds[] = { BIOCGSTATS };
+               static const unsigned long cmds[] = { BIOCGSTATS, BIOCROTZBUF };
 
                cap_rights_init(&rights, CAP_IOCTL, CAP_READ);
                if (cap_rights_limit(pcap_fileno(pd), &rights) < 0 &&
@@ -1782,6 +1839,7 @@ main(int argc, char **argv)
        while (ret != NULL);
 
        free(cmdbuf);
+       pcap_freecode(&fcode);
        exit(status == -1 ? 1 : 0);
 }
 
@@ -1884,17 +1942,31 @@ info(register int verbose)
 }
 
 #if defined(HAVE_FORK) || defined(HAVE_VFORK)
+#ifdef HAVE_FORK
+#define fork_subprocess() fork()
+#else
+#define fork_subprocess() vfork()
+#endif
 static void
 compress_savefile(const char *filename)
 {
-# ifdef HAVE_FORK
-       if (fork())
-# else
-       if (vfork())
-# endif
+       pid_t child;
+
+       child = fork_subprocess();
+       if (child == -1) {
+               fprintf(stderr,
+                       "compress_savefile: fork failed: %s\n",
+                       pcap_strerror(errno));
+               return;
+       }
+       if (child != 0) {
+               /* Parent process. */
                return;
+       }
+
        /*
-        * Set to lowest priority so that this doesn't disturb the capture
+        * Child process.
+        * Set to lowest priority so that this doesn't disturb the capture.
         */
 #ifdef NZERO
        setpriority(PRIO_PROCESS, 0, NZERO - 1);
@@ -1903,15 +1975,15 @@ compress_savefile(const char *filename)
 #endif
        if (execlp(zflag, zflag, filename, (char *)NULL) == -1)
                fprintf(stderr,
-                       "compress_savefile:execlp(%s, %s): %s\n",
+                       "compress_savefile: execlp(%s, %s) failed: %s\n",
                        zflag,
                        filename,
-                       strerror(errno));
-# ifdef HAVE_FORK
+                       pcap_strerror(errno));
+#ifdef HAVE_FORK
        exit(1);
-# else
+#else
        _exit(1);
-# endif
+#endif
 }
 #else  /* HAVE_FORK && HAVE_VFORK */
 static void