Skip to content

Commit 38184e1

Browse files
author
Carsten Schoene
committed
+ complete SOA records
- refresh, retry, expire and minimum were missing in the SOA record which was/is OK because pdns has defaults for this, but this gives the user the full options which are configurable from the UI + drop/replaced pdns service reloads - the initscripts reload function was called which internally does 'pdns_control cycle', which is a quick service restart. This is no needed in pdns to load the new zone data. All updates are available without service reloads. - to be sure the zone data is really loaded 'pdns_control rediscover' is called - for pdns versions starting from 3 (DNSSEC) all zones must be rectified, implemented this using pdnssec. + send notify to slaves - implemented using pdns_control, this enables zone transfers to slaves (maybe this never worked before, because auf the service reloads) hint: use supermasters table on slave server for zone autodeployment, but you need an extra cleanup script for deleted zones for now + fetch Slave zone from master - call 'pdns_control retrieve <zone>' for new slave zones + added fix from FS#3121 + code cleanup
1 parent 604d25e commit 38184e1

File tree

1 file changed

+99
-35
lines changed

1 file changed

+99
-35
lines changed

server/plugins-available/powerdns_plugin.inc.php

Lines changed: 99 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,17 @@ function soa_insert($event_name, $data) {
144144
if($ns == '') $ns = $origin;
145145

146146
$hostmaster = substr($data["new"]["mbox"], 0, -1);
147-
$content = $ns.' '.$hostmaster.' 0';
147+
$content = $ns.' '.$hostmaster.' '.$data["new"]["serial"].' '.$data["new"]["refresh"].' '.$data["new"]["retry"].' '.$data["new"]["expire"].' '.$data["new"]["minimum"];
148148
$ttl = $data["new"]["ttl"];
149149

150150
$app->db->query("INSERT INTO powerdns.records (domain_id, name, type, content, ttl, prio, change_date, ispconfig_id) VALUES ($zone_id, '$origin', 'SOA', '$content', $ttl, 0, ".time().", $ispconfig_id)");
151151

152-
//* Reload powerdns nameserver
153-
$app->services->restartServiceDelayed('powerdns', 'reload');
154-
152+
//* tell pdns to rediscover zones in DB
153+
$this->zoneRediscover();
154+
//* tell pdns to use 'pdnssec rectify' on the new zone
155+
$this->rectifyZone($data);
156+
//* tell pdns to send notify to slave
157+
$this->notifySlave($data);
155158
}
156159

