support pooling of IP ranges (RFE 107)

This commit is contained in:
Roland Gruber 2014-09-13 14:43:44 +00:00
parent 2131405664
commit 6d86cef692
11 changed files with 496 additions and 149 deletions

View File

@ -1,5 +1,6 @@
September 2014 4.7
- Nginx webserver support
- DHCP: support pooling of IP ranges (RFE 107)
- Personal: support pager attribute (hidden by default)
- renamed config/lam.conf_sample to lam.conf.sample and config.cfg_sample to config.cfg.sample
- LAM Pro:

View File

@ -4243,9 +4243,12 @@ Attention: If the Active Directory schema is used then LAM will always use dn an
<title>DHCP</title>
<para>You can mange your DHCP server with LAM. It supports to manage
subnets, fixed IP entries, IP ranges and DDNS. The DHCP can be activated
by adding the account type DHCP to your server profile. Please also add
the DHCP modules.</para>
subnets, fixed IP entries, IP ranges and DDNS.</para>
<para><emphasis role="bold">Configuration</emphasis></para>
<para>The DHCP management can be activated by adding the account type
DHCP to your server profile. Please also add the DHCP modules.</para>
<para>LAM requires that you use an LDAP entry with the object class
"dhcpService" or "dhcpServer" as suffix for this account type. If the
@ -4256,6 +4259,36 @@ Attention: If the Active Directory schema is used then LAM will always use dn an
<literallayout>
</literallayout>
<para>Add account type:</para>
<screenshot>
<mediaobject>
<imageobject>
<imagedata fileref="images/dhcpConf1.png" />
</imageobject>
</mediaobject>
</screenshot>
<para>Set suffix:</para>
<screenshot>
<mediaobject>
<imageobject>
<imagedata fileref="images/dhcpConf2.png" />
</imageobject>
</mediaobject>
</screenshot>
<para>Add modules:</para>
<screenshot>
<mediaobject>
<imageobject>
<imagedata fileref="images/dhcpConf3.png" />
</imageobject>
</mediaobject>
</screenshot>
<para><emphasis role="bold">Example server
entry:</emphasis><code></code></para>
@ -4375,6 +4408,10 @@ Run slapindex to rebuild the index.
<para>IP ranges may be specified.</para>
<para>If you use failover pools for your IP ranges please use the pool
options on the bottom. Here you can add DHCP pools (object class
"dhcpPool") and specify the failover peer.</para>
<screenshot>
<mediaobject>
<imageobject>

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View File

@ -624,7 +624,7 @@ class htmlInputField extends htmlElement {
}
/**
* Sets the field size.
* Sets the field size (default is 30).
*
* @param int $fieldSize size
*/

View File

