Skip to content

Commit 40e6570

Browse files
author
wyrie
committed
Bind DLZ plugin
1 parent ffa0d3d commit 40e6570

File tree

1 file changed

+347
-0
lines changed

1 file changed

+347
-0
lines changed
Lines changed: 347 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,347 @@
1+
<?php
2+
3+
/*
4+
Copyright (c) 2009, Falko Timme, Till Brehm, projektfarm Gmbh
5+
All rights reserved.
6+
7+
Redistribution and use in source and binary forms, with or without modification,
8+
are permitted provided that the following conditions are met:
9+
10+
* Redistributions of source code must retain the above copyright notice,
11+
this list of conditions and the following disclaimer.
12+
* Redistributions in binary form must reproduce the above copyright notice,
13+
this list of conditions and the following disclaimer in the documentation
14+
and/or other materials provided with the distribution.
15+
* Neither the name of ISPConfig nor the names of its contributors
16+
may be used to endorse or promote products derived from this software without
17+
specific prior written permission.
18+
19+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22+
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24+
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26+
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
*/
30+
31+
/*
32+
TABLE STRUCTURE of the "named" database:
33+
34+
CREATE TABLE IF NOT EXISTS `records` (
35+
`id` int(10) unsigned NOT NULL auto_increment,
36+
`zone` varchar(255) NOT NULL,
37+
`ttl` int(11) NOT NULL default '86400',
38+
`type` varchar(255) NOT NULL,
39+
`host` varchar(255) NOT NULL default '@',
40+
`mx_priority` int(11) default NULL,
41+
`data` text,
42+
`primary_ns` varchar(255) default NULL,
43+
`resp_contact` varchar(255) default NULL,
44+
`serial` bigint(20) default NULL,
45+
`refresh` int(11) default NULL,
46+
`retry` int(11) default NULL,
47+
`expire` int(11) default NULL,
48+
`minimum` int(11) default NULL,
49+
`ispconfig_id` int(11) NOT NULL,
50+
PRIMARY KEY (`id`),
51+
KEY `type` (`type`),
52+
KEY `host` (`host`),
53+
KEY `zone` (`zone`)
54+
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
55+
56+
CREATE TABLE IF NOT EXISTS `xfr` (
57+
`id` int(11) NOT NULL auto_increment,
58+
`zone` varchar(255) NOT NULL,
59+
`client` varchar(255) NOT NULL,
60+
`ispconfig_id` int(11) NOT NULL,
61+
PRIMARY KEY (`id`),
62+
KEY `zone` (`zone`),
63+
KEY `client` (`client`)
64+
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
65+
66+
*/
67+
68+
class bind_dlz_plugin {
69+
70+
var $plugin_name = 'bind_dlz_plugin';
71+
var $class_name = 'bind_dlz_plugin';
72+
73+
//* This function is called during ispconfig installation to determine
74+
// if a symlink shall be created for this plugin.
75+
function onInstall()
76+
{
77+
global $conf;
78+
79+
if(isset($conf['bind']['installed']) && $conf['bind']['installed'] == true) {
80+
return true;
81+
} else {
82+
return false;
83+
}
84+
85+
}
86+
87+
/*
88+
This function is called when the plugin is loaded
89+
*/
90+
91+
function onLoad()
92+
{
93+
global $app;
94+
95+
/*
96+
Register for the events
97+
*/
98+
99+
//* SOA
100+
$app->plugins->registerEvent('dns_soa_insert',$this->plugin_name,'soa_insert');
101+
$app->plugins->registerEvent('dns_soa_update',$this->plugin_name,'soa_update');
102+
$app->plugins->registerEvent('dns_soa_delete',$this->plugin_name,'soa_delete');
103+
104+
//* RR
105+
$app->plugins->registerEvent('dns_rr_insert',$this->plugin_name,'rr_insert');
106+
$app->plugins->registerEvent('dns_rr_update',$this->plugin_name,'rr_update');
107+
$app->plugins->registerEvent('dns_rr_delete',$this->plugin_name,'rr_delete');
108+
}
109+
110+
111+
function soa_insert($event_name,$data)
112+
{
113+
global $app, $conf;
114+
115+
if($data["new"]["active"] != 'Y') return;
116+
117+
$origin = substr($data["new"]["origin"], 0, -1);
118+
$ispconfig_id = $data["new"]["id"];
119+
$serial = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = ".$ispconfig_id);
120+
121+
$ttl = $data["new"]["ttl"];
122+
123+
$_db = clone $app->db;
124+
$_db->dbName = 'named';
125+
126+
$_db->query("INSERT INTO records (zone, ttl, type, primary_ns, resp_contact, serial, refresh, retry, expire, minimum, ispconfig_id) VALUES ".
127+
"('$origin', $ttl, 'SOA', '{$data["new"]["ns"]}', '{$data["new"]["mbox"]}', '{$serial["serial"]}', '{$serial["refresh"]}'," .
128+
"'{$serial["retry"]}', '{$serial["expire"]}', '{$serial["minimum"]}', $ispconfig_id)");
129+
unset($_db);
130+
}
131+
132+
function soa_update($event_name,$data)
133+
{
134+
global $app, $conf;
135+
136+
if($data["new"]["active"] != 'Y')
137+
{
138+
if($data["old"]["active"] != 'Y') return;
139+
$this->soa_delete($event_name,$data);
140+
}
141+
else
142+
{
143+
if($data["old"]["active"] == 'Y')
144+
{
145+
$origin = substr($data["new"]["origin"], 0, -1);
146+
$ispconfig_id = $data["new"]["id"];
147+
$serial = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = ".$ispconfig_id);
148+
149+
$ttl = $data["new"]["ttl"];
150+
151+
$_db = clone $app->db;
152+
$_db->dbName = 'named';
153+
154+
$_db->query("UPDATE records SET zone = '$origin', ttl = $ttl, primary_ns = '{$data["new"]["ns"]}', resp_contact = '{$data["new"]["mbox"]}', ".
155+
"serial = '{$serial["serial"]}', refresh = '{$serial["refresh"]}', retry = '{$serial["retry"]}', expire = '{$serial["expire"]}', ".
156+
"minimum = '{$serial["minimum"]}' WHERE ispconfig_id = ".$data["new"]["id"]." AND type = 'SOA'");
157+
unset($_db);
158+
}
159+
else
160+
{
161+
$this->soa_insert($event_name,$data);
162+
$ispconfig_id = $data["new"]["id"];
163+
164+
if ($records = $app->db->queryAllRecords("SELECT * FROM dns_rr WHERE zone = $ispconfig_id AND active = 'Y'"))
165+
{
166+
foreach($records as $record)
167+
{
168+
foreach ($record as $key => $val) {
169+
$data["new"][$key] = $val;
170+
}
171+
$this->rr_insert("dns_rr_insert", $data);
172+
}
173+
}
174+
}
175+
}
176+
177+
}
178+
179+
function soa_delete($event_name,$data)
180+
{
181+
global $app, $conf;
182+
183+
$_db = clone $app->db;
184+
$_db->dbName = 'named';
185+
186+
$_db->query("DELETE FROM records WHERE ispconfig_id = {$data["old"]["id"]}");
187+
unset($_db);
188+
}
189+
190+
function rr_insert($event_name,$data)
191+
{
192+
global $app, $conf;
193+
if($data["new"]["active"] != 'Y') return;
194+
195+
$zone = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = ".$data["new"]["zone"]);
196+
$origin = substr($zone["origin"], 0, -1);
197+
$ispconfig_id = $data["new"]["id"];
198+
199+
$type = $data["new"]["type"];
200+
201+
if (substr($data["new"]["name"], -1) == '.') {
202+
$name = substr($data["new"]["name"], 0, -1);
203+
} else {
204+
$name = ($data["new"]["name"] == "") ? $name = '@' : $data["new"]["name"];
205+
}
206+
207+
if ($name == $origin || $name == '') {
208+
$name = '@';
209+
}
210+
211+
switch ($type)
212+
{
213+
case "CNAME":
214+
case "MX":
215+
case "NS":
216+
case "ALIAS":
217+
case "PTR":
218+
case "SRV":
219+
if(substr($data["new"]["data"], -1) != '.'){
220+
$content = $data["new"]["data"] . '.';
221+
} else {
222+
$content = $data["new"]["data"];
223+
}
224+
break;
225+
case "HINFO":
226+
$content = $data["new"]["data"];
227+
$quote1 = strpos($content, '"');
228+
229+
if($quote1 !== FALSE) {
230+
$quote2 = strpos(substr($content, ($quote1 + 1)), '"');
231+
}
232+
233+
if ($quote1 !== FALSE && $quote2 !== FALSE) {
234+
$text_between_quotes = str_replace(' ', '_', substr($content, ($quote1 + 1), (($quote2 - $quote1))));
235+
$content = $text_between_quotes.substr($content, ($quote2 + 2));
236+
}
237+
break;
238+
default:
239+
$content = $data["new"]["data"];
240+
}
241+
242+
$ttl = $data["new"]["ttl"];
243+
244+
$_db = clone $app->db;
245+
$_db->dbName = 'named';
246+
247+
if ($type == 'MX') {
248+
$_db->query("INSERT INTO records (zone, ttl, type, host, mx_priority, data, ispconfig_id)".
249+
" VALUES ('$origin', $ttl, '$type', '$name', {$data["new"]["aux"]}, '$content', $ispconfig_id)");
250+
} else {
251+
$_db->query("INSERT INTO records (zone, ttl, type, host, data, ispconfig_id)".
252+
" VALUES ('$origin', $ttl, '$type', '$name', '$content', $ispconfig_id)");
253+
}
254+
255+
unset($_db);
256+
}
257+
258+
function rr_update($event_name,$data)
259+
{
260+
global $app, $conf;
261+
262+
if ($data["new"]["active"] != 'Y')
263+
{
264+
if($data["old"]["active"] != 'Y') return;
265+
$this->rr_delete($event_name,$data);
266+
}
267+
else
268+
{
269+
if ($data["old"]["active"] == 'Y')
270+
{
271+
$zone = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = ".$data["new"]["zone"]);
272+
$origin = substr($zone["origin"], 0, -1);
273+
$ispconfig_id = $data["new"]["id"];
274+
275+
$type = $data["new"]["type"];
276+
277+
if (substr($data["new"]["name"], -1) == '.') {
278+
$name = substr($data["new"]["name"], 0, -1);
279+
} else {
280+
$name = ($data["new"]["name"] == "") ? $name = '@' : $data["new"]["name"];
281+
}
282+
283+
if ($name == $origin || $name == '') {
284+
$name = '@';
285+
}
286+
287+
switch ($type)
288+
{
289+
case "CNAME":
290+
case "MX":
291+
case "NS":
292+
case "ALIAS":
293+
case "PTR":
294+
case "SRV":
295+
if(substr($data["new"]["data"], -1) != '.'){
296+
$content = $data["new"]["data"] . '.';
297+
} else {
298+
$content = $data["new"]["data"];
299+
}
300+
break;
301+
case "HINFO":
302+
$content = $data["new"]["data"];
303+
$quote1 = strpos($content, '"');
304+
if($quote1 !== FALSE){
305+
$quote2 = strpos(substr($content, ($quote1 + 1)), '"');
306+
}
307+
if($quote1 !== FALSE && $quote2 !== FALSE){
308+
$text_between_quotes = str_replace(' ', '_', substr($content, ($quote1 + 1), (($quote2 - $quote1))));
309+
$content = $text_between_quotes.substr($content, ($quote2 + 2));
310+
}
311+
break;
312+
default:
313+
$content = $data["new"]["data"];
314+
}
315+
316+
$ttl = $data["new"]["ttl"];
317+
$prio = (int)$data["new"]["aux"];
318+
319+
$_db = clone $app->db;
320+
$_db->dbName = 'named';
321+
322+
if ($type == 'MX') {
323+
$_db->query("UPDATE records SET zone = '$origin', ttl = $ttl, type = '$type', host = '$name', mx_priority = $prio, ".
324+
"data = '$content' WHERE ispconfig_id = $ispconfig_id AND type != 'SOA'");
325+
} else {
326+
$_db->query("UPDATE records SET zone = '$origin', ttl = $ttl, type = '$type', host = '$name', ".
327+
"data = '$content' WHERE ispconfig_id = $ispconfig_id AND type != 'SOA'");
328+
}
329+
330+
unset($_db);
331+
} else {
332+
$this->rr_insert($event_name,$data);
333+
}
334+
}
335+
}
336+
337+
function rr_delete($event_name,$data) {
338+
global $app, $conf;
339+
340+
$_db = clone $app->db;
341+
$_db->dbName = 'named';
342+
343+
$_db->query("DELETE FROM named.records WHERE ispconfig_id = {$data["old"]["id"]} AND type != 'SOA'");
344+
unset($_db);
345+
}
346+
} // end class
347+
?>

0 commit comments

Comments
 (0)