2 * Routines for packet capture windows
4 * $Id: capture.c,v 1.101 2000/05/06 07:07:27 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 "gtk/gtkglobals.h"
95 #include "simple_dialog.h"
99 #include "packet-eth.h"
100 #include "packet-fddi.h"
101 #include "packet-null.h"
102 #include "packet-ppp.h"
103 #include "packet-raw.h"
104 #include "packet-tr.h"
106 int sync_mode; /* fork a child to do the capture, and sync between them */
107 static int sync_pipe[2]; /* used to sync father */
108 int quit_after_cap; /* Makes a "capture only mode". Implies -k */
109 gboolean capture_child; /* if this is the child for "-S" */
110 static guint cap_input_id;
112 static void cap_file_input_cb(gpointer, gint, GdkInputCondition);
113 static void capture_delete_cb(GtkWidget *, GdkEvent *, gpointer);
114 static void capture_stop_cb(GtkWidget *, gpointer);
115 static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
117 static void send_errmsg_to_parent(const char *);
118 static float pct(gint, gint);
120 typedef struct _loop_data {
125 packet_counts counts;
129 /* Win32 needs the O_BINARY flag for open() */
134 /* Open a specified file, or create a temporary file, and start a capture
135 to the file in question. */
137 do_capture(char *capfile_name)
140 gboolean is_tempfile;
146 int capture_succeeded;
148 if (capfile_name != NULL) {
149 /* Try to open/create the specified file for use as a capture buffer. */
150 cf.save_file_fd = open(capfile_name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT, 0600);
153 /* Choose a random name for the capture buffer */
154 cf.save_file_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
155 capfile_name = g_strdup(tmpname);
158 if (cf.save_file_fd == -1) {
159 simple_dialog(ESD_TYPE_WARN, NULL,
160 "The file to which the capture would be saved (\"%s\")"
161 "could not be opened: %s.", capfile_name, strerror(errno));
164 close_cap_file(&cf, info_bar);
165 g_assert(cf.save_file == NULL);
166 cf.save_file = capfile_name;
168 if (sync_mode) { /* do the capture in a child process */
172 char scount[24]; /* need a constant for len of numbers */
173 char save_file_fd[24];
177 sprintf(ssnap,"%d",cf.snap); /* in lieu of itoa */
178 sprintf(scount,"%d",cf.count);
179 sprintf(save_file_fd,"%d",cf.save_file_fd);
180 signal(SIGCHLD, SIG_IGN);
181 if (pipe(sync_pipe) < 0) {
182 /* Couldn't create the pipe between parent and child. */
184 unlink(cf.save_file);
185 g_free(cf.save_file);
187 simple_dialog(ESD_TYPE_WARN, NULL, "Couldn't create sync pipe: %s",
191 if ((fork_child = fork()) == 0) {
193 * Child process - run Ethereal with the right arguments to make
194 * it just pop up the live capture dialog box and capture with
195 * the specified capture parameters, writing to the specified file.
197 * args: -i interface specification
199 * -W file descriptor to write
200 * -c count to capture
203 * -f "filter expression"
208 execlp(ethereal_path, CHILD_NAME, "-i", cf.iface,
209 "-w", cf.save_file, "-W", save_file_fd,
210 "-c", scount, "-s", ssnap,
211 "-m", medium_font, "-b", bold_font,
212 (cf.cfilter == NULL)? 0 : "-f",
213 (cf.cfilter == NULL)? 0 : cf.cfilter,
215 snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
216 ethereal_path, strerror(errno));
217 send_errmsg_to_parent(errmsg);
219 /* Exit with "_exit()", so that we don't close the connection
220 to the X server (and cause stuff buffered up by our parent but
221 not yet sent to be sent, as that stuff should only be sent by
226 if (fork_child == -1) {
227 /* We couldn't even create the child process. */
231 unlink(cf.save_file);
232 g_free(cf.save_file);
234 simple_dialog(ESD_TYPE_WARN, NULL, "Couldn't create child process: %s",
239 /* Parent process - read messages from the child process over the
243 /* Read a byte count from "sync_pipe[0]", terminated with a
244 colon; if the count is 0, the child process created the
245 capture file and we should start reading from it, otherwise
246 the capture couldn't start and the count is a count of bytes
247 of error message, and we should display the message. */
250 i = read(sync_pipe[0], &c, 1);
252 /* EOF - the child process died.
253 Close the read side of the sync pipe, remove the capture file,
254 and report the failure.
255 XXX - reap the child process and report the status in detail. */
257 unlink(cf.save_file);
258 g_free(cf.save_file);
260 simple_dialog(ESD_TYPE_WARN, NULL, "Capture child process died");
266 /* Child process handed us crap.
267 Close the read side of the sync pipe, remove the capture file,
268 and report the failure. */
270 unlink(cf.save_file);
271 g_free(cf.save_file);
273 simple_dialog(ESD_TYPE_WARN, NULL,
274 "Capture child process sent us a bad message");
277 byte_count = byte_count*10 + c - '0';
279 if (byte_count == 0) {
280 /* Success. Open the capture file, and set up to read it. */
281 err = start_tail_cap_file(cf.save_file, is_tempfile, &cf);
283 /* We were able to open and set up to read the capture file;
284 arrange that our callback be called whenever it's possible
285 to read from the sync pipe, so that it's called when
286 the child process wants to tell us something. */
287 cap_input_id = gtk_input_add_full(sync_pipe[0],
288 GDK_INPUT_READ|GDK_INPUT_EXCEPTION,
294 /* We weren't able to open the capture file; complain, and
295 close the sync pipe. */
296 simple_dialog(ESD_TYPE_WARN, NULL,
297 file_open_error_message(err, FALSE), cf.save_file);
299 /* Close the sync pipe. */
302 /* Don't unlink the save file - leave it around, for debugging
304 g_free(cf.save_file);
308 /* Failure - the child process sent us a message indicating
309 what the problem was. */
310 msg = g_malloc(byte_count + 1);
312 simple_dialog(ESD_TYPE_WARN, NULL,
313 "Capture child process failed, but its error message was too big.");
315 i = read(sync_pipe[0], msg, byte_count);
317 simple_dialog(ESD_TYPE_WARN, NULL,
318 "Capture child process failed: Error %s reading its error message.",
321 simple_dialog(ESD_TYPE_WARN, NULL,
322 "Capture child process failed: EOF reading its error message.");
324 simple_dialog(ESD_TYPE_WARN, NULL, msg);
327 /* Close the sync pipe. */
330 /* Get rid of the save file - the capture never started. */
331 unlink(cf.save_file);
332 g_free(cf.save_file);
339 capture_succeeded = capture();
340 if (quit_after_cap) {
341 /* DON'T unlink the save file. Presumably someone wants it. */
344 if (capture_succeeded) {
345 /* Capture succeeded; read in the capture file. */
346 if ((err = open_cap_file(cf.save_file, is_tempfile, &cf)) == 0) {
347 /* Set the read filter to NULL. */
349 err = read_cap_file(&cf);
352 /* We're not doing a capture any more, so we don't have a save
354 g_free(cf.save_file);
360 /* There's stuff to read from the sync pipe, meaning the child has sent
361 us a message, or the sync pipe has closed, meaning the child has
362 closed it (perhaps because it exited). */
364 cap_file_input_cb(gpointer data, gint source, GdkInputCondition condition)
366 capture_file *cf = (capture_file *)data;
367 char buffer[256+1], *p = buffer, *q = buffer;
370 gboolean exit_loop = FALSE;
376 char sigmsg_buf[6+1+3+1];
379 /* avoid reentrancy problems and stack overflow */
380 gtk_input_remove(cap_input_id);
382 if ((nread = read(sync_pipe[0], buffer, 256)) <= 0) {
383 /* The child has closed the sync pipe, meaning it's not going to be
384 capturing any more packets. Pick up its exit status, and
385 complain if it died of a signal. */
386 if (wait(&wstatus) != -1) {
387 /* XXX - are there any platforms on which we can run that *don't*
388 support POSIX.1's <sys/wait.h> and macros therein? */
389 wsignal = wstatus & 0177;
391 if (wstatus == 0177) {
392 /* It stopped, rather than exiting. "Should not happen." */
394 wsignal = (wstatus >> 8) & 0xFF;
398 coredumped = " - core dumped";
408 sigmsg = "Interrupted";
416 sigmsg = "Illegal instruction";
420 sigmsg = "Trace trap";
428 sigmsg = "Arithmetic exception";
436 sigmsg = "Bus error";
440 sigmsg = "Segmentation violation";
443 /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO
444 Linux is POSIX compliant. These are not POSIX-defined signals ---
445 ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
447 ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
448 were omitted from POSIX.1 because their behavior is
449 implementation dependent and could not be adequately catego-
450 rized. Conforming implementations may deliver these sig-
451 nals, but must document the circumstances under which they
452 are delivered and note any restrictions concerning their
458 sigmsg = "Bad system call";
463 sigmsg = "Broken pipe";
467 sigmsg = "Alarm clock";
471 sigmsg = "Terminated";
475 sprintf(sigmsg_buf, "Signal %d", wsignal);
479 simple_dialog(ESD_TYPE_WARN, NULL,
480 "Child capture process %s: %s%s", msg, sigmsg, coredumped);
484 /* Read what remains of the capture file, and finish the capture.
485 XXX - do something if this fails? */
486 err = finish_tail_cap_file(cf);
488 /* We're not doing a capture any more, so we don't have a save
490 g_free(cf->save_file);
491 cf->save_file = NULL;
496 buffer[nread] = '\0';
499 /* look for (possibly multiple) '*' */
507 /* XXX should handle the case of a pipe full (i.e. no star found) */
516 /* Read from the capture file the number of records the child told us
518 XXX - do something if this fails? */
519 err = continue_tail_cap_file(cf, to_read);
521 /* restore pipe handler */
522 cap_input_id = gtk_input_add_full (sync_pipe[0],
523 GDK_INPUT_READ|GDK_INPUT_EXCEPTION,
532 * Timeout, in milliseconds, for reads from the stream of captured packets.
534 #define CAP_READ_TIMEOUT 250
536 /* Do the low-level work of a capture.
537 Returns TRUE if it succeeds, FALSE otherwise. */
541 GtkWidget *cap_w, *main_vb, *count_lb, *tcp_lb, *udp_lb, *icmp_lb,
542 *ospf_lb, *gre_lb, *netbios_lb, *ipx_lb, *vines_lb, *other_lb, *stop_bt;
544 gchar err_str[PCAP_ERRBUF_SIZE], label_str[32];
546 bpf_u_int32 netnum, netmask;
547 time_t upd_time, cur_time;
552 struct timeval timeout;
556 WORD wVersionRequested;
560 /* Initialize Windows Socket if we are in a WIN32 OS
561 This needs to be done before querying the interface for network/netmask */
563 wVersionRequested = MAKEWORD( 1, 1 );
564 err = WSAStartup( wVersionRequested, &wsaData );
566 snprintf(errmsg, sizeof errmsg,
567 "Couldn't initialize Windows Sockets.");
576 ld.linktype = WTAP_ENCAP_UNKNOWN;
584 ld.counts.netbios = 0;
589 /* Open the network interface to capture from it. */
590 pch = pcap_open_live(cf.iface, cf.snap, 1, CAP_READ_TIMEOUT, err_str);
593 /* Well, we couldn't start the capture.
594 If this is a child process that does the capturing in sync
595 mode or fork mode, it shouldn't do any UI stuff until we pop up the
596 capture-progress window, and, since we couldn't start the
597 capture, we haven't popped it up. */
598 if (!capture_child) {
599 while (gtk_events_pending()) gtk_main_iteration();
601 snprintf(errmsg, sizeof errmsg,
602 "The capture session could not be initiated (%s).\n"
603 "Please check to make sure you have sufficient permissions, and that\n"
604 "you have the proper interface specified.", err_str);
609 /* A capture filter was specified; set it up. */
610 if (pcap_lookupnet (cf.iface, &netnum, &netmask, err_str) < 0) {
611 snprintf(errmsg, sizeof errmsg,
612 "Can't use filter: Couldn't obtain netmask info (%s).", err_str);
615 if (pcap_compile(pch, &cf.fcode, cf.cfilter, 1, netmask) < 0) {
616 snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
620 if (pcap_setfilter(pch, &cf.fcode) < 0) {
621 snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
627 /* Set up to write to the capture file. */
628 ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(pch));
629 if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
630 strcpy(errmsg, "The network you're capturing from is of a type"
631 " that Ethereal doesn't support.");
634 ld.pdh = wtap_dump_fdopen(cf.save_file_fd, WTAP_FILE_PCAP,
635 ld.linktype, pcap_snapshot(pch), &err);
637 if (ld.pdh == NULL) {
638 /* We couldn't set up to write to the capture file. */
641 case WTAP_ERR_CANT_OPEN:
642 strcpy(errmsg, "The file to which the capture would be saved"
643 " couldn't be created for some unknown reason.");
646 case WTAP_ERR_SHORT_WRITE:
647 strcpy(errmsg, "A full header couldn't be written to the file"
648 " to which the capture would be saved.");
653 sprintf(errmsg, "The file to which the capture would be"
654 " saved (\"%s\") could not be opened: Error %d.",
657 sprintf(errmsg, "The file to which the capture would be"
658 " saved (\"%s\") could not be opened: %s.",
659 cf.save_file, strerror(err));
667 /* Well, we should be able to start capturing.
669 This is the child process for a sync mode capture, so sync out
670 the capture file, so the header makes it to the file system,
671 and send a "capture started successfully and capture file created"
672 message to our parent so that they'll open the capture file and
673 update its windows to indicate that we have a live capture in
675 fflush(wtap_dump_file(ld.pdh));
679 cap_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
680 gtk_window_set_title(GTK_WINDOW(cap_w), "Ethereal: Capture / Playback");
682 /* Container for capture display widgets */
683 main_vb = gtk_vbox_new(FALSE, 1);
684 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
685 gtk_container_add(GTK_CONTAINER(cap_w), main_vb);
686 gtk_widget_show(main_vb);
688 count_lb = gtk_label_new("Count: 0");
689 gtk_box_pack_start(GTK_BOX(main_vb), count_lb, FALSE, FALSE, 3);
690 gtk_widget_show(count_lb);
692 tcp_lb = gtk_label_new("TCP: 0 (0.0%)");
693 gtk_box_pack_start(GTK_BOX(main_vb), tcp_lb, FALSE, FALSE, 3);
694 gtk_widget_show(tcp_lb);
696 udp_lb = gtk_label_new("UDP: 0 (0.0%)");
697 gtk_box_pack_start(GTK_BOX(main_vb), udp_lb, FALSE, FALSE, 3);
698 gtk_widget_show(udp_lb);
700 icmp_lb = gtk_label_new("ICMP: 0 (0.0%)");
701 gtk_box_pack_start(GTK_BOX(main_vb), icmp_lb, FALSE, FALSE, 3);
702 gtk_widget_show(icmp_lb);
704 ospf_lb = gtk_label_new("OSPF: 0 (0.0%)");
705 gtk_box_pack_start(GTK_BOX(main_vb), ospf_lb, FALSE, FALSE, 3);
706 gtk_widget_show(ospf_lb);
708 gre_lb = gtk_label_new("GRE: 0 (0.0%)");
709 gtk_box_pack_start(GTK_BOX(main_vb), gre_lb, FALSE, FALSE, 3);
710 gtk_widget_show(gre_lb);
712 netbios_lb = gtk_label_new("NetBIOS: 0 (0.0%)");
713 gtk_box_pack_start(GTK_BOX(main_vb), netbios_lb, FALSE, FALSE, 3);
714 gtk_widget_show(netbios_lb);
716 ipx_lb = gtk_label_new("IPX: 0 (0.0%)");
717 gtk_box_pack_start(GTK_BOX(main_vb), ipx_lb, FALSE, FALSE, 3);
718 gtk_widget_show(ipx_lb);
720 vines_lb = gtk_label_new("VINES: 0 (0.0%)");
721 gtk_box_pack_start(GTK_BOX(main_vb), vines_lb, FALSE, FALSE, 3);
722 gtk_widget_show(vines_lb);
724 other_lb = gtk_label_new("Other: 0 (0.0%)");
725 gtk_box_pack_start(GTK_BOX(main_vb), other_lb, FALSE, FALSE, 3);
726 gtk_widget_show(other_lb);
728 /* allow user to either click a stop button, or the close button on
729 the window to stop a capture in progress. */
730 stop_bt = gtk_button_new_with_label ("Stop");
731 gtk_signal_connect(GTK_OBJECT(stop_bt), "clicked",
732 GTK_SIGNAL_FUNC(capture_stop_cb), (gpointer) &ld);
733 gtk_signal_connect(GTK_OBJECT(cap_w), "delete_event",
734 GTK_SIGNAL_FUNC(capture_delete_cb), (gpointer) &ld);
735 gtk_box_pack_end(GTK_BOX(main_vb), stop_bt, FALSE, FALSE, 3);
736 GTK_WIDGET_SET_FLAGS(stop_bt, GTK_CAN_DEFAULT);
737 gtk_widget_grab_default(stop_bt);
738 GTK_WIDGET_SET_FLAGS(stop_bt, GTK_CAN_DEFAULT);
739 gtk_widget_grab_default(stop_bt);
740 gtk_widget_show(stop_bt);
742 gtk_widget_show(cap_w);
745 upd_time = time(NULL);
747 pcap_fd = pcap_fileno(pch);
750 while (gtk_events_pending()) gtk_main_iteration();
753 * Sigh. The semantics of the read timeout argument to
754 * "pcap_open_live()" aren't particularly well specified by
755 * the "pcap" man page - at least with the BSD BPF code, the
756 * intent appears to be, at least in part, a way of cutting
757 * down the number of reads done on a capture, by blocking
758 * until the buffer fills or a timer expires - and the Linux
759 * libpcap doesn't actually support it, so we can't use it
760 * to break out of the "pcap_dispatch()" every 1/4 of a second
763 * Thus, on Linux, we do a "select()" on the file descriptor for the
764 * capture, with a timeout of CAP_READ_TIMEOUT milliseconds, or
765 * CAP_READ_TIMEOUT*1000 microseconds.
768 FD_SET(pcap_fd, &set1);
770 timeout.tv_usec = CAP_READ_TIMEOUT*1000;
771 if (select(pcap_fd+1, &set1, NULL, NULL, &timeout) != 0) {
773 * "select()" says we can read from it without blocking; go for
776 inpkts = pcap_dispatch(pch, 1, capture_pcap_cb, (u_char *) &ld);
780 inpkts = pcap_dispatch(pch, 1, capture_pcap_cb, (u_char *) &ld);
783 ld.sync_packets += inpkts;
784 /* Only update once a second so as not to overload slow displays */
785 cur_time = time(NULL);
786 if (cur_time > upd_time) {
789 sprintf(label_str, "Count: %d", ld.counts.total);
790 gtk_label_set(GTK_LABEL(count_lb), label_str);
792 sprintf(label_str, "TCP: %d (%.1f%%)", ld.counts.tcp,
793 pct(ld.counts.tcp, ld.counts.total));
794 gtk_label_set(GTK_LABEL(tcp_lb), label_str);
796 sprintf(label_str, "UDP: %d (%.1f%%)", ld.counts.udp,
797 pct(ld.counts.udp, ld.counts.total));
798 gtk_label_set(GTK_LABEL(udp_lb), label_str);
800 sprintf(label_str, "ICMP: %d (%.1f%%)", ld.counts.icmp,
801 pct(ld.counts.icmp, ld.counts.total));
802 gtk_label_set(GTK_LABEL(icmp_lb), label_str);
804 sprintf(label_str, "OSPF: %d (%.1f%%)", ld.counts.ospf,
805 pct(ld.counts.ospf, ld.counts.total));
806 gtk_label_set(GTK_LABEL(ospf_lb), label_str);
808 sprintf(label_str, "GRE: %d (%.1f%%)", ld.counts.gre,
809 pct(ld.counts.gre, ld.counts.total));
810 gtk_label_set(GTK_LABEL(gre_lb), label_str);
812 sprintf(label_str, "NetBIOS: %d (%.1f%%)", ld.counts.netbios,
813 pct(ld.counts.netbios, ld.counts.total));
814 gtk_label_set(GTK_LABEL(netbios_lb), label_str);
816 sprintf(label_str, "IPX: %d (%.1f%%)", ld.counts.ipx,
817 pct(ld.counts.ipx, ld.counts.total));
818 gtk_label_set(GTK_LABEL(ipx_lb), label_str);
820 sprintf(label_str, "VINES: %d (%.1f%%)", ld.counts.vines,
821 pct(ld.counts.vines, ld.counts.total));
822 gtk_label_set(GTK_LABEL(vines_lb), label_str);
824 sprintf(label_str, "Other: %d (%.1f%%)", ld.counts.other,
825 pct(ld.counts.other, ld.counts.total));
826 gtk_label_set(GTK_LABEL(other_lb), label_str);
828 /* do sync here, too */
829 fflush(wtap_dump_file(ld.pdh));
830 if (capture_child && ld.sync_packets) {
831 /* This is the child process for a sync mode capture, so send
832 our parent a message saying we've written out "ld.sync_packets"
833 packets to the capture file. */
835 sprintf(tmp, "%d*", ld.sync_packets);
836 write(1, tmp, strlen(tmp));
842 if (!wtap_dump_close(ld.pdh, &err)) {
843 /* XXX - in fork mode, this may not pop up, or, if it does,
844 it may disappear as soon as we exit.
846 We should have the parent process, while it's reading
847 the packet count update messages, catch error messages
848 and pop up a message box if it sees one. */
851 case WTAP_ERR_CANT_CLOSE:
852 simple_dialog(ESD_TYPE_WARN, NULL,
853 "The file to which the capture was being saved"
854 " couldn't be closed for some unknown reason.");
857 case WTAP_ERR_SHORT_WRITE:
858 simple_dialog(ESD_TYPE_WARN, NULL,
859 "Not all the data could be written to the file"
860 " to which the capture was being saved.");
864 simple_dialog(ESD_TYPE_WARN, NULL,
865 "The file to which the capture was being"
866 " saved (\"%s\") could not be closed: %s.",
867 cf.save_file, wtap_strerror(err));
873 gtk_grab_remove(GTK_WIDGET(cap_w));
874 gtk_widget_destroy(GTK_WIDGET(cap_w));
879 /* We couldn't even start the capture, so get rid of the capture
881 unlink(cf.save_file); /* silently ignore error */
882 g_free(cf.save_file);
885 /* This is the child process for a sync mode capture.
886 Send the error message to our parent, so they can display a
887 dialog box containing it. */
888 send_errmsg_to_parent(errmsg);
890 /* Display the dialog box ourselves; there's no parent. */
891 simple_dialog(ESD_TYPE_WARN, NULL, errmsg);
900 send_errmsg_to_parent(const char *errmsg)
902 int msglen = strlen(errmsg);
905 sprintf(lenbuf, "%u;", msglen);
906 write(1, lenbuf, strlen(lenbuf));
907 write(1, errmsg, msglen);
911 pct(gint num, gint denom) {
913 return (float) num * 100.0 / (float) denom;
920 capture_delete_cb(GtkWidget *w, GdkEvent *event, gpointer data) {
921 capture_stop_cb(NULL, data);
925 capture_stop_cb(GtkWidget *w, gpointer data) {
926 loop_data *ld = (loop_data *) data;
932 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
934 struct wtap_pkthdr whdr;
935 loop_data *ld = (loop_data *) user;
938 if ((++ld->counts.total >= ld->max) && (ld->max > 0))
943 /* "phdr->ts" may not necessarily be a "struct timeval" - it may
944 be a "struct bpf_timeval", with member sizes wired to 32
945 bits - and we may go that way ourselves in the future, so
946 copy the members individually. */
947 whdr.ts.tv_sec = phdr->ts.tv_sec;
948 whdr.ts.tv_usec = phdr->ts.tv_usec;
949 whdr.caplen = phdr->caplen;
950 whdr.len = phdr->len;
951 whdr.pkt_encap = ld->linktype;
953 /* XXX - do something if this fails */
954 wtap_dump(ld->pdh, &whdr, pd, &err);
957 /* Set the initial payload to the packet length, and the initial
958 captured payload to the capture length (other protocols may
959 reduce them if their headers say they're less). */
961 pi.captured_len = phdr->caplen;
963 switch (ld->linktype) {
964 case WTAP_ENCAP_ETHERNET:
965 capture_eth(pd, 0, &ld->counts);
967 case WTAP_ENCAP_FDDI:
968 case WTAP_ENCAP_FDDI_BITSWAPPED:
969 capture_fddi(pd, &ld->counts);
972 capture_tr(pd, 0, &ld->counts);
974 case WTAP_ENCAP_NULL:
975 capture_null(pd, &ld->counts);
978 capture_ppp(pd, &ld->counts);
980 case WTAP_ENCAP_RAW_IP:
981 capture_raw(pd, &ld->counts);
983 /* XXX - FreeBSD may append 4-byte ATM pseudo-header to DLT_ATM_RFC1483,
984 with LLC header following; we should implement it at some
989 #endif /* HAVE_LIBPCAP */