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