fix doxygen generation
[obnox/wireshark/wip.git] / capture.c
index 31f250b16f43b9dc1c39417158b9922e84888f4b..e848d29d6d27a2033d1ce92c02641fad223fa716 100644 (file)
--- a/capture.c
+++ b/capture.c
@@ -1,7 +1,7 @@
 /* capture.c
  * Routines for packet capture windows
  *
- * $Id: capture.c,v 1.243 2004/03/02 22:07:21 ulfl Exp $
+ * $Id$
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+/* With MSVC and a libethereal.dll this file needs to import some variables 
+   in a special way. Therefore _NEED_VAR_IMPORT_ is defined. */
+#define _NEED_VAR_IMPORT_
+
 #ifdef HAVE_CONFIG_H
 # include "config.h"
 #endif
 #include "pcap-util.h"
 #include "alert_box.h"
 #include "simple_dialog.h"
-#include "prefs.h"
+#include <epan/prefs.h>
 #include "globals.h"
 #include "conditions.h"
 #include "capture_stop_conditions.h"
 #include "wiretap/wtap.h"
 #include "wiretap/wtap-capture.h"
 
-#include "packet-atalk.h"
-#include "packet-atm.h"
-#include "packet-clip.h"
-#include "packet-eth.h"
-#include "packet-fddi.h"
-#include "packet-null.h"
-#include "packet-ppp.h"
-#include "packet-raw.h"
-#include "packet-sll.h"
-#include "packet-tr.h"
-#include "packet-ieee80211.h"
-#include "packet-chdlc.h"
-#include "packet-prism.h"
-#include "packet-ipfc.h"
-#include "packet-arcnet.h"
+#include <epan/dissectors/packet-ap1394.h>
+#include <epan/dissectors/packet-atalk.h>
+#include <epan/dissectors/packet-atm.h>
+#include <epan/dissectors/packet-clip.h>
+#include <epan/dissectors/packet-eth.h>
+#include <epan/dissectors/packet-fddi.h>
+#include <epan/dissectors/packet-null.h>
+#include <epan/dissectors/packet-ppp.h>
+#include <epan/dissectors/packet-raw.h>
+#include <epan/dissectors/packet-sll.h>
+#include <epan/dissectors/packet-tr.h>
+#include <epan/dissectors/packet-ieee80211.h>
+#include <epan/dissectors/packet-chdlc.h>
+#include <epan/dissectors/packet-prism.h>
+#include <epan/dissectors/packet-ipfc.h>
+#include <epan/dissectors/packet-arcnet.h>
 
 #ifdef _WIN32
 #include "capture-wpcap.h"
