Steve Karg:
[obnox/wireshark/wip.git] / capture_opts.c
1 /* capture_opts.c
2  * Routines for capture options setting
3  *
4  * $Id$
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #ifdef HAVE_LIBPCAP
30
31 #include <string.h>
32 #include <ctype.h>
33
34 #include <pcap.h>
35
36 #include <glib.h>
37
38 #include <epan/packet.h>
39
40 #include "capture.h"
41 #include "capture_opts.h"
42 #include "ringbuffer.h"
43 #include "clopts_common.h"
44 #include "cmdarg_err.h"
45
46 #include "capture-pcap-util.h"
47 #include "capture_ui_utils.h"
48
49
50
51 void
52 capture_opts_init(capture_options *capture_opts, void *cfile)
53 {
54   capture_opts->cf                      = cfile;            
55   capture_opts->cfilter                     = g_strdup("");     /* No capture filter string specified */
56   capture_opts->iface                   = NULL;             /* Default is "pick the first interface" */
57 #ifdef _WIN32
58   capture_opts->buffer_size             = 1;                /* 1 MB */
59 #endif
60   capture_opts->has_snaplen             = FALSE;
61   capture_opts->snaplen                 = WTAP_MAX_PACKET_SIZE; /* snapshot length - default is
62                                                                     infinite, in effect */
63   capture_opts->promisc_mode            = TRUE;             /* promiscuous mode is the default */
64   capture_opts->linktype                = -1;               /* the default linktype */
65   capture_opts->save_file               = NULL;
66   capture_opts->real_time_mode          = TRUE;
67   capture_opts->show_info               = TRUE;
68   capture_opts->quit_after_cap          = FALSE;
69   capture_opts->restart                 = FALSE;
70
71   capture_opts->multi_files_on          = FALSE;
72   capture_opts->has_file_duration       = FALSE;
73   capture_opts->file_duration           = 60;               /* 1 min */
74   capture_opts->has_ring_num_files      = FALSE;
75   capture_opts->ring_num_files          = RINGBUFFER_MIN_NUM_FILES;
76
77   capture_opts->has_autostop_files      = FALSE;
78   capture_opts->autostop_files          = 1;
79   capture_opts->has_autostop_packets    = FALSE;            
80   capture_opts->autostop_packets        = 0;
81   capture_opts->has_autostop_filesize   = FALSE;
82   capture_opts->autostop_filesize       = 1024;             /* 1 MB */
83   capture_opts->has_autostop_duration   = FALSE;
84   capture_opts->autostop_duration       = 60;               /* 1 min */
85
86
87   capture_opts->fork_child              = -1;               /* invalid process handle */
88 #ifdef _WIN32
89   capture_opts->signal_pipe_fd          = -1;
90 #endif
91   capture_opts->state                   = CAPTURE_STOPPED;
92 }
93
94
95 /* log content of capture_opts */
96 void
97 capture_opts_log(const char *log_domain, GLogLevelFlags log_level, capture_options *capture_opts) {
98     g_log(log_domain, log_level, "CAPTURE OPTIONS    :");
99     g_log(log_domain, log_level, "CFile              : 0x%p", capture_opts->cf);
100     g_log(log_domain, log_level, "Filter             : %s", capture_opts->cfilter);
101     g_log(log_domain, log_level, "Interface          : %s", capture_opts->iface);
102 #ifdef _WIN32
103     g_log(log_domain, log_level, "BufferSize         : %u (MB)", capture_opts->buffer_size);
104 #endif
105     g_log(log_domain, log_level, "SnapLen         (%u): %u", capture_opts->has_snaplen, capture_opts->snaplen);
106     g_log(log_domain, log_level, "Promisc            : %u", capture_opts->promisc_mode);
107     g_log(log_domain, log_level, "LinkType           : %d", capture_opts->linktype);
108     g_log(log_domain, log_level, "SaveFile           : %s", (capture_opts->save_file) ? capture_opts->save_file : "");
109     g_log(log_domain, log_level, "RealTimeMode       : %u", capture_opts->real_time_mode);
110     g_log(log_domain, log_level, "ShowInfo           : %u", capture_opts->show_info);
111     g_log(log_domain, log_level, "QuitAfterCap       : %u", capture_opts->quit_after_cap);
112
113     g_log(log_domain, log_level, "MultiFilesOn       : %u", capture_opts->multi_files_on);
114     g_log(log_domain, log_level, "FileDuration    (%u): %u", capture_opts->has_file_duration, capture_opts->file_duration);
115     g_log(log_domain, log_level, "RingNumFiles    (%u): %u", capture_opts->has_ring_num_files, capture_opts->ring_num_files);
116
117     g_log(log_domain, log_level, "AutostopFiles   (%u): %u", capture_opts->has_autostop_files, capture_opts->autostop_files);
118     g_log(log_domain, log_level, "AutostopPackets (%u): %u", capture_opts->has_autostop_packets, capture_opts->autostop_packets);
119     g_log(log_domain, log_level, "AutostopFilesize(%u): %u (KB)", capture_opts->has_autostop_filesize, capture_opts->autostop_filesize);
120     g_log(log_domain, log_level, "AutostopDuration(%u): %u", capture_opts->has_autostop_duration, capture_opts->autostop_duration);
121
122     g_log(log_domain, log_level, "ForkChild          : %d", capture_opts->fork_child);
123 #ifdef _WIN32
124     g_log(log_domain, log_level, "SignalPipeFd       : %d", capture_opts->signal_pipe_fd);
125 #endif
126 }
127
128 /*
129  * Given a string of the form "<autostop criterion>:<value>", as might appear
130  * as an argument to a "-a" option, parse it and set the criterion in
131  * question.  Return an indication of whether it succeeded or failed
132  * in some fashion.
133  */
134 static gboolean
135 set_autostop_criterion(capture_options *capture_opts, const char *autostoparg)
136 {
137   gchar *p, *colonp;
138
139   colonp = strchr(autostoparg, ':');
140   if (colonp == NULL)
141     return FALSE;
142
143   p = colonp;
144   *p++ = '\0';
145
146   /*
147    * Skip over any white space (there probably won't be any, but
148    * as we allow it in the preferences file, we might as well
149    * allow it here).
150    */
151   while (isspace((guchar)*p))
152     p++;
153   if (*p == '\0') {
154     /*
155      * Put the colon back, so if our caller uses, in an
156      * error message, the string they passed us, the message
157      * looks correct.
158      */
159     *colonp = ':';
160     return FALSE;
161   }
162   if (strcmp(autostoparg,"duration") == 0) {
163     capture_opts->has_autostop_duration = TRUE;
164     capture_opts->autostop_duration = get_positive_int(p,"autostop duration");
165   } else if (strcmp(autostoparg,"filesize") == 0) {
166     capture_opts->has_autostop_filesize = TRUE;
167     capture_opts->autostop_filesize = get_positive_int(p,"autostop filesize");
168   } else if (strcmp(autostoparg,"files") == 0) {
169     capture_opts->multi_files_on = TRUE;
170     capture_opts->has_autostop_files = TRUE;
171     capture_opts->autostop_files = get_positive_int(p,"autostop files");
172   } else {
173     return FALSE;
174   }
175   *colonp = ':'; /* put the colon back */
176   return TRUE;
177 }
178
179 /*
180  * Given a string of the form "<ring buffer file>:<duration>", as might appear
181  * as an argument to a "-b" option, parse it and set the arguments in
182  * question.  Return an indication of whether it succeeded or failed
183  * in some fashion.
184  */
185 static gboolean
186 get_ring_arguments(capture_options *capture_opts, const char *arg)
187 {
188   gchar *p = NULL, *colonp;
189
190   colonp = strchr(arg, ':');
191   if (colonp == NULL)
192     return TRUE;
193
194   p = colonp;
195   *p++ = '\0';
196
197   /*
198    * Skip over any white space (there probably won't be any, but
199    * as we allow it in the preferences file, we might as well
200    * allow it here).
201    */
202   while (isspace((guchar)*p))
203     p++;
204   if (*p == '\0') {
205     /*
206      * Put the colon back, so if our caller uses, in an
207      * error message, the string they passed us, the message
208      * looks correct.
209      */
210     *colonp = ':';
211     return FALSE;
212   }
213
214   if (strcmp(arg,"files") == 0) {
215     capture_opts->has_ring_num_files = TRUE;
216     capture_opts->ring_num_files = get_natural_int(p, "number of ring buffer files");
217   } else if (strcmp(arg,"filesize") == 0) {
218     capture_opts->has_autostop_filesize = TRUE;
219     capture_opts->autostop_filesize = get_positive_int(p, "ring buffer filesize");
220   } else if (strcmp(arg,"duration") == 0) {
221     capture_opts->has_file_duration = TRUE;
222     capture_opts->file_duration = get_positive_int(p, "ring buffer duration");
223   }
224
225   *colonp = ':';        /* put the colon back */
226   return TRUE;
227 }
228
229
230 #ifdef _WIN32
231 /*
232  * Given a string of the form "<pipe name>:<file descriptor>", as might appear
233  * as an argument to a "-Z" option, parse it and set the arguments in
234  * question.  Return an indication of whether it succeeded or failed
235  * in some fashion.
236  */
237 static gboolean
238 get_pipe_arguments(capture_options *capture_opts, const char *arg)
239 {
240   gchar *p = NULL, *colonp;
241   int pipe_fd;
242
243
244   colonp = strchr(arg, ':');
245   if (colonp == NULL)
246     return TRUE;
247
248   p = colonp;
249   *p++ = '\0';
250
251   /*
252    * Skip over any white space (there probably won't be any, but
253    * as we allow it in the preferences file, we might as well
254    * allow it here).
255    */
256   while (isspace((guchar)*p))
257     p++;
258   if (*p == '\0') {
259     /*
260      * Put the colon back, so if our caller uses, in an
261      * error message, the string they passed us, the message
262      * looks correct.
263      */
264     *colonp = ':';
265     return FALSE;
266   }
267
268   if (strcmp(arg,"sync") == 0) {
269     /* associate stdout with sync pipe */
270     pipe_fd = get_natural_int(p, "sync pipe file descriptor");
271     if (dup2(pipe_fd, 1) < 0) {
272       cmdarg_err("Unable to dup sync pipe handle");
273       return FALSE;
274     }
275   } else if (strcmp(arg,"signal") == 0) {
276     /* associate stdin with signal pipe */
277     pipe_fd = get_natural_int(p, "signal pipe file descriptor");
278     if (dup2(pipe_fd, 0) < 0) {
279       cmdarg_err("Unable to dup signal pipe handle");
280       return FALSE;
281     }
282     capture_opts->signal_pipe_fd = pipe_fd;
283   }
284
285   *colonp = ':';        /* put the colon back */
286   return TRUE;
287 }
288 #endif
289
290
291 void
292 capture_opts_add_iface_opt(capture_options *capture_opts, const char *optarg)
293 {
294     long        adapter_index;
295     char        *p;
296     GList       *if_list;
297     if_info_t   *if_info;
298     int         err;
299     gchar       err_str[PCAP_ERRBUF_SIZE];
300     gchar       *cant_get_if_list_errstr;
301
302
303     /*
304      * If the argument is a number, treat it as an index into the list
305      * of adapters, as printed by "tethereal -D".
306      *
307      * This should be OK on UNIX systems, as interfaces shouldn't have
308      * names that begin with digits.  It can be useful on Windows, where
309      * more than one interface can have the same name.
310      */
311     adapter_index = strtol(optarg, &p, 10);
312     if (p != NULL && *p == '\0') {
313       if (adapter_index < 0) {
314         cmdarg_err("The specified adapter index is a negative number");
315        exit(1);
316       }
317       if (adapter_index > INT_MAX) {
318         cmdarg_err("The specified adapter index is too large (greater than %d)",
319             INT_MAX);
320         exit(1);
321       }
322       if (adapter_index == 0) {
323         cmdarg_err("there is no interface with that adapter index");
324         exit(1);
325       }
326       if_list = get_interface_list(&err, err_str);
327       if (if_list == NULL) {
328         switch (err) {
329
330         case CANT_GET_INTERFACE_LIST:
331             cant_get_if_list_errstr =
332                 cant_get_if_list_error_message(err_str);
333             cmdarg_err("%s", cant_get_if_list_errstr);
334             g_free(cant_get_if_list_errstr);
335             break;
336
337         case NO_INTERFACES_FOUND:
338             cmdarg_err("There are no interfaces on which a capture can be done");
339             break;
340         }
341         exit(2);
342       }
343       if_info = g_list_nth_data(if_list, adapter_index - 1);
344       if (if_info == NULL) {
345         cmdarg_err("there is no interface with that adapter index");
346         exit(1);
347       }
348       capture_opts->iface = g_strdup(if_info->name);
349       free_interface_list(if_list);
350     } else {
351       capture_opts->iface = g_strdup(optarg);
352     }
353 }
354
355 void
356 capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg, gboolean *start_capture)
357 {
358     switch(opt) {
359     case 'a':        /* autostop criteria */
360         if (set_autostop_criterion(capture_opts, optarg) == FALSE) {
361           cmdarg_err("Invalid or unknown -a flag \"%s\"", optarg);
362           exit(1);
363         }
364         break;
365     case 'b':        /* Ringbuffer option */
366         capture_opts->multi_files_on = TRUE;
367         if (get_ring_arguments(capture_opts, optarg) == FALSE) {
368           cmdarg_err("Invalid or unknown -b arg \"%s\"", optarg);
369           exit(1);
370         }
371         break;
372 #ifdef _WIN32
373     case 'B':        /* Buffer size */
374         capture_opts->buffer_size = get_positive_int(optarg, "buffer size");
375         break;
376 #endif
377     case 'c':        /* Capture xxx packets */
378         capture_opts->has_autostop_packets = TRUE;
379         capture_opts->autostop_packets = get_positive_int(optarg, "packet count");
380         break;
381     case 'f':        /* capture filter */
382         if (capture_opts->cfilter)
383             g_free(capture_opts->cfilter);
384         capture_opts->cfilter = g_strdup(optarg);
385         break;
386     case 'H':        /* Hide capture info dialog box */
387         capture_opts->show_info = FALSE;
388         break;
389     case 'i':        /* Use interface xxx */
390         capture_opts_add_iface_opt(capture_opts, optarg);
391         break;
392     case 'k':        /* Start capture immediately */
393         *start_capture = TRUE;
394         break;
395     /*case 'l':*/    /* Automatic scrolling in live capture mode */
396     case 'p':        /* Don't capture in promiscuous mode */
397         capture_opts->promisc_mode = FALSE;
398         break;
399     case 'Q':        /* Quit after capture (just capture to file) */
400         capture_opts->quit_after_cap  = TRUE;
401         *start_capture   = TRUE;  /*** -Q implies -k !! ***/
402         break;
403     case 's':        /* Set the snapshot (capture) length */
404         capture_opts->has_snaplen = TRUE;
405         capture_opts->snaplen = get_positive_int(optarg, "snapshot length");
406         break;
407     case 'S':        /* "Real-Time" mode: used for following file ala tail -f */
408         capture_opts->real_time_mode = TRUE;
409         break;
410     case 'w':        /* Write to capture file xxx */
411         capture_opts->save_file = g_strdup(optarg);
412             break;
413     case 'y':        /* Set the pcap data link type */
414 #ifdef HAVE_PCAP_DATALINK_NAME_TO_VAL
415         capture_opts->linktype = pcap_datalink_name_to_val(optarg);
416         if (capture_opts->linktype == -1) {
417           cmdarg_err("The specified data link type \"%s\" isn't valid",
418                   optarg);
419           exit(1);
420         }
421 #else /* HAVE_PCAP_DATALINK_NAME_TO_VAL */
422         /* XXX - just treat it as a number */
423         capture_opts->linktype = get_natural_int(optarg, "data link type");
424 #endif /* HAVE_PCAP_DATALINK_NAME_TO_VAL */
425         break;
426 #ifdef _WIN32
427       /* Hidden option supporting Sync mode */
428     case 'Z':        /* Write to pipe FD XXX */
429        if (get_pipe_arguments(capture_opts, optarg) == FALSE) {
430           cmdarg_err("Invalid or unknown -Z flag \"%s\"", optarg);
431           exit(1);
432         }
433         break;
434 #endif /* _WIN32 */
435     default:
436         /* the caller is responsible to send us only the right opt's */
437         g_assert_not_reached();
438     }
439 }
440
441
442 void capture_opts_list_link_layer_types(capture_options *capture_opts)
443 {
444     gchar err_str[PCAP_ERRBUF_SIZE];
445     GList *lt_list, *lt_entry;
446     data_link_info_t *data_link_info;
447
448     /* Get the list of link-layer types for the capture device. */
449     lt_list = get_pcap_linktype_list(capture_opts->iface, err_str);
450     if (lt_list == NULL) {
451       if (err_str[0] != '\0') {
452         cmdarg_err("The list of data link types for the capture device could not be obtained (%s)."
453           "Please check to make sure you have sufficient permissions, and that\n"
454           "you have the proper interface or pipe specified.\n", err_str);
455       } else
456         cmdarg_err("The capture device has no data link types.");
457       exit(2);
458     }
459     cmdarg_err_cont("Data link types (use option -y to set):");
460     for (lt_entry = lt_list; lt_entry != NULL;
461          lt_entry = g_list_next(lt_entry)) {
462       data_link_info = lt_entry->data;
463       cmdarg_err_cont("  %s", data_link_info->name);
464       if (data_link_info->description != NULL)
465         cmdarg_err_cont(" (%s)", data_link_info->description);
466       else
467         cmdarg_err_cont(" (not supported)");
468       putchar('\n');
469     }
470     free_pcap_linktype_list(lt_list);
471 }
472
473
474 void capture_opts_list_interfaces()
475 {
476     GList       *if_list;
477     GList       *if_entry;
478     if_info_t   *if_info;
479     int         err;
480     gchar       err_str[PCAP_ERRBUF_SIZE];
481     gchar       *cant_get_if_list_errstr;
482     int         i;
483
484
485     if_list = get_interface_list(&err, err_str);
486     if (if_list == NULL) {
487         switch (err) {
488         case CANT_GET_INTERFACE_LIST:
489             cant_get_if_list_errstr = cant_get_if_list_error_message(err_str);
490             cmdarg_err("%s", cant_get_if_list_errstr);
491             g_free(cant_get_if_list_errstr);
492         break;
493
494         case NO_INTERFACES_FOUND:
495             cmdarg_err("There are no interfaces on which a capture can be done");
496         break;
497         }
498         exit(2);
499     }
500
501     i = 1;  /* Interface id number */
502     for (if_entry = g_list_first(if_list); if_entry != NULL;
503     if_entry = g_list_next(if_entry)) {
504         if_info = if_entry->data;
505         printf("%d. %s", i++, if_info->name);
506         if (if_info->description != NULL)
507             printf(" (%s)", if_info->description);
508         printf("\n");
509     }
510     free_interface_list(if_list);
511 }
512
513
514 void capture_opts_trim_snaplen(capture_options *capture_opts, int snaplen_min)
515 {
516   if (capture_opts->snaplen < 1)
517     capture_opts->snaplen = WTAP_MAX_PACKET_SIZE;
518   else if (capture_opts->snaplen < snaplen_min)
519     capture_opts->snaplen = snaplen_min;
520 }
521
522
523 void capture_opts_trim_ring_num_files(capture_options *capture_opts)
524 {
525   /* Check the value range of the ring_num_files parameter */
526   if (capture_opts->ring_num_files > RINGBUFFER_MAX_NUM_FILES)
527     capture_opts->ring_num_files = RINGBUFFER_MAX_NUM_FILES;
528 #if RINGBUFFER_MIN_NUM_FILES > 0
529   else if (capture_opts->ring_num_files < RINGBUFFER_MIN_NUM_FILES)
530     capture_opts->ring_num_files = RINGBUFFER_MIN_NUM_FILES;
531 #endif
532 }
533
534
535 gboolean capture_opts_trim_iface(capture_options *capture_opts, const char *capture_device)
536 {
537     GList       *if_list;
538     if_info_t   *if_info;
539     int         err;
540     gchar       err_str[PCAP_ERRBUF_SIZE];
541     gchar       *cant_get_if_list_errstr;
542
543
544     /* Did the user specify an interface to use? */
545     if (capture_opts->iface == NULL) {
546       /* No - is a default specified in the preferences file? */
547       if (capture_device != NULL) {
548           /* Yes - use it. */
549           capture_opts->iface = g_strdup(capture_device);
550       } else {
551         /* No - pick the first one from the list of interfaces. */
552         if_list = get_interface_list(&err, err_str);
553         if (if_list == NULL) {
554           switch (err) {
555
556           case CANT_GET_INTERFACE_LIST:
557               cant_get_if_list_errstr = cant_get_if_list_error_message(err_str);
558               cmdarg_err("%s", cant_get_if_list_errstr);
559               g_free(cant_get_if_list_errstr);
560               break;
561
562           case NO_INTERFACES_FOUND:
563               cmdarg_err("There are no interfaces on which a capture can be done");
564               break;
565           }
566           return FALSE;
567         }
568         if_info = if_list->data;        /* first interface */
569         capture_opts->iface = g_strdup(if_info->name);
570         free_interface_list(if_list);
571       }
572     }
573
574     return TRUE;
575 }
576
577
578 #endif /* HAVE_LIBPCAP */