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