Make the "Save only marked frames" button in the "Save As..." dialog box
[obnox/wireshark/wip.git] / capture.c
index 8f4749df6d00cf62908e9f5e9780f35eadf7b5a1..413b1750edcdf9554fe0ea2d8eb7e960a13a5fda 100644 (file)
--- a/capture.c
+++ b/capture.c
@@ -1,7 +1,7 @@
 /* capture.c
  * Routines for packet capture windows
  *
- * $Id: capture.c,v 1.160 2001/11/28 07:11:07 guy Exp $
+ * $Id: capture.c,v 1.163 2001/12/04 08:25:55 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 #include "simple_dialog.h"
 #include "prefs.h"
 #include "globals.h"
+#include "conditions.h"
+#include "capture_stop_conditions.h"
+#include "ringbuffer.h"
 
 #include "wiretap/libpcap.h"
 #include "wiretap/wtap.h"
 
+#include "packet-atalk.h"
 #include "packet-clip.h"
 #include "packet-eth.h"
 #include "packet-fddi.h"
@@ -284,8 +288,13 @@ do_capture(char *capfile_name)
   struct pcap_stat stats;
 
   if (capfile_name != NULL) {
-    /* 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, 0600);
+    if (cfile.ringbuffer_on) {
+      /* ringbuffer is enabled */
+      cfile.save_file_fd = ringbuf_init(capfile_name, cfile.ringbuffer_num_files);
+    } 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, 0600);
+    }
     is_tempfile = FALSE;
   } else {
     /* Choose a random name for the capture buffer */
@@ -299,6 +308,9 @@ do_capture(char *capfile_name)
        "The temporary file to which the capture would be saved (\"%s\")"
        "could not be opened: %s.", capfile_name, strerror(errno));
     } else {
+      if (cfile.ringbuffer_on) {
+        ringbuf_error_cleanup();
+      }
       simple_dialog(ESD_TYPE_CRIT, NULL,
        file_open_error_message(errno, TRUE), capfile_name);
     }
@@ -310,7 +322,9 @@ do_capture(char *capfile_name)
 
   if (prefs.capture_real_time) {       /* do the capture in a child process */
     char ssnap[24];
-    char scount[24];   /* need a constant for len of numbers */
+    char scount[24];                   /* need a constant for len of numbers */
+    char sautostop_filesize[24];       /* need a constant for len of numbers */
+    char sautostop_duration[24];       /* need a constant for len of numbers */
     char save_file_fd[24];
     char errmsg[1024+1];
     int error;
@@ -349,6 +363,14 @@ do_capture(char *capfile_name)
     sprintf(ssnap,"%d",cfile.snap);
     argv = add_arg(argv, &argc, ssnap);
 
+    argv = add_arg(argv, &argc, "-a");
+    sprintf(sautostop_filesize,"filesize:%d",cfile.autostop_filesize);
+    argv = add_arg(argv, &argc, sautostop_filesize);
+
+    argv = add_arg(argv, &argc, "-a");
+    sprintf(sautostop_duration,"duration:%d",cfile.autostop_duration);
+    argv = add_arg(argv, &argc, sautostop_duration);
+
     if (!prefs.capture_prom_mode)
       argv = add_arg(argv, &argc, "-p");
 
@@ -639,7 +661,11 @@ do_capture(char *capfile_name)
     }
     /* We're not doing a capture any more, so we don't have a save
        file. */
-    g_free(cfile.save_file);
+    if (cfile.ringbuffer_on) {
+      ringbuf_free();
+    } else {
+      g_free(cfile.save_file);
+    }
     cfile.save_file = NULL;
   }
 }
@@ -1158,7 +1184,7 @@ pipe_dispatch(int fd, loop_data *ld, struct pcap_hdr *hdr)
     case WTAP_ENCAP_FDDI_BITSWAPPED:
       capture_fddi(pd, whdr.caplen, &ld->counts);
       break;
-    case WTAP_ENCAP_PRISM:
+    case WTAP_ENCAP_PRISM_HEADER:
       capture_prism(pd, 0, whdr.caplen, &ld->counts);
       break;
     case WTAP_ENCAP_TOKEN_RING:
@@ -1182,6 +1208,9 @@ pipe_dispatch(int fd, loop_data *ld, struct pcap_hdr *hdr)
     case WTAP_ENCAP_CHDLC:
       capture_chdlc(pd, 0, whdr.caplen, &ld->counts);
       break;
+    case WTAP_ENCAP_LOCALTALK:
+      capture_llap(pd, whdr.caplen, &ld->counts);
+      break;
     /* XXX - FreeBSD may append 4-byte ATM pseudo-header to DLT_ATM_RFC1483,
        with LLC header following; we should implement it at some
        point. */
@@ -1213,9 +1242,12 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
   struct bpf_program fcode;
   time_t      upd_time, cur_time;
   int         err, inpkts;
+  condition *cnd_stop_capturesize;
+  condition *cnd_stop_timeout;
   unsigned int i;
   static const char capstart_msg = SP_CAPSTART;
   char        errmsg[4096+1];
+  gboolean    dump_ok;
 #ifndef _WIN32
   static const char ppamsg[] = "can't find PPA for ";
   char       *libpcap_warn;
@@ -1407,8 +1439,13 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
        " that Ethereal doesn't support (data link type %d).", pcap_encap);
     goto error;
   }