@@ -219,7 +224,6 @@ typedef struct _loop_data {
 #define O_BINARY       0
 #endif
 
-
 static gboolean sync_pipe_do_capture(gboolean is_tempfile);
 static gboolean sync_pipe_input_cb(gint source, gpointer user_data);
 static void sync_pipe_wait_for_child(gboolean);
@@ -256,6 +260,7 @@ do_capture(const char *save_file)
   char tmpname[128+1];
   gboolean is_tempfile;
   gchar *capfile_name;
+  gboolean ret;
 
   if (save_file != NULL) {
     /* If the Sync option is set, we return to the caller while the capture
@@ -266,7 +271,7 @@ do_capture(const char *save_file)
     if (capture_opts.multi_files_on) {
       /* ringbuffer is enabled */
       cfile.save_file_fd = ringbuf_init(capfile_name,
-          (capture_opts.has_ring_num_files) ? capture_opts.num_files : 0);
+          (capture_opts.has_ring_num_files) ? capture_opts.ring_num_files : 0);
     } else {
       /* Try to open/create the specified file for use as a capture buffer. */
       cfile.save_file_fd = open(capfile_name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT,
@@ -298,16 +303,21 @@ do_capture(const char *save_file)
   cfile.save_file = capfile_name;
   /* cfile.save_file is "g_free"ed below, which is equivalent to
      "g_free(capfile_name)". */
+  fork_child = -1;
 
   if (capture_opts.sync_mode) {        
     /* sync mode: do the capture in a child process */
-    return sync_pipe_do_capture(is_tempfile);
+    ret = sync_pipe_do_capture(is_tempfile);
     /* capture is still running */
+    set_main_window_name("(Live Capture in Progress) - Ethereal");
   } else {
     /* normal mode: do the capture synchronously */
-    return normal_do_capture(is_tempfile);
+    set_main_window_name("(Live Capture in Progress) - Ethereal");
+    ret = normal_do_capture(is_tempfile);
     /* capture is finished here */
   }
+
+  return ret;
 }
 
 
@@ -396,9 +406,9 @@ sync_pipe_do_capture(gboolean is_tempfile) {
     sprintf(save_file_fd,"%d",cfile.save_file_fd);     /* in lieu of itoa */
     argv = sync_pipe_add_arg(argv, &argc, save_file_fd);
 
-    if (capture_opts.has_autostop_count) {
+    if (capture_opts.has_autostop_packets) {
       argv = sync_pipe_add_arg(argv, &argc, "-c");
-      sprintf(scount,"%d",capture_opts.autostop_count);
+      sprintf(scount,"%d",capture_opts.autostop_packets);
       argv = sync_pipe_add_arg(argv, &argc, scount);
     }
 
@@ -410,7 +420,12 @@ sync_pipe_do_capture(gboolean is_tempfile) {
 
     if (capture_opts.linktype != -1) {
       argv = sync_pipe_add_arg(argv, &argc, "-y");
+#ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
+      sprintf(ssnap,"%s",pcap_datalink_val_to_name(capture_opts.linktype));
+#else
+      /* XXX - just treat it as a number */
       sprintf(ssnap,"%d",capture_opts.linktype);
+#endif
       argv = sync_pipe_add_arg(argv, &argc, ssnap);
     }
 
@@ -426,6 +441,10 @@ sync_pipe_do_capture(gboolean is_tempfile) {
       argv = sync_pipe_add_arg(argv, &argc, sautostop_duration);
     }
 
+    if (!capture_opts.show_info) {
+      argv = sync_pipe_add_arg(argv, &argc, "-H");
+    }
+
     if (!capture_opts.promisc_mode)
       argv = sync_pipe_add_arg(argv, &argc, "-p");
 
@@ -572,7 +591,7 @@ sync_pipe_do_capture(gboolean is_tempfile) {
        unlink(cfile.save_file);
        g_free(cfile.save_file);
        cfile.save_file = NULL;
-       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                        "Capture child process sent us a bad message");
        return FALSE;
       }
@@ -583,22 +602,22 @@ sync_pipe_do_capture(gboolean is_tempfile) {
         what the problem was. */
       if (byte_count == 0) {
        /* Zero-length message? */
-       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                "Capture child process failed, but its error message was empty.");
       } else {
        msg = g_malloc(byte_count + 1);
        if (msg == NULL) {
-         simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                "Capture child process failed, but its error message was too big.");
        } else {
          i = read(sync_pipe[READ], msg, byte_count);
          msg[byte_count] = '\0';
          if (i < 0) {
-           simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+           simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                  "Capture child process failed: Error %s reading its error message.",
                  strerror(errno));
          } else if (i == 0) {
-           simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+           simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                  "Capture child process failed: EOF reading its error message.");
            sync_pipe_wait_for_child(FALSE);
          } else
@@ -786,7 +805,7 @@ sync_pipe_wait_for_child(gboolean always_report)
      in the dialog box?
      XXX - set "fork_child" to -1 if we find it exited? */
   if (_cwait(&wstatus, fork_child, _WAIT_CHILD) == -1) {
-    simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                "Child capture process stopped unexpectedly");
   }
 #else
@@ -795,25 +814,25 @@ sync_pipe_wait_for_child(gboolean always_report)
       /* The child exited; display its exit status, if it's not zero,
          and even if it's zero if "always_report" is true. */
       if (always_report || WEXITSTATUS(wstatus) != 0) {
-        simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                      "Child capture process exited: exit status %d",
                      WEXITSTATUS(wstatus));
       }
     } else if (WIFSTOPPED(wstatus)) {
       /* It stopped, rather than exiting.  "Should not happen." */
-      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                    "Child capture process stopped: %s",
                    sync_pipe_signame(WSTOPSIG(wstatus)));
     } else if (WIFSIGNALED(wstatus)) {
       /* It died with a signal. */
-      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                    "Child capture process died: %s%s",
                    sync_pipe_signame(WTERMSIG(wstatus)),
                    WCOREDUMP(wstatus) ? " - core dumped" : "");
     } else {
       /* What?  It had to either have exited, or stopped, or died with
          a signal; what happened here? */
-      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                    "Child capture process died: wait status %#o", wstatus);
     }
   }
