Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rpc dumpzone: dump HNS root zone to file #534

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions lib/dns/resource.js
Original file line number Diff line number Diff line change
Expand Up @@ -258,12 +258,12 @@ class Resource extends Struct {
for (const record of this.records) {
switch (record.type) {
case hsTypes.GLUE4:
case hsTypes.GLUE6:
case hsTypes.SYNTH4:
case hsTypes.SYNTH6: {
case hsTypes.GLUE6: {
if (!util.isSubdomain(name, record.ns))
continue;

}
case hsTypes.SYNTH4:
case hsTypes.SYNTH6: {
zone.push(record.toGlue(record.ns, this.ttl));
break;
}
Expand Down
67 changes: 67 additions & 0 deletions lib/node/rpc.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

'use strict';

const constants = require('bns/lib/constants');
const {types} = constants;
const fs = require('fs');
const bns = require('bns');
const assert = require('bsert');
const bweb = require('bweb');
const {Lock} = require('bmutex');
Expand Down Expand Up @@ -246,6 +250,7 @@ class RPC extends RPCBase {
this.add('validateresource', this.validateResource);

this.add('resetrootcache', this.resetRootCache);
this.add('dumpzone', this.dumpzone);

// Compat
// this.add('getnameinfo', this.getNameInfo);
Expand Down Expand Up @@ -2533,6 +2538,68 @@ class RPC extends RPCBase {
return null;
}

async dumpzone(args, help) {
if (help || args.length !== 1)
throw new RPCError(errs.MISC_ERROR, 'dumpzone <filename>');

const valid = new Validator(args);
const filename = valid.str(0, null);
if (filename == null)
throw new RPCError(errs.MISC_ERROR, 'dumpzone <filename>');

const tmp = filename + '~';
this.logger.debug(`dumping root zone to file: ${filename}`);

let fd = null;
let fileErr = null;
fd = fs.createWriteStream(tmp, { flags: 'a+' });
fd.on('error', (err) => {
fd.end();
fd = null;
fileErr = err;
});

const tree = this.chain.db.tree;
const iter = tree.iterator(true);

let count = 0;
while ((await iter.next()) && (fd != null)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this fd check redundant with the check on 2571?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably can remove one or other, just trying to catch if the fd.on('error',... got triggered

JS isn't my strongest skill, so likely all that error handling can all be done better
I think it was to try & catch things like disk-full

count++;
if (count % 10000 === 0)
this.logger.debug('dumpzone names processed: %d', count);

if (fd == null)
break;

const {value} = iter;
const ns = NameState.decode(value);

if (ns.data.length <= 0)
continue;

const fqdn = bns.util.fqdn(ns.name.toString('ascii'));
const resource = Resource.decode(ns.data);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const resource = Resource.decode(ns.data);
try {
const resource = Resource.decode(ns.data);
} catch (e) {
continue;
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per our testing this needs to be updated to:

let resource;
try {
resource = Resource.decode(ns.data);
if (!resource) continue;
} catch (e) {
continue;
}

const zone = resource.toZone(fqdn);
for (const record of zone) {
if (fd == null)
break;

if (record.type !== types.RRSIG)
fd.write(record.toString() + '\n');
}
}

if (fd == null)
return fileErr;

fd.end();
fs.renameSync(tmp, filename);

this.logger.debug('root zone dump complete. Total names: %d', count);

return filename;
}

/*
* Helpers
*/
Expand Down
12 changes: 12 additions & 0 deletions test/data/hns.zone
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
hns. 21600 IN DS 57355 8 2 95A57C3BAB7849DBCDDF7C72ADA71A88146B141110318CA5BE672057 E865C3E2 ; alg = RSASHA256 ; hash = SHA256
hns. 21600 IN NS ns1.hns.
hns. 21600 IN NS ns2.hns.
hns. 21600 IN NS ns3.some-other-domain.
hns. 21600 IN NS ns4.hns.
hns. 21600 IN NS _fs0000g._synth.
hns. 21600 IN NS _00000000000000000000000008._synth.
hns. 21600 IN TXT "hello world"
ns2.hns. 21600 IN A 127.0.0.1
ns4.hns. 21600 IN AAAA ::1
_fs0000g._synth. 21600 IN A 127.0.0.2
_00000000000000000000000008._synth. 21600 IN AAAA ::2
19 changes: 19 additions & 0 deletions test/resource-test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
'use strict';

const assert = require('bsert');
const fs = require('fs');
const Path = require ('path');
const {wire} = require('bns');
const {Resource} = require('../lib/dns/resource');
const {types} = wire;
Expand Down Expand Up @@ -58,6 +60,23 @@ describe('Resource', function() {
assert.deepStrictEqual(res1.toJSON(), res2.toJSON());
});

it('should dump zone', async () => {
const expected = await fs.readFileSync(
Path.join(__dirname, 'data', 'hns.zone'),
'ascii'
);

const res = Resource.fromJSON(json);
const zone = res.toZone('hns.');
let file = '';
for (const record of zone) {
if (record.type !== types.RRSIG)
file += record.toString() + '\n';
}

assert.deepStrictEqual(file, expected);
});

it('should synthesize a referral', () => {
const res = Resource.fromJSON(json);
const msg = res.toDNS('hns.', types.MX);
Expand Down