957703a96d49b96a09d814e067f42e8fa6bb74b4
[obnox/wireshark/wip.git] / capture.c
1 /* capture.c
2  * Routines for packet capture windows
3  *
4  * $Id: capture.c,v 1.95 2000/02/09 19:17:50 gram Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * 
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.
15  * 
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.
20  * 
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.
24  */
25
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #ifdef HAVE_LIBPCAP
32
33 #ifdef HAVE_SYS_TYPES_H
34 # include <sys/types.h>
35 #endif
36
37 #ifdef HAVE_SYS_STAT_H
38 # include <sys/stat.h>
39 #endif
40
41 #ifdef HAVE_SYS_WAIT_H
42 # include <sys/wait.h>
43 #endif
44 #ifdef HAVE_IO_H
45 #include <io.h>
46 #endif
47
48 #include <gtk/gtk.h>
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <ctype.h>
52 #include <string.h>
53 #include <fcntl.h>
54
55 #ifdef HAVE_UNISTD_H
56 #include <unistd.h>
57 #endif
58
59 #include <time.h>
60
61 #ifdef HAVE_SYS_SOCKET_H
62 #include <sys/socket.h>
63 #endif
64
65 #ifdef HAVE_SYS_IOCTL_H
66 #include <sys/ioctl.h>
67 #endif
68
69 #ifdef HAVE_NET_IF_H
70 #include <net/if.h>
71 #endif
72
73 #include <signal.h>
74 #include <errno.h>
75
76 #ifdef NEED_SNPRINTF_H
77 # ifdef HAVE_STDARG_H
78 #  include <stdarg.h>
79 # else
80 #  include <varargs.h>
81 # endif
82 # include "snprintf.h"
83 #endif
84
85 #ifndef lib_pcap_h
86 #include <pcap.h>
87 #endif
88
89 #include "gtk/main.h"
90 #include "gtk/gtkglobals.h"
91 #include "packet.h"
92 #include "file.h"
93 #include "capture.h"
94 #include "util.h"
95 #include "simple_dialog.h"
96 #include "prefs.h"
97 #include "globals.h"
98
99 int sync_mode;  /* fork a child to do the capture, and sync between them */
100 static int sync_pipe[2]; /* used to sync father */
101 int quit_after_cap; /* Makes a "capture only mode". Implies -k */
102 gboolean capture_child; /* if this is the child for "-S" */
103 static guint cap_input_id;
104
105 static void cap_file_input_cb(gpointer, gint, GdkInputCondition);
106 static void capture_delete_cb(GtkWidget *, GdkEvent *, gpointer);
107 static void capture_stop_cb(GtkWidget *, gpointer);
108 static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
109   const u_char *);
110 static float pct(gint, gint);
111
112 typedef struct _loop_data {
113   gint           go;
114   gint           max;
115   gint           linktype;
116   gint           sync_packets;
117   packet_counts  counts;
118   wtap_dumper   *pdh;
119 } loop_data;
120
121 /* Win32 needs the O_BINARY flag for open() */
122 #ifndef O_BINARY
123 #define O_BINARY        0
124 #endif
125
126 /* Open a specified file, or create a temporary file, and start a capture
127    to the file in question. */
128 void
129 do_capture(char *capfile_name)
130 {
131   char tmpname[128+1];
132   gboolean is_tempfile;
133   u_char c;
134   int i;
135   guint byte_count;
136   char *msg;
137   int err;
138   int capture_succeeded;
139
140   if (capfile_name != NULL) {
141     /* Try to open/create the specified file for use as a capture buffer. */
142     cf.save_file_fd = open(capfile_name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT, 0600);
143     is_tempfile = FALSE;
144   } else {
145     /* Choose a random name for the capture buffer */
146     cf.save_file_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
147     capfile_name = g_strdup(tmpname);
148     is_tempfile = TRUE;
149   }
150   if (cf.save_file_fd == -1) {
151     simple_dialog(ESD_TYPE_WARN, NULL,
152         "The file to which the capture would be saved (\"%s\")"
153         "could not be opened: %s.", capfile_name, strerror(errno));
154     return;
155   }
156   close_cap_file(&cf, info_bar);
157   g_assert(cf.save_file == NULL);
158   cf.save_file = capfile_name;
159
160   if (sync_mode) {      /*  use fork() for capture */
161 #ifndef _WIN32
162     int  fork_child;
163     char ssnap[24];
164     char scount[24];    /* need a constant for len of numbers */
165     char save_file_fd[24];
166
167     sprintf(ssnap,"%d",cf.snap); /* in lieu of itoa */
168     sprintf(scount,"%d",cf.count);
169     sprintf(save_file_fd,"%d",cf.save_file_fd);
170     signal(SIGCHLD, SIG_IGN);
171     pipe(sync_pipe);
172     if ((fork_child = fork()) == 0) {
173       /*
174        * Child process - run Ethereal with the right arguments to make
175        * it just pop up the live capture dialog box and capture with
176        * the specified capture parameters, writing to the specified file.
177        *
178        * args: -i interface specification
179        * -w file to write
180        * -W file descriptor to write
181        * -c count to capture
182        * -s snaplen
183        * -m / -b fonts
184        * -f "filter expression"
185        */
186       close(1);
187       dup(sync_pipe[1]);
188       close(sync_pipe[0]);
189       execlp(ethereal_path, CHILD_NAME, "-i", cf.iface,
190                 "-w", cf.save_file, "-W", save_file_fd,
191                 "-c", scount, "-s", ssnap, 
192                 "-m", medium_font, "-b", bold_font,
193                 (cf.cfilter == NULL)? 0 : "-f",
194                 (cf.cfilter == NULL)? 0 : cf.cfilter,
195                 (const char *)NULL);    
196     } else {
197       /* Parent process - read messages from the child process over the
198          sync pipe. */
199       close(sync_pipe[1]);
200
201       /* Read a byte count from "sync_pipe[0]", terminated with a
202          colon; if the count is 0, the child process created the
203          capture file and we should start reading from it, otherwise
204          the capture couldn't start and the count is a count of bytes
205          of error message, and we should display the message. */
206       byte_count = 0;
207       for (;;) {
208         i = read(sync_pipe[0], &c, 1);
209         if (i == 0) {
210           /* EOF - the child process died.
211              Close the read side of the sync pipe, remove the capture file,
212              and report the failure.
213              XXX - reap the child process and report the status in detail. */
214           close(sync_pipe[0]);
215           unlink(cf.save_file);
216           g_free(cf.save_file);
217           cf.save_file = NULL;
218           simple_dialog(ESD_TYPE_WARN, NULL, "Capture child process died");
219           return;
220         }
221         if (c == ';')
222           break;
223         if (!isdigit(c)) {
224           /* Child process handed us crap.
225              Close the read side of the sync pipe, remove the capture file,
226              and report the failure. */
227           close(sync_pipe[0]);
228           unlink(cf.save_file);
229           g_free(cf.save_file);
230           cf.save_file = NULL;
231           simple_dialog(ESD_TYPE_WARN, NULL,
232              "Capture child process sent us a bad message");
233           return;
234         }
235         byte_count = byte_count*10 + c - '0';
236       }
237       if (byte_count == 0) {
238         /* Success.  Open the capture file, and set up to read it. */
239         err = start_tail_cap_file(cf.save_file, is_tempfile, &cf);
240         if (err == 0) {
241           /* We were able to open and set up to read the capture file;
242              arrange that our callback be called whenever it's possible
243              to read from the sync pipe, so that it's called when
244              the child process wants to tell us something. */
245           cap_input_id = gtk_input_add_full(sync_pipe[0],
246                                        GDK_INPUT_READ|GDK_INPUT_EXCEPTION,
247                                        cap_file_input_cb,
248                                        NULL,
249                                        (gpointer) &cf,
250                                        NULL);
251         } else {
252           /* We weren't able to open the capture file; complain, and
253              close the sync pipe. */
254           simple_dialog(ESD_TYPE_WARN, NULL,
255                         file_open_error_message(err, FALSE), cf.save_file);
256
257           /* Close the sync pipe. */
258           close(sync_pipe[0]);
259
260           /* Don't unlink the save file - leave it around, for debugging
261              purposes. */
262           g_free(cf.save_file);
263           cf.save_file = NULL;
264         }
265       } else {
266         /* Failure - the child process sent us a message indicating
267            what the problem was. */
268         msg = g_malloc(byte_count + 1);
269         if (msg == NULL) {
270           simple_dialog(ESD_TYPE_WARN, NULL,
271                 "Capture child process failed, but its error message was too big.");
272         } else {
273           i = read(sync_pipe[0], msg, byte_count);
274           if (i < 0) {
275             simple_dialog(ESD_TYPE_WARN, NULL,
276                   "Capture child process failed: Error %s reading its error message.",
277                   strerror(errno));
278           } else if (i == 0) {
279             simple_dialog(ESD_TYPE_WARN, NULL,
280                   "Capture child process failed: EOF reading its error message.");
281           } else
282             simple_dialog(ESD_TYPE_WARN, NULL, msg);
283           g_free(msg);
284
285           /* Close the sync pipe. */
286           close(sync_pipe[0]);
287
288           /* Get rid of the save file - the capture never started. */
289           unlink(cf.save_file);
290           g_free(cf.save_file);
291           cf.save_file = NULL;
292         }
293       }
294     }
295 #endif
296   } else {
297     /* Not sync mode. */
298     capture_succeeded = capture();
299     if (quit_after_cap) {
300       /* DON'T unlink the save file.  Presumably someone wants it. */
301       gtk_exit(0);
302     }
303     if (capture_succeeded) {
304       /* Capture succeeded; read in the capture file. */
305       if ((err = open_cap_file(cf.save_file, is_tempfile, &cf)) == 0) {
306         /* Set the read filter to NULL. */
307         cf.rfcode = NULL;
308         err = read_cap_file(&cf);
309       }
310     }
311     /* We're not doing a capture any more, so we don't have a save
312        file. */
313     g_free(cf.save_file);
314     cf.save_file = NULL;
315   }
316 }
317
318 #ifndef _WIN32
319 /* There's stuff to read from the sync pipe, meaning the child has sent
320    us a message, or the sync pipe has closed, meaning the child has
321    closed it (perhaps because it exited). */
322 static void 
323 cap_file_input_cb(gpointer data, gint source, GdkInputCondition condition)
324 {
325   capture_file *cf = (capture_file *)data;
326   char buffer[256+1], *p = buffer, *q = buffer;
327   int  nread;
328   int  to_read = 0;
329   gboolean exit_loop = FALSE;
330   int  err;
331   int  wstatus;
332   int  wsignal;
333   char *msg;
334   char *sigmsg;
335   char sigmsg_buf[6+1+3+1];
336   char *coredumped;
337
338   /* avoid reentrancy problems and stack overflow */
339   gtk_input_remove(cap_input_id);
340
341   if ((nread = read(sync_pipe[0], buffer, 256)) <= 0) {
342     /* The child has closed the sync pipe, meaning it's not going to be
343        capturing any more packets.  Pick up its exit status, and
344        complain if it died of a signal. */
345     if (wait(&wstatus) != -1) {
346       /* XXX - are there any platforms on which we can run that *don't*
347          support POSIX.1's <sys/wait.h> and macros therein? */
348       wsignal = wstatus & 0177;
349       coredumped = "";
350       if (wstatus == 0177) {
351         /* It stopped, rather than exiting.  "Should not happen." */
352         msg = "stopped";
353         wsignal = (wstatus >> 8) & 0xFF;
354       } else {
355         msg = "terminated";
356         if (wstatus & 0200)
357           coredumped = " - core dumped";
358       }
359       if (wsignal != 0) {
360         switch (wsignal) {
361
362         case SIGHUP:
363           sigmsg = "Hangup";
364           break;
365
366         case SIGINT:
367           sigmsg = "Interrupted";
368           break;
369
370         case SIGQUIT:
371           sigmsg = "Quit";
372           break;
373
374         case SIGILL:
375           sigmsg = "Illegal instruction";
376           break;
377
378         case SIGTRAP:
379           sigmsg = "Trace trap";
380           break;
381
382         case SIGABRT:
383           sigmsg = "Abort";
384           break;
385
386         case SIGFPE:
387           sigmsg = "Arithmetic exception";
388           break;
389
390         case SIGKILL:
391           sigmsg = "Killed";
392           break;
393
394         case SIGBUS:
395           sigmsg = "Bus error";
396           break;
397
398         case SIGSEGV:
399           sigmsg = "Segmentation violation";
400           break;
401
402         /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO 
403                 Linux is POSIX compliant.  These are not POSIX-defined signals ---
404                   ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
405
406                ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
407                 were omitted from POSIX.1 because their behavior is
408                 implementation dependent and could not be adequately catego-
409                 rized.  Conforming implementations may deliver these sig-
410                 nals, but must document the circumstances under which they
411                 are delivered and note any restrictions concerning their
412                 delivery.''
413         */
414
415         #ifdef SIGSYS
416         case SIGSYS:
417           sigmsg = "Bad system call";
418           break;
419         #endif
420
421         case SIGPIPE:
422           sigmsg = "Broken pipe";
423           break;
424
425         case SIGALRM:
426           sigmsg = "Alarm clock";
427           break;
428
429         case SIGTERM:
430           sigmsg = "Terminated";
431           break;
432
433         default:
434           sprintf(sigmsg_buf, "Signal %d", wsignal);
435           sigmsg = sigmsg_buf;
436           break;
437         }
438         simple_dialog(ESD_TYPE_WARN, NULL,
439                 "Child capture process %s: %s%s", msg, sigmsg, coredumped);
440       }
441     }
442       
443     /* Read what remains of the capture file, and finish the capture.
444        XXX - do something if this fails? */
445     err = finish_tail_cap_file(cf);
446
447     /* We're not doing a capture any more, so we don't have a save
448        file. */
449     g_free(cf->save_file);
450     cf->save_file = NULL;
451
452     return;
453   }
454
455   buffer[nread] = '\0';
456
457   while(!exit_loop) {
458     /* look for (possibly multiple) '*' */
459     switch (*q) {
460     case '*' :
461       to_read += atoi(p);
462       p = q + 1; 
463       q++;
464       break;
465     case '\0' :
466       /* XXX should handle the case of a pipe full (i.e. no star found) */
467       exit_loop = TRUE;
468       break;
469     default :
470       q++;
471       break;
472     } 
473   }
474
475   /* Read from the capture file the number of records the child told us
476      it added.
477      XXX - do something if this fails? */
478   err = continue_tail_cap_file(cf, to_read);
479
480   /* restore pipe handler */
481   cap_input_id = gtk_input_add_full (sync_pipe[0],
482                                      GDK_INPUT_READ|GDK_INPUT_EXCEPTION,
483                                      cap_file_input_cb,
484                                      NULL,
485                                      (gpointer) cf,
486                                      NULL);
487 }
488 #endif /* _WIN32 */
489
490 /*
491  * Timeout, in milliseconds, for reads from the stream of captured packets.
492  */
493 #define CAP_READ_TIMEOUT        250
494
495 /* Do the low-level work of a capture.
496    Returns TRUE if it succeeds, FALSE otherwise. */
497 int
498 capture(void)
499 {
500   GtkWidget  *cap_w, *main_vb, *count_lb, *tcp_lb, *udp_lb, *icmp_lb,
501              *ospf_lb, *gre_lb, *netbios_lb, *ipx_lb, *vines_lb, *other_lb, *stop_bt;
502   pcap_t     *pch;
503   gchar       err_str[PCAP_ERRBUF_SIZE], label_str[32];
504   loop_data   ld;
505   bpf_u_int32 netnum, netmask;
506   time_t      upd_time, cur_time;
507   int         err, inpkts;
508   char        errmsg[1024+1];
509 #ifdef linux
510   fd_set      set1;
511   struct timeval timeout;
512   int         pcap_fd;
513 #endif
514
515   ld.go             = TRUE;
516   ld.counts.total   = 0;
517   ld.max            = cf.count;
518   ld.linktype       = WTAP_ENCAP_UNKNOWN;
519   ld.sync_packets   = 0;
520   ld.counts.tcp     = 0;
521   ld.counts.udp     = 0;
522   ld.counts.icmp    = 0;
523   ld.counts.ospf    = 0;
524   ld.counts.gre     = 0;
525   ld.counts.ipx     = 0;
526   ld.counts.netbios = 0;
527   ld.counts.vines   = 0;
528   ld.counts.other   = 0;
529   ld.pdh            = NULL;
530
531   /* Open the network interface to capture from it. */
532   pch = pcap_open_live(cf.iface, cf.snap, 1, CAP_READ_TIMEOUT, err_str);
533
534   if (pch == NULL) {
535     /* Well, we couldn't start the capture.
536        If this is a child process that does the capturing in sync
537        mode or fork mode, it shouldn't do any UI stuff until we pop up the
538        capture-progress window, and, since we couldn't start the
539        capture, we haven't popped it up. */
540     if (!capture_child) {
541       while (gtk_events_pending()) gtk_main_iteration();
542     }
543     snprintf(errmsg, sizeof errmsg,
544       "The capture session could not be initiated (%s).\n"
545       "Please check to make sure you have sufficient permissions, and that\n"
546       "you have the proper interface specified.", err_str);
547     goto error;
548   }
549
550   if (cf.cfilter) {
551     /* A capture filter was specified; set it up. */
552     if (pcap_lookupnet (cf.iface, &netnum, &netmask, err_str) < 0) {
553       snprintf(errmsg, sizeof errmsg,
554         "Can't use filter:  Couldn't obtain netmask info (%s).", err_str);
555       goto error;
556     }
557     if (pcap_compile(pch, &cf.fcode, cf.cfilter, 1, netmask) < 0) {
558       snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
559         pcap_geterr(pch));
560       goto error;
561     }
562     if (pcap_setfilter(pch, &cf.fcode) < 0) {
563       snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
564         pcap_geterr(pch));
565       goto error;
566     }
567   }
568
569   /* Set up to write to the capture file. */
570   ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(pch));
571   if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
572     strcpy(errmsg, "The network you're capturing from is of a type"
573              " that Ethereal doesn't support.");
574     goto error;
575   }
576   ld.pdh = wtap_dump_fdopen(cf.save_file_fd, WTAP_FILE_PCAP,
577                 ld.linktype, pcap_snapshot(pch), &err);
578
579   if (ld.pdh == NULL) {
580     /* We couldn't set up to write to the capture file. */
581     switch (err) {
582
583     case WTAP_ERR_CANT_OPEN:
584       strcpy(errmsg, "The file to which the capture would be saved"
585                " couldn't be created for some unknown reason.");
586       break;
587
588     case WTAP_ERR_SHORT_WRITE:
589       strcpy(errmsg, "A full header couldn't be written to the file"
590                " to which the capture would be saved.");
591       break;
592
593     default:
594       if (err < 0) {
595         sprintf(errmsg, "The file to which the capture would be"
596                      " saved (\"%s\") could not be opened: Error %d.",
597                         cf.save_file, err);
598       } else {
599         sprintf(errmsg, "The file to which the capture would be"
600                      " saved (\"%s\") could not be opened: %s.",
601                         cf.save_file, strerror(err));
602       }
603       break;
604     }
605     goto error;
606   }
607
608   if (capture_child) {
609     /* Well, we should be able to start capturing.
610
611        This is the child process for a sync mode capture, so sync out
612        the capture file, so the header makes it to the file system,
613        and send a "capture started successfully and capture file created"
614        message to our parent so that they'll open the capture file and
615        update its windows to indicate that we have a live capture in
616        progress. */
617     fflush(wtap_dump_file(ld.pdh));
618     write(1, "0;", 2);
619   }
620
621   cap_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
622   gtk_window_set_title(GTK_WINDOW(cap_w), "Ethereal: Capture / Playback");
623
624   /* Container for capture display widgets */
625   main_vb = gtk_vbox_new(FALSE, 1);
626   gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
627   gtk_container_add(GTK_CONTAINER(cap_w), main_vb);
628   gtk_widget_show(main_vb);
629
630   count_lb = gtk_label_new("Count: 0");
631   gtk_box_pack_start(GTK_BOX(main_vb), count_lb, FALSE, FALSE, 3);
632   gtk_widget_show(count_lb);
633
634   tcp_lb = gtk_label_new("TCP: 0 (0.0%)");
635   gtk_box_pack_start(GTK_BOX(main_vb), tcp_lb, FALSE, FALSE, 3);
636   gtk_widget_show(tcp_lb);
637
638   udp_lb = gtk_label_new("UDP: 0 (0.0%)");
639   gtk_box_pack_start(GTK_BOX(main_vb), udp_lb, FALSE, FALSE, 3);
640   gtk_widget_show(udp_lb);
641
642   icmp_lb = gtk_label_new("ICMP: 0 (0.0%)");
643   gtk_box_pack_start(GTK_BOX(main_vb), icmp_lb, FALSE, FALSE, 3);
644   gtk_widget_show(icmp_lb);
645
646   ospf_lb = gtk_label_new("OSPF: 0 (0.0%)");
647   gtk_box_pack_start(GTK_BOX(main_vb), ospf_lb, FALSE, FALSE, 3);
648   gtk_widget_show(ospf_lb);
649
650   gre_lb = gtk_label_new("GRE: 0 (0.0%)");
651   gtk_box_pack_start(GTK_BOX(main_vb), gre_lb, FALSE, FALSE, 3);
652   gtk_widget_show(gre_lb);
653
654   netbios_lb = gtk_label_new("NetBIOS: 0 (0.0%)");
655   gtk_box_pack_start(GTK_BOX(main_vb), netbios_lb, FALSE, FALSE, 3);
656   gtk_widget_show(netbios_lb);
657
658   ipx_lb = gtk_label_new("IPX: 0 (0.0%)");
659   gtk_box_pack_start(GTK_BOX(main_vb), ipx_lb, FALSE, FALSE, 3);
660   gtk_widget_show(ipx_lb);
661
662   vines_lb = gtk_label_new("VINES: 0 (0.0%)");
663   gtk_box_pack_start(GTK_BOX(main_vb), vines_lb, FALSE, FALSE, 3);
664   gtk_widget_show(vines_lb);
665
666   other_lb = gtk_label_new("Other: 0 (0.0%)");
667   gtk_box_pack_start(GTK_BOX(main_vb), other_lb, FALSE, FALSE, 3);
668   gtk_widget_show(other_lb);
669
670   /* allow user to either click a stop button, or the close button on
671         the window to stop a capture in progress. */
672   stop_bt = gtk_button_new_with_label ("Stop");
673   gtk_signal_connect(GTK_OBJECT(stop_bt), "clicked",
674     GTK_SIGNAL_FUNC(capture_stop_cb), (gpointer) &ld);
675   gtk_signal_connect(GTK_OBJECT(cap_w), "delete_event",
676         GTK_SIGNAL_FUNC(capture_delete_cb), (gpointer) &ld);
677   gtk_box_pack_end(GTK_BOX(main_vb), stop_bt, FALSE, FALSE, 3);
678   GTK_WIDGET_SET_FLAGS(stop_bt, GTK_CAN_DEFAULT);
679   gtk_widget_grab_default(stop_bt);
680   GTK_WIDGET_SET_FLAGS(stop_bt, GTK_CAN_DEFAULT);
681   gtk_widget_grab_default(stop_bt);
682   gtk_widget_show(stop_bt);
683
684   gtk_widget_show(cap_w);
685   gtk_grab_add(cap_w);
686
687   upd_time = time(NULL);
688 #ifdef linux
689   pcap_fd = pcap_fileno(pch);
690 #endif
691   while (ld.go) {
692     while (gtk_events_pending()) gtk_main_iteration();
693 #ifdef linux
694     /*
695      * Sigh.  The semantics of the read timeout argument to
696      * "pcap_open_live()" aren't particularly well specified by
697      * the "pcap" man page - at least with the BSD BPF code, the
698      * intent appears to be, at least in part, a way of cutting
699      * down the number of reads done on a capture, by blocking
700      * until the buffer fills or a timer expires - and the Linux
701      * libpcap doesn't actually support it, so we can't use it
702      * to break out of the "pcap_dispatch()" every 1/4 of a second
703      * or so.
704      *
705      * Thus, on Linux, we do a "select()" on the file descriptor for the
706      * capture, with a timeout of CAP_READ_TIMEOUT milliseconds, or
707      * CAP_READ_TIMEOUT*1000 microseconds.
708      */
709     FD_ZERO(&set1);
710     FD_SET(pcap_fd, &set1);
711     timeout.tv_sec = 0;
712     timeout.tv_usec = CAP_READ_TIMEOUT*1000;
713     if (select(pcap_fd+1, &set1, NULL, NULL, &timeout) != 0) {
714       /*
715        * "select()" says we can read from it without blocking; go for
716        * it.
717        */
718       inpkts = pcap_dispatch(pch, 1, capture_pcap_cb, (u_char *) &ld);
719     } else
720       inpkts = 0;
721 #else
722     inpkts = pcap_dispatch(pch, 1, capture_pcap_cb, (u_char *) &ld);
723 #endif
724     if (inpkts > 0)
725       ld.sync_packets += inpkts;
726     /* Only update once a second so as not to overload slow displays */
727     cur_time = time(NULL);
728     if (cur_time > upd_time) {
729       upd_time = cur_time;
730
731       sprintf(label_str, "Count: %d", ld.counts.total);
732       gtk_label_set(GTK_LABEL(count_lb), label_str);
733
734       sprintf(label_str, "TCP: %d (%.1f%%)", ld.counts.tcp,
735                 pct(ld.counts.tcp, ld.counts.total));
736       gtk_label_set(GTK_LABEL(tcp_lb), label_str);
737
738       sprintf(label_str, "UDP: %d (%.1f%%)", ld.counts.udp,
739                 pct(ld.counts.udp, ld.counts.total));
740       gtk_label_set(GTK_LABEL(udp_lb), label_str);
741
742       sprintf(label_str, "ICMP: %d (%.1f%%)", ld.counts.icmp,
743                 pct(ld.counts.icmp, ld.counts.total));
744       gtk_label_set(GTK_LABEL(icmp_lb), label_str);
745
746       sprintf(label_str, "OSPF: %d (%.1f%%)", ld.counts.ospf,
747                 pct(ld.counts.ospf, ld.counts.total));
748       gtk_label_set(GTK_LABEL(ospf_lb), label_str);
749
750       sprintf(label_str, "GRE: %d (%.1f%%)", ld.counts.gre,
751                 pct(ld.counts.gre, ld.counts.total));
752       gtk_label_set(GTK_LABEL(gre_lb), label_str);
753
754       sprintf(label_str, "NetBIOS: %d (%.1f%%)", ld.counts.netbios,
755                 pct(ld.counts.netbios, ld.counts.total));
756       gtk_label_set(GTK_LABEL(netbios_lb), label_str);
757
758       sprintf(label_str, "IPX: %d (%.1f%%)", ld.counts.ipx,
759                 pct(ld.counts.ipx, ld.counts.total));
760       gtk_label_set(GTK_LABEL(ipx_lb), label_str);
761
762       sprintf(label_str, "VINES: %d (%.1f%%)", ld.counts.vines,
763                 pct(ld.counts.vines, ld.counts.total));
764       gtk_label_set(GTK_LABEL(vines_lb), label_str);
765
766       sprintf(label_str, "Other: %d (%.1f%%)", ld.counts.other,
767                 pct(ld.counts.other, ld.counts.total));
768       gtk_label_set(GTK_LABEL(other_lb), label_str);
769
770       /* do sync here, too */
771       fflush(wtap_dump_file(ld.pdh));
772       if (capture_child && ld.sync_packets) {
773         /* This is the child process for a sync mode capture, so send
774            our parent a message saying we've written out "ld.sync_packets"
775            packets to the capture file. */
776         char tmp[20];
777         sprintf(tmp, "%d*", ld.sync_packets);
778         write(1, tmp, strlen(tmp));
779         ld.sync_packets = 0;
780       }
781     }
782   }
783     
784   if (!wtap_dump_close(ld.pdh, &err)) {
785     /* XXX - in fork mode, this may not pop up, or, if it does,
786        it may disappear as soon as we exit.
787
788        We should have the parent process, while it's reading
789        the packet count update messages, catch error messages
790        and pop up a message box if it sees one. */
791     switch (err) {
792
793     case WTAP_ERR_CANT_CLOSE:
794       simple_dialog(ESD_TYPE_WARN, NULL,
795                 "The file to which the capture was being saved"
796                 " couldn't be closed for some unknown reason.");
797       break;
798
799     case WTAP_ERR_SHORT_WRITE:
800       simple_dialog(ESD_TYPE_WARN, NULL,
801                 "Not all the data could be written to the file"
802                 " to which the capture was being saved.");
803       break;
804
805     default:
806       simple_dialog(ESD_TYPE_WARN, NULL,
807                 "The file to which the capture was being"
808                 " saved (\"%s\") could not be closed: %s.",
809                 cf.save_file, wtap_strerror(err));
810       break;
811     }
812   }
813   pcap_close(pch);
814
815   gtk_grab_remove(GTK_WIDGET(cap_w));
816   gtk_widget_destroy(GTK_WIDGET(cap_w));
817
818   return TRUE;
819
820 error:
821   /* We couldn't even start the capture, so get rid of the capture
822      file. */
823   unlink(cf.save_file); /* silently ignore error */
824   g_free(cf.save_file);
825   cf.save_file = NULL;
826   if (capture_child) {
827     /* This is the child process for a sync mode capture.
828        Send the error message to our parent, so they can display a
829        dialog box containing it. */
830     int msglen = strlen(errmsg);
831     char lenbuf[10+1+1];
832     sprintf(lenbuf, "%u;", msglen);
833     write(1, lenbuf, strlen(lenbuf));
834     write(1, errmsg, msglen);
835   } else {
836     /* Display the dialog box ourselves; there's no parent. */
837     simple_dialog(ESD_TYPE_WARN, NULL, errmsg);
838   }
839   if (pch != NULL)
840     pcap_close(pch);
841
842   return FALSE;
843 }
844
845 static float
846 pct(gint num, gint denom) {
847   if (denom) {
848     return (float) num * 100.0 / (float) denom;
849   } else {
850     return 0.0;
851   }
852 }
853
854 static void
855 capture_delete_cb(GtkWidget *w, GdkEvent *event, gpointer data) {
856   capture_stop_cb(NULL, data);
857 }
858
859 static void
860 capture_stop_cb(GtkWidget *w, gpointer data) {
861   loop_data *ld = (loop_data *) data;
862   
863   ld->go = FALSE;
864 }
865
866 static void
867 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
868   const u_char *pd) {
869   struct wtap_pkthdr whdr;
870   loop_data *ld = (loop_data *) user;
871   int err;
872
873   if ((++ld->counts.total >= ld->max) && (ld->max > 0)) 
874   {
875      ld->go = FALSE;
876   }
877   if (ld->pdh) {
878      /* "phdr->ts" may not necessarily be a "struct timeval" - it may
879         be a "struct bpf_timeval", with member sizes wired to 32
880         bits - and we may go that way ourselves in the future, so
881         copy the members individually. */
882      whdr.ts.tv_sec = phdr->ts.tv_sec;
883      whdr.ts.tv_usec = phdr->ts.tv_usec;
884      whdr.caplen = phdr->caplen;
885      whdr.len = phdr->len;
886      whdr.pkt_encap = ld->linktype;
887
888      /* XXX - do something if this fails */
889      wtap_dump(ld->pdh, &whdr, pd, &err);
890   }
891
892   /* Set the initial payload to the packet length, and the initial
893      captured payload to the capture length (other protocols may
894      reduce them if their headers say they're less). */
895   pi.len = phdr->len;
896   pi.captured_len = phdr->caplen;
897     
898   switch (ld->linktype) {
899     case WTAP_ENCAP_ETHERNET:
900       capture_eth(pd, 0, &ld->counts);
901       break;
902     case WTAP_ENCAP_FDDI:
903     case WTAP_ENCAP_FDDI_BITSWAPPED:
904       capture_fddi(pd, &ld->counts);
905       break;
906     case WTAP_ENCAP_TR:
907       capture_tr(pd, 0, &ld->counts);
908       break;
909     case WTAP_ENCAP_NULL:
910       capture_null(pd, &ld->counts);
911       break;
912     case WTAP_ENCAP_PPP:
913       capture_ppp(pd, &ld->counts);
914       break;
915     case WTAP_ENCAP_RAW_IP:
916       capture_raw(pd, &ld->counts);
917       break;
918     /* XXX - FreeBSD may append 4-byte ATM pseudo-header to DLT_ATM_RFC1483,
919        with LLC header following; we should implement it at some
920        point. */
921   }
922 }
923
924 #endif /* HAVE_LIBPCAP */