/*
- * Timeout, in milliseconds, for reads from the stream of captured packets.
+ * Timeout, in milliseconds, for reads from the stream of captured packets
+ * from a capture device.
*
* A bug in Mac OS X 10.6 and 10.6.1 causes calls to pcap_open_live(), in
* 64-bit applications, with sub-second timeouts not to work. The bug is
- * fixed in 10.6.2.
+ * fixed in 10.6.2, re-broken in 10.6.3, and again fixed in 10.6.5.
*/
#if defined(__APPLE__) && defined(__LP64__)
static gboolean need_timeout_workaround;
#endif
/*
- * Timeout, in microseconds, for threaded reads from a pipe.
+ * Timeout, in microseconds, for reads from the stream of captured packets
+ * from a pipe. Pipes don't have the same problem that BPF devices do
+ * in OS X 10.6, 10.6.1, 10.6.3, and 10.6.4, so we always use a timeout
+ * of 250ms, i.e. the same value as CAP_READ_TIMEOUT when not on one
+ * of the offending versions of Snow Leopard.
+ *
+ * On Windows this value is converted to milliseconds and passed to
+ * WaitForSingleObject. If it's less than 1000 WaitForSingleObject
+ * will return immediately.
*/
-#define THREAD_READ_TIMEOUT 100
+#ifndef USE_THREADS
+#define PIPE_READ_TIMEOUT 250000
+#else
+#define PIPE_READ_TIMEOUT 100000
+#endif
static const char *cap_pipe_err_str;
static void
/*fprintf(output, "\n");*/
fprintf(output, "Output (files):\n");
fprintf(output, " -w <filename> name of file to save (def: tempfile)\n");
+ fprintf(output, " -g enable group read access on the output file(s)\n");
fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
char *set_linktype_err_str;
if (capture_opts->linktype == -1)
- return TRUE; /* just use the default */
+ return TRUE; /* just use the default */
#ifdef HAVE_PCAP_SET_DATALINK
if (pcap_set_datalink(pcap_h, capture_opts->linktype) == 0)
return TRUE; /* no error */
return TRUE;
}
+#ifdef HAVE_BPF_IMAGE
static gboolean
show_filter_code(capture_options *capture_opts)
{
printf("%s\n", bpf_image(insn, i));
return TRUE;
}
+#endif
/*
* capture_interface_list() is expected to do the right thing to get
static int
cap_pipe_select(int pipe_fd) {
fd_set rfds;
- struct timeval timeout, *pto;
+ struct timeval timeout;
int sel_ret;
cap_pipe_err_str = "Unknown error";
FD_ZERO(&rfds);
FD_SET(pipe_fd, &rfds);
- timeout.tv_sec = 0;
- timeout.tv_usec = CAP_READ_TIMEOUT * 1000;
- pto = &timeout;
+ timeout.tv_sec = PIPE_READ_TIMEOUT / 1000000;
+ timeout.tv_usec = PIPE_READ_TIMEOUT % 1000000;
- sel_ret = select(pipe_fd+1, &rfds, NULL, NULL, pto);
+ sel_ret = select(pipe_fd+1, &rfds, NULL, NULL, &timeout);
if (sel_ret < 0)
cap_pipe_err_str = strerror(errno);
return sel_ret;
ld->cap_pipe_bytes_read += b;
#else /* USE_THREADS */
g_get_current_time(&wait_time);
- g_time_val_add(&wait_time, THREAD_READ_TIMEOUT);
+ g_time_val_add(&wait_time, PIPE_READ_TIMEOUT);
q_status = g_async_queue_timed_pop(cap_pipe_done_q, &wait_time);
if (ld->cap_pipe_err == PIPEOF) {
result = PD_PIPE_EOF;
ld->cap_pipe_bytes_read += b;
#else /* USE_THREADS */
g_get_current_time(&wait_time);
- g_time_val_add(&wait_time, THREAD_READ_TIMEOUT);
+ g_time_val_add(&wait_time, PIPE_READ_TIMEOUT);
q_status = g_async_queue_timed_pop(cap_pipe_done_q, &wait_time);
if (ld->cap_pipe_err == PIPEOF) {
result = PD_PIPE_EOF;
return ld->packet_count - packet_count_before;
}
+#ifdef _WIN32
+/* Isolate the Universally Unique Identifier from the interface. Basically, we
+ * want to grab only the characters between the '{' and '}' delimiters.
+ *
+ * Returns a GString that must be freed with g_string_free(). */
+static GString *isolate_uuid(const char *iface)
+{
+ gchar *ptr;
+ GString *gstr;
+
+ ptr = strchr(iface, '{');
+ if (ptr == NULL)
+ return g_string_new(iface);
+ gstr = g_string_new(ptr + 1);
+
+ ptr = strchr(gstr->str, '}');
+ if (ptr == NULL)
+ return gstr;
+
+ gstr = g_string_truncate(gstr, ptr - gstr->str);
+ return gstr;
+}
+#endif
/* open the output file (temporary/specified name/ringbuffer/named pipe/stdout) */
/* Returns TRUE if the file opened successfully, FALSE otherwise. */
char *tmpname;
gchar *capfile_name;
+ gchar *prefix;
gboolean is_tempfile;
#ifndef _WIN32
int ret;
if (capture_opts->multi_files_on) {
/* ringbuffer is enabled */
*save_file_fd = ringbuf_init(capfile_name,
- (capture_opts->has_ring_num_files) ? capture_opts->ring_num_files : 0);
+ (capture_opts->has_ring_num_files) ? capture_opts->ring_num_files : 0,
+ capture_opts->group_read_access);
/* we need the ringbuf name */
if(*save_file_fd != -1) {
} else {
/* Try to open/create the specified file for use as a capture buffer. */
*save_file_fd = ws_open(capfile_name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT,
- 0600);
+ (capture_opts->group_read_access) ? 0640 : 0600);
}
}
is_tempfile = FALSE;
} else {
/* Choose a random name for the temporary capture buffer */
- *save_file_fd = create_tempfile(&tmpname, "wireshark");
+#ifdef _WIN32
+ GString *iface;
+
+ iface = isolate_uuid(capture_opts->iface);
+ prefix = g_strconcat("wireshark_", g_basename(iface->str), NULL);
+ g_string_free(iface, TRUE);
+#else
+ prefix = g_strconcat("wireshark_", g_basename(capture_opts->iface), NULL);
+#endif
+ *save_file_fd = create_tempfile(&tmpname, prefix);
+ g_free(prefix);
capfile_name = g_strdup(tmpname);
is_tempfile = TRUE;
}
if (ringbuf_switch_file(&global_ld.pdh, &capture_opts->save_file,
&global_ld.save_file_fd, &global_ld.err)) {
gboolean successful;
+#ifndef _WIN32
+ int ret;
+#endif
/* File switch succeeded: reset the conditions */
global_ld.bytes_written = 0;
report_packet_count(global_ld.inpkts_to_sync_pipe);
global_ld.inpkts_to_sync_pipe = 0;
report_new_capture_file(capture_opts->save_file);
+
+#ifndef _WIN32
+ ret = fchown(global_ld.save_file_fd, capture_opts->owner, capture_opts->group);
+#endif
} else {
/* File switch failed: stop here */
global_ld.go = FALSE;
cap_err_str = pcap_geterr(global_ld.pcap_h);
if (strcmp(cap_err_str, "recvfrom: Network is down") == 0 ||
strcmp(cap_err_str, "read: Device not configured") == 0 ||
- strcmp(cap_err_str, "read: I/O error") == 0) {
+ strcmp(cap_err_str, "read: I/O error") == 0 ||
+ strcmp(cap_err_str, "read error: PacketReceivePacket failed") == 0) {
report_capture_error("The network adapter on which the capture was being done "
"is no longer running; the capture has stopped.",
"");
struct utsname osinfo;
#endif
+#ifdef _WIN32
+ /*
+ * Initialize our DLL search path. MUST be called before LoadLibrary
+ * or g_module_open.
+ */
+ ws_init_dll_search_path();
+#endif
+
#ifdef HAVE_PCAP_REMOTE
#define OPTSTRING_A "A:"
#define OPTSTRING_r "r"
#define OPTSTRING_d ""
#endif
-#define OPTSTRING "a:" OPTSTRING_A "b:" OPTSTRING_B "c:" OPTSTRING_d "Df:hi:" OPTSTRING_I "L" OPTSTRING_m "Mnpq" OPTSTRING_r "Ss:" OPTSTRING_u "vw:y:Z:"
+#define OPTSTRING "a:" OPTSTRING_A "b:" OPTSTRING_B "c:" OPTSTRING_d "Df:ghi:" OPTSTRING_I "L" OPTSTRING_m "Mnpq" OPTSTRING_r "Ss:" OPTSTRING_u "vw:y:Z:"
#ifdef DEBUG_CHILD_DUMPCAP
if ((debug_log = ws_fopen("dumpcap_debug_log.tmp","w")) == NULL) {
#if defined(__APPLE__) && defined(__LP64__)
/*
- * Is this Mac OS X 10.6.x, other than 10.6.2? If so, we need a bug
- * workaround - timeouts less than 1 second don't work with libpcap
+ * Is this Mac OS X 10.6.0, 10.6.1, 10.6.3, or 10.6.4? If so, we need
+ * a bug workaround - timeouts less than 1 second don't work with libpcap
* in 64-bit code. (The bug was introduced in 10.6, fixed in 10.6.2,
- * and re-introduced in 10.6.3. We don't know whether it'll be fixed
- * again in a later 10.6.x release; we'll assume that it'll be fixed
- * in any future major releases.)
+ * re-introduced in 10.6.3, not fixed in 10.6.4, and fixed in 10.6.5.
+ * The problem is extremely unlikely to be reintroduced in a future
+ * release.)
*/
if (uname(&osinfo) == 0) {
/*
* {x+4}.y.0 (except that 10.6.1 appears to have a uname version
* number of 10.0.0, not 10.1.0 - go figure).
*/
- if (strncmp(osinfo.release, "10.", 3) == 0) {
- /*
- * OK, it's Snow Leopard - which version?
- */
- if (strcmp(osinfo.release, "10.2.0") != 0) {
- /* Not 10.6.2. */
- need_timeout_workaround = TRUE;
- }
- }
+ if (strcmp(osinfo.release, "10.0.0") == 0 || /* 10.6, 10.6.1 */
+ strcmp(osinfo.release, "10.3.0") == 0 || /* 10.6.3 */
+ strcmp(osinfo.release, "10.4.0") == 0) /* 10.6.4 */
+ need_timeout_workaround = TRUE;
}
#endif
/* */
/* ----------------------------------------------------------------- */
- get_credential_info();
+ init_process_policies();
#ifdef HAVE_LIBCAP
/* If 'started with special privileges' (and using libcap) */
GString *runtime_info_str;
/* Assemble the compile-time version information string */
comp_info_str = g_string_new("Compiled ");
- get_compiled_version_info(comp_info_str, NULL);
+ get_compiled_version_info(comp_info_str, NULL, NULL);
/* Assemble the run-time version information string */
runtime_info_str = g_string_new("Running ");
case 'p': /* Don't capture in promiscuous mode */
case 's': /* Set the snapshot (capture) length */
case 'w': /* Write to capture file x */
+ case 'g': /* enable group read accesson file(s) */
case 'y': /* Set the pcap data link type */
#ifdef HAVE_PCAP_REMOTE
case 'u': /* Use UDP for data transfer */