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