21
use Net::IPv4Addr qw(:all);
22
22
$|=1; # line buffering
24
24
$General::version = 'VERSION';
25
25
$General::swroot = 'CONFIG_ROOT';
26
26
$General::noipprefix = 'noipg-';
28
require "${General::swroot}/network-functions.pl";
30
# This function executes a shell command without forking a shell or do any other
31
# Perl-voodoo before it. It deprecates the "system" command and is the only way
32
# to call shell commands.
36
system { ${command[0]} } @command;
42
# Calls a process in the background and returns nothing
43
sub system_background($) {
54
# Returns the output of a shell command
55
sub system_output($) {
60
unless ($pid = open(OUTPUT, "-|")) {
61
open(STDERR, ">&STDOUT");
62
exec { ${command[0]} } @command;
63
die "Could not execute @command: $!";
76
# Calls a shell command and throws away the output
80
open(SAVEOUT, ">&STDOUT");
81
open(SAVEERR, ">&STDERR");
83
open(STDOUT, ">/dev/null");
84
open(STDERR, ">&STDOUT");
89
my $rc = &safe_system(@command);
95
open(STDOUT, ">&SAVEOUT");
96
open(STDERR, ">&SAVEERR");
101
# Function to remove duplicates from an array
102
sub uniq { my %seen; grep !$seen{$_}++, @_ }
27
$General::adminmanualurl = 'http://wiki.ipfire.org';
105
30
# log ("message") use default 'ipcop' tag
112
37
my $logmessage = $_[0];
113
38
$logmessage =~ /([\w\W]*)/;
115
&system('logger', '-t', $tag, $logmessage);
117
sub setup_default_networks
120
my $defaultNetworks = shift;
122
&readhash("/var/ipfire/ethernet/settings", \%netsettings);
124
# Get current defined networks (Red, Green, Blue, Orange)
125
$defaultNetworks->{$Lang::tr{'fwhost any'}}{'IPT'} = "0.0.0.0/0.0.0.0";
126
$defaultNetworks->{$Lang::tr{'fwhost any'}}{'NAME'} = "ALL";
128
$defaultNetworks->{$Lang::tr{'green'}}{'IPT'} = "$netsettings{'GREEN_NETADDRESS'}/$netsettings{'GREEN_NETMASK'}";
129
$defaultNetworks->{$Lang::tr{'green'}}{'NET'} = "$netsettings{'GREEN_ADDRESS'}";
130
$defaultNetworks->{$Lang::tr{'green'}}{'NAME'} = "GREEN";
132
if ($netsettings{'RED_DEV'} ne ''){
133
$defaultNetworks->{$Lang::tr{'fwdfw red'}}{'IPT'} = "$netsettings{'RED_NETADDRESS'}/$netsettings{'RED_NETMASK'}";
134
$defaultNetworks->{$Lang::tr{'fwdfw red'}}{'NET'} = "$netsettings{'RED_ADDRESS'}";
135
$defaultNetworks->{$Lang::tr{'fwdfw red'}}{'NAME'} = "RED";
137
if ($netsettings{'ORANGE_DEV'} ne ''){
138
$defaultNetworks->{$Lang::tr{'orange'}}{'IPT'} = "$netsettings{'ORANGE_NETADDRESS'}/$netsettings{'ORANGE_NETMASK'}";
139
$defaultNetworks->{$Lang::tr{'orange'}}{'NET'} = "$netsettings{'ORANGE_ADDRESS'}";
140
$defaultNetworks->{$Lang::tr{'orange'}}{'NAME'} = "ORANGE";
143
if ($netsettings{'BLUE_DEV'} ne ''){
144
$defaultNetworks->{$Lang::tr{'blue'}}{'IPT'} = "$netsettings{'BLUE_NETADDRESS'}/$netsettings{'BLUE_NETMASK'}";
145
$defaultNetworks->{$Lang::tr{'blue'}}{'NET'} = "$netsettings{'BLUE_ADDRESS'}";
146
$defaultNetworks->{$Lang::tr{'blue'}}{'NAME'} = "BLUE";
150
$defaultNetworks->{'IPFire'}{'NAME'} = "IPFire";
153
if(-e "${General::swroot}/ovpn/settings")
155
my %ovpnSettings = ();
156
&readhash("${General::swroot}/ovpn/settings", \%ovpnSettings);
159
if(defined($ovpnSettings{'DOVPN_SUBNET'}))
161
my ($ip,$sub) = split(/\//,$ovpnSettings{'DOVPN_SUBNET'});
162
$sub=&General::iporsubtocidr($sub);
163
my @tempovpnsubnet = split("\/", $ovpnSettings{'DOVPN_SUBNET'});
164
$defaultNetworks->{'OpenVPN ' ."($ip/$sub)"}{'ADR'} = $tempovpnsubnet[0];
165
$defaultNetworks->{'OpenVPN ' ."($ip/$sub)"}{'NAME'} = "OpenVPN-Dyn";
169
if(-e "${General::swroot}/vpn/settings")
171
my %ipsecsettings = ();
172
&readhash("${General::swroot}/vpn/settings", \%ipsecsettings);
173
if($ipsecsettings{'RW_NET'} ne '')
175
my ($ip,$sub) = split(/\//,$ipsecsettings{'RW_NET'});
176
$sub=&General::iporsubtocidr($sub);
177
my @tempipsecsubnet = split("\/", $ipsecsettings{'RW_NET'});
178
$defaultNetworks->{'IPsec RW (' .$ip."/".$sub.")"}{'ADR'} = $tempipsecsubnet[0];
179
$defaultNetworks->{'IPsec RW (' .$ip."/".$sub.")"}{'NAME'} = "IPsec RW";
180
$defaultNetworks->{'IPsec RW (' .$ip."/".$sub.")"}{'NET'} = &getnextip($ip);
187
my $defaultNetworks = shift;
188
open(FILE, "${General::swroot}/ethernet/aliases") or die 'Unable to open aliases file.';
189
my @current = <FILE>;
192
foreach my $line (@current)
196
my @temp = split(/\,/,$line);
197
if ($temp[2] eq '') {
198
$temp[2] = "Alias $ctr : $temp[0]";
200
$defaultNetworks->{$temp[2]}{'IPT'} = "$temp[0]";
201
$defaultNetworks->{$temp[2]}{'NET'} = "$temp[0]";
40
system('logger', '-t', $tag, $logmessage);
277
# This function replaces the given hash in the original hash by keeping the old
278
# content and just replacing the new content
280
my $filename = $_[0];
285
readhash("${filename}", \%oldhash);
287
foreach $var (keys %$newhash){
288
$oldhash{$var}=$newhash->{$var};
291
# write cgi vars to the file.
292
open(FILE, ">${filename}") or die "Unable to write file $filename";
294
foreach $var (keys %oldhash)
296
if ( $var eq "__CGI__"){next;}
297
$val = $oldhash{$var};
298
# Darren Critchley Jan 17, 2003 added the following because when submitting with a graphic, the x and y
299
# location of the mouse are submitted as well, this was being written to the settings file causing
300
# some serious grief! This skips the variable.x and variable.y
301
if (!($var =~ /(.x|.y)$/)) {
304
if (!($var =~ /^ACTION/)) {
305
print FILE "${var}=${val}\n"; }
312
109
my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
313
$atime, $mtime, $ctime, $blksize, $blocks) = stat $_[0];
314
my $t = time() - $mtime;
316
return &format_time($t);
320
my $totalsecs = shift;
110
$atime, $mtime, $ctime, $blksize, $blocks) = stat $_[0];
113
my $totalsecs = $now - $mtime;
114
my $days = int($totalsecs / 86400);
115
my $totalhours = int($totalsecs / 3600);
116
my $hours = $totalhours % 24;
117
my $totalmins = int($totalsecs / 60);
118
my $mins = $totalmins % 60;
323
119
my $secs = $totalsecs % 60;
326
push(@s, "${secs}s");
329
my $min = $totalsecs % 60;
335
my $hrs = $totalsecs % 24;
341
my $days = int($totalsecs);
343
push(@s, "${days}d");
346
return join(" ", reverse(@s));
121
return "${days}d ${hours}h ${mins}m ${secs}s";
390
176
return &validmask($mask);
394
return &Network::convert_netmask2prefix(shift);
398
return &Network::convert_prefix2netmask(shift);
403
#Gets: Ip address or subnetmask in decimal oder CIDR
404
#Gives: What it gets only in CIDR format
409
if ($subnet =~ /^(.*?)\/(.*?)$/) {
410
($net,$mask) = split (/\//,$subnet);
416
#Subnet already in decimal and valid?
417
if ($mask=~/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ &&(($1<=255 && $2<=$1 && $3<=$2 && $4<=$3 ))) {
418
for (my $i=0;$i<=32;$i++){
419
if (&General::cidrtosub($i) eq $mask){
420
if ($full == 0){return $mask;}else{
421
return $net."/".$mask;
426
#Subnet in binary format?
427
if ($mask=~/^(\d{1,2})$/ && (($1<=32 && $1>=0))){
428
if($full == 0){ return &General::cidrtosub($mask);}else{
429
return $net."/".&General::cidrtosub($mask);
440
#gets: Ip Address or subnetmask in decimal oder CIDR
441
#Gives: What it gets only in CIDR format
446
if ($subnet =~ /^(.*?)\/(.*?)$/) {
447
($net,$mask) = split (/\//,$subnet);
452
#Subnet in decimal and valid?
453
if ($mask=~/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ &&(($1<=255 && $2<=$1 && $3<=$2 && $4<=$3 ))) {
454
for (my $i=0;$i<=32;$i++){
455
if (&General::cidrtosub($i) eq $mask){
456
if ($full == 0){return &General::subtocidr($mask);}else{
457
return $net."/".&General::subtocidr($mask);
462
#Subnet already in binary format?
463
if ($mask=~/^(\d{1,2})$/ && (($1<=32 && $1>=0))){
464
if($full == 0){ return $mask;}else{
465
return $net."/".$mask;
474
my $arg = join("/", @_);
476
return &Network::get_netaddress($arg);
481
#Gets: IP in Form ("192.168.0.0/24")
482
#Gives: Broadcastaddress of network
484
my ($ccdip,$ccdsubnet) = split "/",$ccdnet;
485
my $ip_address_binary = inet_aton( $ccdip );
486
my $netmask_binary = ~pack("N", (2**(32-$ccdsubnet))-1);
487
my $broadcast_address = inet_ntoa( $ip_address_binary | ~$netmask_binary );
488
return $broadcast_address;
492
return &Network::ip2bin(shift);
496
return &Network::bin2ip(shift);
500
return &Network::find_next_ip_address(shift, 4);
504
return &Network::find_next_ip_address(shift, -1);
507
179
sub validipandmask
509
#Gets: Ip address in 192.168.0.0/24 or 192.168.0.0/255.255.255.0 and checks if subnet valid
510
#Gives: True bzw 0 if success or false
514
if (!($ccdnet =~ /^(.*?)\/(.*?)$/)) {
517
my ($ccdip,$ccdsubnet)=split (/\//, $ccdnet);
519
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 ))) {
520
#Subnet in decimal and valid?
521
if ($ccdsubnet=~/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ &&(($1<=255 && $2<=$1 && $3<=$2 && $4<=$3 ))) {
522
for (my $i=0;$i<=32;$i++){
523
if (&General::cidrtosub($i) eq $ccdsubnet){
527
#Subnet already in binary format?
528
}elsif ($ccdsubnet=~/^(\d{1,2})$/ && (($1<=32 && $1>=0))){
552
my ($ip,$cidr)=split(/\//,$ccdnet);
553
$cidr=&iporsubtocidr($cidr);
555
#get OVPN-Subnet (dynamic range)
556
&readhash("${General::swroot}/ovpn/settings", \%ovpnconf);
557
my ($ovpnip,$ovpncidr)= split (/\//,$ovpnconf{'DOVPN_SUBNET'});
558
$ovpncidr=&iporsubtocidr($ovpncidr);
560
#check if we try to use same network as ovpn server
561
if ("$ip/$cidr" eq "$ovpnip/$ovpncidr") {
562
$errormessage=$errormessage.$Lang::tr{'ccd err isovpnnet'}."<br>";
563
return $errormessage;
566
#check if we try to use same network as another ovpn N2N
567
if($ownnet ne 'ovpn'){
568
&readhasharray("${General::swroot}/ovpn/ovpnconfig", \%ovpnconfhash);
569
foreach my $key (keys %ovpnconfhash) {
570
if ($ovpnconfhash{$key}[3] eq 'net'){
571
my @ovpnnet=split (/\//,$ovpnconfhash{$key}[11]);
572
if (&IpInSubnet($ip,$ovpnnet[0],&iporsubtodec($ovpnnet[1]))){
573
$errormessage=$errormessage.$Lang::tr{'ccd err isovpnn2n'}." $ovpnconfhash{$key}[1] <br>";
574
return $errormessage;
580
#check if we use a network-name/subnet (static-ovpn) that already exists
581
&readhasharray("${General::swroot}/ovpn/ccd.conf", \%ccdconfhash);
582
foreach my $key (keys %ccdconfhash) {
583
@ccdconf=split(/\//,$ccdconfhash{$key}[1]);
584
if ($ccdname eq $ccdconfhash{$key}[0])
586
$errormessage=$errormessage.$Lang::tr{'ccd err nameexist'}."<br>";
587
return $errormessage;
589
my ($newip,$newsub) = split(/\//,$ccdnet);
590
if (&IpInSubnet($newip,$ccdconf[0],&iporsubtodec($ccdconf[1])))
592
$errormessage=$errormessage.$Lang::tr{'ccd err issubnet'}." $ccdconfhash{$key}[0]<br>";
593
return $errormessage;
597
#check if we use a ipsec right network which is already defined
598
if($ownnet ne 'ipsec'){
599
&General::readhasharray("${General::swroot}/vpn/config", \%ipsecconf);
600
foreach my $key (keys %ipsecconf){
601
if ($ipsecconf{$key}[11] ne '' && $ipsecconf{$key}[36] eq ""){
602
foreach my $ipsecsubitem (split(/\|/, $ipsecconf{$key}[11])) {
603
my ($ipsecip,$ipsecsub) = split (/\//, $ipsecsubitem);
604
$ipsecsub=&iporsubtodec($ipsecsub);
605
if($ipsecconf{$key}[1] ne $ccdname){
606
if ( &IpInSubnet ($ip,$ipsecip,$ipsecsub) ){
607
$errormessage=$Lang::tr{'ccd err isipsecnet'}." Name: $ipsecconf{$key}[1]";
608
return $errormessage;
616
#check if we use the ipsec RW Network (if defined)
617
&readhash("${General::swroot}/vpn/settings", \%vpnconf);
618
if ($vpnconf{'RW_NET'} ne ''){
619
my ($ipsecrwnet,$ipsecrwsub)=split (/\//, $vpnconf{'RW_NET'});
620
if (&IpInSubnet($ip,$ipsecrwnet,&iporsubtodec($ipsecrwsub)))
622
$errormessage=$errormessage.$Lang::tr{'ccd err isipsecrw'}."<br>";
623
return $errormessage;
627
#call check_net_internal
628
if ($checktype eq "exact")
630
&General::check_net_internal_exact($ccdnet);
632
&General::check_net_internal_range($ccdnet);
636
sub check_net_internal_range{
638
my ($ip,$cidr)=split(/\//,$network);
641
$cidr=&iporsubtocidr($cidr);
642
#check if we use one of ipfire's networks (green,orange,blue)
643
&readhash("${General::swroot}/ethernet/settings", \%ownnet);
644
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;}
645
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;}
646
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;}
647
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;}
650
sub check_net_internal_exact{
652
my ($ip,$cidr)=split(/\//,$network);
655
$cidr=&iporsubtocidr($cidr);
656
#check if we use one of ipfire's networks (green,orange,blue)
657
&readhash("${General::swroot}/ethernet/settings", \%ownnet);
658
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;}
659
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;}
660
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;}
661
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;}
181
my $ipandmask = $_[0];
183
# split it into number and mask.
184
if (!($ipandmask =~ /^(.*?)\/(.*?)$/)) {
188
# first part not a ip?
189
if (!(&validip($ip))) {
191
return &validmask($mask);
726
# Checks a ccdname for letters, numbers and spaces
729
# ccdname should be at least one character in length
730
# but no more than 63 characters
731
if (length ($ccdname) < 1 || length ($ccdname) > 63) {
733
# Only valid characters are a-z, A-Z, 0-9, space and -
734
if ($ccdname !~ /^[a-zA-Z0-9 -]*$/) {
739
254
sub validdomainname
743
# Checks a domain name against RFC1035 and RFC2181
258
# Checks a domain name against RFC1035
744
259
my $domainname = $_[0];
745
my @parts = split (/\./, $domainname); # Split domain name at the '.'
260
my @parts = split (/\./, $domainname); # Split hostname at the '.'
747
262
foreach $part (@parts) {
748
# Each part should be at least one character in length
263
# Each part should be at least two characters in length
749
264
# but no more than 63 characters
750
if (length ($part) < 1 || length ($part) > 63) {
752
# Only valid characters are a-z, A-Z, 0-9, _ and -
753
if ($part !~ /^[a-zA-Z0-9_-]*$/) {
265
if (length ($part) < 2 || length ($part) > 63) {
267
# Only valid characters are a-z, A-Z, 0-9 and -
268
if ($part !~ /^[a-zA-Z0-9-]*$/) {
270
# First character can only be a letter or a digit
271
if (substr ($part, 0, 1) !~ /^[a-zA-Z0-9]*$/) {
273
# Last character can only be a letter or a digit
274
if (substr ($part, -1, 1) !~ /^[a-zA-Z0-9]*$/) {
759
sub validwildcarddomainname($) {
760
my $domainname = shift;
762
# Ignore any leading dots
763
if ($domainname =~ m/^\*\.([^\*]*)\*?/) {
767
return &validdomainname($domainname);
772
# Checks a fully qualified domain name against RFC1035 and RFC2181
284
# Checks a fully qualified domain name against RFC1035
773
285
my $fqdn = $_[0];
774
my @parts = split (/\./, $fqdn); # Split FQDN at the '.'
286
my @parts = split (/\./, $fqdn); # Split hostname at the '.'
775
287
if (scalar(@parts) < 2) { # At least two parts should
776
288
return 0;} # exist in a FQDN
777
# (i.e.hostname.domain)
779
for (my $index=0; $index < scalar(@parts); $index++) {
289
# (i.e. hostname.domain)
290
foreach $part (@parts) {
780
291
# Each part should be at least one character in length
781
292
# but no more than 63 characters
782
if (length ($parts[$index]) < 1 || length ($parts[$index]) > 63) {
785
# This is the hostname part
786
# Only valid characters are a-z, A-Z, 0-9 and -
787
if ($parts[$index] !~ /^[a-zA-Z0-9-]*$/) {
789
# First character can only be a letter or a digit
790
if (substr ($parts[$index], 0, 1) !~ /^[a-zA-Z0-9]*$/) {
792
# Last character can only be a letter or a digit
793
if (substr ($parts[$index], -1, 1) !~ /^[a-zA-Z0-9]*$/) {
796
# This is the domain part
797
# Only valid characters are a-z, A-Z, 0-9, _ and -
798
if ($parts[$index] !~ /^[a-zA-Z0-9_-]*$/) {
293
if (length ($part) < 1 || length ($part) > 63) {
295
# Only valid characters are a-z, A-Z, 0-9 and -
296
if ($part !~ /^[a-zA-Z0-9-]*$/) {
298
# First character can only be a letter or a digit
299
if (substr ($part, 0, 1) !~ /^[a-zA-Z0-9]*$/) {
301
# Last character can only be a letter or a digit
302
if (substr ($part, -1, 1) !~ /^[a-zA-Z0-9]*$/) {
855
365
# Call: NextIP ('1.1.1.1');
856
366
# Return: '1.1.1.2'
859
return &Network::find_next_ip_address(shift, 1);
863
return &Network::find_next_ip_address(shift, 4);
867
my ($ip,$cidr) = &Net::IPv4Addr::ipv4_parse(shift);
872
my ($ip,$cidr) = &Net::IPv4Addr::ipv4_parse(shift);
873
my $netmask = &Net::IPv4Addr::ipv4_cidr2msk($cidr);
874
return "$ip\/$netmask";
370
return &Socket::inet_ntoa( pack("N", 1 + unpack('N', &Socket::inet_aton(shift))
879
my @parts = split( /\@/, $address );
882
#check if we have one part before and after '@'
883
return 0 if ( $count != 2 );
885
#check if one of the parts starts or ends with a dot
886
return 0 if ( substr($parts[0],0,1) eq '.' );
887
return 0 if ( substr($parts[0],-1,1) eq '.' );
888
return 0 if ( substr($parts[1],0,1) eq '.' );
889
return 0 if ( substr($parts[1],-1,1) eq '.' );
891
#check first addresspart (before '@' sign)
892
return 0 if ( $parts[0] !~ m/^[a-zA-Z0-9\.!\-\_\+#]+$/ );
894
#check second addresspart (after '@' sign)
895
return 0 if ( $parts[1] !~ m/^[a-zA-Z0-9\.\-]+$/ );
377
return 0 if ( $mail !~ /^[0-9a-zA-Z\.\-\_]+\@[0-9a-zA-Z\.\-]+$/ );
378
return 0 if ( $mail =~ /^[^0-9a-zA-Z]|[^0-9a-zA-Z]$/);
379
return 0 if ( $mail !~ /([0-9a-zA-Z]{1})\@./ );
380
return 0 if ( $mail !~ /.\@([0-9a-zA-Z]{1})/ );
381
return 0 if ( $mail =~ /.\.\-.|.\-\..|.\.\..|.\-\-./g );
382
return 0 if ( $mail =~ /.\.\_.|.\-\_.|.\_\..|.\_\-.|.\_\_./g );
383
return 0 if ( $mail !~ /\.([a-zA-Z]{2,4})$/ );
1162
646
'Experimental');
1163
if ($index>41) {return 'unknown'} else {return $icmp_description[$index]};
1166
sub GetCoreUpdateVersion() {
1169
open(FILE, "/opt/pakfire/db/core/mine");
1176
return $core_update;
1179
sub MakeUserAgent() {
1180
my $user_agent = "IPFire/$General::version";
1182
my $core_update = &GetCoreUpdateVersion();
1183
if ($core_update ne "") {
1184
$user_agent .= "/$core_update";
1190
sub RedIsWireless() {
1191
# This function checks if a network device is a wireless device.
1194
&readhash("${General::swroot}/ethernet/settings", \%settings);
1196
# Find the name of the network device.
1197
my $device = $settings{'RED_DEV'};
1199
# Exit, if no device is configured.
1200
return 0 if ($device eq "");
1202
# Return 1 if the device is a wireless one.
1203
my $path = "/sys/class/net/$device/wireless";
1208
# Otherwise return zero.
1212
# Function to read a file with UTF-8 charset.
1213
sub read_file_utf8 ($) {
1216
open my $in, '<:encoding(UTF-8)', $file or die "Could not open '$file' for reading $!";
1224
# Function to write a file with UTF-8 charset.
1225
sub write_file_utf8 ($) {
1226
my ($file, $content) = @_;
1228
open my $out, '>:encoding(UTF-8)', $file or die "Could not open '$file' for writing $!";;
1229
print $out $content;
1235
my $FIREWALL_RELOAD_INDICATOR = "${General::swroot}/firewall/reread";
1237
sub firewall_config_changed() {
1238
open FILE, ">$FIREWALL_RELOAD_INDICATOR" or die "Could not open $FIREWALL_RELOAD_INDICATOR";
1242
sub firewall_needs_reload() {
1243
if (-e "$FIREWALL_RELOAD_INDICATOR") {
1250
sub firewall_reload() {
1251
&system("/usr/local/bin/firewallctrl");
1254
# Function which will return the used interface for the red network zone (red0, ppp0, etc).
1255
# if you change this also check speed.cgi that include a local copy for systemload reasons
1256
sub get_red_interface() {
1258
my $red_iface_file = "${General::swroot}/red/iface";
1260
if (-e $red_iface_file) {
1261
open(IFACE, "$red_iface_file") or die "Could not open $red_iface_file";
1262
$interface = <IFACE>;
1270
sub number_cpu_cores() {
1271
open my $cpuinfo, "/proc/cpuinfo" or die "Can't open cpuinfo: $!\n";
1272
my $cores = scalar (map /^processor/, <$cpuinfo>);
1278
# Tiny function to grab a single IP-address from a given file.
1279
sub grab_address_from_file($) {
1284
# Check if the given file exists.
1286
# Open the file for reading.
1287
open(FILE, $file) or die "Could not read from $file. $!\n";
1289
# Read the address from the file.
1298
# Check if the obtained address is valid.
1299
if (&validip($address)) {
1300
# Return the address.
1309
# Function to get all configured and enabled nameservers.
1310
sub get_nameservers () {
1316
# Read DNS configuration.
1317
&readhash("$General::swroot/dns/settings", \%settings);
1319
# Read configured DNS servers.
1320
&readhasharray("$General::swroot/dns/servers", \%servers);
1322
# Check if the ISP assigned server should be used.
1323
if ($settings{'USE_ISP_NAMESERVERS'} eq "on") {
1324
# Assign ISP nameserver files.
1325
my @ISP_nameserver_files = ( "/var/run/dns1", "/var/run/dns2" );
1327
# Loop through the array of ISP assigned DNS servers.
1328
foreach my $file (@ISP_nameserver_files) {
1329
# Grab the IP address.
1330
my $address = &grab_address_from_file($file);
1332
# Check if an address has been grabbed.
1334
# Add the address to the array of nameservers.
1335
push(@nameservers, $address);
1340
# Check if DNS servers are configured.
1342
# Loop through the hash of configured DNS servers.
1343
foreach my $id (keys %servers) {
1344
my $address = $servers{$id}[0];
1345
my $status = $servers{$id}[2];
1347
# Check if the current processed server is enabled.
1348
if ($status eq "enabled") {
1349
# Add the address to the array of nameservers.
1350
push(@nameservers, $address);
1356
return &uniq(@nameservers);
1359
# Function to format a string containing the amount of bytes to
1360
# something human-readable.
1362
# Private array which contains the units.
1363
my @units = qw(B KB MB GB TB PB);
1368
# Loop through the array of units.
1369
foreach my $element (@units) {
1370
# Assign current processed element to unit.
1373
# Break loop if the bytes are less than the next unit.
1374
last if $bytes < 1024;
1376
# Divide bytes amount with 1024.
1380
# Return the divided and rounded bytes count and the unit.
1381
return sprintf("%.2f %s", $bytes, $unit);
1384
# Function to collect and generate a hash for translating protocol numbers into
1386
sub generateProtoTransHash () {
1387
# File which contains the protocol definitions.
1388
my $protocols_file = "/etc/protocols";
1392
# Open protocols file.
1393
open(FILE, "$protocols_file") or die "Could not open $protocols_file. $!\n";
1395
# Loop through the file.
1396
while (my $line = <FILE>) {
1398
next if ($line =~ /^\#/);
1401
next if ($line =~ /^\s*$/);
1403
# Remove any newlines.
1406
# Split line content.
1407
my ($protocol_lc, $number, $protocol_uc, $comment) = split(' ', $line);
1409
# Add proto details to the hash of protocols.
1410
$protocols{$number} = $protocol_uc;
1413
# Close file handle.
1422
sub running_in_cloud() {
1423
return &running_on_ec2() || &running_on_gcp();
1426
sub running_on_ec2() {
1427
if (-e "/var/run/aws-instance-id") {
1434
sub running_on_gcp() {
1435
if (-e "/var/run/gcp-instance-id") {
647
if ($index>41) {return 'unknown'} else {return @icmp_description[$index]};