diff --git a/CHANGELOG.md b/CHANGELOG.md index 4797c57..1c8753a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [0.3.0](https://github.com/NicTool/dns-nameserver/compare/v0.1.0...v0.3.0) (2022-04-09) + + +### ⚠ BREAKING CHANGES + +* add maradns config parser + +### Features + +* add maradns config parser ([1b4608e](https://github.com/NicTool/dns-nameserver/commit/1b4608e22b60250a67823851772538418e59d187)) +* parsers added for Knot ([#2](https://github.com/NicTool/dns-nameserver/issues/2)) ([139235e](https://github.com/NicTool/dns-nameserver/commit/139235e8acd105ce872cddb22224e1470c972cbe)) + ## [0.2.0](https://github.com/NicTool/dns-nameserver/compare/v0.1.2...v0.2.0) (2022-04-08) ### [0.1.2](https://github.com/NicTool/dns-nameserver/compare/v0.1.0...v0.1.2) (2022-04-08) diff --git a/README.md b/README.md index d2eaee0..df91ee1 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Name servers have configuration files, each with their own format. This package - [x] bind - [x] nsd - [x] knot - - [ ] maradns + - [x] maradns - [ ] tinydns - [ ] powerdns - [ ] config generator diff --git a/index.js b/index.js index 8309ade..bcb4e5a 100644 --- a/index.js +++ b/index.js @@ -1,85 +1,26 @@ -const os = require('os') -const nearley = require('nearley') -exports.parseBindConfig = async str => { - // eslint-disable-next-line node/no-unpublished-require - const grammar = nearley.Grammar.fromCompiled(require('./dist/bind.js')) - grammar.start = 'main' - const parser = new nearley.Parser(grammar) - parser.feed(str) - if (!str.endsWith(os.EOL)) parser.feed(os.EOL) - if (parser.length > 1) { - console.error(`ERROR: ambigious parser rule`) - } - - if (parser.results.length === 0) return [] - - return parser.results[0] - .filter(z => z[0] && z[0].type) // weed out nulls - .map(z => z[0]) // remove array nesting -} -exports.parseKnotConfig = async str => { - // eslint-disable-next-line node/no-unpublished-require - const grammar = nearley.Grammar.fromCompiled(require('./dist/knot.js')) - grammar.start = 'main' - const parser = new nearley.Parser(grammar) - parser.feed(str) - if (!str.endsWith(os.EOL)) parser.feed(os.EOL) - if (parser.results.length === 0) return [] - const r = {} - const sections = [ 'acl', 'key', 'log', 'policy', 'remote', 'server', 'template', 'zone' ] - - parser.results[0][0] - .filter(z => z !== null) - .map(z => { - for (const s of sections) { - if (z[s]) { - if (!r[s]) r[s] = [] - r[s].push(...z[s]) - } - } - }) - - return r -} -exports.parseNsdConfig = async str => { - // eslint-disable-next-line node/no-unpublished-require - const grammar = nearley.Grammar.fromCompiled(require('./dist/nsd.js')) - grammar.start = 'main' - - const parser = new nearley.Parser(grammar) - parser.feed(str + os.EOL) - if (!str.endsWith(os.EOL)) parser.feed(os.EOL) - - if (parser.results.length === 0) return [] - - const r = {} - - const sections = [ 'key', 'pattern', 'remote-control', 'server', 'tls-auth', 'zone' ] +exports.valueCleanup = function (str) { + // strip double quotes + if (str.charAt(0) === '"' && str.charAt(str.length -1) === '"') { + str = str.substr(1,str.length -2) + } - parser.results[0] - .filter(z => z !== null) - .map(z => { - for (const s of sections) { - if (z[s]) { - if (!r[s]) r[s] = [] - r[s].push(z[s]) - } - } - }) + if (/^[0-9.]+$/.test(str) && Number(str).toString() === str) { + return Number(str) + } - return r + return str } diff --git a/lib/bind.js b/lib/bind.js new file mode 100644 index 0000000..1260528 --- /dev/null +++ b/lib/bind.js @@ -0,0 +1,25 @@ + +const os = require('os') + +const nearley = require('nearley') + +exports.parseConfig = async str => { + + // eslint-disable-next-line node/no-unpublished-require + const grammar = nearley.Grammar.fromCompiled(require('../dist/bind.js')) + grammar.start = 'main' + + const parser = new nearley.Parser(grammar) + parser.feed(str) + if (!str.endsWith(os.EOL)) parser.feed(os.EOL) + + if (parser.length > 1) { + console.error(`ERROR: ambigious parser rule`) + } + + if (parser.results.length === 0) return [] + + return parser.results[0] + .filter(z => z[0] && z[0].type) // weed out nulls + .map(z => z[0]) // remove array nesting +} diff --git a/lib/knot.js b/lib/knot.js new file mode 100644 index 0000000..332c1cf --- /dev/null +++ b/lib/knot.js @@ -0,0 +1,34 @@ + +const os = require('os') + +const nearley = require('nearley') + +exports.parseConfig = async str => { + + // eslint-disable-next-line node/no-unpublished-require + const grammar = nearley.Grammar.fromCompiled(require('../dist/knot.js')) + grammar.start = 'main' + + const parser = new nearley.Parser(grammar) + parser.feed(str) + if (!str.endsWith(os.EOL)) parser.feed(os.EOL) + + if (parser.results.length === 0) return [] + + const r = {} + + const sections = [ 'acl', 'key', 'log', 'policy', 'remote', 'server', 'template', 'zone' ] + + parser.results[0][0] + .filter(z => z !== null) + .map(z => { + for (const s of sections) { + if (z[s]) { + if (!r[s]) r[s] = [] + r[s].push(...z[s]) + } + } + }) + + return r +} \ No newline at end of file diff --git a/lib/maradns.js b/lib/maradns.js new file mode 100644 index 0000000..f96dd19 --- /dev/null +++ b/lib/maradns.js @@ -0,0 +1,31 @@ + +const ns = require('../index') + +exports.parseConfig = async str => { + // https://maradns.samiam.org/tutorial/man.mararc.html + + const re = { + blank : /^\s*?$/, + comment : /^\s*(?:#)[^\r\n]*?$/, + variable: /^([^ \t]*)\s*=\s*([^\r\n]*)$/, + } + + const res = {} + + for (const line of str.split(/[\r\n]/)) { + + if (re.blank.test(line)) continue + if (re.comment.test(line)) continue + + const match = line.match(re.variable) + if (match) { + res[match[1]] = ns.valueCleanup(match[2]) + } + else { + console.log(line) + throw ('parser failed') + } + } + + return res +} diff --git a/lib/nsd.js b/lib/nsd.js new file mode 100644 index 0000000..189757d --- /dev/null +++ b/lib/nsd.js @@ -0,0 +1,36 @@ + +const os = require('os') + +const nearley = require('nearley') + +const ns = require('../index') + +exports.parseConfig = async str => { + + // eslint-disable-next-line node/no-unpublished-require + const grammar = nearley.Grammar.fromCompiled(require('../dist/nsd.js')) + grammar.start = 'main' + + const parser = new nearley.Parser(grammar) + parser.feed(str + os.EOL) + if (!str.endsWith(os.EOL)) parser.feed(os.EOL) + + if (parser.results.length === 0) return [] + + const r = {} + + const sections = [ 'key', 'pattern', 'remote-control', 'server', 'tls-auth', 'zone' ] + + parser.results[0] + .filter(z => z !== null) + .map(z => { + for (const s of sections) { + if (z[s]) { + if (!r[s]) r[s] = [] + r[s].push(z[s]) + } + } + }) + + return r +} diff --git a/package.json b/package.json index ac5b7bd..3a7103c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dns-nameserver", - "version": "0.2.0", + "version": "0.3.0", "description": "DNS Nameserver", "main": "index.js", "bin": {}, diff --git a/src/mara.ne b/src/mara.ne new file mode 100644 index 0000000..6024539 --- /dev/null +++ b/src/mara.ne @@ -0,0 +1,30 @@ +@lexer lexer + +main -> ( comment {% id %} + | blank {% id %} + | variable {% id %} + ):* {% id %} + +blank -> %blank {% asNull %} +comment -> %comment {% asNull %} +variable -> %variable {% asVariable %} + +@{% +const moo = require("moo"); + +const lexer = moo.compile({ + variable: /^[^ \t]*\s*=\s*[^\r\n]*?[\r\n]/, + blank : /^\s*?$[\r\n]/, + comment: /^\s*(?:#)[^\r\n]*?[\r\n]/, +}); + +function asNull (d) { return null } + +const varRe = /^([^ \t]*)\s*=\s*([^\r\n]*?)[\r\n]/ + +function asVariable (d) { + const match = d[0].value.match(varRe) + return { [match[1]]: match[2].trim().replace(/^"(.*)"$/, '$1') } +} + +%} diff --git a/src/nsd-moo.ne b/src/nsd-moo.ne index feb586c..06d5089 100644 --- a/src/nsd-moo.ne +++ b/src/nsd-moo.ne @@ -1,7 +1,7 @@ +# https://nsd.docs.nlnetlabs.nl/en/latest/manpages/nsd.conf.html @lexer lexer -main -> ( - comment {% id %} +main -> ( comment {% id %} | blank {% id %} | key {% id %} | pattern {% id %} @@ -11,15 +11,17 @@ main -> ( | zone {% id %} ):* {% id %} -blank -> %blank {% comment %} -comment -> %comment {% comment %} -key_val -> %key_val {% id %} -key -> %key (key_val {% asKeyValue %} | %comment {% comment %}):* {% asGroup %} -pattern -> %pattern (key_val {% asKeyValue %} | %comment {% comment %}):* {% asGroup %} -remote -> %remote (key_val {% asKeyValue %} | %comment {% comment %}):* {% asGroup %} -server -> %server (key_val {% asKeyValue %} | %comment {% comment %}):* {% asGroup %} -tls -> %tls (key_val {% asKeyValue %} | %comment {% comment %}):* {% asGroup %} -zone -> %zone (key_val {% asKeyValue %} | %comment {% comment %}):* {% asGroup %} +blank -> %blank {% asComment %} +comment -> %comment {% asComment %} +key_val -> %key_val {% asKeyValue %} +attrib -> key_val {% id %} + | comment {% id %} +key -> %key (attrib {% id %}):* {% asGroup %} +pattern -> %pattern (attrib {% id %}):* {% asGroup %} +remote -> %remote (attrib {% id %}):* {% asGroup %} +server -> %server (attrib {% id %}):* {% asGroup %} +tls -> %tls (attrib {% id %}):* {% asGroup %} +zone -> %zone (attrib {% id %}):* {% asGroup %} @{% const moo = require("moo"); @@ -36,16 +38,19 @@ const lexer = moo.compile({ comment: /^\s*(?:#)[^\r\n]*?[\r\n]/, }); -function comment (d) { return null } +function asComment (d) { return null } function asGroup (d) { - return { [d[0].type]: Object.assign({}, ...d[1].filter(e => typeof e !== 'null')) } + return { + // merge the attributes into a top level "group" + [d[0].type]: Object.assign({}, ...d[1].filter(e => typeof e !== 'null')) + } } const kvRe = /^[ \t]+([^\s]+?):\s*?([^\r\n#]+)(#[^\r\n]+)?[\r\n]/ function asKeyValue (d) { const match = d[0].value.match(kvRe) - return { [match[1]]: match[2].trim() } + return { [match[1]]: match[2].trim().replace(/^"|"$/g, '') } } %} diff --git a/test/bind.js b/test/bind.js new file mode 100644 index 0000000..a2d0b09 --- /dev/null +++ b/test/bind.js @@ -0,0 +1,22 @@ + +const assert = require('assert') +const fs = require('fs').promises + +const ns = require('../lib/bind.js') + + +describe('bind', function () { + + describe('parseConfig', function () { + + it('parses named.conf file', async () => { + const file = './test/fixtures/bind/named.conf-ztrax-master' + const buf = await fs.readFile(file) + + const r = await ns.parseConfig(buf.toString()) + // console.dir(r, { depth: null }) + assert.equal(r.length, 5) + }) + }) + +}) diff --git a/test/fixtures/maradns/example.com b/test/fixtures/maradns/example.com new file mode 100644 index 0000000..927772a --- /dev/null +++ b/test/fixtures/maradns/example.com @@ -0,0 +1,20 @@ + +csv2 = {} +csv2["example.com."] = "db.example.com" +csv2["example2.com."] = "db.example2.com" + +ipv4_bind_addresses = "10.1.2.3,10.1.2.4,127.0.0.1" + +chroot_dir = "/etc/maradns" + +maradns_uid = 99 +maradns_gid = 99 + +no_fingerprint = 0 + +max_chain = 8 +max_ar_chain = 1 +max_total = 20 + +verbose_level = 3 +zone_transfer_acl = "10.1.1.1/24, 10.100.100.100/255.255.255.224" diff --git a/test/fixtures/maradns/mararc b/test/fixtures/maradns/mararc new file mode 100644 index 0000000..f2f1f05 --- /dev/null +++ b/test/fixtures/maradns/mararc @@ -0,0 +1,63 @@ +# Example mararc file (unabridged version) + +# The various zones we support + +# We must initialize the csv2 hash, or MaraDNS will be unable to +# load any csv2 zone files +csv2 = {} + +# This is just to show the format of the file +#csv2["example.com."] = "db.example.com" + +# The address this DNS server runs on. If you want to bind +# to multiple addresses, separate them with a comma like this: +# "10.1.2.3,10.1.2.4,127.0.0.1" +ipv4_bind_addresses = "127.0.0.1" +# The directory with all of the zone files +chroot_dir = "/etc/maradns" +# The numeric UID MaraDNS will run as +maradns_uid = 99 +# The (optional) numeric GID MaraDNS will run as +# maradns_gid = 99 + +# Normally, MaraDNS has some MaraDNS-specific features, such as DDIP +# synthesizing, a special DNS query ("erre-con-erre-cigarro.maradns.org." +# with a TXT query returns the version of MaraDNS that a server is +# running), unique handling of multiple QDCOUNTs, etc. Some people +# might not like these features, so I have added a switch that lets +# a sys admin disable all these features. Just give "no_fingerprint" +# a value of one here, and MaraDNS should be more or less +# indistinguishable from a tinydns server. +no_fingerprint = 0 + +# These constants limit the number of records we will display, in order +# to help keep packets 512 bytes or smaller. This, combined with round_robin +# record rotation, help to use DNS as a crude load-balancer. + +# The maximum number of records to display in a chain of records (list +# of records) for a given host name +max_chain = 8 +# The maximum number of records to display in a list of records in the +# additional section of a query. If this is any value besides one, +# round robin rotation is disabled (due to limitations in the current +# data structure MaraDNS uses) +max_ar_chain = 1 +# The maximum number of records to show total for a given question +max_total = 20 + +# The number of messages we log to stdout +# 0: No messages except for fatal parsing errors and the legal disclaimer +# 1: Only startup messages logged (default) +# 2: Error queries logged +# 3: All queries logged (but not very verbosely right now) +verbose_level = 1 + +# Here is a ACL which restricts who is allowed to perform zone transfer from +# the zoneserver program + +# Simplest form: 10.1.1.1/24 (IP: 10.1.1.1, 24 left bits in IP need to match) +# and 10.100.100.100/255.255.255.224 (IP: 10.100.100.100, netmask +# 255.255.255.224) are allowed to connect to the zone server +# NOTE: The "maradns" program does not serve zones. Zones are served +# by the "zoneserver" program. +#zone_transfer_acl = "10.1.1.1/24, 10.100.100.100/255.255.255.224" \ No newline at end of file diff --git a/test/index.js b/test/index.js deleted file mode 100644 index 4db1a50..0000000 --- a/test/index.js +++ /dev/null @@ -1,20 +0,0 @@ - -const assert = require('assert') -const fs = require('fs').promises - -const ns = require('../index.js') - - -describe('parseBindConfig', function () { - - it('parses named.conf file', async () => { - const file = './test/fixtures/bind/named.conf-ztrax-master' - const buf = await fs.readFile(file) - - const r = await ns.parseBindConfig(buf.toString()) - // console.dir(r, { depth: null }) - assert.equal(r.length, 5) - }) -}) - - diff --git a/test/knot.js b/test/knot.js index 0c7a86e..b576292 100644 --- a/test/knot.js +++ b/test/knot.js @@ -2,108 +2,111 @@ const assert = require('assert') const fs = require('fs').promises -const ns = require('../index.js') +const ns = require('../lib/knot.js') -describe('parseKnotConfig', function () { +describe('knot', function () { - it('parses v2 knot.conf', async () => { - const file = './test/fixtures/knot/knotd-v2.conf' - const buf = await fs.readFile(file) + describe('parseConfig', function () { - const r = await ns.parseKnotConfig(buf.toString()) - // console.dir(r, { depth: null }) - assert.deepEqual(r, { - server: [{ listen: '0.0.0.0@53' }, { listen: '::@53' }], - zone : [ - { - domain : 'example.com', - storage: '/var/lib/knot/zones/', - file : 'example.com.zone', - }, - ], - log: [{ target: 'syslog', any: 'info' }], + it('parses v2 knot.conf', async () => { + const file = './test/fixtures/knot/knotd-v2.conf' + const buf = await fs.readFile(file) + + const r = await ns.parseConfig(buf.toString()) + // console.dir(r, { depth: null }) + assert.deepEqual(r, { + server: [{ listen: '0.0.0.0@53' }, { listen: '::@53' }], + zone : [ + { + domain : 'example.com', + storage: '/var/lib/knot/zones/', + file : 'example.com.zone', + }, + ], + log: [{ target: 'syslog', any: 'info' }], + }) }) - }) - it('parses v3 knot.conf', async () => { - const file = './test/fixtures/knot/knotd-v3.conf' - const buf = await fs.readFile(file) + it('parses v3 knot.conf', async () => { + const file = './test/fixtures/knot/knotd-v3.conf' + const buf = await fs.readFile(file) - const r = await ns.parseKnotConfig(buf.toString()) - // console.dir(r, { depth: null }) - assert.deepEqual(r, { - server: [{ listen: '0.0.0.0@53' }, { listen: '::@53' }], - zone : [ - { - domain : 'example.com', - storage: '/var/lib/knot/zones/', - file : 'example.com.zone', - }, - ], - log: [{ target: 'syslog', any: 'info' }], + const r = await ns.parseConfig(buf.toString()) + // console.dir(r, { depth: null }) + assert.deepEqual(r, { + server: [{ listen: '0.0.0.0@53' }, { listen: '::@53' }], + zone : [ + { + domain : 'example.com', + storage: '/var/lib/knot/zones/', + file : 'example.com.zone', + }, + ], + log: [{ target: 'syslog', any: 'info' }], + }) }) - }) - it('parses knot-flex.conf', async () => { - const file = './test/fixtures/knot/knot-flex.conf' - const buf = await fs.readFile(file) + it('parses knot-flex.conf', async () => { + const file = './test/fixtures/knot/knot-flex.conf' + const buf = await fs.readFile(file) - const r = await ns.parseKnotConfig(buf.toString()) - // console.dir(r, { depth: null }) - assert.deepStrictEqual(r, { - server: [{ listen: '0.0.0.0@53' }, { listen: '::@53' }], - zone : [ - { - domain : 'example.com', - storage: '/var/lib/knot/zones/', - file : 'example.com.zone', - }, - { domain: 'example2.com', file: 'example2.com.zone' }, - { domain: 'example3.com', file: 'example3.com.zone' }, - { domain: 'example4.com', file: 'example4.com.zone' }, - { domain: 'example5.com', file: 'example5.com.zone' }, - ], - log: [ - { target: 'syslog', any: 'info' }, - { target: '/var/log/knotd.log', any: 'info' }, - ], + const r = await ns.parseConfig(buf.toString()) + // console.dir(r, { depth: null }) + assert.deepStrictEqual(r, { + server: [{ listen: '0.0.0.0@53' }, { listen: '::@53' }], + zone : [ + { + domain : 'example.com', + storage: '/var/lib/knot/zones/', + file : 'example.com.zone', + }, + { domain: 'example2.com', file: 'example2.com.zone' }, + { domain: 'example3.com', file: 'example3.com.zone' }, + { domain: 'example4.com', file: 'example4.com.zone' }, + { domain: 'example5.com', file: 'example5.com.zone' }, + ], + log: [ + { target: 'syslog', any: 'info' }, + { target: '/var/log/knotd.log', any: 'info' }, + ], + }) }) - }) - it('parses ns2.cadillac.net.conf', async () => { - const file = './test/fixtures/knot/ns2.cadillac.net.conf' - const buf = await fs.readFile(file) + it('parses ns2.cadillac.net.conf', async () => { + const file = './test/fixtures/knot/ns2.cadillac.net.conf' + const buf = await fs.readFile(file) - const r = await ns.parseKnotConfig(buf.toString()) - // console.dir(r, { depth: null }) - assert.deepEqual(r, { - zone: [ - { - domain: '0.0.127.in-addr.arpa', - file : '/data/knot/0.0.127.in-addr.arpa', - }, - { - domain: '160/27.51.128.66.in-addr.arpa', - file : '/data/knot/160/27.51.128.66.in-addr.arpa', - }, - { domain: 'horseshoeing.org', file: '/data/knot/horseshoeing.org' }, - { domain: 'txalamako.org', file: '/data/knot/txalamako.org' }, - { domain: 'theartfarm.com', file: '/data/knot/theartfarm.com' }, - { - domain: '_report._dmarc.theartfarm.com', - file : '/data/knot/_report._dmarc.theartfarm.com', - }, - { domain: 'w8ct.net', file: '/data/knot/w8ct.net' }, - { domain: 'tikismikis.org', file: '/data/knot/tikismikis.org' }, - { domain: 'lynboyer.com', file: '/data/knot/lynboyer.com' }, - { - domain: '_tcp.theartfarm.com', - file : '/data/knot/_tcp.theartfarm.com', - }, - { domain: 'horsenetwork.com', file: '/data/knot/horsenetwork.com' }, - { domain: 'ctacllc.com', file: '/data/knot/ctacllc.com' }, - ], + const r = await ns.parseConfig(buf.toString()) + // console.dir(r, { depth: null }) + assert.deepEqual(r, { + zone: [ + { + domain: '0.0.127.in-addr.arpa', + file : '/data/knot/0.0.127.in-addr.arpa', + }, + { + domain: '160/27.51.128.66.in-addr.arpa', + file : '/data/knot/160/27.51.128.66.in-addr.arpa', + }, + { domain: 'horseshoeing.org', file: '/data/knot/horseshoeing.org' }, + { domain: 'txalamako.org', file: '/data/knot/txalamako.org' }, + { domain: 'theartfarm.com', file: '/data/knot/theartfarm.com' }, + { + domain: '_report._dmarc.theartfarm.com', + file : '/data/knot/_report._dmarc.theartfarm.com', + }, + { domain: 'w8ct.net', file: '/data/knot/w8ct.net' }, + { domain: 'tikismikis.org', file: '/data/knot/tikismikis.org' }, + { domain: 'lynboyer.com', file: '/data/knot/lynboyer.com' }, + { + domain: '_tcp.theartfarm.com', + file : '/data/knot/_tcp.theartfarm.com', + }, + { domain: 'horsenetwork.com', file: '/data/knot/horsenetwork.com' }, + { domain: 'ctacllc.com', file: '/data/knot/ctacllc.com' }, + ], + }) }) - }) + }) }) diff --git a/test/mara.js b/test/mara.js new file mode 100644 index 0000000..be1f25f --- /dev/null +++ b/test/mara.js @@ -0,0 +1,54 @@ + +const assert = require('assert') +const fs = require('fs').promises + +const ns = require('../lib/maradns.js') + +describe('maradns', function () { + + describe('parseConfig', function () { + + it('parses mararc', async () => { + const file = './test/fixtures/maradns/mararc' + const buf = await fs.readFile(file) + + const r = await ns.parseConfig(buf.toString()) + // console.dir(r, { depth: null }) + assert.deepEqual(r, { + chroot_dir : '/etc/maradns', + csv2 : '{}', + ipv4_bind_addresses: '127.0.0.1', + maradns_uid : 99, + max_ar_chain : 1, + max_chain : 8, + max_total : 20, + no_fingerprint : 0, + verbose_level : 1, + }) + }) + + it('parses example.com mararc', async () => { + const file = './test/fixtures/maradns/example.com' + const buf = await fs.readFile(file) + + const r = await ns.parseConfig(buf.toString()) + // console.dir(r, { depth: null }) + assert.deepEqual(r, { + 'csv2["example.com."]' : 'db.example.com', + 'csv2["example2.com."]': 'db.example2.com', + chroot_dir : '/etc/maradns', + csv2 : '{}', + ipv4_bind_addresses : '10.1.2.3,10.1.2.4,127.0.0.1', + maradns_gid : 99, + maradns_uid : 99, + max_ar_chain : 1, + max_chain : 8, + max_total : 20, + no_fingerprint : 0, + verbose_level : 3, + zone_transfer_acl : '10.1.1.1/24, 10.100.100.100/255.255.255.224', + }) + }) + + }) +}) diff --git a/test/nsd.js b/test/nsd.js index 0a6f823..a1289d8 100644 --- a/test/nsd.js +++ b/test/nsd.js @@ -2,98 +2,99 @@ const assert = require('assert') const fs = require('fs').promises -const ns = require('../index.js') +const ns = require('../lib/nsd.js') -describe('parseNsdConfig', function () { +describe('nsd', function () { - it('parses nsd.conf', async () => { - const file = './test/fixtures/nsd/nsd.conf' - const buf = await fs.readFile(file) + describe('parseConfig', function () { - const r = await ns.parseNsdConfig(buf.toString()) - // console.dir(r, { depth: null }) - assert.deepEqual(r, { - server: [ - { - 'server-count': '1', - database : '""', - zonelistfile : '"/var/db/nsd/zone.list"', - username : 'nsd', - logfile : '"/var/log/nsd.log"', - pidfile : '"/var/run/nsd.pid"', - xfrdfile : '"/var/db/nsd/xfrd.state"', - }, - ], - zone: [ - { name: 'example.com', zonefile: '/etc/nsd/example.com.zone' }, - { - name : 'masterzone.com', - zonefile : '/etc/nsd/masterzone.com.zone', - notify : '192.0.2.1 NOKEY', - 'provide-xfr': '192.0.2.1 NOKEY', - }, - { - name : 'secondzone.com', - zonefile : '/etc/nsd/secondzone.com.zone', - 'allow-notify': '192.0.2.2 NOKEY', - 'request-xfr' : '192.0.2.2 NOKEY', - }, - ], - }) - }) + it('parses nsd.conf', async () => { + const file = './test/fixtures/nsd/nsd.conf' + const buf = await fs.readFile(file) + const r = await ns.parseConfig(buf.toString()) + // console.dir(r, { depth: null }) + assert.deepEqual(r, { + server: [ + { + 'server-count': '1', + database : '', + zonelistfile : '/var/db/nsd/zone.list', + username : 'nsd', + logfile : '/var/log/nsd.log', + pidfile : '/var/run/nsd.pid', + xfrdfile : '/var/db/nsd/xfrd.state', + }, + ], + zone: [ + { name: 'example.com', zonefile: '/etc/nsd/example.com.zone' }, + { + name : 'masterzone.com', + zonefile : '/etc/nsd/masterzone.com.zone', + notify : '192.0.2.1 NOKEY', + 'provide-xfr': '192.0.2.1 NOKEY', + }, + { + name : 'secondzone.com', + zonefile : '/etc/nsd/secondzone.com.zone', + 'allow-notify': '192.0.2.2 NOKEY', + 'request-xfr' : '192.0.2.2 NOKEY', + }, + ], + }) + }) - it('parses example.com', async () => { - const file = './test/fixtures/nsd/example.com' - const buf = await fs.readFile(file) + it('parses example.com', async () => { + const file = './test/fixtures/nsd/example.com' + const buf = await fs.readFile(file) - const r = await ns.parseNsdConfig(buf.toString()) - // console.dir(r, { depth: null }) - assert.deepEqual(r, { - server: [ - { - 'server-count': '1', - database : '""', - logfile : '"/var/log/nsd.log"', - pidfile : '"/var/run/nsd.pid"', - username : 'nsd', - }, - ], - zone: [ - { - name : 'example.com', - zonefile: '/etc/nsd/example.com.zone', - }, - ], + const r = await ns.parseConfig(buf.toString()) + // console.dir(r, { depth: null }) + assert.deepEqual(r, { + server: [ + { + 'server-count': '1', + database : '', + logfile : '/var/log/nsd.log', + pidfile : '/var/run/nsd.pid', + username : 'nsd', + }, + ], + zone: [ + { + name : 'example.com', + zonefile: '/etc/nsd/example.com.zone', + }, + ], + }) }) - }) - it('parses ns3.cadillac.net.conf', async () => { - const file = './test/fixtures/nsd/ns2.cadillac.net.conf' - const buf = await fs.readFile(file) + it('parses ns3.cadillac.net.conf', async () => { + const file = './test/fixtures/nsd/ns2.cadillac.net.conf' + const buf = await fs.readFile(file) - const r = await ns.parseNsdConfig(buf.toString()) - // console.dir(r, { depth: null }) - assert.deepEqual(r, { - zone: [ - { - name : 'emeraldparadise.realty', - zonefile: '/data/nsd/emeraldparadise.realty', - }, - { name: 'virus.realty', zonefile: '/data/nsd/virus.realty' }, - { - name : 'insanangelotx.realty', - zonefile: '/data/nsd/insanangelotx.realty', - }, - { - name : 'bluehawaii.realty', - zonefile: '/data/nsd/bluehawaii.realty', - }, - { name: 'iz.feedback', zonefile: '/data/nsd/iz.feedback' }, - { name: 'raveis.realty', zonefile: '/data/nsd/raveis.realty' }, - ], + const r = await ns.parseConfig(buf.toString()) + // console.dir(r, { depth: null }) + assert.deepEqual(r, { + zone: [ + { + name : 'emeraldparadise.realty', + zonefile: '/data/nsd/emeraldparadise.realty', + }, + { name: 'virus.realty', zonefile: '/data/nsd/virus.realty' }, + { + name : 'insanangelotx.realty', + zonefile: '/data/nsd/insanangelotx.realty', + }, + { + name : 'bluehawaii.realty', + zonefile: '/data/nsd/bluehawaii.realty', + }, + { name: 'iz.feedback', zonefile: '/data/nsd/iz.feedback' }, + { name: 'raveis.realty', zonefile: '/data/nsd/raveis.realty' }, + ], + }) }) }) - })