diff --git a/net/nm-lib.pl b/net/nm-lib.pl index b12c2caa5..bbae38f6c 100644 --- a/net/nm-lib.pl +++ b/net/nm-lib.pl @@ -1,6 +1,6 @@ # Networking functions for Network Manager -# XXX apply one interface? -# XXX static routes +# XXX apply new interface +# XXX UUID has to match $nm_conn_dir = "/etc/NetworkManager/system-connections"; $sysctl_config = "/etc/sysctl.conf"; @@ -85,7 +85,11 @@ foreach my $f (glob("$nm_conn_dir/*.nmconnection")) { $iface->{'mtu'} = &find_nm_config($cfg, "ethernet", "mtu"); # Static routes - $iface->{'routes'} = [ &find_nm_config($cfg, "ipv4", "routes") ]; + my @routes; + for(my $i=1; defined($r = &find_nm_config($cfg, "ipv4", "route$i")); $i++) { + push(@routes, $r); + } + $iface->{'routes'} = \@routes if (@routes); push(@rv, $iface); push(@rv, @virts); @@ -123,8 +127,21 @@ else { } else { # Need to create a new empty config - my $uuid = &read_file_contents("/proc/sys/kernel/random/uuid"); - $uuid =~ s/\r|\n//g; + my $uuid; + my $out = &backquote_command("nmcli conn show"); + foreach my $l (split(/\r?\n/, $out)) { + my @w = split(/\s+/, $l); + if ($w[@w-1] eq $iface->{'name'}) { + $uuid = $w[@w-3]; + last; + } + } + if (!$uuid) { + # Make one up! + $uuid = &read_file_contents( + "/proc/sys/kernel/random/uuid"); + $uuid =~ s/\r|\n//g; + } $cfg = [ { 'sect' => 'connection', 'members' => [ { 'name' => 'id', @@ -135,8 +152,27 @@ else { 'value' => 'ethernet' }, { 'name' => 'interface-name', 'value' => $iface->{'name'} }, + { 'name' => 'autoconnect-priority', + 'value' => '-999' }, + { 'name' => 'timestamp', + 'value' => time() }, ], }, + { 'sect' => 'ethernet', + 'members' => [ ], + }, + { 'sect' => 'ipv4', + 'members' => [ ], + }, + { 'sect' => 'ipv6', + 'members' => [ + { 'name' => 'addr-gen-mode', + 'value' => 'default' }, + ], + }, + { 'sect' => 'ethernet', + 'members' => [ ], + }, ]; $f = $nm_conn_dir."/".$iface->{'name'}.".nmconnection"; &lock_file($f); @@ -163,7 +199,7 @@ else { $maxv6 = $i+1; &save_nm_config($cfg, "ipv6", "address".($i+1), $v); } - for(my $i=$maxv6+1; &find_nm_config($cfg, "ipv6", $i); $i++) { + for(my $i=$maxv6+1; &find_nm_config($cfg, "ipv6", "address".$i); $i++) { &save_nm_config($cfg, "ipv6", "address".$i, undef); } &save_nm_config($cfg, "ipv6", "method", @@ -184,6 +220,17 @@ else { # Update MTU &save_nm_config($cfg, "ethernet", "mtu", $iface->{'mtu'}); + + # Update static routes + my $maxrt = 0; + for(my $i=0; $i<@{$iface->{'routes'}}; $i++) { + $maxrt = $i+1; + &save_nm_config($cfg, "ipv4", "route".($i+1), + $iface->{'routes'}->[$i]); + } + for(my $i=$maxrt+1; &find_nm_config($cfg, "ipv4", "route".$i); $i++) { + &save_nm_config($cfg, "ipv6", "route".$i, undef); + } } &flush_file_lines($f); &unlock_file($f); @@ -316,7 +363,7 @@ my $i = 0; @inames = ( "", @inames ); foreach my $b (@ifaces) { foreach my $v (@{$b->{'routes'}}) { - my ($net, $gw) = split(/\s+/, $v); + my ($net, $gw) = split(/,/, $v); my $cidr; ($net, $cidr) = split(/\//, $net); my $mask = &prefix_to_mask($cidr); @@ -372,32 +419,30 @@ $sysctl{'net.ipv4.ip_forward'} = $in{'forward'}; &unlock_file($sysctl_config); # Save static routes -# XXX -#my @boot = &boot_interfaces(); -#foreach my $b (grep { $_->{'virtual'} eq '' } @boot) { -# my @r; -# for(my $i=0; defined($in{"dev_$i"}); $i++) { -# if ($in{"dev_$i"} eq $b->{'fullname'}) { -# &check_ipaddress($in{"net_$i"}) || -# &error(&text('routes_enet', $in{"net_$i"})); -# &check_ipaddress($in{"mask_$i"}) || -# &error(&text('routes_emask', $in{"mask_$i"})); -# my $to = $in{"net_$i"}."/". -# &mask_to_prefix($in{"mask_$i"}); -# &check_ipaddress($in{"gw_$i"}) || -# &error(&text('routes_egateway', $in{"gw_$i"})); -# push(@r, { 'to' => $to, 'via' => $in{"gw_$i"} }); -# } -# } -# if (@r) { -# $b->{'routes'} = { 'name' => 'routes', -# 'value' => \@r }; -# } -# else { -# delete($b->{'routes'}); -# } -# &save_interface($b, \@boot); -# } +my @boot = &boot_interfaces(); +foreach my $b (grep { $_->{'virtual'} eq '' } @boot) { + my @r; + for(my $i=0; defined($in{"dev_$i"}); $i++) { + if ($in{"dev_$i"} eq $b->{'fullname'}) { + &check_ipaddress($in{"net_$i"}) || + &error(&text('routes_enet', $in{"net_$i"})); + &check_ipaddress($in{"mask_$i"}) || + &error(&text('routes_emask', $in{"mask_$i"})); + my $to = $in{"net_$i"}."/". + &mask_to_prefix($in{"mask_$i"}); + &check_ipaddress($in{"gw_$i"}) || + &error(&text('routes_egateway', $in{"gw_$i"})); + push(@r, $to.",".$in{"gw_$i"}); + } + } + if (@r) { + $b->{'routes'} = \@r; + } + else { + delete($b->{'routes'}); + } + &save_interface($b, \@boot); + } } sub supports_address6 @@ -567,6 +612,7 @@ my $lnum = 0; &open_lock_tempfile(NW, ">$file"); foreach my $sect (@$cfg) { $sect->{'line'} = $lnum; + $sect->{'eline'} = $lnum; $sect->{'file'} = $file; &print_tempfile(NW, "[$sect->{'sect'}]\n"); $lnum++; @@ -619,31 +665,34 @@ if (!$sect) { } # Find the directive -my ($dir) = grep { $_->{'name'} eq $name } @{$sect->{'members'}}; -if ($dir && defined($value)) { - # Update existing line - $dir->{'value'} = $value; - $lref->[$dir->{'line'}] = $name."=".$value; - } -elsif ($dir && !defined($value)) { - # Remove existing line - $sect->{'members'} = [ grep { $_ ne $dir } @{$sect->{'members'}} ]; - splice(@$lref, $dir->{'line'}, 1); - &renumber_nm_config($cfg, $dir->{'line'}, -1); - } -elsif (!$dir && defined($value)) { - # Add a new line - $dir = { 'name' => $name, - 'value' => $value, - 'file' => $file, - 'line' => $sect->{'eline'}+1, - 'eline' => $sect->{'eline'}+1 }; - splice(@$lref, $sect->{'eline'}+1, 0, $name."=".$value); - &renumber_nm_config($cfg, $sect->{'eline'}, 1); - push(@{$sect->{'members'}}, $dir); - } -elsif (!$dir && !defined($value)) { - # No value, and it's not current set either .. so nothing to do! +my @dirs = grep { $_->{'name'} eq $name } @{$sect->{'members'}}; +my @values = ref($value) ? @$value : + defined($value) ? ( $value ) : ( ); +for(my $i=0; $i<@dirs || $i<@values; $i++) { + my $dir = $i<@dirs ? $dirs[$i] : undef; + my $val = $i<@values ? $values[$i] : undef; + if ($dir && defined($val)) { + # Update existing line + $dir->{'value'} = $val; + $lref->[$dir->{'line'}] = $name."=".$val; + } + elsif ($dir && !defined($val)) { + # Remove existing line + $sect->{'members'} = [ grep { $_ ne $dir } @{$sect->{'members'}} ]; + splice(@$lref, $dir->{'line'}, 1); + &renumber_nm_config($cfg, $dir->{'line'}, -1); + } + elsif (!$dir && defined($val)) { + # Add a new line + $dir = { 'name' => $name, + 'value' => $val, + 'file' => $file, + 'line' => $sect->{'eline'}+1, + 'eline' => $sect->{'eline'}+1 }; + splice(@$lref, $sect->{'eline'}+1, 0, $name."=".$val); + &renumber_nm_config($cfg, $sect->{'eline'}, 1); + push(@{$sect->{'members'}}, $dir); + } } }