351e2112c7f993bde1e4d1933a57f94891c64cda
1 <?php
3 class servdhcp extends plugin
4 {
5 /* attribute list for save action */
6 var $attributes= array("dhcpServiceDN");
7 var $objectclasses= array("dhcpServer");
9 var $dhcpServiceDN= "";
11 /* Section storage */
12 var $dhcpSections= array();
13 var $dhcpObjectCache= array();
14 var $current_object= "";
15 var $types= array();
16 var $serviceDN= "";
18 var $quote_option = array("domain-name");
20 var $orig_dn = "";
22 var $dhcp_server_list = array();
23 var $take_over_id = -1;
25 function servdhcp ($config, $dn= NULL, $parent= NULL)
26 {
27 plugin::plugin ($config, $dn, $parent);
29 $this->serviceDN = "cn=dhcp,".$dn;
30 $this->orig_dn = $dn;
32 $this->types= array( "dhcpLog" => _("Logging"),
33 "dhcpService" => _("Global options"),
34 "dhcpClass" => _("Class"),
35 "dhcpSubClass" => _("Subclass"),
36 "dhcpHost" => _("Host"),
37 "dhcpGroup" => _("Group"),
38 "dhcpPool" => _("Pool"),
39 "dhcpSubnet" => _("Subnet"),
40 "dhcpFailOverPeer" => _("Failover peer"),
41 "dhcpSharedNetwork" => _("Shared network"));
44 /* Backport: PHP4 compatibility */
45 foreach($this->types as $type => $translation){
46 $this->types[strtolower($type)] = $translation;
47 }
49 /* Load information about available services */
50 $this->reload();
51 if (!count($this->dhcpSections)){
52 $this->is_account= FALSE;
53 }
55 $this->dhcp_server_list = $this->get_list_of_dhcp_servers();
56 }
59 function take_over_service()
60 {
62 }
65 function get_list_of_dhcp_servers()
66 {
67 $ret = array();
68 $ldap = $this->config->get_ldap_link();
69 $ldap->cd($this->config->current['BASE']);
70 $ldap->search("(&(objectClass=goServer)(dhcpServiceDN=*))",array("dn","cn","dhcpServiceDN"));
71 while($attrs = $ldap->fetch()){
72 $ret['ENTRIES'][] = $attrs;
73 }
74 foreach($ret['ENTRIES'] as $key => $data){
75 $ret['FOR_LIST'][$key] = $data['cn'][0];
76 }
77 return($ret);
78 }
81 function get_dhcp_info_string($id)
82 {
83 $ret = "";
84 $ldap = $this->config->get_ldap_link();
85 $ldap->cd("cn=dhcp,".$this->dhcp_server_list['ENTRIES'][$id]['dn']);
86 $ldap->search("(|(objectClass=dhcpSharedNetwork)(objectClass=dhcpSubnet)(objectClass=dhcpPool)(objectClass=dhcpGroup)(objectClass=dhcpHost))",array("dn","cn"));
87 $ldap->search("(objectClass=*)",array("dn","cn"));
88 while($attrs = $ldap->fetch()){
89 $ret .= $attrs['dn']."\n";
90 }
91 return($ret);
92 }
95 function execute()
96 {
97 /* Call parent execute */
98 plugin::execute();
100 /* Fill templating stuff */
101 $smarty= get_smarty();
102 $smarty->assign("dns_take_over",FALSE);
103 $display= "";
106 /*****************/
107 /* Handle Take Over Actions
108 /*****************/
110 /* Give smarty the required informations */
111 $smarty->assign("dhcp_server_list", $this->dhcp_server_list['FOR_LIST']);
113 /* Take over requested, save id */
114 if(isset($_POST['take_over_src']) && isset($_POST['take_over'])){
115 $id = $_POST['take_over_src'];
116 if(isset($this->dhcp_server_list['ENTRIES'][$id])){
117 $this->take_over_id = $id;
118 }
119 }
121 /* Abort take over action */
122 if(isset($_POST['cancel_take_over'])){
123 $this->dialog =false;
124 $this->take_over_id = -1;
125 $this->dhcp_server_list = $this->get_list_of_dhcp_servers();
126 }
128 /* Display informartion about take over that will be started when saving this server
129 * and hide default dhcp output
130 */
131 if($this->take_over_id != -1){
132 $this->dialog = FALSE;
133 $id = $this->take_over_id;
134 $info = $this->get_dhcp_info_string($id);
135 $smarty->assign("dns_take_over",TRUE);
136 $smarty->assign("info",$info);
137 $warning = sprintf(_("You are going to take over the dhcp setup from server '%s'."),$this->dhcp_server_list['ENTRIES'][$id]['cn'][0]);
138 $warning2 = _("The take over will be startet when you save this system. To abort this action, use the cancel button below.");
139 $smarty->assign("warning",$warning);
140 $smarty->assign("warning2",$warning2);
141 return($smarty->fetch(get_template_path('servdhcp.tpl', TRUE)));
142 }
145 /*****************/
146 /* List handling
147 /*****************/
149 /* Section Creation? */
150 if (isset($_POST['create_section']) && isset($_POST['section'])){
151 $section= $_POST['section'];
152 $tmp = new dhcpNewSectionDialog(NULL);
153 if (isset($tmp->sectionMap[$section])){
154 $this->dialog= new $section($this->current_object);
155 $this->current_object= "";
156 } else {
157 $this->dialog= NULL;
158 }
159 }
161 /* Cancel section creation? */
162 if (isset($_POST['cancel_section']) || isset($_POST['cancel_dhcp'])){
163 $this->dialog= NULL;
164 }
166 /* Save changes */
167 if (isset($_POST['save_dhcp'])){
168 $this->dialog->save_object();
169 $messages= $this->dialog->check($this->dhcpObjectCache);
170 if (count($messages)){
171 show_errors($messages);
172 } else {
173 $dn= $this->dialog->dn;
174 $class= get_class($this->dialog);
175 $type= $this->types[$class];
176 if(empty($this->serviceDN)){
177 $indent= substr_count(preg_replace("/".$this->dn."/", '', $dn), ",") -1;
178 }else{
179 $indent= substr_count(preg_replace("/".$this->serviceDN."/", '', $dn), ",");
180 }
181 $spaces= "";
182 for ($i= 0; $i<$indent; $i++){
183 $spaces.= " ";
184 }
185 $data= $this->dialog->save();
186 if ($this->current_object == ""){
187 /* New object */
188 $newsects= array();
189 foreach ($this->dhcpSections as $key => $dsc){
190 $newsects[$key]= $dsc;
191 if ($key == $dn){
192 $spaces.= " ";
193 $newsects[$data['dn']]= "$spaces$type '".preg_replace('/^[^=]+=([^,]+),.*$/', '\1', $data['dn'])."'";
194 }
195 }
196 $this->dhcpObjectCache[$data['dn']]= $data;
197 $this->dhcpSections= $newsects;
198 } else {
199 if ($dn != $data['dn']){
200 /* Old object, new name */
201 $this->dhcpObjectCache[$dn]= array();
202 $this->dhcpObjectCache[$data['dn']]= $data;
204 /* If we renamed a section, we've to rename a couple of objects, too */
205 foreach ($this->dhcpObjectCache as $key => $dsc){
206 if (preg_match("/,$dn$/", $key)){
207 $new_dn= preg_replace("/,$dn$/", ",".$data['dn'], $key);
208 $dsc['MODIFIED']= TRUE;
209 $this->dhcpObjectCache[$new_dn]= $dsc;
210 unset($this->dhcpObjectCache[$key]);
211 }
212 }
213 $newsects= array();
214 foreach ($this->dhcpSections as $key => $dsc){
215 if ($key == $dn){
216 $newsects[$data['dn']]= "$spaces$type '".preg_replace('/^[^=]+=([^,]+),.*$/', '\1', $data['dn'])."'";
217 continue;
218 }
219 if (preg_match("/,$dn$/", $key)){
220 $new_dn= preg_replace("/,$dn$/", ",".$data['dn'], $key);
221 $newsects[$new_dn]= $dsc;
222 } else {
223 $newsects[$key]= $dsc;
224 }
225 }
226 $this->dhcpSections= $newsects;
228 } else {
229 /* Old object, old name */
230 $this->dhcpObjectCache[$data['dn']]= $data;
231 }
232 }
233 $this->dialog= NULL;
234 }
235 }
237 /* Remove section? */
238 if (isset($_POST['delete_dhcp_confirm'])){
239 if (chkacl($this->acl, "delete") == ""){
240 unset($this->dhcpSections[$this->current_object]);
241 unset($this->dhcpObjectCache[$this->current_object]);
242 $this->dhcpObjectCache[$this->current_object]= array();
243 foreach ($this->dhcpSections as $key => $value){
244 if (preg_match("/".$this->current_object."$/", $key)){
245 unset($this->dhcpSections[$key]);
246 unset($this->dhcpObjectCache[$key]);
247 $this->dhcpObjectCache[$key]= array();
248 }
249 }
250 } else {
251 print_red(_("You're not allowed to remove DHCP sections!"));
252 }
253 $this->dialog= NULL;
254 }
256 /* Look for post entries */
257 foreach($_POST as $name => $value){
259 /* Insert new section? */
260 if (preg_match('/^insertDhcp_.*_x$/', $name)){
261 $dn= base64_decode(preg_replace('/^insertDhcp_([^_]+)_x$/', '\1', $name));
262 if (isset($this->dhcpObjectCache[$dn])){
263 $this->dialog= new dhcpNewSectionDialog($this->objectType($dn));
264 $this->current_object= $dn;
265 $this->dialog->acl= $this->acl;
266 }
267 }
269 /* Edit section? */
270 if (preg_match('/^editDhcp_.*_x$/', $name)){
271 $dn= base64_decode(preg_replace('/^editDhcp_([^_]+)_x$/', '\1', $name));
272 if (isset($this->dhcpObjectCache[$dn])){
273 $section= $this->objectType($dn);
274 $this->current_object= $dn;
275 $this->dialog= new $section($this->dhcpObjectCache[$dn]);
276 }
277 }
279 /* Remove section? */
280 if (preg_match('/^delDhcp_.*_x$/', $name)){
281 $dn= base64_decode(preg_replace('/^delDhcp_([^_]+)_x$/', '\1', $name));
282 if (isset($this->dhcpObjectCache[$dn])){
283 $this->current_object= $dn;
284 $this->dialog= 1;
285 $smarty->assign("warning", sprintf(_("You're about to delete the DHCP section '%s'."), $dn));
286 return($smarty->fetch(get_template_path('remove_dhcp.tpl', TRUE)));
287 }
288 }
290 }
292 /* Do we need to flip is_account state? */
293 if (isset($_POST['modify_state'])){
294 $this->is_account= !$this->is_account;
295 }
297 /* Show tab dialog headers */
298 if ($this->is_account){
299 $display= $this->show_header(_("Remove DHCP service"),
300 _("This server has DHCP features enabled. You can disable them by clicking below."));
302 if (!count($this->dhcpObjectCache)){
303 $attrs= array();
304 $attrs['dn']= 'cn=dhcp,'.$this->dn;
305 $attrs['cn']= array('dhcp');
306 $attrs['objectClass']= array('top', 'dhcpService');
307 $attrs['dhcpPrimaryDN']= array($this->dn);
308 $attrs['dhcpStatements']= array("default-lease-time 600",
309 "max-lease-time 1200",
310 "authoritative",
311 "ddns-update-style none");
312 $attrs['MODIFIED']= TRUE;
313 $this->dhcpSections['cn=dhcp,'.$this->dn]= _("Global options");
314 $this->dhcpObjectCache['cn=dhcp,'.$this->dn]= $attrs;
315 }
317 } else {
318 $display= $this->show_header(_("Add DHCP service"),
319 _("This server has DHCP features disabled. You can enable them by clicking below."));
320 return ($display);
321 }
324 /* Show dialog
325 */
326 if($this->dialog != NULL && !is_int($this->dialog)){
327 $this->dialog->save_object();
328 $this->dialog->parent = $this;
329 return($this->dialog->execute());
330 }
332 /* Create Listbox with existing Zones
333 */
334 $DhcpList = new divSelectBox("dhcpSections");
335 $DhcpList->SetHeight(400);
337 /* Add entries to divlist
338 */
339 $editImgIns = "<input type='image' src='images/list_new.png' name='insertDhcp_%s' title='"._("Insert new DHCP section")."'>".
340 "<input type='image' src='images/edit.png' name='editDhcp_%s' title='"._("Edit DHCP section")."'>".
341 "<input type='image' src='images/edittrash.png' name='delDhcp_%s' title='"._("Remove DHCP section")."'>";
342 $editImgInsNoDel = "<input type='image' src='images/list_new.png' name='insertDhcp_%s' title='"._("Insert new DHCP section")."'>".
343 "<input type='image' src='images/edit.png' name='editDhcp_%s' title='"._("Edit DHCP section")."'>";
344 $editImg = "<input type='image' src='images/edit.png' name='editDhcp_%s' title='"._("Edit DHCP section")."'>".
345 "<input type='image' src='images/edittrash.png' name='delDhcp_%s' title='"._("Remove DHCP section")."'>";
347 $tmp = new dhcpNewSectionDialog(NULL);
348 foreach($this->dhcpSections as $section => $values ){
350 if (count($tmp->sectionMap[$this->objectType($section)])){
351 if ($this->objectType($section) == "dhcpService"){
352 $DhcpList->AddEntry(array(
353 array("string" => $values),
354 array("string" => str_replace("%s",base64_encode($section),$editImgInsNoDel), "attach" => "style='text-align:right;'")
355 ));
356 } else {
357 $DhcpList->AddEntry(array(
358 array("string" => $values),
359 array("string" => str_replace("%s",base64_encode($section),$editImgIns), "attach" => "style='text-align:right;'")
360 ));
361 }
362 } else {
363 $DhcpList->AddEntry(array(
364 array("string" => $values),
365 array("string" => str_replace("%s",base64_encode($section),$editImg), "attach" => "style='text-align:right;'")
366 ));
367 }
368 }
370 $smarty->assign("dhcpACL",chkacl($this->acl,"servdhcp"));
372 /* Display tempalte */
373 $smarty->assign("DhcpList",$DhcpList->DrawList());
374 $display.= $smarty->fetch(get_template_path('servdhcp.tpl', TRUE));
375 return($display);
376 }
379 function remove_from_parent()
380 {
381 /* Cancel if there's nothing to do here */
382 if (!$this->initially_was_account){
383 return;
384 }
386 /* Remove subtrees */
387 $ldap= $this->config->get_ldap_link();
388 foreach ($this->dhcpObjectCache as $dn => $content){
389 if ($this->objectType($dn) == 'dhcpService'){
390 $ldap->rmdir_recursive($dn);
391 show_ldap_error($ldap->get_error(), _("Removing DHCP entries failed"));
392 }
393 }
395 /* Remove from self */
396 $ldap= $this->config->get_ldap_link();
398 /* Remove and write to LDAP */
399 plugin::remove_from_parent();
401 @DEBUG (DEBUG_LDAP, __LINE__, __FUNCTION__, __FILE__, $this->attributes, "Save");
402 $ldap->cd($this->dn);
403 $this->cleanup();
404 $ldap->modify ($this->attrs);
406 show_ldap_error($ldap->get_error(), _("Removing DHCP entries failed"));
408 /* Optionally execute a command after we're done */
409 $this->handle_post_events("remove");
410 }
413 /* Save data to object */
414 function save_object()
415 {
416 plugin::save_object();
417 }
420 /* Check supplied data */
421 function check()
422 {
423 /* Call common method to give check the hook */
424 $message= plugin::check();
426 return ($message);
427 }
430 /* Save to LDAP */
431 function save()
432 {
433 /* Take over handling
434 * - Load servdhcp class and dhcpObjectCache for the source dhcp setup.
435 * - Assign dhcpObjectCache to this configuration.
436 * - Save this setup and remove source setup from ldap.
437 */
438 if($this->take_over_id != -1){
439 $id = $this->take_over_id;
440 $src = preg_replace("/cn=dhcp,/","",$this->dhcp_server_list['ENTRIES'][$id]['dn']);
441 $tmp = new servdhcp ($this->config, $src);
442 $this->orig_dn = $src;
443 $this->dhcpObjectCache = $tmp->dhcpObjectCache;
444 }
446 /* Save dhcp setttings */
447 $ldap= $this->config->get_ldap_link();
448 foreach ($this->dhcpObjectCache as $dn => $data){
450 if($this->dn != $this->orig_dn){
451 $dn = preg_replace("/".normalizePreg($this->orig_dn)."$/i",$this->dn,$dn);
452 }
454 /* Remove entry? */
455 if (count($data) == 0){
456 /* Check if exists, then remove... */
457 if($ldap->cat($dn)){
458 $ldap->rmdir_recursive($dn);
459 show_ldap_error($ldap->get_error(), _("Can't remove DHCP object!"));
460 }
461 continue;
462 }
464 /* Modify existing entry? */
465 if (isset($data['MODIFIED']) || $this->orig_dn != $this->dn){
467 if($ldap->cat($dn)){
468 $modify= TRUE;
469 } else {
470 $modify= FALSE;
471 }
473 /* Build new entry */
474 $attrs= array();
475 foreach ($data as $attribute => $values){
476 if ($attribute == "MODIFIED" || $attribute == "dn"){
477 continue;
478 }
480 if(in_array($attribute,array("dhcpPrimaryDN","dhcpSecondaryDN","dhcpServerDN","dhcpFailOverPeerDN"))){
481 foreach($values as $v_key => $value){
482 $values[$v_key] = preg_replace("/".normalizePreg($this->orig_dn)."$/i",$this->dn,$value);
483 }
484 }
486 if (count($values)){
488 if($attribute == "dhcpOption"){
489 foreach($values as $key => $value){
490 $option_name = trim(preg_replace("/[^ ]*$/","",$value));
491 $option_value= trim(preg_replace("/^[^ ]*/","",$value));
492 if(in_array($option_name,$this->quote_option)){
493 $values[$key] = $option_name." \"".$option_value."\"";
494 }
495 }
496 }
497 if (count($values) == 1){
498 $attrs[$attribute]= $values[0];
499 } else {
500 $attrs[$attribute]= $values;
501 }
502 } else {
503 if ($modify){
504 $attrs[$attribute]= array();
505 }
506 }
507 }
509 $ldap->cd($dn);
510 if ($modify){
511 $ldap->modify($attrs);
512 show_ldap_error($ldap->get_error(), _("Can't save DHCP object!"));
513 } else {
514 $ldap->add($attrs);
515 show_ldap_error($ldap->get_error(), _("Can't save DHCP object!"));
516 }
517 }
518 }
520 $this->dhcpServiceDN= $this->serviceDN;
521 if($this->dn != $this->orig_dn){
522 $this->dhcpServiceDN= preg_replace("/".normalizePreg($this->orig_dn)."$/i",$this->dn,$this->dhcpServiceDN);
523 }
525 plugin::save();
527 /* Save data to LDAP */
528 $ldap->cd($this->dn);
529 $this->cleanup();
530 $ldap->modify ($this->attrs);
532 show_ldap_error($ldap->get_error(), _("Saving DHCP service failed"));
534 /* Optionally execute a command after we're done */
535 if ($this->initially_was_account == $this->is_account){
536 if ($this->is_modified){
537 $this->handle_post_events("modify");
538 }
539 } else {
540 $this->handle_post_events("add");
541 }
543 /* Take over handling
544 * - Remove old dhcp config from source server
545 */
546 if($this->take_over_id != -1){
547 $id = $this->take_over_id;
548 $src = $this->dhcp_server_list['ENTRIES'][$id]['dn'];
549 $tmp = new servdhcp ($this->config, $src);
550 $tmp->remove_from_parent();
551 }
552 }
555 function reload()
556 {
557 /* Init LDAP and load list */
558 $ldap= $this->config->get_ldap_link();
559 $ui= get_userinfo();
560 $me= $this->dn;
562 $list= get_list("(&(objectClass=dhcpService)(|(dhcpPrimaryDN=$me)(dhcpSecondaryDN=$me)(dhcpServerDN=$me)(dhcpFailOverPeerDN=$me)))", $ui->subtreeACL, $this->config->current['BASE'], array("cn"));
563 $final= array();
564 foreach ($list as $value){
566 /* Set header */
567 $sortpart= split(",", $value['dn']);
568 $sortpart= array_reverse($sortpart);
569 $tmp= implode(",", $sortpart);
571 $final[$value['dn']]= $tmp."!"._("Global options");
573 /* Read all sub entries to place here */
574 $ldap->cd($value['dn']);
575 $ldap->search("(|(objectClass=dhcpService)(objectClass=dhcpLog)(objectClass=dhcpClass)(objectClass=dhcpSubClass)(objectClass=dhcpHost)(objectClass=dhcpGroup)(objectClass=dhcpPool)(objectClass=dhcpSubnet)(objectClass=dhcpSharedNetwork)(objectClass=dhcpOptions)(objectClass=dhcpTSigKey)(objectClass=dhcpDnsZone)(objectClass=dhcpFailOverPeer))", array());
576 $this->serviceDN= $value['dn'];
578 while ($attrs= $ldap->fetch()){
579 $sattrs= array();
580 for ($i= 0; $i<$attrs['count']; $i++){
581 $sattrs[$attrs[$i]]= $attrs[$attrs[$i]];
582 unset($sattrs[$attrs[$i]]['count']);
583 }
584 $sattrs['dn']= $ldap->getDN();
586 foreach($sattrs as $name => $values){
587 if($name == "dhcpOption"){
588 foreach($values as $key => $value){
589 $value_name = trim(preg_replace("/[^ ]*$/","",$value));
590 $value_value= trim(preg_replace("/^[^ ]*/","",$value));
591 if(in_array($value_name,$this->quote_option)){
592 $value_value = preg_replace("/^\"/","",$value_value);
593 $value_value = preg_replace("/\"$/","",$value_value);
594 $sattrs[$name][$key] = $value_name." ".$value_value;
595 }
596 }
597 }
598 }
600 $this->dhcpObjectCache[$ldap->getDN()]= $sattrs;
601 $tmp= preg_replace("/".$this->serviceDN."/", "", $ldap->getDN());
602 $indent= substr_count($tmp, ",");
603 $spaces= "";
604 for ($i= 0; $i<$indent; $i++){
605 $spaces.= " ";
606 }
608 foreach ($this->types as $key => $val){
609 if (in_array("$key", $attrs['objectClass'])){
610 $type= $val;
611 break;
612 }
613 }
615 /* Prepare for sorting... */
616 $sortpart= split(",", $ldap->getDN());
617 $sortpart= array_reverse($sortpart);
618 $tmp= implode(",", $sortpart);
619 $final[$ldap->getDN()]= $tmp."!".$spaces.$type." '".$attrs['cn'][0]."'";
620 }
621 }
623 /* Sort it... */
624 natsort($final);
625 $this->dhcpSections= array();
626 foreach ($final as $key => $val){
627 $this->dhcpSections[$key]= preg_replace('/^[^!]+!(.*)$/', '\\1', $val);
628 }
630 }
633 function objectType($dn)
634 {
635 $type= "";
636 $types= array("dhcpService", "dhcpClass", "dhcpSubClass", "dhcpHost",
637 "dhcpGroup", "dhcpPool", "dhcpSubnet", "dhcpSharedNetwork");
639 foreach ($this->dhcpObjectCache[$dn]['objectClass'] as $oc){
640 if (in_array($oc, $types)){
641 $type= $oc;
642 break;
643 }
644 }
646 /* That should not happen... */
647 if ($type == ""){
648 print_red(_("DHCP configuration set is unknown. Please contact your system administrator."));
649 }
651 return ($type);
652 }
654 }
656 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
657 ?>