diff --git a/net/lang/en b/net/lang/en index f656a3dae..1441b8da3 100644 --- a/net/lang/en +++ b/net/lang/en @@ -122,6 +122,7 @@ routes_gateway6=IPv6 gateway routes_forward=Act as router? routes_routed=Start route discovery daemon? routes_edefault='$1' is not a valid default router +routes_edefault6='$1' is not a valid IPv6 default router routes_edevice='$1' is not a valid device routes_device2=Default route device routes_static=Static routes @@ -134,6 +135,7 @@ routes_emask='$1' is not a valid netmask routes_egateway='$1' is not a valid gateway routes_egateway6='$1' is not a valid IPv6 gateway routes_defaults=Default routers +routes_defaults6=Default IPv6 routers routes_possible=If possible routes_local=Local routes routes_err=Failed to save routing diff --git a/net/list_ifcs.cgi b/net/list_ifcs.cgi index f96ea6774..e6e97fa3f 100755 --- a/net/list_ifcs.cgi +++ b/net/list_ifcs.cgi @@ -34,6 +34,7 @@ if (!$access{'bootonly'}) { push(@tds, "width=20% valign=top", "width=20% valign=top", "width=20% valign=top", "width=20% valign=top"); push(@tds, "width=20% valign=top") if (&supports_address6()); + push(@tds, "width=5% valign=top"); if ($allow_add) { push(@links, "$text{'ifcs_add'}"); @@ -124,9 +125,9 @@ if ($allow_add && defined(&supports_ranges) && &supports_ranges()) { } print &ui_links_row(\@links); @tds = ( "width=5 valign=top", "width=20% valign=top", "width=20% valign=top", - "width=20% valign=top", "width=20% valign=top", - "width=20% valign=top"); -push(@tds, "width=20% valign=top") if (&supports_address6()); + "width=20% valign=top", "width=20% valign=top" ); +push(@tds, "width=20% valign=top xxx") if (&supports_address6()); +push(@tds, "width=5% valign=top"); print &ui_columns_start([ "", $text{'ifcs_name'}, $text{'ifcs_type'}, diff --git a/net/solaris-lib.pl b/net/solaris-lib.pl index eebea9a85..1c9edb934 100755 --- a/net/solaris-lib.pl +++ b/net/solaris-lib.pl @@ -87,23 +87,37 @@ local $out = &backquote_logged("$cmd 2>&1"); if ($?) { &error("$cmd : $out"); } if ($_[0]->{'virtual'} eq '') { - # Remove existing IPv6 addresses, except for the first one + # Remove existing IPv6 addresses, except for ones we want to keep + my %need6 = map { $_, 1 } @{$_[0]->{'address6'}}; if ($already) { - for(my $i=1; $i<@{$already->{'address6'}}; $i++) { - local $cmd = "ifconfig $_[0]->{'name'} inet6 removeif ". - $already->{'address6'}->[$i]; - local $out = &backquote_logged("$cmd 2>&1"); - if ($?) { &error("$cmd : $out"); } + if (@{$already->{'address6'}}) { + # Never remove first IPv6 address, which is dynamic + $need6{$already->{'address6'}->[0]} = 1; + } + foreach my $a (@{$already->{'address6'}}) { + if (!$need6{$a}) { + # Not needed, can remove + local $cmd = "ifconfig $_[0]->{'name'} inet6 ". + "removeif ".$a; + local $out = &backquote_logged("$cmd 2>&1"); + if ($?) { &error("$cmd : $out"); } + } + else { + # Don't need to add this one later + $need6{$a} = 0; + } } } # Add all new addresses - for(my $i=($already ? 1 : 0); $i<@{$_[0]->{'address6'}}; $i++) { - local $cmd = "ifconfig $_[0]->{'name'} inet6 addif ". - $_[0]->{'address6'}->[$i]."/". - $_[0]->{'netmask6'}->[$i]; - local $out = &backquote_logged("$cmd 2>&1"); - if ($?) { &error("$cmd : $out"); } + for(my $i=0; $i<@{$_[0]->{'address6'}}; $i++) { + if ($need6{$_[0]->{'address6'}->[$i]}) { + local $cmd = "ifconfig $_[0]->{'name'} inet6 addif ". + $_[0]->{'address6'}->[$i]."/". + $_[0]->{'netmask6'}->[$i]." up"; + local $out = &backquote_logged("$cmd 2>&1"); + if ($?) { &error("$cmd : $out"); } + } } # XXX routes too } @@ -453,7 +467,8 @@ else { sub routing_config_files { -return ( "/etc/defaultrouter", "/etc/notrouter", "/etc/gateways" ); +return ( "/etc/defaultrouter", "/etc/defaultrouter6", + "/etc/notrouter", "/etc/gateways" ); } sub network_config_files @@ -475,14 +490,33 @@ close(DEFRT); return @defrt; } +# get_ipv6_defaultrouters() +# Returns a list of all IPv6 default routers +sub get_ipv6_defaultrouters +{ +local @defrt; +&open_readfile(DEFRT, "/etc/defaultrouter6"); +while() { + s/#.*$//g; + if (/(\S+)/) { push(@defrt, $1); } + } +close(DEFRT); +return @defrt; +} + sub routing_input { -# show default router(s) input +# Show default IPv4 router(s) input local @defrt = &get_defaultrouters(); print &ui_table_row($text{'routes_defaults'}, &ui_textarea("defrt", join("\n", @defrt), 3, 40)); -# show router input +# Show default IPv6 router(s) input +local @defrt6 = &get_ipv6_defaultrouters(); +print &ui_table_row($text{'routes_defaults6'}, + &ui_textarea("defrt6", join("\n", @defrt6), 3, 40)); + +# Show router input local $notrt = (-r "/etc/notrouter"); local $gatew = (-r "/etc/gateways"); print &ui_table_row($text{'routes_forward'}, @@ -495,6 +529,7 @@ print &ui_table_row($text{'routes_forward'}, sub parse_routing { +# Save IPv4 default routers local @defrt = split(/\s+/, $in{'defrt'}); foreach my $d (@defrt) { &to_ipaddress($d) || &error(&text('routes_edefault', $d)); @@ -510,6 +545,23 @@ else { } &unlock_file("/etc/defaultrouter"); +# Save IPv6 default routers +local @defrt6 = split(/\s+/, $in{'defrt6'}); +foreach my $d (@defrt6) { + &to_ip6address($d) || &error(&text('routes_edefault6', $d)); + } +&lock_file("/etc/defaultrouter6"); +if (@defrt6) { + &open_tempfile(DEFRT, ">/etc/defaultrouter6"); + foreach $d (@defrt6) { &print_tempfile(DEFRT, $d,"\n"); } + &close_tempfile(DEFRT); + } +else { + &unlink_file("/etc/defaultrouter6"); + } +&unlock_file("/etc/defaultrouter6"); + +# Save router enabled flag &lock_file("/etc/gateways"); &lock_file("/etc/notrouter"); if ($in{'router'} == 0) { @@ -572,6 +624,32 @@ else { &unlock_file("/etc/defaultrouter"); } +# get_default_ipv6_gateway() +# Returns the default gateway IPv6 address (if one is set) boot time +# settings. +sub get_default_ipv6_gateway +{ +local @defrt = &get_ipv6_defaultrouters(); +return @defrt ? ( $defrt[0] ) : ( ); +} + +# set_default_ipv6_gateway(gateway, device) +# Sets the default gateway to the given IP accessible via the given device, +# in the boot time settings. +sub set_default_ipv6_gateway +{ +&lock_file("/etc/defaultrouter6"); +if ($_[0]) { + &open_tempfile(DEF, ">/etc/defaultrouter6"); + &print_tempfile(DEF, $_[0],"\n"); + &close_tempfile(DEF); + } +else { + &unlink_file("/etc/defaultrouter6"); + } +&unlock_file("/etc/defaultrouter6"); +} + # list_routes() # Returns a list of active routes sub list_routes @@ -580,7 +658,7 @@ local @rv; &open_execute_command(ROUTES, "netstat -rn", 1, 1); while() { s/\s+$//; - if (/^([0-9\.]+|default)\s+([0-9\.]+)\s+\S+\s+\S+\s+\S+(\s+(\S+))?$/) { + if (/^([0-9a-f:\.\/]+|default)\s+([0-9a-f:\.]+)\s+\S+\s+\S+\s+\S+(\s+(\S+))?$/) { local $r = { 'dest' => $1 eq "default" ? "0.0.0.0" : $1, 'gateway' => $2, 'iface' => $4 }; @@ -589,6 +667,9 @@ while() { $r->{'dest'} =~ /\.0\.0$/ ? "255.255.0.0" : $r->{'dest'} =~ /\.0$/ ? "255.255.255.0" : undef; + if ($r->{'dest'} =~ s/\/(\d+)$//) { + $r->{'netmask'} = $1; + } push(@rv, $r); } } @@ -603,11 +684,19 @@ sub delete_route { local ($route) = @_; local $cmd = "route delete"; +local $inet6 = &check_ip6address($route->{'dest'}) || + &check_ip6address($route->{'gateway'}); +if ($inet6) { + $cmd .= " -inet6"; + } if (!$route->{'dest'} || $route->{'dest'} eq '0.0.0.0') { $cmd .= " default"; } else { $cmd .= " $route->{'dest'}"; + if ($route->{'netmask'} && $inet6) { + $cmd .= "/$route->{'netmask'}"; + } } if ($route->{'gateway'}) { $cmd .= " $route->{'gateway'}"; @@ -619,7 +708,7 @@ elsif ($route->{'iface'}) { $cmd .= " $aiface->{'address'}"; } } -if ($route->{'netmask'}) { +if ($route->{'netmask'} && !$inet6) { $cmd .= " $route->{'netmask'}"; } local $out = &backquote_logged("$cmd 2>&1 {'dest'}) || + &check_ip6address($route->{'gateway'}); local $cmd = "route add "; +if ($inet6) { + $cmd .= " -inet6"; + } if (!$route->{'dest'}) { $cmd .= " default"; } else { $cmd .= " $route->{'dest'}"; + if ($route->{'netmask'} && $inet6) { + $cmd .= "/$route->{'netmask'}"; + } } if ($route->{'gateway'}) { $cmd .= " $route->{'gateway'}"; @@ -648,7 +745,7 @@ elsif ($route->{'iface'}) { $cmd .= " $aiface->{'address'}"; } } -if ($route->{'netmask'}) { +if ($route->{'netmask'} && !$inet6) { $cmd .= " $route->{'netmask'}"; } local $out = &backquote_logged("$cmd 2>&1 {'name'} eq 'lo0'); &apply_interface($b); $done{$b->{'fullname'}}++; } foreach $a (&active_interfaces()) { + next if ($a->{'name'} eq 'lo0'); if (!$done{$a->{'fullname'}} && !$a->{'zone'}) { &deactive_interface($a); } } + +# Apply default IPv4 router local @infile = &get_defaultrouters(); local @routes = &list_routes(); local @inmem = map { $_->{'gateway'} } - grep { $_->{'dest'} eq "0.0.0.0" } @routes; + grep { $_->{'dest'} eq "0.0.0.0" && + !&check_ip6address($_->{'gateway'}) } @routes; if (join(" ", @infile) ne join(" ", @inmem)) { # Fix up default routes local $r; @@ -684,6 +788,23 @@ if (join(" ", @infile) ne join(" ", @inmem)) { &system_logged("route add default $r >/dev/null 2>&1"); } } + +# Apply default IPv6 router +local @infile = &get_ipv6_defaultrouters(); +local @routes = &list_routes(); +local @inmem = map { $_->{'gateway'} } + grep { $_->{'dest'} eq "0.0.0.0" && + &check_ip6address($_->{'gateway'}) } @routes; +if (join(" ", @infile) ne join(" ", @inmem)) { + # Fix up default routes + local $r; + foreach $r (@inmem) { + &system_logged("route delete -inet6 default $r >/dev/null 2>&1"); + } + foreach $r (@infile) { + &system_logged("route add -inet6 default $r >/dev/null 2>&1"); + } + } } # apply_interface(&iface)