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)