]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - config/cfgroot/general-functions.pl
general-functions.pl: Update to fix bug #12428
[people/pmueller/ipfire-2.x.git] / config / cfgroot / general-functions.pl
CommitLineData
ac1cfefa
MT
1# SmoothWall CGIs
2#
3# This code is distributed under the terms of the GPL
4#
5# (c) The SmoothWall Team
6# Copyright (C) 2002 Alex Hudson - getcgihash() rewrite
7# Copyright (C) 2002 Bob Grant <bob@cache.ucr.edu> - validmac()
8# Copyright (c) 2002/04/13 Steve Bootes - add alias section, helper functions
9# Copyright (c) 2002/08/23 Mark Wormgoor <mark@wormgoor.com> validfqdn()
10# Copyright (c) 2003/09/11 Darren Critchley <darrenc@telus.net> srtarray()
11#
12# $Id: general-functions.pl,v 1.1.2.26 2006/01/04 16:33:55 franck78 Exp $
13#
14
15package General;
16
17use strict;
18use Socket;
19use IO::Socket;
c545beb1 20use Net::SSLeay;
8c877a82 21use Net::IPv4Addr qw(:all);
ac1cfefa
MT
22$|=1; # line buffering
23
776a1761
MT
24$General::version = 'VERSION';
25$General::swroot = 'CONFIG_ROOT';
ac1cfefa 26$General::noipprefix = 'noipg-';
c545beb1 27$General::adminmanualurl = 'http://wiki.ipfire.org';
ac1cfefa 28
4e9a2b57
MT
29require "${General::swroot}/network-functions.pl";
30
e8adbea9
AF
31# Function to remove duplicates from an array
32sub uniq { my %seen; grep !$seen{$_}++, @_ }
33
c545beb1
MT
34#
35# log ("message") use default 'ipcop' tag
36# log ("tag","message") use your tag
37#
ac1cfefa
MT
38sub log
39{
c545beb1
MT
40 my $tag='ipfire';
41 $tag = shift if (@_>1);
ac1cfefa
MT
42 my $logmessage = $_[0];
43 $logmessage =~ /([\w\W]*)/;
44 $logmessage = $1;
77007ce5 45 system('logger', '-t', $tag, $logmessage);
ac1cfefa 46}
111c99dd
MT
47sub setup_default_networks
48{
49 my %netsettings=();
50 my $defaultNetworks = shift;
51
52 &readhash("/var/ipfire/ethernet/settings", \%netsettings);
53
54 # Get current defined networks (Red, Green, Blue, Orange)
55 $defaultNetworks->{$Lang::tr{'fwhost any'}}{'IPT'} = "0.0.0.0/0.0.0.0";
56 $defaultNetworks->{$Lang::tr{'fwhost any'}}{'NAME'} = "ALL";
57
58 $defaultNetworks->{$Lang::tr{'green'}}{'IPT'} = "$netsettings{'GREEN_NETADDRESS'}/$netsettings{'GREEN_NETMASK'}";
68f6312a 59 $defaultNetworks->{$Lang::tr{'green'}}{'NET'} = "$netsettings{'GREEN_ADDRESS'}";
111c99dd
MT
60 $defaultNetworks->{$Lang::tr{'green'}}{'NAME'} = "GREEN";
61
b9648e58 62 if ($netsettings{'RED_DEV'} ne ''){
223d3b1d 63 $defaultNetworks->{$Lang::tr{'fwdfw red'}}{'IPT'} = "$netsettings{'RED_NETADDRESS'}/$netsettings{'RED_NETMASK'}";
68f6312a 64 $defaultNetworks->{$Lang::tr{'fwdfw red'}}{'NET'} = "$netsettings{'RED_ADDRESS'}";
223d3b1d 65 $defaultNetworks->{$Lang::tr{'fwdfw red'}}{'NAME'} = "RED";
b9648e58 66 }
111c99dd
MT
67 if ($netsettings{'ORANGE_DEV'} ne ''){
68 $defaultNetworks->{$Lang::tr{'orange'}}{'IPT'} = "$netsettings{'ORANGE_NETADDRESS'}/$netsettings{'ORANGE_NETMASK'}";
68f6312a 69 $defaultNetworks->{$Lang::tr{'orange'}}{'NET'} = "$netsettings{'ORANGE_ADDRESS'}";
111c99dd
MT
70 $defaultNetworks->{$Lang::tr{'orange'}}{'NAME'} = "ORANGE";
71 }
72
73 if ($netsettings{'BLUE_DEV'} ne ''){
74 $defaultNetworks->{$Lang::tr{'blue'}}{'IPT'} = "$netsettings{'BLUE_NETADDRESS'}/$netsettings{'BLUE_NETMASK'}";
68f6312a 75 $defaultNetworks->{$Lang::tr{'blue'}}{'NET'} = "$netsettings{'BLUE_ADDRESS'}";
111c99dd
MT
76 $defaultNetworks->{$Lang::tr{'blue'}}{'NAME'} = "BLUE";
77 }
c7043621
AM
78
79 #IPFire himself
80 $defaultNetworks->{'IPFire'}{'NAME'} = "IPFire";
111c99dd
MT
81
82 # OpenVPN
83 if(-e "${General::swroot}/ovpn/settings")
84 {
85 my %ovpnSettings = ();
86 &readhash("${General::swroot}/ovpn/settings", \%ovpnSettings);
87
88 # OpenVPN on Red?
89 if(defined($ovpnSettings{'DOVPN_SUBNET'}))
90 {
91 my ($ip,$sub) = split(/\//,$ovpnSettings{'DOVPN_SUBNET'});
92 $sub=&General::iporsubtocidr($sub);
93 my @tempovpnsubnet = split("\/", $ovpnSettings{'DOVPN_SUBNET'});
1a8fde0e
AM
94 $defaultNetworks->{'OpenVPN ' ."($ip/$sub)"}{'ADR'} = $tempovpnsubnet[0];
95 $defaultNetworks->{'OpenVPN ' ."($ip/$sub)"}{'NAME'} = "OpenVPN-Dyn";
111c99dd
MT
96 }
97 } # end OpenVPN
98 # IPsec RW NET
99 if(-e "${General::swroot}/vpn/settings")
100 {
101 my %ipsecsettings = ();
102 &readhash("${General::swroot}/vpn/settings", \%ipsecsettings);
103 if($ipsecsettings{'RW_NET'} ne '')
104 {
105 my ($ip,$sub) = split(/\//,$ipsecsettings{'RW_NET'});
106 $sub=&General::iporsubtocidr($sub);
107 my @tempipsecsubnet = split("\/", $ipsecsettings{'RW_NET'});
6ee90535
AM
108 $defaultNetworks->{'IPsec RW (' .$ip."/".$sub.")"}{'ADR'} = $tempipsecsubnet[0];
109 $defaultNetworks->{'IPsec RW (' .$ip."/".$sub.")"}{'NAME'} = "IPsec RW";
110 $defaultNetworks->{'IPsec RW (' .$ip."/".$sub.")"}{'NET'} = &getnextip($ip);
111c99dd
MT
111 }
112 }
111c99dd
MT
113}
114sub get_aliases
115{
116
117 my $defaultNetworks = shift;
118 open(FILE, "${General::swroot}/ethernet/aliases") or die 'Unable to open aliases file.';
119 my @current = <FILE>;
120 close(FILE);
121 my $ctr = 0;
122 foreach my $line (@current)
123 {
124 if ($line ne ''){
125 chomp($line);
126 my @temp = split(/\,/,$line);
127 if ($temp[2] eq '') {
128 $temp[2] = "Alias $ctr : $temp[0]";
129 }
130 $defaultNetworks->{$temp[2]}{'IPT'} = "$temp[0]";
68f6312a 131 $defaultNetworks->{$temp[2]}{'NET'} = "$temp[0]";
111c99dd
MT
132
133 $ctr++;
134 }
135 }
136}
ac1cfefa
MT
137
138sub readhash
139{
140 my $filename = $_[0];
141 my $hash = $_[1];
142 my ($var, $val);
143
144
145 # Some ipcop code expects that readhash 'complete' the hash if new entries
146 # are presents. Not clear it !!!
147 #%$hash = ();
148
149 open(FILE, $filename) or die "Unable to read file $filename";
150
151 while (<FILE>)
152 {
153 chop;
9f5247f6
SS
154
155 # Skip comments.
06f57f72 156 next if ($_ =~ /^#/);
9f5247f6 157
ac1cfefa
MT
158 ($var, $val) = split /=/, $_, 2;
159 if ($var)
160 {
161 $val =~ s/^\'//g;
162 $val =~ s/\'$//g;
163
164 # Untaint variables read from hash
77007ce5
MT
165 # trim space from begin and end
166 $var =~ s/^\s+//;
167 $var =~ s/\s+$//;
168 $var =~ /([A-Za-z0-9_-]*)/;
169 $var = $1;
170 $val =~ /([\w\W]*)/;
171 $val = $1;
ac1cfefa
MT
172 $hash->{$var} = $val;
173 }
174 }
175 close FILE;
176}
177
178
179sub writehash
180{
181 my $filename = $_[0];
182 my $hash = $_[1];
183 my ($var, $val);
184
185 # write cgi vars to the file.
186 open(FILE, ">${filename}") or die "Unable to write file $filename";
187 flock FILE, 2;
188 foreach $var (keys %$hash)
189 {
ad60e3ea 190 if ( $var eq "__CGI__"){next;}
ac1cfefa
MT
191 $val = $hash->{$var};
192 # Darren Critchley Jan 17, 2003 added the following because when submitting with a graphic, the x and y
193 # location of the mouse are submitted as well, this was being written to the settings file causing
194 # some serious grief! This skips the variable.x and variable.y
195 if (!($var =~ /(.x|.y)$/)) {
196 if ($val =~ / /) {
197 $val = "\'$val\'"; }
198 if (!($var =~ /^ACTION/)) {
199 print FILE "${var}=${val}\n"; }
200 }
201 }
202 close FILE;
203}
204
90c2e164
CS
205sub writehashpart
206{
207 # This function replaces the given hash in the original hash by keeping the old
208 # content and just replacing the new content
209
210 my $filename = $_[0];
211 my $newhash = $_[1];
212 my %oldhash;
213 my ($var, $val);
214
215 readhash("${filename}", \%oldhash);
216
217 foreach $var (keys %$newhash){
218 $oldhash{$var}=$newhash->{$var};
219 }
220
221 # write cgi vars to the file.
222 open(FILE, ">${filename}") or die "Unable to write file $filename";
223 flock FILE, 2;
224 foreach $var (keys %oldhash)
225 {
226 if ( $var eq "__CGI__"){next;}
227 $val = $oldhash{$var};
228 # Darren Critchley Jan 17, 2003 added the following because when submitting with a graphic, the x and y
229 # location of the mouse are submitted as well, this was being written to the settings file causing
230 # some serious grief! This skips the variable.x and variable.y
231 if (!($var =~ /(.x|.y)$/)) {
232 if ($val =~ / /) {
233 $val = "\'$val\'"; }
234 if (!($var =~ /^ACTION/)) {
235 print FILE "${var}=${val}\n"; }
236 }
237 }
238 close FILE;
239}
ac1cfefa 240
1dc44471 241sub age {
ac1cfefa 242 my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
1dc44471 243 $atime, $mtime, $ctime, $blksize, $blocks) = stat $_[0];
a0b271e4
MT
244 my $t = time() - $mtime;
245
246 return &format_time($t);
247}
248
249sub format_time($) {
250 my $totalsecs = shift;
1dc44471 251 my @s = ();
ac1cfefa 252
ac1cfefa 253 my $secs = $totalsecs % 60;
1dc44471
MT
254 $totalsecs /= 60;
255 if ($secs > 0) {
256 push(@s, "${secs}s");
3687a2e2
JIW
257 }
258
1dc44471
MT
259 my $min = $totalsecs % 60;
260 $totalsecs /= 60;
261 if ($min > 0) {
262 push(@s, "${min}m");
3687a2e2
JIW
263 }
264
1dc44471
MT
265 my $hrs = $totalsecs % 24;
266 $totalsecs /= 24;
267 if ($hrs > 0) {
268 push(@s, "${hrs}h");
3687a2e2
JIW
269 }
270
1dc44471
MT
271 my $days = int($totalsecs);
272 if ($days > 0) {
273 push(@s, "${days}d");
3687a2e2 274 }
3687a2e2 275
1dc44471 276 return join(" ", reverse(@s));
ac1cfefa
MT
277}
278
279sub validip
280{
281 my $ip = $_[0];
282
283 if (!($ip =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/)) {
284 return 0; }
285 else
286 {
287 my @octets = ($1, $2, $3, $4);
288 foreach $_ (@octets)
289 {
290 if (/^0./) {
291 return 0; }
292 if ($_ < 0 || $_ > 255) {
293 return 0; }
294 }
295 return 1;
296 }
297}
298
4e9a2b57
MT
299sub validmask {
300 my $mask = shift;
ac1cfefa 301
c1420324 302 return &Network::check_netmask($mask) || &Network::check_prefix($mask);
ac1cfefa
MT
303}
304
305sub validipormask
306{
307 my $ipormask = $_[0];
308
309 # see if it is a IP only.
310 if (&validip($ipormask)) {
311 return 1; }
312 # split it into number and mask.
313 if (!($ipormask =~ /^(.*?)\/(.*?)$/)) {
314 return 0; }
315 my $ip = $1;
316 my $mask = $2;
317 # first part not a ip?
318 if (!(&validip($ip))) {
319 return 0; }
320 return &validmask($mask);
321}
322
4e9a2b57
MT
323sub subtocidr {
324 return &Network::convert_netmask2prefix(shift);
8c877a82 325}
ac1cfefa 326
4e9a2b57
MT
327sub cidrtosub {
328 return &Network::convert_prefix2netmask(shift);
8c877a82
AM
329}
330
331sub iporsubtodec
332{
333 #Gets: Ip address or subnetmask in decimal oder CIDR
334 #Gives: What it gets only in CIDR format
335 my $subnet=$_[0];
336 my $net;
337 my $mask;
338 my $full=0;
339 if ($subnet =~ /^(.*?)\/(.*?)$/) {
340 ($net,$mask) = split (/\//,$subnet);
341 $full=1;
342 return "$subnet";
343 }else{
344 $mask=$subnet;
345 }
346 #Subnet already in decimal and valid?
347 if ($mask=~/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ &&(($1<=255 && $2<=$1 && $3<=$2 && $4<=$3 ))) {
7490b22e 348 for (my $i=0;$i<=32;$i++){
8c877a82
AM
349 if (&General::cidrtosub($i) eq $mask){
350 if ($full == 0){return $mask;}else{
351 return $net."/".$mask;
352 }
353 }
354 }
355 }
356 #Subnet in binary format?
7490b22e 357 if ($mask=~/^(\d{1,2})$/ && (($1<=32 && $1>=0))){
8c877a82
AM
358 if($full == 0){ return &General::cidrtosub($mask);}else{
359 return $net."/".&General::cidrtosub($mask);
360 }
361 }else{
362 return 3;
363 }
364 return 3;
365}
366
367
368sub iporsubtocidr
369{
370 #gets: Ip Address or subnetmask in decimal oder CIDR
371 #Gives: What it gets only in CIDR format
372 my $subnet=$_[0];
373 my $net;
374 my $mask;
375 my $full=0;
376 if ($subnet =~ /^(.*?)\/(.*?)$/) {
377 ($net,$mask) = split (/\//,$subnet);
378 $full=1;
379 }else{
380 $mask=$subnet;
381 }
382 #Subnet in decimal and valid?
383 if ($mask=~/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ &&(($1<=255 && $2<=$1 && $3<=$2 && $4<=$3 ))) {
7490b22e 384 for (my $i=0;$i<=32;$i++){
8c877a82
AM
385 if (&General::cidrtosub($i) eq $mask){
386 if ($full == 0){return &General::subtocidr($mask);}else{
387 return $net."/".&General::subtocidr($mask);
388 }
389 }
390 }
391 }
392 #Subnet already in binary format?
7490b22e 393 if ($mask=~/^(\d{1,2})$/ && (($1<=32 && $1>=0))){
8c877a82
AM
394 if($full == 0){ return $mask;}else{
395 return $net."/".$mask;
396 }
397 }else{
398 return 3;
399 }
400 return 3;
401}
402
4e9a2b57 403sub getnetworkip {
da05e076 404 my $arg = join("/", @_);
6a2a62cf
MT
405
406 return &Network::get_netaddress($arg);
8c877a82
AM
407}
408
409sub getccdbc
410{
411 #Gets: IP in Form ("192.168.0.0/24")
412 #Gives: Broadcastaddress of network
413 my $ccdnet=$_;
414 my ($ccdip,$ccdsubnet) = split "/",$ccdnet;
415 my $ip_address_binary = inet_aton( $ccdip );
416 my $netmask_binary = ~pack("N", (2**(32-$ccdsubnet))-1);
417 my $broadcast_address = inet_ntoa( $ip_address_binary | ~$netmask_binary );
418 return $broadcast_address;
419}
e81be1e1 420
4e9a2b57
MT
421sub ip2dec {
422 return &Network::ip2bin(shift);
8c877a82 423}
e81be1e1 424
4e9a2b57
MT
425sub dec2ip {
426 return &Network::bin2ip(shift);
427}
428
429sub getnextip {
430 return &Network::find_next_ip_address(shift, 4);
431}
432
433sub getlastip {
434 return &Network::find_next_ip_address(shift, -1);
8c877a82
AM
435}
436
437sub validipandmask
438{
439 #Gets: Ip address in 192.168.0.0/24 or 192.168.0.0/255.255.255.0 and checks if subnet valid
440 #Gives: True bzw 0 if success or false
441 my $ccdnet=$_[0];
442 my $subcidr;
443
444 if (!($ccdnet =~ /^(.*?)\/(.*?)$/)) {
445 return 0;
446 }
447 my ($ccdip,$ccdsubnet)=split (/\//, $ccdnet);
448 #IP valid?
449 if ($ccdip=~/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ &&(($1>0 && $1<=255 && $2>=0 && $2<=255 && $3>=0 && $3<=255 && $4<=255 ))) {
450 #Subnet in decimal and valid?
451 if ($ccdsubnet=~/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ &&(($1<=255 && $2<=$1 && $3<=$2 && $4<=$3 ))) {
7490b22e 452 for (my $i=0;$i<=32;$i++){
8c877a82
AM
453 if (&General::cidrtosub($i) eq $ccdsubnet){
454 return 1;
455 }
7490b22e 456 }
8c877a82 457 #Subnet already in binary format?
7490b22e 458 }elsif ($ccdsubnet=~/^(\d{1,2})$/ && (($1<=32 && $1>=0))){
8c877a82
AM
459 return 1;
460 }else{
461 return 0;
462 }
463
464 }
465 return 0;
ac1cfefa
MT
466}
467
e2429e8d
AM
468sub checksubnets
469{
4d81e0f3
AM
470 my %ccdconfhash=();
471 my %ovpnconfhash=();
472 my %vpnconf=();
473 my %ipsecconf=();
474 my %ownnet=();
475 my %ovpnconf=();
476 my @ccdconf=();
477 my $ccdname=$_[0];
478 my $ccdnet=$_[1];
479 my $ownnet=$_[2];
b7ab17ad 480 my $checktype=$_[3];
e2429e8d
AM
481 my $errormessage;
482 my ($ip,$cidr)=split(/\//,$ccdnet);
483 $cidr=&iporsubtocidr($cidr);
4d81e0f3 484
e2429e8d 485 #get OVPN-Subnet (dynamic range)
e2429e8d
AM
486 &readhash("${General::swroot}/ovpn/settings", \%ovpnconf);
487 my ($ovpnip,$ovpncidr)= split (/\//,$ovpnconf{'DOVPN_SUBNET'});
488 $ovpncidr=&iporsubtocidr($ovpncidr);
4d81e0f3 489
e2429e8d
AM
490 #check if we try to use same network as ovpn server
491 if ("$ip/$cidr" eq "$ovpnip/$ovpncidr") {
492 $errormessage=$errormessage.$Lang::tr{'ccd err isovpnnet'}."<br>";
493 return $errormessage;
494 }
4d81e0f3
AM
495
496 #check if we try to use same network as another ovpn N2N
497 if($ownnet ne 'ovpn'){
498 &readhasharray("${General::swroot}/ovpn/ovpnconfig", \%ovpnconfhash);
499 foreach my $key (keys %ovpnconfhash) {
500 if ($ovpnconfhash{$key}[3] eq 'net'){
501 my @ovpnnet=split (/\//,$ovpnconfhash{$key}[11]);
502 if (&IpInSubnet($ip,$ovpnnet[0],&iporsubtodec($ovpnnet[1]))){
503 $errormessage=$errormessage.$Lang::tr{'ccd err isovpnn2n'}." $ovpnconfhash{$key}[1] <br>";
504 return $errormessage;
505 }
506 }
507 }
508 }
509
510 #check if we use a network-name/subnet (static-ovpn) that already exists
e2429e8d
AM
511 &readhasharray("${General::swroot}/ovpn/ccd.conf", \%ccdconfhash);
512 foreach my $key (keys %ccdconfhash) {
513 @ccdconf=split(/\//,$ccdconfhash{$key}[1]);
514 if ($ccdname eq $ccdconfhash{$key}[0])
515 {
516 $errormessage=$errormessage.$Lang::tr{'ccd err nameexist'}."<br>";
517 return $errormessage;
518 }
519 my ($newip,$newsub) = split(/\//,$ccdnet);
520 if (&IpInSubnet($newip,$ccdconf[0],&iporsubtodec($ccdconf[1])))
521 {
4d81e0f3 522 $errormessage=$errormessage.$Lang::tr{'ccd err issubnet'}." $ccdconfhash{$key}[0]<br>";
e2429e8d
AM
523 return $errormessage;
524 }
e2429e8d 525 }
4d81e0f3 526
e2429e8d 527 #check if we use a ipsec right network which is already defined
4d81e0f3
AM
528 if($ownnet ne 'ipsec'){
529 &General::readhasharray("${General::swroot}/vpn/config", \%ipsecconf);
530 foreach my $key (keys %ipsecconf){
087e3023 531 if ($ipsecconf{$key}[11] ne '' && $ipsecconf{$key}[36] eq ""){
ecc9c73b
HG
532 foreach my $ipsecsubitem (split(/\|/, $ipsecconf{$key}[11])) {
533 my ($ipsecip,$ipsecsub) = split (/\//, $ipsecconf{$key}[11]);
534 $ipsecsub=&iporsubtodec($ipsecsub);
535 if($ipsecconf{$key}[1] ne $ccdname){
536 if ( &IpInSubnet ($ip,$ipsecip,$ipsecsub) ){
537 $errormessage=$Lang::tr{'ccd err isipsecnet'}." Name: $ipsecconf{$key}[1]";
538 return $errormessage;
539 }
4d81e0f3 540 }
f7e3d208 541 }
e2429e8d
AM
542 }
543 }
544 }
4d81e0f3
AM
545
546 #check if we use the ipsec RW Network (if defined)
547 &readhash("${General::swroot}/vpn/settings", \%vpnconf);
548 if ($vpnconf{'RW_NET'} ne ''){
549 my ($ipsecrwnet,$ipsecrwsub)=split (/\//, $vpnconf{'RW_NET'});
550 if (&IpInSubnet($ip,$ipsecrwnet,&iporsubtodec($ipsecrwsub)))
551 {
552 $errormessage=$errormessage.$Lang::tr{'ccd err isipsecrw'}."<br>";
553 return $errormessage;
554 }
555 }
4f857eea
AM
556
557 #call check_net_internal
b7ab17ad
AM
558 if ($checktype eq "exact")
559 {
560 &General::check_net_internal_exact($ccdnet);
561 }else{
562 &General::check_net_internal_range($ccdnet);
563 }
e2429e8d
AM
564}
565
b7ab17ad 566sub check_net_internal_range{
29f238b2
AM
567 my $network=shift;
568 my ($ip,$cidr)=split(/\//,$network);
569 my %ownnet=();
570 my $errormessage;
571 $cidr=&iporsubtocidr($cidr);
572 #check if we use one of ipfire's networks (green,orange,blue)
573 &readhash("${General::swroot}/ethernet/settings", \%ownnet);
65c3b7c9
MT
574 if (($ownnet{'GREEN_NETADDRESS'} ne '' && $ownnet{'GREEN_NETADDRESS'} ne '0.0.0.0') && &IpInSubnet($ip,$ownnet{'GREEN_NETADDRESS'},&iporsubtodec($ownnet{'GREEN_NETMASK'}))){ $errormessage=$Lang::tr{'ccd err green'};return $errormessage;}
575 if (($ownnet{'ORANGE_NETADDRESS'} ne '' && $ownnet{'ORANGE_NETADDRESS'} ne '0.0.0.0') && &IpInSubnet($ip,$ownnet{'ORANGE_NETADDRESS'},&iporsubtodec($ownnet{'ORANGE_NETMASK'}))){ $errormessage=$Lang::tr{'ccd err orange'};return $errormessage;}
576 if (($ownnet{'BLUE_NETADDRESS'} ne '' && $ownnet{'BLUE_NETADDRESS'} ne '0.0.0.0') && &IpInSubnet($ip,$ownnet{'BLUE_NETADDRESS'},&iporsubtodec($ownnet{'BLUE_NETMASK'}))){ $errormessage=$Lang::tr{'ccd err blue'};return $errormessage;}
577 if (($ownnet{'RED_NETADDRESS'} ne '' && $ownnet{'RED_NETADDRESS'} ne '0.0.0.0') && &IpInSubnet($ip,$ownnet{'RED_NETADDRESS'},&iporsubtodec($ownnet{'RED_NETMASK'}))){ $errormessage=$Lang::tr{'ccd err red'};return $errormessage;}
b7ab17ad
AM
578}
579
580sub check_net_internal_exact{
581 my $network=shift;
582 my ($ip,$cidr)=split(/\//,$network);
583 my %ownnet=();
584 my $errormessage;
585 $cidr=&iporsubtocidr($cidr);
586 #check if we use one of ipfire's networks (green,orange,blue)
587 &readhash("${General::swroot}/ethernet/settings", \%ownnet);
588 if (($ownnet{'GREEN_NETADDRESS'} ne '' && $ownnet{'GREEN_NETADDRESS'} ne '0.0.0.0') && &Network::network_equal("$ownnet{'GREEN_NETADDRESS'}/$ownnet{'GREEN_NETMASK'}", $network)){ $errormessage=$Lang::tr{'ccd err green'};return $errormessage;}
589 if (($ownnet{'ORANGE_NETADDRESS'} ne '' && $ownnet{'ORANGE_NETADDRESS'} ne '0.0.0.0') && &Network::network_equal("$ownnet{'ORANGE_NETADDRESS'}/$ownnet{'ORANGE_NETMASK'}", $network)){ $errormessage=$Lang::tr{'ccd err orange'};return $errormessage;}
590 if (($ownnet{'BLUE_NETADDRESS'} ne '' && $ownnet{'BLUE_NETADDRESS'} ne '0.0.0.0') && &Network::network_equal("$ownnet{'BLUE_NETADDRESS'}/$ownnet{'BLUE_NETMASK'}", $network)){ $errormessage=$Lang::tr{'ccd err blue'};return $errormessage;}
591 if (($ownnet{'RED_NETADDRESS'} ne '' && $ownnet{'RED_NETADDRESS'} ne '0.0.0.0') && &Network::network_equal("$ownnet{'RED_NETADDRESS'}/$ownnet{'RED_NETMASK'}", $network)){ $errormessage=$Lang::tr{'ccd err red'};return $errormessage;}
29f238b2 592}
e2429e8d 593
ac1cfefa
MT
594sub validport
595{
596 $_ = $_[0];
597
598 if (!/^\d+$/) {
599 return 0; }
600 if (/^0./) {
601 return 0; }
602 if ($_ >= 1 && $_ <= 65535) {
603 return 1; }
604 return 0;
605}
606
d30ea451
CS
607sub validproxyport
608{
609 $_ = $_[0];
610
611 if (!/^\d+$/) {
612 return 0; }
613 if (/^0./) {
614 return 0; }
615 if ($_ == 53 || $_ == 222 || $_ == 444 || $_ == 81 ) {
616 return 0; }
617 elsif ($_ >= 1 && $_ <= 65535) {
618 return 1; }
619 return 0;
620}
621
ac1cfefa
MT
622sub validmac
623{
624 my $checkmac = $_[0];
625 my $ot = '[0-9a-f]{2}'; # 2 Hex digits (one octet)
626 if ($checkmac !~ /^$ot:$ot:$ot:$ot:$ot:$ot$/i)
627 {
628 return 0;
629 }
630 return 1;
631}
632
633sub validhostname
634{
635 # Checks a hostname against RFC1035
636 my $hostname = $_[0];
637
5b4e33bc 638 # Hostname should be at least one character in length
ac1cfefa
MT
639 # but no more than 63 characters
640 if (length ($hostname) < 1 || length ($hostname) > 63) {
641 return 0;}
642 # Only valid characters are a-z, A-Z, 0-9 and -
5b4e33bc 643 if ($hostname !~ /^[a-zA-Z0-9-]*$/) {
ac1cfefa
MT
644 return 0;}
645 # First character can only be a letter or a digit
646 if (substr ($hostname, 0, 1) !~ /^[a-zA-Z0-9]*$/) {
647 return 0;}
648 # Last character can only be a letter or a digit
649 if (substr ($hostname, -1, 1) !~ /^[a-zA-Z0-9]*$/) {
650 return 0;}
651 return 1;
652}
653
654sub validdomainname
655{
656 my $part;
657
5b4e33bc 658 # Checks a domain name against RFC1035 and RFC2181
ac1cfefa 659 my $domainname = $_[0];
5b4e33bc 660 my @parts = split (/\./, $domainname); # Split domain name at the '.'
ac1cfefa
MT
661
662 foreach $part (@parts) {
5b4e33bc
AB
663 # Each part should be at least one character in length
664 # but no more than 63 characters
8ed77b03 665 if (length ($part) < 1 || length ($part) > 63) {
ac1cfefa 666 return 0;}
03306ff6
MT
667 # Only valid characters are a-z, A-Z, 0-9, _ and -
668 if ($part !~ /^[a-zA-Z0-9_-]*$/) {
5b4e33bc 669 return 0;}
ac1cfefa
MT
670 }
671 return 1;
672}
673
674sub validfqdn
675{
5b4e33bc 676 # Checks a fully qualified domain name against RFC1035 and RFC2181
ac1cfefa 677 my $fqdn = $_[0];
5b4e33bc 678 my @parts = split (/\./, $fqdn); # Split FQDN at the '.'
ac1cfefa
MT
679 if (scalar(@parts) < 2) { # At least two parts should
680 return 0;} # exist in a FQDN
b00797e2 681 # (i.e.hostname.domain)
5b4e33bc
AB
682
683 for (my $index=0; $index < scalar(@parts); $index++) {
ac1cfefa
MT
684 # Each part should be at least one character in length
685 # but no more than 63 characters
5b4e33bc 686 if (length ($parts[$index]) < 1 || length ($parts[$index]) > 63) {
ac1cfefa 687 return 0;}
5b4e33bc
AB
688 if ($index eq 0) {
689 # This is the hostname part
690 # Only valid characters are a-z, A-Z, 0-9 and -
691 if ($parts[$index] !~ /^[a-zA-Z0-9-]*$/) {
692 return 0;}
693 # First character can only be a letter or a digit
694 if (substr ($parts[$index], 0, 1) !~ /^[a-zA-Z0-9]*$/) {
695 return 0;}
696 # Last character can only be a letter or a digit
697 if (substr ($parts[$index], -1, 1) !~ /^[a-zA-Z0-9]*$/) {
698 return 0;}
699 } else{
700 # This is the domain part
701 # Only valid characters are a-z, A-Z, 0-9, _ and -
702 if ($parts[$index] !~ /^[a-zA-Z0-9_-]*$/) {
703 return 0;}
704 }
ac1cfefa
MT
705 }
706 return 1;
707}
708
709sub validportrange # used to check a port range
710{
711 my $port = $_[0]; # port values
712 $port =~ tr/-/:/; # replace all - with colons just in case someone used -
713 my $srcdst = $_[1]; # is it a source or destination port
714
715 if (!($port =~ /^(\d+)\:(\d+)$/)) {
716
717 if (!(&validport($port))) {
718 if ($srcdst eq 'src'){
719 return $Lang::tr{'source port numbers'};
720 } else {
721 return $Lang::tr{'destination port numbers'};
722 }
723 }
724 }
725 else
726 {
727 my @ports = ($1, $2);
728 if ($1 >= $2){
729 if ($srcdst eq 'src'){
730 return $Lang::tr{'bad source range'};
731 } else {
732 return $Lang::tr{'bad destination range'};
733 }
734 }
735 foreach $_ (@ports)
736 {
737 if (!(&validport($_))) {
738 if ($srcdst eq 'src'){
739 return $Lang::tr{'source port numbers'};
740 } else {
741 return $Lang::tr{'destination port numbers'};
742 }
743 }
744 }
745 return;
746 }
747}
748
4e9a2b57 749sub IpInSubnet {
ab92dc0c
AM
750 my $addr = shift;
751 my $network = shift;
752 my $netmask = shift;
753
4e9a2b57 754 return &Network::ip_address_in_network($addr, "$network/$netmask");
ac1cfefa
MT
755}
756
c545beb1
MT
757#
758# Return the following IP (IP+1) in dotted notation.
759# Call: NextIP ('1.1.1.1');
760# Return: '1.1.1.2'
761#
4e9a2b57
MT
762sub NextIP {
763 return &Network::find_next_ip_address(shift, 1);
c545beb1 764}
4e9a2b57
MT
765
766sub NextIP2 {
767 return &Network::find_next_ip_address(shift, 4);
8c877a82 768}
4e9a2b57
MT
769
770sub ipcidr {
45762fc6
AF
771 my ($ip,$cidr) = &Net::IPv4Addr::ipv4_parse(shift);
772 return "$ip\/$cidr";
773}
774
4e9a2b57 775sub ipcidr2msk {
54fd0535
MT
776 my ($ip,$cidr) = &Net::IPv4Addr::ipv4_parse(shift);
777 my $netmask = &Net::IPv4Addr::ipv4_cidr2msk($cidr);
778 return "$ip\/$netmask";
779}
780
ac1cfefa 781sub validemail {
b00797e2
AM
782 my $address = shift;
783 my @parts = split( /\@/, $address );
784 my $count=@parts;
785
786 #check if we have one part before and after '@'
787 return 0 if ( $count != 2 );
788
789 #check if one of the parts starts or ends with a dot
790 return 0 if ( substr($parts[0],0,1) eq '.' );
791 return 0 if ( substr($parts[0],-1,1) eq '.' );
792 return 0 if ( substr($parts[1],0,1) eq '.' );
793 return 0 if ( substr($parts[1],-1,1) eq '.' );
794
795 #check first addresspart (before '@' sign)
cc724c14 796 return 0 if ( $parts[0] !~ m/^[a-zA-Z0-9\.!\-\_\+#]+$/ );
b00797e2
AM
797
798 #check second addresspart (after '@' sign)
799 return 0 if ( $parts[1] !~ m/^[a-zA-Z0-9\.\-]+$/ );
800
ac1cfefa
MT
801 return 1;
802}
803
c545beb1
MT
804#
805# Currently only vpnmain use this three procs (readhasharray, writehasharray, findhasharray)
806# The 'key' used is numeric but is perfectly unneeded! This will to be removed so don't use
807# this code. Vpnmain will be splitted in parts: x509/pki, connection ipsec, connection other,... .
808#
ac1cfefa
MT
809sub readhasharray {
810 my ($filename, $hash) = @_;
811 %$hash = ();
812
813 open(FILE, $filename) or die "Unable to read file $filename";
814
815 while (<FILE>) {
816 my ($key, $rest, @temp);
817 chomp;
818 ($key, $rest) = split (/,/, $_, 2);
c545beb1 819 if ($key =~ /^[0-9]+$/) {
ac1cfefa
MT
820 @temp = split (/,/, $rest);
821 $hash->{$key} = \@temp;
822 }
823 }
824 close FILE;
825 return;
826}
827
828sub writehasharray {
829 my ($filename, $hash) = @_;
830 my ($key, @temp, $i);
831
832 open(FILE, ">$filename") or die "Unable to write to file $filename";
833
834 foreach $key (keys %$hash) {
8c877a82
AM
835 if ($key =~ /^[0-9]+$/) {
836 print FILE "$key";
837 foreach $i (0 .. $#{$hash->{$key}}) {
838 print FILE ",$hash->{$key}[$i]";
839 }
840 print FILE "\n";
841 }
ac1cfefa
MT
842 }
843 close FILE;
844 return;
845}
846
847sub findhasharraykey {
848 foreach my $i (1 .. 1000000) {
849 if ( ! exists $_[0]{$i}) {
850 return $i;
851 }
852 }
853}
854
855sub srtarray
856# Darren Critchley - darrenc@telus.net - (c) 2003
857# &srtarray(SortOrder, AlphaNumeric, SortDirection, ArrayToBeSorted)
858# This subroutine will take the following parameters:
859# ColumnNumber = the column which you want to sort on, starts at 1
860# AlphaNumberic = a or n (lowercase) defines whether the sort should be alpha or numberic
861# SortDirection = asc or dsc (lowercase) Ascending or Descending sort
862# ArrayToBeSorted = the array that wants sorting
863#
864# Returns an array that is sorted to your specs
865#
866# If SortOrder is greater than the elements in array, then it defaults to the first element
867#
868{
869 my ($colno, $alpnum, $srtdir, @tobesorted) = @_;
870 my @tmparray;
871 my @srtedarray;
872 my $line;
873 my $newline;
874 my $ctr;
875 my $ttlitems = scalar @tobesorted; # want to know the number of rows in the passed array
876 if ($ttlitems < 1){ # if no items, don't waste our time lets leave
877 return (@tobesorted);
878 }
879 my @tmp = split(/\,/,$tobesorted[0]);
880 $ttlitems = scalar @tmp; # this should be the number of elements in each row of the passed in array
881
882 # Darren Critchley - validate parameters
883 if ($colno > $ttlitems){$colno = '1';}
884 $colno--; # remove one from colno to deal with arrays starting at 0
885 if($colno < 0){$colno = '0';}
886 if ($alpnum ne '') { $alpnum = lc($alpnum); } else { $alpnum = 'a'; }
887 if ($srtdir ne '') { $srtdir = lc($srtdir); } else { $srtdir = 'src'; }
888
889 foreach $line (@tobesorted)
890 {
891 chomp($line);
892 if ($line ne '') {
893 my @temp = split(/\,/,$line);
894 # Darren Critchley - juggle the fields so that the one we want to sort on is first
895 my $tmpholder = $temp[0];
896 $temp[0] = $temp[$colno];
897 $temp[$colno] = $tmpholder;
898 $newline = "";
899 for ($ctr=0; $ctr < $ttlitems ; $ctr++) {
900 $newline=$newline . $temp[$ctr] . ",";
901 }
902 chop($newline);
903 push(@tmparray,$newline);
904 }
905 }
906 if ($alpnum eq 'n') {
907 @tmparray = sort {$a <=> $b} @tmparray;
908 } else {
909 @tmparray = (sort @tmparray);
910 }
911 foreach $line (@tmparray)
912 {
913 chomp($line);
914 if ($line ne '') {
915 my @temp = split(/\,/,$line);
916 my $tmpholder = $temp[0];
917 $temp[0] = $temp[$colno];
918 $temp[$colno] = $tmpholder;
919 $newline = "";
920 for ($ctr=0; $ctr < $ttlitems ; $ctr++){
921 $newline=$newline . $temp[$ctr] . ",";
922 }
923 chop($newline);
924 push(@srtedarray,$newline);
925 }
926 }
927
928 if ($srtdir eq 'dsc') {
929 @tmparray = reverse(@srtedarray);
930 return (@tmparray);
931 } else {
932 return (@srtedarray);
933 }
934}
935
936sub FetchPublicIp {
937 my %proxysettings;
938 &General::readhash("${General::swroot}/proxy/settings", \%proxysettings);
939 if ($_=$proxysettings{'UPSTREAM_PROXY'}) {
940 my ($peer, $peerport) = (/^(?:[a-zA-Z ]+\:\/\/)?(?:[A-Za-z0-9\_\.\-]*?(?:\:[A-Za-z0-9\_\.\-]*?)?\@)?([a-zA-Z0-9\.\_\-]*?)(?:\:([0-9]{1,5}))?(?:\/.*?)?$/);
941 Net::SSLeay::set_proxy($peer,$peerport,$proxysettings{'UPSTREAM_USER'},$proxysettings{'UPSTREAM_PASSWORD'} );
942 }
b2f8244a 943 my $user_agent = &MakeUserAgent();
0aa0cdcd 944 my ($out, $response) = Net::SSLeay::get_http( 'checkip4.dns.lightningwirelabs.com',
ac1cfefa
MT
945 80,
946 "/",
b2f8244a 947 Net::SSLeay::make_headers('User-Agent' => $user_agent )
ac1cfefa
MT
948 );
949 if ($response =~ m%HTTP/1\.. 200 OK%) {
5a2935b1 950 $out =~ /Your IP address is: (\d+.\d+.\d+.\d+)/;
ac1cfefa
MT
951 return $1;
952 }
953 return '';
954}
955
956#
957# Check if hostname.domain provided have IP provided
958# use gethostbyname to verify that
959# Params:
960# IP
961# hostname
962# domain
963# Output
964# 1 IP matches host.domain
965# 0 not in sync
966#
967sub DyndnsServiceSync ($;$;$) {
968
969 my ($ip,$hostName,$domain) = @_;
970 my @addresses;
971
972 #fix me no ip GROUP, what is the name ?
973 $hostName =~ s/$General::noipprefix//;
974 if ($hostName) { #may be empty
975 $hostName = "$hostName.$domain";
976 @addresses = gethostbyname($hostName);
977 }
978
979 if ($addresses[0] eq '') { # nothing returned ?
980 $hostName = $domain; # try resolving with domain only
981 @addresses = gethostbyname($hostName);
982 }
983
984 if ($addresses[0] ne '') { # got something ?
985 #&General::log("name:$addresses[0], alias:$addresses[1]");
986 # Build clear text list of IP
987 @addresses = map ( &Socket::inet_ntoa($_), @addresses[4..$#addresses]);
988 if (grep (/$ip/, @addresses)) {
989 return 1;
990 }
991 }
992 return 0;
993}
994#
995# This sub returns the red IP used to compare in DyndnsServiceSync
996#
997sub GetDyndnsRedIP {
998 my %settings;
999 &General::readhash("${General::swroot}/ddns/settings", \%settings);
1000
1001 open(IP, "${General::swroot}/red/local-ipaddress") or return 'unavailable';
1002 my $ip = <IP>;
1003 close(IP);
1004 chomp $ip;
1005
057dbeeb 1006 # 100.64.0.0/10 is reserved for dual-stack lite (http://tools.ietf.org/html/rfc6598).
ac1cfefa
MT
1007 if (&General::IpInSubnet ($ip,'10.0.0.0','255.0.0.0') ||
1008 &General::IpInSubnet ($ip,'172.16.0.0.','255.240.0.0') ||
057dbeeb
MT
1009 &General::IpInSubnet ($ip,'192.168.0.0','255.255.0.0') ||
1010 &General::IpInSubnet ($ip,'100.64.0.0', '255.192.0.0'))
ac1cfefa
MT
1011 {
1012 if ($settings{'BEHINDROUTER'} eq 'FETCH_IP') {
1013 my $RealIP = &General::FetchPublicIp;
1014 $ip = (&General::validip ($RealIP) ? $RealIP : 'unavailable');
1015 }
1016 }
1017 return $ip;
1018}
c545beb1
MT
1019
1020# Translate ICMP code to text
1021# ref: http://www.iana.org/assignments/icmp-parameters
1022sub GetIcmpDescription ($) {
1023 my $index = shift;
1024 my @icmp_description = (
1025 'Echo Reply', #0
1026 'Unassigned',
1027 'Unassigned',
1028 'Destination Unreachable',
1029 'Source Quench',
1030 'Redirect',
1031 'Alternate Host Address',
1032 'Unassigned',
1033 'Echo',
1034 'Router Advertisement',
1035 'Router Solicitation', #10
1036 'Time Exceeded',
1037 'Parameter Problem',
1038 'Timestamp',
1039 'Timestamp Reply',
1040 'Information Request',
1041 'Information Reply',
1042 'Address Mask Request',
1043 'Address Mask Reply',
1044 'Reserved (for Security)',
1045 'Reserved (for Robustness Experiment)', #20
1046 'Reserved',
1047 'Reserved',
1048 'Reserved',
1049 'Reserved',
1050 'Reserved',
1051 'Reserved',
1052 'Reserved',
1053 'Reserved',
1054 'Reserved',
1055 'Traceroute', #30
1056 'Datagram Conversion Error',
1057 'Mobile Host Redirect',
1058 'IPv6 Where-Are-You',
1059 'IPv6 I-Am-Here',
1060 'Mobile Registration Request',
1061 'Mobile Registration Reply',
1062 'Domain Name Request',
1063 'Domain Name Reply',
1064 'SKIP',
1065 'Photur', #40
1066 'Experimental');
a2b3eba9 1067 if ($index>41) {return 'unknown'} else {return $icmp_description[$index]};
c545beb1 1068}
b2f8244a
MT
1069
1070sub GetCoreUpdateVersion() {
1071 my $core_update;
1072
1073 open(FILE, "/opt/pakfire/db/core/mine");
1074 while (<FILE>) {
1075 $core_update = $_;
1076 last;
1077 }
1078 close(FILE);
1079
1080 return $core_update;
1081}
1082
1083sub MakeUserAgent() {
1084 my $user_agent = "IPFire/$General::version";
1085
1086 my $core_update = &GetCoreUpdateVersion();
1087 if ($core_update ne "") {
1088 $user_agent .= "/$core_update";
1089 }
1090
1091 return $user_agent;
1092}
1093
61027579
MT
1094sub RedIsWireless() {
1095 # This function checks if a network device is a wireless device.
1096
1097 my %settings = ();
1098 &readhash("${General::swroot}/ethernet/settings", \%settings);
1099
1100 # Find the name of the network device.
1101 my $device = $settings{'RED_DEV'};
1102
1103 # Exit, if no device is configured.
1104 return 0 if ($device eq "");
1105
1106 # Return 1 if the device is a wireless one.
1107 my $path = "/sys/class/net/$device/wireless";
1108 if (-d $path) {
1109 return 1;
1110 }
1111
1112 # Otherwise return zero.
1113 return 0;
1114}
1115
dfee7582
SS
1116# Function to read a file with UTF-8 charset.
1117sub read_file_utf8 ($) {
1118 my ($file) = @_;
1119
1120 open my $in, '<:encoding(UTF-8)', $file or die "Could not open '$file' for reading $!";
1121 local $/ = undef;
1122 my $all = <$in>;
1123 close $in;
1124
3e862ce4 1125 return $all;
dfee7582
SS
1126}
1127
1128# Function to write a file with UTF-8 charset.
1129sub write_file_utf8 ($) {
1130 my ($file, $content) = @_;
1131
1132 open my $out, '>:encoding(UTF-8)', $file or die "Could not open '$file' for writing $!";;
1133 print $out $content;
1134 close $out;
1135
1136 return;
1137}
1138
6d8eb5de 1139my $FIREWALL_RELOAD_INDICATOR = "${General::swroot}/firewall/reread";
0e430797
MT
1140
1141sub firewall_config_changed() {
1142 open FILE, ">$FIREWALL_RELOAD_INDICATOR" or die "Could not open $FIREWALL_RELOAD_INDICATOR";
1143 close FILE;
1144}
1145
1146sub firewall_needs_reload() {
1147 if (-e "$FIREWALL_RELOAD_INDICATOR") {
1148 return 1;
1149 }
1150
1151 return 0;
1152}
1153
1154sub firewall_reload() {
8039a710 1155 system("/usr/local/bin/firewallctrl");
0e430797
MT
1156}
1157
4cb523d4
SS
1158# Function which will return the used interface for the red network zone (red0, ppp0, etc).
1159sub get_red_interface() {
1160
1161 open(IFACE, "${General::swroot}/red/iface") or die "Could not open /var/ipfire/red/iface";
1162
1163 my $interface = <IFACE>;
1164 close(IFACE);
1165 chomp $interface;
1166
1167 return $interface;
1168}
1169
183b23b5
MT
1170sub dnssec_status() {
1171 my $path = "${General::swroot}/red/dnssec-status";
1172
1173 open(STATUS, $path) or return 0;
1174 my $status = <STATUS>;
1175 close(STATUS);
1176
1177 chomp($status);
1178
1179 return $status;
1180}
1a3323f2
DW
1181sub number_cpu_cores() {
1182 open my $cpuinfo, "/proc/cpuinfo" or die "Can't open cpuinfo: $!\n";
1183 my $cores = scalar (map /^processor/, <$cpuinfo>);
1184 close $cpuinfo;
1185
1186 return $cores;
1187}
183b23b5 1188
97022524
SS
1189# Tiny function to grab a single IP-address from a given file.
1190sub grab_address_from_file($) {
1191 my ($file) = @_;
1192
1193 my $address;
1194
1195 # Check if the given file exists.
1196 if(-f $file) {
1197 # Open the file for reading.
1198 open(FILE, $file) or die "Could not read from $file. $!\n";
1199
1200 # Read the address from the file.
1201 $address = <FILE>;
1202
1203 # Close filehandle.
1204 close(FILE);
1205
1206 # Remove newlines.
1207 chomp($address);
1208
1209 # Check if the obtained address is valid.
1210 if (&validip($address)) {
1211 # Return the address.
1212 return $address;
1213 }
1214 }
1215
1216 # Return nothing.
1217 return;
1218}
1219
c8dcd465
SS
1220# Function to get all configured and enabled nameservers.
1221sub get_nameservers () {
1222 my %settings;
1223 my %servers;
1224
1225 my @nameservers;
1226
1227 # Read DNS configuration.
1228 &readhash("$General::swroot/dns/settings", \%settings);
1229
1230 # Read configured DNS servers.
1231 &readhasharray("$General::swroot/dns/servers", \%servers);
1232
1233 # Check if the ISP assigned server should be used.
1234 if ($settings{'USE_ISP_NAMESERVERS'} eq "on") {
1235 # Assign ISP nameserver files.
1236 my @ISP_nameserver_files = ( "/var/run/dns1", "/var/run/dns2" );
1237
1238 # Loop through the array of ISP assigned DNS servers.
1239 foreach my $file (@ISP_nameserver_files) {
1240 # Grab the IP address.
1241 my $address = &grab_address_from_file($file);
1242
1243 # Check if an address has been grabbed.
1244 if ($address) {
1245 # Add the address to the array of nameservers.
1246 push(@nameservers, $address);
1247 }
1248 }
1249 }
1250
1251 # Check if DNS servers are configured.
1252 if (%servers) {
1253 # Loop through the hash of configured DNS servers.
1254 foreach my $id (keys %servers) {
1255 my $address = $servers{$id}[0];
1256 my $status = $servers{$id}[2];
1257
1258 # Check if the current processed server is enabled.
1259 if ($status eq "enabled") {
1260 # Add the address to the array of nameservers.
1261 push(@nameservers, $address);
1262 }
1263 }
1264 }
1265
1266 # Return the array.
e8adbea9 1267 return &uniq(@nameservers);
c8dcd465
SS
1268}
1269
c5f85b11
SS
1270# Function to format a string containing the amount of bytes to
1271# something human-readable.
1272sub formatBytes {
1273 # Private array which contains the units.
1274 my @units = qw(B KB MB GB TB PB);
1275
1276 my $bytes = shift;
1277 my $unit;
1278
1279 # Loop through the array of units.
1280 foreach my $element (@units) {
25932be3
SS
1281 # Assign current processed element to unit.
1282 $unit = $element;
1283
c5f85b11
SS
1284 # Break loop if the bytes are less than the next unit.
1285 last if $bytes < 1024;
1286
1287 # Divide bytes amount with 1024.
1288 $bytes /= 1024;
c5f85b11
SS
1289 }
1290
1291 # Return the divided and rounded bytes count and the unit.
1292 return sprintf("%.2f %s", $bytes, $unit);
1293}
1294
4e58ab4b
MT
1295# Cloud Stuff
1296
46b0f9ab
MT
1297sub running_in_cloud() {
1298 return &running_on_ec2() || &running_on_gcp();
1299}
1300
4e58ab4b
MT
1301sub running_on_ec2() {
1302 if (-e "/var/run/aws-instance-id") {
1303 return 1;
1304 }
1305
1306 return 0;
1307}
1308
e7978f56
MT
1309sub running_on_gcp() {
1310 if (-e "/var/run/gcp-instance-id") {
1311 return 1;
1312 }
1313
1314 return 0;
1315}
1316
ac1cfefa 13171;