Skip to content

Commit

Permalink
named.conf parser, basics (#1)
Browse files Browse the repository at this point in the history
* declare engines 12+
  • Loading branch information
msimerson authored Apr 4, 2022
1 parent 94c2a56 commit 69deaa5
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 3 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Name servers have configuration files, each with their own format. This package
## TODO

- config parser
- [ ] bind
- [x] bind
- [ ] nsd
- [ ] knot
- [ ] maradns
Expand All @@ -31,4 +31,4 @@ Name servers have configuration files, each with their own format. This package
- [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)
+ fix, feature, BREAKING CHANGE, build, chore, ci, docs, style, test
- [keep a changelog](https://keepachangelog.com/)
-
- [sentimental versioning](http://sentimentalversioning.org)
1 change: 1 addition & 0 deletions dist/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!.gitignore
25 changes: 25 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

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
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
"description": "DNS Nameserver",
"main": "index.js",
"bin": {},
"engines" : { "node" : ">=12.0" },
"scripts": {
"bind": "npx -p nearley nearleyc src/bind.ne -o dist/bind.js",
"knot": "npx -p nearley nearleyc src/knot.ne -o dist/knot.js",
"nsd": "npx -p nearley nearleyc src/nsd.ne -o dist/nsd.js",
"mara": "npx -p nearley nearleyc src/mara.ne -o dist/mara.js",
"lint": "npx eslint index.js test/*.js",
"lintfix": "npx eslint --fix index.js test/*.js",
"postinstall": "npm run bind && npm run mara",
"postinstall": "npm run bind",
"release": "npx standard-version",
"test": "npx mocha",
"versions": "npx dependency-version-checker check"
Expand Down
62 changes: 62 additions & 0 deletions src/bind.ne
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
@lexer lexer

main -> (comment | blank | block):* {% id %}

blank -> %blank {% id %}
comment -> %comment {% comment %}
block -> %options (opt | comment):+ %eoblock {% optValue %}
| %logging (opt | comment | optblock):+ %eoblock
| zone {% id %}

opt -> %opt {% optValue %}
optblock -> %optblock
zone -> %zone (zonefile | zonetype | opt | comment):+ %eoblock {% asZone %}
zonefile -> %zonefile {% asZoneFile %}
zonetype -> %zonetype {% asZoneType %}

@{%
const moo = require("moo");

const lexer = moo.compile({
blank: /^\s*?$[\n\r]/,
comment: /^\s*(?:\/\/|#)[^\n]*?\n/,
eoblock: /};\s*\n/,
zone: {
match: /\s*zone\s+[^\s]+\s+(?:in|IN)?\s*{\n/s,
value: f => f.trim().match(/zone\s+"([^"]+)"/)[1]
},
zonetype: /\s*type\s+(?:master|slave|hint);\n/,
zonefile: /\s*file\s+"[^"]*?";\n/,
logging : /\s*logging\s*{$\n/s,
options : /\s*options\s+{$\n/s,
opt : { match: /^\s*[^\n]*?;$\n/s, value: f => f.trim() },
optblock: /^\s*[^\n]+?{[^}]*?};\n/,
nl : { match: /\n\r/, lineBreaks: true },
ws : /[ \t]+/,
});

function comment (d) { return null }
function flatten (d) {
if (!d) return ''
return Array.isArray(d) ? d.flat(Infinity).join('') : d
}
function optValue (d) { return (d.type === 'obj') ? d.value : d }
function asZoneType (d) {
return { ztype: d[0].value.trim().match(/type\s+(\w+?);/)[1] }
}
function asZoneFile (d) {
return { zfile: d[0].value.trim().match(/file\s+"([^\"]+)";/)[1] }
}
function asZone (z) {
if (!Array.isArray(z)) return z
if (z[0] === null) return z[0]
if (typeof z[0] !== 'object') return z[0]

return {
zone: z[0].value,
type: z[1].filter(y => y[0] && y[0].ztype)[0][0].ztype,
file: z[1].filter(y => y[0] && y[0].zfile)[0][0].zfile,
}
}

%}
69 changes: 69 additions & 0 deletions test/fixtures/named.conf-ztrax-master
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// MASTER & CACHING NAME SERVER for EXAMPLE, INC.
// maintained by: me myself alone
// CHANGELOG:
// 1. 9 july 2003 - did something
// 2. 16 july 2003 - did something else
// 3. 23 july 2003 - did something more
//
options {
directory "/var/named";
// version statement - inhibited for security
// (avoids hacking any known weaknesses)
version "get lost";
// optional - disables all transfers
// slaves allowed in zone clauses
allow-transfer {"none";};
// Closed DNS - permits only local IPs to issue recursive queries
// remove if an Open DNS required to support all users
// or add additional ranges
allow-recursion {192.168.3.0/24;};
};
//
// log to /var/log/named/example.log all events from
// info UP in severity (no debug)
// defaults to use 3 files in rotation
// BIND 8.x logging MUST COME FIRST in this file
// BIND 9.x parses the whole file before using the log
// failure messages up to this point are in (syslog)
// typically /var/log/messages
//
logging{
channel example_log{
file "/var/log/named/example.log" versions 3 size 2m;
severity info;
print-severity yes;
print-time yes;
print-category yes;
};
category default{
example_log;
};
};
// required zone for recursive queries
zone "." {
type hint;
file "root.servers";
};
zone "example.com" in{
type master;
file "master/master.example.com";
// enable slaves only
allow-transfer {192.168.23.1;192.168.23.2;};
};
// required local host domain
zone "localhost" in{
type master;
file "master.localhost";
allow-update{none;};
};
// localhost reverse map
zone "0.0.127.in-addr.arpa" in{
type master;
file "localhost.rev";
allow-update{none;};
};
// reverse map for class C 192.168.0.0
zone "0.168.192.IN-ADDR.ARPA" in{
type master;
file "192.168.0.rev";
};
18 changes: 18 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

const assert = require('assert')
const fs = require('fs').promises

const ns = require('../index.js')


describe('parseBindConfig', function () {

it('parses named.conf zone file', async () => {
const file = './test/fixtures/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)
})
})

0 comments on commit 69deaa5

Please sign in to comment.