From c7c629945e9993cb9d33d0f91fcca43de9bfde0e Mon Sep 17 00:00:00 2001 From: Franco Fichtner Date: Fri, 17 Sep 2021 12:18:37 +0200 Subject: [PATCH] dhcp: try to guide when subnets are too small; closes #4762 Lots of loosely related changes addressing small bugs and wrong assumptions of the available IP ranges. --- src/www/services_dhcp.php | 25 ++++----- src/www/services_dhcpv6.php | 102 ++++++++++++++++++++---------------- 2 files changed, 69 insertions(+), 58 deletions(-) diff --git a/src/www/services_dhcp.php b/src/www/services_dhcp.php index b82c48b64..0912e8f63 100644 --- a/src/www/services_dhcp.php +++ b/src/www/services_dhcp.php @@ -1,7 +1,7 @@ * All rights reserved. * @@ -453,6 +453,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { } } +$range_from = ip2long(long2ip32(ip2long($config['interfaces'][$if]['ipaddr']) & gen_subnet_mask_long($config['interfaces'][$if]['subnet']))) + 1; +$range_to = ip2long(long2ip32(ip2long($config['interfaces'][$if]['ipaddr']) | (~gen_subnet_mask_long($config['interfaces'][$if]['subnet'])))) - 1; + $service_hook = 'dhcpd'; legacy_html_escape_form_data($pconfig); include("head.inc"); @@ -667,20 +670,18 @@ include("head.inc"); - - - - + + + + - + +
In-use DHCP Pool Ranges:
- - +
- - + + diff --git a/src/www/services_dhcpv6.php b/src/www/services_dhcpv6.php index 0ccef5983..4e8107b4d 100644 --- a/src/www/services_dhcpv6.php +++ b/src/www/services_dhcpv6.php @@ -1,7 +1,7 @@ * Copyright (C) 2010 Seth Mos * All rights reserved. @@ -54,7 +54,38 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { header(url_safe('Location: /index.php')); exit; } +} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') { + // handle identifiers and actions + if (!empty($_POST['if']) && !empty($config['interfaces'][$_POST['if']])) { + $if = $_POST['if']; + } + if (!empty($_POST['act'])) { + $act = $_POST['act']; + } else { + $act = null; + } +} +$ifcfgip = $config['interfaces'][$if]['ipaddrv6']; +$ifcfgsn = $config['interfaces'][$if]['subnetv6']; + +if (isset($config['interfaces'][$if]['dhcpd6track6allowoverride'])) { + list ($ifcfgip, $networkv6) = interfaces_primary_address6($if); + $ifcfgsn = explode('/', $networkv6)[1]; + $prefix_array = array(); + $prefix_array = explode(':', $ifcfgip); + $prefix_array[4] = '0'; + $prefix_array[5] = '0'; + $prefix_array[6] = '0'; + $prefix_array[7] = '0'; + $wifprefix = Net_IPv6::compress(implode(':', $prefix_array)); + $pdlen = calculate_ipv6_delegation_length($config['interfaces'][$if]['track6-interface']) - 1; +} + +$subnet_start = gen_subnetv6($ifcfgip, $ifcfgsn); +$subnet_end = gen_subnetv6_max($ifcfgip, $ifcfgsn); + +if ($_SERVER['REQUEST_METHOD'] === 'GET') { $pconfig = array(); if (!empty($config['dhcpdv6'][$if]['range'])) { @@ -95,15 +126,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { } } elseif ($_SERVER['REQUEST_METHOD'] === 'POST') { - // handle identifiers and actions - if (!empty($_POST['if']) && !empty($config['interfaces'][$_POST['if']])) { - $if = $_POST['if']; - } - if (!empty($_POST['act'])) { - $act = $_POST['act']; - } else { - $act = null; - } $pconfig = $_POST; $input_errors = array(); @@ -192,11 +214,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { } if (count($input_errors) == 0) { - /* make sure the range lies within the current subnet */ - list ($ifcfgip, $ifcfgsn) = explode('/', find_interface_networkv6(get_real_interface($if, 'inet6'), false)); - $subnet_start = gen_subnetv6($ifcfgip, $ifcfgsn); - $subnet_end = gen_subnetv6_max($ifcfgip, $ifcfgsn); - $range_from = $pconfig['range_from']; $range_to = $pconfig['range_to']; @@ -206,15 +223,17 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { } if (!empty($pconfig['range_from']) && !empty($pconfig['range_to'])) { - if (is_ipaddrv6($ifcfgip) && !empty($pconfig['range_from']) && !empty($pconfig['range_to'])) { - if ((!is_inrange_v6($range_from, $subnet_start, $subnet_end)) || - (!is_inrange_v6($range_to, $subnet_start, $subnet_end))) { - $input_errors[] = gettext("The specified range lies outside of the current subnet."); - } + /* make sure the range lies within the current subnet */ + if ((!is_inrange_v6($range_from, $subnet_start, $subnet_end)) || + (!is_inrange_v6($range_to, $subnet_start, $subnet_end))) { + $input_errors[] = gettext('The specified range lies outside of the current subnet.'); } + /* single IP subnet does not have enough addresses */ + if ($subnet_start == $subnet_end) { + $input_errors[] = gettext('The range is unavailable (single host network mask /128 used).'); /* "from" cannot be higher than "to" */ - if (inet_pton($pconfig['range_from']) > inet_pton($pconfig['range_to'])) { + } elseif (inet_pton($pconfig['range_from']) > inet_pton($pconfig['range_to'])) { $input_errors[] = gettext("The range is invalid (first element higher than second element)."); } @@ -332,20 +351,6 @@ legacy_html_escape_form_data($pconfig); include("head.inc"); -list ($wifcfgip, $networkv6) = interfaces_primary_address6($if); -$wifcfgsn = explode('/', $networkv6)[1]; - -if (isset($config['interfaces'][$if]['dhcpd6track6allowoverride'])) { - $prefix_array = array(); - $prefix_array = explode(':', $wifcfgip); - $prefix_array[4] = '0'; - $prefix_array[5] = '0'; - $prefix_array[6] = '0'; - $prefix_array[7] = '0'; - $wifprefix = Net_IPv6::compress(implode(':', $prefix_array)); - $pdlen = calculate_ipv6_delegation_length($config['interfaces'][$if]['track6-interface']) - 1; -} - ?>