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