#!perl
sub
version {
print
'viarni v. '
.
$Virani::VERSION
.
"\n"
;
}
sub
help {
&version
;
print
'
--help Print this.
-h Print this.
--version Print version.
-v Print version..
-r <remote> Remote URL or config file
for
remote info.
-a <apikey> API key
for
remote URL
if
needed.
-f <filter> Filter
for
use
with
tshark or tcpdump.
-t <type> tcpdump or tshark
Default :: tcpdump
--set <set> Set to
use
. If
undef
, uses whatever the
default
is.
Default ::
undef
--config <config> Config file to
use
.
Default :: /usr/
local
/etc/virani.toml
-s <timestamp> Start timestamp. Any
format
supported by
Time::Piece::Guess is usable.
-e <timestamp> End timestamp. Any
format
supported by
Time::Piece::Guess is usable.
-w <output> The file to
write
the PCAP to.
Default :: out.pcap
--nc If cached,
do
not
use
it.
-k Do not check the SSL cert
for
HTTPS
for
remote.
--buffer <secs> Apply this many seconds
before
and
after
the start
time
.
Default:
undef
';
}
my
$help
= 0;
my
$version
= 0;
my
$filter
=
undef
;
my
$start
;
my
$end
;
my
$write
=
'out.pcap'
;
my
$format
;
my
$remote
;
my
$url
;
my
$apikey
;
my
$set
=
'default'
;
my
$config_virani
=
'/usr/local/etc/virani.toml'
;
my
$tmpdir
;
my
$no_cache
= 0;
my
$quiet
= 0,
my
$verbose
= 1;
my
$type
;
my
$verify_hostname
= 1;
my
$verify_hostname_flag
= 0;
my
$timeout
;
my
$buffer
;
Getopt::Long::Configure(
'no_ignore_case'
);
Getopt::Long::Configure(
'bundling'
);
GetOptions(
'version'
=> \
$version
,
'v'
=> \
$version
,
'help'
=> \
$help
,
'h'
=> \
$help
,
'f=s'
=> \
$filter
,
's=s'
=> \
$start
,
'e=s'
=> \
$end
,
'w=s'
=> \
$write
,
'r=s'
=> \
$remote
,
'set=s'
=> \
$set
,
'nc'
=> \
$no_cache
,
'q'
=> \
$quiet
,
'config=s'
=> \
$config_virani
,
'a=s'
=> \
$apikey
,
't=s'
=> \
$type
,
'k'
=> \
$verify_hostname_flag
,
'timeout=s'
=> \
$timeout
,
'buffer=s'
=> \
$buffer
,
);
if
(
$help
) {
&help
;
exit
;
}
if
(
$version
) {
&version
;
exit
;
}
if
( !
defined
(
$filter
) ) {
if
(
defined
(
$ARGV
[0] ) ) {
$filter
=
join
(
' '
,
@ARGV
);
}
}
if
(
defined
(
$filter
) ) {
$filter
=~ s/^\s+//;
$filter
=~ s/\s+$//;
}
else
{
$filter
=
''
;
}
if
( -f
$filter
) {
my
$raw_filter
;
eval
{
$raw_filter
= read_file(
$filter
); };
if
($@) {
die
(
'Failed to read "'
.
$filter
.
'" ... '
. $@ );
}
$filter
=
''
;
foreach
my
$line
(
grep
( !/^\s*\
$line
=~ s/^\s+//;
$line
=~ s/\s+$//;
$line
=~ s/\
$filter
=
$filter
.
' '
.
$line
;
}
$filter
=~ s/^\ //;
}
if
( !
defined
(
$start
) ) {
die
(
'No start time set via -s'
);
}
elsif
( !
defined
(
$end
) ) {
die
(
'No end time set via -e'
);
}
if
(
$quiet
) {
$verbose
= 0;
}
if
(
$verify_hostname_flag
) {
$verify_hostname
= 0;
}
if
(
defined
(
$buffer
) &&
$buffer
!~ /^\d+$/ ) {
die
(
'--buffer is set to "'
.
$buffer
.
'" which is non-numeric'
);
}
elsif
(
defined
(
$buffer
) ) {
my
$start_obj
= Time::Piece::Guess->guess_to_object(
$start
, 1 );
if
( !
defined
(
$start_obj
) ) {
die
(
'-s value of "'
.
$start
.
'" could not be parsed by Time::Piece::Guess'
);
}
my
$end_obj
= Time::Piece::Guess->guess_to_object(
$end
, 1 );
if
( !
defined
(
$end_obj
) ) {
die
(
'-e value of "'
.
$end
.
'" could not be parsed by Time::Piece::Guess'
);
}
$start_obj
=
$start_obj
-
$buffer
;
$end_obj
=
$end_obj
+
$buffer
;
$start
=
$start_obj
->epoch;
$end
=
$end_obj
->epoch;
}
my
$start_obj
;
eval
{
$start_obj
= Time::Piece::Guess->guess_to_object(
$start
, 1 ); };
if
( $@ || !
defined
(
$start_obj
) ) {
die
(
'Failed to parse the start stamp,"'
.
$start
.
'",'
);
}
my
$end_obj
;
eval
{
$end_obj
= Time::Piece::Guess->guess_to_object(
$end
, 1 ); };
if
( $@ || !
defined
(
$end_obj
) ) {
die
(
'Failed to parse the end timestamp,"'
.
$end
.
'",'
);
}
if
( !
$remote
) {
my
$virani
= Virani->new_from_conf(
conf
=>
$config_virani
);
$virani
->set_verbose(
$verbose
);
$virani
->set_verbose_to_syslog(0);
my
$returned
=
$virani
->get_pcap_local(
start
=>
$start_obj
,
end
=>
$end_obj
,
filter
=>
$filter
,
file
=>
$write
,
no_cache
=>
$no_cache
,
verbose
=>
$verbose
,
set
=>
$set
,
type
=>
$type
,
);
if
(
$returned
->{using_cache} ) {
my
$json
= JSON->new->allow_nonref->pretty->canonical(1);
print
"Cache metadata...\n"
.
$json
->encode(
$returned
);
}
exit
0;
}
else
{
my
$config_file
;
if
( -f
$remote
) {
$config_file
=
$remote
;
}
elsif
( -f
$remote
.
'.toml'
) {
$config_file
=
$remote
.
'.toml'
;
}
elsif
( -f
'/usr/local/etc/virani.d/'
.
$remote
) {
$config_file
=
'/usr/local/etc/virani.d/'
.
$remote
;
}
elsif
( -f
'/usr/local/etc/virani.d/'
.
$remote
.
'.toml'
) {
$config_file
=
'/usr/local/etc/virani.d/'
.
$remote
.
'.toml'
;
}
elsif
( -f
'/etc/virani.d/'
.
$remote
) {
$config_file
=
'/etc/virani.d/'
.
$remote
;
}
elsif
( -f
'/etc/virani.d/'
.
$remote
.
'.toml'
) {
$config_file
=
'/etc/virani.d/'
.
$remote
.
'.toml'
;
}
my
$toml
;
if
(
defined
(
$config_file
) ) {
print
'Config File: '
.
$config_file
.
"\n"
;
my
$err
;
my
$raw_toml
= read_file(
$config_file
) ||
die
(
'Failed to read "'
.
$config_file
.
'"'
);
(
$toml
,
$err
) = from_toml(
$raw_toml
);
unless
(
$toml
) {
die
(
"Error parsing '"
.
$config_file
.
"':"
.
$err
);
}
}
elsif
(
$remote
=~ /^[Hh][Tt][Tt][Pp][Ss]*\:\/\// ) {
print
'URL: '
.
$remote
.
"\n"
;
$url
=
$remote
;
}
else
{
die
(
"'"
.
$remote
.
"' does not appear to be a config file or a HTTP or HTTPS URL"
);
}
if
(
defined
(
$apikey
) ) {
print
"API key: specified via -a\n"
;
}
elsif
(
defined
(
$ENV
{virani_api_key} ) ) {
print
'API key: specified via $ENV{virani_api_key}'
.
"\n"
;
$apikey
=
$ENV
{virani_api_key};
}
elsif
(
defined
(
$toml
) &&
defined
(
$toml
->{apikey} ) ) {
print
'API key: specified via config file at '
.
$config_file
.
"\n"
;
$apikey
=
$toml
->{apikey};
}
if
(
defined
(
$timeout
) ) {
print
"Timeout: specified via --timeout\n"
;
}
elsif
(
defined
(
$ENV
{virani_timeout} ) ) {
print
'Timeout: specified via $ENV{virani_timeout}'
.
"\n"
;
$timeout
=
$ENV
{virani_timeout};
}
elsif
(
defined
(
$toml
) &&
defined
(
$toml
->{timeout} ) ) {
print
'Timeout: specified via config file at '
.
$config_file
.
"\n"
;
$timeout
=
$toml
->{timeout};
}
if
( !
defined
(
$url
) ) {
if
(
defined
(
$toml
->{url} ) ) {
$url
=
$toml
->{url};
}
else
{
die
(
"No url specified in '"
.
$config_file
.
"'"
);
}
}
my
$vc
= Virani::Client->new(
url
=>
$url
,
apikey
=>
$apikey
,
verify_hostname
=>
$verify_hostname
);
$vc
->fetch(
start
=>
$start_obj
,
end
=>
$end_obj
,
filter
=>
$filter
,
file
=>
$write
,
no_cache
=>
$no_cache
,
verbose
=>
$verbose
,
set
=>
$set
,
type
=>
$type
,
timeout
=>
$timeout
,
);
print
'Written to '
.
$write
.
"\n"
;
exit
0;
}