remove dependencies to pcap.h, so getting an idea what needs to be done by dumpcap...
[obnox/wireshark/wip.git] / dumpcap.c
1 /* dumpcap.c
2  *
3  * $Id$
4  *
5  * Ethereal - Network traffic analyzer
6  * By Gerald Combs <gerald@ethereal.com>
7  * Copyright 1998 Gerald Combs
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include <glib.h>
29
30 #include <string.h>
31 #include <ctype.h>
32
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36
37 #ifdef NEED_GETOPT_H
38 #include "getopt.h"
39 #endif
40
41 #ifdef HAVE_NETDB_H
42 #include <netdb.h>
43 #endif
44
45 #include "ringbuffer.h"
46 #include "clopts_common.h"
47 #include "cmdarg_err.h"
48 #include "version_info.h"
49
50 #include <pcap.h>
51 #include "capture-pcap-util.h"
52
53 #ifdef _WIN32
54 #include "capture-wpcap.h"
55 #endif
56
57 #include "capture.h"
58 #include "capture_loop.h"
59 #include "capture_sync.h"
60
61 #include "simple_dialog.h"
62 #include "util.h"
63 #include "log.h"
64 #include "file_util.h"
65
66
67
68 gboolean capture_child = FALSE; /* FALSE: standalone call, TRUE: this is an Ethereal capture child */
69
70 static void
71 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
72                     const char *message, gpointer user_data _U_);
73
74 /* capture related options */
75 capture_options global_capture_opts;
76 capture_options *capture_opts = &global_capture_opts;
77
78 #if __GNUC__ >= 2
79 void exit_main(int err) __attribute__ ((noreturn));
80 #else
81 void exit_main(int err);
82 #endif
83
84
85 static void
86 print_usage(gboolean print_ver) {
87
88   FILE *output;
89
90
91   if (print_ver) {
92     output = stdout;
93     fprintf(output,
94         "Dumpcap " VERSION "%s\n"
95         "Capture network packets and dump them into a libpcap file.\n"
96         "See http://www.ethereal.com for more information.\n",
97         svnversion);
98   } else {
99     output = stderr;
100   }
101   fprintf(output, "\nUsage: dumpcap [options] ...\n");
102   fprintf(output, "\n");
103   fprintf(output, "Capture interface:\n");
104   fprintf(output, "  -i <interface>           name or idx of interface (def: first none loopback)\n");
105   fprintf(output, "  -f <capture filter>      packet filter in libpcap filter syntax\n");
106   fprintf(output, "  -s <snaplen>             packet snapshot length (def: 65535)\n");
107   fprintf(output, "  -p                       don't capture in promiscuous mode\n");
108 #ifdef _WIN32
109   fprintf(output, "  -B <buffer size>         size of kernel buffer (def: 1MB)\n");
110 #endif
111   fprintf(output, "  -y <link type>           link layer type (def: first appropriate)\n");
112   fprintf(output, "  -D                       print list of interfaces and exit\n");
113   fprintf(output, "  -L                       print list of link-layer types of iface and exit\n");
114   fprintf(output, "\n");
115   fprintf(output, "Stop conditions:\n");
116   fprintf(output, "  -c <packet count>        stop after n packets (def: infinite)\n");
117   fprintf(output, "  -a <autostop cond.> ...  duration:NUM - stop after NUM seconds\n");
118   fprintf(output, "                           filesize:NUM - stop this file after NUM KB\n");
119   fprintf(output, "                              files:NUM - stop after NUM files\n");
120   /*fprintf(output, "\n");*/
121   fprintf(output, "Output (files):\n");
122   fprintf(output, "  -w <filename>            name of file to save (def: tempfile)\n");
123   fprintf(output, "  -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
124   fprintf(output, "                           filesize:NUM - switch to next file after NUM KB\n");
125   fprintf(output, "                              files:NUM - ringbuffer: replace after NUM files\n");
126   /*fprintf(output, "\n");*/
127   fprintf(output, "Miscellaneous:\n");
128   fprintf(output, "  -v                       print version information and exit\n");
129   fprintf(output, "  -h                       display this help and exit\n");
130   fprintf(output, "\n");
131   fprintf(output, "Example: dumpcap -i eth0 -a duration:60 -w output.pcap\n");
132   fprintf(output, "\"Capture network packets from interface eth0 until 60s passed into output.pcap\"\n");
133   fprintf(output, "\n");
134   fprintf(output, "Use Ctrl-C to stop capturing at any time.\n");
135 }
136
137 static void
138 show_version(GString *comp_info_str, GString *runtime_info_str)
139 {
140
141   printf(
142         "Dumpcap " VERSION "%s\n"
143         "\n"
144         "%s\n"
145         "%s\n"
146         "%s\n"
147         "See http://www.ethereal.com for more information.\n",
148         svnversion, get_copyright_info() ,comp_info_str->str, runtime_info_str->str);
149 }
150
151 /*
152  * Report an error in command-line arguments.
153  */
154 void
155 cmdarg_err(const char *fmt, ...)
156 {
157   va_list ap;
158
159   if(capture_child) {
160     /* XXX - convert to g_log */
161   } else {
162     va_start(ap, fmt);
163     fprintf(stderr, "dumpcap: ");
164     vfprintf(stderr, fmt, ap);
165     fprintf(stderr, "\n");
166     va_end(ap);
167   }
168 }
169
170 /*
171  * Report additional information for an error in command-line arguments.
172  */
173 void
174 cmdarg_err_cont(const char *fmt, ...)
175 {
176   va_list ap;
177
178   if(capture_child) {
179     /* XXX - convert to g_log */
180   } else {
181     va_start(ap, fmt);
182     vfprintf(stderr, fmt, ap);
183     fprintf(stderr, "\n");
184     va_end(ap);
185   }
186 }
187
188
189 #ifdef _WIN32
190 BOOL WINAPI ConsoleCtrlHandlerRoutine(DWORD dwCtrlType)
191 {
192     g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO,
193         "Console: Ctrl+C");
194     g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
195         "Console: Ctrl+C CtrlType: %u", dwCtrlType);
196
197     capture_loop_stop();
198
199     return TRUE;
200 }
201 #endif
202
203 void exit_main(int status)
204 {
205 #ifdef _WIN32
206   /* Shutdown windows sockets */
207   WSACleanup();
208 #endif
209
210   /* can be helpful for debugging */
211 #ifdef DEBUG_DUMPCAP
212   printf("Press any key\n");
213   _getch();
214 #endif
215
216   exit(status);
217 }
218
219
220 /* And now our feature presentation... [ fade to music ] */
221 int
222 main(int argc, char *argv[])
223 {
224   int                  opt;
225   extern char         *optarg;
226   gboolean             arg_error = FALSE;
227   GString             *comp_info_str;
228   GString             *runtime_info_str;
229
230 #ifdef _WIN32
231   WSADATA              wsaData;
232 #endif  /* _WIN32 */
233
234   gboolean             start_capture = TRUE;
235   gboolean             stats_known;
236   struct pcap_stat     stats;
237   GLogLevelFlags       log_flags;
238   gboolean             list_link_layer_types = FALSE;
239   int                  status;
240
241 #define OPTSTRING_INIT "a:b:c:Df:hi:Lps:vw:y:Z"
242
243 #ifdef _WIN32
244 #define OPTSTRING_WIN32 "B:"
245 #else
246 #define OPTSTRING_WIN32 ""
247 #endif  /* _WIN32 */
248
249   char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_WIN32) - 1] =
250     OPTSTRING_INIT OPTSTRING_WIN32;
251
252 #ifdef _WIN32
253   /* Load wpcap if possible. Do this before collecting the run-time version information */
254   load_wpcap();
255
256   /* ... and also load the packet.dll from wpcap */
257   /* XXX - currently not required, may change later. */
258   /*wpcap_packet_load();*/
259
260   /* Start windows sockets */
261   WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
262
263   /* Set handler for Ctrl+C key */
264   SetConsoleCtrlHandler(&ConsoleCtrlHandlerRoutine, TRUE);
265 #endif  /* _WIN32 */
266
267   /* Assemble the compile-time version information string */
268   comp_info_str = g_string_new("Compiled ");
269   g_string_append(comp_info_str, "with ");
270   get_compiled_version_info(comp_info_str);
271
272   /* Assemble the run-time version information string */
273   runtime_info_str = g_string_new("Running ");
274   get_runtime_version_info(runtime_info_str);
275
276   /* Arrange that if we have no console window, and a GLib message logging
277      routine is called to log a message, we pop up a console window.
278
279      We do that by inserting our own handler for all messages logged
280      to the default domain; that handler pops up a console if necessary,
281      and then calls the default handler. */
282
283   /* We might want to have component specific log levels later ... */
284
285   /* the default_log_handler will use stdout, which makes trouble with the */
286   /* capture child, as it uses stdout for it's sync_pipe */
287   /* so do the filtering in the console_log_handler and not here */
288   log_flags = 
289                     G_LOG_LEVEL_ERROR|
290                     G_LOG_LEVEL_CRITICAL|
291                     G_LOG_LEVEL_WARNING|
292                     G_LOG_LEVEL_MESSAGE|
293                     G_LOG_LEVEL_INFO|
294                     G_LOG_LEVEL_DEBUG|
295                     G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
296
297   g_log_set_handler(NULL,
298                     log_flags,
299                     console_log_handler, NULL /* user_data */);
300   g_log_set_handler(LOG_DOMAIN_MAIN,
301                     log_flags,
302                     console_log_handler, NULL /* user_data */);
303   g_log_set_handler(LOG_DOMAIN_CAPTURE,
304                     log_flags,
305             console_log_handler, NULL /* user_data */);
306   g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
307                     log_flags,
308             console_log_handler, NULL /* user_data */);
309
310   /* Set the initial values in the capture_opts. This might be overwritten 
311      by the command line parameters. */
312   capture_opts_init(capture_opts, NULL);
313
314   capture_opts->snaplen             = MIN_PACKET_SIZE;
315   capture_opts->has_ring_num_files  = TRUE;
316
317   /* Now get our args */
318   while ((opt = getopt(argc, argv, optstring)) != -1) {
319     switch (opt) {
320       case 'h':        /* Print help and exit */
321         print_usage(TRUE);
322         exit_main(0);
323         break;
324       case 'v':        /* Show version and exit */
325         show_version(comp_info_str, runtime_info_str);
326         exit_main(0);
327         break;
328       /*** capture option specific ***/
329       case 'a':        /* autostop criteria */
330       case 'b':        /* Ringbuffer option */
331       case 'c':        /* Capture x packets */
332       case 'f':        /* capture filter */
333       case 'i':        /* Use interface x */
334       case 'p':        /* Don't capture in promiscuous mode */
335       case 's':        /* Set the snapshot (capture) length */
336       case 'w':        /* Write to capture file x */
337       case 'y':        /* Set the pcap data link type */
338 #ifdef _WIN32
339       case 'B':        /* Buffer size */
340 #endif /* _WIN32 */
341         status = capture_opts_add_opt(capture_opts, opt, optarg, &start_capture);
342         if(status != 0) {
343             exit_main(status);
344         }
345         break;
346       /*** hidden option: Ethereal child mode (using binary output messages) ***/
347       case 'Z':
348           capture_child = TRUE;
349           break;
350
351       /*** all non capture option specific ***/
352       case 'D':        /* Print a list of capture devices and exit */
353         status = capture_opts_list_interfaces();
354         exit_main(status);
355         break;
356       case 'L':        /* Print list of link-layer types and exit */
357         list_link_layer_types = TRUE;
358         break;
359       default:
360       case '?':        /* Bad flag - print usage message */
361         cmdarg_err("Invalid Option: %s", argv[optind-1]);
362         arg_error = TRUE;
363         break;
364     }
365   }
366   argc -= optind;
367   argv += optind;
368   if (argc >= 1) {
369       /* user specified file name as regular command-line argument */
370       /* XXX - use it as the capture file name (or something else)? */
371     argc--;
372     argv++;
373   }
374
375   if (argc != 0) {
376     /*
377      * Extra command line arguments were specified; complain.
378      */
379     cmdarg_err("Invalid argument: %s", argv[0]);
380     arg_error = TRUE;
381   }
382
383   if (arg_error) {
384     print_usage(FALSE);
385     exit_main(1);
386   }
387
388   if (list_link_layer_types) {
389     /* We're supposed to list the link-layer types for an interface;
390        did the user also specify a capture file to be read? */
391     /* No - did they specify a ring buffer option? */
392     if (capture_opts->multi_files_on) {
393       cmdarg_err("Ring buffer requested, but a capture isn't being done.");
394       exit_main(1);
395     }
396   } else {
397     /* No - was the ring buffer option specified and, if so, does it make
398        sense? */
399     if (capture_opts->multi_files_on) {
400       /* Ring buffer works only under certain conditions:
401          a) ring buffer does not work with temporary files;
402          b) it makes no sense to enable the ring buffer if the maximum
403             file size is set to "infinite". */
404       if (capture_opts->save_file == NULL) {
405         cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
406         capture_opts->multi_files_on = FALSE;
407       }
408       if (!capture_opts->has_autostop_filesize && !capture_opts->has_file_duration) {
409         cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
410 /* XXX - this must be redesigned as the conditions changed */
411 /*      capture_opts->multi_files_on = FALSE;*/
412       }
413     }
414   }
415
416   if (capture_opts_trim_iface(capture_opts, NULL) == FALSE) {
417         cmdarg_err("No capture interfaces available (maybe lack of privileges?).");
418     exit_main(1);
419   }
420
421   /* Let the user know what interface was chosen. */
422   /* get_interface_descriptive_name() is not available! */
423   g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_MESSAGE, "Interface: %s\n", capture_opts->iface);
424
425   if (list_link_layer_types) {
426     status = capture_opts_list_link_layer_types(capture_opts);
427     exit_main(status);
428   }
429
430   capture_opts_trim_snaplen(capture_opts, MIN_PACKET_SIZE);
431   capture_opts_trim_ring_num_files(capture_opts);
432
433   /* Now start the capture. */
434
435   if(capture_loop_start(capture_opts, &stats_known, &stats) == TRUE) {
436       /* capture ok */
437       exit_main(0);
438   } else {
439       /* capture failed */
440       exit_main(1);
441   }
442 }
443
444
445 /* This routine should not be necessary, at least as I read the GLib
446    source code, as it looks as if GLib is, on Win32, *supposed* to
447    create a console window into which to display its output.
448
449    That doesn't happen, however.  I suspect there's something completely
450    broken about that code in GLib-for-Win32, and that it may be related
451    to the breakage that forces us to just call "printf()" on the message
452    rather than passing the message on to "g_log_default_handler()"
453    (which is the routine that does the aforementioned non-functional
454    console window creation). */
455 static void
456 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
457                     const char *message, gpointer user_data _U_)
458 {
459   time_t curr;
460   struct tm *today;
461   const char *level;
462
463
464   if(capture_child) {
465     return;
466   }
467
468   /* ignore log message, if log_level isn't interesting */
469   if( !(log_level & G_LOG_LEVEL_MASK & ~(G_LOG_LEVEL_DEBUG|G_LOG_LEVEL_INFO))) {
470 #ifndef DEBUG_DUMPCAP
471     return;
472 #endif
473   }
474
475   /* create a "timestamp" */
476   time(&curr);
477   today = localtime(&curr);    
478
479     switch(log_level & G_LOG_LEVEL_MASK) {
480     case G_LOG_LEVEL_ERROR:
481         level = "Err ";
482         break;
483     case G_LOG_LEVEL_CRITICAL:
484         level = "Crit";
485         break;
486     case G_LOG_LEVEL_WARNING:
487         level = "Warn";
488         break;
489     case G_LOG_LEVEL_MESSAGE:
490         level = "Msg ";
491         break;
492     case G_LOG_LEVEL_INFO:
493         level = "Info";
494         break;
495     case G_LOG_LEVEL_DEBUG:
496         level = "Dbg ";
497         break;
498     default:
499         fprintf(stderr, "unknown log_level %u\n", log_level);
500         level = NULL;
501         g_assert_not_reached();
502     }
503
504     /* don't use printf (stdout), in child mode we're using stdout for the sync_pipe */
505     if(log_level & G_LOG_LEVEL_MESSAGE) {
506         /* normal user messages without additional infos */
507         fprintf(stderr, "%s\n", message);
508         fflush(stderr);
509     } else {
510         /* info/debug messages with additional infos */
511         fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
512                 today->tm_hour, today->tm_min, today->tm_sec,
513                 log_domain != NULL ? log_domain : "",
514                 level, message);
515         fflush(stderr);
516     }
517 }
518
519
520 /****************************************************************************************************************/
521 /* sync_pipe handling */
522
523
524 /*
525  * Maximum length of sync pipe message data.  Must be < 2^24, as the
526  * message length is 3 bytes.
527  * XXX - this must be large enough to handle a Really Big Filter
528  * Expression, as the error message for an incorrect filter expression
529  * is a bit larger than the filter expression.
530  */
531 #define SP_MAX_MSG_LEN  4096
532
533
534  /* write a message to the recipient pipe in the standard format 
535    (3 digit message length (excluding length and indicator field), 
536    1 byte message indicator and the rest is the message) */
537 static void
538 pipe_write_block(int pipe, char indicator, int len, const char *msg)
539 {
540     guchar header[3+1]; /* indicator + 3-byte len */
541     int ret;
542
543     /*g_warning("write %d enter", pipe);*/
544
545     g_assert(indicator < '0' || indicator > '9');
546     g_assert(len <= SP_MAX_MSG_LEN);
547
548     /* write header (indicator + 3-byte len) */
549     header[0] = indicator;
550     header[1] = (len >> 16) & 0xFF;
551     header[2] = (len >> 8) & 0xFF;
552     header[3] = (len >> 0) & 0xFF;
553
554     ret = write(pipe, header, sizeof header);
555     if(ret == -1) {
556         return;
557     }
558
559     /* write value (if we have one) */
560     if(len) {
561         /*g_warning("write %d indicator: %c value len: %u msg: %s", pipe, indicator, len, msg);*/
562         ret = write(pipe, msg, len);
563         if(ret == -1) {
564             return;
565         }
566     } else {
567         /*g_warning("write %d indicator: %c no value", pipe, indicator);*/
568     }
569
570     /*g_warning("write %d leave", pipe);*/
571 }
572
573
574 void
575 sync_pipe_packet_count_to_parent(int packet_count)
576 {
577     char tmp[SP_DECISIZE+1+1];
578     static int count = 0;
579
580
581     if(capture_child) {
582         g_snprintf(tmp, sizeof(tmp), "%d", packet_count);
583         g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Packets: %s", tmp);
584         pipe_write_block(1, SP_PACKET_COUNT, strlen(tmp)+1, tmp);
585     } else {
586         count += packet_count;
587         fprintf(stderr, "\rPackets: %u ", count);
588         /* stderr could be line buffered */
589         fflush(stderr);
590     }
591
592 }
593
594 void
595 sync_pipe_filename_to_parent(const char *filename)
596 {
597
598     g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_MESSAGE, "File: %s", filename);
599
600     if(capture_child) {
601         pipe_write_block(1, SP_FILE, strlen(filename)+1, filename);
602     }
603 }
604
605 void
606 sync_pipe_errmsg_to_parent(const char *errmsg)
607 {
608
609     g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_MESSAGE, "Error: %s", errmsg);
610
611     if(capture_child) {
612         pipe_write_block(1, SP_ERROR_MSG, strlen(errmsg)+1, errmsg);
613     }
614 }
615
616 void
617 sync_pipe_drops_to_parent(int drops)
618 {
619     char tmp[SP_DECISIZE+1+1];
620
621
622     g_snprintf(tmp, sizeof(tmp), "%d", drops);
623     g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_MESSAGE, "Packets dropped: %s", tmp);
624
625     if(capture_child) {
626         pipe_write_block(1, SP_DROPS, strlen(tmp)+1, tmp);
627     }
628 }
629
630
631 /****************************************************************************************************************/
632 /* signal_pipe handling */
633
634
635 #ifdef _WIN32
636 gboolean
637 signal_pipe_check_running(void)
638 {
639     /* any news from our parent (stdin)? -> just stop the capture */
640     HANDLE handle;
641     DWORD avail = 0;
642     gboolean result;
643
644
645     /* if we are running standalone, no check required */
646     if(!capture_child) {
647         return TRUE;
648     }
649
650     handle = (HANDLE) GetStdHandle(STD_INPUT_HANDLE);
651     result = PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL);
652
653     if(!result || avail > 0) {
654         /* peek failed or some bytes really available */
655         /* (if not piping from stdin this would fail) */
656         g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO,
657             "Signal pipe: Stop capture");
658         g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
659             "Signal pipe: handle: %x result: %u avail: %u", handle, result, avail);
660         return FALSE;
661     } else {
662         /* pipe ok and no bytes available */
663         return TRUE;
664     }
665 }
666 #endif
667
668
669 /****************************************************************************************************************/
670 /* simple_dialog stubs */
671
672
673 char *simple_dialog_primary_start(void)
674 {
675     return "";
676 }
677
678 char *simple_dialog_primary_end(void)
679 {
680     return "";
681 }
682
683 char *
684 simple_dialog_format_message(const char *msg)
685 {
686     char *str;
687
688     if (msg) {
689 #if GTK_MAJOR_VERSION < 2
690         str = g_strdup(msg);
691 #else
692         str = xml_escape(msg);
693 #endif
694     } else {
695         str = NULL;
696     }
697     return str;
698 }
699
700
701 /****************************************************************************************************************/
702 /* Stub functions */
703
704
705 const char *netsnmp_get_version(void) { return ""; }
706
707 gboolean dfilter_compile(const gchar *text, dfilter_t **dfp) { (void)text; (void)dfp; return FALSE; }
708
709 void dfilter_free(dfilter_t *df) { (void)df; }