Split "load_cap_file()" into "open_cap_file()" and "read_cap_file()".
[obnox/wireshark/wip.git] / capture.c
index f60892a549cc3b55ea6df3e978ddf86a9863813d..106fc1302e7ec3b9590d46893da573b846fae608 100644 (file)
--- a/capture.c
+++ b/capture.c
@@ -1,7 +1,7 @@
 /* capture.c
  * Routines for packet capture windows
  *
- * $Id: capture.c,v 1.28 1999/06/21 19:04:34 gram Exp $
+ * $Id: capture.c,v 1.48 1999/08/15 00:26:10 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
 # include "config.h"
 #endif
 
+#ifdef HAVE_LIBPCAP
+
 #ifdef HAVE_SYS_TYPES_H
 # include <sys/types.h>
 #endif
 
-#include <gtk/gtk.h>
-#include <pcap.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
 
+#include <gtk/gtk.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
+
 #include <time.h>
+
+#ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_NET_IF_H
 #include <net/if.h>
+#endif
+
 #include <signal.h>
 #include <errno.h>
 
@@ -305,6 +323,7 @@ capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w) {
 
   filter_text = gtk_entry_get_text(GTK_ENTRY(filter_te));
   if (cf.cfilter) g_free(cf.cfilter);
+  cf.cfilter = NULL; /* ead 06/16/99 */
   if (filter_text && filter_text[0]) {
          cf.cfilter = g_strdup(gtk_entry_get_text(GTK_ENTRY(filter_te))); 
   }