@@ -1403,9 +1422,11 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
   time_t      upd_time, cur_time;
   time_t      start_time;
   int         err, inpkts;
-  condition  *cnd_stop_capturesize = NULL;
-  condition  *cnd_stop_timeout = NULL;
-  condition  *cnd_ring_timeout = NULL;
+  condition  *cnd_file_duration = NULL;
+  condition  *cnd_autostop_files = NULL;
+  condition  *cnd_autostop_size = NULL;
+  condition  *cnd_autostop_duration = NULL;
+  guint32     autostop_files = 0;
   char        errmsg[4096+1];
   gboolean    write_ok;
   gboolean    close_ok;
@@ -1428,7 +1449,7 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
 #ifdef MUST_DO_SELECT
   int         pcap_fd = 0;
 #endif
-  guint32     num_files = capture_opts.num_files;
+  gboolean    show_info = capture_opts.show_info || !capture_opts.sync_mode;
 
   /* Initialize Windows Socket if we are in a WIN32 OS
      This needs to be done before querying the interface for network/netmask */
@@ -1478,8 +1499,8 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
 
   ld.go             = TRUE;
   ld.counts.total   = 0;
-  if (capture_opts.has_autostop_count)
-    ld.max          = capture_opts.autostop_count;
+  if (capture_opts.has_autostop_packets)
+    ld.max          = capture_opts.autostop_packets;
   else
     ld.max          = 0;       /* no limit */
   ld.err            = 0;       /* no error seen yet */
@@ -1515,6 +1536,20 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
                       open_err_str);
 
   if (pch != NULL) {
+#ifdef _WIN32
+    /* try to set the capture buffer size */
+    if (pcap_setbuff(pch, capture_opts.buffer_size * 1024 * 1024) != 0) {
+        simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
+          "%sCouldn't set the capture buffer size!%s\n"
+          "\n"
+          "The capture buffer size of %luMB seems to be too high for your machine,\n"
+          "the default of 1MB will be used.\n"
+          "\n"
+          "Nonetheless, the capture is started.\n",
+          simple_dialog_primary_start(), simple_dialog_primary_end(), capture_opts.buffer_size);
+    }
+#endif
+
     /* setting the data link type only works on real interfaces */
     if (capture_opts.linktype != -1) {
       set_linktype_err_str = set_pcap_linktype(pch, cfile.iface,
@@ -1738,9 +1773,11 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
   }
 
   /* start capture info dialog */
-  capture_ui.callback_data  = &ld;
-  capture_ui.counts         = &ld.counts;
-  capture_info_create(&capture_ui);
+  if(show_info) {
+      capture_ui.callback_data  = &ld;
+      capture_ui.counts         = &ld.counts;
+      capture_info_create(&capture_ui, cfile.iface);
+  }
 
   start_time = time(NULL);
   upd_time = time(NULL);
@@ -1756,20 +1793,26 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
   if (capture_child)
     signal(SIGUSR1, stop_capture_signal_handler);
 #endif
+
   /* initialize capture stop conditions */
   init_capture_stop_conditions();
   /* create stop conditions */
   if (capture_opts.has_autostop_filesize)
-    cnd_stop_capturesize =
-        cnd_new(CND_CLASS_CAPTURESIZE,(long)capture_opts.autostop_filesize * 1000);
+    cnd_autostop_size =
+        cnd_new(CND_CLASS_CAPTURESIZE,(long)capture_opts.autostop_filesize);
   if (capture_opts.has_autostop_duration)
-    cnd_stop_timeout =
+    cnd_autostop_duration =
         cnd_new(CND_CLASS_TIMEOUT,(gint32)capture_opts.autostop_duration);
 
-  if (capture_opts.multi_files_on && capture_opts.has_ring_duration)
-    cnd_ring_timeout =
-       cnd_new(CND_CLASS_TIMEOUT, capture_opts.ringbuffer_duration);
+  if (capture_opts.multi_files_on) {
+      if (capture_opts.has_file_duration)
+        cnd_file_duration =
+           cnd_new(CND_CLASS_TIMEOUT, capture_opts.file_duration);
 
+      if (capture_opts.has_autostop_files)
+        cnd_autostop_files =
+           cnd_new(CND_CLASS_CAPTURESIZE, capture_opts.autostop_files);
+  }
 
   /* WOW, everything is prepared! */
   /* please fasten your seat belts, we will enter now the actual capture loop */
@@ -1803,7 +1846,7 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
       }
     }
     else
