# linux-lib.pl # Active interface functions for all flavours of linux # active_interfaces([include-no-ipv4-address]) # Returns a list of currently ifconfig'd interfaces sub active_interfaces { local ($empty) = @_; my @rv; my $ethtool = &has_command("ethtool"); if (&has_command("ip")) { # Get status from new ip command &clean_language(); &open_execute_command(IFC, "ip addr", 1, 1); my @lines; while(<IFC>) { s/\r|\n//g; if (/^\S+/) { push(@lines, $_); } else { $lines[$#lines] .= $_; } } close(IFC); &reset_environment(); foreach my $l (@lines) { my %ifc; if ($l =~ /^\d+:\s+([^ \t\r\n\@]+\d+\.(\d+))@([^ \t\r\n\@]+\d+):/) { # Line like : # 3: eth0.99@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 $ifc{'fullname'} = $1; $ifc{'name'} = $ifc{'fullname'}; $ifc{'vlanid'} = $2; $ifc{'virtual'} = $3; } elsif ($l =~ /^\d+:\s+([^ \t\r\n\@]+):/) { # Line like : # 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 $ifc{'fullname'} = $1; $ifc{'name'} = $ifc{'fullname'} } elsif ($l =~ /^\d+:\s+([^ \t\r\n\@]+\d+)@([^ \t\r\n\@]+\d+):/) { # Line like : # 3: eth0@if0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 $ifc{'fullname'} = $1; $ifc{'name'} = $ifc{'fullname'}; $ifc{'ifname'} = $2; } else { # Unknown line! next; } if ($l =~ /\sinet\s+([0-9\.]+)\s+peer\s+([0-9\.]+)\/(\d+)(\s+brd\s+([0-9\.]+))?\s+scope\s+global(\s+(noprefixroute|dynamic))*\s+(\S+)/ && $8 eq $ifc{'name'}) { # Line like : # inet 193.9.101.120 peer 193.9.101.104/32 brd 193.9.101.120 scope global eth0 $ifc{'address'} = $1; $ifc{'netmask'} = &prefix_to_mask("$3"); } elsif ($l =~ /\sinet\s+([0-9\.]+)\/(\d+)(\s+metric\s+\d+)?(\s+brd\s+(\S+))?\s+scope\s+global(\s+(noprefixroute|dynamic|secondary))*\s+(\S+)/ && $8 eq $ifc{'name'}) { # Line like : # inet 193.9.101.120/24 brd 193.9.101.255 scope global br0 $ifc{'address'} = $1; $ifc{'netmask'} = &prefix_to_mask("$2"); } elsif ($l =~ /\sinet\s+([0-9\.]+)\s+peer\s+([0-9\.]+)\/(\d+)/) { # Line like : # inet 46.4.13.87 peer 46.4.13.65/32 $ifc{'address'} = $1; $ifc{'netmask'} = &prefix_to_mask("$3"); } elsif ($l =~ /\sinet\s+([0-9\.]+)\/(\d+)(\s+brd\s+(\S+))?\s+scope\s+host\s+(\S+)/ && $5 eq $ifc{'name'}) { # Line like : # inet 127.0.0.1/8 scope host lo $ifc{'address'} = $1; $ifc{'netmask'} = &prefix_to_mask("$2"); } if ($l =~ /\sbrd\s+([0-9\.]+)/) { $ifc{'broadcast'} = $1; } if ($l =~ /\smtu\s+(\d+)/) { $ifc{'mtu'} = $1; } if ($l =~ /ether\s+([0-9a-f:]+)/i) { $ifc{'ether'} = $1; } my (@address6, @netmask6, @scope6); while($l =~ s/inet6\s+(\S+)\/(\d+)\s+scope\s+(\S+)//i) { local ($address6, $netmask6, $scope6) = ($1, $2, $3); push(@address6, $address6); push(@netmask6, $netmask6); push(@scope6, $scope6); } $ifc{'address6'} = \@address6; $ifc{'netmask6'} = \@netmask6; $ifc{'scope6'} = \@scope6; $ifc{'up'}++ if ($l =~ /\sUP\s|<\S*UP\S*>/); $ifc{'promisc'}++ if ($l =~ /\sPROMISC\s/); $ifc{'edit'} = ($ifc{'name'} !~ /^ppp/); $ifc{'index'} = scalar(@rv); push(@rv, \%ifc); # Strip off the line for the primary IP, but only if there # is one if ($ifc{'address'}) { $l =~ s/\sinet\s+([0-9\.]+)\s+peer// || $l =~ s/\sinet\s+([0-9\.]+)\/(\d+)//; } # Add extra IPs as fake virtual interfaces, from lines like my $i = 0; my $bn = $ifc{'name'}; while($l =~ s/\sinet\s+([0-9\.]+)\/(\d+).*?\s\Q$bn\E:(\d+)// || $l =~ s/\sinet\s+([0-9\.]+)\/(\d+).*?(?:secondary|dynamic|global).*?\s\Q$bn\E//) { my %vifc; my $vn = defined($3) ? $3 : $i; $vifc{'name'} = $ifc{'name'}; $vifc{'fullname'} = $ifc{'name'}.":".$vn; $vifc{'address'} = $1; $vifc{'netmask'} = &prefix_to_mask("$2"); $vifc{'broadcast'} = &compute_broadcast( $vifc{'address'}, $vifc{'netmask'}); $vifc{'mtu'} = $ifc{'mtu'}; $vifc{'up'} = $ifc{'up'}; $vifc{'virtual'} = $vn; $vifc{'edit'} = ($vifc{'name'} !~ /^ppp/); $vifc{'index'} = scalar(@rv); push(@rv, \%vifc); $i++; } } } elsif (&has_command("ifconfig")) { &clean_language(); &open_execute_command(IFC, "ifconfig -a", 1, 1); my @lines; while(<IFC>) { s/\r|\n//g; if (/^\S+/) { push(@lines, $_); } else { $lines[$#lines] .= $_; } } close(IFC); &reset_environment(); foreach my $l (@lines) { my %ifc; $l =~ /^([^:\s]+)/ || next; $ifc{'name'} = $1; $l =~ /^(\S+)/; $ifc{'fullname'} = $1; $ifc{'fullname'} =~ s/:$//; if ($l =~ /^(\S+):(\d+)/) { $ifc{'virtual'} = $2; } if ($l =~ /^(\S+)\.(\d+)/) { $ifc{'vlanid'} = $2; } if ($l =~ /inet addr:(\S+)/) { $ifc{'address'} = $1; } elsif ($l =~ /inet (\S+)/) { $ifc{'address'} = $1; } elsif (!$empty) { next; } if ($l =~ /Mask:(\S+)/) { $ifc{'netmask'} = $1; } elsif ($l =~ /netmask (\S+)/) { $ifc{'netmask'} = $1; } if ($l =~ /Bcast:(\S+)/) { $ifc{'broadcast'} = $1; } elsif ($l =~ /broadcast (\S+)/) { $ifc{'broadcast'} = $1; } if ($l =~ /HWaddr (\S+)/) { $ifc{'ether'} = $1; } elsif ($l =~ /ether (\S+)/) { $ifc{'ether'} = $1; } if ($l =~ /MTU:(\d+)/) { $ifc{'mtu'} = $1; } elsif ($l =~ /mtu (\d+)/) { $ifc{'mtu'} = $1; } if ($l =~ /P-t-P:(\S+)/) { $ifc{'ptp'} = $1; } elsif ($l =~ /ptp (\S+)/) { $ifc{'ptp'} = $1; } $ifc{'up'}++ if ($l =~ /\sUP\s|<\S*UP\S*>/); $ifc{'promisc'}++ if ($l =~ /\sPROMISC\s/); my (@address6, @netmask6, @scope6); while($l =~ s/inet6 addr:\s*(\S+)\/(\d+)\s+Scope:(Global)//i) { local ($address6, $netmask6, $scope6) = ($1, $2, $3); push(@address6, $address6); push(@netmask6, $netmask6); push(@scope6, $scope6); } while($l =~ s/inet6 (\S+)\s+prefixlen (\d+)\s+scopeid\s+(\S+)<global>//i) { local ($address6, $netmask6, $scope6) = ($1, $2, $3); push(@address6, $address6); push(@netmask6, $netmask6); push(@scope6, $scope6); } $ifc{'address6'} = \@address6; $ifc{'netmask6'} = \@netmask6; $ifc{'scope6'} = \@scope6; $ifc{'edit'} = ($ifc{'name'} !~ /^ppp/); $ifc{'index'} = scalar(@rv); push(@rv, \%ifc); } } else { &error("Both the ifconfig and ip commands are missing"); } foreach my $ifc (@rv) { # For each ethernet interface, merge in data from ethtool if (&iface_type($ifc->{'fullname'}) eq 'Ethernet' && $ifc->{'virtual'} eq '' && $ethtool) { my $out = &backquote_command( "$ethtool $ifc->{'fullname'} 2>/dev/null"); if ($out =~ /Speed:\s+(\S+)/i && $1 ne "Unknown!") { $ifc->{'speed'} = $1; } if ($out =~ /Duplex:\s+(\S+)/i && $1 ne "Unknown!") { $ifc->{'duplex'} = $1; } if ($out =~ /Link\s+detected:\s+(\S+)/i) { $ifc->{'link'} = lc($1) eq 'yes' ? 1 : 0; } } } return @rv; } # activate_interface(&details) # Create or modify an interface sub activate_interface { my ($a) = @_; my ($old) = grep { $_->{'fullname'} eq $a->{'fullname'} } &active_interfaces(); # For Debian 5.0+ the "vconfig add" command is deprecated, this is handled # by ifup. if(($a->{'vlan'} == 1) && !(($gconfig{'os_type'} eq 'debian-linux') && ($gconfig{'os_version'} >= 5))) { local $vconfigCMD = "vconfig add " . quotemeta($a->{'physical'})." ". quotemeta($a->{'vlanid'}); local $vconfigout = &backquote_logged("$vconfigCMD 2>&1"); if ($?) { &error($vonconfigout); } } if (!&has_command("ifconfig") && &has_command("ip")) { # For a real interface, activate or de-activate the link if ($a->{'virtual'} eq '' && $a->{'up'} && (!$old || !$old->{'up'})) { # Bring up my $cmd = "ip link set dev ".quotemeta($a->{'name'})." up"; my $out = &backquote_logged("$cmd 2>&1"); &error("Failed to bring up link : $out") if ($?); } elsif ($a->{'virtual'} eq '' && !$a->{'up'} && $old && $old->{'up'}) { # Take down my $cmd = "ip link set dev ".quotemeta($a->{'name'})." down"; my $out = &backquote_logged("$cmd 2>&1"); &error("Failed to bring down link : $out") if ($?); } } my $cmd; if (&use_ifup_command($a)) { # Use Debian / Redhat ifup command if($a->{'vlan'} == 1) { # Name and fullname for VLAN tagged interfaces are "auto" so # we need to ifup using physical and vlanid. if ($a->{'up'}) { if(($a->{'mtu'}) && (($gconfig{'os_type'} eq 'redhat-linux') && ($gconfig{'os_version'} >= 13))) { my $cmd2 = "ifconfig ".quotemeta($a->{'physical'})." mtu ".quotemeta($a->{'mtu'}); my $out = &backquote_logged("$cmd2 2>&1"); if ($?) { &error($out); } } $cmd .= "ifup ".quotemeta($a->{'physical'}).".". quotemeta($a->{'vlanid'}); } else { $cmd .= "ifdown ".quotemeta($a->{'physical'}).".". quotemeta($a->{'vlanid'}); } } elsif ($a->{'up'}) { $cmd .= "ifdown ".quotemeta($a->{'fullname'}). "; ifup ".quotemeta($a->{'fullname'}); } else { $cmd .= "ifdown ".quotemeta($a->{'fullname'}); } } elsif (&has_command("ifconfig")) { # Build ifconfig command manually if($a->{'vlan'} == 1) { $cmd .= "ifconfig ".quotemeta($a->{'physical'}).".". quotemeta($a->{'vlanid'}); } else { $cmd .= "ifconfig ".quotemeta($a->{'name'}); if ($a->{'virtual'} ne "") { $cmd .= ":".quotemeta($a->{'virtual'}); } } $cmd .= " ".quotemeta($a->{'address'}); if ($a->{'netmask'}) { $cmd .= " netmask ".quotemeta($a->{'netmask'}); } if ($a->{'broadcast'}) { $cmd .= " broadcast ".quotemeta($a->{'broadcast'}); } if ($a->{'mtu'} && $a->{'virtual'} eq "") { $cmd .= " mtu ".quotemeta($a->{'mtu'}); } if ($a->{'up'}) { $cmd .= " up"; } else { $cmd .= " down"; } } elsif (&has_command("ip")) { # If the IP is changing, first remove it then re-add my $readd = 0; if ($old && $old->{'address'}) { if ($old->{'address'} ne $a->{'address'} || $old->{'netmask'} ne $a->{'netmask'}) { my $rcmd = "ip addr del ".quotemeta($old->{'address'}). "/".&mask_to_prefix($old->{'netmask'}). " dev ".quotemeta($a->{'name'}); &system_logged("$rcmd >/dev/null 2>&1"); $readd = 1; } } else { $readd = 1; } # Build ip command to add the new IP if ($readd) { $cmd .= "ip addr add ".quotemeta($a->{'address'}); if ($a->{'netmask'}) { $cmd .= "/".&mask_to_prefix($a->{'netmask'}); } if ($a->{'broadcast'}) { $cmd .= " broadcast ".quotemeta($a->{'broadcast'}); } if($a->{'vlan'} == 1) { $cmd .= " dev ".quotemeta($a->{'physical'}).".". quotemeta($a->{'vlanid'}); } else { $cmd .= " dev ".quotemeta($a->{'name'}); } } } else { &error("Both the ifconfig and ip commands are missing"); } my $out = &backquote_logged("cd / ; $cmd 2>&1"); if ($?) { &error($out); } # Apply ethernet address if ($a->{'ether'} && !&use_ifup_command($a) && &has_command("ifconfig")) { # With ifconfig command $out = &backquote_logged("ifconfig ".quotemeta($a->{'name'}). " hw ether ".quotemeta($a->{'ether'})." 2>&1"); if ($?) { &error($out); } } elsif ($a->{'ether'} && !&use_ifup_command($a) && &has_command("ip")) { # With ip link command $out = &backquote_logged("ip link set dev ".quotemeta($a->{'name'}). " address ".quotemeta($a->{'ether'})." 2>&1"); if ($?) { &error($out); } } # Apply MTU if ($a->{'mtu'} && !&use_ifup_command($a) && &has_command("ip")) { $out = &backquote_logged( "ip link set dev ".quotemeta($a->{'name'})." mtu ". quotemeta($a->{'mtu'})." 2>&1"); if ($?) { &error($out); } } if ($a->{'virtual'} eq '' && &has_command("ifconfig")) { # Remove old IPv6 addresses local $l = &backquote_command("ifconfig ".quotemeta($a->{'name'})); while($l =~ s/inet6 addr:\s*(\S+)\/(\d+)\s+Scope:(\S+)// || $l =~ s/inet6\s+(\S+)\s+prefixlen\s+(\d+)\s+scopeid\s+\S+//) { my $cmd = "ifconfig ".quotemeta($a->{'name'})." inet6 del ". quotemeta("$1/$2")." 2>&1"; $out = &backquote_logged($cmd); &error("Failed to remove old IPv6 address : $out") if ($?); } # Add IPv6 addresses for(my $i=0; $i<@{$a->{'address6'}}; $i++) { my $cmd = "ifconfig ".quotemeta($a->{'name'})." inet6 add ". quotemeta($a->{'address6'}->[$i])."/". quotemeta($a->{'netmask6'}->[$i])." 2>&1"; $out = &backquote_logged($cmd); &error("Failed to add IPv6 address : $out") if ($?); } } elsif ($a->{'virtual'} eq '' && &has_command("ip")) { # Remove old IPv6 addresses if ($old) { for(my $i=0; $i<@{$old->{'address6'}}; $i++) { my $cmd = "ip -6 addr del ". quotemeta($old->{'address6'}->[$i])."/". quotemeta($old->{'netmask6'}->[$i])." dev ". quotemeta($a->{'name'}); $out = &backquote_logged("$cmd 2>&1"); &error("Failed to remove old IPv6 address : $out") if ($?); } } # Add IPv6 addresses for(my $i=0; $i<@{$a->{'address6'}}; $i++) { my $cmd = "ip -6 addr add ". quotemeta($a->{'address6'}->[$i])."/". quotemeta($a->{'netmask6'}->[$i])." dev ". quotemeta($a->{'name'}); $out = &backquote_logged("$cmd 2>&1"); &error("Failed to add IPv6 address : $out") if ($?); } } } # deactivate_interface(&details) # Shutdown some active interface sub deactivate_interface { my ($a) = @_; if (&has_command("ifconfig")) { # Use old ifconfig command my $name = $a->{'name'}. ($a->{'virtual'} ne "" ? ":$a->{'virtual'}" : ""); my $address = $a->{'address'}. ($a->{'virtual'} ne "" ? ":$a->{'virtual'}" : ""); my $netmask = $a->{'netmask'}; if ($a->{'virtual'} ne "") { # Shutdown virtual interface by setting address to 0 &system_logged("ifconfig $name 0 >/dev/null 2>&1"); } # Delete all v6 addresses for(my $i=0; $i<@{$a->{'address6'}}; $i++) { my $cmd = "ifconfig ".quotemeta($a->{'name'})." inet6 del ". quotemeta($a->{'address6'}->[$i])."/". quotemeta($a->{'netmask6'}->[$i]); &backquote_logged("$cmd 2>&1"); } # Check if still up somehow my ($still) = grep { $_->{'fullname'} eq $name } &active_interfaces(); if ($still) { # Old version of ifconfig or non-virtual interface.. down it my $out; if (&use_ifup_command($a)) { $out = &backquote_logged( "ifdown ".quotemeta($name)." 2>&1"); } else { $out = &backquote_logged( "ifconfig ".quotemeta($name)." down 2>&1"); } my ($still) = grep { $_->{'fullname'} eq $name } &active_interfaces(); if ($still && $still->{'up'}) { &error($out ? "<pre>".&html_escape($out)."</pre>" : "Interface is still active even after ". "being shut down"); } if (&iface_type($name) =~ /^(.*) (VLAN)$/) { $out = &backquote_logged( "vconfig rem ".quotemeta($name)." 2>&1"); } } } elsif (&has_command("ip")) { # Use new ip command to remove all IPs my @del; if ($a->{'address'}) { push(@del, $a->{'address'}."/". &mask_to_prefix($a->{'netmask'})); } for(my $i=0; $i<@{$a->{'address6'}}; $i++) { push(@del, $a->{'address6'}->[$i]."/". $a->{'netmask6'}->[$i]); } foreach my $d (@del) { my $cmd = "ip addr del ".quotemeta($d)." dev ". quotemeta($a->{'name'}); my $out = &backquote_logged("$cmd 2>&1"); &error("Failed to remove old address : $out") if ($?); } if ($a->{'virtual'} eq '') { my $cmd = "ip link set dev ".quotemeta($a->{'name'})." down"; my $out = &backquote_logged("$cmd 2>&1"); &error("<pre>".&html_escape($out)."</pre>") if ($?); } } else { &error("Both the ifconfig and ip commands are missing"); } } # use_ifup_command(&iface) # Returns 1 if the ifup command must be used to bring up some interface. # True on Debian 5.0+ for non-ethernet, typically bonding and VLAN tagged interfaces. sub use_ifup_command { local ($iface) = @_; return ($gconfig{'os_type'} eq 'debian-linux' && $gconfig{'os_version'} >= 5 || $gconfig{'os_type'} eq 'redhat-linux' && $gconfig{'os_version'} >= 13) && ($iface->{'name'} !~ /^(eth|em|eno|ens|enp|enx|lo|br)/ || $iface->{'name'} =~ /^(\S+)\.(\d+)/) && $iface->{'virtual'} eq ''; } # iface_type(name) # Returns a human-readable interface type name sub iface_type { my ($name) = @_; if ($name =~ /^(.*)\.(\d+)$/) { return &iface_type("$1")." VLAN"; } return "PPP" if ($name =~ /^ppp/); return "SLIP" if ($name =~ /^sl/); return "PLIP" if ($name =~ /^plip/); return "Ethernet" if ($name =~ /^eth|em|eno|ens|enp|enx|p\d+p\d+|vtnet/); return "Wireless Ethernet" if ($name =~ /^(wlan|ath)/); return "Arcnet" if ($name =~ /^arc/); return "Token Ring" if ($name =~ /^tr/); return "Pocket/ATP" if ($name =~ /^atp/); return "Loopback" if ($name =~ /^lo/); return "ISDN rawIP" if ($name =~ /^isdn/); return "ISDN syncPPP" if ($name =~ /^ippp/); return "CIPE" if ($name =~ /^cip/); return "VmWare" if ($name =~ /^vmnet/); return "Wireless" if ($name =~ /^wlan/); return "Bonded" if ($name =~ /^bond/); return "OpenVZ" if ($name =~ /^venet/); return "Bridge" if ($name =~ /^(br|xenbr|virbr)/); return $text{'ifcs_unknown'}; } # list_routes() # Returns a list of active routes sub list_routes { local @rv; if (&has_command("netstat")) { # Use old netstat command if installed &open_execute_command(ROUTES, "netstat -rn", 1, 1); while(<ROUTES>) { s/\s+$//; if (/^([0-9\.]+)\s+([0-9\.]+)\s+([0-9\.]+)\s+\S+\s+\S+\s+\S+\s*\S+\s+(\S+)$/) { push(@rv, { 'dest' => $1, 'gateway' => $2, 'netmask' => $3, 'iface' => $4 }); } } close(ROUTES); &open_execute_command(ROUTES, "netstat -rn -A inet6", 1, 1); while(<ROUTES>) { s/\s+$//; if (/^([0-9a-z:]+)\/([0-9]+)\s+([0-9a-z:]+)\s+\S+\s+\S+\s+\S+\s*\S+\s+(\S+)$/) { push(@rv, { 'dest' => $1, 'gateway' => $3, 'netmask' => $2, 'iface' => $4 }); } } close(ROUTES); } elsif (&has_command("ip")) { # Use new ip command &open_execute_command(ROUTES, "ip route", 1, 1); while(<ROUTES>) { s/\r|\n//g; if (/^(\S+)\s+/) { my $r = { 'dest' => $1 }; if ($r->{'dest'} =~ /^(\S+)\/(\d+)/) { $r->{'dest'} = $1; $r->{'netmask'} = &prefix_to_mask("$2"); } if (/\sdev\s+(\S+)/) { $r->{'iface'} = $1; } if (/\svia\s+(\S+)/) { $r->{'gateway'} = $1; } push(@rv, $r); } } close(ROUTES); } else { &error("Both the ip and netstat commands are missing!"); } return @rv; } # load_module(&details) # Load or modify a loaded module sub load_module { local $a = $_[0]; local $cmd = "modprobe bonding"; if ($a->{'mode'}) { $cmd .= " mode=".quotemeta($a->{'mode'}); } if ($a->{'miimon'}) { $cmd .= " miimon=".quotemeta($a->{'miimon'}); } if ($a->{'downdelay'}) { $cmd .= " downdelay=".quotemeta($a->{'downdelay'}); } if ($a->{'updelay'}) { $cmd .= " updelay=".quotemeta($a->{'updelay'}); } local $out = &backquote_logged("$cmd 2>&1"); &error($out) if ($?); } # Tries to unload the module # unload_module(name) sub unload_module { my ($name) = @_; my $cmd = "modprobe -r bonding"; local $out = &backquote_logged("$cmd 2>&1"); &error($out) if ($?); } # list_interfaces() # Returns a list of active interface names sub list_interfaces { my @ret; $cmd = "ifconfig -a"; local $out = &backquote_logged("$cmd 2>&1"); &error($out) if ($?); my @lines = split("\n", $out); foreach my $line (@lines) { $line =~ /^([\w|.]*)/m; if ($1) { push(@ret, $1); } } return @ret; } # delete_route(&route) # Delete one active route, as returned by list_routes. Returns an error message # on failure, or undef on success sub delete_route { my ($route) = @_; my $cmd; my $proto = &check_ip6address($route->{'dest'}) || $route->{'dest'} eq '::' ? 6 : 4; if (&has_command("route")) { # Use old route command $cmd = "route ". ($proto == 6 ? "-A inet6" : "-A inet")." del "; if (!$route->{'dest'} || $route->{'dest'} eq '0.0.0.0' || $route->{'dest'} eq '::') { $cmd .= " default"; } elsif ($route->{'netmask'} eq '255.255.255.255') { $cmd .= " -host ".quotemeta($route->{'dest'}); } elsif (!&check_ip6address($route->{'dest'})) { $cmd .= " -net ".quotemeta($route->{'dest'}); if ($route->{'netmask'} && $route->{'netmask'} ne '0.0.0.0') { $cmd .= " netmask ".quotemeta($route->{'netmask'}); } } else { $cmd .= quotemeta("$route->{'dest'}/$route->{'netmask'}"); } if ($route->{'gateway'}) { $cmd .= " gw ".quotemeta($route->{'gateway'}); } elsif ($route->{'iface'}) { $cmd .= " dev ".quotemeta($route->{'iface'}); } } elsif (&has_command("ip")) { # Use new ip command $cmd = "ip -".$proto." route delete"; if (!$route->{'dest'} || $route->{'dest'} eq '0.0.0.0' || $route->{'dest'} eq '::') { $cmd .= " default"; } else { $cmd .= " ".quotemeta($route->{'dest'}); if ($route->{'netmask'} && $route->{'netmask'} ne '0.0.0.0' && $route->{'netmask'} != 32) { if ($route->{'netmask'} =~ /^\d+$/) { $cmd .= "/".quotemeta($route->{'netmask'}); } else { $cmd .= "/".&mask_to_prefix($route->{'netmask'}); } } } } else { return "Missing the route and ip commands"; } my $out = &backquote_logged("$cmd 2>&1 </dev/null"); return $? ? $out : undef; } # create_route(&route) # Adds a new active route sub create_route { local ($route) = @_; my $cmd; my $proto = &check_ip6address($route->{'dest'}) || &check_ip6address($route->{'gateway'}) ? 6 : 4; if (&has_command("route")) { # Use old route command $cmd = "route ".($proto == 6 ? "-A inet6" : "-A inet")." add"; if (!$route->{'dest'} || $route->{'dest'} eq '0.0.0.0' || $route->{'dest'} eq '::') { $cmd .= " default"; } elsif ($route->{'netmask'} eq '255.255.255.255') { $cmd .= " -host ".quotemeta($route->{'dest'}); } elsif (!&check_ip6address($route->{'dest'})) { $cmd .= " -net ".quotemeta($route->{'dest'}); if ($route->{'netmask'} && $route->{'netmask'} ne '0.0.0.0') { $cmd .= " netmask ".quotemeta($route->{'netmask'}); } } else { $cmd .= quotemeta("$route->{'dest'}/$route->{'netmask'}"); } if ($route->{'gateway'}) { $cmd .= " gw ".quotemeta($route->{'gateway'}); } elsif ($route->{'iface'}) { $cmd .= " dev ".quotemeta($route->{'iface'}); } } elsif (&has_command("ip")) { # Use new ip command $cmd = "ip -".$proto." route add"; if (!$route->{'dest'} || $route->{'dest'} eq '0.0.0.0' || $route->{'dest'} eq '::') { $cmd .= " default"; } else { $cmd .= " ".quotemeta($route->{'dest'}); if ($route->{'netmask'} && $route->{'netmask'} ne '0.0.0.0' && $route->{'netmask'} != 32) { if ($route->{'netmask'} =~ /^\d+$/) { $cmd .= "/".quotemeta($route->{'netmask'}); } else { $cmd .= "/".&mask_to_prefix($route->{'netmask'}); } } } if ($route->{'gateway'}) { $cmd .= " via ".quotemeta($route->{'gateway'}); } if ($route->{'iface'}) { $cmd .= " dev ".quotemeta($route->{'iface'}); } } else { return "Missing the route and ip commands"; } my $out = &backquote_logged("$cmd 2>&1 </dev/null"); return $? ? $out : undef; } # iface_hardware(name) # Does some interface have an editable hardware address sub iface_hardware { return $_[0] =~ /^(eth|em|eno|ens|enp|enx)/; } # allow_interface_clash() # Returns 0 to indicate that two virtual interfaces with the same IP # are not allowed sub allow_interface_clash { return 0; } # get_dns_config() # Returns a hashtable containing keys nameserver, domain, search & order # XXX factor out to os_ functions sub get_dns_config { local $dns = { }; local $rc; local $dnsfile; if ($use_suse_dns && ($rc = &parse_rc_config()) && $rc->{'NAMESERVER'}) { # Special case - get DNS settings from SuSE config local @ns = split(/\s+/, $rc->{'NAMESERVER'}->{'value'}); $dns->{'nameserver'} = [ grep { $_ ne "YAST_ASK" } @ns ]; local $src = $rc->{'SEARCHLIST'}; $dns->{'domain'} = [ split(/\s+/, $src->{'value'}) ] if ($src); $dnsfile = $rc_config; } elsif ($gconfig{'os_type'} eq 'debian-linux' && -l "/etc/resolv.conf" && $netplan_dir) { # On Ubuntu 18+, /etc/resolv.conf is auto-generated from netplan config my @boot = &boot_interfaces(); foreach my $b (@boot) { if ($b->{'nameserver'}) { $dns->{'nameserver'} = $b->{'nameserver'}; $dns->{'domain'} = $b->{'search'}; $dnsfile = $b->{'file'}; last; } } } elsif ($gconfig{'os_type'} eq 'debian-linux' && -l "/etc/resolv.conf") { # On Ubuntu 12+, /etc/resolv.conf is auto-generated from network # interface config my @ifaces = &get_interface_defs(); foreach my $i (@ifaces) { local ($ns) = grep { $_->[0] eq 'dns-nameservers' } @{$i->[3]}; local @dom = grep { $_->[0] eq 'dns-domain' || $_->[0] eq 'dns-search' } @{$i->[3]}; if ($ns) { $dns->{'nameserver'} = [ split(/\s+/, $ns->[1]) ]; if (@dom) { $dns->{'domain'} = [ map { split(/\s+/, $_->[1]) } @dom ]; } $dnsfile = "/etc/network/interfaces"; last; } } } if (!$dnsfile) { # Just read resolv.conf &open_readfile(RESOLV, "/etc/resolv.conf"); while(<RESOLV>) { s/\r|\n//g; s/#.*$//; s/;.*$//; if (/nameserver\s+(.*)/) { push(@{$dns->{'nameserver'}}, split(/\s+/, $1)); } elsif (/domain\s+(\S+)/) { $dns->{'domain'} = [ $1 ]; } elsif (/search\s+(.*)/) { $dns->{'domain'} = [ split(/\s+/, $1) ]; } } close(RESOLV); $dnsfile = "/etc/resolv.conf"; } &open_readfile(SWITCH, "/etc/nsswitch.conf"); while(<SWITCH>) { s/\r|\n//g; if (/^\s*hosts:\s+(.*)/) { $dns->{'order'} = $1; } } close(SWITCH); $dns->{'files'} = [ $dnsfile, "/etc/nsswitch.conf" ]; return $dns; } # save_dns_config(&config) # Writes out the resolv.conf and nsswitch.conf files sub save_dns_config { local ($conf) = @_; local ($need_apply, $generated_resolv) = (0, 0); # Call OS-specific function to update resolvers elsewhere if (defined(&os_save_dns_config)) { ($need_apply, $generated_resolv) = &os_save_dns_config($conf); } if (!$generated_resolv) { # Update standard resolv.conf file &lock_file("/etc/resolv.conf"); &open_readfile(RESOLV, "/etc/resolv.conf"); local @resolv = <RESOLV>; close(RESOLV); &open_tempfile(RESOLV, ">/etc/resolv.conf"); foreach (@{$conf->{'nameserver'}}) { &print_tempfile(RESOLV, "nameserver $_\n"); } if ($conf->{'domain'}) { if ($conf->{'domain'}->[1]) { &print_tempfile(RESOLV, "search ",join(" ", @{$conf->{'domain'}}),"\n"); } else { &print_tempfile(RESOLV, "domain $conf->{'domain'}->[0]\n"); } } foreach (@resolv) { &print_tempfile(RESOLV, $_) if (!/^\s*(nameserver|domain|search)\s+/); } &close_tempfile(RESOLV); &unlock_file("/etc/resolv.conf"); } # Update resolution order in nsswitch.conf &lock_file("/etc/nsswitch.conf"); &open_readfile(SWITCH, "/etc/nsswitch.conf"); local @switch = <SWITCH>; close(SWITCH); &open_tempfile(SWITCH, ">/etc/nsswitch.conf"); foreach (@switch) { if (/^\s*hosts:\s+/) { &print_tempfile(SWITCH, "hosts:\t$conf->{'order'}\n"); } else { &print_tempfile(SWITCH, $_); } } &close_tempfile(SWITCH); &unlock_file("/etc/nsswitch.conf"); # Update SuSE config file for resolution order if ($use_suse_dns) { &lock_file($rc_config); local $rc = &parse_rc_config(); if ($rc->{'USE_NIS_FOR_RESOLVING'}) { if ($conf->{'order'} =~ /nis/) { &save_rc_config($rc, "USE_NIS_FOR_RESOLVING", "yes"); } else { &save_rc_config($rc, "USE_NIS_FOR_RESOLVING", "no"); } } &unlock_file($rc_config); } # Update resolv.conf from network interfaces config if ($need_apply) { &apply_network(); } } $max_dns_servers = 3; # order_input(&dns) # Returns HTML for selecting the name resolution order sub order_input { my @o = split(/\s+/, $_[0]->{'order'}); @o = map { s/nis\+/nisplus/; s/yp/nis/; $_; } @o; my @opts = ( [ "files", "Hosts file" ], [ "dns", "DNS" ], [ "nis", "NIS" ], [ "nisplus", "NIS+" ], [ "ldap", "LDAP" ], [ "db", "DB" ], [ "mdns4", "Multicast DNS" ], [ "myhostname", "Local hostname" ] ); if (&indexof("mdns4_minimal", @o) >= 0) { push(@opts, [ "mdns4_minimal", "Multicast DNS (minimal)" ]); } return &common_order_input("order", join(" ", @o), \@opts); } # parse_order(&dns) # Parses the form created by order_input() sub parse_order { if (defined($in{'order'})) { $in{'order'} =~ /\S/ || &error($text{'dns_eorder'}); $_[0]->{'order'} = $in{'order'}; } else { local($i, @order); for($i=0; defined($in{"order_$i"}); $i++) { push(@order, $in{"order_$i"}) if ($in{"order_$i"}); } $_[0]->{'order'} = join(" ", @order); } } 1;
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
images | Folder | 0755 |
|
|
lang | Folder | 0755 |
|
|
CHANGELOG | File | 5.55 KB | 0644 |
|
acl_security.pl | File | 3.08 KB | 0755 |
|
apply.cgi | File | 184 B | 0755 |
|
backup_config.pl | File | 1005 B | 0755 |
|
cgi_args.pl | File | 752 B | 0755 |
|
cobalt-linux-lib.pl | File | 32.85 KB | 0755 |
|
coherent-linux-lib.pl | File | 32.85 KB | 0755 |
|
config | File | 48 B | 0644 |
|
config-ALL-linux | File | 48 B | 0644 |
|
config-cygwin | File | 82 B | 0644 |
|
config-freebsd | File | 48 B | 0644 |
|
config-macos | File | 48 B | 0644 |
|
config-netbsd | File | 48 B | 0644 |
|
config-openbsd | File | 48 B | 0644 |
|
config-solaris | File | 79 B | 0644 |
|
config-syno-linux | File | 48 B | 0644 |
|
config-unixware | File | 48 B | 0644 |
|
config-windows | File | 78 B | 0644 |
|
config.info | File | 193 B | 0644 |
|
config.info.ca | File | 241 B | 0644 |
|
config.info.cs | File | 205 B | 0644 |
|
config.info.de | File | 219 B | 0644 |
|
config.info.es | File | 175 B | 0644 |
|
config.info.fa | File | 255 B | 0644 |
|
config.info.fr | File | 246 B | 0644 |
|
config.info.hu | File | 0 B | 0644 |
|
config.info.ja | File | 68 B | 0644 |
|
config.info.nl | File | 197 B | 0644 |
|
config.info.no | File | 208 B | 0644 |
|
config.info.pl | File | 240 B | 0644 |
|
config.info.pt_BR | File | 229 B | 0644 |
|
config.info.ru | File | 361 B | 0644 |
|
config.info.sk | File | 225 B | 0644 |
|
config.info.sv | File | 42 B | 0644 |
|
config.info.tr | File | 65 B | 0644 |
|
config.info.uk | File | 87 B | 0644 |
|
config.info.zh | File | 43 B | 0644 |
|
config.info.zh_TW | File | 44 B | 0644 |
|
create_route.cgi | File | 1004 B | 0755 |
|
cygwin-lib.pl | File | 11.28 KB | 0755 |
|
debian-linux-lib.pl | File | 33.58 KB | 0755 |
|
defaultacl | File | 114 B | 0644 |
|
delete_aifcs.cgi | File | 537 B | 0755 |
|
delete_bifcs.cgi | File | 1.44 KB | 0755 |
|
delete_hosts.cgi | File | 523 B | 0755 |
|
delete_ipnodes.cgi | File | 542 B | 0755 |
|
delete_routes.cgi | File | 458 B | 0755 |
|
edit_aifc.cgi | File | 5.09 KB | 0755 |
|
edit_bifc.cgi | File | 10.42 KB | 0755 |
|
edit_host.cgi | File | 1.13 KB | 0755 |
|
edit_ipnode.cgi | File | 1.04 KB | 0755 |
|
edit_range.cgi | File | 1.34 KB | 0755 |
|
freebsd-lib.pl | File | 19.22 KB | 0755 |
|
gentoo-linux-lib.pl | File | 8.47 KB | 0755 |
|
index.cgi | File | 1.25 KB | 0755 |
|
interface_chooser.cgi | File | 3.8 KB | 0755 |
|
linux-lib.pl | File | 27.58 KB | 0755 |
|
list_dns.cgi | File | 2.3 KB | 0755 |
|
list_hosts.cgi | File | 1.36 KB | 0755 |
|
list_ifcs.cgi | File | 7.96 KB | 0755 |
|
list_ipnodes.cgi | File | 1.07 KB | 0755 |
|
list_routes.cgi | File | 3.38 KB | 0755 |
|
log_parser.pl | File | 1.24 KB | 0755 |
|
macos-lib.pl | File | 11.57 KB | 0755 |
|
mandrake-linux-lib.pl | File | 32.85 KB | 0755 |
|
mod_aifc.cgi | File | 720 B | 0755 |
|
module.info | File | 485 B | 0644 |
|
module.info.af | File | 0 B | 0644 |
|
module.info.af.auto | File | 123 B | 0644 |
|
module.info.ar | File | 0 B | 0644 |
|
module.info.ar.auto | File | 170 B | 0644 |
|
module.info.be | File | 0 B | 0644 |
|
module.info.be.auto | File | 226 B | 0644 |
|
module.info.bg | File | 0 B | 0644 |
|
module.info.bg.auto | File | 261 B | 0644 |
|
module.info.ca | File | 127 B | 0644 |
|
module.info.ca.auto | File | 25 B | 0644 |
|
module.info.cs | File | 27 B | 0644 |
|
module.info.cs.auto | File | 111 B | 0644 |
|
module.info.da | File | 0 B | 0644 |
|
module.info.da.auto | File | 129 B | 0644 |
|
module.info.de | File | 121 B | 0644 |
|
module.info.de.auto | File | 19 B | 0644 |
|
module.info.el | File | 0 B | 0644 |
|
module.info.el.auto | File | 229 B | 0644 |
|
module.info.es | File | 30 B | 0644 |
|
module.info.es.auto | File | 116 B | 0644 |
|
module.info.eu | File | 0 B | 0644 |
|
module.info.eu.auto | File | 142 B | 0644 |
|
module.info.fa | File | 0 B | 0644 |
|
module.info.fa.auto | File | 194 B | 0644 |
|
module.info.fi | File | 0 B | 0644 |
|
module.info.fi.auto | File | 145 B | 0644 |
|
module.info.fr | File | 30 B | 0644 |
|
module.info.fr.auto | File | 128 B | 0644 |
|
module.info.he | File | 0 B | 0644 |
|
module.info.he.auto | File | 161 B | 0644 |
|
module.info.hr | File | 0 B | 0644 |
|
module.info.hr.auto | File | 148 B | 0644 |
|
module.info.hu | File | 34 B | 0644 |
|
module.info.hu.auto | File | 148 B | 0644 |
|
module.info.it | File | 28 B | 0644 |
|
module.info.it.auto | File | 112 B | 0644 |
|
module.info.ja | File | 33 B | 0644 |
|
module.info.ja.auto | File | 153 B | 0644 |
|
module.info.ko | File | 28 B | 0644 |
|
module.info.ko.auto | File | 105 B | 0644 |
|
module.info.lt | File | 0 B | 0644 |
|
module.info.lt.auto | File | 157 B | 0644 |
|
module.info.lv | File | 0 B | 0644 |
|
module.info.lv.auto | File | 157 B | 0644 |
|
module.info.ms | File | 136 B | 0644 |
|
module.info.ms.auto | File | 18 B | 0644 |
|
module.info.mt | File | 0 B | 0644 |
|
module.info.mt.auto | File | 144 B | 0644 |
|
module.info.nl | File | 29 B | 0644 |
|
module.info.nl.auto | File | 105 B | 0644 |
|
module.info.no | File | 31 B | 0644 |
|
module.info.no.auto | File | 99 B | 0644 |
|
module.info.pl | File | 122 B | 0644 |
|
module.info.pl.auto | File | 19 B | 0644 |
|
module.info.pt | File | 31 B | 0644 |
|
module.info.pt.auto | File | 125 B | 0644 |
|
module.info.pt_BR | File | 34 B | 0644 |
|
module.info.pt_BR.auto | File | 131 B | 0644 |
|
module.info.ro | File | 0 B | 0644 |
|
module.info.ro.auto | File | 143 B | 0644 |
|
module.info.ru | File | 36 B | 0644 |
|
module.info.ru.auto | File | 167 B | 0644 |
|
module.info.sk | File | 28 B | 0644 |
|
module.info.sk.auto | File | 113 B | 0644 |
|
module.info.sl | File | 0 B | 0644 |
|
module.info.sl.auto | File | 140 B | 0644 |
|
module.info.sv | File | 31 B | 0644 |
|
module.info.sv.auto | File | 103 B | 0644 |
|
module.info.th | File | 0 B | 0644 |
|
module.info.th.auto | File | 327 B | 0644 |
|
module.info.tr | File | 30 B | 0644 |
|
module.info.tr.auto | File | 130 B | 0644 |
|
module.info.uk | File | 0 B | 0644 |
|
module.info.uk.auto | File | 223 B | 0644 |
|
module.info.ur | File | 0 B | 0644 |
|
module.info.ur.auto | File | 210 B | 0644 |
|
module.info.vi | File | 0 B | 0644 |
|
module.info.vi.auto | File | 170 B | 0644 |
|
module.info.zh | File | 21 B | 0644 |
|
module.info.zh.auto | File | 90 B | 0644 |
|
module.info.zh_TW | File | 24 B | 0644 |
|
module.info.zh_TW.auto | File | 96 B | 0644 |
|
msc-linux-lib.pl | File | 32.85 KB | 0755 |
|
net-lib.pl | File | 12 KB | 0755 |
|
netbsd-lib.pl | File | 19.22 KB | 0755 |
|
netplan-lib.pl | File | 21.01 KB | 0644 |
|
open-linux-lib.pl | File | 7.2 KB | 0755 |
|
openbsd-lib.pl | File | 12.6 KB | 0755 |
|
openmamba-linux-lib.pl | File | 32.85 KB | 0755 |
|
pardus-linux-lib.pl | File | 32.85 KB | 0755 |
|
rbac-mapping | File | 180 B | 0644 |
|
rc.inet1 | File | 1.95 KB | 0644 |
|
redhat-linux-lib.pl | File | 32.85 KB | 0755 |
|
save_aifc.cgi | File | 5.78 KB | 0755 |
|
save_bifc.cgi | File | 10.12 KB | 0755 |
|
save_dns.cgi | File | 3.65 KB | 0755 |
|
save_host.cgi | File | 1.18 KB | 0755 |
|
save_ipnode.cgi | File | 1.26 KB | 0755 |
|
save_range.cgi | File | 1.42 KB | 0755 |
|
save_routes.cgi | File | 283 B | 0755 |
|
slackware-linux-9.1-ALL-lib.pl | File | 7.85 KB | 0755 |
|
slackware-linux-lib.pl | File | 6.71 KB | 0755 |
|
solaris-lib.pl | File | 20.79 KB | 0755 |
|
suse-linux-8.0-lib.pl | File | 7.31 KB | 0755 |
|
suse-linux-8.2-lib.pl | File | 7.31 KB | 0755 |
|
suse-linux-9.0-lib.pl | File | 8.74 KB | 0755 |
|
suse-linux-9.1-lib.pl | File | 8.74 KB | 0755 |
|
suse-linux-9.2-ALL-lib.pl | File | 11.23 KB | 0755 |
|
suse-linux-lib.pl | File | 9.08 KB | 0755 |
|
system_info.pl | File | 2.42 KB | 0644 |
|
trustix-linux-lib.pl | File | 32.85 KB | 0755 |
|
turbo-linux-lib.pl | File | 32.85 KB | 0755 |
|
united-linux-lib.pl | File | 7.31 KB | 0755 |
|
unixware-lib.pl | File | 9.9 KB | 0755 |
|
windows-lib.pl | File | 11.28 KB | 0755 |
|