@@ -350,18 +369,18 @@ capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w) {
         close(1);
         dup(sync_pipe[1]);
         close(sync_pipe[0]);
-        execl(ethereal_path,"ethereal","-k","-Q","-i",cf.iface,"-w",cf.save_file,
-              "-c", scount, "-s", ssnap, "-S", 
-              "-m", medium_font, "-b", bold_font,
-              (cf.cfilter == NULL)? 0 : "-f", (cf.cfilter == NULL)? 0 : cf.cfilter, 
-              0);      
+        execlp(ethereal_path,"ethereal","-k","-Q","-i",cf.iface,"-w",cf.save_file,
+               "-c", scount, "-s", ssnap, "-S", 
+               "-m", medium_font, "-b", bold_font,
+               (cf.cfilter == NULL)? 0 : "-f", (cf.cfilter == NULL)? 0 : cf.cfilter, 
+               0);     
        }
        else {
-        execl(ethereal_path,"ethereal","-k","-Q","-i",cf.iface,"-w",cf.save_file,
-              "-c", scount, "-s", ssnap,
-              "-m", medium_font, "-b", bold_font,
-              (cf.cfilter == NULL)? 0 : "-f", (cf.cfilter == NULL)? 0 : cf.cfilter,
-              0);
+        execlp(ethereal_path,"ethereal","-k","-Q","-i",cf.iface,"-w",cf.save_file,
+               "-c", scount, "-s", ssnap,
+               "-m", medium_font, "-b", bold_font,
+               (cf.cfilter == NULL)? 0 : "-f", (cf.cfilter == NULL)? 0 : cf.cfilter,
+               0);
        }
     }
     else {
@@ -398,35 +417,43 @@ capture_prep_close_cb(GtkWidget *close_bt, gpointer parent_w)
 
 void
 capture(void) {
-  GtkWidget  *cap_w, *main_vb, *count_lb, *tcp_lb, *udp_lb, 
-             *ospf_lb, *gre_lb, *other_lb, *stop_bt;
+  GtkWidget  *cap_w, *main_vb, *count_lb, *tcp_lb, *udp_lb, *icmp_lb,
+             *ospf_lb, *gre_lb, *netbios_lb, *other_lb, *stop_bt;
   pcap_t     *pch;
   gchar       err_str[PCAP_ERRBUF_SIZE], label_str[32];
   loop_data   ld;
   bpf_u_int32 netnum, netmask;
   time_t      upd_time, cur_time;
-  int         err;
+  int         err, inpkts;
   
-  ld.go           = TRUE;
-  ld.counts.total = 0;
-  ld.max          = cf.count;
-  ld.linktype     = DLT_NULL;
-  ld.signal_sent  = 0;
-  ld.sync_time    = 0;
-  ld.counts.tcp   = 0;
-  ld.counts.udp   = 0;
-  ld.counts.ospf  = 0;
-  ld.counts.gre   = 0;
-  ld.counts.other = 0;
-  ld.pdh          = NULL;
+  ld.go             = TRUE;
+  ld.counts.total   = 0;
+  ld.max            = cf.count;
+  ld.linktype       = DLT_NULL;
+  ld.sync_packets   = 0;
+  ld.counts.tcp     = 0;
+  ld.counts.udp     = 0;
+  ld.counts.icmp    = 0;
+  ld.counts.ospf    = 0;
+  ld.counts.gre     = 0;
+  ld.counts.netbios = 0;
+  ld.counts.other   = 0;
+  ld.pdh            = NULL;
 
   close_cap_file(&cf, info_bar, file_ctx);
 
   pch = pcap_open_live(cf.iface, cf.snap, 1, 250, err_str);
 
   if (pch) {
+    /* save the old new umask and set the new one to readable only by the user */
+    mode_t old_umask = umask(0066);
+
+    /* Have libpcap create the empty dumpfile */
     ld.pdh = pcap_dump_open(pch, cf.save_file);
 
+    /* reset the umask to the original value */
+    (void) umask(old_umask); 
+
     if (ld.pdh == NULL) {  /* We have an error */
       snprintf(err_str, PCAP_ERRBUF_SIZE, "Error trying to save capture to "
         "file:\n%s", pcap_geterr(pch));
@@ -441,16 +468,34 @@ capture(void) {
       if (pcap_lookupnet (cf.iface, &netnum, &netmask, err_str) < 0) {
         simple_dialog(ESD_TYPE_WARN, NULL,
           "Can't use filter:  Couldn't obtain netmask info.");
+        pcap_dump_close(ld.pdh);
+        unlink(cf.save_file); /* silently ignore error */
+        pcap_close(pch);
         return;
       } else if (pcap_compile(pch, &cf.fcode, cf.cfilter, 1, netmask) < 0) {
         simple_dialog(ESD_TYPE_WARN, NULL, "Unable to parse filter string.");
+        pcap_dump_close(ld.pdh);
+        unlink(cf.save_file); /* silently ignore error */
+        pcap_close(pch);
         return;
       } else if (pcap_setfilter(pch, &cf.fcode) < 0) {
         simple_dialog(ESD_TYPE_WARN, NULL, "Can't install filter.");
+        pcap_dump_close(ld.pdh);
+        unlink(cf.save_file); /* silently ignore error */
+        pcap_close(pch);
         return;
       }
     }
 
+    if (sync_mode) {
+      /* Sync out the capture file, so the header makes it to the file
+         system, and signal our parent so that they'll open the capture
+        file and update its windows to indicate that we have a live
+        capture in progress. */
+      fflush((FILE *)ld.pdh);
+      kill(getppid(), SIGUSR2);
+    }
+
     cap_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
     gtk_window_set_title(GTK_WINDOW(cap_w), "Ethereal: Capture / Playback");
 
@@ -472,6 +517,10 @@ capture(void) {
     gtk_box_pack_start(GTK_BOX(main_vb), udp_lb, FALSE, FALSE, 3);
     gtk_widget_show(udp_lb);
 
+    icmp_lb = gtk_label_new("ICMP: 0 (0.0%)");
+    gtk_box_pack_start(GTK_BOX(main_vb), icmp_lb, FALSE, FALSE, 3);
+    gtk_widget_show(icmp_lb);
+
     ospf_lb = gtk_label_new("OSPF: 0 (0.0%)");
     gtk_box_pack_start(GTK_BOX(main_vb), ospf_lb, FALSE, FALSE, 3);
     gtk_widget_show(ospf_lb);
@@ -480,6 +529,10 @@ capture(void) {
     gtk_box_pack_start(GTK_BOX(main_vb), gre_lb, FALSE, FALSE, 3);
     gtk_widget_show(gre_lb);
 
+    netbios_lb = gtk_label_new("NetBIOS: 0 (0.0%)");
+    gtk_box_pack_start(GTK_BOX(main_vb), netbios_lb, FALSE, FALSE, 3);
+    gtk_widget_show(netbios_lb);
+
     other_lb = gtk_label_new("Other: 0 (0.0%)");
     gtk_box_pack_start(GTK_BOX(main_vb), other_lb, FALSE, FALSE, 3);
     gtk_widget_show(other_lb);
@@ -500,8 +553,9 @@ capture(void) {
     upd_time = time(NULL);
     while (ld.go) {
       while (gtk_events_pending()) gtk_main_iteration();
-      pcap_dispatch(pch, 1, capture_pcap_cb, (u_char *) &ld);
-
+      inpkts = pcap_dispatch(pch, 1, capture_pcap_cb, (u_char *) &ld);
+      if (inpkts > 0)
+        ld.sync_packets += inpkts;
       /* Only update once a second so as not to overload slow displays */
       cur_time = time(NULL);
       if (cur_time > upd_time) {
@@ -519,6 +573,10 @@ capture(void) {
          pct(ld.counts.udp, ld.counts.total));
         gtk_label_set(GTK_LABEL(udp_lb), label_str);
 
+        sprintf(label_str, "ICMP: %d (%.1f%%)", ld.counts.icmp,
+         pct(ld.counts.icmp, ld.counts.total));
+        gtk_label_set(GTK_LABEL(icmp_lb), label_str);
+
         sprintf(label_str, "OSPF: %d (%.1f%%)", ld.counts.ospf,
          pct(ld.counts.ospf, ld.counts.total));
         gtk_label_set(GTK_LABEL(ospf_lb), label_str);
@@ -527,9 +585,22 @@ capture(void) {
          pct(ld.counts.gre, ld.counts.total));
         gtk_label_set(GTK_LABEL(gre_lb), label_str);
 
+        sprintf(label_str, "NetBIOS: %d (%.1f%%)", ld.counts.netbios,
+         pct(ld.counts.netbios, ld.counts.total));
+        gtk_label_set(GTK_LABEL(netbios_lb), label_str);
+
         sprintf(label_str, "Other: %d (%.1f%%)", ld.counts.other,
           pct(ld.counts.other, ld.counts.total));
         gtk_label_set(GTK_LABEL(other_lb), label_str);
+
+       /* do sync here, too */
+       fflush((FILE *)ld.pdh);
+       if (sync_mode && ld.sync_packets) {
+         char tmp[20];
+         sprintf(tmp, "%d*", ld.sync_packets);
+         write(1, tmp, strlen(tmp));
+         ld.sync_packets = 0;
+       }
       }
     }
     
@@ -551,20 +622,15 @@ capture(void) {
     gtk_exit(0);
   }
 
-  if (cf.save_file) {
-    err = load_cap_file(cf.save_file, &cf);
-    if (err != 0) {
-      simple_dialog(ESD_TYPE_WARN, NULL,
-                       file_open_error_message(err, FALSE), cf.save_file);
+  if (pch) {
+    /* "pch" is non-NULL only if we successfully started a capture.
+       If we haven't, there's no capture file to load. */
+    if ((err = open_cap_file(cf.save_file, &cf)) == 0 &&
+       (err = read_cap_file(cf.save_file, NULL, &cf)) == 0) {
+      set_menu_sensitivity("/File/Save", TRUE);
+      set_menu_sensitivity("/File/Save As...", FALSE);
     }
   }
-#ifdef USE_ITEM
-  set_menu_sensitivity("/File/Save", TRUE);
-  set_menu_sensitivity("/File/Save as", FALSE);
-#else
-  set_menu_sensitivity("<Main>/File/Save", TRUE);
-  set_menu_sensitivity("<Main>/File/Save as", FALSE);
-#endif
 }
 
 static float
@@ -588,7 +654,6 @@ capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
   const u_char *pd) {
   
   loop_data *ld = (loop_data *) user;
-  time_t *sync_time= &ld->sync_time, cur_time;
   
   if ((++ld->counts.total >= ld->max) && (ld->max > 0)) 
   {
@@ -596,16 +661,7 @@ capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
   }
   /* Currently, pcap_dumper_t is a FILE *.  Let's hope that doesn't change. */
   if (ld->pdh) pcap_dump((u_char *) ld->pdh, phdr, pd);
-  
-  cur_time = time(NULL);
-  if (cur_time > *sync_time) {
-    /* sync every seconds */
-    *sync_time = cur_time;
-    fflush((FILE *)ld->pdh);
-    if (sync_mode) 
-      write(1, "D", 1);
-  }
-
+    
   switch (ld->linktype) {
     case DLT_EN10MB :
       capture_eth(pd, phdr->caplen, &ld->counts);
@@ -626,13 +682,6 @@ capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
       capture_raw(pd, phdr->caplen, &ld->counts);
       break;
   }
-
-  if (sync_mode && !ld->signal_sent) {
-    /* will trigger the father to open the cap file which contains 
-       at least one complete packet */
-    fflush((FILE *)ld->pdh);
-    kill(getppid(), SIGUSR2);
-    ld->signal_sent = 1;
-  }
-  
 }
+
+#endif /* HAVE_LIBPCAP */