1 <?php
2 /*
3 * This code is part of GOsa (http://www.gosa-project.org)
4 * Copyright (C) 2003-2008 GONICUS GmbH
5 *
6 * ID: $$Id$$
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
23 class termDNS extends plugin
24 {
25 /* attribute list for save action */
26 var $ignore_account = true;
28 /* Basic informations
29 */
30 var $attributes = array("ipHostNumber","macAddress");
31 var $objectclasses = array("whatever");
33 var $ipHostNumber = ""; // IP address
34 var $additionalHostNumbers = array();
35 var $macAddress = ""; // Mac address
37 // Used in manufacturer detection
38 var $last_macAddress = "";
39 var $manufacturer = "";
41 var $orig_ipHostNumber = ""; // IP address
42 var $orig_macAddress = ""; // Mac address
44 var $cn = ""; // CN of currently edited device
45 var $OrigCn = ""; // Initial cn
46 var $IPisMust = false;
47 var $MACisMust = false;
48 var $dialog = false;
50 /* DCHP Attributes
51 */
52 var $dhcpAttributes = array("dhcpParentNode");
53 var $dhcpEnabled = FALSE;
54 var $dhcp_is_Account = FALSE;
55 var $dhcpParentNodes = array();
56 var $dhcpParentNode = "";
57 var $dhcpHostEntry = array();
58 var $initial_dhcpParentNode = "";
59 var $initial_dhcpHostEntry = array();
60 var $initial_dhcp_is_Account = FALSE;
62 var $used_ip_mac = array();
64 /* DNS attributes
65 */
66 var $DNSattributes = array("zoneName","dNSTTL");
67 var $DNS_is_account = false;
68 var $initially_was_account = false;
69 var $dnsEntry = array();
70 var $DNSenabled = false;
71 var $hide_dns_check_box = FALSE;
72 var $namingAttr = "cn";
74 /* Terminal dns
75 */
76 function termDNS (&$config, $parent,$objectClasses,$IPisMust = false,$namingAttr = "cn")
77 {
78 /* We need to know which objectClasses are used, to store the ip/mac
79 * Because of different type of devices
80 */
81 $this->parent = $parent;
82 $this->objectclasses = $objectClasses;
83 $this->IPisMust = $IPisMust;
84 $this->namingAttr = $namingAttr;
86 plugin::plugin ($config, $parent->dn, $this->parent);
88 $this->attrs = &$this->parent->attrs;
90 if(isset($this->attrs[$namingAttr][0])){
91 $this->OrigCn = preg_replace("/\\\$\$/","",$this->attrs[$namingAttr][0]);
92 $this->cn = preg_replace("/\\\$\$/","",$this->attrs[$namingAttr][0]);
93 }
95 /* Create list of additional ipHostNumber.
96 */
97 $this->additionalHostNumbers = array();
98 if(isset($this->attrs['ipHostNumber']) && $this->attrs['ipHostNumber']['count'] > 1){
99 for($i = 1 ; $i < $this->attrs['ipHostNumber']['count']; $i ++){
100 $this->additionalHostNumbers[] = $this->attrs['ipHostNumber'][$i];
101 }
102 }
104 /************
105 * DHCP
106 ************/
108 /* Hide all dhcp specific code, if dhcp plugin is not present in config */
109 $this->dhcpEnabled = FALSE;
110 if($this->config->pluginEnabled("servdhcp")){
111 $this->dhcpEnabled = TRUE;
112 }
114 if(!class_available("dhcpHost")){
115 $this->dhcpEnabled = FALSE;
116 }
118 if($this->dhcpEnabled){
119 $this->dhcpParentNodes = $this->get_dhcp_parent_nodes();
120 $this->dhcpParentNode = $this->get_dhcp_parent_node();
121 if($this->dhcpParentNode){
122 $this->dhcp_is_Account = TRUE;
123 $this->initial_dhcp_is_Account = TRUE;
124 $this->dhcpHostEntry = $this->get_dhcp_host_entry();
125 }
126 $this->initial_dhcpHostEntry = $this->dhcpHostEntry;
127 $this->initial_dhcpParentNode= $this->dhcpParentNode;
128 }
131 /************
132 * DNS
133 ************/
135 /* Hide all dns specific code, if dns is not available
136 */
137 $DNSenabled = false;
138 foreach($this->config->data['TABS']['SERVERSERVICE'] as $tab){
139 if(preg_match("/^servdns$/",$tab['CLASS'])){
140 $this->DNSenabled = true;
141 }
142 }
144 if(!class_available("DNS")){
145 $this->DNSenabled = FALSE;
146 }
148 if(!$this->DNSenabled){
149 $this->DNS_is_account = false;
150 return;
151 }
153 if($this->DNSenabled){
155 /* Get Zones
156 */
157 $this->Zones = DNS::getAvailableZones($config);
159 /* Get Entry
160 */
161 $this->dnsEntry = DNS::getDNSHostEntries($config,$this->OrigCn);
163 $ptr = DNS::FlipIp($this->get_pTRRecord());
165 /* Remove A record which equals $this->ipHostNumber
166 */
167 foreach($this->dnsEntry['RECORDS'] as $key => $rec){
168 if(($rec['type'] == "aRecord") && ($rec['value'] == $this->ipHostNumber)){
169 unset($this->dnsEntry['RECORDS'][$key]);
170 }
171 if(($rec['type'] == "pTRRecord") && ($rec['value'] == $ptr)){
172 unset($this->dnsEntry['RECORDS'][$key]);
173 }
174 }
176 /* Get Record types
177 */
178 $this->RecordTypes = DNS::getDnsRecordTypes();
180 /* If there is at least one entry in this -> types, we have DNS enabled
181 */
182 if($this->dnsEntry['exists']){
183 $this->DNS_is_account = true;
184 }else{
185 $this->DNS_is_account = false;
186 }
187 }
189 /* Create a list of used mac and ip addresses.
191 ! We use this optically huge amount of code to fetch all
192 Mac and IP addresses, because a simple search for mac and IP
193 over the whole ldap server was 10 to 20 times slower.
194 */
195 $deps = array();
196 $ou = preg_replace("/,.*$/","",get_ou("systemManagement", "systemRDN"));
197 $a_ous = array(get_ou("servgeneric", "serverRDN"),
198 get_ou("termgeneric", "terminalRDN"),
199 get_ou("workgeneric", "workstationRDN"),
200 get_ou("printgeneric", "printerRDN"),
201 get_ou("phoneGeneric", "phoneRDN"),
202 get_ou("componentGeneric", "componentRDN"));
204 $ldap = $this->config->get_ldap_link();
205 $ldap->cd($this->config->current['BASE']);
206 $ldap->search("(&(objectClass=organizationalUnit)(".$ou."))",array("dn"));
207 while($attrs = $ldap->fetch()){
208 foreach($a_ous as $allowed){
209 $deps[] = $allowed.$attrs['dn'];
210 }
211 }
213 foreach($deps as $dep){
214 $ldap->cd($dep);
215 $ldap->search("(|(macAddress=*)(ipHostNumber=*))",array("macAddress","ipHostNumber"));
216 while($attrs = $ldap->fetch()){
217 if(isset($attrs['ipHostNumber'][0])){
218 $this->used_ip_mac["ip:".$attrs['ipHostNumber'][0]] = "ip:".$attrs['ipHostNumber'][0];
219 }
220 if(isset($attrs['macAddress'][0])){
221 $this->used_ip_mac["mac:".$attrs['macAddress'][0]] = "mac:".$attrs['macAddress'][0];
222 }
223 }
224 }
226 /* Save initial ip and mac values, to be able
227 check if the used values are already in use */
228 $this->orig_ipHostNumber = $this->ipHostNumber;
229 $this->orig_macAddress = $this->macAddress;
231 /* Store initally account settings
232 */
233 $this->initially_was_account = $this->DNS_is_account;
235 if($this->DNS_is_account){
236 new log("view","unknown/".get_class($this),$this->dn);
237 }
238 }
241 function netmaskIsCoherent($idZone)
242 {
243 $netmask = DNS::FlipIp(str_replace(".in-addr.arpa.","",DNS::getNameFromMix($idZone)));
244 if(!strstr($this->ipHostNumber, $netmask)){
245 return false;
246 }else{
247 return true;
248 }
249 }
252 function getVarsForSaving($attrs)
253 {
254 foreach($this->attributes as $attr){
255 if(!empty($this->$attr)){
256 $attrs[$attr] = $this->$attr;
257 }
258 }
259 return($attrs);
260 }
262 function execute()
263 {
264 plugin::execute();
266 /* Call parent execute */
267 $smarty= get_smarty();
268 $smarty->assign("autonetACL",$this->acl_is_writeable("macAddress") && $this->acl_is_writeable("ipHostNumber")?"rw":"");
270 $tmp = $this->plInfo();
271 foreach($tmp['plProvidedAcls'] as $name => $translation){
272 $smarty->assign($name."ACL",$this->getacl($name));
273 }
275 $display= "";
277 /**********
278 * Additional ipHostNumber handling
279 **********/
281 /* Add a new one */
282 if($this->acl_is_writeable("ipHostNumber")){
283 foreach($_POST as $name => $value){
284 if(preg_match("/^additionalHostNumbers_add/",$name)){
285 $this->additionalHostNumbers[] = "";
286 break;
287 }
289 /* Delete given entry */
290 if(preg_match("/^additionalHostNumbers_del_/",$name)){
291 $id = preg_replace("/^^additionalHostNumbers_del_([0-9]*)$/","\\1",$name);
292 if(isset($this->additionalHostNumbers[$id])){
293 unset($this->additionalHostNumbers[$id]);
294 $this->additionalHostNumbers = array_values($this->additionalHostNumbers);
295 }
296 break;
297 }
298 }
299 }
301 $smarty->assign("additionalHostNumbers",$this->additionalHostNumbers);
302 $smarty->assign("MACisMust",$this->MACisMust);
304 /**********
305 * Autonet completion
306 **********/
308 /* Check for autonet button */
309 if (isset($_POST['autonet']) && ($this->acl_is_writeable("ipHostNumber") || $this->acl_is_writeable("macAddress"))){
311 if ($this->config->get_cfg_value("core","gosaRpcServer") != ""){
312 $rpc = $this->config->getRpcHandle();
313 $res = $rpc->networkCompletion($this->cn);
314 if(!$rpc->success()){
315 msg_dialog::display(_("Error"), msgPool::rpcError($rpc->get_error()), ERROR_DIALOG);
316 }else{
317 if(isset($res['ip']) && tests::is_ip($res['ip'])) $this->ipHostNumber= $res['ip'];
318 if(isset($res['mac']) && tests::is_mac($res['mac'])) $this->macAddress= $res['mac'];
319 }
320 }elseif ($this->config->get_cfg_value("core","gosaSupportURI") != ""){
322 $d= new gosaSupportDaemon(TRUE, 0.5);
323 $res= $d->_send("<xml><header>gosa_network_completition</header>".
324 "<source>GOSA</source><target>GOSA</target><hostname>".$this->cn."</hostname></xml>", TRUE);
325 if (isset($res['XML']['IP']) && $this->acl_is_writeable("ipHostNumber")){
326 $this->ipHostNumber= $res['XML']['IP'];
327 }
328 if (isset($res['XML']['MAC']) && $this->acl_is_writeable("macAddress")){
329 $this->macAddress= $res['XML']['MAC'];
330 }
331 }
332 }
335 /**********
336 * DHCP Handling
337 **********/
339 if(isset($_POST['dhcpEditOptions']) && $this->acl_is_readable("dhcpSetup")){
340 if(count($this->dhcpHostEntry) == 0){
341 $this->dialog = new dhcpHost($this->parent,$this->dhcpParentNode,TRUE);
342 }else{
343 $this->dialog = new dhcpHost($this->parent,$this->dhcpHostEntry,TRUE);
344 }
345 $this->dialog->cn = $this->cn;
346 $this->dialog->read_only = !$this->acl_is_writeable("dhcpSetup");
347 $this->dialog->dhcpHWAddress = "ethernet ".$this->macAddress;
348 if(!empty($this->ipHostNumber)){
349 $this->dialog->statements->set('fixed-address', $this->ipHostNumber);
350 }
351 }
353 if(isset($_POST['cancel_dhcp'])){
354 $this->dialog = FALSE;
355 }
357 if(isset($_POST['save_dhcp']) && $this->acl_is_writeable("dhcpSetup") && is_object($this->dialog)){
358 $this->dialog->save_object();
359 $msgs = $this->dialog->check(array());
360 if(count($msgs)){
361 foreach($msgs as $msg){
362 msg_dialog::display(_("Error"), $msg, ERROR_DIALOG);
363 }
364 }else{
365 $this->dhcpHostEntry = $this->dialog->save();
366 $this->dialog = FALSE;
367 }
368 }
370 if(is_object($this->dialog)){
371 $this->dialog->save_object();
372 return($this->dialog->execute());
373 }
375 $smarty->assign("dhcpEnabled", $this->dhcpEnabled && $this->acl_is_readable("dhcpSetup"));
376 $smarty->assign("dhcp_is_Account",$this->dhcp_is_Account);
377 $smarty->assign("dhcpParentNode", $this->dhcpParentNode);
378 $smarty->assign("dhcpParentNodes",$this->dhcpParentNodes);
379 $smarty->assign("dhcpParentNodeCnt",count($this->dhcpParentNodes));
381 // Assign network card manufacturer string
382 if ($this->config->get_cfg_value("core","gosaRpcServer") != "" &&
383 $this->macAddress != $this->last_macAddress){
384 $rpc = $this->config->getRpcHandle();
385 $res = $rpc->getMacManufacturer($this->macAddress);
386 if($rpc->success()){
387 $this->manufacturer = $rpc->getMacManufacturer($this->macAddress);
388 }
389 }
390 $smarty->assign("macManufacturer", set_post($this->manufacturer));
392 /**********
393 * DNS Handling
394 **********/
396 /* There is no dns available
397 */
398 $smarty->assign("DNS_is_account",$this->DNS_is_account);
399 $smarty->assign("DNSenabled",$this->DNSenabled && $this->acl_is_readable("dnsSetup"));
401 if($this->DNSenabled == false){
403 /* Is IP address must ? */
404 # $smarty->assign("DNS_is_account",false);
405 $smarty->assign("IPisMust",(($this->IPisMust)||($this->DNS_is_account)));
407 /* Assign smarty all non DNs attributes */
408 foreach($this->attributes as $attr){
409 $smarty->assign($attr,set_post($this->$attr));
410 }
412 $display.= $smarty->fetch(get_template_path('network.tpl', TRUE));
413 }else{
414 # $smarty->assign("DNS_is_account",true);
416 /* Add new empty array to our record list */
417 if(isset($_POST['AddNewRecord']) && $this->acl_is_writeable("dnsSetup")){
418 $this->dnsEntry['RECORDS'][] =array("type"=>"aRecord","value"=>"");
419 }
421 /* propose_ip */
422 if(isset($_POST['propose_ip']) && $this->acl_is_writeable("ipHostNumber")){
423 foreach($this->Zones as $key => $name){
424 if($name == $this->dnsEntry['zoneName']){
425 $net = DNS::FlipIp(str_replace(".in-addr.arpa.","",DNS::getNameFromMix($key)));
426 $this->ipHostNumber = $this->generateRandomIP($net);
427 }
428 }
429 }
431 /* Handle all posts */
432 $only_once =true;
433 if($this->acl_is_writeable("dnsSetup")){
434 foreach($_POST as $name => $value){
436 /* Check if we have to delete a record entry */
437 if((preg_match("/RemoveRecord_/",$name))&&($only_once)) {
439 /* Avoid performing this once again */
440 $only_once = false;
442 /* Extract id for specified entry */
443 $id = preg_replace("/RemoveRecord_/","",$name);
444 $id = preg_replace("/_.*$/","",$id);
446 /* Delete this record, mark edited entries to be able to delete them */
447 if(isset($this->dnsEntry['RECORDS'][$id])){
448 unset($this->dnsEntry['RECORDS'][$id]);
449 }
450 }
451 }
452 }
453 /* Assign smarty all non DNs attributes */
454 foreach($this->attributes as $attr){
455 $smarty->assign($attr,set_post($this->$attr));
456 }
458 /* Assign smarty all DNS attributes */
459 foreach($this->DNSattributes as $attr){
460 $smarty->assign($attr,set_post($this->dnsEntry[$attr]));
461 }
463 /* Assign all needed vars */
464 # $smarty->assign("DNSAccount",$this->DNS_is_account);
465 $smarty->assign("hide_dns_check_box",$this->hide_dns_check_box);
467 $smarty->assign("Zones",$this->Zones);
468 $smarty->assign("ZoneCnt",count($this->Zones));
469 $smarty->assign("ZoneKeys",($this->Zones));
470 $smarty->assign("IPisMust",(($this->IPisMust)||($this->DNS_is_account)));
472 /* Create zone array */
473 $idZones = array();
474 foreach($this->Zones as $id => $zone){
475 if($this->netmaskIsCoherent($id)) {
476 $idZones[$id] = $zone;
477 }else{
478 $idZones[$id] = $zone." ("._("Not matching").")";
479 }
480 }
481 $smarty->assign("Zones",$idZones);
482 $smarty->assign("ZoneKeys", $this->Zones);
484 $tmp = $this->generateRecordsList();
486 $changeStateForRecords = $tmp['changeStateForRecords'];
488 $smarty->assign("records",$tmp['str']);
489 $smarty->assign("changeStateForRecords",$changeStateForRecords);
491 $smarty->assign("autonetACL",$this->acl_is_writeable("macAddress") && $this->acl_is_writeable("ipHostNumber")?"rw":"");
492 $display.= $smarty->fetch(get_template_path('network.tpl', TRUE));
493 }
495 return($display);
496 }
499 function remove_from_parent()
500 {
501 if($this->DNS_is_account){
503 $ldap = $this->config->get_ldap_link();
505 $tmp = array();
506 $this->dnsEntry['exists'] = false;
507 $tmp = DNS::getDNSHostEntriesDiff($this->config,$this->OrigCn,$this->dnsEntry,$this->cn);
509 /* Delete dns */
510 foreach($tmp['del'] as $dn => $del){
511 $ldap->cd($dn);
512 $ldap->rmdir_recursive($dn);
513 new log("remove","unknown/".get_class($this),$dn);
514 if (!$ldap->success()){
515 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, LDAP_DEL, get_class()));
516 }
517 }
518 }
519 }
522 /* Save data to object */
523 function save_object()
524 {
526 if(isset($_POST['network_tpl_posted'])){
528 $this->last_macAddress = $this->macAddress;
530 /* Save all posted vars */
531 plugin::save_object();
533 /******
534 Additional IP Host Numbers
535 ******/
537 /* Get posts for all additionally added ipHostNumbers */
538 if($this->acl_is_writeable("ipHostNumber")){
539 foreach($this->additionalHostNumbers as $id => $value){
540 if(isset($_POST['additionalHostNumbers_'.$id])){
541 $this->additionalHostNumbers[$id] = get_post('additionalHostNumbers_'.$id);
542 }
543 }
544 }
547 /******
548 DHCP posts
549 ******/
551 if($this->acl_is_writeable("dhcpSetup") && $this->dhcpEnabled && isset($_POST['network_tpl_posted'])){
552 foreach($this->dhcpAttributes as $attr){
553 if(isset($_POST[$attr])){
554 $this->$attr = get_post($attr);
555 }
556 }
557 if(isset($_POST['dhcp_is_Account'])){
558 $this->dhcp_is_Account = TRUE;
559 }else{
560 $this->dhcp_is_Account = FALSE;
561 }
562 }
564 /* Ge all non dns attributes (IP/MAC)*/
565 foreach($this->attributes as $attr){
566 if(isset($_POST[$attr]) && $this->acl_is_writeable($attr)){
567 $this->$attr = get_post($attr);
568 }
569 }
572 /******
573 DNS posts
574 ******/
576 /* Check if DNS should be enabled / disabled
577 * -skip this, if the dns account is enforced.
578 */
579 if(!$this->hide_dns_check_box){
580 if($this->DNS_is_account && $this->acl_is_writeable("dnsSetup") && !isset($_POST['DNS_is_account'])){
581 $this->DNS_is_account = false;
582 }elseif(!$this->DNS_is_account && $this->acl_is_writeable("dnsSetup") && isset($_POST['DNS_is_account'])){
583 $this->DNS_is_account = true;
584 }
585 }
587 /* Get dns attributes */
588 if(($this->DNSenabled) && (isset($_POST['network_tpl_posted'])) && $this->acl_is_writeable("dnsSetup")){
590 /* Check for posted record changes */
591 if(is_array($this->dnsEntry['RECORDS'])){
592 foreach($this->dnsEntry['RECORDS'] as $key => $value){
594 /* Check if type has changed */
595 if(isset($_POST['RecordTypeSelectedFor_'.$key])){
596 $this->dnsEntry['RECORDS'][$key]['type'] = get_post('RecordTypeSelectedFor_'.$key);
597 }
598 /* Check if value has changed */
599 if(isset($_POST['RecordValue_'.$key])){
600 $this->dnsEntry['RECORDS'][$key]['value'] = get_post('RecordValue_'.$key);
601 }
602 }
603 }
605 /* Get all basic DNS attributes (TTL, Clas ..)*/
606 foreach($this->DNSattributes as $attr){
607 if(isset($_POST[$attr])){
608 $this->dnsEntry[$attr] = get_post($attr);
609 }
610 }
611 }
612 if($this->hide_dns_check_box){
613 $this->DNS_is_account = true;
614 }
615 }
616 }
619 /* Check supplied data */
620 function check()
621 {
622 /* Call common method to give check the hook */
623 $message= plugin::check();
625 /******
626 check additional IP Host Numbers
627 ******/
629 foreach($this->additionalHostNumbers as $id => $value){
630 if(!tests::is_ip($value)){
631 $message[]= msgPool::invalid(sprintf(_("IP address %s"),($id +2)), "", "", "192.168.1.10");
632 }
633 }
636 /* Check if mac and ip are already used */
637 if(!empty($this->ipHostNumber) && $this->DNS_is_account &&
638 $this->ipHostNumber != $this->orig_ipHostNumber &&
639 in_array_strict("ip:".$this->ipHostNumber,$this->used_ip_mac)){
640 $message[]= msgPool::duplicated(_("IP address"));
641 }
642 if(!empty($this->macAddress) && $this->dhcp_is_Account &&
643 $this->macAddress != $this->orig_macAddress &&
644 in_array_strict("mac:".$this->macAddress,$this->used_ip_mac)){
645 $message[]= msgPool::duplicated(_("MAC address"));
646 }
648 /* Check if ip must be given
649 */
650 if(($this->IPisMust)||($this->DNS_is_account)){
651 if (empty($this->ipHostNumber)){
652 $message[]= msgPool::required(_("IP address"));
653 }elseif (!tests::is_ip($this->ipHostNumber)){
654 $message[]= msgPool::invalid(_("IP address"), "", "", "192.168.1.10");
655 }
656 }
658 /* Check if mac is empty
659 */
660 if($this->MACisMust || $this->dhcp_is_Account){
661 if ($this->macAddress == "" ){
662 $message[]= msgPool::required(_("MAC address"));
663 }elseif(!tests::is_mac($this->macAddress)){
664 $message[]= msgPool::invalid(_("MAC address"), "", "", "00:0C:7F:31:33:F1");
665 }
666 }
668 /* only perfrom this checks if this is a valid DNS account */
669 if($this->DNS_is_account){
671 $checkArray = array();
672 $onlyOnce = array();
674 // $onlyOnce['cNAMERecord'] = 0;
675 $tmp = array_flip($this->Zones);
676 $tmp2 = $tmp[$this->dnsEntry['zoneName']];
677 if(!$this->netmaskIsCoherent($tmp2)){ //this->dnsEntry['zoneName'])){
678 $tmp2 = preg_replace("/^.*\//","",$tmp2);
679 $message[] =sprintf(_("The IP address '%s' is not part of the selected reverse zone '%s'!"),$this->ipHostNumber,$tmp2);
680 }
682 /* Walk through all entries and detect duplicates or mismatches
683 */
684 foreach($this->dnsEntry['RECORDS'] as $name => $values){
686 /* Count record values, to detect duplicate entries for a specific record
687 */
688 if(!isset($checkArray[$values['type']][$values['value']])){
689 $checkArray[$values['type']][$values['value']] = 0;
690 }else{
691 $message[] = sprintf(_("Record type '%s' is duplicated!"),$values['type']);
692 }
694 /* Check if given entries in $onlyOnce are used more than once
695 */
696 if(isset($onlyOnce[$values['type']])){
697 $onlyOnce[$values['type']] ++;
698 if($onlyOnce[$values['type']] > 1){
699 $message[] = sprintf(_("Unique record type '%s' is duplicated!"),$values['type']);
700 }
701 }
703 /* Skip txt record ...
704 */
705 if($values['type'] == "tXTRecord") continue;
707 /* Check if there is an aRecord defined which uses the same IP as used in IPhostAddress
708 */
709 if(($values['type'] == "aRecord")&&($values['value'] == $this->ipHostNumber)){
710 #TODO: Where's the problem here?
711 $message[]=sprintf(_("The IP address '%s' will be added as 'A Record', this will be done automatically, please remove the record."),
712 $this->ipHostNumber);
713 }
715 /* only lower-case is allowed in record entries ...
716 */
717 if($values['value'] != strtolower($values['value'])){
718 #TODO: What's in values['value']? Something for a propper message?
719 $message[] = sprintf(_("Only lowercase records are allowed, please check your '%ss'."),$values['type']);
720 }
721 }
722 }
723 return ($message);
724 }
727 /* Save to LDAP */
728 function save()
729 {
730 $ldap= $this->config->get_ldap_link();
732 $dn = $this->parent->dn;
734 /*******************/
735 /* IP-MAC HANDLING */
736 /*******************/
738 /* $dn was posted as parameter */
739 $this->dn = $dn;
741 /* Save DNS setting & ip/Mac*/
742 plugin::save();
744 /* Add all additional ipHostNumbers now
745 */
746 if(!empty($this->ipHostNumber)){
747 $this->attrs['ipHostNumber'] = array($this->ipHostNumber);
748 }
749 foreach($this->additionalHostNumbers as $value){
750 $this->attrs['ipHostNumber'][] = $value;
751 }
753 /* Do not add the objectClass ipHost if no ip address is given */
754 if(!isset($this->attrs['ipHostNumber'])){
755 $this->attrs['objectClass'] = array_remove_entries(array("ipHost"),$this->attrs['objectClass']);
756 }
758 /* Write back to ldap */
759 $ldap->cd($this->dn);
760 $this->cleanup();
761 $ldap->modify ($this->attrs);
763 /****************/
764 /* DHCP HANDLING */
765 /****************/
767 /* New entry */
768 if($this->dhcpEnabled && $this->acl_is_writeable("dhcpSetup")) {
770 if(count($this->dhcpHostEntry) == 0){
771 $this->dialog = new dhcpHost($this->parent,$this->dhcpParentNode,TRUE);
772 $this->dialog->cn = $this->cn;
773 $this->dialog->dhcpHWAddress = "ethernet ".$this->macAddress;
774 if(!empty($this->ipHostNumber)){
775 $this->dialog->statements->set('fixed-address', $this->ipHostNumber);
776 }
777 $this->dialog->execute();
778 $this->dialog->save_object();
779 $this->dhcpHostEntry = $this->dialog->save();
780 if(count($this->dhcpHostEntry['dhcpOption']) == 0){
781 $this->dhcpHostEntry['dhcpOption']= array("host-name ".$this->cn);
782 }
783 }else{
785 // Updated Host-Name entry
786 foreach($this->dhcpHostEntry['dhcpOption'] as $key => $entry){
787 if(preg_match("/^host-name/", $entry)){
788 $this->dhcpHostEntry['dhcpOption'][$key] = "host-name ".$this->cn;
789 break;
790 }
791 }
792 }
794 /* Write mac address to dhcp settings */
795 if($this->dhcp_is_Account){
796 if(!isset($this->dhcpHostEntry['dhcpHWAddress'][0]) ||
797 !preg_match("/ethernet ".$this->macAddress."/",$this->dhcpHostEntry['dhcpHWAddress'][0])){
798 $this->dhcpHostEntry['dhcpHWAddress'] = array("ethernet ".$this->macAddress);
799 $this->dhcpHostEntry['MODIFIED'] = TRUE;
800 }
801 }
803 /* Updated IP host number */
804 if($this->dhcp_is_Account && $this->dhcpHostEntry['dhcpStatements']){
805 foreach($this->dhcpHostEntry['dhcpStatements'] as $id => $value){
806 if(preg_match("/^fixed-address/",$value)){
807 $this->dhcpHostEntry['dhcpStatements'][$id] = "fixed-address ".$this->ipHostNumber;
808 $this->dhcpHostEntry['MODIFIED'] = TRUE;
809 }
810 }
811 }
813 /* Unset dhcpStatements if this attribute is empty */
814 if(isset($this->dhcpHostEntry['dhcpStatements']) &&
815 ($this->dhcpHostEntry['dhcpStatements'] == "" || count($this->dhcpHostEntry['dhcpStatements']) == 0) ){
816 unset($this->dhcpHostEntry['dhcpStatements']);
817 }
819 /* DHCP removed */
820 if($this->initial_dhcp_is_Account && !$this->dhcp_is_Account){
821 $ldap->rmdir_recursive($this->dhcpHostEntry['dn']);
822 if (!$ldap->success()){
823 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dhcpHostEntry['dn'], LDAP_DEL, get_class()));
824 }
826 $tmp = new servdhcp($this->config,$this->dhcpParentNode);
827 $tmp->handle_post_events("remove");
828 }
830 /* DHCP Added */
831 if(!$this->initial_dhcp_is_Account && $this->dhcp_is_Account){
832 $attrs = $this->dhcpHostEntry;
833 unset($attrs['MODIFIED']);
834 unset($attrs['dn']);
835 $ldap->cd("cn=".$this->cn.",".$this->dhcpParentNode);
836 $res = $ldap->add($attrs);
838 $tmp = new servdhcp($this->config,$this->dhcpParentNode);
839 $tmp->handle_post_events("add");
841 if (!$ldap->success()){
842 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), "cn=".$this->cn.",".$this->dhcpParentNode, LDAP_ADD, get_class()));
843 }
844 }
846 /* DHCP still activated */
847 if($this->initial_dhcp_is_Account && $this->dhcp_is_Account){
849 /* DHCP node changed */
850 if(($this->initial_dhcpParentNode != $this->dhcpParentNode) ||
851 ($this->cn != $this->OrigCn)){
852 $attrs = $this->dhcpHostEntry;
853 $attrs[$this->namingAttr] = $this->cn;
854 unset($attrs['dn']);
855 unset($attrs['MODIFIED']);
856 $ldap->cd("cn=".$this->cn.",".$this->dhcpParentNode);
857 $res = $ldap->add($attrs);
859 $tmp = new servdhcp($this->config,$this->dhcpParentNode);
860 $tmp->handle_post_events("modify");
862 if (!$ldap->success()){
863 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), "cn=".$this->cn.",".$this->dhcpParentNode, LDAP_ADD, get_class()));
864 }
865 if($res){
866 $ldap->rmdir_recursive($this->dhcpHostEntry['dn']);
867 if (!$ldap->success()){
868 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dhcpHostEntry['dn'], LDAP_DEL, get_class()));
869 }
870 }
871 }
873 /* SAME node but modified */
874 if(isset($this->dhcpHostEntry['MODIFIED']) && $this->dhcpHostEntry['MODIFIED'] == 1 &&
875 $this->initial_dhcpParentNode == $this->dhcpParentNode){
876 $attrs = $this->dhcpHostEntry;
877 unset($attrs['dn']);
878 unset($attrs['MODIFIED']);
879 $ldap->cd($this->dhcpHostEntry['dn']);
880 $ldap->modify($attrs);
882 $tmp = new servdhcp($this->config,$this->dhcpParentNode);
883 $tmp->handle_post_events("modify");
885 if (!$ldap->success()){
886 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dhcpHostEntry['dn'], LDAP_MOD, get_class()));
887 }
888 }
889 }
890 }
891 $this->dialog = FALSE;
893 /****************/
894 /* DNS HANDLING */
895 /****************/
897 /* If isn't DNS account but initially was DNS account
898 remove all DNS entries
899 */
900 if((!$this->DNSenabled) || ((!$this->DNS_is_account)&&(!$this->initially_was_account))){
901 return;
902 }elseif($this->acl_is_writeable("dnsSetup")){
904 /* Add ipHostNumber to aRecords
905 */
906 $backup_dnsEntry = $this->dnsEntry;
907 if(!empty($this->ipHostNumber)){
908 $this->dnsEntry['RECORDS'][] = array("type"=>"aRecord","value"=>$this->ipHostNumber);
909 $ptr = $this->get_pTRRecord();
910 if(!empty($ptr)){
911 $this->dnsEntry['RECORDS'][] = array("type"=>"pTRRecord","value"=>$ptr);
912 }
913 }
915 /* Create diff and follow instructions
916 * If Account was disabled, remove account by setting exists to false
917 */
918 if((!$this->DNS_is_account)&&($this->initially_was_account)){
919 $this->dnsEntry['exists'] = false;
920 $tmp = DNS::getDNSHostEntriesDiff($this->config,$this->OrigCn,$this->dnsEntry,$this->cn);
921 }else{
922 $this->dnsEntry['exists'] = $this->DNS_is_account;
923 $tmp = DNS::getDNSHostEntriesDiff($this->config,$this->OrigCn,$this->dnsEntry,$this->cn);
924 }
926 /* Update SOA record if needed
927 */
928 $this->updateSOARecord();
930 /* move follwoing entries
931 */
932 foreach($tmp['move'] as $src => $dst){
933 $this->recursive_move($src,$dst);
934 }
936 /* Delete dns */
937 foreach($tmp['del'] as $dn => $del){
938 $ldap->cd($dn);
939 $ldap->rmdir_recursive($dn);
940 new log("modify","unknown/".get_class($this),$dn,array("*"),$ldap->get_error());
941 }
943 /* Add || Update new DNS entries
944 */
945 foreach($tmp['add'] as $dn => $attrs){
946 $ldap->cd($dn);
947 $ldap->cat($dn, array('dn'));
948 if(count($ldap->fetch())){
949 $ldap->cd($dn);
950 $ldap->modify ($attrs);
951 }else{
952 $ldap->cd($dn);
953 $ldap->add($attrs);
954 }
955 new log("modify","unknown/".get_class($this),$dn,array_keys($attrs),$ldap->get_error());
956 }
959 /* Display errors
960 */
961 if (!$ldap->success()){
962 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, 0, get_class()));
963 }
965 $tmp2 = new servdns($this->config,$this->dn);
966 $tmp2->handle_post_events("modify");
968 $this->dnsEntry = $backup_dnsEntry;
969 }
970 }
972 /* Create html table with all used record types
973 */
974 function generateRecordsList()
975 {
976 $changeStateForRecords = "";
977 $str = "<table summary='' width='100%'>";
978 foreach($this->dnsEntry['RECORDS'] as $key => $entry){
980 $changeStateForRecords.= "changeState('RecordTypeSelectedFor_".$key."');\n";
981 $changeStateForRecords.= "changeState('RecordValue_".$key."');\n";
982 $changeStateForRecords.= "changeState('RemoveRecord_".$key."');\n";
984 $str.=" <tr>".
985 " <td>".$this->generateRecordListBox($entry['type'],"RecordTypeSelectedFor_".$key)."</td>".
986 " <td><input type='text' value=\"".htmlentities($entry['value'])."\" name='RecordValue_".$key."' id='RecordValue_".$key."'></td>".
987 " <td><button type='submit' name='RemoveRecord_".$key."' id='RemoveRecord_".$key."'>".msgPool::delButton()."</button>";
988 "</tr>";
989 }
991 $str.= " <tr>".
992 " <td colspan=2 width='50%'></td><td>".
993 " <button type='submit' name='AddNewRecord' id='AddNewRecord'>".msgPool::addButton()."</button>".
994 " </td>".
995 " </tr>".
996 "</table>";
997 $ret = array("str" => $str, "changeStateForRecords" => $changeStateForRecords);
999 return($ret);
1000 }
1003 /* Create a html select box which allows us to select different types of records
1004 */
1005 function generateRecordListBox($selected,$name)
1006 {
1007 $str = "<select name='".$name."' id='".$name."'>";
1008 foreach($this->RecordTypes as $type => $value){
1009 $use = "";
1010 if($type == $selected){
1011 $use = " selected ";
1012 }
1013 $str.="\n <option value='".$type."' ".$use.">".strtoupper(preg_replace("/record/i","",$type))."</option>";
1014 }
1015 $str.="</select>";
1016 return($str);
1017 }
1020 /* Return plugin informations for acl handling */
1021 static function plInfo()
1022 {
1023 $tmp = array(
1024 "plShortName" => _("DNS"),
1025 "plDescription" => _("DNS settings"),
1026 "plSelfModify" => FALSE,
1027 "plDepends" => array(),
1028 "plPriority" => 5,
1029 "plSection" => array("administration"),
1030 "plCategory" => array("workstation","terminal","phone","server","component","printer","winworkstation","opsi"),
1032 "plProvidedAcls"=> array(
1033 "ipHostNumber" => _("IP address"),
1034 "macAddress" => _("MAC address"))
1035 );
1037 /* Hide all dns/dhcp configurations if not available
1038 */
1039 if(class_available("servdns")){
1040 $tmp['plProvidedAcls']["dnsSetup"] = _("DNS configuration");
1041 }
1042 if(class_available("servdhcp")){
1043 $tmp['plProvidedAcls']["dhcpSetup"] = _("DHCP configuration");
1044 }
1045 return($tmp);
1046 }
1049 function get_dhcp_host_entry()
1050 {
1051 $attrs = array();
1052 $dn = $this->get_dhcp_host_entry_dn();
1053 if($dn){
1054 $ldap = $this->config->get_ldap_link();
1055 $ldap->cd($this->config->current['BASE']);
1056 $ldap->cat($dn,array("*"));
1057 if($ldap->count()){
1058 $attrs = $ldap->fetch();
1059 foreach($attrs as $key => $value){
1060 if(is_numeric($key) || ($key == "count")){
1061 unset($attrs[$key]);
1062 }
1063 if(is_array($value) && isset($value['count'])){
1064 unset($attrs[$key]['count']);
1065 }
1066 }
1067 }
1068 }
1069 return($attrs);
1070 }
1073 function get_dhcp_host_entry_dn()
1074 {
1075 $ldap = $this->config->get_ldap_link();
1076 $ldap->cd($this->config->current['BASE']);
1077 $ldap->search ("(&(objectClass=dhcpHost)(cn=".$this->cn."))",array("uid","cn","dn"));
1079 if($ldap->count()){
1080 $attr = $ldap->fetch();
1081 return($attr['dn']);
1082 }else{
1083 return("");
1084 }
1085 }
1088 function get_dhcp_parent_node()
1089 {
1090 return(preg_replace("/^cn=".preg_quote($this->cn, '/').",/","",$this->get_dhcp_host_entry_dn()));
1091 }
1094 function get_dhcp_parent_nodes()
1095 {
1096 $ldap = $this->config->get_ldap_link();
1097 $ldap->cd($this->config->current['BASE']);
1098 $ldap->search("(objectClass=dhcpService)",array("dhcpPrimaryDN"));
1100 $dhcp_dns = array();
1101 while($attr = $ldap->fetch()){
1102 $dhcp_dns[$attr['dn']] = $attr['dhcpPrimaryDN'][0];
1103 }
1105 foreach($dhcp_dns as $key => $pri_dns){
1106 $ldap->cat($pri_dns,array("cn"));
1107 $tmp = $ldap->fetch();
1108 if(isset($tmp['cn'][0])){
1109 $dhcp_dns[$key] = $tmp['cn'][0];
1110 }else{
1111 unset($dhcp_dns[$key]);
1112 }
1113 }
1115 $tmp = $tmp2 = array();
1116 foreach($dhcp_dns as $dn => $cn){
1117 $ldap->cd($dn);
1118 $ldap->search("(|(objectClass=dhcpService)(objectClass=dhcpGroup)".
1119 "(objectClass=dhcpSubnet)(objectClass=dhcpSharedNetwork))",array("cn"));
1120 while($attr = $ldap->fetch()){
1121 $tmp[$attr['dn']] = $attr['cn'][0];
1122 }
1123 $tmp2 = array_merge($tmp2,$this->create_tree($tmp,preg_replace("/^[^,]+,/i","",$dn),"(".$cn.") "));
1124 }
1125 return($tmp2);
1126 }
1129 /* this function returns the default ptr record entry */
1130 function get_pTRRecord()
1131 {
1132 if(!empty($this->ipHostNumber) && isset($this->dnsEntry['zoneName']) && !empty($this->dnsEntry['zoneName'])){
1133 $ldap = $this->config->get_ldap_link();
1134 $ldap->cat(DNS::getDNSZoneDN($this->config,$this->dnsEntry['zoneName']));
1135 $attrs = $ldap->fetch();
1136 $tmp = array_flip($this->Zones);
1137 $tmp = preg_replace("/^[^\/]*+\//","",$tmp[$this->dnsEntry['zoneName']]);
1138 $tmp = trim(preg_replace("/\.in-addr.arpa\.$/","",$tmp));
1139 $ptr = preg_replace("/^".preg_quote(DNS::FlipIp($tmp), '/')."\./","",$this->ipHostNumber);
1140 return($ptr);
1141 }else{
1142 return(FALSE);
1143 }
1144 }
1147 function generateRandomIP($net = "")
1148 {
1149 $str = $net;
1150 $cnt = 4;
1152 // first gather all IPs
1153 $ldap = $this->config->get_ldap_link();
1154 $ocs =
1155 "(objectClass=goFonHardware)".
1156 "(objectClass=goServer)".
1157 "(objectClass=GOhard)".
1158 "(objectClass=gotoTerminal)".
1159 "(objectClass=gotoWorkstation)".
1160 "(objectClass=gotoPrinter)".
1161 "(objectClass=ipHost)";
1162 $list = array();
1163 $ldap->search("(&(|{$ocs})(ipHostNumber=*))",array("ipHostNumber"));
1164 while($attrs = $ldap->fetch()){
1165 if (preg_match("/^$net\./", $attrs['ipHostNumber'][0])) {
1166 $list[] = $attrs['ipHostNumber'][0];
1167 }
1168 }
1170 // Set starting ip.
1171 $ip_data = preg_split("/\./",$net);
1172 for($i=0;$i<4;$i++){
1173 if(!isset($ip_data[$i])) $ip_data[$i] = 0;
1174 }
1176 // Search the next free and valid ip.
1177 while(in_array_strict(implode(".",$ip_data),$list) || $ip_data[3] <= 1){
1178 $ip_data[3] ++ ;
1179 if($ip_data[3] > 255){
1180 $ip_data[3] = 1 ;
1181 $ip_data[2] ++ ;
1182 }
1183 if($ip_data[2] > 255){
1184 $ip_data[2] = 1 ;
1185 $ip_data[1] ++ ;
1186 }
1187 if($ip_data[1] > 255){
1188 $ip_data[1] = 1 ;
1189 $ip_data[0] ++ ;
1190 }
1191 if($ip_data[0] > 255) break;
1192 }
1194 return(implode(".",$ip_data));
1195 }
1198 function create_tree($arr,$base,$current = "")
1199 {
1200 $ret = array();
1201 foreach($arr as $r => $name){
1202 $base_part = str_replace($base,"",$r);
1203 if(preg_match("/^[a-z]*=".preg_quote($name, '/')."(|,)$/i",$base_part)){
1204 $ret[$r] = $current.$name;
1205 $tmp = $this->create_tree($arr,$r,$current.". ");
1206 foreach($tmp as $sub_key => $sub_name){
1207 $ret[$sub_key] = $sub_name;
1208 }
1209 }
1210 }
1211 return($ret);
1212 }
1214 function force_dns()
1215 {
1216 if($this->DNSenabled){
1218 /* Only force DNS account, if we have at least on dns Zone */
1219 if(count($this->Zones)){
1220 $this->DNS_is_account = TRUE;
1221 $this->hide_dns_check_box = TRUE;
1222 }
1223 }
1224 }
1226 function updateSOARecord()
1227 {
1228 $oldEntries = DNS::getDNSHostEntries($this->config,$this->OrigCn);
1229 $newEntries = $this->dnsEntry;
1230 if(array_differs($newEntries['RECORDS'],$oldEntries['RECORDS'])){
1231 DNS::touchDNSZone($this->config,$this->dnsEntry['zoneName']);
1232 }
1233 }
1234 }
1236 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1237 ?>