diff --git a/bin/import.js b/bin/import.js index d8ccaa5..b8ffb87 100755 --- a/bin/import.js +++ b/bin/import.js @@ -19,14 +19,8 @@ console.log(`reading file ${filePath}`) fs.readFile(filePath, (err, buf) => { if (err) throw err - let asString = buf.toString() - const base = path.basename(filePath) - if (!/^\$ORIGIN/m.test(asString)) { - console.log(`inserting $ORIGIN ${base}`) - asString = `$ORIGIN ${base}.${os.EOL}${asString}` - } - // console.log(asString) + const asString = fileAsString(buf, base) dz.parseZoneFile(asString) .then(dz.expandShortcuts) @@ -48,6 +42,17 @@ fs.readFile(filePath, (err, buf) => { }) }) +function fileAsString (buf, base) { + let str = buf.toString() + + if (!/^\$ORIGIN/m.test(str)) { + console.log(`inserting $ORIGIN ${base}`) + str = `$ORIGIN ${base}.${os.EOL}${str}` + } + // console.log(str) + return str +} + function toBind (zoneArray, origin) { for (const rr of zoneArray) { let out = rr.toBind() diff --git a/index.js b/index.js index 3636ad4..a278d56 100644 --- a/index.js +++ b/index.js @@ -40,23 +40,23 @@ exports.expandShortcuts = async zoneArray => { const entry = zoneArray[i] if (entry.$TTL) { - ttl = entry.$TTL - continue + ttl = entry.$TTL; continue } + // When a zone is first read, there is an implicit $ORIGIN . // note the trailing dot. The current $ORIGIN is appended to the domain // specified in the $ORIGIN argument if it is not absolute. -- BIND 9 - if (entry.implicitOrigin) { - implicitOrigin = fullyQualify(entry.implicitOrigin) - origin = fullyQualify(entry.implicitOrigin) + if (entry.implicitOrigin) { // zone 'name' in named.conf + implicitOrigin = origin = fullyQualify(entry.implicitOrigin) continue } - if (entry.$ORIGIN) { + if (entry.$ORIGIN) { // declared $ORIGIN within zone file origin = fullyQualify(entry.$ORIGIN, implicitOrigin) continue } if (!origin) throw new Error(`zone origin ambiguous, cowardly bailing out`) + if (ttl === 0 && entry.type === 'SOA' && entry.minimum) ttl = entry.minimum if (empty.includes(entry.ttl )) entry.ttl = ttl if (empty.includes(entry.class)) entry.class = 'IN' @@ -76,21 +76,7 @@ exports.expandShortcuts = async zoneArray => { if (entry.name !== lastName) lastName = entry.name - // expand rdata shortcuts - switch (entry.type) { - case 'SOA': - for (const f of [ 'mname', 'rname' ]) { - entry[f] = fullyQualify(entry[f], origin) - } - if (entry.minimum && ttl === 0) ttl = entry.minimum - break - case 'MX': - entry.exchange = fullyQualify(entry.exchange, origin) - break - case 'NS': - entry.dname = fullyQualify(entry.dname, origin) - break - } + expandRdata(entry, origin, ttl) try { expanded.push(new RR[entry.type](entry)) @@ -109,3 +95,19 @@ function fullyQualify (hostname, origin) { if (hostname.endsWith('.')) return hostname return `${hostname}.${origin}`.toLowerCase() } + +function expandRdata (entry, origin, ttl) { + switch (entry.type) { + case 'SOA': + for (const f of [ 'mname', 'rname' ]) { + entry[f] = fullyQualify(entry[f], origin) + } + break + case 'MX': + entry.exchange = fullyQualify(entry.exchange, origin) + break + case 'NS': + entry.dname = fullyQualify(entry.dname, origin) + break + } +} \ No newline at end of file diff --git a/src/bind-grammar.ne b/src/bind-grammar.ne index 03c2d2e..fb55da5 100644 --- a/src/bind-grammar.ne +++ b/src/bind-grammar.ne @@ -23,11 +23,11 @@ soa -> hostname ( __ uint ):? ( __ class ):? __ "SOA" __ hostname __ hostname __ "(" - _ uint (_ comment):? - __ uint (_ comment):? - __ uint (_ comment):? - __ uint (_ comment):? - __ uint (_ comment):? + _ uint (ws comment):? + __ uint (ws comment):? + __ uint (ws comment):? + __ uint (ws comment):? + __ uint (ws comment):? _ ")" _ (comment):? {% (d) => toResourceRecord(d) %} @@ -114,6 +114,7 @@ IPv6v4_comp -> (IPv6_hex times_3[":" IPv6_hex]):? "::" # Whitespace: `_` is optional, `__` is mandatory. _ -> wschar:* {% function(d) {return null;} %} __ -> wschar:+ {% function(d) {return null;} %} +ws -> wschar:* {% id %} wschar -> [ \t\n\r\v\f] {% id %} @@ -125,57 +126,63 @@ function flat_string(d) { } function ttlAsObject (d) { - return { $TTL: d[2] } + return { $TTL: d[2] } } function originAsObject (d) { - return { $ORIGIN: d[2] } + return { $ORIGIN: d[2] } } function toResourceRecord (d) { - const r = { - name: d[0], - ttl : d[1] ? d[1][1] : d[1], - class: d[2] ? d[2][1][0] : d[2], - type: d[4], - } - - switch (r.type) { - case 'A': - r.address = d[6] - break - case 'AAAA': - r.address = d[6][0] - break - case 'CNAME': - r.cname = d[6] - break - case 'DNAME': - r.target = d[6] - break - case 'MX': - r.preference = d[6] - r.exchange = d[8] - break - case 'NS': - r.dname = d[6] - break - case 'SOA': - r.mname = d[6] - r.rname = d[8] - r.serial = d[12] - r.refresh = d[15] - r.retry = d[18] - r.expire = d[21] - r.minimum = d[24] - break - case 'TXT': - r.data = d[6].map(e => e[0]) - break - default: - throw new Error(`undefined type: ${r.type}`) - } - return r + const r = { + name: d[0], + ttl : d[1] ? d[1][1] : d[1], + class: d[2] ? d[2][1][0] : d[2], + type: d[4], + } + + switch (r.type) { + case 'A': + r.address = d[6] + break + case 'AAAA': + r.address = d[6][0] + break + case 'CNAME': + r.cname = d[6] + break + case 'DNAME': + r.target = d[6] + break + case 'MX': + r.preference = d[6] + r.exchange = d[8] + break + case 'NS': + r.dname = d[6] + break + case 'SOA': + r.comment = {} + r.mname = d[6] + r.rname = d[8] + r.serial = d[12] + r.comment.serial = flat_string(d[13]) + r.refresh = d[15] + r.comment.refresh = flat_string(d[16]) + r.retry = d[18] + r.comment.retry = flat_string(d[19]) + r.expire = d[21] + r.comment.expire = flat_string(d[22]) + r.minimum = d[24] + r.comment.minimum = flat_string(d[25]) + break + case 'TXT': + r.data = d[6].map(e => e[0]) + break + default: + throw new Error(`undefined type: ${r.type}`) + } + return r } %} diff --git a/test/index.js b/test/index.js index 2c54af3..2f203d2 100644 --- a/test/index.js +++ b/test/index.js @@ -53,6 +53,13 @@ describe('parseZoneFile', function () { retry : 2048, expire : 604800, minimum: 2560, + comment: { + expire : ' ; expiry', + minimum: ' ; minimum', + refresh: ' ; refresh', + retry : ' ; retry', + serial : ' ; serial', + }, }) })