2 * Routines for packet capture windows
4 * $Id: capture.c,v 1.65 1999/09/09 02:42:22 gram 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>
52 #ifdef HAVE_SYS_SOCKET_H
53 #include <sys/socket.h>
56 #ifdef HAVE_SYS_IOCTL_H
57 #include <sys/ioctl.h>
67 #ifdef NEED_SNPRINTF_H
73 # include "snprintf.h"
76 #ifdef HAVE_SYS_SOCKIO_H
77 # include <sys/sockio.h>
88 extern capture_file cf;
89 extern GtkWidget *info_bar;
90 extern guint file_ctx;
92 extern gchar *ethereal_path;
93 extern gchar *medium_font;
94 extern gchar *bold_font;
96 extern int sync_pipe[];
98 extern int sigusr2_received;
99 extern int quit_after_cap;
101 /* Capture callback data keys */
102 #define E_CAP_IFACE_KEY "cap_iface"
103 #define E_CAP_FILT_KEY "cap_filter"
104 #define E_CAP_COUNT_KEY "cap_count"
105 #define E_CAP_OPEN_KEY "cap_open"
106 #define E_CAP_SNAP_KEY "cap_snap"
108 /* Capture filter key */
109 #define E_CAP_FILT_TE_KEY "cap_filt_te"
111 static void search_for_if_cb(gpointer data, gpointer user_data);
112 static void free_if_cb(gpointer data, gpointer user_data);
113 static void capture_prep_ok_cb(GtkWidget *, gpointer);
114 static void capture_prep_close_cb(GtkWidget *, gpointer);
115 static float pct(gint, gint);
116 static void capture_stop_cb(GtkWidget *, gpointer);
117 static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
120 struct search_user_data {
126 get_interface_list() {
128 gint nonloopback_pos = 0;
129 struct ifreq *ifr, *last;
131 struct ifreq ifrflags;
132 int sock = socket(AF_INET, SOCK_DGRAM, 0);
133 struct search_user_data user_data;
135 gchar err_str[PCAP_ERRBUF_SIZE];
139 simple_dialog(ESD_TYPE_WARN, NULL,
140 "Can't list interfaces: error opening socket.");
144 /* Since we have to grab the interface list all at once, we'll make
146 ifc.ifc_len = 1024 * sizeof(struct ifreq);
147 ifc.ifc_buf = malloc(ifc.ifc_len);
149 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0 ||
150 ifc.ifc_len < sizeof(struct ifreq))
152 simple_dialog(ESD_TYPE_WARN, NULL,
153 "Can't list interfaces: SIOCGIFCONF error: %s", strerror(errno));
157 ifr = (struct ifreq *) ifc.ifc_req;
158 last = (struct ifreq *) ((char *) ifr + ifc.ifc_len);
162 * Skip addresses that begin with "dummy", or that include a ":"
163 * (the latter are Solaris virtuals).
165 if (strncmp(ifr->ifr_name, "dummy", 5) == 0 ||
166 strchr(ifr->ifr_name, ':') != NULL)
170 * If we already have this interface name on the list, don't add
171 * it (SIOCGIFCONF returns, at least on BSD-flavored systems, one
172 * entry per interface *address*; if an interface has multiple
173 * addresses, we get multiple entries for it).
175 user_data.name = ifr->ifr_name;
176 user_data.found = FALSE;
177 g_list_foreach(il, search_for_if_cb, &user_data);
182 * Get the interface flags.
184 memset(&ifrflags, 0, sizeof ifrflags);
185 strncpy(ifrflags.ifr_name, ifr->ifr_name, sizeof ifrflags.ifr_name);
186 if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
189 simple_dialog(ESD_TYPE_WARN, NULL,
190 "Can't list interfaces: SIOCGIFFLAGS error on %s: %s",
191 ifr->ifr_name, strerror(errno));
196 * Skip interfaces that aren't up.
198 if (!(ifrflags.ifr_flags & IFF_UP))
202 * Skip interfaces that we can't open with "libpcap".
204 pch = pcap_open_live(ifr->ifr_name, WTAP_MAX_PACKET_SIZE, 0, 0, err_str);
210 * If it's a loopback interface, add it at the end of the list,
211 * otherwise add it after the last non-loopback interface,
212 * so all loopback interfaces go at the end - we don't want a
213 * loopback interface to be the default capture device unless there
214 * are no non-loopback devices.
216 if ((ifrflags.ifr_flags & IFF_LOOPBACK) ||
217 strncmp(ifr->ifr_name, "lo", 2) == 0)
218 il = g_list_insert(il, g_strdup(ifr->ifr_name), -1);
220 il = g_list_insert(il, g_strdup(ifr->ifr_name), nonloopback_pos);
221 /* Insert the next non-loopback interface after this one. */
227 ifr = (struct ifreq *) ((char *) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
229 ifr = (struct ifreq *) ((char *) ifr + sizeof(struct ifreq));
237 simple_dialog(ESD_TYPE_WARN, NULL,
238 "There are no network interfaces that can be opened.\n"
239 "Please check to make sure you have sufficient permission\n"
240 "to capture packets.");
248 g_list_foreach(il, free_if_cb, NULL);
257 search_for_if_cb(gpointer data, gpointer user_data)
259 struct search_user_data *search_user_data = user_data;
261 if (strcmp((char *)data, search_user_data->name) == 0)
262 search_user_data->found = TRUE;
266 free_if_cb(gpointer data, gpointer user_data)
272 capture_prep_cb(GtkWidget *w, gpointer d) {
273 GtkWidget *cap_open_w, *if_cb, *if_lb,
274 *count_lb, *count_cb, *main_vb, *if_hb, *count_hb,
275 *filter_hb, *filter_bt, *filter_te, *caplen_hb,
276 *bbox, *ok_bt, *cancel_bt, *snap_lb,
279 GList *if_list, *count_list = NULL;
280 gchar *count_item1 = "0 (Infinite)", count_item2[16];
282 if_list = get_interface_list();
286 cap_open_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
287 gtk_window_set_title(GTK_WINDOW(cap_open_w), "Ethereal: Capture Preferences");
289 /* Container for each row of widgets */
290 main_vb = gtk_vbox_new(FALSE, 3);
291 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
292 gtk_container_add(GTK_CONTAINER(cap_open_w), main_vb);
293 gtk_widget_show(main_vb);
296 if_hb = gtk_hbox_new(FALSE, 3);
297 gtk_container_add(GTK_CONTAINER(main_vb), if_hb);
298 gtk_widget_show(if_hb);
300 if_lb = gtk_label_new("Interface:");
301 gtk_box_pack_start(GTK_BOX(if_hb), if_lb, FALSE, FALSE, 0);
302 gtk_widget_show(if_lb);
304 if_cb = gtk_combo_new();
305 gtk_combo_set_popdown_strings(GTK_COMBO(if_cb), if_list);
307 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), cf.iface);
309 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), if_list->data);
310 gtk_box_pack_start(GTK_BOX(if_hb), if_cb, FALSE, FALSE, 0);
311 gtk_widget_show(if_cb);
314 g_free(if_list->data);
315 if_list = g_list_remove_link(if_list, if_list);
319 count_hb = gtk_hbox_new(FALSE, 3);
320 gtk_container_add(GTK_CONTAINER(main_vb), count_hb);
321 gtk_widget_show(count_hb);
323 count_lb = gtk_label_new("Count:");
324 gtk_box_pack_start(GTK_BOX(count_hb), count_lb, FALSE, FALSE, 0);
325 gtk_widget_show(count_lb);
327 count_list = g_list_append(count_list, count_item1);
329 snprintf(count_item2, 15, "%d", cf.count);
330 count_list = g_list_append(count_list, count_item2);
333 count_cb = gtk_combo_new();
334 gtk_combo_set_popdown_strings(GTK_COMBO(count_cb), count_list);
335 gtk_box_pack_start(GTK_BOX(count_hb), count_cb, FALSE, FALSE, 0);
336 gtk_widget_show(count_cb);
339 count_list = g_list_remove_link(count_list, count_list);
342 filter_hb = gtk_hbox_new(FALSE, 3);
343 gtk_container_add(GTK_CONTAINER(main_vb), filter_hb);
344 gtk_widget_show(filter_hb);
346 filter_bt = gtk_button_new_with_label("Filter:");
347 gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked",
348 GTK_SIGNAL_FUNC(prefs_cb), (gpointer) E_PR_PG_FILTER);
349 gtk_box_pack_start(GTK_BOX(filter_hb), filter_bt, FALSE, TRUE, 0);
350 gtk_widget_show(filter_bt);
352 filter_te = gtk_entry_new();
353 if (cf.cfilter) gtk_entry_set_text(GTK_ENTRY(filter_te), cf.cfilter);
354 gtk_object_set_data(GTK_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
355 gtk_box_pack_start(GTK_BOX(filter_hb), filter_te, TRUE, TRUE, 0);
356 gtk_widget_show(filter_te);
358 /* Misc row: Capture file checkbox and snap spinbutton */
359 caplen_hb = gtk_hbox_new(FALSE, 3);
360 gtk_container_add(GTK_CONTAINER(main_vb), caplen_hb);
361 gtk_widget_show(caplen_hb);
363 snap_lb = gtk_label_new("Capture length");
364 gtk_misc_set_alignment(GTK_MISC(snap_lb), 0, 0.5);
365 gtk_box_pack_start(GTK_BOX(caplen_hb), snap_lb, FALSE, FALSE, 6);
366 gtk_widget_show(snap_lb);
368 adj = (GtkAdjustment *) gtk_adjustment_new((float) cf.snap,
369 MIN_PACKET_SIZE, WTAP_MAX_PACKET_SIZE, 1.0, 10.0, 0.0);
370 snap_sb = gtk_spin_button_new (adj, 0, 0);
371 gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (snap_sb), TRUE);
372 gtk_widget_set_usize (snap_sb, 80, 0);
373 gtk_box_pack_start (GTK_BOX(caplen_hb), snap_sb, FALSE, FALSE, 3);
374 gtk_widget_show(snap_sb);
376 /* Button row: OK and cancel buttons */
377 bbox = gtk_hbutton_box_new();
378 gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
379 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
380 gtk_container_add(GTK_CONTAINER(main_vb), bbox);
381 gtk_widget_show(bbox);
383 ok_bt = gtk_button_new_with_label ("OK");
384 gtk_signal_connect(GTK_OBJECT(ok_bt), "clicked",
385 GTK_SIGNAL_FUNC(capture_prep_ok_cb), GTK_OBJECT(cap_open_w));
386 GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT);
387 gtk_box_pack_start (GTK_BOX (bbox), ok_bt, TRUE, TRUE, 0);
388 gtk_widget_grab_default(ok_bt);
389 gtk_widget_show(ok_bt);
391 cancel_bt = gtk_button_new_with_label ("Cancel");
392 gtk_signal_connect(GTK_OBJECT(cancel_bt), "clicked",
393 GTK_SIGNAL_FUNC(capture_prep_close_cb), GTK_OBJECT(cap_open_w));
394 GTK_WIDGET_SET_FLAGS(cancel_bt, GTK_CAN_DEFAULT);
395 gtk_box_pack_start (GTK_BOX (bbox), cancel_bt, TRUE, TRUE, 0);
396 gtk_widget_show(cancel_bt);
398 /* Attach pointers to needed widgets to the capture prefs window/object */
399 gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_IFACE_KEY, if_cb);
400 gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_FILT_KEY, filter_te);
401 gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_COUNT_KEY, count_cb);
402 gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_SNAP_KEY, snap_sb);
404 gtk_widget_show(cap_open_w);
408 capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w) {
409 GtkWidget *if_cb, *filter_te, *count_cb, *snap_sb;
413 if_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_IFACE_KEY);
414 filter_te = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_FILT_KEY);
415 count_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_COUNT_KEY);
416 snap_sb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SNAP_KEY);
418 if (cf.iface) g_free(cf.iface);
420 g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry)));
422 filter_text = gtk_entry_get_text(GTK_ENTRY(filter_te));
423 if (cf.cfilter) g_free(cf.cfilter);
424 cf.cfilter = NULL; /* ead 06/16/99 */
425 if (filter_text && filter_text[0]) {
426 cf.cfilter = g_strdup(gtk_entry_get_text(GTK_ENTRY(filter_te)));
428 cf.count = atoi(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(count_cb)->entry)));
429 cf.snap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(snap_sb));
431 cf.snap = WTAP_MAX_PACKET_SIZE;
432 else if (cf.snap < MIN_PACKET_SIZE)
433 cf.snap = MIN_PACKET_SIZE;
435 gtk_widget_destroy(GTK_WIDGET(parent_w));
437 /* Choose a random name for the capture buffer */
438 if (cf.save_file && !cf.user_saved) {
439 unlink(cf.save_file); /* silently ignore error */
440 g_free(cf.save_file);
442 cf.save_file_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
443 cf.save_file = g_strdup(tmpname);
446 if( fork_mode ){ /* use fork() for capture */
449 char scount[24]; /* need a constant for len of numbers */
450 char save_file_fd[24];
453 sprintf(ssnap,"%d",cf.snap); /* in lieu of itoa */
454 sprintf(scount,"%d",cf.count);
455 sprintf(save_file_fd,"%d",cf.save_file_fd);
456 signal(SIGCHLD, SIG_IGN);
457 if (sync_mode) pipe(sync_pipe);
458 if((fork_child = fork()) == 0){
459 /* args: -k -- capture
460 * -i interface specification
462 * -W file descriptor to write
463 * -c count to capture
464 * -Q quit after capture (forces -k)
468 * -f "filter expression"
474 execlp(ethereal_path, "ethereal", "-k", "-Q", "-i", cf.iface,
475 "-w", cf.save_file, "-W", save_file_fd,
476 "-c", scount, "-s", ssnap, "-S",
477 "-m", medium_font, "-b", bold_font,
478 (cf.cfilter == NULL)? 0 : "-f",
479 (cf.cfilter == NULL)? 0 : cf.cfilter,
483 execlp(ethereal_path, "ethereal", "-k", "-Q", "-i", cf.iface,
484 "-w", cf.save_file, "-W", save_file_fd,
485 "-c", scount, "-s", ssnap,
486 "-m", medium_font, "-b", bold_font,
487 (cf.cfilter == NULL)? 0 : "-f",
488 (cf.cfilter == NULL)? 0 : cf.cfilter,
493 cf.filename = cf.save_file;
496 while (!sigusr2_received) {
497 struct timeval timeout = {1,0};
498 select(0, NULL, NULL, NULL, &timeout);
499 if (kill(fork_child, 0) == -1 && errno == ESRCH)
502 if (sigusr2_received) {
503 err = tail_cap_file(cf.save_file, &cf);
505 simple_dialog(ESD_TYPE_WARN, NULL,
506 file_open_error_message(err, FALSE), cf.save_file);
509 sigusr2_received = FALSE;
518 capture_prep_close_cb(GtkWidget *close_bt, gpointer parent_w)
520 gtk_grab_remove(GTK_WIDGET(parent_w));
521 gtk_widget_destroy(GTK_WIDGET(parent_w));
524 typedef struct _loop_data {
529 packet_counts counts;
535 GtkWidget *cap_w, *main_vb, *count_lb, *tcp_lb, *udp_lb, *icmp_lb,
536 *ospf_lb, *gre_lb, *netbios_lb, *other_lb, *stop_bt;
538 gchar err_str[PCAP_ERRBUF_SIZE], label_str[32];
540 bpf_u_int32 netnum, netmask;
541 time_t upd_time, cur_time;
544 char errmsg_errno[1024+1];
549 ld.linktype = WTAP_ENCAP_UNKNOWN;
556 ld.counts.netbios = 0;
560 close_cap_file(&cf, info_bar, file_ctx);
562 pch = pcap_open_live(cf.iface, cf.snap, 1, 250, err_str);
565 ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(pch));
566 if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
567 errmsg = "The network you're capturing from is of a type"
568 " that Ethereal doesn't support.";
571 ld.pdh = wtap_dump_fdopen(cf.save_file_fd, WTAP_FILE_PCAP,
572 ld.linktype, pcap_snapshot(pch), &err);
574 if (ld.pdh == NULL) { /* We have an error */
577 case WTAP_ERR_CANT_OPEN:
578 errmsg = "The file to which the capture would be saved"
579 " couldn't be created for some unknown reason.";
582 case WTAP_ERR_SHORT_WRITE:
583 errmsg = "A full header couldn't be written to the file"
584 " to which the capture would be saved.";
589 sprintf(errmsg_errno, "The file to which the capture would be"
590 " saved (\"%%s\") could not be opened: Error %d.",
593 sprintf(errmsg_errno, "The file to which the capture would be"
594 " saved (\"%%s\") could not be opened: %s.",
597 errmsg = errmsg_errno;
601 snprintf(err_str, PCAP_ERRBUF_SIZE, errmsg, cf.save_file);
602 simple_dialog(ESD_TYPE_WARN, NULL, err_str);
608 if (pcap_lookupnet (cf.iface, &netnum, &netmask, err_str) < 0) {
609 simple_dialog(ESD_TYPE_WARN, NULL,
610 "Can't use filter: Couldn't obtain netmask info (%s).", err_str);
611 wtap_dump_close(ld.pdh, NULL);
612 unlink(cf.save_file); /* silently ignore error */
615 } else if (pcap_compile(pch, &cf.fcode, cf.cfilter, 1, netmask) < 0) {
616 simple_dialog(ESD_TYPE_WARN, NULL, "Unable to parse filter string (%s).",
618 wtap_dump_close(ld.pdh, NULL);
619 unlink(cf.save_file); /* silently ignore error */
622 } else if (pcap_setfilter(pch, &cf.fcode) < 0) {
623 simple_dialog(ESD_TYPE_WARN, NULL, "Can't install filter (%s).",
625 wtap_dump_close(ld.pdh, NULL);
626 unlink(cf.save_file); /* silently ignore error */
633 /* Sync out the capture file, so the header makes it to the file
634 system, and signal our parent so that they'll open the capture
635 file and update its windows to indicate that we have a live
636 capture in progress. */
637 fflush(wtap_dump_file(ld.pdh));
638 kill(getppid(), SIGUSR2);
641 cap_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
642 gtk_window_set_title(GTK_WINDOW(cap_w), "Ethereal: Capture / Playback");
644 /* Container for capture display widgets */
645 main_vb = gtk_vbox_new(FALSE, 1);
646 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
647 gtk_container_add(GTK_CONTAINER(cap_w), main_vb);
648 gtk_widget_show(main_vb);
650 count_lb = gtk_label_new("Count: 0");
651 gtk_box_pack_start(GTK_BOX(main_vb), count_lb, FALSE, FALSE, 3);
652 gtk_widget_show(count_lb);
654 tcp_lb = gtk_label_new("TCP: 0 (0.0%)");
655 gtk_box_pack_start(GTK_BOX(main_vb), tcp_lb, FALSE, FALSE, 3);
656 gtk_widget_show(tcp_lb);
658 udp_lb = gtk_label_new("UDP: 0 (0.0%)");
659 gtk_box_pack_start(GTK_BOX(main_vb), udp_lb, FALSE, FALSE, 3);
660 gtk_widget_show(udp_lb);
662 icmp_lb = gtk_label_new("ICMP: 0 (0.0%)");
663 gtk_box_pack_start(GTK_BOX(main_vb), icmp_lb, FALSE, FALSE, 3);
664 gtk_widget_show(icmp_lb);
666 ospf_lb = gtk_label_new("OSPF: 0 (0.0%)");
667 gtk_box_pack_start(GTK_BOX(main_vb), ospf_lb, FALSE, FALSE, 3);
668 gtk_widget_show(ospf_lb);
670 gre_lb = gtk_label_new("GRE: 0 (0.0%)");
671 gtk_box_pack_start(GTK_BOX(main_vb), gre_lb, FALSE, FALSE, 3);
672 gtk_widget_show(gre_lb);
674 netbios_lb = gtk_label_new("NetBIOS: 0 (0.0%)");
675 gtk_box_pack_start(GTK_BOX(main_vb), netbios_lb, FALSE, FALSE, 3);
676 gtk_widget_show(netbios_lb);
678 other_lb = gtk_label_new("Other: 0 (0.0%)");
679 gtk_box_pack_start(GTK_BOX(main_vb), other_lb, FALSE, FALSE, 3);
680 gtk_widget_show(other_lb);
682 stop_bt = gtk_button_new_with_label ("Stop");
683 gtk_signal_connect(GTK_OBJECT(stop_bt), "clicked",
684 GTK_SIGNAL_FUNC(capture_stop_cb), (gpointer) &ld);
685 gtk_box_pack_end(GTK_BOX(main_vb), stop_bt, FALSE, FALSE, 3);
686 GTK_WIDGET_SET_FLAGS(stop_bt, GTK_CAN_DEFAULT);
687 gtk_widget_grab_default(stop_bt);
688 GTK_WIDGET_SET_FLAGS(stop_bt, GTK_CAN_DEFAULT);
689 gtk_widget_grab_default(stop_bt);
690 gtk_widget_show(stop_bt);
692 gtk_widget_show(cap_w);
695 upd_time = time(NULL);
697 while (gtk_events_pending()) gtk_main_iteration();
698 inpkts = pcap_dispatch(pch, 1, capture_pcap_cb, (u_char *) &ld);
700 ld.sync_packets += inpkts;
701 /* Only update once a second so as not to overload slow displays */
702 cur_time = time(NULL);
703 if (cur_time > upd_time) {
707 sprintf(label_str, "Count: %d", ld.counts.total);
708 gtk_label_set(GTK_LABEL(count_lb), label_str);
710 sprintf(label_str, "TCP: %d (%.1f%%)", ld.counts.tcp,
711 pct(ld.counts.tcp, ld.counts.total));
712 gtk_label_set(GTK_LABEL(tcp_lb), label_str);
714 sprintf(label_str, "UDP: %d (%.1f%%)", ld.counts.udp,
715 pct(ld.counts.udp, ld.counts.total));
716 gtk_label_set(GTK_LABEL(udp_lb), label_str);
718 sprintf(label_str, "ICMP: %d (%.1f%%)", ld.counts.icmp,
719 pct(ld.counts.icmp, ld.counts.total));
720 gtk_label_set(GTK_LABEL(icmp_lb), label_str);
722 sprintf(label_str, "OSPF: %d (%.1f%%)", ld.counts.ospf,
723 pct(ld.counts.ospf, ld.counts.total));
724 gtk_label_set(GTK_LABEL(ospf_lb), label_str);
726 sprintf(label_str, "GRE: %d (%.1f%%)", ld.counts.gre,
727 pct(ld.counts.gre, ld.counts.total));
728 gtk_label_set(GTK_LABEL(gre_lb), label_str);
730 sprintf(label_str, "NetBIOS: %d (%.1f%%)", ld.counts.netbios,
731 pct(ld.counts.netbios, ld.counts.total));
732 gtk_label_set(GTK_LABEL(netbios_lb), label_str);
734 sprintf(label_str, "Other: %d (%.1f%%)", ld.counts.other,
735 pct(ld.counts.other, ld.counts.total));
736 gtk_label_set(GTK_LABEL(other_lb), label_str);
738 /* do sync here, too */
739 fflush(wtap_dump_file(ld.pdh));
740 if (sync_mode && ld.sync_packets) {
742 sprintf(tmp, "%d*", ld.sync_packets);
743 write(1, tmp, strlen(tmp));
750 if (!wtap_dump_close(ld.pdh, &err)) {
753 case WTAP_ERR_CANT_CLOSE:
754 errmsg = "The file to which the capture was being saved"
755 " couldn't be closed for some unknown reason.";
758 case WTAP_ERR_SHORT_WRITE:
759 errmsg = "Not all the data could be written to the file"
760 " to which the capture was being saved.";
765 sprintf(errmsg_errno, "The file to which the capture was being"
766 " saved (\"%%s\") could not be closed: Error %d.",
769 sprintf(errmsg_errno, "The file to which the capture was being"
770 " saved (\"%%s\") could not be closed: %s.",
773 errmsg = errmsg_errno;
776 snprintf(err_str, PCAP_ERRBUF_SIZE, errmsg, cf.save_file);
777 simple_dialog(ESD_TYPE_WARN, NULL, err_str);
782 gtk_grab_remove(GTK_WIDGET(cap_w));
783 gtk_widget_destroy(GTK_WIDGET(cap_w));
785 while (gtk_events_pending()) gtk_main_iteration();
786 simple_dialog(ESD_TYPE_WARN, NULL,
787 "The capture session could not be initiated (%s).\n"
788 "Please check to make sure you have sufficient permissions, and that\n"
789 "you have the proper interface specified.", err_str);
792 if( quit_after_cap ){
793 /* DON'T unlink the save file. Presumably someone wants it. */
798 /* "pch" is non-NULL only if we successfully started a capture.
799 If we haven't, there's no capture file to load. */
800 if ((err = open_cap_file(cf.save_file, &cf)) == 0) {
801 /* Set the read filter to NULL. */
803 err = read_cap_file(&cf);
804 set_menu_sensitivity("/File/Save", TRUE);
805 set_menu_sensitivity("/File/Save As...", FALSE);
811 pct(gint num, gint denom) {
813 return (float) num * 100.0 / (float) denom;
820 capture_stop_cb(GtkWidget *w, gpointer data) {
821 loop_data *ld = (loop_data *) data;
827 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
829 struct wtap_pkthdr whdr;
830 loop_data *ld = (loop_data *) user;
833 if ((++ld->counts.total >= ld->max) && (ld->max > 0))
839 whdr.caplen = phdr->caplen;
840 whdr.len = phdr->len;
841 whdr.pkt_encap = ld->linktype;
843 /* XXX - do something if this fails */
844 wtap_dump(ld->pdh, &whdr, pd, &err);
847 switch (ld->linktype) {
848 case WTAP_ENCAP_ETHERNET:
849 capture_eth(pd, phdr->caplen, &ld->counts);
851 case WTAP_ENCAP_FDDI:
852 case WTAP_ENCAP_FDDI_BITSWAPPED:
853 capture_fddi(pd, phdr->caplen, &ld->counts);
856 capture_tr(pd, phdr->caplen, &ld->counts);
858 case WTAP_ENCAP_NULL:
859 capture_null(pd, phdr->caplen, &ld->counts);
862 capture_ppp(pd, phdr->caplen, &ld->counts);
864 case WTAP_ENCAP_RAW_IP:
865 capture_raw(pd, phdr->caplen, &ld->counts);
867 /* XXX - FreeBSD may append 4-byte ATM pseudo-header to DLT_ATM_RFC1483,
868 with LLC header following; we should implement it at some
873 #endif /* HAVE_LIBPCAP */