diff options
author | Renato Botelho <renato@netgate.com> | 2016-02-19 08:28:44 -0200 |
---|---|---|
committer | Renato Botelho <renato@netgate.com> | 2016-02-19 10:57:32 -0200 |
commit | 2bf455caa3aaca83287309b6a7629c7d3a328652 (patch) | |
tree | d86087d0db6abc692d570e9f2dde7067675b0ffb /src | |
parent | 934b8a98b29b01978f6d36d9487423df1b2f7339 (diff) | |
download | pfsense-2bf455caa3aaca83287309b6a7629c7d3a328652.zip pfsense-2bf455caa3aaca83287309b6a7629c7d3a328652.tar.gz |
Ticket #3029
Import patch from @Robert-Nelson to enable DHCPv6 Server/RA to
interfaces configured to track DHCP-PD
This patch only works for PD with length 64
Diffstat (limited to 'src')
-rw-r--r-- | src/etc/inc/pfsense-utils.inc | 8 | ||||
-rw-r--r-- | src/etc/inc/services.inc | 46 | ||||
-rw-r--r-- | src/etc/inc/system.inc | 23 | ||||
-rw-r--r-- | src/usr/local/www/services_dhcpv6.php | 37 | ||||
-rw-r--r-- | src/usr/local/www/services_dhcpv6_edit.php | 9 | ||||
-rw-r--r-- | src/usr/local/www/services_router_advertisements.php | 5 |
6 files changed, 100 insertions, 28 deletions
diff --git a/src/etc/inc/pfsense-utils.inc b/src/etc/inc/pfsense-utils.inc index 5090a94..67cf1bc 100644 --- a/src/etc/inc/pfsense-utils.inc +++ b/src/etc/inc/pfsense-utils.inc @@ -2823,6 +2823,14 @@ function calculate_ipv6_delegation_length($if) { return($pdlen); } +function merge_ipv6_delegated_prefix($prefix, $suffix) { + $prefix_array = explode(':', Net_IPv6::uncompress($prefix)); + $suffix_array = explode(':', Net_IPv6::uncompress($suffix)); + return Net_IPv6::compress(implode(':', + array_merge(array_slice($prefix_array, 0, 4), + array_slice($suffix_array, 4)))); +} + function huawei_rssi_to_string($rssi) { $dbm = array(); $i = 0; diff --git a/src/etc/inc/services.inc b/src/etc/inc/services.inc index e07601d..4e121e9 100644 --- a/src/etc/inc/services.inc +++ b/src/etc/inc/services.inc @@ -1237,13 +1237,17 @@ function services_dhcpdv6_configure($blacklist = array()) { sleep(1); } - /* we add a fake entry for interfaces that are set to track6 another WAN */ + /* + * We add a fake entry for interfaces that are set to track6 + * another WAN unless DHCP has been configured + */ foreach ($Iflist as $ifname) { /* Do not put in the config an interface which is down */ if (isset($blacklist[$ifname])) { continue; } - if (!empty($config['interfaces'][$ifname]['track6-interface'])) { + if (!empty($config['interfaces'][$ifname]['track6-interface']) && + (empty($dhcpdv6cfg[$ifname]) || !isset($dhcpdv6cfg[$ifname]['enable']))) { $realif = get_real_interface($ifname, "inet6"); $ifcfgipv6 = get_interface_ipv6($ifname); if (!is_ipaddrv6($ifcfgipv6)) { @@ -1416,8 +1420,15 @@ EOD; $dhcpdv6conf .= " {\n"; + $range_from = $dhcpv6ifconf['range']['from']; + $range_to = $dhcpv6ifconf['range']['to']; + if ($ifcfgv6['ipaddrv6'] == 'track6') { + $range_from = merge_ipv6_delegated_prefix($ifcfgipv6, $range_from); + $range_to = merge_ipv6_delegated_prefix($ifcfgipv6, $range_to); + } + $dhcpdv6conf .= <<<EOD - range6 {$dhcpv6ifconf['range']['from']} {$dhcpv6ifconf['range']['to']}; + range6 {$range_from} {$range_to}; $dnscfgv6 EOD; @@ -1426,7 +1437,12 @@ EOD; $dhcpdv6conf .= " prefix6 {$dhcpv6ifconf['prefixrange']['from']} {$dhcpv6ifconf['prefixrange']['to']} /{$dhcpv6ifconf['prefixrange']['prefixlength']};\n"; } if (is_ipaddrv6($dhcpv6ifconf['dns6ip'])) { - $dhcpdv6conf .= " option dhcp6.name-servers {$dhcpv6ifconf['dns6ip']};\n"; + $dns6ip = $dhcpv6ifconf['dns6ip']; + if ($ifcfgv6['ipaddrv6'] == 'track6' && + Net_IPv6::isInNetmask($dns6ip, '::', 64)) { + $dns6ip = merge_ipv6_delegated_prefix($ifcfgipv6, $dns6ip); + } + $dhcpdv6conf .= " option dhcp6.name-servers {$dns6ip};\n"; } // default-lease-time if ($dhcpv6ifconf['defaultleasetime']) { @@ -1442,9 +1458,14 @@ EOD; if (is_array($dhcpv6ifconf['ntpserver']) && $dhcpv6ifconf['ntpserver'][0]) { $ntpservers = array(); foreach ($dhcpv6ifconf['ntpserver'] as $ntpserver) { - if (is_ipaddrv6($ntpserver)) { - $ntpservers[] = $ntpserver; + if (!is_ipaddrv6($ntpserver)) { + continue; + } + if ($ifcfgv6['ipaddrv6'] == 'track6' && + Net_IPv6::isInNetmask($ntpserver, '::', 64)) { + $ntpserver =merge_ipv6_delegated_prefix($ifcfgipv6, $ntpserver); } + $ntpservers[] = $ntpserver; } if (count($ntpservers) > 0) { $dhcpdv6conf .= " option dhcp6.sntp-servers " . join(",", $dhcpv6ifconf['ntpserver']) . ";\n"; @@ -1468,7 +1489,12 @@ EOD; // ldap-server if ($dhcpv6ifconf['ldap'] <> "") { - $dhcpdv6conf .= " option ldap-server \"{$dhcpv6ifconf['ldap']}\";\n"; + $ldapserver = $dhcpv6ifconf['ldap']; + if ($ifcfgv6['ipaddrv6'] == 'track6' && + Net_IPv6::isInNetmask($ldapserver, '::', 64)) { + $ldapserver = merge_ipv6_delegated_prefix($ifcfgipv6, $ldapserver); + } + $dhcpdv6conf .= " option ldap-server \"{$ldapserver}\";\n"; } // net boot information @@ -1491,7 +1517,11 @@ host s_{$dhcpv6if}_{$i} { EOD; if ($sm['ipaddrv6']) { - $dhcpdv6conf .= " fixed-address6 {$sm['ipaddrv6']};\n"; + $ipaddrv6 = $sm['ipaddrv6']; + if ($ifcfgv6['ipaddrv6'] == 'track6') { + $ipaddrv6 = merge_ipv6_delegated_prefix($ifcfgipv6, $ipaddrv6); + } + $dhcpdv6conf .= " fixed-address6 {$ipaddrv6};\n"; } if ($sm['hostname']) { diff --git a/src/etc/inc/system.inc b/src/etc/inc/system.inc index 631ab68..2204416 100644 --- a/src/etc/inc/system.inc +++ b/src/etc/inc/system.inc @@ -420,13 +420,24 @@ function system_hosts_generate() { if (isset($dnsmasqcfg['regdhcpstatic']) && is_array($config['dhcpdv6'])) { foreach ($config['dhcpdv6'] as $dhcpif => $dhcpifconf) { if (is_array($dhcpifconf['staticmap']) && isset($dhcpifconf['enable'])) { + $isdelegated = $config['interfaces'][$dhcpif]['ipaddrv6'] == 'track6'; + if ($isdelegated) { + $prefix = array_slice(explode(':', Net_IPv6::uncompress(get_interface_ipv6($dhcpif))), 0, 4); + } foreach ($dhcpifconf['staticmap'] as $host) { - if ($host['ipaddrv6'] && $host['hostname'] && $host['domain']) { - $dhosts .= "{$host['ipaddrv6']} {$host['hostname']}.{$host['domain']} {$host['hostname']}\n"; - } else if ($host['ipaddrv6'] && $host['hostname'] && $dhcpifconf['domain']) { - $dhosts .= "{$host['ipaddrv6']} {$host['hostname']}.{$dhcpifconf['domain']} {$host['hostname']}\n"; - } else if ($host['ipaddrv6'] && $host['hostname']) { - $dhosts .= "{$host['ipaddrv6']} {$host['hostname']}.{$syscfg['domain']} {$host['hostname']}\n"; + $ipaddrv6 = $host['ipaddrv6']; + if ($ipaddrv6 && $host['hostname']) { + if ($isdelegated) { + $suffix = array_slice(explode(':', Net_IPv6::uncompress($ipaddrv6)), 4); + $ipaddrv6 = Net_IPv6::compress(implode(':', array_merge($prefix, $suffix))); + } + if ($host['domain']) { + $dhosts .= "{$ipaddrv6} {$host['hostname']}.{$host['domain']} {$host['hostname']}\n"; + } else if ($dhcpifconf['domain']) { + $dhosts .= "{$ipaddrv6} {$host['hostname']}.{$dhcpifconf['domain']} {$host['hostname']}\n"; + } else { + $dhosts .= "{$ipaddrv6} {$host['hostname']}.{$syscfg['domain']} {$host['hostname']}\n"; + } } } } diff --git a/src/usr/local/www/services_dhcpv6.php b/src/usr/local/www/services_dhcpv6.php index 5513b3d..ea80ac4 100644 --- a/src/usr/local/www/services_dhcpv6.php +++ b/src/usr/local/www/services_dhcpv6.php @@ -99,8 +99,9 @@ $iflist = array_merge($iflist, get_configured_pppoe_server_interfaces()); if (!$if || !isset($iflist[$if])) { foreach ($iflist as $ifent => $ifname) { $oc = $config['interfaces'][$ifent]; - $valid_if_ipaddrv6 = (bool) (is_ipaddrv6($oc['ipaddrv6']) && - !is_linklocal($oc['ipaddrv6'])); + $valid_if_ipaddrv6 = (bool) ($oc['ipaddrv6'] == 'track6' || + (is_ipaddrv6($oc['ipaddrv6']) && + !is_linklocal($oc['ipaddrv6']))); if ((!is_array($config['dhcpdv6'][$ifent]) || !isset($config['dhcpdv6'][$ifent]['enable'])) && @@ -151,8 +152,13 @@ if (is_array($config['dhcpdv6'][$if])) { $a_maps = &$config['dhcpdv6'][$if]['staticmap']; } -$ifcfgip = get_interface_ipv6($if); -$ifcfgsn = get_interface_subnetv6($if); +if ($config['interfaces'][$if]['ipaddrv6'] == 'track6') { + $ifcfgip = '::'; + $ifcfgsn = 64; +} else { + $ifcfgip = get_interface_ipv6($if); + $ifcfgsn = get_interface_subnetv6($if); +} /* set the enabled flag which will tell us if DHCP relay is enabled * on any interface. We will use this to disable DHCP server since @@ -234,11 +240,21 @@ if ($_POST) { } } - if (($_POST['range_from'] && !is_ipaddrv6($_POST['range_from']))) { - $input_errors[] = gettext("A valid range must be specified."); + if ($_POST['range_from']) { + if (!is_ipaddrv6($_POST['range_from'])) { + $input_errors[] = gettext("A valid range must be specified."); + } elseif ($config['interfaces'][$if]['ipaddrv6'] == 'track6' && + !Net_IPv6::isInNetmask($_POST['range_from'], '::', 64)) { + $input_errors[] = gettext("The prefix (upper 64 bits) must be zero. Use the form ::x:x:x:x"); + } } - if (($_POST['range_to'] && !is_ipaddrv6($_POST['range_to']))) { - $input_errors[] = gettext("A valid range must be specified."); + if ($_POST['range_to']) { + if (!is_ipaddrv6($_POST['range_to'])) { + $input_errors[] = gettext("A valid range must be specified."); + } elseif ($config['interfaces'][$if]['ipaddrv6'] == 'track6' && + !Net_IPv6::isInNetmask($_POST['range_to'], '::', 64)) { + $input_errors[] = gettext("The prefix (upper 64 bits) must be zero. Use the form ::x:x:x:x"); + } } if (($_POST['gateway'] && !is_ipaddrv6($_POST['gateway']))) { $input_errors[] = gettext("A valid IPv6 address must be specified for the gateway."); @@ -507,8 +523,9 @@ $i = 0; foreach ($iflist as $ifent => $ifname) { $oc = $config['interfaces'][$ifent]; - $valid_if_ipaddrv6 = (bool) (is_ipaddrv6($oc['ipaddrv6']) && - !is_linklocal($oc['ipaddrv6'])); + $valid_if_ipaddrv6 = (bool) ($oc['ipaddrv6'] == 'track6' || + (is_ipaddrv6($oc['ipaddrv6']) && + !is_linklocal($oc['ipaddrv6']))); if ((!is_array($config['dhcpdv6'][$ifent]) || !isset($config['dhcpdv6'][$ifent]['enable'])) && diff --git a/src/usr/local/www/services_dhcpv6_edit.php b/src/usr/local/www/services_dhcpv6_edit.php index f8c26da..b26ba9d 100644 --- a/src/usr/local/www/services_dhcpv6_edit.php +++ b/src/usr/local/www/services_dhcpv6_edit.php @@ -155,8 +155,13 @@ if ($_POST) { } } } - if (($_POST['ipaddrv6'] && !is_ipaddrv6($_POST['ipaddrv6']))) { - $input_errors[] = gettext("A valid IPv6 address must be specified."); + if ($_POST['ipaddrv6']) { + if (!is_ipaddrv6($_POST['ipaddrv6'])) { + $input_errors[] = gettext("A valid IPv6 address must be specified."); + } elseif ($config['interfaces'][$if]['ipaddrv6'] == 'track6' && + !Net_IPv6::isInNetmask($_POST['ipaddrv6'], '::', 64)) { + $input_errors[] = gettext("The prefix (upper 64 bits) must be zero. Use the form ::x:x:x:x"); + } } if (empty($_POST['duid'])) { diff --git a/src/usr/local/www/services_router_advertisements.php b/src/usr/local/www/services_router_advertisements.php index 3a4746d..9ef58e1 100644 --- a/src/usr/local/www/services_router_advertisements.php +++ b/src/usr/local/www/services_router_advertisements.php @@ -102,8 +102,9 @@ $iflist = get_configured_interface_with_descr(); if (!$if || !isset($iflist[$if])) { foreach ($iflist as $ifent => $ifname) { $oc = $config['interfaces'][$ifent]; - $valid_if_ipaddrv6 = (bool) (is_ipaddrv6($oc['ipaddrv6']) && - !is_linklocal($oc['ipaddrv6'])); + $valid_if_ipaddrv6 = (bool) ($oc['ipaddrv6'] == 'track6' || + (is_ipaddrv6($oc['ipaddrv6']) && + !is_linklocal($oc['ipaddrv6']))); if ((!is_array($config['dhcpdv6'][$ifent]) || !isset($config['dhcpdv6'][$ifent]['enable'])) && |