From 596b9b9aa815364723d598b9091b748cd1179f51 Mon Sep 17 00:00:00 2001 From: Matthew Zipkin Date: Fri, 8 Jan 2021 15:48:17 -0500 Subject: [PATCH] node: rpc dumpzone Co-authored-by: James Stevens Co-authored-by: Mark Tyneway --- lib/node/rpc.js | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/lib/node/rpc.js b/lib/node/rpc.js index 9668d61d2d..d2e7fbb97e 100644 --- a/lib/node/rpc.js +++ b/lib/node/rpc.js @@ -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'); @@ -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); @@ -2533,6 +2538,67 @@ class RPC extends RPCBase { return null; } + async dumpzone(args, help) { + if (help || args.length !== 1) + throw new RPCError(errs.MISC_ERROR, 'dumpzone '); + + const valid = new Validator(args); + const filename = valid.str(0, null); + if (filename == null) + throw new RPCError(errs.MISC_ERROR, 'dumpzone '); + + 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)) { + 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); + for (const rr of resource.records) { + if (fd == null) + break; + + if (rr.type !== types.RRSIG) + fd.write(rr.toDNS(fqdn).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 */