@ -41,7 +41,7 @@ $Id$
class fixed_ip extends baseModule {
/** fixed ips */
public $fixed_ip;
public $fixed_ip = array();
/** already processed? */
public $processed = false;

View File

@ -51,6 +51,11 @@ class range extends baseModule {
/** For check, if IPs overlaped. */
public $overlaped;
/** list of pools that currently exist in LDAP */
private $poolsOrig = array();
/** list of pools that need to be updated in LDAP */
private $poolsNew = array();
/**
* Returns true if this module can manage accounts of the current type, otherwise false.
@ -88,19 +93,35 @@ class range extends baseModule {
$return['attributes'] = array('dhcpRange');
// help Entries
$return['help'] = array(
'range_from' => array(
'range_from' => array(
"Headline" => _("Range from"),
"Text" => _("The starting IP address of the range.")
) , 'range_to' => array(
),
'range_to' => array(
"Headline" => _("Range to"),
"Text" => _("The ending IP address of the range.")
) , 'drop_range' => array(
),
'drop_range' => array(
"Headline" => _("Delete range"),
"Text" => _("Deletes an IP range.")
) , 'add_range' => array(
),
'add_range' => array(
"Headline" => _("New range"),
"Text" => _("Adds input fields for a new IP range.")
) );
),
'add_pool' => array(
"Headline" => _("New pool"),
"Text" => _("Adds a new range pool.")
),
'poolName' => array(
"Headline" => _("Name"), 'attr' => 'cn',
"Text" => _("The pool's name.")
),
'poolPeer' => array(
"Headline" => _("Failover peer"), 'attr' => 'dhcpStatements',
"Text" => _("The pool's failover peer.")
),
);
// available PDF fields
$return['PDF_fields'] = array('ranges' => _('Ranges'));
@ -114,6 +135,8 @@ class range extends baseModule {
$this->messages['range_errors'][0] = array('ERROR', _('One or more errors occured. The invalid fields are marked.'), '');
$this->messages['add_range'][0] = array('ERROR', _('New range'), _('Adding the range failed because errors occured.'));
$this->messages['drop_range'][0] = array('ERROR', _('Delete range'), _('It is not possible to delete all ranges.'));
$this->messages['pool_cn'][0] = array('ERROR', _('Name'), _('Please enter a pool name.'));
$this->messages['pool_range'][0] = array('ERROR', _('Please enter at least one range for pool "%s".'), null);
}
/**
@ -225,8 +248,6 @@ class range extends baseModule {
if ($this->getAccountContainer()->dn_orig!=$_SESSION['config']->get_suffix('dhcp')) {
$this->orig = $attr;
$this->attributes = $attr;
// Load DHCP Options:
if (isset($attr['dhcpRange']) && is_array($attr['dhcpRange'])) {
natcasesort($attr['dhcpRange']);
@ -237,6 +258,8 @@ class range extends baseModule {
$this->ranges[$id] = array('range_start'=>$ex[0],'range_end'=>$ex[1]);
}
}
// load pools
$this->loadPools();
}
}
@ -290,107 +313,171 @@ class range extends baseModule {
*/
public function process_attributes() {
$errors = array();
$droped = false; // Was a Range droped???
if ($this->getAccountContainer()->dn_orig!=$_SESSION['config']->get_suffix('dhcp')) {
if ($this->getAccountContainer()->getAccountModule('dhcp_settings')->attributes['cn'][0]!="") {
$was_a_error = false;
$this->reset_overlaped_range();
if ($this->getAccountContainer()->dn_orig == $_SESSION['config']->get_suffix('dhcp')) {
return $errors;
}
$subnet = $this->getAccountContainer()->getAccountModule('dhcp_settings')->attributes['cn'][0];
$mask = $this->getAccountContainer()->getAccountModule('dhcp_settings')->getDHCPOption('subnet-mask');
$errorOccured = false;
$this->reset_overlaped_range();
if ($this->getAccountContainer()->getAccountModule('dhcp_settings')->attributes['cn'][0]!="") {
foreach($this->ranges AS $id=>$arr) {
foreach($this->ranges AS $id=>$arr) {
// Check if range is to drop
if (isset($_POST['drop_range_'.$id])) {
// drop Range:
unset($this->ranges[$id]);
unset($this->attributes['dhcpRange'][$id]);
continue;
}
// Check if range is to drop
if (isset($_POST['drop_range_'.$id])) {
// Drop Range:
unset($this->ranges[$id]);
unset($this->attributes['dhcpRange'][$id]);
$droped = true;
continue;
}
// if the inputs are empty, then do nothing:
if ($_POST['range_start_'.$id]=="" && $_POST['range_end_'.$id]=="") {
unset($this->attributes['dhcpRange'][$id]);
}
else {
// Check range_start:
$_POST['range_start_'.$id] = trim($_POST['range_start_'.$id]);
if (!check_ip($_POST['range_start_'.$id])) {
$errorOccured = true;
}
$this->ranges[$id]['range_start'] = $_POST['range_start_'.$id];
// if the inputs are empty, then do nothing:
if ($_POST['range_start_'.$id]=="" && $_POST['range_end_'.$id]=="") {
unset($this->attributes['dhcpRange'][$id]);
// Check end:
$_POST['range_end_'.$id] = trim($_POST['range_end_'.$id]);
if (!check_ip($_POST['range_end_'.$id])) {
$errorOccured = true;
}
$this->ranges[$id]['range_end'] = $_POST['range_end_'.$id];
// Check if ip overlaped:
if(!$this->overlaped_range($_POST['range_start_'.$id],$_POST['range_end_'.$id])) {
$errorOccured = true;
}
// Check if Subnet and range first are valid:
if (!range::check_subnet_range($_POST['range_start_'.$id], $subnet, $mask)) {
$errorOccured = true;
}
// Check if Subnet and range last are valid:
if (!range::check_subnet_range($_POST['range_end_'.$id], $subnet, $mask)) {
$errorOccured = true;
}
// Check if Range is valid
if (!$this->check_range($_POST['range_start_'.$id],$_POST['range_end_'.$id])) {
$errorOccured = true;
}
// Check, if range_start and range_end are ok!
if (!$errorOccured) {
$this->attributes['dhcpRange'][$id] = $_POST['range_start_'.$id]." ".$_POST['range_end_'.$id];
}
else {
$mask = $this->getAccountContainer()->getAccountModule('dhcp_settings')->getDHCPOption('subnet-mask');
// Check range_start:
$_POST['range_start_'.$id] = trim($_POST['range_start_'.$id]);
if (!check_ip($_POST['range_start_'.$id])) {
$this->ranges[$id]['range_start'] = $_POST['range_start_'.$id];
$was_a_error = true;
}
else
{
$this->ranges[$id]['range_start'] = $_POST['range_start_'.$id];
}
unset($this->attributes['dhcpRange'][$id]);
}
}
}
}
// Check end:
$_POST['range_end_'.$id] = trim($_POST['range_end_'.$id]);
if (!check_ip($_POST['range_end_'.$id])) {
$this->ranges[$id]['range_end'] = $_POST['range_end_'.$id];
$was_a_error = true;
}
else
{
$this->ranges[$id]['range_end'] = $_POST['range_end_'.$id];
}
// Check if ip overlaped:
if(!$this->overlaped_range($_POST['range_start_'.$id],$_POST['range_end_'.$id])) {
$was_a_error = true;
}
// Check if Subnet and range first are valid:
if (!range::check_subnet_range($_POST['range_start_'.$id],$this->getAccountContainer()->getAccountModule('dhcp_settings')->attributes['cn'][0], $mask)) {
$was_a_error = true;
}
// Check if Subnet and range last are valid:
if (!range::check_subnet_range($_POST['range_end_'.$id],$this->getAccountContainer()->getAccountModule('dhcp_settings')->attributes['cn'][0], $mask)) {
$was_a_error = true;
}
// Check if Range is valid
if (!$this->check_range($_POST['range_start_'.$id],$_POST['range_end_'.$id])) {
$was_a_error = true;
}
// Check, if range_start and range_end are ok!
if (!$was_a_error) {
$this->attributes['dhcpRange'][$id] = $_POST['range_start_'.$id]." ".$_POST['range_end_'.$id];
}
else {
unset($this->attributes['dhcpRange'][$id]);
}
// Add new Range
if(isset($_POST['add_range'])) {
// Check, if there where no errors:
if ($errorOccured) {
$errors[] = $this->messages['add_range'][0];
}
else
{
// Add Range:
$this->ranges[] = array('range_start'=>'','range_end'=>'');
}
}
// update pool data
foreach ($this->poolsNew as $index => $pool) {
// delete pool
if (isset($_POST['del_pool_' . $index])) {
unset($this->poolsNew[$index]);
continue;
}
// name
$this->poolsNew[$index]['cn'][0] = trim($_POST['pool_cn_' . $index]);
if (empty($this->poolsNew[$index]['cn'][0])) {
$errors[] = $this->messages['pool_cn'][0];
}
// failover peer
$peer = trim($_POST['pool_peer_' . $index]);
if (!empty($this->poolsNew[$index]['dhcpstatements'])) {
// remove old peer setting
foreach ($this->poolsNew[$index]['dhcpstatements'] as $indexS => $stmt) {
if (strpos($stmt, 'failover peer "') === 0) {
unset($this->poolsNew[$index]['dhcpstatements'][$indexS]);
break;
}
}
}
// Check if there was a error:
if ($was_a_error) {
$errors[] = $this->messages['range_errors'][0];
if (!empty($peer)) {
$this->poolsNew[$index]['dhcpstatements'][] = 'failover peer "' . $peer . '"';
}
// Add new Range
if(isset($_POST['add_range'])) {
// Check, if there where no errors:
if ($was_a_error) {
$errors[] = $this->messages['add_range'][0];
}
else
{
// Add Range:
$this->ranges[] = array('range_start'=>'','range_end'=>'');
if (!empty($this->poolsNew[$index]['dhcprange'])) {
foreach ($this->poolsNew[$index]['dhcprange'] as $rIndex => $range) {
// delete pool range
if (isset($_POST['drop_poolrange_' . $index . '_' . $rIndex])) {
unset($this->poolsNew[$index]['dhcprange'][$rIndex]);
continue;
}
$from = trim($_POST['pool_from_' . $index . '_' . $rIndex]);
$to = trim($_POST['pool_to_' . $index . '_' . $rIndex]);
if (empty($from) && empty($to)) {
unset($this->poolsNew[$index]['dhcprange'][$rIndex]);
}
else {
$this->poolsNew[$index]['dhcprange'][$rIndex] = $from . ' ' . $to;
// check ranges
if (!check_ip($from) || !check_ip($to)) {
$errorOccured = true;
}
elseif (!$this->overlaped_range($from, $to)) {
$errorOccured = true;
}
elseif (!range::check_subnet_range($from, $subnet, $mask) || !range::check_subnet_range($to, $subnet, $mask)) {
$errorOccured = true;
}
elseif (!$this->check_range($from, $to)) {
$errorOccured = true;
}
}
}
}
$this->processed = true;
// check if at least one range is still set
if (empty($this->poolsNew[$index]['dhcprange'])) {
$error = $this->messages['pool_range'][0];
$error[] = array(htmlspecialchars($this->poolsNew[$index]['cn'][0]));
$errors[] = $error;
}
// add pool range
if (isset($_POST['add_poolrange_' . $index])) {
$this->poolsNew[$index]['dhcprange'][] = '';
}
}
// add a new pool
if (isset($_POST['add_pool'])) {
$this->poolsNew[] = array(
'objectclass' => array('dhcpPool'),
'dhcprange' => array('')
);
}
// Check if there was a error:
if ($errorOccured) {
$errors[] = $this->messages['range_errors'][0];
}
$this->processed = true;
return $errors;
}
/**
* Returns the HTML meta data for the main account page.
*
@ -400,66 +487,257 @@ class range extends baseModule {
$return = new htmlTable();
if ($this->getAccountContainer()->getAccountModule('dhcp_settings')->attributes['cn'][0]=="") {
$return->addElement(new htmlStatusMessage('INFO', _("Please fill out the DHCP settings first.")));
return $return;
}
else {
// If $ranges is not a array, then create it
if (!is_array($this->ranges)) {
$this->ranges = array();
}
$this->reset_overlaped_range();
$mask = $this->getAccountContainer()->getAccountModule('dhcp_settings')->getDHCPOption('subnet-mask');
foreach($this->ranges AS $id=>$arr) {
// Range start
$error = "";
if (isset($this->ranges[$id]['range_start']) && !empty($this->ranges[$id]['range_start'])) {
if ($this->processed && !check_ip($this->ranges[$id]['range_start'])) {
$error = _("The IP address is invalid.");
} elseif($this->processed && !$this->check_range($this->ranges[$id]['range_start'],$this->ranges[$id]['range_end'])) {
$error = _("The range end needs to be greater than the range start.");
} elseif ($this->processed && !range::check_subnet_range($this->ranges[$id]['range_start'],$this->getAccountContainer()->getAccountModule('dhcp_settings')->attributes['cn'][0], $mask)) {
$error = _("The IP does not match the subnet.");
} elseif ($this->processed && !$this->overlaped_range($this->ranges[$id]['range_start'],$this->ranges[$id]['range_end']) ) {
$error = _("The range conflicts with another range.");
}
// If $ranges is not a array, then create it
if (!is_array($this->ranges)) {
$this->ranges = array();
}
$this->reset_overlaped_range();
$mask = $this->getAccountContainer()->getAccountModule('dhcp_settings')->getDHCPOption('subnet-mask');
$subnet = $this->getAccountContainer()->getAccountModule('dhcp_settings')->attributes['cn'][0];
foreach($this->ranges AS $id=>$arr) {
// Range start
$error = "";
if (isset($this->ranges[$id]['range_start']) && !empty($this->ranges[$id]['range_start'])) {
if ($this->processed && !check_ip($this->ranges[$id]['range_start'])) {
$error = _("The IP address is invalid.");
} elseif($this->processed && !$this->check_range($this->ranges[$id]['range_start'],$this->ranges[$id]['range_end'])) {
$error = _("The range end needs to be greater than the range start.");
} elseif ($this->processed && !range::check_subnet_range($this->ranges[$id]['range_start'], $subnet, $mask)) {
$error = _("The IP does not match the subnet.");
} elseif ($this->processed && !$this->overlaped_range($this->ranges[$id]['range_start'],$this->ranges[$id]['range_end']) ) {
$error = _("The range conflicts with another range.");
}
$fromInput = new htmlTableExtendedInputField(_('Range from'), 'range_start_'.$id, $this->ranges[$id]['range_start'], 'range_from');
$fromInput->setRequired(true);
$return->addElement($fromInput);
$return->addElement(new htmlOutputText($error), true);
// Range end
$error = "";
if (isset($this->ranges[$id]['range_end']) && !empty($this->ranges[$id]['range_end'])) {
if ($this->processed && !check_ip($this->ranges[$id]['range_end'])) {
$error = _("The IP address is invalid.");
} elseif ($this->processed && !range::check_subnet_range($this->ranges[$id]['range_end'],$this->getAccountContainer()->getAccountModule('dhcp_settings')->attributes['cn'][0], $mask)) {
$error = _("The IP does not match the subnet.");
}
}
$toInput = new htmlTableExtendedInputField(_('Range to'), 'range_end_'.$id, $this->ranges[$id]['range_end'], 'range_to');
$toInput->setRequired(true);
$return->addElement($toInput);
$return->addElement(new htmlOutputText($error), true);
// Drop range:
$dropButton = new htmlButton('drop_range_'.$id, _('Delete range'));
$dropButton->colspan = 2;
$return->addElement($dropButton);
$return->addElement(new htmlHelpLink('drop_range'), true);
$return->addElement(new htmlSpacer(null, '10px'), true);
}
// add new range
$addButton = new htmlButton('add_range', _('New range'));
$addButton->colspan = 2;
$return->addElement($addButton);
$return->addElement(new htmlHelpLink('add_range'));
$fromInput = new htmlTableExtendedInputField(_('Range from'), 'range_start_'.$id, $this->ranges[$id]['range_start'], 'range_from');
$fromInput->setRequired(true);
$return->addElement($fromInput);
$return->addElement(new htmlOutputText($error), true);
// Range end
$error = "";
if (isset($this->ranges[$id]['range_end']) && !empty($this->ranges[$id]['range_end'])) {
if ($this->processed && !check_ip($this->ranges[$id]['range_end'])) {
$error = _("The IP address is invalid.");
} elseif ($this->processed && !range::check_subnet_range($this->ranges[$id]['range_end'], $subnet, $mask)) {
$error = _("The IP does not match the subnet.");
}
}
$toInput = new htmlTableExtendedInputField(_('Range to'), 'range_end_'.$id, $this->ranges[$id]['range_end'], 'range_to');
$toInput->setRequired(true);
$return->addElement($toInput);
$return->addElement(new htmlOutputText($error), true);
// Drop range:
$dropButton = new htmlButton('drop_range_'.$id, _('Delete range'));
$dropButton->colspan = 2;
$dropButton->setIconClass('deleteButton');
$return->addElement($dropButton);
$return->addElement(new htmlHelpLink('drop_range'), true);
$return->addElement(new htmlSpacer(null, '10px'), true);
}
// add new range
$addButton = new htmlButton('add_range', _('New range'));
$addButton->setIconClass('createButton');
$addButton->colspan = 2;
$return->addElement($addButton);
$return->addElement(new htmlHelpLink('add_range'), true);
// pools
if (!empty($this->poolsNew)) {
$return->addElement(new htmlSubTitle(_('Pools')), true);
foreach ($this->poolsNew as $index => $poolAttrs) {
$cn = !empty($poolAttrs['cn'][0]) ? $poolAttrs['cn'][0] : '';
$nameField = new htmlTableExtendedInputField(_('Name'), 'pool_cn_' . $index, $cn, 'poolName');
$nameField->setRequired(true);
$return->addElement($nameField);
$delPoolButton = new htmlButton('del_pool_' . $index, _('Delete pool'));
$delPoolButton->setIconClass('trashButton');
$return->addElement($delPoolButton, true);
$peer = '';
if (!empty($poolAttrs['dhcpstatements'])) {
foreach ($poolAttrs['dhcpstatements'] as $statement) {
if (strpos($statement, 'failover peer "') === 0) {
$peer = substr($statement, strlen('failover peer "'), -1);
}
}
}
$return->addElement(new htmlTableExtendedInputField(_('Failover peer'), 'pool_peer_' . $index, $peer, 'poolPeer'), true);
$return->addVerticalSpace('10px');
if (!empty($poolAttrs['dhcprange'])) {
foreach ($poolAttrs['dhcprange'] as $rIndex => $range) {
$range = explode(' ', $range);
$from = !empty($range[0]) ? $range[0] : '';
$to = !empty($range[1]) ? $range[1] : '';
$fromInput = new htmlTableExtendedInputField(_('Range from'), 'pool_from_' . $index . '_' . $rIndex, $from, 'range_from');
$fromInput->setRequired(true);
$toInput = new htmlTableExtendedInputField(_('Range to'), 'pool_to_' . $index . '_' . $rIndex, $to, 'range_to');
$toInput->setRequired(true);
$return->addElement($fromInput);
$message = '';
if (!empty($from) && $this->processed) {
if (!check_ip($from)) {
$message = _("The IP address is invalid.");
}
elseif (!$this->check_range($from, $to)) {
$message = _("The range end needs to be greater than the range start.");
}
elseif (!range::check_subnet_range($from, $subnet, $mask)) {
$message = _("The IP does not match the subnet.");
}
elseif (!$this->overlaped_range($from, $to)) {
$message = _("The range conflicts with another range.");
}
}
$return->addElement(new htmlOutputText($message), true);
$return->addElement($toInput);
$message = '';
if (!empty($to) && $this->processed) {
if (!check_ip($to)) {
$message = _("The IP address is invalid.");
}
elseif (!range::check_subnet_range($to, $subnet, $mask)) {
$message = _("The IP does not match the subnet.");
}
}
$return->addElement(new htmlOutputText($message), true);
// drop range
$dropButton = new htmlButton('drop_poolrange_' . $index . '_' . $rIndex, _('Delete range'));
$dropButton->colspan = 2;
$dropButton->setIconClass('deleteButton');
$return->addElement($dropButton);
$return->addElement(new htmlHelpLink('drop_range'), true);
$return->addElement(new htmlSpacer(null, '10px'), true);
}
}
// add new range
$newButton = new htmlButton('add_poolrange_' . $index, _('New range'));
$newButton->colspan = 2;
$newButton->setIconClass('createButton');
$return->addElement($newButton);
$return->addElement(new htmlHelpLink('add_range'), true);
$return->addVerticalSpace('20px');
}
$return->addVerticalSpace('20px');
}
// add new range pool
$addButton = new htmlButton('add_pool', _('New pool'));
$addButton->setIconClass('createButton');
$addButton->colspan = 2;
$return->addElement($addButton);
$return->addElement(new htmlHelpLink('add_pool'), true);
return $return;
}
/**
* Allows the module to run commands after the LDAP entry is changed or created.
*
* Calling this method requires the existence of an enclosing {@link accountContainer}.
*
* @param boolean $newAccount new account
* @param array $attributes LDAP attributes of this entry
* @return array array which contains status messages. Each entry is an array containing the status message parameters.
*/
public function postModifyActions($newAccount, $attributes) {
$errors = array();
// update pool data
// add new pools
foreach ($this->poolsNew as $pool) {
$found = false;
foreach ($this->poolsOrig as $poolOrig) {
if ($pool['cn'][0] == $poolOrig['cn'][0]) {
$found = true;
break;
}
}
if (!$found) {
// create new pool
$dn = 'cn=' . $pool['cn'][0] . ',' . $this->getAccountContainer()->finalDN;
if (isset($pool['dn'])) {
unset($pool['dn']);
}
$success = @ldap_add($_SESSION['ldap']->server(), $dn, $pool);
if (!$success) {
$msg = sprintf(_('Was unable to create DN: %s.'), $dn);
logNewMessage(LOG_ERR, $msg . getDefaultLDAPErrorString($_SESSION['ldap']->server()));
$errors[] = array('ERROR', $msg, getDefaultLDAPErrorString($_SESSION['ldap']->server()));
}
}
}
// update existing pools
foreach ($this->poolsNew as $pool) {
foreach ($this->poolsOrig as $poolOrig) {
if ($pool['cn'][0] == $poolOrig['cn'][0]) {
// check for changes
$mod = array();
// check attributes
$attrs = array('dhcpstatements', 'dhcprange');
foreach ($attrs as $attr) {
$changed = false;
if (empty($pool[$attr]) && empty($poolOrig[$attr])) {
continue;
}
if ((!empty($pool[$attr]) && empty($poolOrig[$attr]))
|| (empty($pool[$attr]) && !empty($poolOrig[$attr]))
|| (sizeof($pool[$attr]) != sizeof($poolOrig[$attr]))) {
$changed = true;
}
else {
sort($pool[$attr]);
sort($poolOrig[$attr]);
foreach ($pool[$attr] as $index => $val) {
if ($val != $poolOrig[$attr][$index]) {
$changed = true;
}
}
}
if ($changed && isset($pool[$attr])) {
$mod[$attr] = $pool[$attr];
}
elseif ($changed) {
$mod[$attr] = array();
}
}
if (!empty($mod)) {
$dn = 'cn=' . $pool['cn'][0] . ',' . $this->getAccountContainer()->finalDN;
$success = @ldap_modify($_SESSION['ldap']->server(), $dn, $mod);
if (!$success) {
$msg = sprintf(_('Was unable to modify attributes of DN: %s.'), $dn);
logNewMessage(LOG_ERR, $msg . getDefaultLDAPErrorString($_SESSION['ldap']->server()));
$errors[] = array('ERROR', $msg, getDefaultLDAPErrorString($_SESSION['ldap']->server()));
}
}
break;
}
}
}
// delete obsolete pools
foreach ($this->poolsOrig as $poolOrig) {
$found = false;
foreach ($this->poolsNew as $pool) {
if ($poolOrig['cn'][0] == $pool['cn'][0]) {
$found = true;
break;
}
}
if (!$found) {
// delete pool
$dn = 'cn=' . $poolOrig['cn'][0] . ',' . $this->getAccountContainer()->finalDN;
$success = @ldap_delete($_SESSION['ldap']->server(), $dn);
if (!$success) {
$msg = sprintf(_('Was unable to delete DN: %s.'), $dn);
logNewMessage(LOG_ERR, $msg . getDefaultLDAPErrorString($_SESSION['ldap']->server()));
$errors[] = array('ERROR', $msg, getDefaultLDAPErrorString($_SESSION['ldap']->server()));
}
}
}
return $errors;
}
/**
* Returns a list of modifications which have to be made to the LDAP account.
*
@ -502,6 +780,20 @@ class range extends baseModule {
return $return;
}
/**
* Loads the list of pools from LDAP.
*/
private function loadPools() {
$dn = $this->getAccountContainer()->dn_orig;
$this->poolsOrig = searchLDAP($dn, '(objectclass=dhcpPool)', array('*'));
foreach ($this->poolsOrig as &$pool) {
if (!empty($pool['dhcprange'])) {
sort($pool['dhcprange']);
}
}
$this->poolsNew = $this->poolsOrig;
}
}
?>

View File

@ -238,6 +238,18 @@ class lamDHCPList extends lamList {
$ranges[] = "<tr><td>".$ex[0]."</td><td width=\"20\"><center>-</center></td><td>".$ex[1]."</td></tr>";
}
}
$pooledRanges = searchLDAP($entry['dn'], '(objectclass=dhcpPool)', array('dhcprange'));
foreach ($pooledRanges as $pool) {
if (empty($pool['dhcprange'])) {
continue;
}
foreach($pool['dhcprange'] AS $id => $value) {
if (!empty($value) && !is_numeric($value)) {
$ex = explode(" ", $value);
$ranges[] = "<tr><td>".$ex[0]."</td><td width=\"20\"><center>-</center></td><td>".$ex[1]."</td></tr>";
}
}
}
natcasesort($ranges);
echo implode('', $ranges);
echo"</table>";

View File

@ -216,6 +216,11 @@ table.collapse {
background-position: 0px 0px !important;
}
.trashButton {
background-image: url(../graphics/trash.png) !important;
background-position: 0px 0px !important;
}
.smallPadding span {
padding: 0.1em 0.4em !important;
}