/* capture.c
* Routines for packet capture windows
*
- * $Id: capture.c,v 1.148 2001/04/13 14:59:28 jfoster Exp $
+ * $Id: capture.c,v 1.172 2002/04/08 09:09:47 guy Exp $
*
* Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
- *
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
#include "gtk/main.h"
#include "gtk/gtkglobals.h"
-#include "packet.h"
+#include <epan/packet.h>
#include "file.h"
#include "capture.h"
#include "util.h"
+#include "pcap-util.h"
#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"
#include "packet-tr.h"
#include "packet-ieee80211.h"
#include "packet-chdlc.h"
+#include "packet-prism.h"
+
+#ifdef WIN32
+#include "capture-wpcap.h"
+#endif
+
+/*
+ * Capture options.
+ */
+capture_options capture_opts;
static int sync_pipe[2]; /* used to sync father */
enum PIPES { READ, WRITE }; /* Constants 0 and 1 for READ and WRITE */
int quit_after_cap; /* Makes a "capture only mode". Implies -k */
gboolean capture_child; /* if this is the child for "-S" */
-static int fork_child; /* In parent, process ID of child */
+static int fork_child = -1; /* If not -1, in parent, process ID of child */
static guint cap_input_id;
/*
* Indications sent out on the sync pipe.
*/
#define SP_CAPSTART ';' /* capture start message */
-#define SP_PACKET_COUNT '*' /* count of packets captured since last message */
-#define SP_ERROR_MSG '!' /* length of error message that follows */
-#define SP_DROPS '#' /* count of packets dropped in capture */
+#define SP_PACKET_COUNT '*' /* followed by count of packets captured since last message */
+#define SP_ERROR_MSG '!' /* followed by length of error message that follows */
+#define SP_DROPS '#' /* followed by count of packets dropped in capture */
#ifdef _WIN32
static guint cap_timer_id;
static void stop_capture(int signo);
typedef struct _loop_data {
- gint go; /* TRUE as long as we're supposed to keep capturing */
+ gboolean go; /* TRUE as long as we're supposed to keep capturing */
gint max; /* Number of packets we're supposed to capture - 0 means infinite */
int err; /* if non-zero, error seen while capturing */
gint linktype;
gint sync_packets;
+ gboolean pcap_err; /* TRUE if error from pcap */
gboolean from_pipe; /* TRUE if we are capturing data from a pipe */
gboolean modified; /* TRUE if data in the pipe uses modified pcap headers */
gboolean byte_swapped; /* TRUE if data in the pipe is byte swapped */
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 (capture_opts.ringbuffer_on) {
+ /* ringbuffer is enabled */
+ cfile.save_file_fd = ringbuf_init(capfile_name,
+ capture_opts.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 */
"The temporary file to which the capture would be saved (\"%s\")"
"could not be opened: %s.", capfile_name, strerror(errno));
} else {
+ if (capture_opts.ringbuffer_on) {
+ ringbuf_error_cleanup();
+ }
simple_dialog(ESD_TYPE_CRIT, NULL,
file_open_error_message(errno, TRUE), capfile_name);
}
return;
}
- close_cap_file(&cfile, info_bar);
+ close_cap_file(&cfile);
g_assert(cfile.save_file == NULL);
cfile.save_file = capfile_name;
- if (prefs.capture_auto_scroll) { /* do the capture in a child process */
+ if (capture_opts.sync_mode) { /* 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;
sprintf(save_file_fd,"%d",cfile.save_file_fd); /* in lieu of itoa */
argv = add_arg(argv, &argc, save_file_fd);
- argv = add_arg(argv, &argc, "-c");
- sprintf(scount,"%d",cfile.count);
- argv = add_arg(argv, &argc, scount);
+ if (capture_opts.has_autostop_count) {
+ argv = add_arg(argv, &argc, "-c");
+ sprintf(scount,"%d",capture_opts.autostop_count);
+ argv = add_arg(argv, &argc, scount);
+ }
+
+ if (capture_opts.has_snaplen) {
+ argv = add_arg(argv, &argc, "-s");
+ sprintf(ssnap,"%d",capture_opts.snaplen);
+ argv = add_arg(argv, &argc, ssnap);
+ }
+
+ if (capture_opts.has_autostop_filesize) {
+ argv = add_arg(argv, &argc, "-a");
+ sprintf(sautostop_filesize,"filesize:%d",capture_opts.autostop_filesize);
+ argv = add_arg(argv, &argc, sautostop_filesize);
+ }
- argv = add_arg(argv, &argc, "-s");
- sprintf(ssnap,"%d",cfile.snap);
- argv = add_arg(argv, &argc, ssnap);
+ if (capture_opts.has_autostop_duration) {
+ argv = add_arg(argv, &argc, "-a");
+ sprintf(sautostop_duration,"duration:%d",capture_opts.autostop_duration);
+ argv = add_arg(argv, &argc, sautostop_duration);
+ }
- if (!prefs.capture_prom_mode)
+ if (!capture_opts.promisc_mode)
argv = add_arg(argv, &argc, "-p");
#ifdef _WIN32
} else {
/* Failure - the child process sent us a message indicating
what the problem was. */
- msg = g_malloc(byte_count + 1);
- if (msg == NULL) {
- simple_dialog(ESD_TYPE_WARN, NULL,
- "Capture child process failed, but its error message was too big.");
- } else if (byte_count == 0) {
- /* Zero-length message? */
+ if (byte_count == 0) {
+ /* Zero-length message? */
simple_dialog(ESD_TYPE_WARN, NULL,
"Capture child process failed, but its error message was empty.");
} else {
- i = read(sync_pipe[READ], msg, byte_count);
- if (i < 0) {
+ msg = g_malloc(byte_count + 1);
+ if (msg == NULL) {
simple_dialog(ESD_TYPE_WARN, NULL,
+ "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, NULL,
"Capture child process failed: Error %s reading its error message.",
strerror(errno));
- } else if (i == 0) {
- simple_dialog(ESD_TYPE_WARN, NULL,
+ } else if (i == 0) {
+ simple_dialog(ESD_TYPE_WARN, NULL,
"Capture child process failed: EOF reading its error message.");
- wait_for_child(FALSE);
- } else
- simple_dialog(ESD_TYPE_WARN, NULL, msg);
- g_free(msg);
+ wait_for_child(FALSE);
+ } else
+ simple_dialog(ESD_TYPE_WARN, NULL, msg);
+ g_free(msg);
+ }
/* Close the sync pipe. */
close(sync_pipe[READ]);
}
/* We're not doing a capture any more, so we don't have a save
file. */
- g_free(cfile.save_file);
+ if (capture_opts.ringbuffer_on) {
+ ringbuf_free();
+ } else {
+ g_free(cfile.save_file);
+ }
cfile.save_file = NULL;
}
}
"Child capture process died: wait status %#o", wstatus);
}
}
+
+ /* No more child process. */
+ fork_child = -1;
#endif
}
/*
* Timeout, in milliseconds, for reads from the stream of captured packets.
+ *
+ * XXX - Michael Tuexen says MacOS X's BPF appears to be broken, in that
+ * if you use a timeout of 250 in "pcap_open_live()", you don't see
+ * packets until a large number of packets arrive; the timeout doesn't
+ * cause a smaller number of packets to be delivered. Perhaps a timeout
+ * that's less than 1 second acts like no timeout at all, so that you
+ * don't see packets until the BPF buffer fills up?
+ *
+ * The workaround is to use a timeout of 1000 seconds on MacOS X.
*/
+#ifdef __APPLE__
+#define CAP_READ_TIMEOUT 1000
+#else
#define CAP_READ_TIMEOUT 250
+#endif
#ifndef _WIN32
/* Take carre of byte order in the libpcap headers read from pipes.
close(fd);
return -1;
}
- while (bytes_read < sizeof(struct pcap_hdr))
+ while ((unsigned) bytes_read < sizeof(struct pcap_hdr))
{
b = read(fd, ((char *)&hdr)+bytes_read, sizeof(struct pcap_hdr) - bytes_read);
if (b <= 0) {
ld->go = FALSE;
return 0;
}
- while (bytes_read < rechdr.hdr.incl_len)
+ while ((unsigned) bytes_read < rechdr.hdr.incl_len)
{
b = read(fd, pd+bytes_read, rechdr.hdr.incl_len - bytes_read);
if (b <= 0) {
whdr.pkt_encap = ld->linktype;
wtap_dump(ld->pdh, &whdr, NULL, pd, &err);
- /* Set the initial payload to the packet length, and the initial
- captured payload to the capture length (other protocols may
- reduce them if their headers say they're less). */
- pi.len = whdr.len;
- pi.captured_len = whdr.caplen;
-
/* update capture statistics */
switch (ld->linktype) {
case WTAP_ENCAP_ETHERNET:
- capture_eth(pd, 0, &ld->counts);
+ capture_eth(pd, 0, whdr.caplen, &ld->counts);
break;
case WTAP_ENCAP_FDDI:
case WTAP_ENCAP_FDDI_BITSWAPPED:
- capture_fddi(pd, &ld->counts);
+ capture_fddi(pd, whdr.caplen, &ld->counts);
+ break;
+ case WTAP_ENCAP_PRISM_HEADER:
+ capture_prism(pd, 0, whdr.caplen, &ld->counts);
break;
case WTAP_ENCAP_TOKEN_RING:
- capture_tr(pd, 0, &ld->counts);
+ capture_tr(pd, 0, whdr.caplen, &ld->counts);
break;
case WTAP_ENCAP_NULL:
- capture_null(pd, &ld->counts);
+ capture_null(pd, whdr.caplen, &ld->counts);
break;
case WTAP_ENCAP_PPP:
- capture_ppp_hdlc(pd, 0, &ld->counts);
+ capture_ppp_hdlc(pd, 0, whdr.caplen, &ld->counts);
break;
case WTAP_ENCAP_RAW_IP:
- capture_raw(pd, &ld->counts);
+ capture_raw(pd, whdr.caplen, &ld->counts);
break;
case WTAP_ENCAP_LINUX_ATM_CLIP:
- capture_clip(pd, &ld->counts);
+ capture_clip(pd, whdr.caplen, &ld->counts);
break;
case WTAP_ENCAP_IEEE_802_11:
- capture_ieee80211(pd, 0, &ld->counts);
+ case WTAP_ENCAP_IEEE_802_11_WITH_RADIO:
+ capture_ieee80211(pd, 0, whdr.caplen, &ld->counts);
break;
case WTAP_ENCAP_CHDLC:
- capture_chdlc(pd, 0, &ld->counts);
+ 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
GtkWidget *cap_w, *main_vb, *stop_bt, *counts_tb;
pcap_t *pch;
int pcap_encap;
- int snaplen;
- gchar err_str[PCAP_ERRBUF_SIZE], label_str[64];
+ int file_snaplen;
+ gchar open_err_str[PCAP_ERRBUF_SIZE];
+ gchar lookup_net_err_str[PCAP_ERRBUF_SIZE];
+ gchar label_str[64];
bpf_u_int32 netnum, netmask;
struct bpf_program fcode;
time_t upd_time, cur_time;
- int err, inpkts, i;
+ int err, inpkts;
+ condition *cnd_stop_capturesize = NULL;
+ condition *cnd_stop_timeout = NULL;
+ 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;
gint *value_ptr;
GtkWidget *label, *value, *percent;
} counts[] = {
- { "Total", &ld.counts.total },
- { "SCTP", &ld.counts.sctp },
- { "TCP", &ld.counts.tcp },
- { "UDP", &ld.counts.udp },
- { "ICMP", &ld.counts.icmp },
- { "OSPF", &ld.counts.ospf },
- { "GRE", &ld.counts.gre },
- { "NetBIOS", &ld.counts.netbios },
- { "IPX", &ld.counts.ipx },
- { "VINES", &ld.counts.vines },
- { "Other", &ld.counts.other }
+ { "Total", &ld.counts.total, NULL, NULL, NULL },
+ { "SCTP", &ld.counts.sctp, NULL, NULL, NULL },
+ { "TCP", &ld.counts.tcp, NULL, NULL, NULL },
+ { "UDP", &ld.counts.udp, NULL, NULL, NULL },
+ { "ICMP", &ld.counts.icmp, NULL, NULL, NULL },
+ { "OSPF", &ld.counts.ospf, NULL, NULL, NULL },
+ { "GRE", &ld.counts.gre, NULL, NULL, NULL },
+ { "NetBIOS", &ld.counts.netbios, NULL, NULL, NULL },
+ { "IPX", &ld.counts.ipx, NULL, NULL, NULL },
+ { "VINES", &ld.counts.vines, NULL, NULL, NULL },
+ { "Other", &ld.counts.other, NULL, NULL, NULL }
};
#define N_COUNTS (sizeof counts / sizeof counts[0])
ld.go = TRUE;
ld.counts.total = 0;
- ld.max = cfile.count;
+ if (capture_opts.has_autostop_count)
+ ld.max = capture_opts.autostop_count;
+ else
+ ld.max = 0; /* no limit */
ld.err = 0; /* no error seen yet */
ld.linktype = WTAP_ENCAP_UNKNOWN;
+ ld.pcap_err = FALSE;
ld.from_pipe = FALSE;
ld.sync_packets = 0;
ld.counts.sctp = 0;
/* We haven't yet gotten the capture statistics. */
*stats_known = FALSE;
- /* Open the network interface to capture from it. */
- pch = pcap_open_live(cfile.iface, cfile.snap, prefs.capture_prom_mode,
- CAP_READ_TIMEOUT, err_str);
+ /* Open the network interface to capture from it.
+ Some versions of libpcap may put warnings into the error buffer
+ 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';
+ pch = pcap_open_live(cfile.iface,
+ capture_opts.has_snaplen ? capture_opts.snaplen :
+ WTAP_MAX_PACKET_SIZE,
+ capture_opts.promisc_mode, CAP_READ_TIMEOUT,
+ open_err_str);
if (pch == NULL) {
#ifdef _WIN32
"\n"
"Note that the driver Ethereal uses for packet capture on Windows\n"
"doesn't support capturing on PPP/WAN interfaces in Windows NT/2000.\n",
- err_str);
+ open_err_str);
goto error;
#else
/* try to open cfile.iface as a pipe */
- pipe_fd = pipe_open_live(cfile.iface, &hdr, &ld, err_str);
+ pipe_fd = pipe_open_live(cfile.iface, &hdr, &ld, open_err_str);
if (pipe_fd == -1) {
/* Well, we couldn't start the capture.
of libpcap that properly handles HP-UX (libpcap 0.6.x and later
versions, which properly handle HP-UX, say "can't find /dev/dlpi
PPA for XXX" rather than "can't find PPA for XXX"). */
- if (strncmp(err_str, ppamsg, sizeof ppamsg - 1) == 0)
+ if (strncmp(open_err_str, ppamsg, sizeof ppamsg - 1) == 0)
libpcap_warn =
"\n\n"
"You are running Ethereal with a version of the libpcap library\n"
snprintf(errmsg, sizeof errmsg,
"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", err_str,
+ "you have the proper interface or pipe specified.%s", open_err_str,
libpcap_warn);
goto error;
}
/* capture filters only work on real interfaces */
if (cfile.cfilter && !ld.from_pipe) {
/* A capture filter was specified; set it up. */
- if (pcap_lookupnet (cfile.iface, &netnum, &netmask, err_str) < 0) {
+ if (pcap_lookupnet(cfile.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
#ifndef _WIN32
if (ld.from_pipe) {
pcap_encap = hdr.network;
- snaplen = hdr.snaplen;
+ file_snaplen = hdr.snaplen;
} else
#endif
{
- pcap_encap = pcap_datalink(pch);
- snaplen = pcap_snapshot(pch);
+ pcap_encap = get_pcap_linktype(pch, cfile.iface);
+ file_snaplen = pcap_snapshot(pch);
}
ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_encap);
if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
" 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,
- ld.linktype, snaplen, &err);
+ if (capture_opts.ringbuffer_on) {
+ ld.pdh = ringbuf_init_wtap_dump_fdopen(WTAP_FILE_PCAP, ld.linktype,
+ file_snaplen, &err);
+ } else {
+ ld.pdh = wtap_dump_fdopen(cfile.save_file_fd, WTAP_FILE_PCAP,
+ ld.linktype, file_snaplen, &err);
+ }
if (ld.pdh == NULL) {
/* We couldn't set up to write to the capture file. */
goto error;
}
+ /* Does "open_err_str" contain a non-empty string? If so, "pcap_open_live()"
+ returned a warning; print it, but keep capturing. */
+ if (open_err_str[0] != '\0')
+ g_warning("%s.", open_err_str);
+
/* XXX - capture SIGTERM and close the capture, in case we're on a
Linux 2.0[.x] system and you have to explicitly close the capture
stream in order to turn promiscuous mode off? We need to do that
*/
signal(SIGUSR1, stop_capture);
#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);
+ if (capture_opts.has_autostop_duration)
+ cnd_stop_timeout =
+ cnd_new(CND_CLASS_TIMEOUT,(gint32)capture_opts.autostop_duration);
+
while (ld.go) {
while (gtk_events_pending()) gtk_main_iteration();
* it.
*/
inpkts = pcap_dispatch(pch, 1, capture_pcap_cb, (u_char *) &ld);
+ if (inpkts < 0) {
+ ld.pcap_err = TRUE;
+ ld.go = FALSE;
+ }
} else
inpkts = 0;
#else
inpkts = pcap_dispatch(pch, 1, capture_pcap_cb, (u_char *) &ld);
+ if (inpkts < 0) {
+ ld.pcap_err = TRUE;
+ ld.go = FALSE;
+ }
#endif
}
if (inpkts > 0)
ld.sync_packets += inpkts;
+ /* check capture stop conditons */
+ if (cnd_stop_timeout != NULL && cnd_eval(cnd_stop_timeout)) {
+ /* The specified capture time has elapsed; stop the capture. */
+ ld.go = FALSE;
+ } else if (cnd_stop_capturesize != NULL && cnd_eval(cnd_stop_capturesize,
+ (guint32)wtap_get_bytes_dumped(ld.pdh))){
+ /* Capture file reached its maximum size. */
+ if (capture_opts.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) {
}
}
+ /* delete stop conditions */
+ if (cnd_stop_capturesize != NULL)
+ cnd_delete(cnd_stop_capturesize);
+ if (cnd_stop_timeout != NULL)
+ cnd_delete(cnd_stop_timeout);
+
+ if (ld.pcap_err) {
+ snprintf(errmsg, sizeof(errmsg), "Error while capturing packets: %s",
+ pcap_geterr(pch));
+ if (capture_child) {
+ /* Tell the parent, so that they can pop up the message;
+ we're going to exit, so if we try to pop it up, either
+ it won't pop up or it'll disappear as soon as we exit. */
+ send_errmsg_to_parent(errmsg);
+ } else {
+ /* Just pop up the message ourselves. */
+ simple_dialog(ESD_TYPE_WARN, NULL, "%s", errmsg);
+ }
+ }
+
if (ld.err != 0) {
get_capture_file_io_error(errmsg, sizeof(errmsg), cfile.save_file, ld.err,
FALSE);
/* 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 (capture_opts.ringbuffer_on) {
+ ringbuf_wtap_dump_close(&cfile, &err);
+ } else {
+ wtap_dump_close(ld.pdh, &err);
+ }
+ } else {
+ if (capture_opts.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) {
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 (capture_opts.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.
#endif
}
+void
+kill_capture_child(void)
+{
+ /*
+ * XXX - find some way of signaling the child in Win32.
+ */
+#ifndef _WIN32
+ if (fork_child != -1)
+ kill(fork_child, SIGTERM); /* SIGTERM so it can clean up if necessary */
+#endif
+}
+
static void
capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
const u_char *pd) {
}
}
- /* Set the initial payload to the packet length, and the initial
- captured payload to the capture length (other protocols may
- reduce them if their headers say they're less). */
- pi.len = phdr->len;
- pi.captured_len = phdr->caplen;
-
switch (ld->linktype) {
case WTAP_ENCAP_ETHERNET:
- capture_eth(pd, 0, &ld->counts);
+ capture_eth(pd, 0, phdr->len, &ld->counts);
break;
case WTAP_ENCAP_FDDI:
case WTAP_ENCAP_FDDI_BITSWAPPED:
- capture_fddi(pd, &ld->counts);
+ 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, &ld->counts);
+ capture_tr(pd, 0, phdr->len, &ld->counts);
break;
case WTAP_ENCAP_NULL:
- capture_null(pd, &ld->counts);
+ capture_null(pd, phdr->len, &ld->counts);
break;
case WTAP_ENCAP_PPP:
- capture_ppp_hdlc(pd, 0, &ld->counts);
+ capture_ppp_hdlc(pd, 0, phdr->len, &ld->counts);
break;
case WTAP_ENCAP_RAW_IP:
- capture_raw(pd, &ld->counts);
+ capture_raw(pd, phdr->len, &ld->counts);
break;
case WTAP_ENCAP_SLL:
- capture_sll(pd, &ld->counts);
+ capture_sll(pd, phdr->len, &ld->counts);
break;
case WTAP_ENCAP_LINUX_ATM_CLIP:
- capture_clip(pd, &ld->counts);
+ 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