--- /etc/inc/services.inc.orig 2017-05-03 19:07:40.000000000 +0200 +++ /etc/inc/services.inc 2017-08-11 21:59:32.000000000 +0200 @@ -185,88 +185,115 @@ case "stateless_dhcp": $radvdconf .= "\tAdvManagedFlag off;\n"; $radvdconf .= "\tAdvOtherConfigFlag on;\n"; break; } - $radvdconf .= "\tprefix {$subnetv6}/{$ifcfgsnv6} {\n"; - if ($racarpif == true) { - $radvdconf .= "\t\tDeprecatePrefix off;\n"; - } else { - $radvdconf .= "\t\tDeprecatePrefix on;\n"; - } - switch ($dhcpv6ifconf['ramode']) { - case "managed": - $radvdconf .= "\t\tAdvOnLink on;\n"; - $radvdconf .= "\t\tAdvAutonomous off;\n"; - $radvdconf .= "\t\tAdvRouterAddr on;\n"; - break; - case "router": - $radvdconf .= "\t\tAdvOnLink off;\n"; - $radvdconf .= "\t\tAdvAutonomous off;\n"; - $radvdconf .= "\t\tAdvRouterAddr on;\n"; - break; - case "stateless_dhcp": - case "assist": - $radvdconf .= "\t\tAdvOnLink on;\n"; - $radvdconf .= "\t\tAdvAutonomous on;\n"; - $radvdconf .= "\t\tAdvRouterAddr on;\n"; - break; - case "unmanaged": - $radvdconf .= "\t\tAdvOnLink on;\n"; - $radvdconf .= "\t\tAdvAutonomous on;\n"; - $radvdconf .= "\t\tAdvRouterAddr on;\n"; - break; - } - - if (is_numericint($dhcpv6ifconf['ravalidlifetime'])) { - $radvdconf .= "\t\tAdvValidLifetime {$dhcpv6ifconf['ravalidlifetime']};\n"; - } else { - $radvdconf .= "\t\tAdvValidLifetime 86400;\n"; - } - - if (is_numericint($dhcpv6ifconf['rapreferredlifetime'])) { - $radvdconf .= "\t\tAdvPreferredLifetime {$dhcpv6ifconf['rapreferredlifetime']};\n"; - } else { - $radvdconf .= "\t\tAdvPreferredLifetime 14400;\n"; - } - - $radvdconf .= "\t};\n"; - + /* If there are subnets defined, do not generate prefix for interface subnet, but use the user-specified subnets instead */ if (is_array($dhcpv6ifconf['subnets']['item'])) { - foreach ($dhcpv6ifconf['subnets']['item'] as $subnet) { - if (is_subnetv6($subnet)) { - $radvdconf .= "\tprefix {$subnet} {\n"; + foreach ($dhcpv6ifconf['subnets']['item'] as $dhcpv6subnet) { + $radvdconf .= "\tprefix {$dhcpv6subnet} {\n"; + if ($racarpif == true) { + $radvdconf .= "\t\tDeprecatePrefix off;\n"; + } else { $radvdconf .= "\t\tDeprecatePrefix on;\n"; - switch ($dhcpv6ifconf['ramode']) { - case "managed": - $radvdconf .= "\t\tAdvOnLink on;\n"; - $radvdconf .= "\t\tAdvAutonomous off;\n"; - $radvdconf .= "\t\tAdvRouterAddr on;\n"; - break; - case "router": - $radvdconf .= "\t\tAdvOnLink off;\n"; - $radvdconf .= "\t\tAdvAutonomous off;\n"; - $radvdconf .= "\t\tAdvRouterAddr on;\n"; - break; - case "assist": - $radvdconf .= "\t\tAdvOnLink on;\n"; - $radvdconf .= "\t\tAdvAutonomous on;\n"; - $radvdconf .= "\t\tAdvRouterAddr on;\n"; - break; - case "unmanaged": - $radvdconf .= "\t\tAdvOnLink on;\n"; - $radvdconf .= "\t\tAdvAutonomous on;\n"; - $radvdconf .= "\t\tAdvRouterAddr on;\n"; - break; - } - $radvdconf .= "\t};\n"; } + switch($dhcpv6ifconf['ramode']) { + case "managed": + $radvdconf .= "\t\tAdvOnLink on;\n"; + $radvdconf .= "\t\tAdvAutonomous off;\n"; + $radvdconf .= "\t\tAdvRouterAddr on;\n"; + break; + case "router": + $radvdconf .= "\t\tAdvOnLink off;\n"; + $radvdconf .= "\t\tAdvAutonomous off;\n"; + $radvdconf .= "\t\tAdvRouterAddr on;\n"; + break; + case "stateless_dhcp": + case "assist": + $radvdconf .= "\t\tAdvOnLink on;\n"; + $radvdconf .= "\t\tAdvAutonomous on;\n"; + $radvdconf .= "\t\tAdvRouterAddr on;\n"; + break; + case "unmanaged": + $radvdconf .= "\t\tAdvOnLink on;\n"; + $radvdconf .= "\t\tAdvAutonomous on;\n"; + $radvdconf .= "\t\tAdvRouterAddr on;\n"; + break; + + } + if (is_numericint($dhcpv6ifconf['ravalidlifetime'])) { + $radvdconf .= "\t\tAdvValidLifetime {$dhcpv6ifconf['ravalidlifetime']};\n"; + } else { + $radvdconf .= "\t\tAdvValidLifetime 14400;\n"; + } + if (is_numericint($dhcpv6ifconf['rapreferredlifetime'])) { + $radvdconf .= "\t\tAdvPreferredLifetime {$dhcpv6ifconf['rapreferredlifetime']};\n"; + } else { + $radvdconf .= "\t\tAdvPreferredLifetime 14400;\n"; + } + $radvdconf .= "\t};\n"; } } - $radvdconf .= "\troute ::/0 {\n"; - $radvdconf .= "\t\tRemoveRoute on;\n"; - $radvdconf .= "\t};\n"; + + /* There are no user-specified subnets, so generate prefix for the interface subnet only */ + else { + $radvdconf .= "\tprefix {$subnetv6}/{$ifcfgsnv6} {\n"; + if ($racarpif == true) { + $radvdconf .= "\t\tDeprecatePrefix off;\n"; + } else { + $radvdconf .= "\t\tDeprecatePrefix on;\n"; + } + switch ($dhcpv6ifconf['ramode']) { + case "managed": + $radvdconf .= "\t\tAdvOnLink on;\n"; + $radvdconf .= "\t\tAdvAutonomous off;\n"; + $radvdconf .= "\t\tAdvRouterAddr on;\n"; + break; + case "router": + $radvdconf .= "\t\tAdvOnLink off;\n"; + $radvdconf .= "\t\tAdvAutonomous off;\n"; + $radvdconf .= "\t\tAdvRouterAddr on;\n"; + break; + case "stateless_dhcp": + case "assist": + $radvdconf .= "\t\tAdvOnLink on;\n"; + $radvdconf .= "\t\tAdvAutonomous on;\n"; + $radvdconf .= "\t\tAdvRouterAddr on;\n"; + break; + case "unmanaged": + $radvdconf .= "\t\tAdvOnLink on;\n"; + $radvdconf .= "\t\tAdvAutonomous on;\n"; + $radvdconf .= "\t\tAdvRouterAddr on;\n"; + break; + } + if (is_numericint($dhcpv6ifconf['ravalidlifetime'])) { + $radvdconf .= "\t\tAdvValidLifetime {$dhcpv6ifconf['ravalidlifetime']};\n"; + } else { + $radvdconf .= "\t\tAdvValidLifetime 86400;\n"; + } + if (is_numericint($dhcpv6ifconf['rapreferredlifetime'])) { + $radvdconf .= "\t\tAdvPreferredLifetime {$dhcpv6ifconf['rapreferredlifetime']};\n"; + } else { + $radvdconf .= "\t\tAdvPreferredLifetime 14400;\n"; + } + $radvdconf .= "\t};\n"; + } + /* If there are routes defined, do not generate a default route, but use the user-specified routes instead */ + if (is_array($dhcpv6ifconf['routes']['item'])) { + foreach ($dhcpv6ifconf['routes']['item'] as $dhcpv6route) { + $radvdconf .= "\troute " . $dhcpv6route['destination'] . " {\n"; + $radvdconf .= "\t\tRemoveRoute on;\n"; + $radvdconf .= "\t\tAdvRoutePreference " . $dhcpv6route['priority'] . ";\n"; + $radvdconf .= "\t};\n"; + } + } + /* There are no user-specified routes, so generate a default route entry */ + else { + $radvdconf .= "\troute ::/0 {\n"; + $radvdconf .= "\t\tRemoveRoute on;\n"; + $radvdconf .= "\t};\n"; + } /* add DNS servers */ $dnslist = array(); if (isset($dhcpv6ifconf['rasamednsasdhcp6']) && is_array($dhcpv6ifconf['dnsserver']) && !empty($dhcpv6ifconf['dnsserver'])) { foreach ($dhcpv6ifconf['dnsserver'] as $server) { --- /usr/local/www/services_router_advertisements.php.orig 2017-05-03 19:07:40.000000000 +0200 +++ /usr/local/www/services_router_advertisements.php 2017-08-11 22:39:59.000000000 +0200 @@ -128,14 +128,18 @@ $pconfig['radomainsearchlist'] = $config['dhcpdv6'][$if]['radomainsearchlist']; list($pconfig['radns1'], $pconfig['radns2'], $pconfig['radns3']) = $config['dhcpdv6'][$if]['radnsserver']; $pconfig['rasamednsasdhcp6'] = isset($config['dhcpdv6'][$if]['rasamednsasdhcp6']); $pconfig['subnets'] = $config['dhcpdv6'][$if]['subnets']['item']; + $pconfig['routes'] = $config['dhcpdv6'][$if]['routes']['item']; } if (!is_array($pconfig['subnets'])) { $pconfig['subnets'] = array(); } +if (!is_array($pconfig['routes'])) { + $pconfig['routes'] = array(); +} $advertise_modes = array( "disabled" => gettext("Disabled"), "router" => gettext("Router Only - RA Flags [none], Prefix Flags [router]"), "unmanaged" => gettext("Unmanaged - RA Flags [none], Prefix Flags [onlink, auto, router]"), @@ -151,10 +155,15 @@ gettext("Subnets are specified in CIDR format. " . "Select the CIDR mask that pertains to each entry. " . "/128 specifies a single IPv6 host; /64 specifies a normal IPv6 network; etc. " . "If no subnets are specified here, the Router Advertisement (RA) Daemon will advertise to the subnet to which the router's interface is assigned.") . ''; +$routes_help = '' . + gettext("Routes are specified in CIDR format. " . + "Enter subnets to which routes should be advertised, and their priority. " . + "If you need a default route, specify it with ::/0 here. " . + "If no routes are specified here, the Router Advertisement (RA) Daemon will advertise only the default route."); // THe use of
here causes the text to be hidden until the user clicks the "info" icon $ramode_help = gettext('Select the Operating Mode for the Router Advertisement (RA) Daemon.') . '
' . '
' . @@ -194,10 +203,33 @@ if (!is_ipaddrv6($address)) { $input_errors[] = sprintf(gettext("An invalid subnet or alias was specified. [%s/%s]"), $address, $bits); } } } + $pconfig['routes'] = array(); + for ($x = 0; $x < 5000; $x += 1) { + $address = trim($_POST['route_address' . $x]); + if ($address === "") { + continue; + } + $bits = trim($_POST['route_bits' . $x]); + if ($bits === "") { + $bits = "128"; + } + $priority = trim($_POST['route_priority' . $x]); + if ($priority === "0") { + $priority = "medium"; + } + if (is_alias($address)) { + $pconfig['routes'][] = array('destination' => $address); + } else { + $pconfig['routes'][] = array('destination' => $address . "/" . $bits, 'priority' => $priority); + if (!is_ipaddrv6($address)) { + $input_errors[] = sprintf(gettext("An invalid route was specified. [%s/%s]"), $address, $bits); + } + } + } if (($_POST['radns1'] && !is_ipaddrv6($_POST['radns1'])) || ($_POST['radns2'] && !is_ipaddrv6($_POST['radns2'])) || ($_POST['radns3'] && !is_ipaddrv6($_POST['radns3']))) { $input_errors[] = gettext("A valid IPv6 address must be specified for each of the DNS servers."); } if ($_POST['radomainsearchlist']) { @@ -271,10 +303,15 @@ if (count($pconfig['subnets'])) { $config['dhcpdv6'][$if]['subnets']['item'] = $pconfig['subnets']; } else { unset($config['dhcpdv6'][$if]['subnets']); } + if (count($pconfig['routes'])) { + $config['dhcpdv6'][$if]['routes']['item'] = $pconfig['routes']; + } else { + unset($config['dhcpdv6'][$if]['routes']); + } write_config(); $retval = services_radvd_configure(); $savemsg = get_std_save_message($retval); } @@ -464,10 +501,59 @@ 'addrow', 'Add', null, 'fa-plus' ))->addClass('btn-success'); +/*-----------------------------------------------------------------------------*/ +$section->addInput(new Form_StaticText( + 'Routes', + $routes_help +)); + +if (empty($pconfig['routes'])) { + $pconfig['routes'] = array('0' => '/128'); +} + +$route_counter = 0; +$numrows = count($pconfig['routes']) - 1; +$route_priority_modes = $priority_modes; +array_unshift($route_priority_modes, ''); +foreach ($pconfig['routes'] as $route) { + $route_address_name = "route_address" . $route_counter; + $route_bits_name = "route_bits" . $route_counter; + $route_priority_name = "route_priority" . $route_counter; + list($address, $mask) = explode("/", $route['destination']); + $priority = $route['priority']; + $group = new Form_Group($route_counter == 0 ? 'Routes':''); + $group->add(new Form_IpAddress( + $route_address_name, + null, + $address + ))->addMask($route_bits_name, $mask, 128, 0); + $group->add(new Form_Select( + $route_priority_name, + null, + $priority, + $route_priority_modes + )); + $group->add(new Form_Button( + 'deleterow_routes' . $route_counter, + 'Delete', + null, + 'fa-trash' + ))->removeClass('btn-primary')->addClass('btn-warning'); + $group->addClass('repeatable_routes'); + $section->add($group); + $route_counter++; +} +$section->addInput(new Form_Button( + 'addrow_routes', + 'Add', + null, + 'fa-plus' +))->addClass('btn-success'); +/*-----------------------------------------------------------------------------*/ $form->add($section); $section = new Form_Section('DNS Configuration'); @@ -508,11 +594,11 @@