Introduce SortAddressHash function.
[people/stevee/guardian.git] / modules / Base.pm
CommitLineData
1e736116
SS
1package Guardian::Base;
2use strict;
3use warnings;
4
5use Exporter qw(import);
6
d91bbb90 7our @EXPORT_OK = qw(GenerateMonitoredFiles GetFileposition DetectIPProtocolVersion FilePositions);
1e736116 8
bc97b7c0
SS
9use Net::IP;
10
1e736116
SS
11#
12## Function to generate a hash of monitored files and their file positions.
13#
14## This function is responsible for creating the hash of which files should be
15## monitored by guardian. In order to do this, all options from the given hash of
cfe5a220
SS
16## main settings will be parsed and all files to monitor and their configured parsers
17## get extracted, validated and stored into a temporary hash.
1e736116 18#
cfe5a220
SS
19## Next step will be to cleanup files which have been monitored in the past but have been
20## requested for beeing unmonitored for now. To do this, a check if the the file name is
21## part of the existing hash of monitored files and if true to transfer the data into the
22## new temporary hash which get returned by the function.
1e736116
SS
23#
24sub GenerateMonitoredFiles (\%\%) {
25 # Dereference the given hash-refs and store
26 # them into a new temporary hashes.
27 my %mainsettings = %{ $_[0] };
28 my %current_monitored_files = %{ $_[1] };
29
30 # Private hash for storing the new monitored files.
31 my %new_monitored_files = ();
32
cfe5a220
SS
33 # Loop through the temporary hash which contains the main settings.
34 # Search for files which should be monitored and extract the requested
35 # parser. Compare if the file already was a part of the hash which contains
36 # the monitored files and add them to the private new hash of monitored
37 # files which will be returned.
1e736116
SS
38 foreach my $config_option (keys %mainsettings) {
39 # Skip option if it does not look like "Monitor_XYZ".
40 next unless($config_option =~ m/^Monitor_/);
41
cfe5a220
SS
42 # Splitt monitor instruction into 2 parts, to grab the
43 # requested parser module.
44 my ($start, $parser) = split (/_/, $config_option);
45
46 # Convert parser name into lower case format.
47 # Internally the parser module name is completely handled
48 # in this way. This also prevents from any problems related
49 # how the parser name has been spelled in the config file.
50 $parser = lc($parser);
51
52 # Check if the configured parser is available and valid.
53 next unless(&Guardian::Parser::IsSupportedParser($parser));
54
1e736116
SS
55 # Get the configured file for this option.
56 my $file = $mainsettings{$config_option};
57
58 # Skip the file, if it does not exist or is not read-able.
59 next unless(-r "$file");
60
61 # Check if the file not yet has been added to the hash
62 # of monitored files.
63 unless(exists($current_monitored_files{$file})) {
64 # Add the file, init and store the fileposition.
cfe5a220
SS
65 $new_monitored_files{$file} = $parser;
66 } else {
67 # Copy file and parser information to the new hash.
1e736116
SS
68 $new_monitored_files{$file} = $current_monitored_files{$file};
69 }
70 }
71
72 # Return the new_monitored_files hash.
73 return %new_monitored_files;
74}
75
cfe5a220
SS
76#
77## The FilePositions function.
78#
79## This function is responsible for creating and/or updating the hash which
80## stores the current cursor position of the end of file (EOF) of all
81## monitored files.
82#
83## The function requires the hash of currently monitored files and the old hash
84## of the current file positions in order to work properly.
85#
86sub FilePositions (\%\%) {
87 # Dereference the given hash-refs and store
88 # them into a new temporary hashes.
89 my %monitored_files = %{ $_[0] };
90 my %current_file_positions = %{ $_[1] };
91
92 # Private hash for storing the new monitored files.
93 my %new_file_positions = ();
94
95 # Loop through the hash of monitored files.
96 # Compare if the file allready has been a part of the hash
97 # which contains the file positions and transfer the stored
98 # cursor position into the temporary hash which will be returned.
99 #
100 # Otherwise, call the responsible function to obtain the current
101 # end of file (EOF) and store it.
102 foreach my $file (keys %monitored_files) {
103 # Check if the filename is allready part of the hash
104 # of file positions.
105 if (exists($current_file_positions{$file})) {
106 # Copy file position into temporary hash.
107 $new_file_positions{$file} = $current_file_positions{$file};
108 } else {
109 # Call function to obtain the file position.
d91bbb90 110 my $position = &GetFileposition($file);
cfe5a220
SS
111
112 # Add filename and position to the temporary hash.
113 $new_file_positions{$file} = $position;
114 }
115 }
116
117 # Return the new_file_positions hash.
118 return %new_file_positions;
119}
120
66e1ad0a
SS
121#
122## Address/Network to binary format caluculator function.
123#
124## This function is used to convert a given single IP address
125## or network into a binary format.
126#
127## The used Net::IP module is not able to directly detect
128## single addresses or network ranges. Only an element which may be
129## a single address or a whole network can be assigned, for which a
130## lot of different values can be calculated. In case the input has
131## been a single address, the module will calculate the same binary
132## address (intip) and last address for the network range (last_int)
133## because internally it uses a /32 bit prefix for IPv4 and a /128 prefix
134## on IPv6 addresses.
135#
136## So a single address can be detected by just comparing both calculated
137## addresses if they are equal.
138#
139sub IPOrNet2Int($) {
140 my $address = shift;
141
142 # Assign and validate the given address, or directly return
143 # nothing (False) and exit the function.
144 my $ip = new Net::IP ($address) || return;
145
146 # Convert the given address into integer format.
147 my $first .= $ip->intip();
148
149 # Calculate last address for the given network.
150 my $last .= $ip->last_int();
151
152 # Check whether the first address equals the last address.
153 # If this is true, a single IP address has been passed.
154 if ($first eq $last) {
155 # Return the binary converted single address.
156 return $first;
157 }
158
159 # If both addresses are not equal a network has been passed.
160 #
161 # Check if the converted first address is less than the calculated last
162 # address of the network.
163 elsif ($first < $last) {
164 # Return the binary converted first and last address of
165 # the given network.
166 return $first, $last;
167 }
168
169 # If we got here, something strange happend, return nothing (False).
170 else {
171 return;
172 }
173}
174
345e62e2
SS
175#
176## DetectIPProtocolVersion function.
177#
178## Wrapper function for determining the used protocol version (4/6)
179## for a given IP address.
180#
181sub DetectIPProtocolVersion ($) {
182 my $address = shift;
183
184 # Call external perl module to detect the used IP protocol version.
185 my $version = &Net::IP::ip_get_version($address);
186
187 # Return the detected version.
188 return $version;
189}
190
7a6a2682 191#
d91bbb90 192## Function to get the current (EOF) cursor postion.
7a6a2682
SS
193#
194## This function is used to get the cursor position of the end of file (EOF) of
195## a specified file.
196#
197## In order to prevent from permanently read and keep files opened, or dealing
198## with huge logfiles, at initialization time of the worker processes, the file will
199## be opened once and the cursor position of the end of file (EOF) get stored.
200#
d91bbb90 201sub GetFileposition ($) {
7a6a2682
SS
202 my $file = $_[0];
203
204 # Open the file.
205 open(FILE, $file) or die "Could not open $file. $!";
206
207 # Just seek to the end of the file (EOF).
208 seek(FILE, 0, 2);
209
210 # Get and store the position.
211 my $position = tell(FILE),
212
213 # Close the file again.
214 close(FILE);
215
216 # Return the position.
217 return $position;
218}
219
fa67ac02
SS
220#
221## The SortAddressHash function.
222#
223# This function requires a reference to an hash containing
224# IP-addresses, will sort them into a nice looking order
225# and return the soreted result as an array.
226#
227sub SortAddressHash (\%) {
228 # Dereference the given hash reference and store it
229 # in a new temporary hash.
230 my %addresshash = %{ $_[0] };
231
232 # Loop through the entire hash keys.
233 foreach my $address (keys(%addresshash)) {
234 # Convert the address or subnet into binary format.
235 my @bin_address = &IPOrNet2Int($address);
236
237 # Only store the first result if there are multiple
238 # one in case of a given subnet.
239 $addresshash{$address} = $bin_address[0];
240 }
241
242 # Sort the addresshash by the binary addresses
243 # of the stored addresses and save them is an array.
244 my @sorted_addresses = sort { $addresshash{$a} <=> $addresshash{$b} } keys %addresshash;
245
246 # Return the sorted address array.
247 return @sorted_addresses;
248}
249
1e736116 2501;