From 4e64cbc599224273043759e365c0b1495a50de73 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Mon, 23 Jun 2014 18:08:47 +0200 Subject: Try to autpmatically detect server ip on init-api --- inc/trigger.inc.php | 56 +++++++++++++++++++++++++++++++++++++--------- inc/util.inc.php | 64 +++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 93 insertions(+), 27 deletions(-) (limited to 'inc') diff --git a/inc/trigger.inc.php b/inc/trigger.inc.php index 2fde45ab..7ab7d5b1 100644 --- a/inc/trigger.inc.php +++ b/inc/trigger.inc.php @@ -18,25 +18,59 @@ class Trigger * @param boolean $force force recompilation even if it seems up to date * @return boolean|string true if already up to date, false if launching task failed, task-id otherwise */ - public static function ipxe($force = false) + public static function ipxe() { - if (!$force && Property::getIPxeIp() === Property::getServerIp()) - return true; // Nothing to do - $last = Property::getIPxeTaskId(); - if ($last !== false) { - $status = Taskmanager::status($last); - if (isset($status['statusCode']) && ($status['statusCode'] === TASK_WAITING || $status['statusCode'] === TASK_PROCESSING)) - return false; // Already compiling - } $data = Property::getBootMenu(); - $data['ip'] = Property::getServerIp(); $task = Taskmanager::submit('CompileIPxe', $data); if (!isset($task['id'])) return false; - Property::setIPxeTaskId($task['id']); return $task['id']; } + /** + * Try to automatically determine the primary IP address of the server. + * This only works if the server has either one public IPv4 address (and potentially + * one or more non-public addresses), or one private address. + */ + public static function autoUpdateServerIp() + { + $task = Taskmanager::submit('LocalAddressesList'); + if ($task === false) + return; + $task = Taskmanager::waitComplete($task, 10000); + if (!isset($task['data']['addresses']) || empty($task['data']['addresses'])) + return; + + $serverIp = Property::getServerIp(); + $publicCandidate = 'none'; + $privateCandidate = 'none'; + foreach ($task['data']['addresses'] as $addr) { + if ($addr['ip'] === $serverIp) + return; + if (substr($addr['ip'], 0, 4) === '127.') + continue; + if (Util::isPublicIpv4($addr['ip'])) { + if ($publicCandidate === 'none') + $publicCandidate = $addr['ip']; + else + $publicCandidate = 'many'; + } else { + if ($privateCandidate === 'none') + $privateCandidate = $addr['ip']; + else + $privateCandidate = 'many'; + } + } + if ($publicCandidate !== 'none' && $publicCandidate !== 'many') { + Property::setServerIp($publicCandidate); + return; + } + if ($privateCandidate !== 'none' && $privateCandidate !== 'many') { + Property::setServerIp($privateCandidate); + return; + } + } + /** * * @return boolean|string false on error, id of task otherwise diff --git a/inc/util.inc.php b/inc/util.inc.php index 8b5a14e4..ea28b4fa 100644 --- a/inc/util.inc.php +++ b/inc/util.inc.php @@ -54,8 +54,10 @@ class Util */ public static function verifyToken() { - if (Session::get('token') === false) return true; - if (isset($_REQUEST['token']) && Session::get('token') === $_REQUEST['token']) return true; + if (Session::get('token') === false) + return true; + if (isset($_REQUEST['token']) && Session::get('token') === $_REQUEST['token']) + return true; Message::addError('token'); return false; } @@ -83,7 +85,8 @@ class Util private static function initCurl($url, $timeout, &$head) { $ch = curl_init(); - if ($ch === false) Util::traceError('Could not initialize cURL'); + if ($ch === false) + Util::traceError('Could not initialize cURL'); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, ceil($timeout / 2)); curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); @@ -93,7 +96,8 @@ class Util curl_setopt($ch, CURLOPT_MAXREDIRS, 6); $tmpfile = '/tmp/' . mt_rand() . '-' . time(); $head = fopen($tmpfile, 'w+b'); - if ($head === false) Util::traceError("Could not open temporary head file $tmpfile for writing."); + if ($head === false) + Util::traceError("Could not open temporary head file $tmpfile for writing."); curl_setopt($ch, CURLOPT_WRITEHEADER, $head); return $ch; } @@ -102,13 +106,13 @@ class Util * Read 10kb from the given file handle, seek to 0 first, * close the file after reading. Returns data read */ - private static function getContents($fh) - { - fseek($fh, 0, SEEK_SET); + private static function getContents($fh) + { + fseek($fh, 0, SEEK_SET); $data = fread($fh, 10000); fclose($fh); return $data; - } + } /** * Download file, obey given timeout in seconds @@ -121,7 +125,7 @@ class Util $data = curl_exec($ch); $head = self::getContents($head); if (preg_match('#^HTTP/\d+\.\d+ (\d+) #', $head, $out)) { - $code = (int)$out[1]; + $code = (int) $out[1]; } else { $code = 999; } @@ -136,7 +140,8 @@ class Util public static function downloadToFile($target, $url, $timeout, &$code) { $fh = fopen($target, 'wb'); - if ($fh === false) Util::traceError("Could not open $target for writing."); + if ($fh === false) + Util::traceError("Could not open $target for writing."); $ch = self::initCurl($url, $timeout, $head); curl_setopt($ch, CURLOPT_FILE, $fh); $res = curl_exec($ch); @@ -148,13 +153,13 @@ class Util return false; } if (preg_match('#^HTTP/\d+\.\d+ (\d+) #', $head, $out)) { - $code = (int)$out[1]; + $code = (int) $out[1]; } else { $code = '999 ' . curl_error($ch); } return true; } - + /** * Convert given number to human readable file size string. * Will append Bytes, KiB, etc. depending on magnitude of number. @@ -163,7 +168,8 @@ class Util * @param type $decimals number of decimals to show, -1 for automatic * @return type human readable string representing the given filesize */ - public static function readableFileSize($bytes, $decimals = -1) { + public static function readableFileSize($bytes, $decimals = -1) + { static $sz = array('Byte', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB'); $factor = floor((strlen($bytes) - 1) / 3); if ($factor == 0) { @@ -173,12 +179,12 @@ class Util } return sprintf("%.{$decimals}f ", $bytes / pow(1024, $factor)) . $sz[$factor]; } - + public static function sanitizeFilename($name) { return preg_replace('/[^a-zA-Z0-9_\-]+/', '_', $name); } - + /** * Create human readable error description from a $_FILES[<..>]['error'] code * @@ -217,5 +223,31 @@ class Util return $message; } -} + /** + * Is given string a public ipv4 address? + * + * @param string $ip_addr input to check + * @return boolean true iff $ip_addr is a valid public ipv4 address + */ + public static function isPublicIpv4($ip_addr) + { + if (!preg_match("/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/", $ip_addr)) + return false; + $parts = explode(".", $ip_addr); + foreach ($parts as $part) { + if (!is_numeric($part) || $part > 255 || $part < 0) + return false; + } + + if ($parts[0] == 0 || $parts[0] == 10 || $parts[0] == 127 || ($parts[0] > 223 && $parts[0] < 240)) + return false; + if (($parts[0] == 192 && $parts[1] == 168) || ($parts[0] == 169 && $parts[1] == 254)) + return false; + if ($parts[0] == 172 && $parts[1] > 15 && $parts[1] < 32) + return false; + + return true; + } + +} -- cgit v1.2.3-55-g7522