From Jakub Zawadzki via bug 4273:
[obnox/wireshark/wip.git] / capture_opts.c
1 /* capture_opts.c
2  * Routines for capture options setting
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
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 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37
38 #include <glib.h>
39
40 #include <epan/packet.h>
41
42 #include "capture_opts.h"
43 #include "ringbuffer.h"
44 #include "clopts_common.h"
45 #include "console_io.h"
46 #include "cmdarg_err.h"
47
48 #include "capture_ifinfo.h"
49 #include "capture-pcap-util.h"
50 #include <wsutil/file_util.h>
51
52 static gboolean capture_opts_output_to_pipe(const char *save_file, gboolean *is_pipe);
53
54
55 void
56 capture_opts_init(capture_options *capture_opts, void *cf)
57 {
58   capture_opts->cf                      = cf;
59   capture_opts->cfilter                 = g_strdup("");     /* No capture filter string specified */
60   capture_opts->iface                   = NULL;             /* Default is "pick the first interface" */
61   capture_opts->iface_descr             = NULL;
62 #ifdef HAVE_PCAP_REMOTE
63   capture_opts->src_type                = CAPTURE_IFLOCAL;
64   capture_opts->remote_host             = NULL;
65   capture_opts->remote_port             = NULL;
66   capture_opts->auth_type               = CAPTURE_AUTH_NULL;
67   capture_opts->auth_username           = NULL;
68   capture_opts->auth_password           = NULL;
69   capture_opts->datatx_udp              = FALSE;
70   capture_opts->nocap_rpcap             = TRUE;
71   capture_opts->nocap_local             = FALSE;
72 #ifdef HAVE_PCAP_SETSAMPLING
73   capture_opts->sampling_method         = CAPTURE_SAMP_NONE;
74   capture_opts->sampling_param          = 0;
75 #endif
76 #endif
77 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
78   capture_opts->buffer_size             = 1;                /* 1 MB */
79 #endif
80   capture_opts->has_snaplen             = FALSE;
81   capture_opts->snaplen                 = WTAP_MAX_PACKET_SIZE; /* snapshot length - default is
82                                                                    infinite, in effect */
83   capture_opts->promisc_mode            = TRUE;             /* promiscuous mode is the default */
84   capture_opts->monitor_mode            = FALSE;
85   capture_opts->linktype                = -1;               /* the default linktype */
86   capture_opts->saving_to_file          = FALSE;
87   capture_opts->save_file               = NULL;
88   capture_opts->use_pcapng              = FALSE;            /* the default is pcap */
89   capture_opts->real_time_mode          = TRUE;
90   capture_opts->show_info               = TRUE;
91   capture_opts->quit_after_cap          = FALSE;
92   capture_opts->restart                 = FALSE;
93
94   capture_opts->multi_files_on          = FALSE;
95   capture_opts->has_file_duration       = FALSE;
96   capture_opts->file_duration           = 60;               /* 1 min */
97   capture_opts->has_ring_num_files      = FALSE;
98   capture_opts->ring_num_files          = RINGBUFFER_MIN_NUM_FILES;
99
100   capture_opts->has_autostop_files      = FALSE;
101   capture_opts->autostop_files          = 1;
102   capture_opts->has_autostop_packets    = FALSE;
103   capture_opts->autostop_packets        = 0;
104   capture_opts->has_autostop_filesize   = FALSE;
105   capture_opts->autostop_filesize       = 1024;             /* 1 MB */
106   capture_opts->has_autostop_duration   = FALSE;
107   capture_opts->autostop_duration       = 60;               /* 1 min */
108
109
110   capture_opts->fork_child              = -1;               /* invalid process handle */
111 #ifdef _WIN32
112   capture_opts->signal_pipe_write_fd    = -1;
113 #endif
114   capture_opts->state                   = CAPTURE_STOPPED;
115   capture_opts->output_to_pipe          = FALSE;
116 #ifndef _WIN32
117   capture_opts->owner                   = getuid();
118   capture_opts->group                   = getgid();
119 #endif
120 }
121
122
123 /* log content of capture_opts */
124 void
125 capture_opts_log(const char *log_domain, GLogLevelFlags log_level, capture_options *capture_opts) {
126     g_log(log_domain, log_level, "CAPTURE OPTIONS    :");
127     g_log(log_domain, log_level, "CFile              : 0x%p", capture_opts->cf);
128     g_log(log_domain, log_level, "Filter             : %s", capture_opts->cfilter);
129     g_log(log_domain, log_level, "Interface          : %s", capture_opts->iface);
130     /* iface_descr may not been filled in and some C Libraries hate a null ptr for %s */
131     g_log(log_domain, log_level, "Interface Descr    : %s",
132           capture_opts->iface_descr ? capture_opts->iface_descr : "<null>");
133 #ifdef HAVE_PCAP_REMOTE
134     g_log(log_domain, log_level, "Capture source     : %s",
135         capture_opts->src_type == CAPTURE_IFLOCAL ? "Local interface" :
136         capture_opts->src_type == CAPTURE_IFREMOTE ? "Remote interface" :
137         "Unknown");
138     if (capture_opts->src_type == CAPTURE_IFREMOTE) {
139         g_log(log_domain, log_level, "Remote host        : %s", capture_opts->remote_host);
140         g_log(log_domain, log_level, "Remote port        : %s", capture_opts->remote_port);
141     }
142     g_log(log_domain, log_level, "Authentication     : %s",
143         capture_opts->auth_type == CAPTURE_AUTH_NULL ? "Null" :
144         capture_opts->auth_type == CAPTURE_AUTH_PWD ? "By username/password" :
145         "Unknown");
146     if (capture_opts->auth_type == CAPTURE_AUTH_PWD) {
147         g_log(log_domain, log_level, "Auth username      : %s", capture_opts->auth_password);
148         g_log(log_domain, log_level, "Auth password      : <hidden>");
149     }
150     g_log(log_domain, log_level, "UDP data transfer  : %u", capture_opts->datatx_udp);
151     g_log(log_domain, log_level, "No capture RPCAP   : %u", capture_opts->nocap_rpcap);
152     g_log(log_domain, log_level, "No capture local   : %u", capture_opts->nocap_local);
153 #endif
154 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
155     g_log(log_domain, log_level, "BufferSize         : %u (MB)", capture_opts->buffer_size);
156 #endif
157     g_log(log_domain, log_level, "SnapLen         (%u): %u", capture_opts->has_snaplen, capture_opts->snaplen);
158     g_log(log_domain, log_level, "Promisc            : %u", capture_opts->promisc_mode);
159     g_log(log_domain, log_level, "LinkType           : %d", capture_opts->linktype);
160     g_log(log_domain, log_level, "SavingToFile       : %u", capture_opts->saving_to_file);
161     g_log(log_domain, log_level, "SaveFile           : %s", (capture_opts->save_file) ? capture_opts->save_file : "");
162     g_log(log_domain, log_level, "Fileformat         : %s", (capture_opts->use_pcapng) ? "PCAPNG" : "PCAP");
163     g_log(log_domain, log_level, "RealTimeMode       : %u", capture_opts->real_time_mode);
164     g_log(log_domain, log_level, "ShowInfo           : %u", capture_opts->show_info);
165     g_log(log_domain, log_level, "QuitAfterCap       : %u", capture_opts->quit_after_cap);
166
167     g_log(log_domain, log_level, "MultiFilesOn       : %u", capture_opts->multi_files_on);
168     g_log(log_domain, log_level, "FileDuration    (%u): %u", capture_opts->has_file_duration, capture_opts->file_duration);
169     g_log(log_domain, log_level, "RingNumFiles    (%u): %u", capture_opts->has_ring_num_files, capture_opts->ring_num_files);
170
171     g_log(log_domain, log_level, "AutostopFiles   (%u): %u", capture_opts->has_autostop_files, capture_opts->autostop_files);
172     g_log(log_domain, log_level, "AutostopPackets (%u): %u", capture_opts->has_autostop_packets, capture_opts->autostop_packets);
173     g_log(log_domain, log_level, "AutostopFilesize(%u): %u (KB)", capture_opts->has_autostop_filesize, capture_opts->autostop_filesize);
174     g_log(log_domain, log_level, "AutostopDuration(%u): %u", capture_opts->has_autostop_duration, capture_opts->autostop_duration);
175
176     g_log(log_domain, log_level, "ForkChild          : %d", capture_opts->fork_child);
177 #ifdef _WIN32
178     g_log(log_domain, log_level, "SignalPipeWrite    : %d", capture_opts->signal_pipe_write_fd);
179 #endif
180 }
181
182 /*
183  * Given a string of the form "<autostop criterion>:<value>", as might appear
184  * as an argument to a "-a" option, parse it and set the criterion in
185  * question.  Return an indication of whether it succeeded or failed
186  * in some fashion.
187  */
188 static gboolean
189 set_autostop_criterion(capture_options *capture_opts, const char *autostoparg)
190 {
191   gchar *p, *colonp;
192
193   colonp = strchr(autostoparg, ':');
194   if (colonp == NULL)
195     return FALSE;
196
197   p = colonp;
198   *p++ = '\0';
199
200   /*
201    * Skip over any white space (there probably won't be any, but
202    * as we allow it in the preferences file, we might as well
203    * allow it here).
204    */
205   while (isspace((guchar)*p))
206     p++;
207   if (*p == '\0') {
208     /*
209      * Put the colon back, so if our caller uses, in an
210      * error message, the string they passed us, the message
211      * looks correct.
212      */
213     *colonp = ':';
214     return FALSE;
215   }
216   if (strcmp(autostoparg,"duration") == 0) {
217     capture_opts->has_autostop_duration = TRUE;
218     capture_opts->autostop_duration = get_positive_int(p,"autostop duration");
219   } else if (strcmp(autostoparg,"filesize") == 0) {
220     capture_opts->has_autostop_filesize = TRUE;
221     capture_opts->autostop_filesize = get_positive_int(p,"autostop filesize");
222   } else if (strcmp(autostoparg,"files") == 0) {
223     capture_opts->multi_files_on = TRUE;
224     capture_opts->has_autostop_files = TRUE;
225     capture_opts->autostop_files = get_positive_int(p,"autostop files");
226   } else {
227     return FALSE;
228   }
229   *colonp = ':'; /* put the colon back */
230   return TRUE;
231 }
232
233 /*
234  * Given a string of the form "<ring buffer file>:<duration>", as might appear
235  * as an argument to a "-b" option, parse it and set the arguments in
236  * question.  Return an indication of whether it succeeded or failed
237  * in some fashion.
238  */
239 static gboolean
240 get_ring_arguments(capture_options *capture_opts, const char *arg)
241 {
242   gchar *p = NULL, *colonp;
243
244   colonp = strchr(arg, ':');
245   if (colonp == NULL)
246     return FALSE;
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,"files") == 0) {
269     capture_opts->has_ring_num_files = TRUE;
270     capture_opts->ring_num_files = get_natural_int(p, "number of ring buffer files");
271   } else if (strcmp(arg,"filesize") == 0) {
272     capture_opts->has_autostop_filesize = TRUE;
273     capture_opts->autostop_filesize = get_positive_int(p, "ring buffer filesize");
274   } else if (strcmp(arg,"duration") == 0) {
275     capture_opts->has_file_duration = TRUE;
276     capture_opts->file_duration = get_positive_int(p, "ring buffer duration");
277   }
278
279   *colonp = ':';    /* put the colon back */
280   return TRUE;
281 }
282
283 #ifdef HAVE_PCAP_SETSAMPLING
284 /*
285  * Given a string of the form "<sampling type>:<value>", as might appear
286  * as an argument to a "-m" option, parse it and set the arguments in
287  * question.  Return an indication of whether it succeeded or failed
288  * in some fashion.
289  */
290 static gboolean
291 get_sampling_arguments(capture_options *capture_opts, const char *arg)
292 {
293     gchar *p = NULL, *colonp;
294
295     colonp = strchr(arg, ':');
296     if (colonp == NULL)
297         return FALSE;
298
299     p = colonp;
300     *p++ = '\0';
301
302     while (isspace((guchar)*p))
303         p++;
304     if (*p == '\0') {
305         *colonp = ':';
306         return FALSE;
307     }
308
309     if (strcmp(arg, "count") == 0) {
310         capture_opts->sampling_method = CAPTURE_SAMP_BY_COUNT;
311         capture_opts->sampling_param = get_positive_int(p, "sampling count");
312     } else if (strcmp(arg, "timer") == 0) {
313         capture_opts->sampling_method = CAPTURE_SAMP_BY_TIMER;
314         capture_opts->sampling_param = get_positive_int(p, "sampling timer");
315     }
316     *colonp = ':';
317     return TRUE;
318 }
319 #endif
320
321 #ifdef HAVE_PCAP_REMOTE
322 /*
323  * Given a string of the form "<username>:<password>", as might appear
324  * as an argument to a "-A" option, parse it and set the arguments in
325  * question.  Return an indication of whether it succeeded or failed
326  * in some fashion.
327  */
328 static gboolean
329 get_auth_arguments(capture_options *capture_opts, const char *arg)
330 {
331     gchar *p = NULL, *colonp;
332
333     colonp = strchr(arg, ':');
334     if (colonp == NULL)
335         return FALSE;
336
337     p = colonp;
338     *p++ = '\0';
339
340     while (isspace((guchar)*p))
341         p++;
342
343     capture_opts->auth_type = CAPTURE_AUTH_PWD;
344     capture_opts->auth_username = g_strdup(arg);
345     capture_opts->auth_password = g_strdup(p);
346     *colonp = ':';
347     return TRUE;
348 }
349 #endif
350
351 static int
352 capture_opts_add_iface_opt(capture_options *capture_opts, const char *optarg_str_p)
353 {
354     long        adapter_index;
355     char        *p;
356     GList       *if_list;
357     if_info_t   *if_info;
358     int         err;
359     gchar       *err_str;
360
361
362     /*
363      * If the argument is a number, treat it as an index into the list
364      * of adapters, as printed by "tshark -D".
365      *
366      * This should be OK on UNIX systems, as interfaces shouldn't have
367      * names that begin with digits.  It can be useful on Windows, where
368      * more than one interface can have the same name.
369      */
370     adapter_index = strtol(optarg_str_p, &p, 10);
371     if (p != NULL && *p == '\0') {
372       if (adapter_index < 0) {
373         cmdarg_err("The specified adapter index is a negative number");
374         return 1;
375       }
376       if (adapter_index > INT_MAX) {
377         cmdarg_err("The specified adapter index is too large (greater than %d)",
378             INT_MAX);
379         return 1;
380       }
381       if (adapter_index == 0) {
382         cmdarg_err("There is no interface with that adapter index");
383         return 1;
384       }
385       if_list = capture_interface_list(&err, &err_str);
386       if (if_list == NULL) {
387         switch (err) {
388
389         case CANT_GET_INTERFACE_LIST:
390             cmdarg_err("%s", err_str);
391             g_free(err_str);
392             break;
393
394         case NO_INTERFACES_FOUND:
395             cmdarg_err("There are no interfaces on which a capture can be done");
396             break;
397         }
398         return 2;
399       }
400       if_info = (if_info_t *)g_list_nth_data(if_list, adapter_index - 1);
401       if (if_info == NULL) {
402         cmdarg_err("There is no interface with that adapter index");
403         return 1;
404       }
405       capture_opts->iface = g_strdup(if_info->name);
406       /*  We don't set iface_descr here because doing so requires
407        *  capture_ui_utils.c which requires epan/prefs.c which is
408        *  probably a bit too much dependency for here...
409        */
410       free_interface_list(if_list);
411     } else {
412       capture_opts->iface = g_strdup(optarg_str_p);
413     }
414
415     return 0;
416 }
417
418 int
419 capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg_str_p, gboolean *start_capture)
420 {
421     int status;
422
423     switch(opt) {
424     case 'a':        /* autostop criteria */
425         if (set_autostop_criterion(capture_opts, optarg_str_p) == FALSE) {
426           cmdarg_err("Invalid or unknown -a flag \"%s\"", optarg_str_p);
427           return 1;
428         }
429         break;
430 #ifdef HAVE_PCAP_REMOTE
431     case 'A':
432         if (get_auth_arguments(capture_opts, optarg_str_p) == FALSE) {
433             cmdarg_err("Invalid or unknown -A arg \"%s\"", optarg_str_p);
434             return 1;
435         }
436         break;
437 #endif
438     case 'b':        /* Ringbuffer option */
439         capture_opts->multi_files_on = TRUE;
440         if (get_ring_arguments(capture_opts, optarg_str_p) == FALSE) {
441           cmdarg_err("Invalid or unknown -b arg \"%s\"", optarg_str_p);
442           return 1;
443         }
444         break;
445 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
446     case 'B':        /* Buffer size */
447         capture_opts->buffer_size = get_positive_int(optarg_str_p, "buffer size");
448         break;
449 #endif
450     case 'c':        /* Capture n packets */
451         capture_opts->has_autostop_packets = TRUE;
452         capture_opts->autostop_packets = get_positive_int(optarg_str_p, "packet count");
453         break;
454     case 'f':        /* capture filter */
455         if (capture_opts->has_cfilter) {
456             cmdarg_err("More than one -f argument specified");
457             return 1;
458         }
459         capture_opts->has_cfilter = TRUE;
460         g_free(capture_opts->cfilter);
461         capture_opts->cfilter = g_strdup(optarg_str_p);
462         break;
463     case 'H':        /* Hide capture info dialog box */
464         capture_opts->show_info = FALSE;
465         break;
466     case 'i':        /* Use interface x */
467         status = capture_opts_add_iface_opt(capture_opts, optarg_str_p);
468         if(status != 0) {
469             return status;
470         }
471         break;
472 #ifdef HAVE_PCAP_CREATE
473     case 'I':        /* Capture in monitor mode */
474         capture_opts->monitor_mode = TRUE;
475         break;
476 #endif
477     case 'k':        /* Start capture immediately */
478         *start_capture = TRUE;
479         break;
480     /*case 'l':*/    /* Automatic scrolling in live capture mode */
481 #ifdef HAVE_PCAP_SETSAMPLING
482     case 'm':
483         if (get_sampling_arguments(capture_opts, optarg_str_p) == FALSE) {
484             cmdarg_err("Invalid or unknown -m arg \"%s\"", optarg_str_p);
485             return 1;
486         }
487         break;
488 #endif
489     case 'n':        /* Use pcapng format */
490         capture_opts->use_pcapng = TRUE;
491         break;
492     case 'p':        /* Don't capture in promiscuous mode */
493         capture_opts->promisc_mode = FALSE;
494         break;
495     case 'Q':        /* Quit after capture (just capture to file) */
496         capture_opts->quit_after_cap  = TRUE;
497         *start_capture   = TRUE;  /*** -Q implies -k !! ***/
498         break;
499 #ifdef HAVE_PCAP_REMOTE
500     case 'r':
501         capture_opts->nocap_rpcap = FALSE;
502         break;
503 #endif
504     case 's':        /* Set the snapshot (capture) length */
505         capture_opts->has_snaplen = TRUE;
506         capture_opts->snaplen = get_natural_int(optarg_str_p, "snapshot length");
507         /*
508          * Make a snapshot length of 0 equivalent to the maximum packet
509          * length, mirroring what tcpdump does.
510          */
511         if (capture_opts->snaplen == 0)
512           capture_opts->snaplen = WTAP_MAX_PACKET_SIZE;
513         break;
514     case 'S':        /* "Real-Time" mode: used for following file ala tail -f */
515         capture_opts->real_time_mode = TRUE;
516         break;
517 #ifdef HAVE_PCAP_REMOTE
518     case 'u':
519         capture_opts->datatx_udp = TRUE;
520         break;
521 #endif
522     case 'w':        /* Write to capture file x */
523         capture_opts->saving_to_file = TRUE;
524         g_free(capture_opts->save_file);
525 #if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
526         /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
527         capture_opts->save_file = g_locale_to_utf8(optarg_str_p, -1, NULL, NULL, NULL);
528 #else
529         capture_opts->save_file = g_strdup(optarg_str_p);
530 #endif
531         status = capture_opts_output_to_pipe(capture_opts->save_file, &capture_opts->output_to_pipe);
532         return status;
533     case 'y':        /* Set the pcap data link type */
534         capture_opts->linktype = linktype_name_to_val(optarg_str_p);
535         if (capture_opts->linktype == -1) {
536           cmdarg_err("The specified data link type \"%s\" isn't valid",
537                   optarg_str_p);
538           return 1;
539         }
540         break;
541     default:
542         /* the caller is responsible to send us only the right opt's */
543         g_assert_not_reached();
544     }
545
546     return 0;
547 }
548
549 void
550 capture_opts_print_if_capabilities(if_capabilities_t *caps,
551                                    gboolean monitor_mode)
552 {
553     GList *lt_entry;
554     data_link_info_t *data_link_info;
555
556     if (caps->can_set_rfmon)
557         fprintf_stderr("Data link types when %sin monitor mode (use option -y to set):\n",
558                        monitor_mode ? "" : "not ");
559     else
560         fprintf_stderr("Data link types (use option -y to set):\n");
561     for (lt_entry = caps->data_link_types; lt_entry != NULL;
562          lt_entry = g_list_next(lt_entry)) {
563         data_link_info = (data_link_info_t *)lt_entry->data;
564         fprintf_stderr("  %s", data_link_info->name);
565         if (data_link_info->description != NULL)
566             fprintf_stderr(" (%s)", data_link_info->description);
567         else
568             fprintf_stderr(" (not supported)");
569         fprintf_stderr("\n");
570     }
571 }
572
573 /* Print an ASCII-formatted list of interfaces. */
574 void
575 capture_opts_print_interfaces(GList *if_list)
576 {
577     int         i;
578     GList       *if_entry;
579     if_info_t   *if_info;
580
581     i = 1;  /* Interface id number */
582     for (if_entry = g_list_first(if_list); if_entry != NULL;
583          if_entry = g_list_next(if_entry)) {
584         if_info = (if_info_t *)if_entry->data;
585         printf("%d. %s", i++, if_info->name);
586
587         /* Print the description if it exists */
588         if (if_info->description != NULL)
589             printf(" (%s)", if_info->description);
590         printf("\n");
591     }
592 }
593
594
595 void capture_opts_trim_snaplen(capture_options *capture_opts, int snaplen_min)
596 {
597   if (capture_opts->snaplen < 1)
598     capture_opts->snaplen = WTAP_MAX_PACKET_SIZE;
599   else if (capture_opts->snaplen < snaplen_min)
600     capture_opts->snaplen = snaplen_min;
601 }
602
603
604 void capture_opts_trim_ring_num_files(capture_options *capture_opts)
605 {
606   /* Check the value range of the ring_num_files parameter */
607   if (capture_opts->ring_num_files > RINGBUFFER_MAX_NUM_FILES) {
608     cmdarg_err("Too many ring buffer files (%u). Reducing to %u.\n", capture_opts->ring_num_files, RINGBUFFER_MAX_NUM_FILES);
609     capture_opts->ring_num_files = RINGBUFFER_MAX_NUM_FILES;
610   } else if (capture_opts->ring_num_files > RINGBUFFER_WARN_NUM_FILES) {
611     cmdarg_err("%u is a lot of ring buffer files.\n", capture_opts->ring_num_files);
612   }
613 #if RINGBUFFER_MIN_NUM_FILES > 0
614   else if (capture_opts->ring_num_files < RINGBUFFER_MIN_NUM_FILES)
615     cmdarg_err("Too few ring buffer files (%u). Increasing to %u.\n", capture_opts->ring_num_files, RINGBUFFER_MIN_NUM_FILES);
616     capture_opts->ring_num_files = RINGBUFFER_MIN_NUM_FILES;
617 #endif
618 }
619
620
621 gboolean capture_opts_trim_iface(capture_options *capture_opts, const char *capture_device)
622 {
623     GList       *if_list;
624     if_info_t   *if_info;
625     int         err;
626     gchar       *err_str;
627
628
629     /* Did the user specify an interface to use? */
630     if (capture_opts->iface == NULL) {
631       /* No - is a default specified in the preferences file? */
632       if (capture_device != NULL) {
633           /* Yes - use it. */
634           capture_opts->iface = g_strdup(capture_device);
635           /*  We don't set iface_descr here because doing so requires
636            *  capture_ui_utils.c which requires epan/prefs.c which is
637            *  probably a bit too much dependency for here...
638            */
639       } else {
640         /* No - pick the first one from the list of interfaces. */
641         if_list = capture_interface_list(&err, &err_str);
642         if (if_list == NULL) {
643           switch (err) {
644
645           case CANT_GET_INTERFACE_LIST:
646               cmdarg_err("%s", err_str);
647               g_free(err_str);
648               break;
649
650           case NO_INTERFACES_FOUND:
651               cmdarg_err("There are no interfaces on which a capture can be done");
652               break;
653           }
654           return FALSE;
655         }
656         if_info = (if_info_t *)if_list->data;   /* first interface */
657         capture_opts->iface = g_strdup(if_info->name);
658         /*  We don't set iface_descr here because doing so requires
659          *  capture_ui_utils.c which requires epan/prefs.c which is
660          *  probably a bit too much dependency for here...
661          */
662         free_interface_list(if_list);
663       }
664     }
665
666     return TRUE;
667 }
668
669
670
671 #ifndef S_IFIFO
672 #define S_IFIFO _S_IFIFO
673 #endif
674 #ifndef S_ISFIFO
675 #define S_ISFIFO(mode)  (((mode) & S_IFMT) == S_IFIFO)
676 #endif
677
678 /* copied from filesystem.c */
679 static int capture_opts_test_for_fifo(const char *path)
680 {
681         struct stat statb;
682
683         if (ws_stat(path, &statb) < 0)
684                 return errno;
685
686         if (S_ISFIFO(statb.st_mode))
687                 return ESPIPE;
688         else
689                 return 0;
690 }
691
692 static gboolean capture_opts_output_to_pipe(const char *save_file, gboolean *is_pipe)
693 {
694   int err;
695
696   *is_pipe = FALSE;
697
698   if (save_file != NULL) {
699     /* We're writing to a capture file. */
700     if (strcmp(save_file, "-") == 0) {
701       /* Writing to stdout. */
702       /* XXX - should we check whether it's a pipe?  It's arguably
703          silly to do "-w - >output_file" rather than "-w output_file",
704          but by not checking we might be violating the Principle Of
705          Least Astonishment. */
706       *is_pipe = TRUE;
707     } else {
708       /* not writing to stdout, test for a FIFO (aka named pipe) */
709       err = capture_opts_test_for_fifo(save_file);
710       switch (err) {
711
712       case ENOENT:      /* it doesn't exist, so we'll be creating it,
713                            and it won't be a FIFO */
714       case 0:           /* found it, but it's not a FIFO */
715         break;
716
717       case ESPIPE:      /* it is a FIFO */
718         *is_pipe = TRUE;
719         break;
720
721       default:          /* couldn't stat it              */
722         break;          /* ignore: later attempt to open */
723                         /*  will generate a nice msg     */
724       }
725     }
726   }
727
728   return 0;
729 }
730
731 #endif /* HAVE_LIBPCAP */