157160
function soa_update($event_name, $data) {
@@ -161,13 +164,10 @@ function soa_update($event_name, $data) {
161164
if($data["old"]["active"] != 'Y') return;
162165
$this->soa_delete($event_name, $data);
163166
} else {
164-
if($data["old"]["active"] == 'Y'){
167+
$exists = $app->db->queryOneRecord("SELECT * FROM powerdns.domains WHERE ispconfig_id = ".$data["new"]["id"]);
168+
if($data["old"]["active"] == 'Y' && $exists){
165169
$origin = substr($data["new"]["origin"], 0, -1);
166170
$ispconfig_id = $data["new"]["id"];
167-
$serial = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = ".$ispconfig_id);
168-
$serial_id = $serial["serial"];
169-
//$app->db->query("UPDATE powerdns.domains SET name = '$origin', notified_serial = $serial_id WHERE ispconfig_id = $ispconfig_idi AND type = 'MASTER'");
170-
//$app->db->query("UPDATE powerdns.domains SET name = '$origin' WHERE ispconfig_id = $ispconfig_id AND type = 'MASTER'");
171171

172172
if(substr($data["new"]["ns"], -1) == '.'){
173173
$ns = substr($data["new"]["ns"], 0, -1);
@@ -177,15 +177,14 @@ function soa_update($event_name, $data) {
177177
if($ns == '') $ns = $origin;
178178

179179
$hostmaster = substr($data["new"]["mbox"], 0, -1);
180-
//$content = $ns.' '.$hostmaster.' 0';
181-
$content = $ns.' '.$hostmaster.' '.$serial_id.'';
180+
$content = $ns.' '.$hostmaster.' '.$data["new"]["serial"].' '.$data["new"]["refresh"].' '.$data["new"]["retry"].' '.$data["new"]["expire"].' '.$data["new"]["minimum"];
182181
$ttl = $data["new"]["ttl"];
183182
$app->db->query("UPDATE powerdns.records SET name = '$origin', content = '$content', ttl = $ttl, change_date = ".time()." WHERE ispconfig_id = ".$data["new"]["id"]." AND type = 'SOA'");
184183

185-
//* Reload powerdns nameserver
186-
$app->services->restartServiceDelayed('powerdns', 'reload');
187-
188-
184+
//* tell pdns to use 'pdnssec rectify' on the new zone
185+
$this->rectifyZone($data);
186+
//* tell pdns to send notify to slave
187+
$this->notifySlave($data);
189188
} else {
190189
$this->soa_insert($event_name, $data);
191190
$ispconfig_id = $data["new"]["id"];
@@ -197,10 +196,12 @@ function soa_update($event_name, $data) {
197196
$this->rr_insert("dns_rr_insert", $data);
198197
}
199198
}
200-
199+
//* tell pdns to use 'pdnssec rectify' on the new zone
200+
$this->rectifyZone($data);
201+
//* tell pdns to send notify to slave
202+
$this->notifySlave($data);
201203
}
202204
}
203-
204205
}
205206

206207
function soa_delete($event_name, $data) {
@@ -210,10 +211,6 @@ function soa_delete($event_name, $data) {
210211
$zone_id = $zone["id"];
211212
$app->db->query("DELETE FROM powerdns.records WHERE domain_id = $zone_id");
212213
$app->db->query("DELETE FROM powerdns.domains WHERE id = $zone_id");
213-
214-
//* Reload powerdns nameserver
215-
$app->services->restartServiceDelayed('powerdns', 'reload');
216-
217214
}
218215

219216
function slave_insert($event_name, $data) {
@@ -227,12 +224,10 @@ function slave_insert($event_name, $data) {
227224

228225
$app->db->query("INSERT INTO powerdns.domains (name, type, master, ispconfig_id) VALUES ('$origin', 'SLAVE', '$master_ns', $ispconfig_id)");
229226

230-
//$app->db->query("INSERT INTO powerdns.domains (name, type, ispconfig_id) VALUES ('$origin', 'NATIVE', $ispconfig_id)");
231227
$zone_id = $app->db->insertID();
232228

233-
//* Reload powerdns nameserver
234-
$app->services->restartServiceDelayed('powerdns', 'reload');
235-
229+
//* tell pdns to fetch zone from master server
230+
$this->fetchFromMaster($data);
236231
}
237232

238233
function slave_update($event_name, $data) {
@@ -249,15 +244,14 @@ function slave_update($event_name, $data) {
249244
$master_ns = $data["new"]["ns"];
250245

251246
$app->db->query("UPDATE powerdns.domains SET name = '$origin', type = 'SLAVE', master = '$master_ns' WHERE ispconfig_id=$ispconfig_id AND type = 'SLAVE'");
252-
//$app->db->query("INSERT INTO powerdns.domains (name, type, ispconfig_id) VALUES ('$origin', 'NATIVE', $ispconfig_id)");
253247
$zone_id = $app->db->insertID();
254248

255249
$zone = $app->db->queryOneRecord("SELECT * FROM powerdns.domains WHERE ispconfig_id = ".$ispconfig_id." AND type = 'SLAVE'");
256250
$zone_id = $zone["id"];
257251
$app->db->query("DELETE FROM powerdns.records WHERE domain_id = $zone_id AND ispconfig_id = 0");
258252

259-
//* Reload powerdns nameserver
260-
$app->services->restartServiceDelayed('powerdns', 'reload');
253+
//* tell pdns to fetch zone from master server
254+
$this->fetchFromMaster($data);
261255

262256
} else {
263257
$this->slave_insert($event_name, $data);
@@ -274,10 +268,6 @@ function slave_delete($event_name, $data) {
274268
$zone_id = $zone["id"];
275269
$app->db->query("DELETE FROM powerdns.records WHERE domain_id = $zone_id");
276270
$app->db->query("DELETE FROM powerdns.domains WHERE id = $zone_id");
277-
278-
//* Reload powerdns nameserver
279-
$app->services->restartServiceDelayed('powerdns', 'reload');
280-
281271
}
282272

283273
function rr_insert($event_name, $data) {
@@ -337,6 +327,8 @@ function rr_insert($event_name, $data) {
337327

338328
$app->db->query("INSERT INTO powerdns.records (domain_id, name, type, content, ttl, prio, change_date, ispconfig_id) VALUES ($zone_id, '$name', '$type', '$content', $ttl, $prio, $change_date, $ispconfig_id)");
339329

330+
//* tell pdns to use 'pdnssec rectify' on the new zone
331+
$this->rectifyZone($data);
340332
}
341333

342334
function rr_update($event_name, $data) {
@@ -346,7 +338,8 @@ function rr_update($event_name, $data) {
346338
if($data["old"]["active"] != 'Y') return;
347339
$this->rr_delete($event_name, $data);
348340
} else {
349-
if($data["old"]["active"] == 'Y'){
341+
$exists = $app->db->queryOneRecord("SELECT * FROM powerdns.records WHERE ispconfig_id = ".$data["new"]["id"]);
342+
if($data["old"]["active"] == 'Y' && $exists){
350343
$zone = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = ".$data["new"]["zone"]);
351344
$origin = substr($zone["origin"], 0, -1);
352345
$powerdns_zone = $app->db->queryOneRecord("SELECT * FROM powerdns.domains WHERE ispconfig_id = ".$data["new"]["zone"]." AND type = 'MASTER'");
@@ -397,24 +390,95 @@ function rr_update($event_name, $data) {
397390
$prio = $data["new"]["aux"];
398391
$change_date = time();
399392
$ispconfig_id = $data["new"]["id"];
400-
//echo "UPDATE powerdns.records SET name = '$name', type = '$type', content = '$content', ttl = $ttl, prio = $prio, change_date = ".time()." WHERE id = $record_id";
401393
$app->db->query("UPDATE powerdns.records SET name = '$name', type = '$type', content = '$content', ttl = $ttl, prio = $prio, change_date = ".time()." WHERE ispconfig_id = $ispconfig_id AND type != 'SOA'");
402394

395+
//* tell pdns to use 'pdnssec rectify' on the new zone
396+
$this->rectifyZone($data);
403397
} else {
404398
$this->rr_insert($event_name, $data);
405399
}
406400
}
407-
408401
}
409402

410403
function rr_delete($event_name, $data) {
411404
global $app, $conf;
412405

413406
$ispconfig_id = $data["old"]["id"];
414407
$app->db->query("DELETE FROM powerdns.records WHERE ispconfig_id = $ispconfig_id AND type != 'SOA'");
408+
}
415409

410+
function find_pdns_control() {
411+
$output = array();
412+
$retval = '';
413+
exec("type -p pdns_control", $output, $retval);
414+
if ($retval == 0 && is_file($output[0])){
415+
return $output[0];
416+
} else {
417+
return false;
418+
}
416419
}
417420

421+
function find_pdns_pdnssec() {
422+
$output = array();
423+
$retval = '';
424+
exec("type -p pdnssec", $output, $retval);
425+
if ($retval == 0 && is_file($output[0])){
426+
return $output[0];
427+
} else {
428+
return false;
429+
}
430+
}
431+
432+
function zoneRediscover() {
433+
$pdns_control = $this->find_pdns_control();
434+
if ( $pdns_control != false ) {
435+
exec($pdns_control . ' rediscover');
436+
}
437+
}
438+
439+
function notifySlave($data) {
440+
$pdns_control = $this->find_pdns_control();
441+
if ( $pdns_control != false ) {
442+
exec($pdns_control . ' notify ' . rtrim($data["new"]["origin"],"."));
443+
}
444+
}
445+
446+
function fetchFromMaster($data) {
447+
$pdns_control = $this->find_pdns_control();
448+
if ( $pdns_control != false ) {
449+
exec($pdns_control . ' retrieve ' . rtrim($data["new"]["origin"],"."));
450+
}
451+
}
452+
453+
function get_pdns_version() {
454+
$pdns_control = $this->find_pdns_control();
455+
if ( $pdns_control != false ) {
456+
$output=array();
457+
$retval='';
458+
exec($pdns_control . ' version',$output,$retval);
459+
return $output[0];
460+
} else {
461+
//* fallback to version 2
462+
return 2;
463+
}
464+
}
465+
466+
function rectifyZone($data) {
467+
global $app, $conf;
468+
if ( preg_match('/^3/',$this->get_pdns_version()) ) {
469+
$pdns_pdnssec = $this->find_pdns_pdnssec();
470+
if ( $pdns_pdnssec != false ) {
471+
if (isset($data["new"]["origin"])) {
472+
//* data has origin field only for SOA recordtypes
473+
exec($pdns_pdnssec . ' rectify-zone ' . rtrim($data["new"]["origin"],"."));
474+
} else {
475+
// get origin from DB for all other recordtypes
476+
$zn = $app->db->queryOneRecord("SELECT d.name AS name FROM powerdns.domains d, powerdns.records r WHERE r.ispconfig_id=".$data["new"]["id"]." AND r.domain_id = d.id");
477+
exec($pdns_pdnssec . ' rectify-zone ' . trim($zn["name"]));
478+
}
479+
}
480+
}
481+
}
418482

419483
} // end class
420484

0 commit comments

Comments
 (0)