-#endif
+#endif /* _WIN32 */
     {
 #ifdef MUST_DO_SELECT
       /*
@@ -1863,23 +1906,29 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
         ld.pcap_err = TRUE;
         ld.go = FALSE;
       }
-#endif
+#endif /* MUST_DO_SELECT */
     }
 
     if (inpkts > 0) {
       ld.sync_packets += inpkts;
-      /* check capture stop conditons */
-      if (cnd_stop_capturesize != NULL && cnd_eval(cnd_stop_capturesize,
+
+      /* check capture size condition */
+      if (cnd_autostop_size != NULL && cnd_eval(cnd_autostop_size,
                     (guint32)wtap_get_bytes_dumped(ld.pdh))){
-        /* Capture file reached its maximum size. */
-        if (num_files > 1 || capture_opts.multi_files_on) {
+        /* Capture size limit reached, do we have another file? */
+        if (capture_opts.multi_files_on) {
+          if (cnd_autostop_files != NULL && cnd_eval(cnd_autostop_files, ++autostop_files)) {
+            /* no files left: stop here */
+            ld.go = FALSE;
+            continue;
+          }
+
           /* Switch to the next ringbuffer file */
           if (ringbuf_switch_file(&cfile, &ld.pdh, &ld.err)) {
-            num_files--;
-            /* File switch succeeded: reset the condition */
-            cnd_reset(cnd_stop_capturesize);
-            if (cnd_ring_timeout) {
-              cnd_reset(cnd_ring_timeout);
+            /* File switch succeeded: reset the conditions */
+            cnd_reset(cnd_autostop_size);
+            if (cnd_file_duration) {
+              cnd_reset(cnd_file_duration);
             }
           } else {
             /* File switch failed: stop here */
@@ -1887,13 +1936,11 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
             continue;
           }
         } else {
-          /* no files left */
-          if (!capture_opts.multi_files_on) {
-            /* ... and no ringbuffer, stop now */
-            ld.go = FALSE;
-          }
+          /* single file, stop now */
+          ld.go = FALSE;
+          continue;
         }
-      }
+      } /* cnd_autostop_size */
     }
 
     /* Only update once a second so as not to overload slow displays */
@@ -1907,10 +1954,12 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
 
        /* Let the parent process know. */
       /* calculate and display running time */
-      cur_time -= start_time;
-      capture_ui.running_time   = cur_time;
-      capture_ui.new_packets    = ld.sync_packets;
-      capture_info_update(&capture_ui);
+      if(show_info) {
+          cur_time -= start_time;
+          capture_ui.running_time   = cur_time;
+          capture_ui.new_packets    = ld.sync_packets;
+          capture_info_update(&capture_ui);
+      }
 
       if (ld.sync_packets) {
         /* do sync here */
@@ -1926,39 +1975,53 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
         ld.sync_packets = 0;
       }
 
-      if (cnd_stop_timeout != NULL && cnd_eval(cnd_stop_timeout)) {
-        /* The specified capture time has elapsed; stop the capture. */
+      /* check capture duration condition */
+      if (cnd_autostop_duration != NULL && cnd_eval(cnd_autostop_duration)) {
+        /* The maximum capture time has elapsed; stop the capture. */
         ld.go = FALSE;
-      } else if (cnd_ring_timeout != NULL && cnd_eval(cnd_ring_timeout)) {
-        if(num_files > 1 || capture_opts.multi_files_on) {
-          /* time elasped for this ring file, switch to the next */
+        continue;
+      }
+      
+      /* check capture file duration condition */
+      if (cnd_file_duration != NULL && cnd_eval(cnd_file_duration)) {
+        /* duration limit reached, do we have another file? */
+        if (capture_opts.multi_files_on) {
+          if (cnd_autostop_files != NULL && cnd_eval(cnd_autostop_files, ++autostop_files)) {
+            /* no files left: stop here */
+            ld.go = FALSE;
+            continue;
+          }
+
+          /* Switch to the next ringbuffer file */
           if (ringbuf_switch_file(&cfile, &ld.pdh, &ld.err)) {
-            /* File switch succeeded: reset the condition */
-            cnd_reset(cnd_ring_timeout);
-            num_files--;
+            /* file switch succeeded: reset the conditions */
+            cnd_reset(cnd_file_duration);
+            if(cnd_autostop_size)
+              cnd_reset(cnd_autostop_size);
           } else {
             /* File switch failed: stop here */
                ld.go = FALSE;
+            continue;
           }
         } else {
-          /* no files left */
-          if (!capture_opts.multi_files_on) {
-            /* ... and no ringbuffer, stop now */
-            ld.go = FALSE;
-          }
+          /* single file, stop now */
+          ld.go = FALSE;
+          continue;
         }
-      }
+      } /* cnd_file_duration */
     }
 
   } /* while (ld.go) */
 
   /* delete stop conditions */
-  if (cnd_stop_capturesize != NULL)
-    cnd_delete(cnd_stop_capturesize);
-  if (cnd_stop_timeout != NULL)
-    cnd_delete(cnd_stop_timeout);
-  if (cnd_ring_timeout != NULL)
-    cnd_delete(cnd_ring_timeout);
+  if (cnd_file_duration != NULL)
+    cnd_delete(cnd_file_duration);
+  if (cnd_autostop_files != NULL)
+    cnd_delete(cnd_autostop_files);
+  if (cnd_autostop_size != NULL)
+    cnd_delete(cnd_autostop_size);
+  if (cnd_autostop_duration != NULL)
+    cnd_delete(cnd_autostop_duration);
 
   if (ld.pcap_err) {
     snprintf(errmsg, sizeof(errmsg), "Error while capturing packets: %s",
@@ -2031,7 +2094,9 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
   WSACleanup();
 #endif
 
-  capture_info_destroy(&capture_ui);
+  if(show_info) {
+    capture_info_destroy(&capture_ui);
+  }
 
   return write_ok;
 
@@ -2282,6 +2347,9 @@ capture_pcap_cb(guchar *user, const struct pcap_pkthdr *phdr,
     case WTAP_ENCAP_ARCNET_LINUX:
       capture_arcnet(pd, whdr.caplen, &ld->counts, TRUE, FALSE);
       break;
+    case WTAP_ENCAP_APPLE_IP_OVER_IEEE1394:
+      capture_ap1394(pd, 0, whdr.caplen, &ld->counts);
+      break;
     /* XXX - some ATM drivers on FreeBSD might prepend a 4-byte ATM
        pseudo-header to DLT_ATM_RFC1483, with LLC header following;
        we might have to implement that at some point. */