Have "cf_merge_files()" always close "out_fd" before returning; it does
[obnox/wireshark/wip.git] / capture_loop.c
index b086dda127c9e9cc5e062caef93a2e933a4f01e3..d4ca37b7aab61563dc7f7a010ee85f383b0f20a6 100644 (file)
@@ -72,7 +72,6 @@
 #include "pcap-util.h"
 
 #include "simple_dialog.h"
-#include "globals.h"
 #include "conditions.h"
 #include "capture_stop_conditions.h"
 #include "ringbuffer.h"
@@ -179,8 +178,9 @@ typedef struct _loop_data {
 
 static void capture_loop_packet_cb(guchar *user, const struct pcap_pkthdr *phdr,
   const guchar *pd);
-static void capture_loop_popup_errmsg(const char *);
-static void capture_loop_get_errmsg(char *, int, const char *, int, gboolean);
+static void capture_loop_popup_errmsg(capture_options *capture_opts, const char *errmsg);
+static void capture_loop_get_errmsg(char *errmsg, int errmsglen, const char *fname,
+                         int err, gboolean is_close);
 
 
 
@@ -558,14 +558,14 @@ static int capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
      if they succeed; to tell if that's happened, we have to clear
      the error buffer, and check if it's still a null string.  */
   open_err_str[0] = '\0';
-  ld->pcap_h = pcap_open_live(cfile.iface,
+  ld->pcap_h = pcap_open_live(capture_opts->iface,
                       capture_opts->has_snaplen ? capture_opts->snaplen :
                                                  WTAP_MAX_PACKET_SIZE,
                       capture_opts->promisc_mode, CAP_READ_TIMEOUT,
                       open_err_str);
 
   if (ld->pcap_h != NULL) {
-    /* we've opened "cfile.iface" as a network device */
+    /* we've opened "iface" as a network device */
 #ifdef _WIN32
     /* try to set the capture buffer size */
     if (pcap_setbuff(ld->pcap_h, capture_opts->buffer_size * 1024 * 1024) != 0) {
@@ -582,7 +582,7 @@ static int capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
 
     /* setting the data link type only works on real interfaces */
     if (capture_opts->linktype != -1) {
-      set_linktype_err_str = set_pcap_linktype(ld->pcap_h, cfile.iface,
+      set_linktype_err_str = set_pcap_linktype(ld->pcap_h, capture_opts->iface,
        capture_opts->linktype);
       if (set_linktype_err_str != NULL) {
        g_snprintf(errmsg, errmsg_len, "Unable to set data link type (%s).",
@@ -591,14 +591,14 @@ static int capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
       }
     }
   } else {
-    /* We couldn't open "cfile.iface" as a network device. */
+    /* We couldn't open "iface" as a network device. */
 #ifdef _WIN32
     /* On Windows, we don't support capturing on pipes, so we give up.
        If this is a child process that does the capturing in sync
        mode or fork mode, it shouldn't do any UI stuff until we pop up the
        capture-progress window, and, since we couldn't start the
        capture, we haven't popped it up. */
-    if (!capture_child) {
+    if (!capture_opts->capture_child) {
       main_window_update();
     }
 
@@ -607,18 +607,22 @@ static int capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
 
        Do, however, warn that WAN devices aren't supported. */
     g_snprintf(errmsg, errmsg_len,
-       "The capture session could not be initiated (%s).\n"
-       "Please check that you have the proper interface specified.\n"
-       "\n"
-       "Note that the WinPcap 2.x version of the driver Ethereal uses for packet\n"
-       "capture on Windows doesn't support capturing on PPP/WAN interfaces in\n"
-       "Windows NT/2000/XP/2003 Server, and that the WinPcap 3.0 and later versions\n"
-       "don't support capturing on PPP/WAN interfaces at all.",
+"The capture session could not be initiated (%s).\n"
+"Please check that you have the proper interface specified.\n"
+"\n"
+"Note that version 3.0 of WinPcap, and earlier versions of WinPcap, don't\n"
+"support capturing on PPP/WAN interfaces in Windows NT 4.0, Windows 2000,\n"
+"Windows XP, or Windows Server 2003.  WinPcap 3.1 has experimental support\n"
+"for it on Windows 2000, Windows XP, and Windows Server 2003, but has no\n"
+"support for it on Windows NT 4.0.  WinPcap 3.1 is currently in beta, so\n"
+"using it might introduce bugs not present in WinPcap 3.0; you should report\n"
+"all problems you see to the WinPcap developers, so they can try to fix\n"
+"them before the final WinPcap 3.1 release.",
        open_err_str);
     return FALSE;
 #else
-    /* try to open cfile.iface as a pipe */
-    ld->cap_pipe_fd = cap_pipe_open_live(cfile.iface, &ld->cap_pipe_hdr, ld, errmsg, errmsg_len);
+    /* try to open iface as a pipe */
+    ld->cap_pipe_fd = cap_pipe_open_live(capture_opts->iface, &ld->cap_pipe_hdr, ld, errmsg, errmsg_len);
 
     if (ld->cap_pipe_fd == -1) {
 
@@ -627,7 +631,7 @@ static int capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
        * capture-progress window, and, since we couldn't start the
        * capture, we haven't popped it up.
        */
-      if (!capture_child) {
+      if (!capture_opts->capture_child) {
           main_window_update();
       }
 
@@ -653,7 +657,7 @@ static int capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
            "at the URL lists a number of mirror sites.";
        else
          libpcap_warn = "";
-       g_snprintf(errmsg, sizeof errmsg,
+       g_snprintf(errmsg, errmsg_len,
          "The capture session could not be initiated (%s).\n"
          "Please check to make sure you have sufficient permissions, and that\n"
          "you have the proper interface or pipe specified.%s", open_err_str,
@@ -708,15 +712,15 @@ static void capture_loop_close_input(loop_data *ld) {
 
 
 /* init the capture filter */
-static int capture_loop_init_filter(loop_data *ld, char *errmsg, int errmsg_len) {
+static int capture_loop_init_filter(loop_data *ld, const gchar * iface, gchar * cfilter, char *errmsg, int errmsg_len) {
   bpf_u_int32 netnum, netmask;
   gchar       lookup_net_err_str[PCAP_ERRBUF_SIZE];
   struct bpf_program fcode;
 
   /* capture filters only work on real interfaces */
-  if (cfile.cfilter && !ld->from_cap_pipe) {
+  if (cfilter && !ld->from_cap_pipe) {
     /* A capture filter was specified; set it up. */
-    if (pcap_lookupnet(cfile.iface, &netnum, &netmask, lookup_net_err_str) < 0) {
+    if (pcap_lookupnet(iface, &netnum, &netmask, lookup_net_err_str) < 0) {
       /*
        * Well, we can't get the netmask for this interface; it's used
        * only for filters that check for broadcast IP addresses, so
@@ -728,10 +732,10 @@ static int capture_loop_init_filter(loop_data *ld, char *errmsg, int errmsg_len)
        */
       netmask = 0;
     }
-    if (pcap_compile(ld->pcap_h, &fcode, cfile.cfilter, 1, netmask) < 0) {
+    if (pcap_compile(ld->pcap_h, &fcode, cfilter, 1, netmask) < 0) {
       dfilter_t   *rfcode = NULL;
       /* filter string invalid, did the user tried a display filter? */
-      if (dfilter_compile(cfile.cfilter, &rfcode) && rfcode != NULL) {
+      if (dfilter_compile(cfilter, &rfcode) && rfcode != NULL) {
         g_snprintf(errmsg, errmsg_len,
           "%sInvalid capture filter: \"%s\"!%s\n"
           "\n"
@@ -742,7 +746,7 @@ static int capture_loop_init_filter(loop_data *ld, char *errmsg, int errmsg_len)
           "so you can't use most display filter expressions as capture filters.\n"
           "\n"
           "See the help for a description of the capture filter syntax.",
-          simple_dialog_primary_start(), cfile.cfilter, simple_dialog_primary_end(),
+          simple_dialog_primary_start(), cfilter, simple_dialog_primary_end(),
           pcap_geterr(ld->pcap_h));
        dfilter_free(rfcode);
       } else {
@@ -751,7 +755,7 @@ static int capture_loop_init_filter(loop_data *ld, char *errmsg, int errmsg_len)
           "\n"
           "That string isn't a valid capture filter (%s).\n"
           "See the help for a description of the capture filter syntax.",
-          simple_dialog_primary_start(), cfile.cfilter, simple_dialog_primary_end(),
+          simple_dialog_primary_start(), cfilter, simple_dialog_primary_end(),
           pcap_geterr(ld->pcap_h));
       }
       return FALSE;
@@ -782,7 +786,7 @@ static int capture_loop_open_wiretap_output(capture_options *capture_opts, loop_
   } else
 #endif
   {
-    pcap_encap = get_pcap_linktype(ld->pcap_h, cfile.iface);
+    pcap_encap = get_pcap_linktype(ld->pcap_h, capture_opts->iface);
     file_snaplen = pcap_snapshot(ld->pcap_h);
   }
 
@@ -798,7 +802,7 @@ static int capture_loop_open_wiretap_output(capture_options *capture_opts, loop_
     ld->wtap_pdh = ringbuf_init_wtap_dump_fdopen(WTAP_FILE_PCAP, ld->wtap_linktype,
       file_snaplen, &err);
   } else {
-    ld->wtap_pdh = wtap_dump_fdopen(cfile.save_file_fd, WTAP_FILE_PCAP,
+    ld->wtap_pdh = wtap_dump_fdopen(capture_opts->save_file_fd, WTAP_FILE_PCAP,
       ld->wtap_linktype, file_snaplen, &err);
   }
 
@@ -821,12 +825,12 @@ static int capture_loop_open_wiretap_output(capture_options *capture_opts, loop_
         g_snprintf(errmsg, errmsg_len,
                     "The file to which the capture would be"
                      " saved (\"%s\") could not be opened: Error %d.",
-                       cfile.save_file, err);
+                       capture_opts->save_file, err);
       } else {
         g_snprintf(errmsg, errmsg_len,
                     "The file to which the capture would be"
                      " saved (\"%s\") could not be opened: %s.",
-                       cfile.save_file, strerror(err));
+                       capture_opts->save_file, strerror(err));
       }
       break;
     }
@@ -839,7 +843,7 @@ static int capture_loop_open_wiretap_output(capture_options *capture_opts, loop_
 
 static gboolean capture_loop_close_output(capture_options *capture_opts, loop_data *ld, int *err_close) {
   if (capture_opts->multi_files_on) {
-    return ringbuf_wtap_dump_close(&cfile, err_close);
+    return ringbuf_wtap_dump_close(&capture_opts->save_file, err_close);
   } else {
     return wtap_dump_close(ld->wtap_pdh, err_close);
   }
@@ -847,7 +851,8 @@ static gboolean capture_loop_close_output(capture_options *capture_opts, loop_da
 
 /* dispatch incoming packets (pcap or capture pipe) */
 static int
-capture_loop_dispatch(loop_data *ld, char *errmsg, int errmsg_len) {
+capture_loop_dispatch(capture_options *capture_opts, loop_data *ld,
+                     char *errmsg, int errmsg_len) {
   int       inpkts;
 #ifndef _WIN32
   fd_set    set1;
@@ -857,7 +862,6 @@ capture_loop_dispatch(loop_data *ld, char *errmsg, int errmsg_len) {
   guchar pcap_data[WTAP_MAX_PACKET_SIZE];
 #endif
 
-
 #ifndef _WIN32
     /* dispatch from capture pipe */
     if (ld->from_cap_pipe) {
@@ -871,7 +875,7 @@ capture_loop_dispatch(loop_data *ld, char *errmsg, int errmsg_len) {
         if (sel_ret < 0 && errno != EINTR) {
           g_snprintf(errmsg, errmsg_len,
             "Unexpected error from select: %s", strerror(errno));
-          capture_loop_popup_errmsg(errmsg);
+          capture_loop_popup_errmsg(capture_opts, errmsg);
           ld->go = FALSE;
         }
       } else {
@@ -937,7 +941,7 @@ capture_loop_dispatch(loop_data *ld, char *errmsg, int errmsg_len) {
         if (sel_ret < 0 && errno != EINTR) {
           g_snprintf(errmsg, errmsg_len,
             "Unexpected error from select: %s", strerror(errno));
-          capture_loop_popup_errmsg(errmsg);
+          capture_loop_popup_errmsg(capture_opts, errmsg);
           ld->go = FALSE;
         }
       }
@@ -1023,7 +1027,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
   }
 
   /* init the input filter from the network interface (capture pipe will do nothing) */
-  if (!capture_loop_init_filter(&ld, errmsg, sizeof(errmsg))) {
+  if (!capture_loop_init_filter(&ld, capture_opts->iface, capture_opts->cfilter, errmsg, sizeof(errmsg))) {
     goto error;
   }
 
@@ -1038,7 +1042,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
      in other places as well - and I don't think that works all the
      time in any case, due to libpcap bugs. */
 
-  if (capture_child) {
+  if (capture_opts->capture_child) {
     /* Well, we should be able to start capturing.
 
        This is the child process for a sync mode capture, so sync out
@@ -1075,7 +1079,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
   if(show_info) {
       capture_ui.callback_data  = &ld;
       capture_ui.counts         = &ld.counts;
-      capture_info_create(&capture_ui, cfile.iface);
+      capture_info_create(&capture_ui, capture_opts->iface);
   }
 
   /* init the time values */
@@ -1088,7 +1092,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
     main_window_update();
 
     /* dispatch incoming packets */
-    inpkts = capture_loop_dispatch(&ld, errmsg, sizeof(errmsg));
+    inpkts = capture_loop_dispatch(capture_opts, &ld, errmsg, sizeof(errmsg));
 
     if (inpkts > 0) {
       ld.packets_sync_pipe += inpkts;
@@ -1105,7 +1109,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
           }
 
           /* Switch to the next ringbuffer file */
-          if (ringbuf_switch_file(&cfile, &ld.wtap_pdh, &ld.err)) {
+          if (ringbuf_switch_file(&ld.wtap_pdh, &capture_opts->save_file, &capture_opts->save_file_fd, &ld.err)) {
             /* File switch succeeded: reset the conditions */
             cnd_reset(cnd_autostop_size);
             if (cnd_file_duration) {
@@ -1146,7 +1150,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
         /* do sync here */
         fflush(wtap_dump_file(ld.wtap_pdh));
 
-        if (capture_child) {
+        if (capture_opts->capture_child) {
          /* This is the child process for a sync mode capture, so send
             our parent a message saying we've written out "ld.sync_packets"
             packets to the capture file. */
@@ -1174,7 +1178,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
           }
 
           /* Switch to the next ringbuffer file */
-          if (ringbuf_switch_file(&cfile, &ld.wtap_pdh, &ld.err)) {
+          if (ringbuf_switch_file(&ld.wtap_pdh, &capture_opts->save_file, &capture_opts->save_file_fd, &ld.err)) {
             /* file switch succeeded: reset the conditions */
             cnd_reset(cnd_file_duration);
             if(cnd_autostop_size)
@@ -1213,20 +1217,20 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
   if (ld.pcap_err) {
     g_snprintf(errmsg, sizeof(errmsg), "Error while capturing packets: %s",
       pcap_geterr(ld.pcap_h));
-    capture_loop_popup_errmsg(errmsg);
+    capture_loop_popup_errmsg(capture_opts, errmsg);
   }
 #ifndef _WIN32
     else if (ld.from_cap_pipe && ld.cap_pipe_err == PIPERR)
-      capture_loop_popup_errmsg(errmsg);
+      capture_loop_popup_errmsg(capture_opts, errmsg);
 #endif
 
   /* did we had an error while capturing? */
   if (ld.err == 0) {
     write_ok = TRUE;
   } else {
-    capture_loop_get_errmsg(errmsg, sizeof(errmsg), cfile.save_file, ld.err,
+    capture_loop_get_errmsg(errmsg, sizeof(errmsg), capture_opts->save_file, ld.err,
                              FALSE);
-    capture_loop_popup_errmsg(errmsg);
+    capture_loop_popup_errmsg(capture_opts, errmsg);
     write_ok = FALSE;
   }
 
@@ -1236,9 +1240,9 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
   /* If we've displayed a message about a write error, there's no point
      in displaying another message about an error on close. */
   if (!close_ok && write_ok) {
-    capture_loop_get_errmsg(errmsg, sizeof(errmsg), cfile.save_file, err_close,
+    capture_loop_get_errmsg(errmsg, sizeof(errmsg), capture_opts->save_file, err_close,
                TRUE);
-    capture_loop_popup_errmsg(errmsg);
+    capture_loop_popup_errmsg(capture_opts, errmsg);
   }
 
   /*
@@ -1257,7 +1261,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
        dropped. */
     if (pcap_stats(ld.pcap_h, stats) >= 0) {
       *stats_known = TRUE;
-      if (capture_child) {
+      if (capture_opts->capture_child) {
        /* Let the parent process know. */
         sync_pipe_drops_to_parent(stats->ps_drop);
       }
@@ -1265,7 +1269,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
       g_snprintf(errmsg, sizeof(errmsg),
                "Can't get packet-drop statistics: %s",
                pcap_geterr(ld.pcap_h));
-      capture_loop_popup_errmsg(errmsg);
+      capture_loop_popup_errmsg(capture_opts, errmsg);
     }
   }
 
@@ -1282,15 +1286,15 @@ error:
   } 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);
+    close(capture_opts->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);
+    unlink(capture_opts->save_file); /* silently ignore error */
+    g_free(capture_opts->save_file);
   }
-  cfile.save_file = NULL;
-  capture_loop_popup_errmsg(errmsg);
+  capture_opts->save_file = NULL;
+  capture_loop_popup_errmsg(capture_opts, errmsg);
 
   /* close the input file (pcap or cap_pipe) */
   capture_loop_close_input(&ld);
@@ -1364,9 +1368,9 @@ capture_loop_get_errmsg(char *errmsg, int errmsglen, const char *fname,
 }
 
 static void
-capture_loop_popup_errmsg(const char *errmsg)
+capture_loop_popup_errmsg(capture_options *capture_opts, const char *errmsg)
 {
-  if (capture_child) {
+  if (capture_opts->capture_child) {
     /* This is the child process for a sync mode capture.
        Send the error message to our parent, so they can display a
        dialog box containing it. */
@@ -1389,7 +1393,8 @@ capture_loop_packet_cb(guchar *user, const struct pcap_pkthdr *phdr,
   int err;
 
   /* if the user told us to stop after x packets, do we have enough? */
-  if ((ld->packets_max > 0) && (++ld->counts.total >= ld->packets_max))
+  ld->counts.total++;
+  if ((ld->packets_max > 0) && (ld->counts.total >= ld->packets_max))
   {
      ld->go = FALSE;
   }