mirror of
https://github.com/webmin/webmin.git
synced 2026-01-16 15:06:07 +00:00
384 lines
8.5 KiB
Perl
Executable File
384 lines
8.5 KiB
Perl
Executable File
# Networking functions for Gentoo 2006+
|
|
|
|
do 'linux-lib.pl';
|
|
|
|
$gentoo_net_config = "/etc/conf.d/net";
|
|
$min_virtual_number = 1;
|
|
|
|
# parse_gentoo_net()
|
|
# Parses the Gentoo net config file into an array of named sections
|
|
sub parse_gentoo_net
|
|
{
|
|
my @rv;
|
|
my $sect;
|
|
my $lnum = 0;
|
|
open(CONF, "<".$gentoo_net_config);
|
|
while(<CONF>) {
|
|
s/\r|\n//g;
|
|
s/#.*$//;
|
|
if (/^\s*(\S+)\s*=\s*\((.*)/) {
|
|
# Start of some section, which may span several lines
|
|
$sect = { 'name' => $1,
|
|
'line' => $lnum };
|
|
push(@rv, $sect);
|
|
my $v = $2;
|
|
if ($v =~ /^(.*)\)/) {
|
|
# Ends on same line
|
|
$sect->{'values'} = [ &split_gentoo_values("$1") ];
|
|
$sect->{'eline'} = $lnum;
|
|
$sect = undef;
|
|
}
|
|
else {
|
|
# May span multiple
|
|
$sect->{'values'} = [ &split_gentoo_values($v) ];
|
|
}
|
|
}
|
|
elsif (/^\s*\)/ && $sect) {
|
|
# End of a section
|
|
$sect->{'eline'} = $lnum;
|
|
$sect = undef;
|
|
}
|
|
elsif (/^\s*(".*")\s*\)/ && $sect) {
|
|
# End of a section, but with some values before it
|
|
push(@{$sect->{'values'}}, &split_gentoo_values("$1"));
|
|
$sect->{'eline'} = $lnum;
|
|
$sect = undef;
|
|
}
|
|
elsif (/^\s*(".*")/ && $sect) {
|
|
# Values within a section
|
|
push(@{$sect->{'values'}}, &split_gentoo_values("$1"));
|
|
}
|
|
$lnum++;
|
|
}
|
|
close(CONF);
|
|
return @rv;
|
|
}
|
|
|
|
# save_gentoo_net(&old, &new)
|
|
# Update or create a Gentoo net config file section
|
|
sub save_gentoo_net
|
|
{
|
|
my ($old, $new) = @_;
|
|
my @lines;
|
|
if ($new) {
|
|
push(@lines, $new->{'name'}."=(");
|
|
foreach my $v (@{$new->{'values'}}) {
|
|
push(@lines," \"$v\"");
|
|
}
|
|
push(@lines, ")");
|
|
}
|
|
my $lref = &read_file_lines($gentoo_net_config);
|
|
if ($old && $new) {
|
|
# Replace section
|
|
splice(@$lref, $old->{'line'}, $old->{'eline'}-$old->{'line'}+1,
|
|
@lines);
|
|
$new->{'eline'} = $new->{'line'}+scalar(@lines)-1;
|
|
}
|
|
elsif ($old && !$new) {
|
|
# Delete section
|
|
splice(@$lref, $old->{'line'}, $old->{'eline'}-$old->{'line'}+1);
|
|
}
|
|
elsif (!$old && $new) {
|
|
# Add section
|
|
$new->{'line'} = scalar(@$lref);
|
|
$new->{'eline'} = $new->{'line'}+scalar(@lines)-1;
|
|
push(@$lref, @lines);
|
|
}
|
|
&flush_file_lines($gentoo_net_config);
|
|
}
|
|
|
|
# split_gentoo_values(string)
|
|
# Splits a string like "foo bar" "smeg spod" into an array
|
|
sub split_gentoo_values
|
|
{
|
|
my ($str) = @_;
|
|
my @rv;
|
|
while($str =~ /^\s*"([^"]+)",?(.*)/) {
|
|
push(@rv, $1);
|
|
$str = $2;
|
|
}
|
|
return @rv;
|
|
}
|
|
|
|
# boot_interfaces()
|
|
# Returns a list of interfaces brought up at boot time
|
|
sub boot_interfaces
|
|
{
|
|
my @rv;
|
|
foreach my $g (&parse_gentoo_net()) {
|
|
if ($g->{'name'} =~ /^config_(\S+)/) {
|
|
my $gn = $1;
|
|
my $n = 0;
|
|
foreach my $v (@{$g->{'values'}}) {
|
|
# An interface definition
|
|
my $iface = { 'name' => $gn,
|
|
'up' => 1,
|
|
'edit' => 1,
|
|
'index' => scalar(@rv) };
|
|
if ($n == 0) {
|
|
$iface->{'fullname'} = $gn;
|
|
}
|
|
else {
|
|
$iface->{'fullname'} = $gn.":".$n;
|
|
$iface->{'virtual'} = $n;
|
|
}
|
|
my @w = split(/\s+/, $v);
|
|
if ($w[0] eq "dhcp") {
|
|
$iface->{'dhcp'} = 1;
|
|
}
|
|
elsif ($w[0] eq "noop") {
|
|
# Skipped, but still uses a up a number
|
|
$n++;
|
|
next;
|
|
}
|
|
if (&check_ipaddress($w[0])) {
|
|
$iface->{'address'} = $w[0];
|
|
}
|
|
elsif ($w[0] =~ /^([0-9\.]+)\/(\d+)$/) {
|
|
$iface->{'address'} = $1;
|
|
$iface->{'netmask'} = &prefix_to_mask($2);
|
|
}
|
|
for($i=1; $i<@w; $i++) {
|
|
if ($w[$i] eq "netmask") {
|
|
$iface->{'netmask'} = $w[++$i];
|
|
}
|
|
elsif ($w[$i] eq "broadcast") {
|
|
$iface->{'broadcast'} = $w[++$i];
|
|
}
|
|
elsif ($w[$i] eq "mtu") {
|
|
$iface->{'mtu'} = $w[++$i];
|
|
}
|
|
}
|
|
if ($iface->{'address'} && $iface->{'netmask'}) {
|
|
$iface->{'broadcast'} ||= &compute_broadcast(
|
|
$iface->{'address'}, $iface->{'netmask'});
|
|
}
|
|
$iface->{'gentoo'} = $g;
|
|
push(@rv, $iface);
|
|
$n++;
|
|
}
|
|
}
|
|
elsif ($g->{'name'} =~ /^routes_(\S+)/) {
|
|
# A route definition for an interface
|
|
my ($iface) = grep { $_->{'fullname'} eq $1 } @rv;
|
|
my $spec = $g->{'values'}->[0];
|
|
if ($iface) {
|
|
if ($spec =~ /default\s+via\s+([0-9\.]+)/ ||
|
|
$spec =~ /default\s+([0-9\.]+)/) {
|
|
$iface->{'gateway'} = $1;
|
|
$iface->{'gentoogw'} = $g;
|
|
}
|
|
}
|
|
}
|
|
$lnum++;
|
|
}
|
|
return @rv;
|
|
}
|
|
|
|
# save_interface(&details)
|
|
# Create or update a boot-time interface
|
|
sub save_interface
|
|
{
|
|
my ($iface) = @_;
|
|
&lock_file($gentoo_net_config);
|
|
|
|
# Build the interface line
|
|
my @w;
|
|
if ($iface->{'dhcp'}) {
|
|
push(@w, "dhcp");
|
|
}
|
|
else {
|
|
push(@w, $iface->{'address'});
|
|
if ($iface->{'netmask'}) {
|
|
push(@w, "netmask", $iface->{'netmask'});
|
|
}
|
|
if ($iface->{'broadcast'}) {
|
|
push(@w, "broadcast", $iface->{'broadcast'});
|
|
}
|
|
if ($iface->{'mtu'}) {
|
|
push(@w, "mtu", $iface->{'mtu'});
|
|
}
|
|
}
|
|
|
|
# Find the current block for this interface
|
|
my @gentoo = &parse_gentoo_net();
|
|
my ($g) = grep { $_->{'name'} eq 'config_'.$iface->{'name'} } @gentoo;
|
|
if ($g) {
|
|
# Found it .. append or replace
|
|
while (!$g->{'values'}->[$iface->{'virtual'}]) {
|
|
push(@{$g->{'values'}}, "noop");
|
|
}
|
|
$g->{'values'}->[$iface->{'virtual'}] = join(" ", @w);
|
|
&save_gentoo_net($g, $g);
|
|
}
|
|
else {
|
|
# Needs a new block
|
|
$g = { 'name' => $iface->{'name'},
|
|
'values' => [ join(" ", @w) ] };
|
|
&save_gentoo_net(undef, $g);
|
|
}
|
|
&unlock_file($gentoo_net_config);
|
|
}
|
|
|
|
# delete_interface(&details)
|
|
# Delete a boot-time interface
|
|
sub delete_interface
|
|
{
|
|
my ($iface) = @_;
|
|
|
|
# Find the current block for this interface
|
|
&lock_file($gentoo_net_config);
|
|
my @gentoo = &parse_gentoo_net();
|
|
my ($g) = grep { $_->{'name'} eq 'config_'.$iface->{'name'} } @gentoo;
|
|
if ($g) {
|
|
# Found it .. take out the interface
|
|
if ($iface->{'virtual'} == scalar(@{$g->{'values'}})-1) {
|
|
# Last one
|
|
pop(@{$g->{'values'}});
|
|
}
|
|
else {
|
|
$g->{'values'}->[$iface->{'virtual'}] = 'noop';
|
|
}
|
|
&save_gentoo_net($g, $g);
|
|
}
|
|
&unlock_file($gentoo_net_config);
|
|
}
|
|
|
|
# can_edit(what)
|
|
# Can some boot-time interface parameter be edited?
|
|
sub can_edit
|
|
{
|
|
return $_[0] ne 'up' && $_[0] ne 'bootp';
|
|
}
|
|
|
|
sub can_broadcast_def
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
# valid_boot_address(address)
|
|
# Is some address valid for a bootup interface
|
|
sub valid_boot_address
|
|
{
|
|
return &check_ipaddress($_[0]);
|
|
}
|
|
|
|
# get_hostname()
|
|
sub get_hostname
|
|
{
|
|
my %host;
|
|
&read_env_file("/etc/conf.d/hostname", \%host);
|
|
if ($host{'HOSTNAME'}) {
|
|
return $host{'HOSTNAME'};
|
|
}
|
|
return &get_system_hostname();
|
|
}
|
|
|
|
# save_hostname(name)
|
|
sub save_hostname
|
|
{
|
|
my ($hostname) = @_;
|
|
my %host;
|
|
&read_env_file("/etc/conf.d/hostname", \%host);
|
|
$host{'HOSTNAME'} = $hostname;
|
|
&write_env_file("/etc/conf.d/hostname", \%host);
|
|
&system_logged("hostname ".quotemeta($hostname)." >/dev/null 2>&1");
|
|
}
|
|
|
|
# routing_input()
|
|
# Prints HTML for editing routing settings
|
|
sub routing_input
|
|
{
|
|
my ($gw, $dev) = &get_default_gateway();
|
|
my @ifaces = grep { $_->{'virtual'} eq '' } &boot_interfaces();
|
|
print &ui_table_row($text{'routes_def'},
|
|
&ui_radio("route_def", $gw ? 0 : 1,
|
|
[ [ 1, $text{'routes_nogw'}."<br>" ],
|
|
[ 0, &text('routes_ggw',
|
|
&ui_textbox("gw", $gw, 20),
|
|
&ui_select("dev", $dev,
|
|
[ map { $_->{'name'} } @ifaces ])) ] ]));
|
|
}
|
|
|
|
# parse_routing()
|
|
# Applies settings from routing_input form
|
|
sub parse_routing
|
|
{
|
|
if ($in{'route_def'}) {
|
|
&set_default_gateway();
|
|
}
|
|
else {
|
|
&check_ipaddress($in{'gw'}) ||
|
|
&error(&text('routes_edefault', &html_escape($in{'gw'})));
|
|
&set_default_gateway($in{'gw'}, $in{'dev'});
|
|
}
|
|
}
|
|
|
|
# apply_network()
|
|
# Apply the interface and routing settings
|
|
sub apply_network
|
|
{
|
|
opendir(DIR, "/etc/init.d");
|
|
foreach my $f (readdir(DIR)) {
|
|
if ($f =~ /^net.(\S+)/ && $1 ne "lo") {
|
|
&system_logged("cd / ; /etc/init.d/$f restart >/dev/null 2>&1 </dev/null");
|
|
}
|
|
}
|
|
closedir(DIR);
|
|
}
|
|
|
|
# get_default_gateway()
|
|
# Returns the default gateway IP (if one is set) and device (if set) boot time
|
|
# settings.
|
|
sub get_default_gateway
|
|
{
|
|
my @ifaces = &boot_interfaces();
|
|
my ($iface) = grep { $_->{'gateway'} } @ifaces;
|
|
if ($iface) {
|
|
return ( $iface->{'gateway'}, $iface->{'name'} );
|
|
}
|
|
else {
|
|
return ( );
|
|
}
|
|
}
|
|
|
|
# set_default_gateway(gateway, device)
|
|
# Sets the default gateway to the given IP accessible via the given device,
|
|
# in the boot time settings.
|
|
sub set_default_gateway
|
|
{
|
|
my ($gw, $dev) = @_;
|
|
&lock_file($gentoo_net_config);
|
|
my @ifaces = &boot_interfaces();
|
|
my ($iface) = grep { $_->{'gateway'} } @ifaces;
|
|
if ($iface && $gw) {
|
|
# Change existing default route
|
|
$g = $iface->{'gentoogw'};
|
|
$g->{'name'} = 'routes_'.$dev;
|
|
$g->{'values'}->[0] = "default via $gw";
|
|
&save_gentoo_net($g, $g);
|
|
}
|
|
elsif ($iface && !$gw) {
|
|
# Deleting existing default route
|
|
$g = $iface->{'gentoogw'};
|
|
&save_gentoo_net($g, undef);
|
|
}
|
|
elsif (!$iface && $gw) {
|
|
# Adding new default route
|
|
$g = { 'name' => 'routes_'.$dev,
|
|
'values' => [ "default via $gw" ] };
|
|
&save_gentoo_net(undef, $g);
|
|
}
|
|
&unlock_file($gentoo_net_config);
|
|
}
|
|
|
|
# supports_address6([&iface])
|
|
# Returns 1 if managing IPv6 interfaces is supported
|
|
sub supports_address6
|
|
{
|
|
my ($iface) = @_;
|
|
return 0;
|
|
}
|
|
|
|
|