2 * Routines for packet capture windows
4 * $Id: capture.c,v 1.91 2000/01/23 08:55:30 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>
58 #ifdef HAVE_SYS_SOCKET_H
59 #include <sys/socket.h>
62 #ifdef HAVE_SYS_IOCTL_H
63 #include <sys/ioctl.h>
73 #ifdef NEED_SNPRINTF_H
79 # include "snprintf.h"
87 #include "gtk/gtkglobals.h"
92 #include "simple_dialog.h"
96 int sync_mode; /* fork a child to do the capture, and sync between them */
97 static int sync_pipe[2]; /* used to sync father */
98 int quit_after_cap; /* Makes a "capture only mode". Implies -k */
99 gboolean capture_child; /* if this is the child for "-S" */
100 static guint cap_input_id;
102 static void cap_file_input_cb(gpointer, gint, GdkInputCondition);
103 static void capture_stop_cb(GtkWidget *, gpointer);
104 static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
106 static float pct(gint, gint);
108 typedef struct _loop_data {
113 packet_counts counts;
117 /* Open a specified file, or create a temporary file, and start a capture
118 to the file in question. */
120 do_capture(char *capfile_name)
123 gboolean is_tempfile;
129 int capture_succeeded;
131 if (capfile_name != NULL) {
132 /* Try to open/create the specified file for use as a capture buffer. */
133 cf.save_file_fd = open(capfile_name, O_RDWR|O_TRUNC|O_CREAT, 0600);
136 /* Choose a random name for the capture buffer */
137 cf.save_file_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
138 capfile_name = g_strdup(tmpname);
141 if (cf.save_file_fd == -1) {
142 simple_dialog(ESD_TYPE_WARN, NULL,
143 "The file to which the capture would be saved (\"%s\")"
144 "could not be opened: %s.", capfile_name, strerror(errno));
147 close_cap_file(&cf, info_bar);
148 g_assert(cf.save_file == NULL);
149 cf.save_file = capfile_name;
151 if (sync_mode) { /* use fork() for capture */
154 char scount[24]; /* need a constant for len of numbers */
155 char save_file_fd[24];
157 sprintf(ssnap,"%d",cf.snap); /* in lieu of itoa */
158 sprintf(scount,"%d",cf.count);
159 sprintf(save_file_fd,"%d",cf.save_file_fd);
160 signal(SIGCHLD, SIG_IGN);
162 if ((fork_child = fork()) == 0) {
164 * Child process - run Ethereal with the right arguments to make
165 * it just pop up the live capture dialog box and capture with
166 * the specified capture parameters, writing to the specified file.
168 * args: -i interface specification
170 * -W file descriptor to write
171 * -c count to capture
174 * -f "filter expression"
179 execlp(ethereal_path, CHILD_NAME, "-i", cf.iface,
180 "-w", cf.save_file, "-W", save_file_fd,
181 "-c", scount, "-s", ssnap,
182 "-m", medium_font, "-b", bold_font,
183 (cf.cfilter == NULL)? 0 : "-f",
184 (cf.cfilter == NULL)? 0 : cf.cfilter,
187 /* Parent process - read messages from the child process over the
191 /* Read a byte count from "sync_pipe[0]", terminated with a
192 colon; if the count is 0, the child process created the
193 capture file and we should start reading from it, otherwise
194 the capture couldn't start and the count is a count of bytes
195 of error message, and we should display the message. */
198 i = read(sync_pipe[0], &c, 1);
200 /* EOF - the child process died.
201 Close the read side of the sync pipe, remove the capture file,
202 and report the failure.
203 XXX - reap the child process and report the status in detail. */
205 unlink(cf.save_file);
206 g_free(cf.save_file);
208 simple_dialog(ESD_TYPE_WARN, NULL, "Capture child process died");
214 /* Child process handed us crap.
215 Close the read side of the sync pipe, remove the capture file,
216 and report the failure. */
218 unlink(cf.save_file);
219 g_free(cf.save_file);
221 simple_dialog(ESD_TYPE_WARN, NULL,
222 "Capture child process sent us a bad message");
225 byte_count = byte_count*10 + c - '0';
227 if (byte_count == 0) {
228 /* Success. Open the capture file, and set up to read it. */
229 err = start_tail_cap_file(cf.save_file, is_tempfile, &cf);
231 /* We were able to open and set up to read the capture file;
232 arrange that our callback be called whenever it's possible
233 to read from the sync pipe, so that it's called when
234 the child process wants to tell us something. */
235 cap_input_id = gtk_input_add_full(sync_pipe[0],
242 /* We weren't able to open the capture file; complain, and
243 close the sync pipe. */
244 simple_dialog(ESD_TYPE_WARN, NULL,
245 file_open_error_message(err, FALSE), cf.save_file);
247 /* Close the sync pipe. */
250 /* Don't unlink the save file - leave it around, for debugging
252 g_free(cf.save_file);
256 /* Failure - the child process sent us a message indicating
257 what the problem was. */
258 msg = g_malloc(byte_count + 1);
260 simple_dialog(ESD_TYPE_WARN, NULL,
261 "Capture child process failed, but its error message was too big.");
263 i = read(sync_pipe[0], msg, byte_count);
265 simple_dialog(ESD_TYPE_WARN, NULL,
266 "Capture child process failed: Error %s reading its error message.",
269 simple_dialog(ESD_TYPE_WARN, NULL,
270 "Capture child process failed: EOF reading its error message.");
272 simple_dialog(ESD_TYPE_WARN, NULL, msg);
275 /* Close the sync pipe. */
278 /* Get rid of the save file - the capture never started. */
279 unlink(cf.save_file);
280 g_free(cf.save_file);
287 capture_succeeded = capture();
288 if (quit_after_cap) {
289 /* DON'T unlink the save file. Presumably someone wants it. */
292 if (capture_succeeded) {
293 /* Capture succeeded; read in the capture file. */
294 if ((err = open_cap_file(cf.save_file, is_tempfile, &cf)) == 0) {
295 /* Set the read filter to NULL. */
297 err = read_cap_file(&cf);
300 /* We're not doing a capture any more, so we don't have a save
302 g_free(cf.save_file);
307 /* There's stuff to read from the sync pipe, meaning the child has sent
308 us a message, or the sync pipe has closed, meaning the child has
309 closed it (perhaps because it exited). */
311 cap_file_input_cb(gpointer data, gint source, GdkInputCondition condition)
313 capture_file *cf = (capture_file *)data;
314 char buffer[256+1], *p = buffer, *q = buffer;
317 gboolean exit_loop = FALSE;
323 char sigmsg_buf[6+1+3+1];
326 /* avoid reentrancy problems and stack overflow */
327 gtk_input_remove(cap_input_id);
329 if ((nread = read(sync_pipe[0], buffer, 256)) <= 0) {
330 /* The child has closed the sync pipe, meaning it's not going to be
331 capturing any more packets. Pick up its exit status, and
332 complain if it died of a signal. */
333 if (wait(&wstatus) != -1) {
334 /* XXX - are there any platforms on which we can run that *don't*
335 support POSIX.1's <sys/wait.h> and macros therein? */
336 wsignal = wstatus & 0177;
338 if (wstatus == 0177) {
339 /* It stopped, rather than exiting. "Should not happen." */
341 wsignal = (wstatus >> 8) & 0xFF;
345 coredumped = " - core dumped";
355 sigmsg = "Interrupted";
363 sigmsg = "Illegal instruction";
367 sigmsg = "Trace trap";
375 sigmsg = "Arithmetic exception";
383 sigmsg = "Bus error";
387 sigmsg = "Segmentation violation";
390 /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO
391 Linux is POSIX compliant. These are not POSIX-defined signals ---
392 ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
394 ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
395 were omitted from POSIX.1 because their behavior is
396 implementation dependent and could not be adequately catego-
397 rized. Conforming implementations may deliver these sig-
398 nals, but must document the circumstances under which they
399 are delivered and note any restrictions concerning their
405 sigmsg = "Bad system call";
410 sigmsg = "Broken pipe";
414 sigmsg = "Alarm clock";
418 sigmsg = "Terminated";
422 sprintf(sigmsg_buf, "Signal %d", wsignal);
426 simple_dialog(ESD_TYPE_WARN, NULL,
427 "Child capture process %s: %s%s", msg, sigmsg, coredumped);
431 /* Read what remains of the capture file, and finish the capture.
432 XXX - do something if this fails? */
433 err = finish_tail_cap_file(cf);
435 /* We're not doing a capture any more, so we don't have a save
437 g_free(cf->save_file);
438 cf->save_file = NULL;
443 buffer[nread] = '\0';
446 /* look for (possibly multiple) '*' */
454 /* XXX should handle the case of a pipe full (i.e. no star found) */
463 /* Read from the capture file the number of records the child told us
465 XXX - do something if this fails? */
466 err = continue_tail_cap_file(cf, to_read);
468 /* restore pipe handler */
469 cap_input_id = gtk_input_add_full (sync_pipe[0],
478 * Timeout, in milliseconds, for reads from the stream of captured packets.
480 #define CAP_READ_TIMEOUT 250
482 /* Do the low-level work of a capture.
483 Returns TRUE if it succeeds, FALSE otherwise. */
487 GtkWidget *cap_w, *main_vb, *count_lb, *tcp_lb, *udp_lb, *icmp_lb,
488 *ospf_lb, *gre_lb, *netbios_lb, *ipx_lb, *vines_lb, *other_lb, *stop_bt;
490 gchar err_str[PCAP_ERRBUF_SIZE], label_str[32];
492 bpf_u_int32 netnum, netmask;
493 time_t upd_time, cur_time;
498 struct timeval timeout;
505 ld.linktype = WTAP_ENCAP_UNKNOWN;
513 ld.counts.netbios = 0;
518 /* Open the network interface to capture from it. */
519 pch = pcap_open_live(cf.iface, cf.snap, 1, CAP_READ_TIMEOUT, err_str);
522 /* Well, we couldn't start the capture.
523 If this is a child process that does the capturing in sync
524 mode or fork mode, it shouldn't do any UI stuff until we pop up the
525 capture-progress window, and, since we couldn't start the
526 capture, we haven't popped it up. */
527 if (!capture_child) {
528 while (gtk_events_pending()) gtk_main_iteration();
530 snprintf(errmsg, sizeof errmsg,
531 "The capture session could not be initiated (%s).\n"
532 "Please check to make sure you have sufficient permissions, and that\n"
533 "you have the proper interface specified.", err_str);
538 /* A capture filter was specified; set it up. */
539 if (pcap_lookupnet (cf.iface, &netnum, &netmask, err_str) < 0) {
540 snprintf(errmsg, sizeof errmsg,
541 "Can't use filter: Couldn't obtain netmask info (%s).", err_str);
544 if (pcap_compile(pch, &cf.fcode, cf.cfilter, 1, netmask) < 0) {
545 snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
549 if (pcap_setfilter(pch, &cf.fcode) < 0) {
550 snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
556 /* Set up to write to the capture file. */
557 ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(pch));
558 if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
559 strcpy(errmsg, "The network you're capturing from is of a type"
560 " that Ethereal doesn't support.");
563 ld.pdh = wtap_dump_fdopen(cf.save_file_fd, WTAP_FILE_PCAP,
564 ld.linktype, pcap_snapshot(pch), &err);
566 if (ld.pdh == NULL) {
567 /* We couldn't set up to write to the capture file. */
570 case WTAP_ERR_CANT_OPEN:
571 strcpy(errmsg, "The file to which the capture would be saved"
572 " couldn't be created for some unknown reason.");
575 case WTAP_ERR_SHORT_WRITE:
576 strcpy(errmsg, "A full header couldn't be written to the file"
577 " to which the capture would be saved.");
582 sprintf(errmsg, "The file to which the capture would be"
583 " saved (\"%s\") could not be opened: Error %d.",
586 sprintf(errmsg, "The file to which the capture would be"
587 " saved (\"%s\") could not be opened: %s.",
588 cf.save_file, strerror(err));
596 /* Well, we should be able to start capturing.
598 This is the child process for a sync mode capture, so sync out
599 the capture file, so the header makes it to the file system,
600 and send a "capture started successfully and capture file created"
601 message to our parent so that they'll open the capture file and
602 update its windows to indicate that we have a live capture in
604 fflush(wtap_dump_file(ld.pdh));
608 cap_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
609 gtk_window_set_title(GTK_WINDOW(cap_w), "Ethereal: Capture / Playback");
611 /* Container for capture display widgets */
612 main_vb = gtk_vbox_new(FALSE, 1);
613 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
614 gtk_container_add(GTK_CONTAINER(cap_w), main_vb);
615 gtk_widget_show(main_vb);
617 count_lb = gtk_label_new("Count: 0");
618 gtk_box_pack_start(GTK_BOX(main_vb), count_lb, FALSE, FALSE, 3);
619 gtk_widget_show(count_lb);
621 tcp_lb = gtk_label_new("TCP: 0 (0.0%)");
622 gtk_box_pack_start(GTK_BOX(main_vb), tcp_lb, FALSE, FALSE, 3);
623 gtk_widget_show(tcp_lb);
625 udp_lb = gtk_label_new("UDP: 0 (0.0%)");
626 gtk_box_pack_start(GTK_BOX(main_vb), udp_lb, FALSE, FALSE, 3);
627 gtk_widget_show(udp_lb);
629 icmp_lb = gtk_label_new("ICMP: 0 (0.0%)");
630 gtk_box_pack_start(GTK_BOX(main_vb), icmp_lb, FALSE, FALSE, 3);
631 gtk_widget_show(icmp_lb);
633 ospf_lb = gtk_label_new("OSPF: 0 (0.0%)");
634 gtk_box_pack_start(GTK_BOX(main_vb), ospf_lb, FALSE, FALSE, 3);
635 gtk_widget_show(ospf_lb);
637 gre_lb = gtk_label_new("GRE: 0 (0.0%)");
638 gtk_box_pack_start(GTK_BOX(main_vb), gre_lb, FALSE, FALSE, 3);
639 gtk_widget_show(gre_lb);
641 netbios_lb = gtk_label_new("NetBIOS: 0 (0.0%)");
642 gtk_box_pack_start(GTK_BOX(main_vb), netbios_lb, FALSE, FALSE, 3);
643 gtk_widget_show(netbios_lb);
645 ipx_lb = gtk_label_new("IPX: 0 (0.0%)");
646 gtk_box_pack_start(GTK_BOX(main_vb), ipx_lb, FALSE, FALSE, 3);
647 gtk_widget_show(ipx_lb);
649 vines_lb = gtk_label_new("VINES: 0 (0.0%)");
650 gtk_box_pack_start(GTK_BOX(main_vb), vines_lb, FALSE, FALSE, 3);
651 gtk_widget_show(vines_lb);
653 other_lb = gtk_label_new("Other: 0 (0.0%)");
654 gtk_box_pack_start(GTK_BOX(main_vb), other_lb, FALSE, FALSE, 3);
655 gtk_widget_show(other_lb);
657 stop_bt = gtk_button_new_with_label ("Stop");
658 gtk_signal_connect(GTK_OBJECT(stop_bt), "clicked",
659 GTK_SIGNAL_FUNC(capture_stop_cb), (gpointer) &ld);
660 gtk_box_pack_end(GTK_BOX(main_vb), stop_bt, FALSE, FALSE, 3);
661 GTK_WIDGET_SET_FLAGS(stop_bt, GTK_CAN_DEFAULT);
662 gtk_widget_grab_default(stop_bt);
663 GTK_WIDGET_SET_FLAGS(stop_bt, GTK_CAN_DEFAULT);
664 gtk_widget_grab_default(stop_bt);
665 gtk_widget_show(stop_bt);
667 gtk_widget_show(cap_w);
670 upd_time = time(NULL);
672 pcap_fd = pcap_fileno(pch);
675 while (gtk_events_pending()) gtk_main_iteration();
678 * Sigh. The semantics of the read timeout argument to
679 * "pcap_open_live()" aren't particularly well specified by
680 * the "pcap" man page - at least with the BSD BPF code, the
681 * intent appears to be, at least in part, a way of cutting
682 * down the number of reads done on a capture, by blocking
683 * until the buffer fills or a timer expires - and the Linux
684 * libpcap doesn't actually support it, so we can't use it
685 * to break out of the "pcap_dispatch()" every 1/4 of a second
688 * Thus, on Linux, we do a "select()" on the file descriptor for the
689 * capture, with a timeout of CAP_READ_TIMEOUT milliseconds, or
690 * CAP_READ_TIMEOUT*1000 microseconds.
693 FD_SET(pcap_fd, &set1);
695 timeout.tv_usec = CAP_READ_TIMEOUT*1000;
696 if (select(pcap_fd+1, &set1, NULL, NULL, &timeout) != 0) {
698 * "select()" says we can read from it without blocking; go for
701 inpkts = pcap_dispatch(pch, 1, capture_pcap_cb, (u_char *) &ld);
705 inpkts = pcap_dispatch(pch, 1, capture_pcap_cb, (u_char *) &ld);
708 ld.sync_packets += inpkts;
709 /* Only update once a second so as not to overload slow displays */
710 cur_time = time(NULL);
711 if (cur_time > upd_time) {
714 sprintf(label_str, "Count: %d", ld.counts.total);
715 gtk_label_set(GTK_LABEL(count_lb), label_str);
717 sprintf(label_str, "TCP: %d (%.1f%%)", ld.counts.tcp,
718 pct(ld.counts.tcp, ld.counts.total));
719 gtk_label_set(GTK_LABEL(tcp_lb), label_str);
721 sprintf(label_str, "UDP: %d (%.1f%%)", ld.counts.udp,
722 pct(ld.counts.udp, ld.counts.total));
723 gtk_label_set(GTK_LABEL(udp_lb), label_str);
725 sprintf(label_str, "ICMP: %d (%.1f%%)", ld.counts.icmp,
726 pct(ld.counts.icmp, ld.counts.total));
727 gtk_label_set(GTK_LABEL(icmp_lb), label_str);
729 sprintf(label_str, "OSPF: %d (%.1f%%)", ld.counts.ospf,
730 pct(ld.counts.ospf, ld.counts.total));
731 gtk_label_set(GTK_LABEL(ospf_lb), label_str);
733 sprintf(label_str, "GRE: %d (%.1f%%)", ld.counts.gre,
734 pct(ld.counts.gre, ld.counts.total));
735 gtk_label_set(GTK_LABEL(gre_lb), label_str);
737 sprintf(label_str, "NetBIOS: %d (%.1f%%)", ld.counts.netbios,
738 pct(ld.counts.netbios, ld.counts.total));
739 gtk_label_set(GTK_LABEL(netbios_lb), label_str);
741 sprintf(label_str, "IPX: %d (%.1f%%)", ld.counts.ipx,
742 pct(ld.counts.ipx, ld.counts.total));
743 gtk_label_set(GTK_LABEL(ipx_lb), label_str);
745 sprintf(label_str, "VINES: %d (%.1f%%)", ld.counts.vines,
746 pct(ld.counts.vines, ld.counts.total));
747 gtk_label_set(GTK_LABEL(vines_lb), label_str);
749 sprintf(label_str, "Other: %d (%.1f%%)", ld.counts.other,
750 pct(ld.counts.other, ld.counts.total));
751 gtk_label_set(GTK_LABEL(other_lb), label_str);
753 /* do sync here, too */
754 fflush(wtap_dump_file(ld.pdh));
755 if (capture_child && ld.sync_packets) {
756 /* This is the child process for a sync mode capture, so send
757 our parent a message saying we've written out "ld.sync_packets"
758 packets to the capture file. */
760 sprintf(tmp, "%d*", ld.sync_packets);
761 write(1, tmp, strlen(tmp));
767 if (!wtap_dump_close(ld.pdh, &err)) {
768 /* XXX - in fork mode, this may not pop up, or, if it does,
769 it may disappear as soon as we exit.
771 We should have the parent process, while it's reading
772 the packet count update messages, catch error messages
773 and pop up a message box if it sees one. */
776 case WTAP_ERR_CANT_CLOSE:
777 simple_dialog(ESD_TYPE_WARN, NULL,
778 "The file to which the capture was being saved"
779 " couldn't be closed for some unknown reason.");
782 case WTAP_ERR_SHORT_WRITE:
783 simple_dialog(ESD_TYPE_WARN, NULL,
784 "Not all the data could be written to the file"
785 " to which the capture was being saved.");
789 simple_dialog(ESD_TYPE_WARN, NULL,
790 "The file to which the capture was being"
791 " saved (\"%s\") could not be closed: %s.",
792 cf.save_file, wtap_strerror(err));
798 gtk_grab_remove(GTK_WIDGET(cap_w));
799 gtk_widget_destroy(GTK_WIDGET(cap_w));
804 /* We couldn't even start the capture, so get rid of the capture
806 unlink(cf.save_file); /* silently ignore error */
807 g_free(cf.save_file);
810 /* This is the child process for a sync mode capture.
811 Send the error message to our parent, so they can display a
812 dialog box containing it. */
813 int msglen = strlen(errmsg);
815 sprintf(lenbuf, "%u;", msglen);
816 write(1, lenbuf, strlen(lenbuf));
817 write(1, errmsg, msglen);
819 /* Display the dialog box ourselves; there's no parent. */
820 simple_dialog(ESD_TYPE_WARN, NULL, errmsg);
829 pct(gint num, gint denom) {
831 return (float) num * 100.0 / (float) denom;
838 capture_stop_cb(GtkWidget *w, gpointer data) {
839 loop_data *ld = (loop_data *) data;
845 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
847 struct wtap_pkthdr whdr;
848 loop_data *ld = (loop_data *) user;
851 if ((++ld->counts.total >= ld->max) && (ld->max > 0))
857 whdr.caplen = phdr->caplen;
858 whdr.len = phdr->len;
859 whdr.pkt_encap = ld->linktype;
861 /* XXX - do something if this fails */
862 wtap_dump(ld->pdh, &whdr, pd, &err);
865 /* Set the initial payload to the packet length, and the initial
866 captured payload to the capture length (other protocols may
867 reduce them if their headers say they're less). */
869 pi.captured_len = phdr->caplen;
871 switch (ld->linktype) {
872 case WTAP_ENCAP_ETHERNET:
873 capture_eth(pd, 0, &ld->counts);
875 case WTAP_ENCAP_FDDI:
876 case WTAP_ENCAP_FDDI_BITSWAPPED:
877 capture_fddi(pd, &ld->counts);
880 capture_tr(pd, 0, &ld->counts);
882 case WTAP_ENCAP_NULL:
883 capture_null(pd, &ld->counts);
886 capture_ppp(pd, &ld->counts);
888 case WTAP_ENCAP_RAW_IP:
889 capture_raw(pd, &ld->counts);
891 /* XXX - FreeBSD may append 4-byte ATM pseudo-header to DLT_ATM_RFC1483,
892 with LLC header following; we should implement it at some
897 #endif /* HAVE_LIBPCAP */