-  ld.pdh = wtap_dump_fdopen(cfile.save_file_fd, WTAP_FILE_PCAP,
+  if (cfile.ringbuffer_on) {
+    ld.pdh = ringbuf_init_wtap_dump_fdopen(WTAP_FILE_PCAP, ld.linktype, 
+      snaplen, &err);
+  } else {
+    ld.pdh = wtap_dump_fdopen(cfile.save_file_fd, WTAP_FILE_PCAP,
       ld.linktype, snaplen, &err);
+  }
 
   if (ld.pdh == NULL) {
     /* We couldn't set up to write to the capture file. */
@@ -1533,6 +1570,14 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
    */
   signal(SIGUSR1, stop_capture);
 #endif
+  /* initialize capture stop conditions */ 
+  init_capture_stop_conditions();
+  /* create stop conditions */
+  cnd_stop_capturesize = 
+    cnd_new(CND_CLASS_CAPTURESIZE,(long)cfile.autostop_filesize * 1000); 
+  cnd_stop_timeout = 
+    cnd_new(CND_CLASS_TIMEOUT,(gint32)cfile.autostop_duration);
+
   while (ld.go) {
     while (gtk_events_pending()) gtk_main_iteration();
 
@@ -1602,6 +1647,28 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
     }
     if (inpkts > 0)
       ld.sync_packets += inpkts;
+    /* check capture stop conditons */
+    if (cnd_eval(cnd_stop_timeout) == TRUE) {
+      /* The specified capture time has elapsed; stop the capture. */
+      ld.go = FALSE;
+    } else if ((cnd_eval(cnd_stop_capturesize, 
+                  (guint32)wtap_get_bytes_dumped(ld.pdh))) == TRUE){
+      /* Capture file reached its maximum size. */
+      if (cfile.ringbuffer_on) {
+        /* Switch to the next ringbuffer file */
+        if (ringbuf_switch_file(&cfile, &ld.pdh, &ld.err)) {
+          /* File switch succeeded: reset the condition */
+          cnd_reset(cnd_stop_capturesize);
+        } else {
+          /* File switch failed: stop here */
+          ld.go = FALSE;
+          continue;
+        }
+      } else {
+        /* no ringbuffer - just stop */
+        ld.go = FALSE;
+      }
+    }
     /* Only update once a second so as not to overload slow displays */
     cur_time = time(NULL);
     if (cur_time > upd_time) {
@@ -1633,6 +1700,10 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
     }
   }
     
+  /* delete stop conditions */
+  cnd_delete(cnd_stop_capturesize);
+  cnd_delete(cnd_stop_timeout);
+
   if (ld.err != 0) {
     get_capture_file_io_error(errmsg, sizeof(errmsg), cfile.save_file, ld.err,
                              FALSE);
@@ -1649,9 +1720,18 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
     /* A write failed, so we've already told the user there's a problem;
        if the close fails, there's no point in telling them about that
        as well. */
-    wtap_dump_close(ld.pdh, &err);
-  } else {
-    if (!wtap_dump_close(ld.pdh, &err)) {
+    if (cfile.ringbuffer_on) {
+      ringbuf_wtap_dump_close(&cfile, &err);
+    } else {
+      wtap_dump_close(ld.pdh, &err);
+    }
+   } else {
+    if (cfile.ringbuffer_on) {
+      dump_ok = ringbuf_wtap_dump_close(&cfile, &err);
+    } else {
+      dump_ok = wtap_dump_close(ld.pdh, &err);
+    }
+    if (!dump_ok) {
       get_capture_file_io_error(errmsg, sizeof(errmsg), cfile.save_file, err,
                                TRUE);
       if (capture_child) {
@@ -1709,14 +1789,19 @@ capture(gboolean *stats_known, struct pcap_stat *stats)
   return TRUE;
 
 error:
-  /* We can't use the save file, and we have no wtap_dump stream
-     to close in order to close it, so close the FD directly. */
-  close(cfile.save_file_fd);
-
-  /* We couldn't even start the capture, so get rid of the capture
-     file. */
-  unlink(cfile.save_file); /* silently ignore error */
-  g_free(cfile.save_file);
+  if (cfile.ringbuffer_on) {
+    /* cleanup ringbuffer */
+    ringbuf_error_cleanup();
+  } else {
+    /* We can't use the save file, and we have no wtap_dump stream
+       to close in order to close it, so close the FD directly. */
+    close(cfile.save_file_fd);
+
+    /* We couldn't even start the capture, so get rid of the capture
+       file. */
+    unlink(cfile.save_file); /* silently ignore error */
+    g_free(cfile.save_file);
+  }
   cfile.save_file = NULL;
   if (capture_child) {
     /* This is the child process for a sync mode capture.
@@ -1879,6 +1964,9 @@ capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
     case WTAP_ENCAP_FDDI_BITSWAPPED:
       capture_fddi(pd, phdr->len, &ld->counts);
       break;
+    case WTAP_ENCAP_PRISM_HEADER:
+      capture_prism(pd, 0, phdr->len, &ld->counts);
+      break;
     case WTAP_ENCAP_TOKEN_RING:
       capture_tr(pd, 0, phdr->len, &ld->counts);
       break;
@@ -1897,6 +1985,9 @@ capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
     case WTAP_ENCAP_LINUX_ATM_CLIP:
       capture_clip(pd, phdr->len, &ld->counts);
       break;
+    case WTAP_ENCAP_LOCALTALK:
+      capture_llap(pd, phdr->len, &ld->counts);
+      break;
     /* XXX - FreeBSD may append 4-byte ATM pseudo-header to DLT_ATM_RFC1483,
        with LLC header following; we should implement it at some
        point. */