3 # Copyright (c) 2013 Michel Ketterle, Steven Schubiger
5 # This file is part of distdns.
7 # distdns is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
12 # distdns is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with distdns. If not, see <http://www.gnu.org/licenses/>.
22 use constant false
=> 0;
25 use Digest
::MD5
qw(md5_hex);
27 use File
::Spec
::Functions
qw(catfile rel2abs);
29 use Getopt::Long qw(:config no_auto_abbrev no_ignore_case);
30 use JSON
qw(decode_json);
32 use POSIX
qw(strftime);
33 use Sys
::Hostname
qw(hostname);
38 my $conf_file = catfile
($Bin, 'client.conf');
40 sub _die
{ die "$0: [client] $_[0]" }
44 warn "$_[0]\n" if defined $_[0];
47 -d, --debug server debugging
48 -h, --help this help screen
49 -i, --init initialize session data
50 -l, --list list remote entries
56 GetOptions
(\
%opts, qw(d|debug h|help i|init l|list)) or usage
();
59 usage
('Cannot combine --init and --list') if $opts{i
} && $opts{l
};
61 my $config = Config
::Tiny
->new;
62 $config = Config
::Tiny
->read($conf_file);
64 my $get_config_opts = sub
66 my ($section, $options) = @_;
68 _die
"Section '$section' missing in $conf_file\n" unless exists $config->{$section};
71 @options{@
$options} = @
{$config->{$section}}{@
$options};
73 foreach my $option (@
$options) {
74 _die
"Option '$option' not set in $conf_file\n" unless defined $options{$option} && length $options{$option};
77 return @options{@
$options};
80 my ($hosts_file, $session_file) = map rel2abs
($_, $Bin), $get_config_opts->('path', [ qw(hosts_file session_file) ]);
82 my ($server_url) = $get_config_opts->('url', [ qw(server_url) ]);
83 my ($netz, $name) = $get_config_opts->('data', [ qw(netz name) ]);
85 my $save_session = sub
89 open(my $fh, '>', $session_file) or _die
"Cannot open $session_file for writing: $!\n";
90 print {$fh} "$session\n";
96 open(my $fh, '<', $session_file) or _die
"Cannot open $session_file for reading: $!\nPerhaps try running --init\n";
97 chomp(my $session = <$fh>);
103 my $session = $opts{i
} ?
substr(md5_hex
(md5_hex
(time() . {} . rand() . $$)), 0, 32) : $get_session->();
109 debug
=> $opts{d
} || false
,
110 init
=> $opts{i
} || false
,
111 list
=> $opts{l
} || false
,
115 my $ua = LWP
::UserAgent
->new;
117 my $response = $ua->post($server_url, \
%params);
119 if ($response->is_success) {
123 $data = decode_json
($response->decoded_content);
126 die "$0: [server] $data->{error}" if defined $data->{error
};
129 $save_session->($session);
133 IP Name PC Netz Aktualisiert
134 ====================================================================================================
136 foreach my $entry (sort { $a->{netz
} cmp $b->{netz
} } @
{$data->{entries
}}) {
137 my $updated = strftime
'%Y-%m-%d %H:%M:%S', localtime $entry->{time};
139 @
<<<<<<<<<<<<<< @
<<<<<<<<<<<<<< @
<<<<<<<<<<<<<<<<<<< @
<<<<<<<<<<<<<< @
<<<<<<<<<<<<<<<<<<
140 @
$entry{qw(ip name pc netz)}, $updated
147 foreach my $entry (@
{$data->{entries
}}) {
148 my $host = "$entry->{ip}\t" . join '.', @
$entry{qw(name pc netz)};
149 push @
{$list{$entry->{netz
}}}, $host;
152 my $o = tie
my @hosts, 'Tie::File', $hosts_file or _die
"Cannot tie $hosts_file: $!\n";
155 foreach my $network (keys %list) {
157 for (my $i = 0; $i < @hosts; $i++) {
158 if ($hosts[$i] =~ /^\#$network\#$/i) {
159 $indexes{start
} = $i;
161 elsif (exists $indexes{start
} && $hosts[$i] =~ /^\#\/$network\#
$/i
) {
163 my $count = ($indexes{end
} - $indexes{start
} > 1)
164 ?
$indexes{end
} - $indexes{start
} - 1
166 splice @hosts, $indexes{start
} + 1, $count, @
{$list{$network}};
177 warn $response->status_line, "\n";