2 * Routines for packet capture windows
4 * $Id: capture.c,v 1.109 2000/06/27 04:35:42 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
8 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 #ifdef HAVE_SYS_TYPES_H
34 # include <sys/types.h>
37 #ifdef HAVE_SYS_STAT_H
38 # include <sys/stat.h>
41 #ifdef HAVE_SYS_WAIT_H
42 # include <sys/wait.h>
61 #ifdef HAVE_SYS_SOCKET_H
62 #include <sys/socket.h>
65 #ifdef HAVE_SYS_IOCTL_H
66 #include <sys/ioctl.h>
76 #ifdef NEED_SNPRINTF_H
82 # include "snprintf.h"
90 #include <process.h> /* For spawning child process */
94 #include "gtk/gtkglobals.h"
99 #include "simple_dialog.h"
103 #include "packet-clip.h"
104 #include "packet-eth.h"
105 #include "packet-fddi.h"
106 #include "packet-null.h"
107 #include "packet-ppp.h"
108 #include "packet-raw.h"
109 #include "packet-tr.h"
111 int sync_mode; /* fork a child to do the capture, and sync between them */
112 static int sync_pipe[2]; /* used to sync father */
113 enum PIPES { READ, WRITE }; /* Constants 0 and 1 for READ and WRITE */
114 int quit_after_cap; /* Makes a "capture only mode". Implies -k */
115 gboolean capture_child; /* if this is the child for "-S" */
116 static guint cap_input_id;
119 static guint cap_timer_id;
120 static int cap_timer_cb(gpointer); /* Win32 kludge to check for pipe input */
123 static void cap_file_input_cb(gpointer, gint, GdkInputCondition);
124 static void capture_delete_cb(GtkWidget *, GdkEvent *, gpointer);
125 static void capture_stop_cb(GtkWidget *, gpointer);
126 static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
128 static void send_errmsg_to_parent(const char *);
129 static float pct(gint, gint);
131 typedef struct _loop_data {
136 packet_counts counts;
140 /* Win32 needs the O_BINARY flag for open() */
146 /* Win32 needs a handle to the child capture process */
150 /* Open a specified file, or create a temporary file, and start a capture
151 to the file in question. */
153 do_capture(char *capfile_name)
156 gboolean is_tempfile;
162 int capture_succeeded;
164 if (capfile_name != NULL) {
165 /* Try to open/create the specified file for use as a capture buffer. */
166 cfile.save_file_fd = open(capfile_name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT, 0600);
169 /* Choose a random name for the capture buffer */
170 cfile.save_file_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
171 capfile_name = g_strdup(tmpname);
174 if (cfile.save_file_fd == -1) {
175 simple_dialog(ESD_TYPE_WARN, NULL,
176 "The file to which the capture would be saved (\"%s\")"
177 "could not be opened: %s.", capfile_name, strerror(errno));
180 close_cap_file(&cfile, info_bar);
181 g_assert(cfile.save_file == NULL);
182 cfile.save_file = capfile_name;
184 if (sync_mode) { /* do the capture in a child process */
187 char scount[24]; /* need a constant for len of numbers */
188 char save_file_fd[24];
192 char sync_pipe_fd[24];
196 sprintf(ssnap,"%d",cfile.snap); /* in lieu of itoa */
197 sprintf(scount,"%d",cfile.count);
198 sprintf(save_file_fd,"%d",cfile.save_file_fd);
201 /* Create a pipe for the child process */
203 if(_pipe(sync_pipe, 512, O_BINARY) < 0) {
204 /* Couldn't create the pipe between parent and child. */
206 unlink(cfile.save_file);
207 g_free(cfile.save_file);
208 cfile.save_file = NULL;
209 simple_dialog(ESD_TYPE_WARN, NULL, "Couldn't create sync pipe: %s",
214 /* Convert pipe write handle to a string and pass to child */
215 itoa(sync_pipe[WRITE], sync_pipe_fd, 10);
216 /* Convert filter string to a quote delimited string */
217 filterstring = g_new(char, strlen(cfile.cfilter) + 3);
218 sprintf(filterstring, "\"%s\"", cfile.cfilter);
219 filterstring[strlen(cfile.cfilter) + 2] = 0;
221 fork_child = spawnlp(_P_NOWAIT, ethereal_path, CHILD_NAME, "-i", cfile.iface,
222 "-w", cfile.save_file, "-W", save_file_fd,
223 "-c", scount, "-s", ssnap,
225 strlen(cfile.cfilter) == 0 ? (const char *)NULL : "-f",
226 strlen(cfile.cfilter) == 0 ? (const char *)NULL : filterstring,
228 g_free(filterstring);
229 /* Keep a copy for later evaluation by _cwait() */
230 child_process = fork_child;
232 signal(SIGCHLD, SIG_IGN);
233 if (pipe(sync_pipe) < 0) {
234 /* Couldn't create the pipe between parent and child. */
236 unlink(cfile.save_file);
237 g_free(cfile.save_file);
238 cfile.save_file = NULL;
239 simple_dialog(ESD_TYPE_WARN, NULL, "Couldn't create sync pipe: %s",
243 if ((fork_child = fork()) == 0) {
245 * Child process - run Ethereal with the right arguments to make
246 * it just pop up the live capture dialog box and capture with
247 * the specified capture parameters, writing to the specified file.
249 * args: -i interface specification
251 * -W file descriptor to write
252 * -c count to capture
255 * -f "filter expression"
258 dup(sync_pipe[WRITE]);
259 close(sync_pipe[READ]);
260 execlp(ethereal_path, CHILD_NAME, "-i", cfile.iface,
261 "-w", cfile.save_file, "-W", save_file_fd,
262 "-c", scount, "-s", ssnap,
263 "-m", medium_font, "-b", bold_font,
264 (cfile.cfilter == NULL)? 0 : "-f",
265 (cfile.cfilter == NULL)? 0 : cfile.cfilter,
267 snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
268 ethereal_path, strerror(errno));
269 send_errmsg_to_parent(errmsg);
271 /* Exit with "_exit()", so that we don't close the connection
272 to the X server (and cause stuff buffered up by our parent but
273 not yet sent to be sent, as that stuff should only be sent by
279 /* Parent process - read messages from the child process over the
282 /* Close the write side of the pipe, so that only the child has it
283 open, and thus it completely closes, and thus returns to us
284 an EOF indication, if the child closes it (either deliberately
285 or by exiting abnormally). */
286 close(sync_pipe[WRITE]);
288 /* Close the save file FD, as we won't be using it - we'll be opening
289 it and reading the save file through Wiretap. */
290 close(cfile.save_file_fd);
292 if (fork_child == -1) {
293 /* We couldn't even create the child process. */
295 close(sync_pipe[READ]);
296 unlink(cfile.save_file);
297 g_free(cfile.save_file);
298 cfile.save_file = NULL;
299 simple_dialog(ESD_TYPE_WARN, NULL, "Couldn't create child process: %s",
304 /* Read a byte count from "sync_pipe[READ]", terminated with a
305 colon; if the count is 0, the child process created the
306 capture file and we should start reading from it, otherwise
307 the capture couldn't start and the count is a count of bytes
308 of error message, and we should display the message. */
311 i = read(sync_pipe[READ], &c, 1);
313 /* EOF - the child process died.
314 Close the read side of the sync pipe, remove the capture file,
315 and report the failure.
316 XXX - reap the child process and report the status in detail. */
317 close(sync_pipe[READ]);
318 unlink(cfile.save_file);
319 g_free(cfile.save_file);
320 cfile.save_file = NULL;
321 simple_dialog(ESD_TYPE_WARN, NULL, "Capture child process died");
327 /* Child process handed us crap.
328 Close the read side of the sync pipe, remove the capture file,
329 and report the failure. */
330 close(sync_pipe[READ]);
331 unlink(cfile.save_file);
332 g_free(cfile.save_file);
333 cfile.save_file = NULL;
334 simple_dialog(ESD_TYPE_WARN, NULL,
335 "Capture child process sent us a bad message");
338 byte_count = byte_count*10 + c - '0';
340 if (byte_count == 0) {
341 /* Success. Open the capture file, and set up to read it. */
342 err = start_tail_cap_file(cfile.save_file, is_tempfile, &cfile);
344 /* We were able to open and set up to read the capture file;
345 arrange that our callback be called whenever it's possible
346 to read from the sync pipe, so that it's called when
347 the child process wants to tell us something. */
349 /* Tricky to use pipes in win9x, as no concept of wait. NT can
350 do this but that doesn't cover all win32 platforms. GTK can do
351 this but doesn't seem to work over processes. Attempt to do
352 something similar here, start a timer and check for data on every
354 cap_timer_id = gtk_timeout_add(1000, cap_timer_cb, NULL);
356 cap_input_id = gtk_input_add_full(sync_pipe[READ],
357 GDK_INPUT_READ|GDK_INPUT_EXCEPTION,
364 /* We weren't able to open the capture file; complain, and
365 close the sync pipe. */
366 simple_dialog(ESD_TYPE_WARN, NULL,
367 file_open_error_message(err, FALSE), cfile.save_file);
369 /* Close the sync pipe. */
370 close(sync_pipe[READ]);
372 /* Don't unlink the save file - leave it around, for debugging
374 g_free(cfile.save_file);
375 cfile.save_file = NULL;
378 /* Failure - the child process sent us a message indicating
379 what the problem was. */
380 msg = g_malloc(byte_count + 1);
382 simple_dialog(ESD_TYPE_WARN, NULL,
383 "Capture child process failed, but its error message was too big.");
385 i = read(sync_pipe[READ], msg, byte_count);
387 simple_dialog(ESD_TYPE_WARN, NULL,
388 "Capture child process failed: Error %s reading its error message.",
391 simple_dialog(ESD_TYPE_WARN, NULL,
392 "Capture child process failed: EOF reading its error message.");
394 simple_dialog(ESD_TYPE_WARN, NULL, msg);
397 /* Close the sync pipe. */
398 close(sync_pipe[READ]);
400 /* Get rid of the save file - the capture never started. */
401 unlink(cfile.save_file);
402 g_free(cfile.save_file);
403 cfile.save_file = NULL;
408 capture_succeeded = capture();
409 if (quit_after_cap) {
410 /* DON'T unlink the save file. Presumably someone wants it. */
413 if (capture_succeeded) {
414 /* Capture succeeded; read in the capture file. */
415 if ((err = open_cap_file(cfile.save_file, is_tempfile, &cfile)) == 0) {
416 /* Set the read filter to NULL. */
418 err = read_cap_file(&cfile);
421 /* We're not doing a capture any more, so we don't have a save
423 g_free(cfile.save_file);
424 cfile.save_file = NULL;
429 /* The timer has expired, see if there's stuff to read from the pipe,
430 if so call the cap_file_input_cb */
432 cap_timer_cb(gpointer data)
436 gboolean result, result1;
439 /* Oddly enough although Named pipes don't work on win9x,
440 PeekNamedPipe does !!! */
441 handle = (HANDLE) _get_osfhandle (sync_pipe[READ]);
442 result = PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL);
444 /* Get the child process exit status */
445 result1 = GetExitCodeProcess((HANDLE)child_process, &childstatus);
447 /* If the Peek returned an error, or there are bytes to be read
448 or the childwatcher thread has terminated then call the normal
450 if (!result || avail > 0 || childstatus != STILL_ACTIVE) {
452 /* avoid reentrancy problems and stack overflow */
453 gtk_timeout_remove(cap_timer_id);
455 /* And call the real handler */
456 cap_file_input_cb((gpointer) &cfile, 0, 0);
458 /* Return false so that the timer is not run again */
462 /* No data so let timer run again */
468 /* There's stuff to read from the sync pipe, meaning the child has sent
469 us a message, or the sync pipe has closed, meaning the child has
470 closed it (perhaps because it exited). */
472 cap_file_input_cb(gpointer data, gint source, GdkInputCondition condition)
474 capture_file *cf = (capture_file *)data;
475 char buffer[256+1], *p = buffer, *q = buffer;
478 gboolean exit_loop = FALSE;
484 char sigmsg_buf[6+1+3+1];
488 /* avoid reentrancy problems and stack overflow */
489 gtk_input_remove(cap_input_id);
492 if ((nread = read(sync_pipe[READ], buffer, 256)) <= 0) {
493 /* The child has closed the sync pipe, meaning it's not going to be
494 capturing any more packets. Pick up its exit status, and
495 complain if it died of a signal. */
497 /* XXX - analyze the wait stuatus and display more information
498 in the dialog box? */
499 if (_cwait(&wstatus, child_process, _WAIT_CHILD) == -1) {
500 simple_dialog(ESD_TYPE_WARN, NULL, "Child capture process stopped unexpectedly");
503 if (wait(&wstatus) != -1) {
504 /* XXX - are there any platforms on which we can run that *don't*
505 support POSIX.1's <sys/wait.h> and macros therein? */
506 wsignal = wstatus & 0177;
508 if (wstatus == 0177) {
509 /* It stopped, rather than exiting. "Should not happen." */
511 wsignal = (wstatus >> 8) & 0xFF;
515 coredumped = " - core dumped";
525 sigmsg = "Interrupted";
533 sigmsg = "Illegal instruction";
537 sigmsg = "Trace trap";
545 sigmsg = "Arithmetic exception";
553 sigmsg = "Bus error";
557 sigmsg = "Segmentation violation";
560 /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO
561 Linux is POSIX compliant. These are not POSIX-defined signals ---
562 ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
564 ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
565 were omitted from POSIX.1 because their behavior is
566 implementation dependent and could not be adequately catego-
567 rized. Conforming implementations may deliver these sig-
568 nals, but must document the circumstances under which they
569 are delivered and note any restrictions concerning their
575 sigmsg = "Bad system call";
580 sigmsg = "Broken pipe";
584 sigmsg = "Alarm clock";
588 sigmsg = "Terminated";
592 sprintf(sigmsg_buf, "Signal %d", wsignal);
596 simple_dialog(ESD_TYPE_WARN, NULL,
597 "Child capture process %s: %s%s", msg, sigmsg, coredumped);
602 /* Read what remains of the capture file, and finish the capture.
603 XXX - do something if this fails? */
604 err = finish_tail_cap_file(cf);
606 /* We're not doing a capture any more, so we don't have a save
608 g_free(cf->save_file);
609 cf->save_file = NULL;
614 buffer[nread] = '\0';
617 /* look for (possibly multiple) '*' */
625 /* XXX should handle the case of a pipe full (i.e. no star found) */
634 /* Read from the capture file the number of records the child told us
636 XXX - do something if this fails? */
637 err = continue_tail_cap_file(cf, to_read);
639 /* restore pipe handler */
641 cap_timer_id = gtk_timeout_add(1000, cap_timer_cb, NULL);
643 cap_input_id = gtk_input_add_full (sync_pipe[READ],
644 GDK_INPUT_READ|GDK_INPUT_EXCEPTION,
653 * Timeout, in milliseconds, for reads from the stream of captured packets.
655 #define CAP_READ_TIMEOUT 250
657 /* Do the low-level work of a capture.
658 Returns TRUE if it succeeds, FALSE otherwise. */
662 GtkWidget *cap_w, *main_vb, *count_lb, *sctp_lb, *tcp_lb, *udp_lb, *icmp_lb,
663 *ospf_lb, *gre_lb, *netbios_lb, *ipx_lb, *vines_lb, *other_lb, *stop_bt;
665 gchar err_str[PCAP_ERRBUF_SIZE], label_str[32];
667 bpf_u_int32 netnum, netmask;
668 time_t upd_time, cur_time;
673 struct timeval timeout;
677 WORD wVersionRequested;
681 /* Initialize Windows Socket if we are in a WIN32 OS
682 This needs to be done before querying the interface for network/netmask */
684 wVersionRequested = MAKEWORD( 1, 1 );
685 err = WSAStartup( wVersionRequested, &wsaData );
687 snprintf(errmsg, sizeof errmsg,
688 "Couldn't initialize Windows Sockets.");
696 ld.max = cfile.count;
697 ld.linktype = WTAP_ENCAP_UNKNOWN;
706 ld.counts.netbios = 0;
711 /* Open the network interface to capture from it. */
712 pch = pcap_open_live(cfile.iface, cfile.snap, 1, CAP_READ_TIMEOUT, err_str);
715 /* Well, we couldn't start the capture.
716 If this is a child process that does the capturing in sync
717 mode or fork mode, it shouldn't do any UI stuff until we pop up the
718 capture-progress window, and, since we couldn't start the
719 capture, we haven't popped it up. */
720 if (!capture_child) {
721 while (gtk_events_pending()) gtk_main_iteration();
723 snprintf(errmsg, sizeof errmsg,
724 "The capture session could not be initiated (%s).\n"
725 "Please check to make sure you have sufficient permissions, and that\n"
726 "you have the proper interface specified.", err_str);
731 /* A capture filter was specified; set it up. */
732 if (pcap_lookupnet (cfile.iface, &netnum, &netmask, err_str) < 0) {
733 snprintf(errmsg, sizeof errmsg,
734 "Can't use filter: Couldn't obtain netmask info (%s).", err_str);
737 if (pcap_compile(pch, &cfile.fcode, cfile.cfilter, 1, netmask) < 0) {
738 snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
742 if (pcap_setfilter(pch, &cfile.fcode) < 0) {
743 snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
749 /* Set up to write to the capture file. */
750 ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(pch));
751 if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
752 strcpy(errmsg, "The network you're capturing from is of a type"
753 " that Ethereal doesn't support.");
756 ld.pdh = wtap_dump_fdopen(cfile.save_file_fd, WTAP_FILE_PCAP,
757 ld.linktype, pcap_snapshot(pch), &err);
759 if (ld.pdh == NULL) {
760 /* We couldn't set up to write to the capture file. */
763 case WTAP_ERR_CANT_OPEN:
764 strcpy(errmsg, "The file to which the capture would be saved"
765 " couldn't be created for some unknown reason.");
768 case WTAP_ERR_SHORT_WRITE:
769 strcpy(errmsg, "A full header couldn't be written to the file"
770 " to which the capture would be saved.");
775 sprintf(errmsg, "The file to which the capture would be"
776 " saved (\"%s\") could not be opened: Error %d.",
777 cfile.save_file, err);
779 sprintf(errmsg, "The file to which the capture would be"
780 " saved (\"%s\") could not be opened: %s.",
781 cfile.save_file, strerror(err));
789 /* Well, we should be able to start capturing.
791 This is the child process for a sync mode capture, so sync out
792 the capture file, so the header makes it to the file system,
793 and send a "capture started successfully and capture file created"
794 message to our parent so that they'll open the capture file and
795 update its windows to indicate that we have a live capture in
797 fflush(wtap_dump_file(ld.pdh));
801 cap_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
802 gtk_window_set_title(GTK_WINDOW(cap_w), "Ethereal: Capture / Playback");
804 /* Container for capture display widgets */
805 main_vb = gtk_vbox_new(FALSE, 1);
806 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
807 gtk_container_add(GTK_CONTAINER(cap_w), main_vb);
808 gtk_widget_show(main_vb);
810 count_lb = gtk_label_new("Count: 0");
811 gtk_box_pack_start(GTK_BOX(main_vb), count_lb, FALSE, FALSE, 3);
812 gtk_widget_show(count_lb);
814 sctp_lb = gtk_label_new("SCTP: 0 (0.0%)");
815 gtk_box_pack_start(GTK_BOX(main_vb), sctp_lb, FALSE, FALSE, 3);
816 gtk_widget_show(sctp_lb);
818 tcp_lb = gtk_label_new("TCP: 0 (0.0%)");
819 gtk_box_pack_start(GTK_BOX(main_vb), tcp_lb, FALSE, FALSE, 3);
820 gtk_widget_show(tcp_lb);
822 udp_lb = gtk_label_new("UDP: 0 (0.0%)");
823 gtk_box_pack_start(GTK_BOX(main_vb), udp_lb, FALSE, FALSE, 3);
824 gtk_widget_show(udp_lb);
826 icmp_lb = gtk_label_new("ICMP: 0 (0.0%)");
827 gtk_box_pack_start(GTK_BOX(main_vb), icmp_lb, FALSE, FALSE, 3);
828 gtk_widget_show(icmp_lb);
830 ospf_lb = gtk_label_new("OSPF: 0 (0.0%)");
831 gtk_box_pack_start(GTK_BOX(main_vb), ospf_lb, FALSE, FALSE, 3);
832 gtk_widget_show(ospf_lb);
834 gre_lb = gtk_label_new("GRE: 0 (0.0%)");
835 gtk_box_pack_start(GTK_BOX(main_vb), gre_lb, FALSE, FALSE, 3);
836 gtk_widget_show(gre_lb);
838 netbios_lb = gtk_label_new("NetBIOS: 0 (0.0%)");
839 gtk_box_pack_start(GTK_BOX(main_vb), netbios_lb, FALSE, FALSE, 3);
840 gtk_widget_show(netbios_lb);
842 ipx_lb = gtk_label_new("IPX: 0 (0.0%)");
843 gtk_box_pack_start(GTK_BOX(main_vb), ipx_lb, FALSE, FALSE, 3);
844 gtk_widget_show(ipx_lb);
846 vines_lb = gtk_label_new("VINES: 0 (0.0%)");
847 gtk_box_pack_start(GTK_BOX(main_vb), vines_lb, FALSE, FALSE, 3);
848 gtk_widget_show(vines_lb);
850 other_lb = gtk_label_new("Other: 0 (0.0%)");
851 gtk_box_pack_start(GTK_BOX(main_vb), other_lb, FALSE, FALSE, 3);
852 gtk_widget_show(other_lb);
854 /* allow user to either click a stop button, or the close button on
855 the window to stop a capture in progress. */
856 stop_bt = gtk_button_new_with_label ("Stop");
857 gtk_signal_connect(GTK_OBJECT(stop_bt), "clicked",
858 GTK_SIGNAL_FUNC(capture_stop_cb), (gpointer) &ld);
859 gtk_signal_connect(GTK_OBJECT(cap_w), "delete_event",
860 GTK_SIGNAL_FUNC(capture_delete_cb), (gpointer) &ld);
861 gtk_box_pack_end(GTK_BOX(main_vb), stop_bt, FALSE, FALSE, 3);
862 GTK_WIDGET_SET_FLAGS(stop_bt, GTK_CAN_DEFAULT);
863 gtk_widget_grab_default(stop_bt);
864 GTK_WIDGET_SET_FLAGS(stop_bt, GTK_CAN_DEFAULT);
865 gtk_widget_grab_default(stop_bt);
866 gtk_widget_show(stop_bt);
868 gtk_widget_show(cap_w);
871 upd_time = time(NULL);
873 pcap_fd = pcap_fileno(pch);
876 while (gtk_events_pending()) gtk_main_iteration();
879 * Sigh. The semantics of the read timeout argument to
880 * "pcap_open_live()" aren't particularly well specified by
881 * the "pcap" man page - at least with the BSD BPF code, the
882 * intent appears to be, at least in part, a way of cutting
883 * down the number of reads done on a capture, by blocking
884 * until the buffer fills or a timer expires - and the Linux
885 * libpcap doesn't actually support it, so we can't use it
886 * to break out of the "pcap_dispatch()" every 1/4 of a second
889 * Thus, on Linux, we do a "select()" on the file descriptor for the
890 * capture, with a timeout of CAP_READ_TIMEOUT milliseconds, or
891 * CAP_READ_TIMEOUT*1000 microseconds.
894 FD_SET(pcap_fd, &set1);
896 timeout.tv_usec = CAP_READ_TIMEOUT*1000;
897 if (select(pcap_fd+1, &set1, NULL, NULL, &timeout) != 0) {
899 * "select()" says we can read from it without blocking; go for
902 inpkts = pcap_dispatch(pch, 1, capture_pcap_cb, (u_char *) &ld);
906 inpkts = pcap_dispatch(pch, 1, capture_pcap_cb, (u_char *) &ld);
909 ld.sync_packets += inpkts;
910 /* Only update once a second so as not to overload slow displays */
911 cur_time = time(NULL);
912 if (cur_time > upd_time) {
915 sprintf(label_str, "Count: %d", ld.counts.total);
916 gtk_label_set(GTK_LABEL(count_lb), label_str);
918 sprintf(label_str, "SCTP: %d (%.1f%%)", ld.counts.sctp,
919 pct(ld.counts.sctp, ld.counts.total));
920 gtk_label_set(GTK_LABEL(sctp_lb), label_str);
922 sprintf(label_str, "TCP: %d (%.1f%%)", ld.counts.tcp,
923 pct(ld.counts.tcp, ld.counts.total));
924 gtk_label_set(GTK_LABEL(tcp_lb), label_str);
926 sprintf(label_str, "UDP: %d (%.1f%%)", ld.counts.udp,
927 pct(ld.counts.udp, ld.counts.total));
928 gtk_label_set(GTK_LABEL(udp_lb), label_str);
930 sprintf(label_str, "ICMP: %d (%.1f%%)", ld.counts.icmp,
931 pct(ld.counts.icmp, ld.counts.total));
932 gtk_label_set(GTK_LABEL(icmp_lb), label_str);
934 sprintf(label_str, "OSPF: %d (%.1f%%)", ld.counts.ospf,
935 pct(ld.counts.ospf, ld.counts.total));
936 gtk_label_set(GTK_LABEL(ospf_lb), label_str);
938 sprintf(label_str, "GRE: %d (%.1f%%)", ld.counts.gre,
939 pct(ld.counts.gre, ld.counts.total));
940 gtk_label_set(GTK_LABEL(gre_lb), label_str);
942 sprintf(label_str, "NetBIOS: %d (%.1f%%)", ld.counts.netbios,
943 pct(ld.counts.netbios, ld.counts.total));
944 gtk_label_set(GTK_LABEL(netbios_lb), label_str);
946 sprintf(label_str, "IPX: %d (%.1f%%)", ld.counts.ipx,
947 pct(ld.counts.ipx, ld.counts.total));
948 gtk_label_set(GTK_LABEL(ipx_lb), label_str);
950 sprintf(label_str, "VINES: %d (%.1f%%)", ld.counts.vines,
951 pct(ld.counts.vines, ld.counts.total));
952 gtk_label_set(GTK_LABEL(vines_lb), label_str);
954 sprintf(label_str, "Other: %d (%.1f%%)", ld.counts.other,
955 pct(ld.counts.other, ld.counts.total));
956 gtk_label_set(GTK_LABEL(other_lb), label_str);
958 /* do sync here, too */
959 fflush(wtap_dump_file(ld.pdh));
960 if (capture_child && ld.sync_packets) {
961 /* This is the child process for a sync mode capture, so send
962 our parent a message saying we've written out "ld.sync_packets"
963 packets to the capture file. */
965 sprintf(tmp, "%d*", ld.sync_packets);
966 write(1, tmp, strlen(tmp));
972 if (!wtap_dump_close(ld.pdh, &err)) {
973 /* XXX - in fork mode, this may not pop up, or, if it does,
974 it may disappear as soon as we exit.
976 We should have the parent process, while it's reading
977 the packet count update messages, catch error messages
978 and pop up a message box if it sees one. */
981 case WTAP_ERR_CANT_CLOSE:
982 simple_dialog(ESD_TYPE_WARN, NULL,
983 "The file to which the capture was being saved"
984 " couldn't be closed for some unknown reason.");
987 case WTAP_ERR_SHORT_WRITE:
988 simple_dialog(ESD_TYPE_WARN, NULL,
989 "Not all the data could be written to the file"
990 " to which the capture was being saved.");
994 simple_dialog(ESD_TYPE_WARN, NULL,
995 "The file to which the capture was being"
996 " saved (\"%s\") could not be closed: %s.",
997 cfile.save_file, wtap_strerror(err));
1003 gtk_grab_remove(GTK_WIDGET(cap_w));
1004 gtk_widget_destroy(GTK_WIDGET(cap_w));
1009 /* We can't use the save file, and we have no wtap_dump stream
1010 to close in order to close it, so close the FD directly. */
1011 close(cfile.save_file_fd);
1013 /* We couldn't even start the capture, so get rid of the capture
1015 unlink(cfile.save_file); /* silently ignore error */
1016 g_free(cfile.save_file);
1017 cfile.save_file = NULL;
1018 if (capture_child) {
1019 /* This is the child process for a sync mode capture.
1020 Send the error message to our parent, so they can display a
1021 dialog box containing it. */
1022 send_errmsg_to_parent(errmsg);
1024 /* Display the dialog box ourselves; there's no parent. */
1025 simple_dialog(ESD_TYPE_WARN, NULL, errmsg);
1034 send_errmsg_to_parent(const char *errmsg)
1036 int msglen = strlen(errmsg);
1037 char lenbuf[10+1+1];
1039 sprintf(lenbuf, "%u;", msglen);
1040 write(1, lenbuf, strlen(lenbuf));
1041 write(1, errmsg, msglen);
1045 pct(gint num, gint denom) {
1047 return (float) num * 100.0 / (float) denom;
1054 capture_delete_cb(GtkWidget *w, GdkEvent *event, gpointer data) {
1055 capture_stop_cb(NULL, data);
1059 capture_stop_cb(GtkWidget *w, gpointer data) {
1060 loop_data *ld = (loop_data *) data;
1066 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
1068 struct wtap_pkthdr whdr;
1069 loop_data *ld = (loop_data *) user;
1072 if ((++ld->counts.total >= ld->max) && (ld->max > 0))
1077 /* "phdr->ts" may not necessarily be a "struct timeval" - it may
1078 be a "struct bpf_timeval", with member sizes wired to 32
1079 bits - and we may go that way ourselves in the future, so
1080 copy the members individually. */
1081 whdr.ts.tv_sec = phdr->ts.tv_sec;
1082 whdr.ts.tv_usec = phdr->ts.tv_usec;
1083 whdr.caplen = phdr->caplen;
1084 whdr.len = phdr->len;
1085 whdr.pkt_encap = ld->linktype;
1087 /* XXX - do something if this fails */
1088 wtap_dump(ld->pdh, &whdr, NULL, pd, &err);
1091 /* Set the initial payload to the packet length, and the initial
1092 captured payload to the capture length (other protocols may
1093 reduce them if their headers say they're less). */
1095 pi.captured_len = phdr->caplen;
1097 switch (ld->linktype) {
1098 case WTAP_ENCAP_ETHERNET:
1099 capture_eth(pd, 0, &ld->counts);
1101 case WTAP_ENCAP_FDDI:
1102 case WTAP_ENCAP_FDDI_BITSWAPPED:
1103 capture_fddi(pd, &ld->counts);
1106 capture_tr(pd, 0, &ld->counts);
1108 case WTAP_ENCAP_NULL:
1109 capture_null(pd, &ld->counts);
1111 case WTAP_ENCAP_PPP:
1112 capture_ppp(pd, 0, &ld->counts);
1114 case WTAP_ENCAP_RAW_IP:
1115 capture_raw(pd, &ld->counts);
1117 case WTAP_ENCAP_LINUX_ATM_CLIP:
1118 capture_clip(pd, &ld->counts);
1120 /* XXX - FreeBSD may append 4-byte ATM pseudo-header to DLT_ATM_RFC1483,
1121 with LLC header following; we should implement it at some
1126 #endif /* HAVE_LIBPCAP */