summaryrefslogtreecommitdiffstats
path: root/modules-available/dnbd3/inc/dnbd3util.inc.php
diff options
context:
space:
mode:
Diffstat (limited to 'modules-available/dnbd3/inc/dnbd3util.inc.php')
-rw-r--r--modules-available/dnbd3/inc/dnbd3util.inc.php52
1 files changed, 48 insertions, 4 deletions
diff --git a/modules-available/dnbd3/inc/dnbd3util.inc.php b/modules-available/dnbd3/inc/dnbd3util.inc.php
index 95b6ffe2..33581b77 100644
--- a/modules-available/dnbd3/inc/dnbd3util.inc.php
+++ b/modules-available/dnbd3/inc/dnbd3util.inc.php
@@ -103,6 +103,7 @@ class Dnbd3Util {
*/
public static function runmodeConfigHook($machineUuid, $mode, $modeData)
{
+ $self = Property::getServerIp();
// Get all directly assigned locations
$res = Database::simpleQuery('SELECT locationid FROM dnbd3_server
INNER JOIN dnbd3_server_x_location USING (serverid)
@@ -124,10 +125,20 @@ class Dnbd3Util {
}
$res = Database::simpleQuery('SELECT startaddr, endaddr FROM subnet WHERE locationid IN (:locs)',
array('locs' => array_values($recursiveLocs)));
+ // Coalesce overlapping ranges
+ $floatIp = ip2long($self); // Float for 32bit php :/
+ if (PHP_INT_SIZE === 4) {
+ $floatIp = (float)sprintf('%u', $floatIp); // Float for 32bit php :/
+ }
+ $ranges = [['startaddr' => $floatIp, 'endaddr' => $floatIp]];
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ settype($row['startaddr'], PHP_INT_SIZE === 4 ? 'float' : 'int');
+ settype($row['endaddr'], PHP_INT_SIZE === 4 ? 'float' : 'int');
+ self::mergeRanges($ranges, $row);
+ }
// Got subnets, build whitelist
- // TODO: Coalesce overlapping ranges
$opt = '';
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($ranges as $row) {
$opt .= ' ' . self::range2Cidr($row['startaddr'], $row['endaddr']);
}
if (!empty($opt)) {
@@ -141,7 +152,6 @@ class Dnbd3Util {
WHERE s.machineuuid <> :uuid OR s.machineuuid IS NULL', array('uuid' => $machineUuid));
$public = array();
$private = array();
- $self = Property::getServerIp();
$public[$self] = $self;
while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
$ip = $row['fixedip'] ? $row['fixedip'] : $row['clientip'];
@@ -188,13 +198,47 @@ class Dnbd3Util {
*/
private static function range2Cidr($start, $end)
{
- $bin = decbin((int)$start ^ (int)$end);
+ if (PHP_INT_SIZE > 4) {
+ $bin = decbin((int)$start ^ (int)$end);
+ } else {
+ $bin = decbin((int)(float)$start ^ (int)(float)$end);
+ }
if ($bin === '0')
return long2ip($start);
$mask = 32 - strlen($bin);
return long2ip($start) . '/' . $mask;
}
+ private static function mergeRanges(&$ranges, $row)
+ {
+ if ($row['startaddr'] >= $row['endaddr'])
+ return; // Don't even bother
+ foreach (array_keys($ranges) as $key) {
+ if ($row['startaddr'] <= $ranges[$key]['startaddr'] && $row['endaddr'] >= $ranges[$key]['endaddr']) {
+ // Fully dominated
+ unset($ranges[$key]);
+ continue; // Might partially overlap with additional ranges, keep going
+ }
+ if ($ranges[$key]['startaddr'] <= $row['startaddr'] && $ranges[$key]['endaddr'] >= $row['startaddr']) {
+ // $row['startaddr'] lies within existing range
+ if ($ranges[$key]['startaddr'] <= $row['endaddr'] && $ranges[$key]['endaddr'] >= $row['endaddr'])
+ return; // Fully in existing range, do nothing
+ // $row['endaddr'] seems to extend range we're checking against but $row['startaddr'] lies within this range, update and keep going
+ $row['startaddr'] = $ranges[$key]['startaddr'];
+ unset($ranges[$key]);
+ continue;
+ }
+ // Last possibility: $row['startaddr'] is before range, $row['endaddr'] within range
+ if ($ranges[$key]['startaddr'] <= $row['endaddr'] && $ranges[$key]['endaddr'] >= $row['endaddr']) {
+ // $row['startaddr'] must lie before range start, otherwise we'd have hit the case above
+ $row['endaddr'] = $ranges[$key]['endaddr'];
+ unset($ranges[$key]);
+ continue;
+ }
+ }
+ $ranges[] = $row;
+ }
+
public static function defaultRunmodeConfig()
{
return array(