Make the Tethereal usage message reflect whether libpcap support was
[obnox/wireshark/wip.git] / capture.c
1 /* capture.c
2  * Routines for packet capture windows
3  *
4  * $Id: capture.c,v 1.91 2000/01/23 08:55:30 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, *vines_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.vines   = 0;
515   ld.counts.other   = 0;
516   ld.pdh            = NULL;
517
518   /* Open the network interface to capture from it. */
519   pch = pcap_open_live(cf.iface, cf.snap, 1, CAP_READ_TIMEOUT, err_str);
520
521   if (pch == NULL) {
522     /* Well, we couldn't start the capture.
523        If this is a child process that does the capturing in sync
524        mode or fork mode, it shouldn't do any UI stuff until we pop up the
525        capture-progress window, and, since we couldn't start the
526        capture, we haven't popped it up. */
527     if (!capture_child) {
528       while (gtk_events_pending()) gtk_main_iteration();
529     }
530     snprintf(errmsg, sizeof errmsg,
531       "The capture session could not be initiated (%s).\n"
532       "Please check to make sure you have sufficient permissions, and that\n"
533       "you have the proper interface specified.", err_str);
534     goto error;
535   }
536
537   if (cf.cfilter) {
538     /* A capture filter was specified; set it up. */
539     if (pcap_lookupnet (cf.iface, &netnum, &netmask, err_str) < 0) {
540       snprintf(errmsg, sizeof errmsg,
541         "Can't use filter:  Couldn't obtain netmask info (%s).", err_str);
542       goto error;
543     }
544     if (pcap_compile(pch, &cf.fcode, cf.cfilter, 1, netmask) < 0) {
545       snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
546         pcap_geterr(pch));
547       goto error;
548     }
549     if (pcap_setfilter(pch, &cf.fcode) < 0) {
550       snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
551         pcap_geterr(pch));
552       goto error;
553     }
554   }
555
556   /* Set up to write to the capture file. */
557   ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(pch));
558   if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
559     strcpy(errmsg, "The network you're capturing from is of a type"
560              " that Ethereal doesn't support.");
561     goto error;
562   }
563   ld.pdh = wtap_dump_fdopen(cf.save_file_fd, WTAP_FILE_PCAP,
564                 ld.linktype, pcap_snapshot(pch), &err);
565
566   if (ld.pdh == NULL) {
567     /* We couldn't set up to write to the capture file. */
568     switch (err) {
569
570     case WTAP_ERR_CANT_OPEN:
571       strcpy(errmsg, "The file to which the capture would be saved"
572                " couldn't be created for some unknown reason.");
573       break;
574
575     case WTAP_ERR_SHORT_WRITE:
576       strcpy(errmsg, "A full header couldn't be written to the file"
577                " to which the capture would be saved.");
578       break;
579
580     default:
581       if (err < 0) {
582         sprintf(errmsg, "The file to which the capture would be"
583                      " saved (\"%s\") could not be opened: Error %d.",
584                         cf.save_file, err);
585       } else {
586         sprintf(errmsg, "The file to which the capture would be"
587                      " saved (\"%s\") could not be opened: %s.",
588                         cf.save_file, strerror(err));
589       }
590       break;
591     }
592     goto error;
593   }
594
595   if (capture_child) {
596     /* Well, we should be able to start capturing.
597
598        This is the child process for a sync mode capture, so sync out
599        the capture file, so the header makes it to the file system,
600        and send a "capture started successfully and capture file created"
601        message to our parent so that they'll open the capture file and
602        update its windows to indicate that we have a live capture in
603        progress. */
604     fflush(wtap_dump_file(ld.pdh));
605     write(1, "0;", 2);
606   }
607
608   cap_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
609   gtk_window_set_title(GTK_WINDOW(cap_w), "Ethereal: Capture / Playback");
610
611   /* Container for capture display widgets */
612   main_vb = gtk_vbox_new(FALSE, 1);
613   gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
614   gtk_container_add(GTK_CONTAINER(cap_w), main_vb);
615   gtk_widget_show(main_vb);
616
617   count_lb = gtk_label_new("Count: 0");
618   gtk_box_pack_start(GTK_BOX(main_vb), count_lb, FALSE, FALSE, 3);
619   gtk_widget_show(count_lb);
620
621   tcp_lb = gtk_label_new("TCP: 0 (0.0%)");
622   gtk_box_pack_start(GTK_BOX(main_vb), tcp_lb, FALSE, FALSE, 3);
623   gtk_widget_show(tcp_lb);
624
625   udp_lb = gtk_label_new("UDP: 0 (0.0%)");
626   gtk_box_pack_start(GTK_BOX(main_vb), udp_lb, FALSE, FALSE, 3);
627   gtk_widget_show(udp_lb);
628
629   icmp_lb = gtk_label_new("ICMP: 0 (0.0%)");
630   gtk_box_pack_start(GTK_BOX(main_vb), icmp_lb, FALSE, FALSE, 3);
631   gtk_widget_show(icmp_lb);
632
633   ospf_lb = gtk_label_new("OSPF: 0 (0.0%)");
634   gtk_box_pack_start(GTK_BOX(main_vb), ospf_lb, FALSE, FALSE, 3);
635   gtk_widget_show(ospf_lb);
636
637   gre_lb = gtk_label_new("GRE: 0 (0.0%)");
638   gtk_box_pack_start(GTK_BOX(main_vb), gre_lb, FALSE, FALSE, 3);
639   gtk_widget_show(gre_lb);
640
641   netbios_lb = gtk_label_new("NetBIOS: 0 (0.0%)");
642   gtk_box_pack_start(GTK_BOX(main_vb), netbios_lb, FALSE, FALSE, 3);
643   gtk_widget_show(netbios_lb);
644
645   ipx_lb = gtk_label_new("IPX: 0 (0.0%)");
646   gtk_box_pack_start(GTK_BOX(main_vb), ipx_lb, FALSE, FALSE, 3);
647   gtk_widget_show(ipx_lb);
648
649   vines_lb = gtk_label_new("VINES: 0 (0.0%)");
650   gtk_box_pack_start(GTK_BOX(main_vb), vines_lb, FALSE, FALSE, 3);
651   gtk_widget_show(vines_lb);
652
653   other_lb = gtk_label_new("Other: 0 (0.0%)");
654   gtk_box_pack_start(GTK_BOX(main_vb), other_lb, FALSE, FALSE, 3);
655   gtk_widget_show(other_lb);
656
657   stop_bt = gtk_button_new_with_label ("Stop");
658   gtk_signal_connect(GTK_OBJECT(stop_bt), "clicked",
659     GTK_SIGNAL_FUNC(capture_stop_cb), (gpointer) &ld);
660   gtk_box_pack_end(GTK_BOX(main_vb), stop_bt, FALSE, FALSE, 3);
661   GTK_WIDGET_SET_FLAGS(stop_bt, GTK_CAN_DEFAULT);
662   gtk_widget_grab_default(stop_bt);
663   GTK_WIDGET_SET_FLAGS(stop_bt, GTK_CAN_DEFAULT);
664   gtk_widget_grab_default(stop_bt);
665   gtk_widget_show(stop_bt);
666
667   gtk_widget_show(cap_w);
668   gtk_grab_add(cap_w);
669
670   upd_time = time(NULL);
671 #ifdef linux
672   pcap_fd = pcap_fileno(pch);
673 #endif
674   while (ld.go) {
675     while (gtk_events_pending()) gtk_main_iteration();
676 #ifdef linux
677     /*
678      * Sigh.  The semantics of the read timeout argument to
679      * "pcap_open_live()" aren't particularly well specified by
680      * the "pcap" man page - at least with the BSD BPF code, the
681      * intent appears to be, at least in part, a way of cutting
682      * down the number of reads done on a capture, by blocking
683      * until the buffer fills or a timer expires - and the Linux
684      * libpcap doesn't actually support it, so we can't use it
685      * to break out of the "pcap_dispatch()" every 1/4 of a second
686      * or so.
687      *
688      * Thus, on Linux, we do a "select()" on the file descriptor for the
689      * capture, with a timeout of CAP_READ_TIMEOUT milliseconds, or
690      * CAP_READ_TIMEOUT*1000 microseconds.
691      */
692     FD_ZERO(&set1);
693     FD_SET(pcap_fd, &set1);
694     timeout.tv_sec = 0;
695     timeout.tv_usec = CAP_READ_TIMEOUT*1000;
696     if (select(pcap_fd+1, &set1, NULL, NULL, &timeout) != 0) {
697       /*
698        * "select()" says we can read from it without blocking; go for
699        * it.
700        */
701       inpkts = pcap_dispatch(pch, 1, capture_pcap_cb, (u_char *) &ld);
702     } else
703       inpkts = 0;
704 #else
705     inpkts = pcap_dispatch(pch, 1, capture_pcap_cb, (u_char *) &ld);
706 #endif
707     if (inpkts > 0)
708       ld.sync_packets += inpkts;
709     /* Only update once a second so as not to overload slow displays */
710     cur_time = time(NULL);
711     if (cur_time > upd_time) {
712       upd_time = cur_time;
713
714       sprintf(label_str, "Count: %d", ld.counts.total);
715       gtk_label_set(GTK_LABEL(count_lb), label_str);
716
717       sprintf(label_str, "TCP: %d (%.1f%%)", ld.counts.tcp,
718                 pct(ld.counts.tcp, ld.counts.total));
719       gtk_label_set(GTK_LABEL(tcp_lb), label_str);
720
721       sprintf(label_str, "UDP: %d (%.1f%%)", ld.counts.udp,
722                 pct(ld.counts.udp, ld.counts.total));
723       gtk_label_set(GTK_LABEL(udp_lb), label_str);
724
725       sprintf(label_str, "ICMP: %d (%.1f%%)", ld.counts.icmp,
726                 pct(ld.counts.icmp, ld.counts.total));
727       gtk_label_set(GTK_LABEL(icmp_lb), label_str);
728
729       sprintf(label_str, "OSPF: %d (%.1f%%)", ld.counts.ospf,
730                 pct(ld.counts.ospf, ld.counts.total));
731       gtk_label_set(GTK_LABEL(ospf_lb), label_str);
732
733       sprintf(label_str, "GRE: %d (%.1f%%)", ld.counts.gre,
734                 pct(ld.counts.gre, ld.counts.total));
735       gtk_label_set(GTK_LABEL(gre_lb), label_str);
736
737       sprintf(label_str, "NetBIOS: %d (%.1f%%)", ld.counts.netbios,
738                 pct(ld.counts.netbios, ld.counts.total));
739       gtk_label_set(GTK_LABEL(netbios_lb), label_str);
740
741       sprintf(label_str, "IPX: %d (%.1f%%)", ld.counts.ipx,
742                 pct(ld.counts.ipx, ld.counts.total));
743       gtk_label_set(GTK_LABEL(ipx_lb), label_str);
744
745       sprintf(label_str, "VINES: %d (%.1f%%)", ld.counts.vines,
746                 pct(ld.counts.vines, ld.counts.total));
747       gtk_label_set(GTK_LABEL(vines_lb), label_str);
748
749       sprintf(label_str, "Other: %d (%.1f%%)", ld.counts.other,
750                 pct(ld.counts.other, ld.counts.total));
751       gtk_label_set(GTK_LABEL(other_lb), label_str);
752
753       /* do sync here, too */
754       fflush(wtap_dump_file(ld.pdh));
755       if (capture_child && ld.sync_packets) {
756         /* This is the child process for a sync mode capture, so send
757            our parent a message saying we've written out "ld.sync_packets"
758            packets to the capture file. */
759         char tmp[20];
760         sprintf(tmp, "%d*", ld.sync_packets);
761         write(1, tmp, strlen(tmp));
762         ld.sync_packets = 0;
763       }
764     }
765   }
766     
767   if (!wtap_dump_close(ld.pdh, &err)) {
768     /* XXX - in fork mode, this may not pop up, or, if it does,
769        it may disappear as soon as we exit.
770
771        We should have the parent process, while it's reading
772        the packet count update messages, catch error messages
773        and pop up a message box if it sees one. */
774     switch (err) {
775
776     case WTAP_ERR_CANT_CLOSE:
777       simple_dialog(ESD_TYPE_WARN, NULL,
778                 "The file to which the capture was being saved"
779                 " couldn't be closed for some unknown reason.");
780       break;
781
782     case WTAP_ERR_SHORT_WRITE:
783       simple_dialog(ESD_TYPE_WARN, NULL,
784                 "Not all the data could be written to the file"
785                 " to which the capture was being saved.");
786       break;
787
788     default:
789       simple_dialog(ESD_TYPE_WARN, NULL,
790                 "The file to which the capture was being"
791                 " saved (\"%s\") could not be closed: %s.",
792                 cf.save_file, wtap_strerror(err));
793       break;
794     }
795   }
796   pcap_close(pch);
797
798   gtk_grab_remove(GTK_WIDGET(cap_w));
799   gtk_widget_destroy(GTK_WIDGET(cap_w));
800
801   return TRUE;
802
803 error:
804   /* We couldn't even start the capture, so get rid of the capture
805      file. */
806   unlink(cf.save_file); /* silently ignore error */
807   g_free(cf.save_file);
808   cf.save_file = NULL;
809   if (capture_child) {
810     /* This is the child process for a sync mode capture.
811        Send the error message to our parent, so they can display a
812        dialog box containing it. */
813     int msglen = strlen(errmsg);
814     char lenbuf[10+1+1];
815     sprintf(lenbuf, "%u;", msglen);
816     write(1, lenbuf, strlen(lenbuf));
817     write(1, errmsg, msglen);
818   } else {
819     /* Display the dialog box ourselves; there's no parent. */
820     simple_dialog(ESD_TYPE_WARN, NULL, errmsg);
821   }
822   if (pch != NULL)
823     pcap_close(pch);
824
825   return FALSE;
826 }
827
828 static float
829 pct(gint num, gint denom) {
830   if (denom) {
831     return (float) num * 100.0 / (float) denom;
832   } else {
833     return 0.0;
834   }
835 }
836
837 static void
838 capture_stop_cb(GtkWidget *w, gpointer data) {
839   loop_data *ld = (loop_data *) data;
840   
841   ld->go = FALSE;
842 }
843
844 static void
845 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
846   const u_char *pd) {
847   struct wtap_pkthdr whdr;
848   loop_data *ld = (loop_data *) user;
849   int err;
850
851   if ((++ld->counts.total >= ld->max) && (ld->max > 0)) 
852   {
853      ld->go = FALSE;
854   }
855   if (ld->pdh) {
856      whdr.ts = phdr->ts;
857      whdr.caplen = phdr->caplen;
858      whdr.len = phdr->len;
859      whdr.pkt_encap = ld->linktype;
860
861      /* XXX - do something if this fails */
862      wtap_dump(ld->pdh, &whdr, pd, &err);
863   }
864
865   /* Set the initial payload to the packet length, and the initial
866      captured payload to the capture length (other protocols may
867      reduce them if their headers say they're less). */
868   pi.len = phdr->len;
869   pi.captured_len = phdr->caplen;
870     
871   switch (ld->linktype) {
872     case WTAP_ENCAP_ETHERNET:
873       capture_eth(pd, 0, &ld->counts);
874       break;
875     case WTAP_ENCAP_FDDI:
876     case WTAP_ENCAP_FDDI_BITSWAPPED:
877       capture_fddi(pd, &ld->counts);
878       break;
879     case WTAP_ENCAP_TR:
880       capture_tr(pd, 0, &ld->counts);
881       break;
882     case WTAP_ENCAP_NULL:
883       capture_null(pd, &ld->counts);
884       break;
885     case WTAP_ENCAP_PPP:
886       capture_ppp(pd, &ld->counts);
887       break;
888     case WTAP_ENCAP_RAW_IP:
889       capture_raw(pd, &ld->counts);
890       break;
891     /* XXX - FreeBSD may append 4-byte ATM pseudo-header to DLT_ATM_RFC1483,
892        with LLC header following; we should implement it at some
893        point. */
894   }
895 }
896
897 #endif /* HAVE_LIBPCAP */