From a31222eef83a2116df785106be75fbd5905e88f0 Mon Sep 17 00:00:00 2001 From: Matt Simerson Date: Thu, 7 Mar 2024 09:53:59 -0800 Subject: [PATCH] Release v1.2.0 (#40) - feat(index): export typeMap (lookup table for type to id) - feat(NXT): added bind support - feat(TSIG, WKS): added stub class - doc(README): move synopsis section into table (#38) - chore(style): set up prettier --- .codeclimate.yml | 8 +- .eslintrc.yaml | 27 ++--- .github/FUNDING.yml | 3 + .github/workflows/ci.yml | 16 +-- .github/workflows/codeql.yml | 4 +- .github/workflows/publish.yml | 2 +- .npmignore | 3 + .prettierrc.yml | 3 + .release | 2 +- CHANGELOG.md | 60 +++-------- DEVELOP.md | 22 +--- README.md | 92 ++++++++--------- index.js | 106 +++++++++++++------ lib/tinydns.js | 129 ++++++++++++----------- package.json | 3 +- rr.js | 188 ++++++++++++++++++++-------------- rr/a.js | 39 ++++--- rr/aaaa.js | 66 ++++++------ rr/caa.js | 80 ++++++++------- rr/cert.js | 40 ++++---- rr/cname.js | 39 ++++--- rr/dname.js | 38 +++---- rr/dnskey.js | 89 ++++++++-------- rr/ds.js | 74 ++++++------- rr/hinfo.js | 51 ++++----- rr/ipseckey.js | 98 ++++++++++-------- rr/key.js | 42 ++++---- rr/loc.js | 121 ++++++++++++---------- rr/mx.js | 50 ++++----- rr/naptr.js | 103 +++++++++---------- rr/ns.js | 47 +++++---- rr/nsec.js | 46 +++++---- rr/nsec3.js | 107 +++++++++++-------- rr/nsec3param.js | 55 +++++----- rr/nxt.js | 67 ++++++++++++ rr/openpgpkey.js | 27 +++-- rr/ptr.js | 41 ++++---- rr/rrsig.js | 48 +++++---- rr/sig.js | 43 ++++---- rr/smimea.js | 63 +++++++----- rr/soa.js | 99 ++++++++++-------- rr/spf.js | 37 ++++--- rr/srv.js | 82 +++++++-------- rr/sshfp.js | 59 ++++++----- rr/tlsa.js | 87 ++++++++-------- rr/tsig.js | 48 +++++++++ rr/txt.js | 73 +++++++------ rr/uri.js | 62 +++++------ rr/wks.js | 44 ++++++++ test/a.js | 11 +- test/aaaa.js | 29 ++++-- test/base.js | 56 +++++----- test/caa.js | 67 ++++++------ test/cert.js | 44 ++++---- test/cname.js | 7 +- test/dname.js | 24 +++-- test/dnskey.js | 21 ++-- test/ds.js | 23 +++-- test/fake.js | 38 ++++--- test/hinfo.js | 37 ++++--- test/ipseckey.js | 140 ++++++++++++++----------- test/key.js | 21 ++-- test/loc.js | 30 +++--- test/mx.js | 41 ++++---- test/naptr.js | 37 ++++--- test/ns.js | 15 +-- test/nsec.js | 15 ++- test/nsec3.js | 31 +++--- test/nsec3param.js | 9 +- test/nxt.js | 37 +++++++ test/openpgpkey.js | 6 +- test/ptr.js | 16 +-- test/rr.js | 82 +++++++++------ test/smimea.js | 30 +++--- test/soa.js | 78 +++++++++----- test/spf.js | 25 +++-- test/srv.js | 66 +++++++----- test/sshfp.js | 57 ++++++----- test/tinydns.js | 61 +++++++---- test/tlsa.js | 47 +++++---- test/txt.js | 64 +++++++----- test/uri.js | 50 ++++----- 82 files changed, 2304 insertions(+), 1744 deletions(-) create mode 100644 .github/FUNDING.yml create mode 100644 .prettierrc.yml create mode 100644 rr/nxt.js create mode 100644 rr/tsig.js create mode 100644 rr/wks.js create mode 100644 test/nxt.js diff --git a/.codeclimate.yml b/.codeclimate.yml index e56fd40..adfe803 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -16,10 +16,10 @@ checks: plugins: eslint: enabled: true - channel: "eslint-8" + channel: 'eslint-8' config: - config: ".eslintrc.yaml" + config: '.eslintrc.yaml' ratings: - paths: - - "**.js" + paths: + - '**.js' diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 098664e..7300f62 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -3,6 +3,7 @@ env: node: true mocha: true es2020: true + es2024: true root: true @@ -13,31 +14,15 @@ extends: - eslint:recommended rules: - quotes: [ error, single, { avoidEscape: true, allowTemplateLiterals: true } ] - semi: [ error, never ] - semi-style: [ error, last ] - no-unused-vars: [ error, { args: none } ] - array-bracket-spacing: [ warn, always, { arraysInArrays: false, objectsInArrays: false } ] - no-trailing-spaces: [ error ] - space-before-function-paren: [ error, always ] - object-curly-spacing: [ error, always ] - indent: [ error, 2, { SwitchCase: 1 } ] - key-spacing: - - warn - - singleLine: - beforeColon: false - afterColon: true - multiLine: - beforeColon: false - afterColon: true - align: colon - mode: minimum + quotes: [error, single, { avoidEscape: true, allowTemplateLiterals: true }] + no-unused-vars: [error, { args: none }] + no-trailing-spaces: [error] + object-curly-spacing: [error, always] comma-dangle: - warn - arrays: always-multiline objects: always-multiline functions: only-multiline - arrow-parens: [ error, as-needed ] - brace-style: [ error, stroustrup ] dot-notation: error prefer-const: warn + no-extra-semi: off diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..53e71ae --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +github: msimerson diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 91f9cd3..f0e07b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,17 +19,17 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ ubuntu-latest, windows-latest, macos-latest ] + os: [ubuntu-latest, windows-latest, macos-latest] node-version: ${{ fromJson(needs.get-lts.outputs.active) }} fail-fast: false steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - name: Node ${{ matrix.node-version }} on ${{ matrix.os }} - with: - node-version: ${{ matrix.node-version }} - - run: npm install - - run: npm test + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + name: Node ${{ matrix.node-version }} on ${{ matrix.os }} + with: + node-version: ${{ matrix.node-version }} + - run: npm install + - run: npm test get-lts: needs: lint diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index fec816c..46e21d1 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -2,10 +2,10 @@ name: CodeQL on: push: - branches: [ main ] + branches: [main] pull_request: # The branches below must be a subset of the branches above - branches: [ main ] + branches: [main] schedule: - cron: '18 7 * * 4' diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 4c300fe..14abdfe 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -13,4 +13,4 @@ env: jobs: publish: uses: NicTool/.github/.github/workflows/publish.yml@main - secrets: inherit \ No newline at end of file + secrets: inherit diff --git a/.npmignore b/.npmignore index 00d4813..0f1a533 100644 --- a/.npmignore +++ b/.npmignore @@ -10,3 +10,6 @@ codecov.yml .travis.yml .eslintrc.yaml .eslintrc.json +.codeclimate.yml +test/ +DEVELOP.md \ No newline at end of file diff --git a/.prettierrc.yml b/.prettierrc.yml new file mode 100644 index 0000000..9b110b8 --- /dev/null +++ b/.prettierrc.yml @@ -0,0 +1,3 @@ +trailingComma: 'all' +semi: false +singleQuote: true diff --git a/.release b/.release index 0890e94..704e50c 160000 --- a/.release +++ b/.release @@ -1 +1 @@ -Subproject commit 0890e945e4e061c96c7b2ab45017525904c17728 +Subproject commit 704e50ce14387d29293bd208d0a6ff290b49d66e diff --git a/CHANGELOG.md b/CHANGELOG.md index 19a3917..0be07b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,45 +2,45 @@ Notable changes to this project are documented in this file. - #### Unreleased +### [1.2.0] - 2024-03-07 + +- feat(index): export typeMap (lookup table for type to id) +- feat(NXT): added bind support +- feat(TSIG, WKS): added stub class +- doc(README): move synopsis section into table (#38) +- chore(style): set up prettier ### [1.1.6] - 2022-06-21 - doc(sshfp): added RFC 7479, 8709 - ### [1.1.5] - 2022-06-03 - ci: auto-populate node LTS versions to run CI tests with - ### [1.1.4] - 2022-05-29 - doc(README): improved develop notes - doc(CHANGELOG): make version numbers links - ### [1.1.3] - 2022-05-29 - chore: publish npm package in @nictool namespace - ### [1.1.2] - 2022-05-28 - chore(ci): replace .release with submodule - chore(ci): use GHA with shared workflows - ### [1.1.1] - 2022-04-28 - feat(DNSKEY): expanded algo from 1-5 to 1-16 (RFC 8624) - - warn if outside that range, not error + - warn if outside that range, not error - feat(HINFO): added to/from tinydns - test(dnskey): update fail test - ### [1.1.0] - 2022-04-22 - feat(tinydns): add ipv4toOctal, octalToIPv4, base64toOctal, octalToBase64 @@ -54,7 +54,6 @@ Notable changes to this project are documented in this file. - test(IPSECKEY): expand test coverage - tinydns.unpackdomain: return fqdn + length, for RRs where the FQDN is part of the byte stream - ### [1.0.1] - 2022-04-19 - feat(IPSECKEY): added basic support @@ -65,7 +64,6 @@ Notable changes to this project are documented in this file. - test(CERT): added two test cases - test(KEY): added valid test - ### [1.0.0] - 2022-04-18 - style: move rr/index to ./rr @@ -73,7 +71,6 @@ Notable changes to this project are documented in this file. - style(esm): convert from CJS to ESM (ES6 module) - test: add base.getRdataFields - ### [0.9.9] - 2022-04-14 - feat: parser improvements (DNSKEY, HINFO, NAPTR, SOA, TLSA, TXT) @@ -83,7 +80,6 @@ Notable changes to this project are documented in this file. - test/rr: update tests with expected error messages - README: move some content to web links - ### [0.9.8] - 2022-04-07 - url updates @@ -91,19 +87,17 @@ Notable changes to this project are documented in this file. - feat: add index.citeRFC - docs: updates - ### [0.9.7] - 2022-03-29 - index - - previousName -> previousOwner - - export a TYPE_MAP (id => name) + - previousName -> previousOwner + - export a TYPE_MAP (id => name) - isValidHostname: allow \ char - add the word 'RFC' in error messages citing RFCs - when rejecting hostname, show the rejected character - maradns: add export support - add index.citeRFC - ### [0.9.6] - 2022-03-27 - rr\*: rename name -> owner (not overloaded) @@ -113,7 +107,6 @@ Notable changes to this project are documented in this file. - add macos testing - add CERT, KEY, NSEC, NSEC3, NSEC3PARAM, OPENPGPKEY, SIG - ### [0.9.5] - 2022-03-26 - README: add docs for getRFCs() @@ -123,7 +116,6 @@ Notable changes to this project are documented in this file. - master: NODE_ENV=cov when running coverage - TXT: pass along zone_opts - ### [0.9.4] - 2022-03-24 - add: getComment @@ -131,15 +123,14 @@ Notable changes to this project are documented in this file. - normalize hostnames to lower case - add tests: fullyQualify, getFQDN - AAAA - - compress: rewrote per RFC 5952, added tests - - internally store address in expanded notation + - compress: rewrote per RFC 5952, added tests + - internally store address in expanded notation - fromTinydns: apply correct semantics for 'x' handling - fullyQualify - - special handling for @ - - consider $ORIGIN + - special handling for @ + - consider $ORIGIN - add uc hex chars to ip6 compress - ### [0.9.3] - 2022-03-22 - hasValidLabels: remove trailing dot, else split returns empty string @@ -155,7 +146,6 @@ Notable changes to this project are documented in this file. - TXT: import BIND format w/o mangling WS - SPF inherits from TXT - ### [0.9.2] - 2022-03-18 - mx: weight -> preference @@ -168,12 +158,10 @@ Notable changes to this project are documented in this file. - validHostname: allow / char - use \_\_dirname to find RR mods - ### [0.9.1] - 2022-03-14 - TLSA, SMIMEA: add BIND support #13 - ### [0.9.0] - 2022-03-10 - added null object instantiation @@ -187,19 +175,16 @@ Notable changes to this project are documented in this file. - tests: more signal, less noise - tests: import tests from nictool 2 - ### [0.8.1] - 2022-03-08 - use RFC example IPs and zone names - ### [0.8.0] - 2022-02-01 - fromBind for: A, AAAA, CNAME, TXT, CNAME, TXT, LOC, MX, NS, SOA, PTR, SPF, SSHFP, URI, CAA, DNAME, NAPTR - add fromTinydns: LOC - rr/\*: add getFields - ### [0.7.0] - 2021-10-26 - tinydns: added octalToHex, octalToUInt16, unpackDomainName, octalToInt8 @@ -207,38 +192,32 @@ Notable changes to this project are documented in this file. - CAA, CNAME, DNAME, SPF, SSHFP, SRV, URI: added fromTinydns - add tests for getRFCs - ### [0.6.0] - 2021-10-25 - tinydns: added octalToChar - A, MX, NS, PTR, SOA, TXT: added fromTinydns - ### [0.5.1] - 2021-10-25 - LOC: added toTinydns - tinydns: add UInt32toOctal - SRV: added support - ### [0.5.0] - 2021-10-24 - NAPTR: add toTinydns - tinydns: remove sprintf-js dependency - ### [0.4.0] - 2021-10-22 - CAA, DNAME, SSHFP, URI: add toTinydns - lib/tinydns: added packHex and UInt16AsOctal - ### [0.3.1] - 2021-10-21 - update index.js to also export RR sub classes - update README examples - ### [0.3.0] - 2021-10-21 - add getRFCs to all RR types @@ -246,7 +225,6 @@ Notable changes to this project are documented in this file. - toBind: use tabs for exported WS - CAA, DNAME, NAPTR, SSHFP, URI: add toBind, tests - ### [0.2.3] - 2021-10-21 - refactored classes into separate files @@ -255,30 +233,25 @@ Notable changes to this project are documented in this file. - lib/tinydns: added escapeOct & packDomainName - PTR, SRV: added tests - ### [0.2.2] - 2021-10-20 -- add tests/* +- add tests/\* - A, AAAA, add toBind and toTinydns() - add .release - ### [0.2.1] - 2021-10-16 - additional RR formats started, weakly validated - ### [0.2.0] - 2021-10-16 - initial release & name grab - # References - [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) - + fix, feature, BREAKING CHANGE, build, chore, ci, docs, style, test - + - fix, feature, BREAKING CHANGE, build, chore, ci, docs, style, test [1.1.3]: https://github.com/NicTool/dns-resource-record/releases/tag/1.1.3 [1.1.2]: https://github.com/NicTool/dns-resource-record/releases/tag/1.1.2 @@ -312,3 +285,4 @@ Notable changes to this project are documented in this file. [1.1.4]: https://github.com/NicTool/dns-resource-record/releases/tag/1.1.4 [1.1.5]: https://github.com/NicTool/dns-resource-record/releases/tag/1.1.5 [1.1.6]: https://github.com/NicTool/dns-resource-record/releases/tag/1.1.6 +[1.1.8]: https://github.com/NicTool/dns-resource-record/releases/tag/1.1.8 diff --git a/DEVELOP.md b/DEVELOP.md index 1ff34d7..a8167c0 100644 --- a/DEVELOP.md +++ b/DEVELOP.md @@ -1,23 +1,9 @@ - # Release process In your local repo: -- make your changes -- git add . -- `.release/do.sh` {major|minor|patch} -- fill in the blanks in CHANGELOG.md -- `.release/push.sh` - -Upon merge to `master`: - -- the new version will be published to NPM. -- a GitHub release will be published. -- a release tag will be committed to the repo. - -## Clean - -`.release/cleanup.sh` +```sh +git submodule update --init --recursive +``` -- will switch to the master branch -- delete the release branch +Read and follow the instructions in .release/README.md diff --git a/README.md b/README.md index 3a3f3a3..eb41360 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ This package is for working with _individual_ Resource Records. For working with Load the index for access to all RR types: ```js -import * as RR from 'dns-resource-record' +import * as RR from '@nictool/dns-resource-record' ``` ### EXAMPLES @@ -179,66 +179,65 @@ A(5) [Map] { Consider this a "running with scissors" mode. - ## Supported Records This module intends to include support for all current (ie, not officially deprecated) DNS RRs **and** all RRs that are in active use on the internet. PRs are welcome, especially PRs with tests. -| **RR** | **toBind** | **toTinydns** | **fromBind** | **fromTinydns** | -|:---------: |:----------------:|:----------------:|:----------------:|:----------------:| -| **A** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| -| **AAAA** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| -| **CAA** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| -| **CERT** |:white_check_mark:| |:white_check_mark:| | -| **CNAME** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| -| **DNAME** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| -| **DNSKEY** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| -| **DS** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| -| **HINFO** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| -|**IPSECKEY**|:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| -| **KEY** | | | | | -| **LOC** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| -| **MX** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| -| **NAPTR** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| -| **NS** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| -| **NSEC** |:white_check_mark:| |:white_check_mark:| | -| **NSEC3** |:white_check_mark:|:white_check_mark:|:white_check_mark:| | -| **NSEC3PARAM**| | | | | -| **OPENPGPKEY**| | | | | -| **PTR** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| -| **RRSIG** | | | | | -| **SIG** | | | | | -| **SMIMEA** |:white_check_mark:| |:white_check_mark:| | -| **SOA** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| -| **SPF** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| -| **SRV** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| -| **SSHFP** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| -| **TLSA** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| -| **TXT** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| -| **URI** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:| - +| **RR** | **toBind** | **toTinydns** | **fromBind** | **fromTinydns** | +| :------------: | :----------------: | :----------------: | :----------------: | :----------------: | +| **A** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **AAAA** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **CAA** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **CERT** | :white_check_mark: | | :white_check_mark: | | +| **CNAME** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **DNAME** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **DNSKEY** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **DS** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **HINFO** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **IPSECKEY** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **KEY** | | | | | +| **LOC** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **MX** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **NAPTR** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **NS** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **NSEC** | :white_check_mark: | | :white_check_mark: | | +| **NSEC3** | :white_check_mark: | :white_check_mark: | :white_check_mark: | | +| **NSEC3PARAM** | | | | | +| **NXT** | | | | | +| **OPENPGPKEY** | | | | | +| **PTR** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **RRSIG** | | | | | +| **SIG** | | | | | +| **SMIMEA** | :white_check_mark: | | :white_check_mark: | | +| **SOA** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **SPF** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **SRV** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **SSHFP** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **TLSA** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **TSIG** | | | | | +| **TXT** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **URI** | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| **WKS** | | | | | ## TIPS - Domain owner names are: - - stored fully qualified, aka absolute. - - normalized to lower case, because: - - DNS is case insensitive (see RFCs 4343, 1035, 1034) - - this library enforces duplicate suppression - - DNSSEC canonicalization (see RFC 4034) - - wire format for most RRs require it - - Master Zone File expansions exist in [dns-zone](https://github.com/NicTool/dns-zone) + - stored fully qualified, aka absolute. + - normalized to lower case, because: + - DNS is case insensitive (see RFCs 4343, 1035, 1034) + - this library enforces duplicate suppression + - DNSSEC canonicalization (see RFC 4034) + - wire format for most RRs require it + - Master Zone File expansions exist in [dns-zone](https://github.com/NicTool/dns-zone) - to{Bind|MaraDNS} output can be influenced (suppress TTL, class, relative domain names) with an options object. See it in `bin/dns-zone` in the [dns-zone](https://github.com/NicTool/dns-zone) package. - ## SEE ALSO - [Dictionary of DNS terms](https://nictool.github.io/web/Dictionary) - [Wikipedia, List of DNS Record Types](https://en.wikipedia.org/wiki/List_of_DNS_record_types) - ## TODO - [x] Change all IPs to use [RFC example/doc](https://en.wikipedia.org/wiki/Reserved_IP_addresses) address space @@ -249,15 +248,14 @@ PRs are welcome, especially PRs with tests. - [x] CERT RRs: CERT, KEY, SIG, OPENPGPKEY - [x] RFC 4034: if the type of RR is NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR, HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT, - NAPTR, KX, SRV, DNAME, A6, RRSIG, or NSEC, all uppercase + NAPTR, KX, SRV, DNAME, A6, RRSIG, or NSEC, all uppercase letters in the DNS names contained within the RDATA are replaced by the lowercase letters; - [x] LOC record ingest/out isn't consistent with API - [ ] export a web page for each RR type - ## DEVELOP - There are no dependencies. That's no accident. - ES modules for use by node.js and browser - Platform independence is a goal - - [x] CI tests are on linux, windows, and macos + - [x] CI tests are on linux, windows, and macos diff --git a/index.js b/index.js index 7f22ea8..bb5e6a9 100644 --- a/index.js +++ b/index.js @@ -1,35 +1,39 @@ +const typeMap = {} -import RR from './rr.js' -import A from './rr/a.js' -import AAAA from './rr/aaaa.js' -import CAA from './rr/caa.js' -import CERT from './rr/cert.js' -import CNAME from './rr/cname.js' -import DNAME from './rr/dname.js' -import DNSKEY from './rr/dnskey.js' -import DS from './rr/ds.js' -import HINFO from './rr/hinfo.js' +import RR from './rr.js' +import A from './rr/a.js' +import AAAA from './rr/aaaa.js' +import CAA from './rr/caa.js' +import CERT from './rr/cert.js' +import CNAME from './rr/cname.js' +import DNAME from './rr/dname.js' +import DNSKEY from './rr/dnskey.js' +import DS from './rr/ds.js' +import HINFO from './rr/hinfo.js' import IPSECKEY from './rr/ipseckey.js' -import KEY from './rr/key.js' -import LOC from './rr/loc.js' -import MX from './rr/mx.js' -import NAPTR from './rr/naptr.js' -import NS from './rr/ns.js' -import NSEC from './rr/nsec.js' -import NSEC3 from './rr/nsec3.js' +import KEY from './rr/key.js' +import LOC from './rr/loc.js' +import MX from './rr/mx.js' +import NAPTR from './rr/naptr.js' +import NS from './rr/ns.js' +import NSEC from './rr/nsec.js' +import NSEC3 from './rr/nsec3.js' import NSEC3PARAM from './rr/nsec3param.js' +import NXT from './rr/nxt.js' import OPENPGPKEY from './rr/openpgpkey.js' -import PTR from './rr/ptr.js' -import RRSIG from './rr/rrsig.js' -import SIG from './rr/sig.js' -import SMIMEA from './rr/smimea.js' -import SOA from './rr/soa.js' -import SPF from './rr/spf.js' -import SRV from './rr/srv.js' -import SSHFP from './rr/sshfp.js' -import TLSA from './rr/tlsa.js' -import TXT from './rr/txt.js' -import URI from './rr/uri.js' +import PTR from './rr/ptr.js' +import RRSIG from './rr/rrsig.js' +import SIG from './rr/sig.js' +import SMIMEA from './rr/smimea.js' +import SOA from './rr/soa.js' +import SPF from './rr/spf.js' +import SRV from './rr/srv.js' +import SSHFP from './rr/sshfp.js' +import TLSA from './rr/tlsa.js' +import TSIG from './rr/tsig.js' +import TXT from './rr/txt.js' +import URI from './rr/uri.js' +import WKS from './rr/wks.js' export default RR @@ -52,6 +56,7 @@ export { NSEC, NSEC3, NSEC3PARAM, + NXT, OPENPGPKEY, PTR, RRSIG, @@ -62,6 +67,49 @@ export { SPF, SRV, TLSA, + TSIG, TXT, - URI + URI, + WKS, + typeMap, +} + +for (const c of [ + A, + AAAA, + CAA, + CERT, + CNAME, + DNAME, + DNSKEY, + DS, + HINFO, + IPSECKEY, + KEY, + LOC, + MX, + NAPTR, + NS, + NSEC, + NSEC3, + NSEC3PARAM, + NXT, + OPENPGPKEY, + PTR, + RRSIG, + SIG, + SMIMEA, + SSHFP, + SOA, + SPF, + SRV, + TLSA, + TSIG, + TXT, + URI, + WKS, +]) { + const id = new c(null).getTypeId() + typeMap[id] = c.name + typeMap[c.name] = id } diff --git a/lib/tinydns.js b/lib/tinydns.js index 2c94fe6..e78f2b5 100644 --- a/lib/tinydns.js +++ b/lib/tinydns.js @@ -1,83 +1,88 @@ - -export const SPECIALCHARS = { - '+': [ 'A' ], - '-': [ undefined ], // disabled RR - '%': [ 'location' ], - '.': [ 'SOA', 'NS', 'A' ], - '&': [ 'NS', 'A' ], - '=': [ 'A', 'PTR' ], - '@': [ 'MX', 'A' ], - '#': [ 'comment' ], - "'": [ 'TXT' ], - '^': [ 'PTR' ], - 'C': [ 'CNAME' ], - 'Z': [ 'SOA' ], - ':': [ 'generic' ], - '3': [ 'AAAA' ], - '6': [ 'AAAA', 'PTR' ], - 'S': [ 'SRV' ], +export const SPECIAL_CHARS = { + '+': ['A'], + '-': [undefined], // disabled RR + '%': ['location'], + '.': ['SOA', 'NS', 'A'], + '&': ['NS', 'A'], + '=': ['A', 'PTR'], + '@': ['MX', 'A'], + '#': ['comment'], + "'": ['TXT'], + '^': ['PTR'], + C: ['CNAME'], + Z: ['SOA'], + ':': ['generic'], + 3: ['AAAA'], + 6: ['AAAA', 'PTR'], + S: ['SRV'], } const octalRe = new RegExp(/\\(?:[1-7][0-7]{0,2}|[0-7]{2,3})/, 'g') -export function escapeOctal (re, str) { +export function escapeOctal(re, str) { let escaped = '' - str.split(/(.{1})/g).map(c => { + str.split(/(.{1})/g).map((c) => { escaped += re.test(c) ? charToOctal(c) : c }) return escaped } -export function octalToChar (str) { +export function octalToChar(str) { // relace instances of \NNN with ASCII - return str.replace(octalRe, o => String.fromCharCode(parseInt(o.substring(1), 8))) + return str.replace(octalRe, (o) => + String.fromCharCode(parseInt(o.substring(1), 8)), + ) } -export function octalToHex (str) { +export function octalToHex(str) { // relace instances of \NNN with Hex - return str.replace(octalRe, o => { + return str.replace(octalRe, (o) => { // parseInt(n, 8) -> from octal to decimal // .toString(16) -> decimal to hex return parseInt(o.substring(1), 8).toString(16).padStart(2, 0) }) } -export function octalToUInt8 (str) { +export function octalToUInt8(str) { const b = Buffer.alloc(1) - b.writeUInt8(parseInt(str.substring(1,4), 8), 0) + b.writeUInt8(parseInt(str.substring(1, 4), 8), 0) return b.readUInt8() } -export function octalToUInt16 (str) { +export function octalToUInt16(str) { const b = Buffer.alloc(2) - b.writeUInt8(parseInt(str.substring(1,4), 8), 0) - b.writeUInt8(parseInt(str.substring(5,8), 8), 1) + b.writeUInt8(parseInt(str.substring(1, 4), 8), 0) + b.writeUInt8(parseInt(str.substring(5, 8), 8), 1) return b.readUInt16BE() } -export function octalToUInt32 (str) { +export function octalToUInt32(str) { const b = Buffer.alloc(4) - b.writeUInt8(parseInt(str.substring(1,4), 8), 0) - b.writeUInt8(parseInt(str.substring(5,8), 8), 1) - b.writeUInt8(parseInt(str.substring(9,12), 8), 2) - b.writeUInt8(parseInt(str.substring(13,16), 8), 3) + b.writeUInt8(parseInt(str.substring(1, 4), 8), 0) + b.writeUInt8(parseInt(str.substring(5, 8), 8), 1) + b.writeUInt8(parseInt(str.substring(9, 12), 8), 2) + b.writeUInt8(parseInt(str.substring(13, 16), 8), 3) return b.readUInt32BE() } -export function packString (str) { - return str.match(/(.{1,255})/g).map(s => { - const len = Buffer.alloc(1) - len.writeUInt8(s.length) - return `${UInt8toOctal(len.readUInt8(0))}${s}` - }).join('') +export function packString(str) { + return str + .match(/(.{1,255})/g) + .map((s) => { + const len = Buffer.alloc(1) + len.writeUInt8(s.length) + return `${UInt8toOctal(len.readUInt8(0))}${s}` + }) + .join('') } -export function unpackString (str) { +export function unpackString(str) { const asBuf = Buffer.from(octalToChar(str.toString())) const res = [] let pos = 0 let len - while ((len = asBuf.readUInt8(pos))) { // encoded length byte + while ((len = asBuf.readUInt8(pos))) { + // encoded length byte pos++ res.push(asBuf.slice(pos, pos + len).toString()) pos = +(pos + len) @@ -86,13 +91,13 @@ export function unpackString (str) { return res } -export function packDomainName (fqdn) { +export function packDomainName(fqdn) { const labelRegEx = new RegExp(/[^A-Za-z0-9-.]/, 'g') // RFC 1035, 3.3 Standard RRs // The standard wire format for DNS names. (1 octet length + octets) let packed = '' - fqdn.split('.').map(label => { + fqdn.split('.').map((label) => { if (label === undefined || !label.length) return const len = Buffer.alloc(1) @@ -105,14 +110,14 @@ export function packDomainName (fqdn) { return packed } -export function unpackDomainName (fqdn) { - +export function unpackDomainName(fqdn) { fqdn = Buffer.from(octalToChar(fqdn.toString())) const labels = [] let pos = 0 let len - while ((len = fqdn.readUInt8(pos))) { // encoded length byte + while ((len = fqdn.readUInt8(pos))) { + // encoded length byte pos++ labels.push(fqdn.slice(pos, pos + len).toString()) pos = +(pos + len) @@ -120,31 +125,31 @@ export function unpackDomainName (fqdn) { const r = `${labels.join('.')}.` // char position + length of last label + label length chars + null byte const strLen = pos + len + labels.length * 4 + 1 - return [ r, strLen ] + return [r, strLen] } -export function packHex (str) { +export function packHex(str) { let r = '' - for (let i = 0; i < str.length; i = i+2) { + for (let i = 0; i < str.length; i = i + 2) { // nibble off 2 hex bytes, encode to octal - r += UInt8toOctal(parseInt(str.slice(i, i+2), 16)) + r += UInt8toOctal(parseInt(str.slice(i, i + 2), 16)) } return r } -export function charToOctal (c) { +export function charToOctal(c) { if (typeof c === 'number') return UInt8toOctal(c) return UInt8toOctal(c.charCodeAt(0)) } -export function UInt8toOctal (n) { +export function UInt8toOctal(n) { if (n > 255) throw new Error('UInt8toOctal does not work on numbers > 255') return `\\${parseInt(n, 10).toString(8).padStart(3, 0)}` } -export function UInt16toOctal (n) { +export function UInt16toOctal(n) { let r = '' const pri = Buffer.alloc(2) pri.writeUInt16BE(n) @@ -153,7 +158,7 @@ export function UInt16toOctal (n) { return r } -export function UInt32toOctal (n) { +export function UInt32toOctal(n) { let r = '' const pri = Buffer.alloc(4) pri.writeUInt32BE(n) @@ -163,24 +168,26 @@ export function UInt32toOctal (n) { return r } -export function ipv4toOctal (ip) { +export function ipv4toOctal(ip) { return UInt32toOctal(ip.split`.`.reduce((int, value) => int * 256 + +value)) } -export function octalToIPv4 (str) { +export function octalToIPv4(str) { const asInt = octalToUInt32(str) - return [ 24,16,8,0 ].map(n => (asInt >> n) & 0xff).join('.') + return [24, 16, 8, 0].map((n) => (asInt >> n) & 0xff).join('.') } -export function base64toOctal (str) { +export function base64toOctal(str) { const bytes = Buffer.from(str, 'base64') let escaped = '' for (const b of bytes) { - escaped += /[A-Za-z0-9\-.]/.test(String.fromCharCode(b)) ? String.fromCharCode(b) : UInt8toOctal(b) + escaped += /[A-Za-z0-9\-.]/.test(String.fromCharCode(b)) + ? String.fromCharCode(b) + : UInt8toOctal(b) } return escaped } -export function octalToBase64 (str) { +export function octalToBase64(str) { return Buffer.from(octalToChar(str), 'binary').toString('base64') } diff --git a/package.json b/package.json index 77a1e73..6cb5617 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@nictool/dns-resource-record", - "version": "1.1.7", + "version": "1.2.0", "description": "DNS Resource Records", "main": "index.js", "type": "module", @@ -39,7 +39,6 @@ }, "homepage": "https://github.com/NicTool/dns-resource-record#readme", "devDependencies": { - "eslint": "^8.56.0", "mocha": "^10.3.0" } } diff --git a/rr.js b/rr.js index a049f16..a7ba890 100644 --- a/rr.js +++ b/rr.js @@ -1,6 +1,5 @@ - export default class RR extends Map { - constructor (opts) { + constructor(opts) { super() if (opts === null) return @@ -15,36 +14,40 @@ export default class RR extends Map { this.setTimestamp(opts?.timestamp) this.setOwner(opts?.owner) - this.setType (opts?.type) - this.setTtl (opts?.ttl) + this.setType(opts?.type) + this.setTtl(opts?.ttl) this.setClass(opts?.class) for (const f of this.getFields('rdata')) { const fnName = `set${this.ucfirst(f)}` - if (this[fnName] === undefined) throw new Error(`Missing ${fnName} in class ${this.get('type')}`) + if (this[fnName] === undefined) + throw new Error(`Missing ${fnName} in class ${this.get('type')}`) this[fnName](opts[f]) } if (opts.comment) this.set('comment', opts.comment) } - ucfirst (str) { - return str.split(/\s/).map(w => w.charAt(0).toUpperCase() + w.slice(1)).join('') + ucfirst(str) { + return str + .split(/\s/) + .map((w) => w.charAt(0).toUpperCase() + w.slice(1)) + .join('') } - setClass (c) { + setClass(c) { switch (c) { - case 'IN': // 1 + case 'IN': // 1 case undefined: case null: case '': this.set('class', 'IN') break - case 'CS': // 2 - case 'CH': // 3 - case 'HS': // 4 - case 'NONE': // 254 - case 'ANY': // 255 + case 'CS': // 2 + case 'CH': // 3 + case 'HS': // 4 + case 'NONE': // 254 + case 'ANY': // 255 this.set('class', c) break default: @@ -52,7 +55,7 @@ export default class RR extends Map { } } - setLocation (l) { + setLocation(l) { switch (l) { case undefined: return @@ -61,7 +64,7 @@ export default class RR extends Map { } } - setTimestamp (l) { + setTimestamp(l) { switch (l) { case undefined: return @@ -70,32 +73,35 @@ export default class RR extends Map { } } - setOwner (n) { + setOwner(n) { if (n === undefined) throw new Error(`owner is required`) if (n.length < 1 || n.length > 255) - throw new Error('Domain names must have 1-255 octets (characters): RFC 2181') + throw new Error( + 'Domain names must have 1-255 octets (characters): RFC 2181', + ) this.isFullyQualified('', 'owner', n) this.hasValidLabels(n) // wildcard records: RFC 1034, 4592 if (/\*/.test(n)) { - if (!/^\*\./.test(n) && !/\.\*\./.test(n)) throw new Error('only *.something or * (by itself) is a valid wildcard') + if (!/^\*\./.test(n) && !/\.\*\./.test(n)) + throw new Error('only *.something or * (by itself) is a valid wildcard') } this.set('owner', n.toLowerCase()) } - setTtl (t) { - + setTtl(t) { if (t === undefined) t = this?.default?.ttl if (t === undefined) { - if ([ 'SOA', 'SSHPF' ].includes(this.get('type'))) return + if (['SOA', 'SSHPF'].includes(this.get('type'))) return throw new Error('TTL is required, no default available') } - if (typeof t !== 'number') throw new Error(`TTL must be numeric (${typeof t})`) + if (typeof t !== 'number') + throw new Error(`TTL must be numeric (${typeof t})`) // RFC 1035, 2181 this.is32bitInt(this.owner, 'TTL', t) @@ -103,7 +109,7 @@ export default class RR extends Map { this.set('ttl', t) } - setType (t) { + setType(t) { switch (t) { case '': case undefined: @@ -116,11 +122,11 @@ export default class RR extends Map { this.set('type', t.toUpperCase()) } - citeRFC () { + citeRFC() { return `see RFC ${this.getRFCs()}` } - fullyQualify (hostname, origin) { + fullyQualify(hostname, origin) { if (!hostname) return hostname if (hostname === '@' && origin) hostname = origin if (hostname.endsWith('.')) return hostname.toLowerCase() @@ -128,7 +134,7 @@ export default class RR extends Map { return `${hostname}.` } - getPrefix (zone_opts = {}) { + getPrefix(zone_opts = {}) { const classVal = zone_opts.hide?.class ? '' : this.get('class') let rrTTL = this.get('ttl') @@ -137,25 +143,24 @@ export default class RR extends Map { let owner = this.get('owner') if (zone_opts.hide?.sameOwner && zone_opts.previousOwner === owner) { owner = '' - } - else { + } else { owner = this.getFQDN('owner', zone_opts) } return `${owner}\t${rrTTL}\t${classVal}\t${this.get('type')}` } - getEmpty (prop) { + getEmpty(prop) { return this.get(prop) === undefined ? '' : this.get(prop) } - getComment (prop) { + getComment(prop) { const c = this.get('comment') if (!c || !c[prop]) return '' return c[prop] } - getQuoted (prop) { + getQuoted(prop) { // if prop is not in quoted list, return bare if (!this.getQuotedFields().includes(prop)) return this.get(prop) @@ -165,16 +170,16 @@ export default class RR extends Map { return `"${this.get(prop)}"` // add double quotes } - getQuotedFields () { + getQuotedFields() { return [] } - getRdataFields () { + getRdataFields() { return [] } - getFields (arg) { - const commonFields = [ 'owner', 'ttl', 'class', 'type' ] + getFields(arg) { + const commonFields = ['owner', 'ttl', 'class', 'type'] Object.freeze(commonFields) switch (arg) { @@ -187,23 +192,24 @@ export default class RR extends Map { } } - getFQDN (field, zone_opts = {}) { + getFQDN(field, zone_opts = {}) { let fqdn = this.get(field) if (!fqdn) throw new Error(`empty value for field ${field}`) if (!fqdn.endsWith('.')) fqdn += '.' if (zone_opts.hide?.origin && zone_opts.origin) { if (fqdn === zone_opts.origin) return '@' - if (fqdn.endsWith(zone_opts.origin)) return fqdn.slice(0, fqdn.length - zone_opts.origin.length - 1) + if (fqdn.endsWith(zone_opts.origin)) + return fqdn.slice(0, fqdn.length - zone_opts.origin.length - 1) } return fqdn } - getTinyFQDN (field) { + getTinyFQDN(field) { const val = this.get(field) - if (val === '') return val // empty - if (val === '.') return val // null MX + if (val === '') return val // empty + if (val === '.') return val // null MX // strip off trailing ., tinydns doesn't require it for FQDN if (val.endsWith('.')) return val.slice(0, -1) @@ -211,15 +217,17 @@ export default class RR extends Map { return val } - getTinydnsGeneric (rdata) { + getTinydnsGeneric(rdata) { return `:${this.getTinyFQDN('owner')}:${this.getTypeId()}:${rdata}:${this.getTinydnsPostamble()}\n` } - getTinydnsPostamble () { - return [ 'ttl', 'timestamp', 'location' ].map(f => this.getEmpty(f)).join(':') + getTinydnsPostamble() { + return ['ttl', 'timestamp', 'location'] + .map((f) => this.getEmpty(f)) + .join(':') } - hasValidLabels (hostname) { + hasValidLabels(hostname) { // RFC 952 defined valid hostnames // RFC 1035 limited domain label chars to letters, digits, and hyphen // RFC 1123 allowed hostnames to start with a digit @@ -231,64 +239,90 @@ export default class RR extends Map { } } - is8bitInt (type, field, value) { - if (typeof value === 'number' - && parseInt(value, 10) === value // assure integer - && value >= 0 - && value <= 255) return true - - throw new Error(`${type} ${field} must be a 8-bit integer (in the range 0-255)`) + is8bitInt(type, field, value) { + if ( + typeof value === 'number' && + parseInt(value, 10) === value && // assure integer + value >= 0 && + value <= 255 + ) + return true + + throw new Error( + `${type} ${field} must be a 8-bit integer (in the range 0-255)`, + ) } - is16bitInt (type, field, value) { - if (typeof value === 'number' - && parseInt(value, 10) === value // assure integer - && value >= 0 - && value <= 65535) return true - - throw new Error(`${type} ${field} must be a 16-bit integer (in the range 0-65535)`) + is16bitInt(type, field, value) { + if ( + typeof value === 'number' && + parseInt(value, 10) === value && // assure integer + value >= 0 && + value <= 65535 + ) + return true + + throw new Error( + `${type} ${field} must be a 16-bit integer (in the range 0-65535)`, + ) } - is32bitInt (type, field, value) { - if (typeof value === 'number' - && parseInt(value, 10) === value // assure integer - && value >= 0 - && value <= 2147483647) return true - - throw new Error(`${type} ${field} must be a 32-bit integer (in the range 0-2147483647)`) + is32bitInt(type, field, value) { + if ( + typeof value === 'number' && + parseInt(value, 10) === value && // assure integer + value >= 0 && + value <= 2147483647 + ) + return true + + throw new Error( + `${type} ${field} must be a 32-bit integer (in the range 0-2147483647)`, + ) } - isQuoted (val) { + isQuoted(val) { return /^["']/.test(val) && /["']$/.test(val) } - isFullyQualified (type, blah, hostname) { + isFullyQualified(type, blah, hostname) { if (hostname.endsWith('.')) return true throw new Error(`${type}: ${blah} must be fully qualified`) } - isValidHostname (type, field, hostname) { + isValidHostname(type, field, hostname) { const allowed = new RegExp(/[^a-zA-Z0-9\-._/\\]/) if (!allowed.test(hostname)) return true const matches = allowed.exec(hostname) - throw new Error(`${type}, ${field} has invalid hostname character (${matches[0]})`) + throw new Error( + `${type}, ${field} has invalid hostname character (${matches[0]})`, + ) } - toBind (zone_opts) { - return `${this.getPrefix(zone_opts)}\t${this.getRdataFields().map(f => this.getQuoted(f)).join('\t')}\n` + toBind(zone_opts) { + return `${this.getPrefix(zone_opts)}\t${this.getRdataFields() + .map((f) => this.getQuoted(f)) + .join('\t')}\n` } - toMaraDNS () { + toMaraDNS() { const type = this.get('type') - const supportedTypes = 'A PTR MX AAAA SRV NAPTR NS SOA TXT SPF RAW FQDN4 FQDN6 CNAME HINFO WKS LOC'.split(/\s+/g) + const supportedTypes = + 'A PTR MX AAAA SRV NAPTR NS SOA TXT SPF RAW FQDN4 FQDN6 CNAME HINFO WKS LOC'.split( + /\s+/g, + ) if (!supportedTypes.includes(type)) return this.toMaraGeneric() - return `${this.get('owner')}\t+${this.get('ttl')}\t${type}\t${this.getRdataFields().map(f => this.getQuoted(f)).join('\t')} ~\n` + return `${this.get('owner')}\t+${this.get('ttl')}\t${type}\t${this.getRdataFields() + .map((f) => this.getQuoted(f)) + .join('\t')} ~\n` } - toMaraGeneric () { + toMaraGeneric() { // throw new Error(`\nMaraDNS does not support ${type} records yet and this package does not support MaraDNS generic records. Yet.\n`) - return `${this.get('owner')}\t+${this.get('ttl')}\tRAW ${this.getTypeId()}\t'${this.getRdataFields().map(f => this.getQuoted(f)).join(' ')}' ~\n` + return `${this.get('owner')}\t+${this.get('ttl')}\tRAW ${this.getTypeId()}\t'${this.getRdataFields() + .map((f) => this.getQuoted(f)) + .join(' ')}' ~\n` } } diff --git a/rr/a.js b/rr/a.js index 31528b3..0daaa96 100644 --- a/rr/a.js +++ b/rr/a.js @@ -1,57 +1,56 @@ - import net from 'net' import RR from '../rr.js' export default class A extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setAddress (val) { + setAddress(val) { if (!val) throw new Error('A: address is required') if (!net.isIPv4(val)) throw new Error('A address must be IPv4') this.set('address', val) } - getDescription () { + getDescription() { return 'Address' } - getRdataFields (arg) { - return [ 'address' ] + getRdataFields(arg) { + return ['address'] } - getRFCs () { - return [ 1035 ] + getRFCs() { + return [1035] } - getTypeId () { + getTypeId() { return 1 } /****** IMPORTERS *******/ - fromTinydns (opts) { + fromTinydns(opts) { // +fqdn:ip:ttl:timestamp:lo - const [ owner, ip, ttl, ts, loc ] = opts.tinyline.substring(1).split(':') + const [owner, ip, ttl, ts, loc] = opts.tinyline.substring(1).split(':') return new A({ - owner : this.fullyQualify(owner), - type : 'A', - address : ip, - ttl : parseInt(ttl, 10), + owner: this.fullyQualify(owner), + type: 'A', + address: ip, + ttl: parseInt(ttl, 10), timestamp: ts, - location : loc !== '' && loc !== '\n' ? loc : '', + location: loc !== '' && loc !== '\n' ? loc : '', }) } - fromBind (opts) { + fromBind(opts) { // test.example.com 3600 IN A 192.0.2.127 - const [ owner, ttl, c, type, address ] = opts.bindline.split(/\s+/) + const [owner, ttl, c, type, address] = opts.bindline.split(/\s+/) return new A({ owner, - ttl : parseInt(ttl, 10), + ttl: parseInt(ttl, 10), class: c, type, address, @@ -59,7 +58,7 @@ export default class A extends RR { } /****** EXPORTERS *******/ - toTinydns () { + toTinydns() { return `+${this.getTinyFQDN('owner')}:${this.get('address')}:${this.getTinydnsPostamble()}\n` } } diff --git a/rr/aaaa.js b/rr/aaaa.js index 63ec7ff..06f2116 100644 --- a/rr/aaaa.js +++ b/rr/aaaa.js @@ -1,86 +1,87 @@ - import net from 'net' import RR from '../rr.js' import * as TINYDNS from '../lib/tinydns.js' export default class AAAA extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setAddress (val) { + setAddress(val) { if (!val) throw new Error('AAAA: address is required') if (!net.isIPv6(val)) throw new Error(`AAAA: address must be IPv6 (${val})`) this.set('address', this.expand(val.toLowerCase())) // lower case: RFC 5952 } - getCompressed (val) { + getCompressed(val) { this.compress(val || this.get('address')) } - getDescription () { + getDescription() { return 'Address IPv6' } - getRdataFields (arg) { - return [ 'address' ] + getRdataFields(arg) { + return ['address'] } - getRFCs () { - return [ 3596 ] + getRFCs() { + return [3596] } - getTypeId () { + getTypeId() { return 28 } /****** IMPORTERS *******/ - fromTinydns (opts) { + fromTinydns(opts) { const str = opts.tinyline let fqdn, ip, n, rdata, ttl, ts, loc switch (str[0]) { case ':': // GENERIC => :fqdn:28:rdata:ttl:timestamp:lo - [ fqdn, n, rdata, ttl, ts, loc ] = str.substring(1).split(':') + ;[fqdn, n, rdata, ttl, ts, loc] = str.substring(1).split(':') if (n != 28) throw new Error('AAAA fromTinydns, invalid n') - ip = TINYDNS.octalToHex(rdata).match(/([0-9a-fA-F]{4})/g).join(':') + ip = TINYDNS.octalToHex(rdata) + .match(/([0-9a-fA-F]{4})/g) + .join(':') break case '3': case '6': // AAAA => 3fqdn:ip:x:ttl:timestamp:lo // AAAA,PTR => 6fqdn:ip:x:ttl:timestamp:lo - [ fqdn, rdata, ttl, ts, loc ] = str.substring(1).split(':') + ;[fqdn, rdata, ttl, ts, loc] = str.substring(1).split(':') ip = rdata.match(/(.{4})/g).join(':') break } return new AAAA({ - owner : this.fullyQualify(fqdn), - ttl : parseInt(ttl, 10), - type : 'AAAA', - address : ip, + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'AAAA', + address: ip, timestamp: ts, - location : loc !== '' && loc !== '\n' ? loc : '', + location: loc !== '' && loc !== '\n' ? loc : '', }) } - fromBind (opts) { + fromBind(opts) { // test.example.com 3600 IN AAAA ... - const [ owner, ttl, c, type, ip ] = opts.bindline.split(/\s+/) + const [owner, ttl, c, type, ip] = opts.bindline.split(/\s+/) return new AAAA({ owner, - ttl : parseInt(ttl, 10), - class : c, + ttl: parseInt(ttl, 10), + class: c, type, address: this.expand(ip), }) } - compress (val) { + compress(val) { /* * RFC 5952 * 4.1. Leading zeros MUST be suppressed...A single 16-bit 0000 field MUST be represented as 0. @@ -88,10 +89,10 @@ export default class AAAA extends RR { * 4.2.2 The symbol "::" MUST NOT be used to shorten just one 16-bit 0 field. * 4.2.3 When choosing placement of a "::", the longest run...MUST be shortened * 4.3 The characters a-f in an IPv6 address MUST be represented in lowercase. - */ + */ let r = val - .replace(/0000/g, '0') // 4.1 0000 -> 0 - .replace(/:0+([1-9a-fA-F])/g, ':$1') // 4.1 remove leading zeros + .replace(/0000/g, '0') // 4.1 0000 -> 0 + .replace(/:0+([1-9a-fA-F])/g, ':$1') // 4.1 remove leading zeros const mostConsecutiveZeros = [ new RegExp(/0?(?::0){6,}:0?/), @@ -111,7 +112,7 @@ export default class AAAA extends RR { return r } - expand (val, delimiter) { + expand(val, delimiter) { if (delimiter === undefined) delimiter = ':' const colons = val.match(/:/g) @@ -121,15 +122,18 @@ export default class AAAA extends RR { } // restore compressed leading zeros - return val.split(':').map(s => s.padStart(4, 0)).join(delimiter) + return val + .split(':') + .map((s) => s.padStart(4, 0)) + .join(delimiter) } /****** EXPORTERS *******/ - toBind (zone_opts) { + toBind(zone_opts) { return `${this.getPrefix(zone_opts)}\t${this.compress(this.get('address'))}\n` } - toTinydns () { + toTinydns() { // from AAAA notation (8 groups of 4 hex digits) to 16 escaped octals const rdata = TINYDNS.packHex(this.expand(this.get('address'), '')) return this.getTinydnsGeneric(rdata) diff --git a/rr/caa.js b/rr/caa.js index c17885f..ad671c2 100644 --- a/rr/caa.js +++ b/rr/caa.js @@ -1,110 +1,112 @@ - import RR from '../rr.js' import * as TINYDNS from '../lib/tinydns.js' export default class CAA extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setFlags (val) { + setFlags(val) { this.is8bitInt('CAA', 'flags', val) - if (![ 0, 128 ].includes(val)) { + if (![0, 128].includes(val)) { throw new Error(`CAA flags ${val} not recognized, ${this.citeRFC()}`) } this.set('flags', val) } - setTag (val) { - if (typeof val !== 'string' - || val.length < 1 - || /[^a-z0-9]/.test(val)) - throw new Error(`CAA tag must be a sequence of ASCII letters and numbers in lowercase, ${this.citeRFC()}`) + setTag(val) { + if (typeof val !== 'string' || val.length < 1 || /[^a-z0-9]/.test(val)) + throw new Error( + `CAA tag must be a sequence of ASCII letters and numbers in lowercase, ${this.citeRFC()}`, + ) - if (![ 'issue', 'issuewild', 'iodef' ].includes(val)) { + if (!['issue', 'issuewild', 'iodef'].includes(val)) { throw new Error(`CAA tag ${val} not recognized: ${this.citeRFC()}`) } this.set('tag', val) } - setValue (val) { + setValue(val) { // either (2) a quoted string or // (1) a contiguous set of characters without interior spaces if (this.isQuoted(val)) { val = val.replace(/^["']|["']$/g, '') // strip quotes - } - else { + } else { // if (/\s/.test(val)) throw new Error(`CAA value may not have spaces unless quoted: RFC 8659`) } // check if val starts with one of iodefSchemes if (this.get('tag') === 'iodef') { - const iodefSchemes = [ 'mailto:', 'http:', 'https:' ] - if (!iodefSchemes.filter(s => val.startsWith(s)).length) { - throw new Error(`CAA value must have valid iodefScheme prefix, ${this.citeRFC()}`) + const iodefSchemes = ['mailto:', 'http:', 'https:'] + if (!iodefSchemes.filter((s) => val.startsWith(s)).length) { + throw new Error( + `CAA value must have valid iodefScheme prefix, ${this.citeRFC()}`, + ) } } this.set('value', val) } - getDescription () { + getDescription() { return 'Certification Authority Authorization' } - getQuotedFields () { - return [ 'value' ] + getQuotedFields() { + return ['value'] } - getRdataFields (arg) { - return [ 'flags', 'tag', 'value' ] + getRdataFields(arg) { + return ['flags', 'tag', 'value'] } - getRFCs () { - return [ 6844, 8659 ] + getRFCs() { + return [6844, 8659] } - getTypeId () { + getTypeId() { return 257 } /****** IMPORTERS *******/ - fromTinydns (opts) { + fromTinydns(opts) { // CAA via generic, :fqdn:n:rdata:ttl:timestamp:lo - const [ fqdn, n, rdata, ttl, ts, loc ] = opts.tinyline.substring(1).split(':') + const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':') if (n != 257) throw new Error('CAA fromTinydns, invalid n') - const flags = TINYDNS.octalToUInt8(rdata.substring(0, 4)) + const flags = TINYDNS.octalToUInt8(rdata.substring(0, 4)) const taglen = TINYDNS.octalToUInt8(rdata.substring(4, 8)) - const unescaped = TINYDNS.octalToChar(rdata.substring(8)) - const tag = unescaped.substring(0, taglen) + const unescaped = TINYDNS.octalToChar(rdata.substring(8)) + const tag = unescaped.substring(0, taglen) const fingerprint = unescaped.substring(taglen) return new CAA({ - owner : this.fullyQualify(fqdn), - ttl : parseInt(ttl, 10), - type : 'CAA', + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'CAA', flags, tag, - value : fingerprint, + value: fingerprint, timestamp: ts, - location : loc !== '' && loc !== '\n' ? loc : '', + location: loc !== '' && loc !== '\n' ? loc : '', }) } - fromBind (opts) { + fromBind(opts) { // test.example.com 3600 IN CAA flags, tags, value - const fields = opts.bindline.match(/^([^\s]+)\s+([0-9]+)\s+(\w+)\s+(\w+)\s+([0-9]+)\s+(\w+)\s+("[^"]+"|[^\s]+?)\s*$/i) + const fields = opts.bindline.match( + /^([^\s]+)\s+([0-9]+)\s+(\w+)\s+(\w+)\s+([0-9]+)\s+(\w+)\s+("[^"]+"|[^\s]+?)\s*$/i, + ) if (!fields) throw new Error(`unable to parse: ${opts.bindline}`) - const [ owner, ttl, c, type, flags, tag, value ] = fields.slice(1) + const [owner, ttl, c, type, flags, tag, value] = fields.slice(1) return new CAA({ owner, - ttl : parseInt(ttl, 10), + ttl: parseInt(ttl, 10), class: c, type, flags: parseInt(flags, 10), @@ -115,7 +117,7 @@ export default class CAA extends RR { /****** EXPORTERS *******/ - toTinydns () { + toTinydns() { let rdata = '' rdata += TINYDNS.UInt8toOctal(this.get('flags')) diff --git a/rr/cert.js b/rr/cert.js index ababf4e..f8dcf09 100644 --- a/rr/cert.js +++ b/rr/cert.js @@ -1,13 +1,12 @@ - import RR from '../rr.js' export default class CERT extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setCertType (val) { + setCertType(val) { // The type field is the certificate type // the type field as an unsigned decimal integer or as a mnemonic symbol // this.is16bitInt('CERT', 'type', val) @@ -15,7 +14,7 @@ export default class CERT extends RR { this.set('cert type', val) } - setKeyTag (val) { + setKeyTag(val) { // The key tag field is the 16-bit value // The key tag field is represented as an unsigned decimal integer. @@ -24,7 +23,7 @@ export default class CERT extends RR { this.set('key tag', val) } - setAlgorithm (val) { + setAlgorithm(val) { // The algorithm field has the same meaning as the algorithm field in DNSKEY // The algorithm field is represented as an unsigned decimal integer this.is8bitInt('CERT', 'algorithm', val) @@ -32,41 +31,44 @@ export default class CERT extends RR { this.set('algorithm', val) } - setCertificate (val) { + setCertificate(val) { // certificate/CRL portion is represented in base 64 [16] and may be // divided into any number of white-space-separated substrings this.set('certificate', val) } - getDescription () { + getDescription() { return 'Certificate' } - getRdataFields () { - return [ 'cert type', 'key tag', 'algorithm', 'certificate' ] + getRdataFields() { + return ['cert type', 'key tag', 'algorithm', 'certificate'] } - getRFCs () { - return [ 2538, 4398 ] + getRFCs() { + return [2538, 4398] } - getTypeId () { + getTypeId() { return 37 } /****** IMPORTERS *******/ - fromBind (opts) { + fromBind(opts) { // test.example.com 3600 IN CERT certtype, keytag, algo, cert - const [ owner, ttl, c, type, certtype, keytag, algo, certificate ] = opts.bindline.split(/\s+/) + const [owner, ttl, c, type, certtype, keytag, algo, certificate] = + opts.bindline.split(/\s+/) return new CERT({ owner, - ttl : parseInt(ttl, 10), - class : c, + ttl: parseInt(ttl, 10), + class: c, type, - 'cert type': /^[0-9]+$/.test(certtype) ? parseInt(certtype, 10) : certtype, - 'key tag' : parseInt(keytag, 10), - algorithm : parseInt(algo, 10), + 'cert type': /^[0-9]+$/.test(certtype) + ? parseInt(certtype, 10) + : certtype, + 'key tag': parseInt(keytag, 10), + algorithm: parseInt(algo, 10), certificate, }) } diff --git a/rr/cname.js b/rr/cname.js index aa9d74e..79f6b07 100644 --- a/rr/cname.js +++ b/rr/cname.js @@ -1,15 +1,14 @@ - import net from 'net' import RR from '../rr.js' export default class CNAME extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setCname (val) { + setCname(val) { // A which specifies the canonical or primary // name for the owner. The owner name is an alias. @@ -25,43 +24,43 @@ export default class CNAME extends RR { this.set('cname', val.toLowerCase()) } - getDescription () { + getDescription() { return 'Canonical Name' } - getRdataFields (arg) { - return [ 'cname' ] + getRdataFields(arg) { + return ['cname'] } - getRFCs () { - return [ 1035, 2181 ] + getRFCs() { + return [1035, 2181] } - getTypeId () { + getTypeId() { return 5 } /****** IMPORTERS *******/ - fromTinydns (opts) { + fromTinydns(opts) { // Cfqdn:p:ttl:timestamp:lo - const [ fqdn, p, ttl, ts, loc ] = opts.tinyline.substring(1).split(':') + const [fqdn, p, ttl, ts, loc] = opts.tinyline.substring(1).split(':') return new CNAME({ - owner : this.fullyQualify(fqdn), - ttl : parseInt(ttl, 10), - type : 'CNAME', - cname : this.fullyQualify(p), + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'CNAME', + cname: this.fullyQualify(p), timestamp: ts, - location : loc !== '' && loc !== '\n' ? loc : '', + location: loc !== '' && loc !== '\n' ? loc : '', }) } - fromBind (opts) { + fromBind(opts) { // test.example.com 3600 IN CNAME ... - const [ owner, ttl, c, type, cname ] = opts.bindline.split(/\s+/) + const [owner, ttl, c, type, cname] = opts.bindline.split(/\s+/) return new CNAME({ owner, - ttl : parseInt(ttl, 10), + ttl: parseInt(ttl, 10), class: c, type, cname, @@ -70,7 +69,7 @@ export default class CNAME extends RR { /****** EXPORTERS *******/ - toTinydns () { + toTinydns() { return `C${this.getTinyFQDN('owner')}:${this.get('cname')}:${this.getTinydnsPostamble()}\n` } } diff --git a/rr/dname.js b/rr/dname.js index 68df0e7..d239102 100644 --- a/rr/dname.js +++ b/rr/dname.js @@ -4,12 +4,12 @@ import RR from '../rr.js' import * as TINYDNS from '../lib/tinydns.js' export default class DNAME extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setTarget (val) { + setTarget(val) { if (!val) throw new Error('DNAME: target is required') if (net.isIPv4(val) || net.isIPv6(val)) @@ -22,44 +22,44 @@ export default class DNAME extends RR { this.set('target', val.toLowerCase()) } - getDescription () { + getDescription() { return 'Delegation Name' } - getRdataFields (arg) { - return [ 'target' ] + getRdataFields(arg) { + return ['target'] } - getRFCs () { - return [ 2672, 6672 ] + getRFCs() { + return [2672, 6672] } - getTypeId () { + getTypeId() { return 39 } /****** IMPORTERS *******/ - fromTinydns (opts) { + fromTinydns(opts) { // DNAME via generic, :fqdn:n:rdata:ttl:timestamp:lo - const [ fqdn, n, rdata, ttl, ts, loc ] = opts.tinyline.substring(1).split(':') + const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':') if (n != 39) throw new Error('DNAME fromTinydns, invalid n') return new DNAME({ - type : 'DNAME', - owner : this.fullyQualify(fqdn), - target : (TINYDNS.unpackDomainName(rdata))[0], - ttl : parseInt(ttl, 10), + type: 'DNAME', + owner: this.fullyQualify(fqdn), + target: TINYDNS.unpackDomainName(rdata)[0], + ttl: parseInt(ttl, 10), timestamp: ts, - location : loc !== '' && loc !== '\n' ? loc : '', + location: loc !== '' && loc !== '\n' ? loc : '', }) } - fromBind (opts) { + fromBind(opts) { // test.example.com 3600 IN DNAME ... - const [ owner, ttl, c, type, target ] = opts.bindline.split(/\s+/) + const [owner, ttl, c, type, target] = opts.bindline.split(/\s+/) return new DNAME({ owner, - ttl : parseInt(ttl, 10), + ttl: parseInt(ttl, 10), class: c, type, target, @@ -67,7 +67,7 @@ export default class DNAME extends RR { } /****** EXPORTERS *******/ - toTinydns () { + toTinydns() { const rdata = TINYDNS.packDomainName(this.get('target')) return this.getTinydnsGeneric(rdata) } diff --git a/rr/dnskey.js b/rr/dnskey.js index b5233a2..1099d10 100644 --- a/rr/dnskey.js +++ b/rr/dnskey.js @@ -1,117 +1,124 @@ - import RR from '../rr.js' import * as TINYDNS from '../lib/tinydns.js' export default class DNSKEY extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setFlags (val) { + setFlags(val) { // a 2 octet Flags Field this.is16bitInt('DNSKEY', 'flags', val) // the possible values are: 0, 256, and 257; RFC 4034 - if (![ 0, 256, 257 ].includes(val)) throw new Error(`DNSKEY: flags invalid, ${this.citeRFC()}`) + if (![0, 256, 257].includes(val)) + throw new Error(`DNSKEY: flags invalid, ${this.citeRFC()}`) this.set('flags', val) } - setProtocol (val) { + setProtocol(val) { // 1 octet this.is8bitInt('DNSKEY', 'protocol', val) // The Protocol Field MUST be represented as an unsigned decimal integer with a value of 3. - if (![ 3 ].includes(val)) throw new Error(`DNSKEY: protocol invalid, ${this.citeRFC()}`) + if (![3].includes(val)) + throw new Error(`DNSKEY: protocol invalid, ${this.citeRFC()}`) this.set('protocol', val) } - setAlgorithm (val) { + setAlgorithm(val) { // 1 octet this.is8bitInt('DNSKEY', 'algorithm', val) // https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml // 1=RSA/MD5, 2=DH, 3=DSA/SHA-1, 4=EC, 5=RSA/SHA-1 - if (![ ...Array(16).keys(),253,254 ].includes(val)) - console.error(`DNSKEY: algorithm (${val}) not recognized, ${this.citeRFC()}`) + if (![...Array(16).keys(), 253, 254].includes(val)) + console.error( + `DNSKEY: algorithm (${val}) not recognized, ${this.citeRFC()}`, + ) this.set('algorithm', val) } - setPublickey (val) { - if (!val) throw new Error(`DNSKEY: publickey is required, ${this.citeRFC()}`) + setPublickey(val) { + if (!val) + throw new Error(`DNSKEY: publickey is required, ${this.citeRFC()}`) this.set('publickey', val) } - getDescription () { + getDescription() { return 'DNS Public Key' } - getRdataFields (arg) { - return [ 'flags', 'protocol', 'algorithm', 'publickey' ] + getRdataFields(arg) { + return ['flags', 'protocol', 'algorithm', 'publickey'] } - getRFCs () { - return [ 4034, 6014, 8624 ] + getRFCs() { + return [4034, 6014, 8624] } - getTypeId () { + getTypeId() { return 48 } /****** IMPORTERS *******/ - fromBind (opts) { + fromBind(opts) { // test.example.com 3600 IN DNSKEY Flags Protocol Algorithm PublicKey - const match = opts.bindline.match(/^([^\s]+)\s+([0-9]+)\s+(\w+)\s+(\w+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+\s*(.*?)\s*$/) + const match = opts.bindline.match( + /^([^\s]+)\s+([0-9]+)\s+(\w+)\s+(\w+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+\s*(.*?)\s*$/, + ) if (!match) throw new Error(`unable to parse DNSKEY: ${opts.bindline}`) - const [ owner, ttl, c, type, flags, protocol, algorithm, publickey ] = match.slice(1) + const [owner, ttl, c, type, flags, protocol, algorithm, publickey] = + match.slice(1) return new DNSKEY({ owner, - ttl : parseInt(ttl, 10), - class : c, - type : type, - flags : parseInt(flags, 10), - protocol : parseInt(protocol, 10), - algorithm: parseInt(algorithm, 10), + ttl: parseInt(ttl, 10), + class: c, + type: type, + flags: parseInt(flags, 10), + protocol: parseInt(protocol, 10), + algorithm: parseInt(algorithm, 10), publickey: publickey, }) } - fromTinydns (opts) { - const [ fqdn, n, rdata, ttl, ts, loc ] = opts.tinyline.substring(1).split(':') + fromTinydns(opts) { + const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':') if (n != 48) throw new Error('DNSKEY fromTinydns, invalid n') const bytes = Buffer.from(TINYDNS.octalToChar(rdata), 'binary') return new DNSKEY({ - owner : this.fullyQualify(fqdn), - ttl : parseInt(ttl, 10), - type : 'DNSKEY', - flags : bytes.readUInt16BE(0), - protocol : bytes.readUInt8(2), - 'algorithm': bytes.readUInt8(3), - 'publickey': bytes.slice(4).toString(), - timestamp : ts, - location : loc !== '' && loc !== '\n' ? loc : '', + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'DNSKEY', + flags: bytes.readUInt16BE(0), + protocol: bytes.readUInt8(2), + algorithm: bytes.readUInt8(3), + publickey: bytes.slice(4).toString(), + timestamp: ts, + location: loc !== '' && loc !== '\n' ? loc : '', }) } /****** EXPORTERS *******/ - toTinydns () { + toTinydns() { const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g') return this.getTinydnsGeneric( TINYDNS.UInt16toOctal(this.get('flags')) + - TINYDNS.UInt8toOctal(this.get('protocol')) + - TINYDNS.UInt8toOctal(this.get('algorithm')) + - TINYDNS.escapeOctal(dataRe, this.get('publickey')) + TINYDNS.UInt8toOctal(this.get('protocol')) + + TINYDNS.UInt8toOctal(this.get('algorithm')) + + TINYDNS.escapeOctal(dataRe, this.get('publickey')), ) } } diff --git a/rr/ds.js b/rr/ds.js index 59d5dc7..4c8f57b 100644 --- a/rr/ds.js +++ b/rr/ds.js @@ -1,104 +1,106 @@ - import RR from '../rr.js' import * as TINYDNS from '../lib/tinydns.js' export default class DS extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setKeyTag (val) { + setKeyTag(val) { // a 2 octet Key Tag field...in network byte order if (!val) throw new Error(`DS: key tag is required`) - if (val.length > 2) throw new Error(`DS: key tag is too long, ${this.citeRFC()}`) + if (val.length > 2) + throw new Error(`DS: key tag is too long, ${this.citeRFC()}`) this.set('key tag', val) } - setAlgorithm (val) { + setAlgorithm(val) { // 1=RSA/MD5, 2=DH, 3=DSA/SHA-1, 4=EC, 5=RSA/SHA-1 - if (![ 1,2,3,4,5,253,254 ].includes(val)) + if (![1, 2, 3, 4, 5, 253, 254].includes(val)) throw new Error(`DS: algorithm invalid, ${this.citeRFC()}`) this.set('algorithm', val) } - setDigestType (val) { - if (![ 1,2 ].includes(val)) throw new Error(`DS: digest type invalid, ${this.citeRFC()}`) + setDigestType(val) { + if (![1, 2].includes(val)) + throw new Error(`DS: digest type invalid, ${this.citeRFC()}`) this.set('digest type', val) } - setDigest (val) { + setDigest(val) { if (!val) throw new Error(`DS: digest is required, ${this.citeRFC()}`) this.set('digest', val) } - getDescription () { + getDescription() { return 'Delegation Signer' } - getRdataFields (arg) { - return [ 'key tag', 'algorithm', 'digest type', 'digest' ] + getRdataFields(arg) { + return ['key tag', 'algorithm', 'digest type', 'digest'] } - getRFCs () { - return [ 4034, 4509 ] + getRFCs() { + return [4034, 4509] } - getTypeId () { + getTypeId() { return 43 } /****** IMPORTERS *******/ - fromBind (opts) { + fromBind(opts) { // test.example.com 3600 IN DS Key Tag Algorithm, Digest Type, Digest - const [ owner, ttl, c, type, keytag, algorithm, digesttype ] = opts.bindline.split(/\s+/) + const [owner, ttl, c, type, keytag, algorithm, digesttype] = + opts.bindline.split(/\s+/) return new DS({ owner, - ttl : parseInt(ttl, 10), - class : c, + ttl: parseInt(ttl, 10), + class: c, type, - 'key tag' : parseInt(keytag, 10), - algorithm : parseInt(algorithm, 10), + 'key tag': parseInt(keytag, 10), + algorithm: parseInt(algorithm, 10), 'digest type': parseInt(digesttype, 10), - digest : opts.bindline.split(/\s+/).slice(7).join(' ').trim(), + digest: opts.bindline.split(/\s+/).slice(7).join(' ').trim(), }) } - fromTinydns (opts) { - const [ fqdn, n, rdata, ttl, ts, loc ] = opts.tinyline.substring(1).split(':') + fromTinydns(opts) { + const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':') if (n != 43) throw new Error('DS fromTinydns, invalid n') const binRdata = Buffer.from(TINYDNS.octalToChar(rdata), 'binary') return new DS({ - owner : this.fullyQualify(fqdn), - ttl : parseInt(ttl, 10), - type : 'DS', - 'key tag' : binRdata.readUInt16BE(0), - algorithm : binRdata.readUInt8(2), + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'DS', + 'key tag': binRdata.readUInt16BE(0), + algorithm: binRdata.readUInt8(2), 'digest type': binRdata.readUInt8(3), - digest : binRdata.slice(4).toString(), - timestamp : ts, - location : loc !== '' && loc !== '\n' ? loc : '', + digest: binRdata.slice(4).toString(), + timestamp: ts, + location: loc !== '' && loc !== '\n' ? loc : '', }) } /****** EXPORTERS *******/ - toTinydns () { + toTinydns() { const rdataRe = new RegExp(/[\r\n\t:\\/]/, 'g') return this.getTinydnsGeneric( TINYDNS.UInt16toOctal(this.get('key tag')) + - TINYDNS.UInt8toOctal(this.get('algorithm')) + - TINYDNS.UInt8toOctal(this.get('digest type')) + - TINYDNS.escapeOctal(rdataRe, this.get('digest')) + TINYDNS.UInt8toOctal(this.get('algorithm')) + + TINYDNS.UInt8toOctal(this.get('digest type')) + + TINYDNS.escapeOctal(rdataRe, this.get('digest')), ) } } diff --git a/rr/hinfo.js b/rr/hinfo.js index 49254b9..f35b12c 100644 --- a/rr/hinfo.js +++ b/rr/hinfo.js @@ -1,54 +1,55 @@ - import RR from '../rr.js' import * as TINYDNS from '../lib/tinydns.js' export default class HINFO extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setCpu (val) { + setCpu(val) { if (val.length > 255) throw new Error('HINFO cpu cannot exceed 255 chars') this.set('cpu', val.replace(/^["']|["']$/g, '')) } - setOs (val) { + setOs(val) { if (val.length > 255) throw new Error('HINFO os cannot exceed 255 chars') this.set('os', val.replace(/^["']|["']$/g, '')) } - getDescription () { + getDescription() { return 'Host Info' } - getRdataFields (arg) { - return [ 'cpu', 'os' ] + getRdataFields(arg) { + return ['cpu', 'os'] } - getRFCs () { - return [ 1034, 1035, 8482 ] + getRFCs() { + return [1034, 1035, 8482] } - getTypeId () { + getTypeId() { return 13 } - getQuotedFields () { - return [ 'cpu', 'os' ] + getQuotedFields() { + return ['cpu', 'os'] } /****** IMPORTERS *******/ - fromBind (opts) { + fromBind(opts) { // test.example.com 3600 IN HINFO DEC-2060 TOPS20 - const match = opts.bindline.match(/([^\s]+)\s+([0-9]+)\s+(IN)\s+(HINFO)\s+("[^"]+"|[^\s]+)\s+("[^"]+"|[^\s]+)/i) + const match = opts.bindline.match( + /([^\s]+)\s+([0-9]+)\s+(IN)\s+(HINFO)\s+("[^"]+"|[^\s]+)\s+("[^"]+"|[^\s]+)/i, + ) if (!match) throw new Error(`unable to parse HINFO: ${opts.bindline}`) - const [ owner, ttl, c, type, cpu, os ] = match.slice(1) + const [owner, ttl, c, type, cpu, os] = match.slice(1) return new HINFO({ owner, - ttl : parseInt(ttl, 10), + ttl: parseInt(ttl, 10), class: c, type, cpu, @@ -56,29 +57,29 @@ export default class HINFO extends RR { }) } - fromTinydns (opts) { + fromTinydns(opts) { // HINFO via generic, :fqdn:n:rdata:ttl:timestamp:lo - const [ fqdn, , rdata, ttl, ts, loc ] = opts.tinyline.substring(1).split(':') - const [ cpu, os ] = [ ...TINYDNS.unpackString(rdata) ] + const [fqdn, , rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':') + const [cpu, os] = [...TINYDNS.unpackString(rdata)] return new this.constructor({ - owner : this.fullyQualify(fqdn), - ttl : parseInt(ttl, 10), - type : 'HINFO', + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'HINFO', cpu, os, timestamp: ts, - location : loc !== '' && loc !== '\n' ? loc : '', + location: loc !== '' && loc !== '\n' ? loc : '', }) } /****** EXPORTERS *******/ - toTinydns () { + toTinydns() { return this.getTinydnsGeneric( [ TINYDNS.packString(this.get('cpu')), TINYDNS.packString(this.get('os')), - ].join('') + ].join(''), ) } } diff --git a/rr/ipseckey.js b/rr/ipseckey.js index 4404a1f..3ae3aa4 100644 --- a/rr/ipseckey.js +++ b/rr/ipseckey.js @@ -1,4 +1,3 @@ - import net from 'net' import RR from '../rr.js' @@ -6,130 +5,139 @@ import RR from '../rr.js' import * as TINYDNS from '../lib/tinydns.js' export default class IPSECKEY extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setPrecedence (val) { + setPrecedence(val) { // an 8-bit precedence for this record. this.is8bitInt('IPSECKEY', 'precedence', val) this.set('precedence', val) } - setGatewayType (val) { + setGatewayType(val) { // 0 (none), 1 (4-byte IPv4), 2 (16-byte IPv6), 3 (wire encoded domain name) - if (![ 0,1,2,3 ].includes(val)) + if (![0, 1, 2, 3].includes(val)) throw new Error(`IPSECKEY: Gateway Type is invalid, ${this.citeRFC()}`) this.set('gateway type', val) } - setAlgorithm (val) { + setAlgorithm(val) { // unsigned int, 1 octet, values: 1=DSA, 2=RSA - if (![ 1,2 ].includes(val)) + if (![1, 2].includes(val)) throw new Error(`IPSECKEY: Algorithm invalid, ${this.citeRFC()}`) this.set('algorithm', val) } - setGateway (val) { - const gwErr = new Error(`IPSECKEY: gateway invalid (${val}), ${this.citeRFC()}`) + setGateway(val) { + const gwErr = new Error( + `IPSECKEY: gateway invalid (${val}), ${this.citeRFC()}`, + ) switch (this.get('gateway type')) { - case 0: if (val !== '.') throw gwErr; break - case 1: if (!net.isIPv4(val)) throw gwErr; break - case 2: if (!net.isIPv6(val)) throw gwErr; break + case 0: + if (val !== '.') throw gwErr + break + case 1: + if (!net.isIPv4(val)) throw gwErr + break + case 2: + if (!net.isIPv6(val)) throw gwErr + break } this.set('gateway', val) } - setPublickey (val) { + setPublickey(val) { // if (val) throw new Error(`IPSECKEY: publickey is optional, ${this.citeRFC()}`) this.set('publickey', val) } - getDescription () { + getDescription() { return 'IPsec Keying' } - getRdataFields (arg) { - return [ 'precedence', 'gateway type', 'algorithm', 'gateway', 'publickey' ] + getRdataFields(arg) { + return ['precedence', 'gateway type', 'algorithm', 'gateway', 'publickey'] } - getRFCs () { - return [ 4025 ] + getRFCs() { + return [4025] } - getTypeId () { + getTypeId() { return 45 } /****** IMPORTERS *******/ - fromBind (opts) { + fromBind(opts) { // FQDN TTL CLASS IPSECKEY Precedence GatewayType Algorithm Gateway PublicKey - const [ owner, ttl, c, type, prec, gwt, algo, gateway, publickey ] = opts.bindline.split(/\s+/) + const [owner, ttl, c, type, prec, gwt, algo, gateway, publickey] = + opts.bindline.split(/\s+/) return new IPSECKEY({ owner, - ttl : parseInt(ttl, 10), - class : c, + ttl: parseInt(ttl, 10), + class: c, type, - precedence : parseInt(prec, 10), - 'gateway type': parseInt(gwt, 10), - algorithm : parseInt(algo, 10), + precedence: parseInt(prec, 10), + 'gateway type': parseInt(gwt, 10), + algorithm: parseInt(algo, 10), gateway, publickey, }) } - fromTinydns (opts) { - const [ fqdn, n, rdata, ttl, ts, loc ] = opts.tinyline.substring(1).split(':') + fromTinydns(opts) { + const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':') if (n != 45) throw new Error('IPSECKEY fromTinydns, invalid n') const precedence = TINYDNS.octalToUInt8(rdata.substring(0, 4)) - const gwType = TINYDNS.octalToUInt8(rdata.substring(4, 8)) - const algorithm = TINYDNS.octalToUInt8(rdata.substring(8, 12)) + const gwType = TINYDNS.octalToUInt8(rdata.substring(4, 8)) + const algorithm = TINYDNS.octalToUInt8(rdata.substring(8, 12)) let len, gateway, octalKey switch (gwType) { - case 0: // no gateway - gateway = rdata.substring(12, 13) // should always be: '.' + case 0: // no gateway + gateway = rdata.substring(12, 13) // should always be: '.' octalKey = rdata.substring(13) break - case 1: // 4-byte IPv4 address - gateway = TINYDNS.octalToIPv4(rdata.substring(12, 28)) + case 1: // 4-byte IPv4 address + gateway = TINYDNS.octalToIPv4(rdata.substring(12, 28)) octalKey = rdata.substring(28) break - case 2: // 16-byte IPv6 - gateway = TINYDNS.octalToHex(rdata.substring(12, 76)) + case 2: // 16-byte IPv6 + gateway = TINYDNS.octalToHex(rdata.substring(12, 76)) octalKey = rdata.substring(76) break - case 3: // wire encoded domain name - [ gateway, len ] = TINYDNS.unpackDomainName(rdata.substring(12)) + case 3: // wire encoded domain name + ;[gateway, len] = TINYDNS.unpackDomainName(rdata.substring(12)) octalKey = rdata.substring(12 + len) break } return new IPSECKEY({ - owner : this.fullyQualify(fqdn), - ttl : parseInt(ttl, 10), - type : 'IPSECKEY', + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'IPSECKEY', precedence, 'gateway type': gwType, algorithm, gateway, - publickey : TINYDNS.octalToBase64(octalKey), - timestamp : ts, - location : loc !== '' && loc !== '\n' ? loc : '', + publickey: TINYDNS.octalToBase64(octalKey), + timestamp: ts, + location: loc !== '' && loc !== '\n' ? loc : '', }) } /****** EXPORTERS *******/ - toTinydns () { + toTinydns() { const rdataRe = new RegExp(/[\r\n\t:\\/]/, 'g') let rdata = '' diff --git a/rr/key.js b/rr/key.js index 0985b80..bbd6790 100644 --- a/rr/key.js +++ b/rr/key.js @@ -1,70 +1,70 @@ - import RR from '../rr.js' export default class KEY extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setFlags (val) { + setFlags(val) { // a 2 octet Flags Field this.is16bitInt('KEY', 'flags', val) this.set('flags', val) } - setProtocol (val) { + setProtocol(val) { // 1 octet this.is8bitInt('KEY', 'protocol', val) this.set('protocol', val) } - setAlgorithm (val) { + setAlgorithm(val) { // 1 octet // 1=RSA/MD5, 2=DH, 3=DSA/SHA-1, 4=EC, 5=RSA/SHA-1 - if (![ 1,2,3,4,5,253,254 ].includes(val)) + if (![1, 2, 3, 4, 5, 253, 254].includes(val)) throw new Error(`KEY: algorithm invalid, ${this.citeRFC()}`) this.set('algorithm', val) } - setPublickey (val) { + setPublickey(val) { if (!val) throw new Error(`KEY: publickey is required, ${this.citeRFC()}`) this.set('publickey', val) } - getDescription () { + getDescription() { return 'DNS Public Key' } - getRdataFields (arg) { - return [ 'flags', 'protocol', 'algorithm', 'publickey' ] + getRdataFields(arg) { + return ['flags', 'protocol', 'algorithm', 'publickey'] } - getRFCs () { - return [ 2535, 3445 ] + getRFCs() { + return [2535, 3445] } - getTypeId () { + getTypeId() { return 25 } /****** IMPORTERS *******/ - fromBind (opts) { + fromBind(opts) { // test.example.com 3600 IN KEY Flags Protocol Algorithm PublicKey - const [ owner, ttl, c, type, flags, protocol, algorithm ] = opts.bindline.split(/\s+/) + const [owner, ttl, c, type, flags, protocol, algorithm] = + opts.bindline.split(/\s+/) return new KEY({ owner, - ttl : parseInt(ttl, 10), - class : c, - type : type, - flags : parseInt(flags, 10), - protocol : parseInt(protocol, 10), - algorithm: parseInt(algorithm, 10), + ttl: parseInt(ttl, 10), + class: c, + type: type, + flags: parseInt(flags, 10), + protocol: parseInt(protocol, 10), + algorithm: parseInt(algorithm, 10), publickey: opts.bindline.split(/\s+/).slice(7).join(' ').trim(), }) } diff --git a/rr/loc.js b/rr/loc.js index 9d93eaf..90b82f9 100644 --- a/rr/loc.js +++ b/rr/loc.js @@ -1,9 +1,9 @@ - import RR from '../rr.js' import * as TINYDNS from '../lib/tinydns.js' -const REF = { // RFC 1876 - LATLON : 2**31, // LAT equator, LON prime meridian +const REF = { + // RFC 1876 + LATLON: 2 ** 31, // LAT equator, LON prime meridian ALTITUDE: 100000 * 100, // reference spheroid used by GPS, in cm } @@ -14,12 +14,12 @@ const CONV = { } export default class LOC extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setAddress (val) { + setAddress(val) { if (!val) throw new Error('LOC: address is required') /* @@ -32,29 +32,29 @@ export default class LOC extends RR { this.set('address', val) } - getDescription () { + getDescription() { return 'Location' } - getRdataFields (arg) { - return [ 'address' ] + getRdataFields(arg) { + return ['address'] } - getRFCs () { - return [ 1876 ] + getRFCs() { + return [1876] } - getTypeId () { + getTypeId() { return 29 } - parseLoc (string) { - + parseLoc(string) { // d1 [m1 [s1]] const dms = '(\\d+)\\s+(?:(\\d+)\\s+)?(?:([\\d.]+)\\s+)?' // alt["m"] [siz["m"] [hp["m"] [vp["m"]]]] - const alt = '(-?[\\d.]+)m?(?:\\s+([\\d.]+)m?)?(?:\\s+([\\d.]+)m?)?(?:\\s+([\\d.]+)m?)?' + const alt = + '(-?[\\d.]+)m?(?:\\s+([\\d.]+)m?)?(?:\\s+([\\d.]+)m?)?(?:\\s+([\\d.]+)m?)?' // put them all together const locRe = new RegExp(`^${dms}(N|S)\\s+${dms}(E|W)\\s+${alt}`, 'i') @@ -63,22 +63,22 @@ export default class LOC extends RR { const loc = { latitude: { - degrees : r[1], - minutes : r[2], - seconds : r[3], + degrees: r[1], + minutes: r[2], + seconds: r[3], hemisphere: r[4].toUpperCase(), }, longitude: { - degrees : r[5], - minutes : r[6], - seconds : r[7], + degrees: r[5], + minutes: r[6], + seconds: r[7], hemisphere: r[8].toUpperCase(), }, - altitude : r[9] * 100, // m -> cm - size : r[10] * 100, + altitude: r[9] * 100, // m -> cm + size: r[10] * 100, precision: { horizontal: r[11] * 100, - vertical : r[12] * 100, + vertical: r[12] * 100, }, } @@ -86,48 +86,61 @@ export default class LOC extends RR { } /****** IMPORTERS *******/ - fromTinydns (opts) { + fromTinydns(opts) { // LOC via generic, :fqdn:n:rdata:ttl:timestamp:lo - const [ fqdn, n, rdata, ttl, ts, loc ] = opts.tinyline.substring(1).split(':') + const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':') if (n != 29) throw new Error('LOC fromTinydns, invalid n') // divide by 100 is to convert cm to meters const l = { - version : TINYDNS.octalToUInt8(rdata.substring(0, 4)), - size : this.fromExponent(TINYDNS.octalToUInt8(rdata.substring(4, 8))), + version: TINYDNS.octalToUInt8(rdata.substring(0, 4)), + size: this.fromExponent(TINYDNS.octalToUInt8(rdata.substring(4, 8))), precision: { - horizontal: this.fromExponent(TINYDNS.octalToUInt8(rdata.substring( 8, 12))), - vertical : this.fromExponent(TINYDNS.octalToUInt8(rdata.substring(12, 16))), + horizontal: this.fromExponent( + TINYDNS.octalToUInt8(rdata.substring(8, 12)), + ), + vertical: this.fromExponent( + TINYDNS.octalToUInt8(rdata.substring(12, 16)), + ), }, - latitude : this.arcSecToDMS(TINYDNS.octalToUInt32(rdata.substring(16, 32)), 'lat'), - longitude: this.arcSecToDMS(TINYDNS.octalToUInt32(rdata.substring(32, 48)), 'lon'), - altitude : TINYDNS.octalToUInt32(rdata.substring(48, 64)) - REF.ALTITUDE, + latitude: this.arcSecToDMS( + TINYDNS.octalToUInt32(rdata.substring(16, 32)), + 'lat', + ), + longitude: this.arcSecToDMS( + TINYDNS.octalToUInt32(rdata.substring(32, 48)), + 'lon', + ), + altitude: TINYDNS.octalToUInt32(rdata.substring(48, 64)) - REF.ALTITUDE, } return new LOC({ - type : 'LOC', - owner : this.fullyQualify(fqdn), - address : this.toHuman(l), - ttl : parseInt(ttl, 10), + type: 'LOC', + owner: this.fullyQualify(fqdn), + address: this.toHuman(l), + ttl: parseInt(ttl, 10), timestamp: ts, - location : loc !== '' && loc !== '\n' ? loc : '', + location: loc !== '' && loc !== '\n' ? loc : '', }) } - fromBind (opts) { - const [ owner, ttl, c, type ] = opts.bindline.split(/\s+/) + fromBind(opts) { + const [owner, ttl, c, type] = opts.bindline.split(/\s+/) return new LOC({ owner, - ttl : parseInt(ttl, 10), - class : c, - type : type, + ttl: parseInt(ttl, 10), + class: c, + type: type, address: opts.bindline.split(/\s+/).slice(4).join(' ').trim(), }) } - dmsToArcSec (obj) { - let retval = (obj.degrees * CONV.deg) + ((obj.minutes || 0) * CONV.min) + ((obj.seconds || 0) * CONV.sec) + dmsToArcSec(obj) { + let retval = + obj.degrees * CONV.deg + + (obj.minutes || 0) * CONV.min + + (obj.seconds || 0) * CONV.sec switch (obj.hemisphere.toUpperCase()) { case 'W': case 'S': @@ -138,7 +151,7 @@ export default class LOC extends RR { return retval } - arcSecToDMS (rawmsec, latlon) { + arcSecToDMS(rawmsec, latlon) { let msec = Math.abs(rawmsec - REF.LATLON) // console.log(`rawmsec: ${rawmsec}, abs msec: ${msec}`) @@ -163,16 +176,16 @@ export default class LOC extends RR { throw new Error('unknown or missing hemisphere') } - return `${deg} ${min} ${sec}${msec ? '.'+msec : ''} ${hem}` + return `${deg} ${min} ${sec}${msec ? '.' + msec : ''} ${hem}` } - fromExponent (prec) { + fromExponent(prec) { const mantissa = ((prec >> 4) & 0x0f) % 10 const exponent = ((prec >> 0) & 0x0f) % 10 return mantissa * Math.pow(10, exponent) } - toExponent (val) { + toExponent(val) { /* RFC 1876, ... expressed as a pair of four-bit unsigned integers, each ranging from zero to nine, with the most @@ -188,22 +201,22 @@ export default class LOC extends RR { return (parseInt(val) << 4) | (exponent & 0x0f) } - toHuman (obj) { - let r = `${obj.latitude} ${obj.longitude} ${(obj.altitude/100)}m` - if (obj.size) r += ` ${obj.size/100}m` + toHuman(obj) { + let r = `${obj.latitude} ${obj.longitude} ${obj.altitude / 100}m` + if (obj.size) r += ` ${obj.size / 100}m` if (obj.precision.horizontal) r += ` ${obj.precision.horizontal / 100}m` - if (obj.precision.vertical ) r += ` ${obj.precision.vertical / 100}m` + if (obj.precision.vertical) r += ` ${obj.precision.vertical / 100}m` return r } /****** EXPORTERS *******/ - toTinydns () { + toTinydns() { const loc = this.parseLoc(this.get('address')) // LOC format declares in meters, tinydns uses cm (hence * 100) let rdata = '' - rdata += TINYDNS.UInt8toOctal(0) // version + rdata += TINYDNS.UInt8toOctal(0) // version rdata += TINYDNS.UInt8toOctal(this.toExponent(loc.size)) rdata += TINYDNS.UInt8toOctal(this.toExponent(loc.precision.horizontal)) rdata += TINYDNS.UInt8toOctal(this.toExponent(loc.precision.vertical)) diff --git a/rr/mx.js b/rr/mx.js index ca0db15..ff4148a 100644 --- a/rr/mx.js +++ b/rr/mx.js @@ -1,21 +1,20 @@ - import net from 'net' import RR from '../rr.js' export default class MX extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setPreference (val) { + setPreference(val) { if (val === undefined) val = this?.default?.preference this.is16bitInt('MX', 'preference', val) this.set('preference', val) } - setExchange (val) { + setExchange(val) { if (!val) throw new Error('MX: exchange is required') if (net.isIPv4(val) || net.isIPv6(val)) @@ -28,47 +27,50 @@ export default class MX extends RR { this.set('exchange', val.toLowerCase()) } - getDescription () { + getDescription() { return 'Mail Exchanger' } - getRdataFields (arg) { - return [ 'preference', 'exchange' ] + getRdataFields(arg) { + return ['preference', 'exchange'] } - getRFCs () { - return [ 1035, 2181, 7505 ] + getRFCs() { + return [1035, 2181, 7505] } - getTypeId () { + getTypeId() { return 15 } /****** IMPORTERS *******/ - fromTinydns (opts) { + fromTinydns(opts) { // @fqdn:ip:x:dist:ttl:timestamp:lo // eslint-disable-next-line no-unused-vars - const [ owner, ip, x, preference, ttl, ts, loc ] = opts.tinyline.substring(1).split(':') + const [owner, ip, x, preference, ttl, ts, loc] = opts.tinyline + .substring(1) + .split(':') return new MX({ - type : 'MX', - owner : this.fullyQualify(owner), - exchange : this.fullyQualify(/\./.test(x) ? x : `${x}.mx.${owner}`), + type: 'MX', + owner: this.fullyQualify(owner), + exchange: this.fullyQualify(/\./.test(x) ? x : `${x}.mx.${owner}`), preference: parseInt(preference, 10) || 0, - ttl : parseInt(ttl, 10), - timestamp : ts, - location : loc !== '' && loc !== '\n' ? loc : '', + ttl: parseInt(ttl, 10), + timestamp: ts, + location: loc !== '' && loc !== '\n' ? loc : '', }) } - fromBind (opts) { + fromBind(opts) { // test.example.com 3600 IN MX preference exchange - const [ owner, ttl, c, type, preference, exchange ] = opts.bindline.split(/\s+/) + const [owner, ttl, c, type, preference, exchange] = + opts.bindline.split(/\s+/) return new MX({ owner, - ttl : parseInt(ttl, 10), - class : c, + ttl: parseInt(ttl, 10), + class: c, type, preference: parseInt(preference), exchange, @@ -76,11 +78,11 @@ export default class MX extends RR { } /****** EXPORTERS *******/ - toBind (zone_opts) { + toBind(zone_opts) { return `${this.getPrefix(zone_opts)}\t${this.get('preference')}\t${this.getFQDN('exchange', zone_opts)}\n` } - toTinydns () { + toTinydns() { return `@${this.getTinyFQDN('owner')}::${this.getTinyFQDN('exchange')}:${this.get('preference')}:${this.getTinydnsPostamble()}\n` } } diff --git a/rr/naptr.js b/rr/naptr.js index 260fa83..8e17b27 100644 --- a/rr/naptr.js +++ b/rr/naptr.js @@ -1,136 +1,135 @@ - import RR from '../rr.js' import * as TINYDNS from '../lib/tinydns.js' const rdataRe = /[\r\n\t:\\/]/ export default class NAPTR extends RR { - constructor (opts) { + constructor(opts) { super(opts) } - getDescription () { + getDescription() { return 'Naming Authority Pointer' } - getQuotedFields () { - return [ 'flags', 'service', 'regexp' ] + getQuotedFields() { + return ['flags', 'service', 'regexp'] } - getRdataFields (arg) { - return [ 'order', 'preference', 'flags', 'service', 'regexp', 'replacement' ] + getRdataFields(arg) { + return ['order', 'preference', 'flags', 'service', 'regexp', 'replacement'] } - getRFCs () { - return [ 2915, 3403 ] + getRFCs() { + return [2915, 3403] } - getTypeId () { + getTypeId() { return 35 } /****** Resource record specific setters *******/ - setOrder (val) { + setOrder(val) { this.is16bitInt('NAPTR', 'order', val) this.set('order', val) } - setPreference (val) { + setPreference(val) { this.is16bitInt('NAPTR', 'preference', val) this.set('preference', val) } - setFlags (val) { - if (![ '', 'S', 'A', 'U', 'P' ].includes(val.toUpperCase())) - throw new Error (`NAPTR flags are invalid, ${this.citeRFC()}`) + setFlags(val) { + if (!['', 'S', 'A', 'U', 'P'].includes(val.toUpperCase())) + throw new Error(`NAPTR flags are invalid, ${this.citeRFC()}`) this.set('flags', val.toUpperCase()) } - setService (val) { + setService(val) { this.set('service', val) } - setRegexp (val) { + setRegexp(val) { this.set('regexp', val) } - setReplacement (val) { + setReplacement(val) { this.set('replacement', val) } /****** IMPORTERS *******/ - fromTinydns (opts) { + fromTinydns(opts) { // NAPTR via generic, :fqdn:n:rdata:ttl:timestamp:lo - const [ fqdn, n, rdata, ttl, ts, loc ] = opts.tinyline.substring(1).split(':') + const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':') if (n != 35) throw new Error('NAPTR fromTinydns, invalid n') const binRdata = Buffer.from(TINYDNS.octalToChar(rdata), 'binary') const rec = { - type : 'NAPTR', - owner : this.fullyQualify(fqdn), - ttl : parseInt(ttl, 10), - timestamp : ts, - location : loc !== '' && loc !== '\n' ? loc : '', - order : binRdata.readUInt16BE(0,2), - preference: binRdata.readUInt16BE(2,4), + type: 'NAPTR', + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + timestamp: ts, + location: loc !== '' && loc !== '\n' ? loc : '', + order: binRdata.readUInt16BE(0, 2), + preference: binRdata.readUInt16BE(2, 4), } let idx = 4 - const flagsLength = binRdata.readUInt8(idx); idx++ - rec.flags = binRdata.slice(idx, flagsLength).toString() + const flagsLength = binRdata.readUInt8(idx) + idx++ + rec.flags = binRdata.slice(idx, flagsLength).toString() idx += flagsLength - const serviceLen = binRdata.readUInt8(idx); idx++ - rec.service = binRdata.slice(idx, idx+serviceLen).toString() + const serviceLen = binRdata.readUInt8(idx) + idx++ + rec.service = binRdata.slice(idx, idx + serviceLen).toString() idx += serviceLen - const regexpLen = binRdata.readUInt8(idx); idx++ - rec.regexp = binRdata.slice(idx, idx+regexpLen).toString() + const regexpLen = binRdata.readUInt8(idx) + idx++ + rec.regexp = binRdata.slice(idx, idx + regexpLen).toString() idx += regexpLen - const replaceLen = binRdata.readUInt8(idx); idx++ - rec.replacement = binRdata.slice(idx, idx+replaceLen).toString() + const replaceLen = binRdata.readUInt8(idx) + idx++ + rec.replacement = binRdata.slice(idx, idx + replaceLen).toString() return new NAPTR(rec) } - fromBind (opts) { + fromBind(opts) { const str = opts.bindline // test.example.com 3600 IN NAPTR order, preference, "flags", "service", "regexp", replacement - const [ owner, ttl, c, type, order, preference ] = str.split(/\s+/) - const [ flags, service, regexp ] = str.match(/(?:").*?(?:"\s)/g) + const [owner, ttl, c, type, order, preference] = str.split(/\s+/) + const [flags, service, regexp] = str.match(/(?:").*?(?:"\s)/g) const replacement = str.trim().split(/\s+/).pop() const bits = { - owner : owner, - ttl : parseInt(ttl, 10), - class : c, - type : type, - order : parseInt(order, 10), - preference : parseInt(preference, 10), - flags : flags.trim().replace(/^['"]|['"]$/g, ''), - service : service.trim().replace(/^['"]|['"]$/g, ''), - regexp : regexp.trim().replace(/^['"]|['"]/g, ''), + owner: owner, + ttl: parseInt(ttl, 10), + class: c, + type: type, + order: parseInt(order, 10), + preference: parseInt(preference, 10), + flags: flags.trim().replace(/^['"]|['"]$/g, ''), + service: service.trim().replace(/^['"]|['"]$/g, ''), + regexp: regexp.trim().replace(/^['"]|['"]/g, ''), replacement: replacement, } return new NAPTR(bits) } /****** EXPORTERS *******/ - toTinydns () { - + toTinydns() { let rdata = TINYDNS.UInt16toOctal(this.get('order')) + TINYDNS.UInt16toOctal(this.get('preference')) + - TINYDNS.UInt8toOctal(this.get('flags').length) + this.get('flags') + - TINYDNS.UInt8toOctal(this.get('service').length) + TINYDNS.escapeOctal(rdataRe, this.get('service')) + - TINYDNS.UInt8toOctal(this.get('regexp').length) + TINYDNS.escapeOctal(rdataRe, this.get('regexp')) diff --git a/rr/ns.js b/rr/ns.js index 235662e..54c907b 100644 --- a/rr/ns.js +++ b/rr/ns.js @@ -1,14 +1,13 @@ - import RR from '../rr.js' export default class NS extends RR { - constructor (opts) { + constructor(opts) { super(opts) if (opts === null) return } /****** Resource record specific setters *******/ - setDname (val) { + setDname(val) { if (!val) throw new Error(`NS: dname is required, ${this.citeRFC()}`) this.isFullyQualified('NS', 'dname', val) @@ -18,57 +17,61 @@ export default class NS extends RR { this.set('dname', val.toLowerCase()) } - getDescription () { + getDescription() { return 'Name Server' } - getRdataFields (arg) { - return [ 'dname' ] + getRdataFields(arg) { + return ['dname'] } - getRFCs () { - return [ 1035 ] + getRFCs() { + return [1035] } - getTypeId () { + getTypeId() { return 2 } /****** IMPORTERS *******/ - fromTinydns (opts) { + fromTinydns(opts) { // &fqdn:ip:x:ttl:timestamp:lo // eslint-disable-next-line no-unused-vars - const [ fqdn, ip, dname, ttl, ts, loc ] = opts.tinyline.substring(1).split(':') + const [fqdn, ip, dname, ttl, ts, loc] = opts.tinyline + .substring(1) + .split(':') return new NS({ - type : 'NS', - owner : this.fullyQualify(fqdn), - dname : this.fullyQualify(/\./.test(dname) ? dname : `${dname}.ns.${fqdn}`), - ttl : parseInt(ttl, 10), + type: 'NS', + owner: this.fullyQualify(fqdn), + dname: this.fullyQualify( + /\./.test(dname) ? dname : `${dname}.ns.${fqdn}`, + ), + ttl: parseInt(ttl, 10), timestamp: ts, - location : loc !== '' && loc !== '\n' ? loc : '', + location: loc !== '' && loc !== '\n' ? loc : '', }) } - fromBind (opts) { + fromBind(opts) { // test.example.com 3600 IN NS dname - const [ owner, ttl, c, type, dname ] = opts.bindline.split(/\s+/) + const [owner, ttl, c, type, dname] = opts.bindline.split(/\s+/) return new NS({ owner, - ttl : parseInt(ttl, 10), + ttl: parseInt(ttl, 10), class: c, - type : type, + type: type, dname: dname, }) } /****** EXPORTERS *******/ - toBind (zone_opts) { + toBind(zone_opts) { return `${this.getPrefix(zone_opts)}\t${this.getFQDN('dname', zone_opts)}\n` } - toTinydns () { + toTinydns() { return `&${this.getTinyFQDN('owner')}::${this.getTinyFQDN('dname')}:${this.getTinydnsPostamble()}\n` } } diff --git a/rr/nsec.js b/rr/nsec.js index 7e23d57..d7d5eab 100644 --- a/rr/nsec.js +++ b/rr/nsec.js @@ -1,15 +1,15 @@ - import RR from '../rr.js' export default class NSEC extends RR { - constructor (opts) { + constructor(opts) { super(opts) if (opts === null) return } /****** Resource record specific setters *******/ - setNextDomain (val) { - if (!val) throw new Error(`NSEC: 'next domain' is required:, ${this.citeRFC()}`) + setNextDomain(val) { + if (!val) + throw new Error(`NSEC: 'next domain' is required:, ${this.citeRFC()}`) this.isFullyQualified('NSEC', 'next domain', val) this.isValidHostname('NSEC', 'next domain', val) @@ -18,44 +18,50 @@ export default class NSEC extends RR { this.set('next domain', val.toLowerCase()) } - setTypeBitMaps (val) { - if (!val) throw new Error(`NSEC: 'type bit maps' is required, ${this.citeRFC()}`) + setTypeBitMaps(val) { + if (!val) + throw new Error(`NSEC: 'type bit maps' is required, ${this.citeRFC()}`) this.set('type bit maps', val) } - getDescription () { + getDescription() { return 'Next Secure' } - getRdataFields (arg) { - return [ 'next domain', 'type bit maps' ] + getRdataFields(arg) { + return ['next domain', 'type bit maps'] } - getRFCs () { - return [ 4034 ] + getRFCs() { + return [4034] } - getTypeId () { + getTypeId() { return 47 } /****** IMPORTERS *******/ - fromBind (opts) { + fromBind(opts) { // test.example.com 3600 IN NSEC NextDomain TypeBitMaps - const [ owner, ttl, c, type, next ] = opts.bindline.split(/\s+/) + const [owner, ttl, c, type, next] = opts.bindline.split(/\s+/) return new NSEC({ owner, - ttl : parseInt(ttl, 10), - class : c, - type : type, - 'next domain' : next, - 'type bit maps': opts.bindline.split(/\s+/).slice(5).filter(removeParens).join(' ').trim(), + ttl: parseInt(ttl, 10), + class: c, + type: type, + 'next domain': next, + 'type bit maps': opts.bindline + .split(/\s+/) + .slice(5) + .filter(removeParens) + .join(' ') + .trim(), }) } /****** EXPORTERS *******/ } -const removeParens = a => ![ '(',')' ].includes(a) +const removeParens = (a) => !['(', ')'].includes(a) diff --git a/rr/nsec3.js b/rr/nsec3.js index 6bf98a6..3ab20d3 100644 --- a/rr/nsec3.js +++ b/rr/nsec3.js @@ -1,26 +1,26 @@ - import RR from '../rr.js' import * as TINYDNS from '../lib/tinydns.js' export default class NSEC3 extends RR { - constructor (opts) { + constructor(opts) { super(opts) if (opts === null) return } /****** Resource record specific setters *******/ - setHashAlgorithm (val) { + setHashAlgorithm(val) { // Hash Algorithm is a single octet. // The Hash Algorithm field is represented as an unsigned decimal integer. - if (!val) throw new Error(`NSEC3: 'hash algorithm' is required, ${this.citeRFC()}`) + if (!val) + throw new Error(`NSEC3: 'hash algorithm' is required, ${this.citeRFC()}`) this.is8bitInt('NSEC3', 'hash algorithm', val) this.set('hash algorithm', val) } - setFlags (val) { + setFlags(val) { // The Flags field is represented as an unsigned decimal integer. if (!val) throw new Error(`NSEC3: 'flags' is required, ${this.citeRFC()}`) @@ -29,16 +29,17 @@ export default class NSEC3 extends RR { this.set('flags', val) } - setIterations (val) { + setIterations(val) { // The Iterations field is represented as an unsigned decimal integer. 0-65535 - if (!val) throw new Error(`NSEC3: 'iterations' is required, ${this.citeRFC()}`) + if (!val) + throw new Error(`NSEC3: 'iterations' is required, ${this.citeRFC()}`) this.is16bitInt('NSEC3', 'flags', val) this.set('iterations', val) } - setSalt (val) { + setSalt(val) { // The Salt field is represented as a sequence of case-insensitive // hexadecimal digits. Whitespace is not allowed within the // sequence. The Salt field is represented as "-" (without the @@ -46,95 +47,113 @@ export default class NSEC3 extends RR { this.set('salt', val) } - setNextHashedOwnerName (val) { + setNextHashedOwnerName(val) { // The Next Hashed Owner Name field is represented as an unpadded // sequence of case-insensitive base32 digits, without whitespace - if (!val) throw new Error(`NSEC3: 'next hashed owner name' is required, ${this.citeRFC()}`) + if (!val) + throw new Error( + `NSEC3: 'next hashed owner name' is required, ${this.citeRFC()}`, + ) this.set('next hashed owner name', val) } - setTypeBitMaps (val) { + setTypeBitMaps(val) { // The Type Bit Maps field is represented as a sequence of RR type mnemonics. - if (!val) throw new Error(`NSEC3: 'type bit maps' is required, ${this.citeRFC()}`) + if (!val) + throw new Error(`NSEC3: 'type bit maps' is required, ${this.citeRFC()}`) this.set('type bit maps', val) } - getDescription () { + getDescription() { return 'Next Secure' } - getRdataFields (arg) { - return [ 'hash algorithm', 'flags', 'iterations', 'salt', 'next hashed owner name', 'type bit maps' ] + getRdataFields(arg) { + return [ + 'hash algorithm', + 'flags', + 'iterations', + 'salt', + 'next hashed owner name', + 'type bit maps', + ] } - getRFCs () { - return [ 5155, 9077 ] + getRFCs() { + return [5155, 9077] } - getTypeId () { + getTypeId() { return 50 } /****** IMPORTERS *******/ - fromBind (opts) { + fromBind(opts) { // test.example.com. 3600 IN NSEC3 1 1 12 aabbccdd (2vptu5timamqttgl4luu9kg21e0aor3s A RRSIG) - const [ owner, ttl, c, type, ha, flags, iterations, salt ] = opts.bindline.split(/\s+/) + const [owner, ttl, c, type, ha, flags, iterations, salt] = + opts.bindline.split(/\s+/) const rdata = opts.bindline.split(/\(|\)/)[1] return new NSEC3({ owner, - ttl : parseInt(ttl, 10), - class : c, - type : type, - 'hash algorithm' : parseInt(ha, 10), - flags : parseInt(flags, 10), - iterations : parseInt(iterations, 10), + ttl: parseInt(ttl, 10), + class: c, + type: type, + 'hash algorithm': parseInt(ha, 10), + flags: parseInt(flags, 10), + iterations: parseInt(iterations, 10), salt, 'next hashed owner name': rdata.split(/\s+/)[0], - 'type bit maps' : rdata.split(/\s+/).slice(1).join('\t'), + 'type bit maps': rdata.split(/\s+/).slice(1).join('\t'), }) } - fromTinydns (opts) { - const [ fqdn, n, rdata, ttl, ts, loc ] = opts.tinyline.substring(1).split(':') + fromTinydns(opts) { + const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':') if (n != 50) throw new Error('NSEC3 fromTinydns, invalid n') const bytes = Buffer.from(TINYDNS.octalToChar(rdata), 'binary') return new NSEC3({ - owner : this.fullyQualify(fqdn), - ttl : parseInt(ttl, 10), - type : 'NSEC3', + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'NSEC3', 'hash algorithm': bytes.readUInt8(0), - flags : bytes.readUInt8(1), - iterations : bytes.readUInt16BE(2), + flags: bytes.readUInt8(1), + iterations: bytes.readUInt16BE(2), // salt : , // 'next hashed owner name': , // 'type bit maps' : , - timestamp : ts, - location : loc !== '' && loc !== '\n' ? loc : '', + timestamp: ts, + location: loc !== '' && loc !== '\n' ? loc : '', }) } /****** EXPORTERS *******/ - toBind (zone_opts) { - return `${this.getFQDN('owner', zone_opts)}\t${this.get('ttl')}\t${this.get('class')}\tNSEC3${this.getRdataFields().slice(0,4).map(f => '\t' + this.get(f)).join('')}\t(${this.getRdataFields().slice(4).map(f => this.get(f)).join('\t')})\n` + toBind(zone_opts) { + return `${this.getFQDN('owner', zone_opts)}\t${this.get('ttl')}\t${this.get('class')}\tNSEC3${this.getRdataFields() + .slice(0, 4) + .map((f) => '\t' + this.get(f)) + .join('')}\t(${this.getRdataFields() + .slice(4) + .map((f) => this.get(f)) + .join('\t')})\n` } - toTinydns () { + toTinydns() { const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g') return this.getTinydnsGeneric( TINYDNS.UInt8toOctal(this.get('hash algorithm')) + - TINYDNS.UInt8toOctal(this.get('flags')) + - TINYDNS.UInt16toOctal(this.get('iterations')) + - TINYDNS.escapeOctal(dataRe, this.get('salt')) + - TINYDNS.escapeOctal(dataRe, this.get('next hashed owner name')) + - TINYDNS.escapeOctal(dataRe, this.get('type bit maps')) + TINYDNS.UInt8toOctal(this.get('flags')) + + TINYDNS.UInt16toOctal(this.get('iterations')) + + TINYDNS.escapeOctal(dataRe, this.get('salt')) + + TINYDNS.escapeOctal(dataRe, this.get('next hashed owner name')) + + TINYDNS.escapeOctal(dataRe, this.get('type bit maps')), ) } } diff --git a/rr/nsec3param.js b/rr/nsec3param.js index c2a5a4c..d81ee32 100644 --- a/rr/nsec3param.js +++ b/rr/nsec3param.js @@ -1,42 +1,46 @@ - import RR from '../rr.js' export default class NSEC3PARAM extends RR { - constructor (opts) { + constructor(opts) { super(opts) if (opts === null) return } /****** Resource record specific setters *******/ - setHashAlgoritm (val) { + setHashAlgoritm(val) { // Hash Algorithm is a single octet. // The Hash Algorithm field is represented as an unsigned decimal integer. - if (!val) throw new Error(`NSEC3PARAM: 'hash algorithm' is required, ${this.citeRFC()}`) + if (!val) + throw new Error( + `NSEC3PARAM: 'hash algorithm' is required, ${this.citeRFC()}`, + ) this.is8bitInt('NSEC3PARAM', 'hash algorithm', val) this.set('hash algorithm', val) } - setFlags (val) { + setFlags(val) { // The Flags field is represented as an unsigned decimal integer. - if (!val) throw new Error(`NSEC3PARAM: 'flags' is required, ${this.citeRFC()}`) + if (!val) + throw new Error(`NSEC3PARAM: 'flags' is required, ${this.citeRFC()}`) this.is8bitInt('NSEC3PARAM', 'flags', val) this.set('flags', val) } - setIterations (val) { + setIterations(val) { // The Iterations field is represented as an unsigned decimal integer. 0-65535 - if (!val) throw new Error(`NSEC3PARAM: 'iterations' is required, ${this.citeRFC()}`) + if (!val) + throw new Error(`NSEC3PARAM: 'iterations' is required, ${this.citeRFC()}`) this.is16bitInt('NSEC3PARAM', 'iterations', val) this.set('iterations', val) } - setSalt (val) { + setSalt(val) { // The Salt field is represented as a sequence of case-insensitive // hexadecimal digits. Whitespace is not allowed within the // sequence. The Salt field is represented as "-" (without the @@ -44,41 +48,40 @@ export default class NSEC3PARAM extends RR { this.set('salt', val) } - getDescription () { + getDescription() { return 'Next Secure Parameters' } - getRdataFields (arg) { - return [ 'hash algorithm', 'flags', 'iterations', 'salt' ] + getRdataFields(arg) { + return ['hash algorithm', 'flags', 'iterations', 'salt'] } - getRFCs () { - return [ 5155 ] + getRFCs() { + return [5155] } - getTypeId () { + getTypeId() { return 51 } /****** IMPORTERS *******/ - fromBind (str) { + fromBind(str) { // test.example.com 3600 IN NSEC3PARAM - const [ owner, ttl, c, type ] = str.split(/\s+/) + const [owner, ttl, c, type] = str.split(/\s+/) return new NSEC3PARAM({ owner, - ttl : parseInt(ttl, 10), - class : c, - type : type, - 'hash algorithm' : '', - 'flags' : '', - 'iterations' : '', - 'salt' : '', + ttl: parseInt(ttl, 10), + class: c, + type: type, + 'hash algorithm': '', + flags: '', + iterations: '', + salt: '', 'next hashed owner name': '', - 'type bit maps' : '', + 'type bit maps': '', }) } /****** EXPORTERS *******/ - } diff --git a/rr/nxt.js b/rr/nxt.js new file mode 100644 index 0000000..c4e82da --- /dev/null +++ b/rr/nxt.js @@ -0,0 +1,67 @@ +import RR from '../rr.js' + +export default class NXT extends RR { + constructor(opts) { + super(opts) + if (opts === null) return + } + + /****** Resource record specific setters *******/ + setNextDomain(val) { + if (!val) + throw new Error(`NXT: 'next domain' is required:, ${this.citeRFC()}`) + + this.isFullyQualified('NXT', 'next domain', val) + this.isValidHostname('NXT', 'next domain', val) + + // RFC 4034: letters in the DNS names are lower cased + this.set('next domain', val.toLowerCase()) + } + + setTypeBitMap(val) { + if (!val) + throw new Error(`NXT: 'type bit map' is required, ${this.citeRFC()}`) + + this.set('type bit map', val) + } + + getDescription() { + return 'Next Secure' + } + + getRdataFields(arg) { + return ['next domain', 'type bit map'] + } + + getRFCs() { + return [2065] + } + + getTypeId() { + return 30 + } + + /****** IMPORTERS *******/ + + fromBind(opts) { + // test.example.com 3600 IN NXT NextDomain TypeBitMap + const [owner, ttl, c, type, next] = opts.bindline.split(/\s+/) + return new NXT({ + owner, + ttl: parseInt(ttl, 10), + class: c, + type: type, + 'next domain': next, + 'type bit map': opts.bindline + .split(/\s+/) + .slice(5) + .filter(removeParens) + .join(' ') + .trim(), + }) + } + + /****** EXPORTERS *******/ +} + +const removeParens = (a) => !['(', ')'].includes(a) diff --git a/rr/openpgpkey.js b/rr/openpgpkey.js index f3be0ea..c971cb6 100644 --- a/rr/openpgpkey.js +++ b/rr/openpgpkey.js @@ -1,41 +1,40 @@ - import RR from '../rr.js' export default class OPENPGPKEY extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setPublicKey (val) { + setPublicKey(val) { this.set('public key', val) } - getDescription () { + getDescription() { return 'OpenPGP Public Key' } - getRdataFields () { - return [ 'public key' ] + getRdataFields() { + return ['public key'] } - getRFCs () { - return [ 4880, 7929 ] + getRFCs() { + return [4880, 7929] } - getTypeId () { + getTypeId() { return 61 } /****** IMPORTERS *******/ - fromBind (str) { + fromBind(str) { // test.example.com 3600 IN OPENPGPKEY - const [ owner, ttl, c, type, privatekey ] = str.split(/\s+/) + const [owner, ttl, c, type, privatekey] = str.split(/\s+/) return new OPENPGPKEY({ owner, - ttl : parseInt(ttl, 10), - class : c, - type : type, + ttl: parseInt(ttl, 10), + class: c, + type: type, 'private key': privatekey, }) } diff --git a/rr/ptr.js b/rr/ptr.js index d201508..b2ab00c 100644 --- a/rr/ptr.js +++ b/rr/ptr.js @@ -1,13 +1,12 @@ - import RR from '../rr.js' export default class PTR extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setDname (val) { + setDname(val) { this.isFullyQualified('PTR', 'dname', val) this.isValidHostname('PTR', 'dname', val) @@ -15,51 +14,51 @@ export default class PTR extends RR { this.set('dname', val.toLowerCase()) } - getDescription () { + getDescription() { return 'Pointer' } - getRdataFields (arg) { - return [ 'dname' ] + getRdataFields(arg) { + return ['dname'] } - getRFCs () { - return [ 1035 ] + getRFCs() { + return [1035] } - getTypeId () { + getTypeId() { return 12 } /****** IMPORTERS *******/ - fromTinydns (opts) { + fromTinydns(opts) { // ^fqdn:p:ttl:timestamp:lo - const [ fqdn, p, ttl, ts, loc ] = opts.tinyline.substring(1).split(':') + const [fqdn, p, ttl, ts, loc] = opts.tinyline.substring(1).split(':') return new PTR({ - owner : this.fullyQualify(fqdn), - ttl : parseInt(ttl, 10), - type : 'PTR', - dname : this.fullyQualify(p), + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'PTR', + dname: this.fullyQualify(p), timestamp: ts, - location : loc !== '' && loc !== '\n' ? loc : '', + location: loc !== '' && loc !== '\n' ? loc : '', }) } - fromBind (opts) { + fromBind(opts) { // test.example.com 3600 IN PTR dname - const [ owner, ttl, c, type, dname ] = opts.bindline.split(/\s+/) + const [owner, ttl, c, type, dname] = opts.bindline.split(/\s+/) return new PTR({ owner, - ttl : parseInt(ttl, 10), + ttl: parseInt(ttl, 10), class: c, - type : type, + type: type, dname: dname, }) } /****** EXPORTERS *******/ - toTinydns () { + toTinydns() { return `^${this.getTinyFQDN('owner')}:${this.getTinyFQDN('dname')}:${this.getTinydnsPostamble()}\n` } } diff --git a/rr/rrsig.js b/rr/rrsig.js index a3955d9..0519fc0 100644 --- a/rr/rrsig.js +++ b/rr/rrsig.js @@ -1,85 +1,92 @@ - import RR from '../rr.js' export default class RRSIG extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setTypeCovered (val) { + setTypeCovered(val) { // a 2 octet Type Covered field if (!val) throw new Error(`RRSIG: 'type covered' is required`) - if (val.length > 2) throw new Error(`RRSIG: 'type covered' is too long, ${this.citeRFC()}`) + if (val.length > 2) + throw new Error(`RRSIG: 'type covered' is too long, ${this.citeRFC()}`) this.set('type covered', val) } - setAlgorithm (val) { + setAlgorithm(val) { // a 1 octet Algorithm field // 1=RSA/MD5, 2=DH, 3=RRSIGA/SHA-1, 4=EC, 5=RSA/SHA-1 - if (![ 1,2,3,4,5,253,254 ].includes(val)) + if (![1, 2, 3, 4, 5, 253, 254].includes(val)) throw new Error(`RRSIG: algorithm invalid, ${this.citeRFC()}`) this.set('algorithm', val) } - setLabels (val) { + setLabels(val) { // a 1 octet Labels field this.is8bitInt('RRSIG', 'labels', val) this.set('labels', val) } - setOriginalTtl (val) { + setOriginalTtl(val) { // a 4 octet Original TTL field this.is32bitInt('RRSIG', 'original ttl', val) this.set('original ttl', val) } - setSignatureExpiration (val) { + setSignatureExpiration(val) { // a 4 octet Signature Expiration field this.set('signature expiration', val) } - setSignatureInception (val) { + setSignatureInception(val) { // a 4 octet Signature Inception field this.set('signature inception', val) } - setKeyTag (val) { + setKeyTag(val) { // a 2 octet Key tag this.set('key tag', val) } - setSignersName (val) { + setSignersName(val) { // the Signer's Name field this.set('signers name', val) } - setSignature (val) { + setSignature(val) { // the Signature field. this.set('signature', val) } - getDescription () { + getDescription() { return 'Resource Record Signature' } - getRdataFields (arg) { + getRdataFields(arg) { return [ - 'type covered', 'algorithm', 'labels', 'original ttl', 'signature expiration', - 'signature inception', 'key tag', 'signers name', 'signature', + 'type covered', + 'algorithm', + 'labels', + 'original ttl', + 'signature expiration', + 'signature inception', + 'key tag', + 'signers name', + 'signature', ] } - getRFCs () { - return [ 4034 ] + getRFCs() { + return [4034] } - getTypeId () { + getTypeId() { return 46 } @@ -97,5 +104,4 @@ export default class RRSIG extends RR { // } /****** EXPORTERS *******/ - } diff --git a/rr/sig.js b/rr/sig.js index ef05d2e..9c62589 100644 --- a/rr/sig.js +++ b/rr/sig.js @@ -1,20 +1,19 @@ - import RR from '../rr.js' export default class SIG extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setTypeCovered (val) { + setTypeCovered(val) { // a 2 octet Type Covered field if (!val) throw new Error(`SIG: 'type covered' is required`) this.set('type covered', val) } - setAlgorithm (val) { + setAlgorithm(val) { // a 1 octet Algorithm field this.is8bitInt('SIG', 'labels', val) @@ -22,64 +21,71 @@ export default class SIG extends RR { this.set('algorithm', val) } - setLabels (val) { + setLabels(val) { // a 1 octet Labels field this.is8bitInt('SIG', 'labels', val) this.set('labels', val) } - setOriginalTtl (val) { + setOriginalTtl(val) { // a 4 octet Original TTL field this.is32bitInt('SIG', 'original ttl', val) this.set('original ttl', val) } - setSignatureExpiration (val) { + setSignatureExpiration(val) { // a 4 octet Signature Expiration field this.set('signature expiration', val) } - setSignatureInception (val) { + setSignatureInception(val) { // a 4 octet Signature Inception field this.set('signature inception', val) } - setKeyTag (val) { + setKeyTag(val) { // a 2 octet Key tag this.set('key tag', val) } - setSignersName (val) { + setSignersName(val) { // the domain name of the signer generating the SIG RR // RFC 4034: letters in the DNS names are lower cased this.set('signers name', val.toLowerCase()) } - setSignature (val) { + setSignature(val) { // the Signature field. this.set('signature', val) } - getDescription () { + getDescription() { return 'Signature' } - getRdataFields (arg) { + getRdataFields(arg) { return [ - 'type covered', 'algorithm', 'labels', 'original ttl', 'signature expiration', - 'signature inception', 'key tag', 'signers name', 'signature', + 'type covered', + 'algorithm', + 'labels', + 'original ttl', + 'signature expiration', + 'signature inception', + 'key tag', + 'signers name', + 'signature', ] } - getRFCs () { - return [ 2535 ] + getRFCs() { + return [2535] } - getTypeId () { + getTypeId() { return 24 } @@ -96,5 +102,4 @@ export default class SIG extends RR { // } /****** EXPORTERS *******/ - } diff --git a/rr/smimea.js b/rr/smimea.js index eb4b350..2968ef7 100644 --- a/rr/smimea.js +++ b/rr/smimea.js @@ -1,73 +1,80 @@ - import RR from '../rr.js' export default class SMIMEA extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setCertificateUsage (val) { - if (![ 0,1,2,3 ].includes(val)) + setCertificateUsage(val) { + if (![0, 1, 2, 3].includes(val)) throw new Error(`SMIMEA: certificate usage invalid, ${this.citeRFC()}`) this.set('certificate usage', val) } - setSelector (val) { - if (![ 0,1 ].includes(val)) + setSelector(val) { + if (![0, 1].includes(val)) throw new Error(`SMIMEA: selector invalid, ${this.citeRFC()}`) this.set('selector', val) } - setMatchingType (val) { - if (![ 0,1,2 ].includes(val)) + setMatchingType(val) { + if (![0, 1, 2].includes(val)) throw new Error(`SMIMEA: matching type, ${this.citeRFC()}`) this.set('matching type', val) } - setCertificateAssociationData (val) { + setCertificateAssociationData(val) { this.set('certificate association data', val) } - - getDescription () { + getDescription() { return 'S/MIME cert association' } - getRdataFields (arg) { - return [ 'certificate usage', 'selector', 'matching type', 'certificate association data' ] + getRdataFields(arg) { + return [ + 'certificate usage', + 'selector', + 'matching type', + 'certificate association data', + ] } - getRFCs () { - return [ 8162 ] + getRFCs() { + return [8162] } - getTypeId () { + getTypeId() { return 53 } - getQuotedFields () { - return [ ] + getQuotedFields() { + return [] } /****** IMPORTERS *******/ - fromBind (opts) { + fromBind(opts) { // test.example.com 3600 IN SMIMEA, usage, selector, match, data - const [ owner, ttl, c, type, usage, selector, match ] = opts.bindline.split(/\s+/) + const [owner, ttl, c, type, usage, selector, match] = + opts.bindline.split(/\s+/) return new SMIMEA({ owner, - ttl : parseInt(ttl, 10), - class : c, - type : type, - 'certificate usage' : parseInt(usage, 10), - selector : parseInt(selector, 10), - 'matching type' : parseInt(match , 10), - 'certificate association data': opts.bindline.split(/\s+/).slice(7).join(' ').trim(), + ttl: parseInt(ttl, 10), + class: c, + type: type, + 'certificate usage': parseInt(usage, 10), + selector: parseInt(selector, 10), + 'matching type': parseInt(match, 10), + 'certificate association data': opts.bindline + .split(/\s+/) + .slice(7) + .join(' ') + .trim(), }) } - } diff --git a/rr/soa.js b/rr/soa.js index 9fc5cc9..a96a6e6 100644 --- a/rr/soa.js +++ b/rr/soa.js @@ -1,13 +1,12 @@ - import RR from '../rr.js' export default class SOA extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setMinimum (val) { + setMinimum(val) { // minimum (used for negative caching, since RFC 2308) // RFC 1912 sugggests 1-5 days // RIPE recommends 3600 (1 hour) @@ -16,7 +15,7 @@ export default class SOA extends RR { this.set('minimum', val) } - setMname (val) { + setMname(val) { // MNAME (primary NS) this.isValidHostname('SOA', 'MNAME', val) this.isFullyQualified('SOA', 'MNAME', val) @@ -25,23 +24,24 @@ export default class SOA extends RR { this.set('mname', val.toLowerCase()) } - setRname (val) { + setRname(val) { // RNAME (email of admin) (escape . with \) this.isValidHostname('SOA', 'RNAME', val) this.isFullyQualified('SOA', 'RNAME', val) - if (/@/.test(val)) throw new Error(`SOA rname replaces @ with a . (dot), ${this.citeRFC()}`) + if (/@/.test(val)) + throw new Error(`SOA rname replaces @ with a . (dot), ${this.citeRFC()}`) // RFC 4034: letters in the DNS names are lower cased this.set('rname', val.toLowerCase()) } - setSerial (val) { + setSerial(val) { this.is32bitInt('SOA', 'serial', val) this.set('serial', val) } - setRefresh (val) { + setRefresh(val) { // refresh (seconds after which to check with master for update) // RFC 1912 suggests 20 min to 12 hours // RIPE recommends 86400 (24 hours) @@ -50,7 +50,7 @@ export default class SOA extends RR { this.set('refresh', val) } - setRetry (val) { + setRetry(val) { // seconds after which to retry serial # update // RIPE recommends 7200 seconds (2 hours) @@ -59,7 +59,7 @@ export default class SOA extends RR { this.set('retry', val) } - setExpire (val) { + setExpire(val) { // seconds after which secondary should drop zone if no master response // RFC 1912 suggests 2-4 weeks // RIPE suggests 3600000 (1,000 hours, 6 weeks) @@ -68,73 +68,88 @@ export default class SOA extends RR { this.set('expire', val) } - getDescription () { + getDescription() { return 'Start Of Authority' } - getRdataFields (arg) { - return [ 'mname', 'rname', 'serial', 'refresh', 'retry', 'expire', 'minimum' ] + getRdataFields(arg) { + return ['mname', 'rname', 'serial', 'refresh', 'retry', 'expire', 'minimum'] } - getRFCs () { - return [ 1035, 2308 ] + getRFCs() { + return [1035, 2308] } - getTypeId () { + getTypeId() { return 6 } /****** IMPORTERS *******/ - fromBind (opts) { + fromBind(opts) { // example.com TTL IN SOA mname rname serial refresh retry expire minimum - const [ owner, ttl, c, type, mname, rname, serial, refresh, retry, expire, minimum ] = opts.bindline.split(/[\s+]/) + const [ + owner, + ttl, + c, + type, + mname, + rname, + serial, + refresh, + retry, + expire, + minimum, + ] = opts.bindline.split(/[\s+]/) return new SOA({ owner, - ttl : parseInt(ttl) || parseInt(minimum), - class : c, + ttl: parseInt(ttl) || parseInt(minimum), + class: c, type, mname, rname, - serial : parseInt(serial , 10), + serial: parseInt(serial, 10), refresh: parseInt(refresh, 10), - retry : parseInt(retry , 10), - expire : parseInt(expire , 10), + retry: parseInt(retry, 10), + expire: parseInt(expire, 10), minimum: parseInt(minimum, 10), }) } - fromTinydns (opts) { + fromTinydns(opts) { // Zfqdn:mname:rname:ser:ref:ret:exp:min:ttl:time:lo - const [ fqdn, mname, rname, ser, ref, ret, exp, min, ttl, ts, loc ] = opts.tinyline.substring(1).split(':') + const [fqdn, mname, rname, ser, ref, ret, exp, min, ttl, ts, loc] = + opts.tinyline.substring(1).split(':') return new SOA({ - owner : this.fullyQualify(fqdn), - ttl : parseInt(ttl, 10), - type : 'SOA', - mname : this.fullyQualify(mname), - rname : this.fullyQualify(rname), - serial : parseInt(ser || opts.default?.serial, 10), - refresh : parseInt(ref, 10) || 16384, - retry : parseInt(ret, 10) || 2048, - expire : parseInt(exp, 10) || 1048576, - minimum : parseInt(min, 10) || 2560, + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'SOA', + mname: this.fullyQualify(mname), + rname: this.fullyQualify(rname), + serial: parseInt(ser || opts.default?.serial, 10), + refresh: parseInt(ref, 10) || 16384, + retry: parseInt(ret, 10) || 2048, + expire: parseInt(exp, 10) || 1048576, + minimum: parseInt(min, 10) || 2560, timestamp: parseInt(ts) || '', - location : loc !== '' && loc !== '\n' ? loc : '', + location: loc !== '' && loc !== '\n' ? loc : '', }) } /****** EXPORTERS *******/ - toBind (zone_opts) { - const numFields = [ 'serial', 'refresh', 'retry', 'expire', 'minimum' ] - return `${this.getFQDN('owner', zone_opts)}\t${this.get('ttl')}\t${this.get('class')}\tSOA\t${this.getFQDN('mname', zone_opts)}\t${this.getFQDN('rname', zone_opts)}${numFields.map(f => '\t' + this.get(f) ).join('')}\n` + toBind(zone_opts) { + const numFields = ['serial', 'refresh', 'retry', 'expire', 'minimum'] + return `${this.getFQDN('owner', zone_opts)}\t${this.get('ttl')}\t${this.get('class')}\tSOA\t${this.getFQDN('mname', zone_opts)}\t${this.getFQDN('rname', zone_opts)}${numFields.map((f) => '\t' + this.get(f)).join('')}\n` } - toMaraDNS () { - return `${this.get('owner')}\t SOA\t${this.getRdataFields().map(f => this.getQuoted(f)).join('\t')} ~\n` + toMaraDNS() { + return `${this.get('owner')}\t SOA\t${this.getRdataFields() + .map((f) => this.getQuoted(f)) + .join('\t')} ~\n` } - toTinydns () { + toTinydns() { return `Z${this.getTinyFQDN('owner')}:${this.getTinyFQDN('mname')}:${this.getTinyFQDN('rname')}:${this.getEmpty('serial')}:${this.getEmpty('refresh')}:${this.getEmpty('retry')}:${this.getEmpty('expire')}:${this.getEmpty('minimum')}:${this.getTinydnsPostamble()}\n` } } diff --git a/rr/spf.js b/rr/spf.js index 22d1f9a..c060727 100644 --- a/rr/spf.js +++ b/rr/spf.js @@ -5,50 +5,53 @@ import TXT from './txt.js' import * as TINYDNS from '../lib/tinydns.js' export default class SPF extends TXT { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setData (val) { + setData(val) { this.set('data', val) } - getDescription () { + getDescription() { return 'Sender Policy Framework' } - getRdataFields (arg) { - return [ 'data' ] + getRdataFields(arg) { + return ['data'] } - getRFCs () { - return [ 4408, 7208 ] + getRFCs() { + return [4408, 7208] } - getTypeId () { + getTypeId() { return 99 } /****** IMPORTERS *******/ - fromTinydns (opts) { + fromTinydns(opts) { // SPF via generic, :fqdn:n:rdata:ttl:timestamp:lo - const [ fqdn, n, rdata, ttl, ts, loc ] = opts.tinyline.substring(1).split(':') + const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':') if (n != 99) throw new Error('SPF fromTinydns, invalid n') return new SPF({ - type : 'SPF', - owner : this.fullyQualify(fqdn), - data : TINYDNS.octalToChar(rdata), - ttl : parseInt(ttl, 10), + type: 'SPF', + owner: this.fullyQualify(fqdn), + data: TINYDNS.octalToChar(rdata), + ttl: parseInt(ttl, 10), timestamp: ts, - location : loc !== '' && loc !== '\n' ? loc : '', + location: loc !== '' && loc !== '\n' ? loc : '', }) } /****** EXPORTERS *******/ - toTinydns () { - const rdata = TINYDNS.escapeOctal(new RegExp(/[\r\n\t:\\/]/, 'g'), this.get('data')) + toTinydns() { + const rdata = TINYDNS.escapeOctal( + new RegExp(/[\r\n\t:\\/]/, 'g'), + this.get('data'), + ) return this.getTinydnsGeneric(rdata) } } diff --git a/rr/srv.js b/rr/srv.js index 0811b3a..d285361 100644 --- a/rr/srv.js +++ b/rr/srv.js @@ -1,34 +1,33 @@ - import net from 'net' import RR from '../rr.js' import * as TINYDNS from '../lib/tinydns.js' export default class SRV extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setPriority (val) { + setPriority(val) { this.is16bitInt('SRV', 'priority', val) this.set('priority', val) } - setPort (val) { + setPort(val) { this.is16bitInt('SRV', 'port', val) this.set('port', val) } - setWeight (val) { + setWeight(val) { this.is16bitInt('SRV', 'weight', val) this.set('weight', val) } - setTarget (val) { + setTarget(val) { if (!val) throw new Error(`SRV: target is required, ${this.citeRFC()}`) if (net.isIPv4(val) || net.isIPv6(val)) @@ -41,77 +40,78 @@ export default class SRV extends RR { this.set('target', val.toLowerCase()) } - getDescription () { + getDescription() { return 'Service' } - getRdataFields (arg) { - return [ 'priority', 'weight', 'port', 'target' ] + getRdataFields(arg) { + return ['priority', 'weight', 'port', 'target'] } - getRFCs () { - return [ 2782 ] + getRFCs() { + return [2782] } - getTypeId () { + getTypeId() { return 33 } /****** IMPORTERS *******/ - fromTinydns (opts) { + fromTinydns(opts) { const str = opts.tinyline let fqdn, addr, port, pri, weight, ttl, ts, loc, n, rdata if (str[0] === 'S') { // patched tinydns with S records - [ fqdn, addr, port, pri, weight, ttl, ts, loc ] = str.substring(1).split(':') - } - else { + ;[fqdn, addr, port, pri, weight, ttl, ts, loc] = str + .substring(1) + .split(':') + } else { // tinydns generic record format - [ fqdn, n, rdata, ttl, ts, loc ] = str.substring(1).split(':') + ;[fqdn, n, rdata, ttl, ts, loc] = str.substring(1).split(':') if (n != 33) throw new Error('SRV fromTinydns: invalid n') - pri = TINYDNS.octalToUInt16(rdata.substring(0, 8)) + pri = TINYDNS.octalToUInt16(rdata.substring(0, 8)) weight = TINYDNS.octalToUInt16(rdata.substring(8, 16)) - port = TINYDNS.octalToUInt16(rdata.substring(16, 24)) - addr = (TINYDNS.unpackDomainName(rdata.substring(24)))[0] + port = TINYDNS.octalToUInt16(rdata.substring(16, 24)) + addr = TINYDNS.unpackDomainName(rdata.substring(24))[0] } return new SRV({ - owner : this.fullyQualify(fqdn), - ttl : parseInt(ttl, 10), - type : 'SRV', - priority : parseInt(pri, 10), - weight : parseInt(weight, 10), - port : parseInt(port, 10), - target : this.fullyQualify(addr), + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'SRV', + priority: parseInt(pri, 10), + weight: parseInt(weight, 10), + port: parseInt(port, 10), + target: this.fullyQualify(addr), timestamp: ts, - location : loc !== '' && loc !== '\n' ? loc : '', + location: loc !== '' && loc !== '\n' ? loc : '', }) } - fromBind (opts) { + fromBind(opts) { // test.example.com 3600 IN SRV Priority Weight Port Target - const [ owner, ttl, c, type, pri, weight, port, target ] = opts.bindline.split(/\s+/) + const [owner, ttl, c, type, pri, weight, port, target] = + opts.bindline.split(/\s+/) return new SRV({ - owner : owner, - ttl : parseInt(ttl, 10), - class : c, - type : type, - priority: parseInt(pri, 10), - weight : parseInt(weight, 10), - port : parseInt(port, 10), - target : target, + owner: owner, + ttl: parseInt(ttl, 10), + class: c, + type: type, + priority: parseInt(pri, 10), + weight: parseInt(weight, 10), + port: parseInt(port, 10), + target: target, }) } /****** EXPORTERS *******/ - toTinydns () { - + toTinydns() { let rdata = '' - for (const e of [ 'priority', 'weight', 'port' ]) { + for (const e of ['priority', 'weight', 'port']) { rdata += TINYDNS.UInt16toOctal(this.get(e)) } diff --git a/rr/sshfp.js b/rr/sshfp.js index e27430f..eea8855 100644 --- a/rr/sshfp.js +++ b/rr/sshfp.js @@ -1,86 +1,85 @@ - import RR from '../rr.js' import * as TINYDNS from '../lib/tinydns.js' export default class SSHFP extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setAlgorithm (val) { + setAlgorithm(val) { // 0: reserved 1: RSA 2: DSA 3: ECDSA 4: Ed25519 6: Ed448 this.is8bitInt('SSHFP', 'algorithm', val) this.set('algorithm', val) } - setFptype (val) { + setFptype(val) { // 0: reserved, 1: SHA-1, 2: SHA-256 this.is8bitInt('SSHFP', 'type', val) this.set('fptype', val) } - setFingerprint (val) { + setFingerprint(val) { this.set('fingerprint', val) } - getDescription () { + getDescription() { return 'Secure Shell Key Fingerprints' } - getRdataFields () { - return [ 'algorithm', 'fptype', 'fingerprint' ] + getRdataFields() { + return ['algorithm', 'fptype', 'fingerprint'] } - getRFCs () { - return [ 4255, 7479, 8709 ] + getRFCs() { + return [4255, 7479, 8709] } - getTypeId () { + getTypeId() { return 44 } /****** IMPORTERS *******/ - fromTinydns (opts) { + fromTinydns(opts) { // SSHFP via generic, :fqdn:n:rdata:ttl:timestamp:lo - const [ fqdn, n, rdata, ttl, ts, loc ] = opts.tinyline.substring(1).split(':') + const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':') if (n != 44) throw new Error('SSHFP fromTinydns, invalid n') return new SSHFP({ - owner : this.fullyQualify(fqdn), - ttl : parseInt(ttl, 10), - type : 'SSHFP', - algorithm : TINYDNS.octalToUInt8(rdata.substring(0, 4)), - fptype : TINYDNS.octalToUInt8(rdata.substring(4, 8)), + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'SSHFP', + algorithm: TINYDNS.octalToUInt8(rdata.substring(0, 4)), + fptype: TINYDNS.octalToUInt8(rdata.substring(4, 8)), fingerprint: TINYDNS.octalToHex(rdata.substring(8)), - timestamp : ts, - location : loc !== '' && loc !== '\n' ? loc : '', + timestamp: ts, + location: loc !== '' && loc !== '\n' ? loc : '', }) } - fromBind (opts) { + fromBind(opts) { // test.example.com 3600 IN SSHFP algo fptype fp - const [ owner, ttl, c, type, algo, fptype, fp ] = opts.bindline.split(/\s+/) + const [owner, ttl, c, type, algo, fptype, fp] = opts.bindline.split(/\s+/) return new SSHFP({ owner, - ttl : parseInt(ttl, 10), - class : c, - type : type, - algorithm : parseInt(algo, 10), - fptype : parseInt(fptype, 10), + ttl: parseInt(ttl, 10), + class: c, + type: type, + algorithm: parseInt(algo, 10), + fptype: parseInt(fptype, 10), fingerprint: fp, }) } /****** EXPORTERS *******/ - toTinydns () { + toTinydns() { return this.getTinydnsGeneric( TINYDNS.UInt8toOctal(this.get('algorithm')) + - TINYDNS.UInt8toOctal(this.get('fptype')) + - TINYDNS.packHex(this.get('fingerprint')) + TINYDNS.UInt8toOctal(this.get('fptype')) + + TINYDNS.packHex(this.get('fingerprint')), ) } } diff --git a/rr/tlsa.js b/rr/tlsa.js index e08c06f..1432cf8 100644 --- a/rr/tlsa.js +++ b/rr/tlsa.js @@ -1,106 +1,113 @@ - import RR from '../rr.js' import * as TINYDNS from '../lib/tinydns.js' export default class TLSA extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setCertificateUsage (val) { - if (![ 0,1,2,3 ].includes(val)) + setCertificateUsage(val) { + if (![0, 1, 2, 3].includes(val)) throw new Error(`TLSA: certificate usage invalid, ${this.citeRFC()}`) this.set('certificate usage', val) } - setSelector (val) { - if (![ 0,1 ].includes(val)) + setSelector(val) { + if (![0, 1].includes(val)) throw new Error(`TLSA: selector invalid, ${this.citeRFC()}`) this.set('selector', val) } - setMatchingType (val) { - if (![ 0,1,2 ].includes(val)) + setMatchingType(val) { + if (![0, 1, 2].includes(val)) throw new Error(`TLSA: matching type, ${this.citeRFC()}`) this.set('matching type', val) } - setCertificateAssociationData (val) { + setCertificateAssociationData(val) { this.set('certificate association data', val) } - getDescription () { + getDescription() { return 'TLSA certificate association' } - getRdataFields (arg) { - return [ 'certificate usage', 'selector', 'matching type', 'certificate association data' ] + getRdataFields(arg) { + return [ + 'certificate usage', + 'selector', + 'matching type', + 'certificate association data', + ] } - getRFCs () { - return [ 6698 ] + getRFCs() { + return [6698] } - getTypeId () { + getTypeId() { return 52 } - getQuotedFields () { - return [ ] + getQuotedFields() { + return [] } /****** IMPORTERS *******/ - fromBind (opts) { + fromBind(opts) { // test.example.com 3600 IN TLSA, usage, selector, match, data - const match = opts.bindline.split(/^([^\s]+)\s+([0-9]+)\s+(\w+)\s+(\w+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+(.*?)\s*$/) + const match = opts.bindline.split( + /^([^\s]+)\s+([0-9]+)\s+(\w+)\s+(\w+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+(.*?)\s*$/, + ) if (!match) throw new Error(`unable to parse TLSA: ${opts.bindline}`) - const [ owner, ttl, c, type, usage, selector, matchtype, cad ] = match.slice(1) + const [owner, ttl, c, type, usage, selector, matchtype, cad] = + match.slice(1) return new TLSA({ - owner : this.fullyQualify(owner), - ttl : parseInt(ttl, 10), - class : c, + owner: this.fullyQualify(owner), + ttl: parseInt(ttl, 10), + class: c, type, - 'certificate usage' : parseInt(usage, 10), - selector : parseInt(selector, 10), - 'matching type' : parseInt(matchtype, 10), + 'certificate usage': parseInt(usage, 10), + selector: parseInt(selector, 10), + 'matching type': parseInt(matchtype, 10), 'certificate association data': cad, }) } - fromTinydns (opts) { - const [ fqdn, n, rdata, ttl, ts, loc ] = opts.tinyline.substring(1).split(':') + fromTinydns(opts) { + const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':') if (n != 52) throw new Error('TLSA fromTinydns, invalid n') const bytes = Buffer.from(TINYDNS.octalToChar(rdata), 'binary') return new TLSA({ - owner : this.fullyQualify(fqdn), - ttl : parseInt(ttl, 10), - type : 'TLSA', - 'certificate usage' : bytes.readUInt8(0), - selector : bytes.readUInt8(1), - 'matching type' : bytes.readUInt8(2), + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'TLSA', + 'certificate usage': bytes.readUInt8(0), + selector: bytes.readUInt8(1), + 'matching type': bytes.readUInt8(2), 'certificate association data': bytes.slice(3).toString(), - timestamp : ts, - location : loc !== '' && loc !== '\n' ? loc : '', + timestamp: ts, + location: loc !== '' && loc !== '\n' ? loc : '', }) } /****** EXPORTERS *******/ - toTinydns () { + toTinydns() { const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g') return this.getTinydnsGeneric( TINYDNS.UInt8toOctal(this.get('certificate usage')) + - TINYDNS.UInt8toOctal(this.get('selector')) + - TINYDNS.UInt8toOctal(this.get('matching type')) + - TINYDNS.escapeOctal(dataRe, this.get('certificate association data')) + TINYDNS.UInt8toOctal(this.get('selector')) + + TINYDNS.UInt8toOctal(this.get('matching type')) + + TINYDNS.escapeOctal(dataRe, this.get('certificate association data')), ) } } diff --git a/rr/tsig.js b/rr/tsig.js new file mode 100644 index 0000000..c88a91f --- /dev/null +++ b/rr/tsig.js @@ -0,0 +1,48 @@ +import RR from '../rr.js' + +export default class TSIG extends RR { + constructor(opts) { + super(opts) + if (opts === null) return + } + + /****** Resource record specific setters *******/ + + getDescription() { + return 'Transaction Signature' + } + + getRdataFields(arg) { + return ['algorithm name', 'time signed', 'fudge', 'mac', 'original id', 'error', 'other'] + } + + getRFCs() { + return [2845] + } + + getTypeId() { + return 250 + } + + /****** IMPORTERS *******/ + + fromBind(opts) { + // test.example.com 3600 IN TSIG SAMPLE-ALG.EXAMPLE. 853804800 300 0 0 0 + const [owner, ttl, c, type, algorithm] = opts.bindline.split(/\s+/) + return new TSIG({ + owner, + ttl: parseInt(ttl, 10), + class: c, + type: type, + 'algorithm': algorithm, + // 'time signed': opts.bindline, + // fudge + // mac + // original id + // error + // other + }) + } + + /****** EXPORTERS *******/ +} diff --git a/rr/txt.js b/rr/txt.js index 895182d..a8649fa 100644 --- a/rr/txt.js +++ b/rr/txt.js @@ -1,61 +1,59 @@ - import RR from '../rr.js' import * as TINYDNS from '../lib/tinydns.js' export default class TXT extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setData (val) { + setData(val) { this.set('data', val) } - getDescription () { + getDescription() { return 'Text' } - getRdataFields (arg) { - return [ 'data' ] + getRdataFields(arg) { + return ['data'] } - getRFCs () { - return [ 1035 ] + getRFCs() { + return [1035] } - getTypeId () { + getTypeId() { return 16 } /****** IMPORTERS *******/ - fromTinydns (opts) { + fromTinydns(opts) { const str = opts.tinyline let fqdn, rdata, s, ttl, ts, loc // 'fqdn:s:ttl:timestamp:lo if (str[0] === "'") { - [ fqdn, s, ttl, ts, loc ] = str.substring(1).split(':') + ;[fqdn, s, ttl, ts, loc] = str.substring(1).split(':') rdata = TINYDNS.octalToChar(s) - } - else { - [ fqdn, rdata, ttl, ts, loc ] = this.fromTinydnsGeneric(str) + } else { + ;[fqdn, rdata, ttl, ts, loc] = this.fromTinydnsGeneric(str) } return new this.constructor({ - owner : this.fullyQualify(fqdn), - ttl : parseInt(ttl, 10), - type : 'TXT', - data : rdata, + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'TXT', + data: rdata, timestamp: ts, - location : loc !== '' && loc !== '\n' ? loc : '', + location: loc !== '' && loc !== '\n' ? loc : '', }) } - fromTinydnsGeneric (str) { + fromTinydnsGeneric(str) { // generic: :fqdn:n:rdata:ttl:timestamp:location // eslint-disable-next-line prefer-const - let [ fqdn, n, rdata, ttl, ts, loc ] = str.substring(1).split(':') + let [fqdn, n, rdata, ttl, ts, loc] = str.substring(1).split(':') if (n != 16) throw new Error('TXT fromTinydns, invalid n') rdata = TINYDNS.octalToChar(rdata) @@ -67,35 +65,40 @@ export default class TXT extends RR { pos = len + pos len = rdata.charCodeAt(pos + 1) } - return [ fqdn, s, ttl, ts, loc ] + return [fqdn, s, ttl, ts, loc] } - fromBind (opts) { + fromBind(opts) { // test.example.com 3600 IN TXT "..." - const match = opts.bindline.split(/^([^\s]+)\s+([0-9]+)\s+(\w+)\s+(\w+)\s+?\s*(.*?)\s*$/) + const match = opts.bindline.split( + /^([^\s]+)\s+([0-9]+)\s+(\w+)\s+(\w+)\s+?\s*(.*?)\s*$/, + ) if (!match) throw new Error(`unable to parse TXT: ${opts.bindline}`) - const [ owner, ttl, c, type, rdata ] = match.slice(1) + const [owner, ttl, c, type, rdata] = match.slice(1) return new this.constructor({ owner, - ttl : parseInt(ttl, 10), + ttl: parseInt(ttl, 10), class: c, type, - data : rdata.match(/"([^"]+?)"/g).map(s => s.replace(/^"|"$/g, '')).join(''), + data: rdata + .match(/"([^"]+?)"/g) + .map((s) => s.replace(/^"|"$/g, '')) + .join(''), }) } /****** EXPORTERS *******/ - toBind (zone_opts) { + toBind(zone_opts) { return `${this.getPrefix(zone_opts)}\t"${asQuotedStrings(this.get('data'))}"\n` } - toMaraDNS () { + toMaraDNS() { const data = asQuotedStrings(this.get('data')).replace(/"/g, "'") return `${this.get('owner')}\t+${this.get('ttl')}\t${this.get('type')}\t'${data}' ~\n` } - toTinydns () { + toTinydns() { let data = this.get('data') if (Array.isArray(data)) data = data.join('') const rdata = TINYDNS.escapeOctal(new RegExp(/[\r\n\t:\\/]/, 'g'), data) @@ -103,15 +106,19 @@ export default class TXT extends RR { } } -function asQuotedStrings (data) { - +function asQuotedStrings(data) { // BIND croaks when any string in the TXT RR data is longer than 255 if (Array.isArray(data)) { let hasTooLong = false for (const str of data) { if (str.length > 255) hasTooLong = true } - return hasTooLong ? data.join('').match(/(.{1,255})/g).join('" "') : data.join('" "') + return hasTooLong + ? data + .join('') + .match(/(.{1,255})/g) + .join('" "') + : data.join('" "') } if (data.length > 255) { diff --git a/rr/uri.js b/rr/uri.js index 449feb2..08aeb94 100644 --- a/rr/uri.js +++ b/rr/uri.js @@ -1,91 +1,91 @@ - import RR from '../rr.js' import * as TINYDNS from '../lib/tinydns.js' export default class URI extends RR { - constructor (opts) { + constructor(opts) { super(opts) } /****** Resource record specific setters *******/ - setPriority (val) { + setPriority(val) { this.is16bitInt('URI', 'priority', val) this.set('priority', val) } - setWeight (val) { + setWeight(val) { this.is16bitInt('URI', 'weight', val) this.set('weight', val) } - setTarget (val) { + setTarget(val) { if (!val) throw new Error(`URI: target is required, ${this.citeRFC()}`) this.set('target', val) } /****** IMPORTERS *******/ - fromTinydns (opts) { + fromTinydns(opts) { // URI via generic, :fqdn:n:rdata:ttl:timestamp:lo - const [ fqdn, n, rdata, ttl, ts, loc ] = opts.tinyline.substring(1).split(':') + const [fqdn, n, rdata, ttl, ts, loc] = opts.tinyline.substring(1).split(':') if (n != 256) throw new Error('URI fromTinydns, invalid n') return new URI({ - type : 'URI', - owner : this.fullyQualify(fqdn), - priority : TINYDNS.octalToUInt16(rdata.substring(0, 8)), - weight : TINYDNS.octalToUInt16(rdata.substring(8, 16)), - target : TINYDNS.octalToChar(rdata.substring(16)), - ttl : parseInt(ttl, 10), + type: 'URI', + owner: this.fullyQualify(fqdn), + priority: TINYDNS.octalToUInt16(rdata.substring(0, 8)), + weight: TINYDNS.octalToUInt16(rdata.substring(8, 16)), + target: TINYDNS.octalToChar(rdata.substring(16)), + ttl: parseInt(ttl, 10), timestamp: ts, - location : loc !== '' && loc !== '\n' ? loc : '', + location: loc !== '' && loc !== '\n' ? loc : '', }) } - fromBind (opts) { + fromBind(opts) { // test.example.com 3600 IN URI priority, weight, target - const [ owner, ttl, c, type, priority, weight, target ] = opts.bindline.split(/\s+/) + const [owner, ttl, c, type, priority, weight, target] = + opts.bindline.split(/\s+/) return new URI({ - class : c, - type : type, + class: c, + type: type, owner, priority: parseInt(priority, 10), - weight : parseInt(weight, 10), - target : target.replace(/^"|"$/g, ''), - ttl : parseInt(ttl, 10), + weight: parseInt(weight, 10), + target: target.replace(/^"|"$/g, ''), + ttl: parseInt(ttl, 10), }) } /****** MISC *******/ - getDescription () { + getDescription() { return 'URI' } - getRdataFields (arg) { - return [ 'priority', 'weight', 'target' ] + getRdataFields(arg) { + return ['priority', 'weight', 'target'] } - getRFCs () { - return [ 7553 ] + getRFCs() { + return [7553] } - getTypeId () { + getTypeId() { return 256 } - getQuotedFields () { - return [ 'target' ] + getQuotedFields() { + return ['target'] } /****** EXPORTERS *******/ - toTinydns () { + toTinydns() { const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g') let rdata = '' - for (const e of [ 'priority', 'weight' ]) { + for (const e of ['priority', 'weight']) { rdata += TINYDNS.UInt16toOctal(this.get(e)) } diff --git a/rr/wks.js b/rr/wks.js new file mode 100644 index 0000000..b09b0eb --- /dev/null +++ b/rr/wks.js @@ -0,0 +1,44 @@ +import RR from '../rr.js' + +export default class WKS extends RR { + constructor(opts) { + super(opts) + if (opts === null) return + } + + /****** Resource record specific setters *******/ + + getDescription() { + return 'Well Known Service' + } + + getRdataFields(arg) { + return ['bit map'] + } + + getRFCs() { + return [883, 1035] + } + + getTypeId() { + return 11 + } + + /****** IMPORTERS *******/ + + fromBind(opts) { + // test.example.com 3600 IN WKS 192.168.1.1 TCP 25 + const [owner, ttl, c, type, address, protocol, bitmap] = opts.bindline.split(/\s+/) + return new WKS({ + owner, + ttl: parseInt(ttl, 10), + class: c, + type, + address, // 32-bit int + protocol, // 8-bit int, 6=TCP, 17=UDP + bitmap, // var len bit map, must be multiple of 8 + }) + } + + /****** EXPORTERS *******/ +} diff --git a/test/a.js b/test/a.js index 17fd666..25e9605 100644 --- a/test/a.js +++ b/test/a.js @@ -1,5 +1,4 @@ - -import A from '../rr/a.js' +import A from '../rr/a.js' import * as base from './base.js' const defaults = { class: 'IN', ttl: 3600, type: 'A', address: '192.0.2.127' } @@ -14,14 +13,14 @@ const validRecords = [ { ...defaults, owner: 'test.example.com.', - ttl : 2147483647, + ttl: 2147483647, testB: 'test.example.com.\t2147483647\tIN\tA\t192.0.2.127\n', testT: '+test.example.com:192.0.2.127:2147483647::\n', }, { ...defaults, owner: 'a.', - ttl : 86400, + ttl: 86400, testB: 'a.\t86400\tIN\tA\t192.0.2.127\n', testT: '+a:192.0.2.127:86400::\n', }, @@ -64,8 +63,8 @@ describe('A record', function () { base.getDescription(A) base.getRFCs(A, validRecords[0]) - base.getRdataFields(A, [ 'address' ]) - base.getFields(A, [ 'address' ]) + base.getRdataFields(A, ['address']) + base.getFields(A, ['address']) base.getTypeId(A, 1) base.toBind(A, validRecords) diff --git a/test/aaaa.js b/test/aaaa.js index a5ae37f..7f5bc67 100644 --- a/test/aaaa.js +++ b/test/aaaa.js @@ -1,4 +1,3 @@ - import assert from 'assert' import * as base from './base.js' @@ -9,19 +8,20 @@ const defaults = { class: 'IN', ttl: 3600, type: 'AAAA' } const validRecords = [ { ...defaults, - owner : 'test.example.com.', + owner: 'test.example.com.', address: '2001:0db8:0020:000a:0000:0000:0000:0004', - testB : 'test.example.com.\t3600\tIN\tAAAA\t2001:db8:20:a::4\n', - testT : ':test.example.com:28:\\040\\001\\015\\270\\000\\040\\000\\012\\000\\000\\000\\000\\000\\000\\000\\004:3600::\n', + testB: 'test.example.com.\t3600\tIN\tAAAA\t2001:db8:20:a::4\n', + testT: + ':test.example.com:28:\\040\\001\\015\\270\\000\\040\\000\\012\\000\\000\\000\\000\\000\\000\\000\\004:3600::\n', }, ] const invalidRecords = [ { ...defaults, - owner : 'test.example.com.', + owner: 'test.example.com.', address: '192.0.2.204', - msg : /address must be IPv6/, + msg: /address must be IPv6/, }, ] @@ -31,7 +31,7 @@ describe('AAAA record', function () { base.getDescription(AAAA) base.getRFCs(AAAA, validRecords[0]) - base.getFields(AAAA, [ 'address' ]) + base.getFields(AAAA, ['address']) base.getTypeId(AAAA, 28) base.toBind(AAAA, validRecords) @@ -44,8 +44,12 @@ describe('AAAA record', function () { it(`imports tinydns AAAA (generic) record (${val.owner})`, async function () { const r = new AAAA({ tinyline: val.testT }) if (process.env.DEBUG) console.dir(r) - for (const f of [ 'owner', 'address', 'ttl' ]) { - assert.deepStrictEqual(r.get(f), val[f], `${f}: ${r.get(f)} !== ${val[f]}`) + for (const f of ['owner', 'address', 'ttl']) { + assert.deepStrictEqual( + r.get(f), + val[f], + `${f}: ${r.get(f)} !== ${val[f]}`, + ) } }) } @@ -56,7 +60,10 @@ describe('AAAA record', function () { { e: '0000:0000:0000:0000:0000:0000:0000:0001', c: '::1' }, { e: '2001:0db8:0000:0000:0000:0000:0002:0001', c: '2001:db8::2:1' }, { e: '2001:0db8:0000:0001:0001:0001:0001:0001', c: '2001:db8:0:1:1:1:1:1' }, - { e: '2001:0DB8:0000:0000:0008:0800:200C:417A', c: '2001:DB8::8:800:200C:417A' }, + { + e: '2001:0DB8:0000:0000:0008:0800:200C:417A', + c: '2001:DB8::8:800:200C:417A', + }, ] describe('compress', function () { @@ -76,4 +83,4 @@ describe('AAAA record', function () { }) } }) -}) \ No newline at end of file +}) diff --git a/test/base.js b/test/base.js index 2d171c4..052c56e 100644 --- a/test/base.js +++ b/test/base.js @@ -1,7 +1,6 @@ - import assert from 'assert' -export function valid (type, validRecords, defaults) { +export function valid(type, validRecords, defaults) { describe('valid', function () { for (const val of validRecords) { // console.log(val) @@ -13,30 +12,36 @@ export function valid (type, validRecords, defaults) { for (const k of Object.keys(val)) { if (/^test/.test(k)) continue - assert.strictEqual(r.get(k), val[k], `${type.name} ${k} ${r.get(k)} !== ${val[k]}`) + assert.strictEqual( + r.get(k), + val[k], + `${type.name} ${k} ${r.get(k)} !== ${val[k]}`, + ) } }) } }) } -export function invalid (type, invalidRecords, defaults) { +export function invalid(type, invalidRecords, defaults) { describe('invalid', function () { for (const inv of invalidRecords) { if (defaults) inv.default = defaults it(`throws on record (${inv.owner})`, async function () { - assert.throws(() => { - new type(inv) - }, - { - message: inv.msg, - }) + assert.throws( + () => { + new type(inv) + }, + { + message: inv.msg, + }, + ) }) } }) } -export function toBind (type, validRecords) { +export function toBind(type, validRecords) { describe('toBind', function () { for (const val of validRecords) { it(`exports to BIND: ${val.owner}`, async function () { @@ -48,7 +53,7 @@ export function toBind (type, validRecords) { }) } -export function toTinydns (type, validRecords) { +export function toTinydns(type, validRecords) { describe('toTinydns', function () { for (const val of validRecords) { if (val.testT === undefined) continue @@ -61,7 +66,7 @@ export function toTinydns (type, validRecords) { }) } -export function getDescription (type) { +export function getDescription(type) { describe('getDescription', function () { const desc = new type(null).getDescription() it(`gets description: ${desc}`, async function () { @@ -70,7 +75,7 @@ export function getDescription (type) { }) } -export function getRFCs (type, valid) { +export function getRFCs(type, valid) { describe('getRFCs', function () { const r = new type(null) const rfcs = r.getRFCs() @@ -80,7 +85,7 @@ export function getRFCs (type, valid) { }) } -function checkFromNS (type, validRecords, nsName, nsLineName) { +function checkFromNS(type, validRecords, nsName, nsLineName) { for (const val of validRecords) { const testLine = nsLineName === 'bindline' ? val.testB : val.testT if (testLine == undefined) continue @@ -90,26 +95,31 @@ function checkFromNS (type, validRecords, nsName, nsLineName) { for (const f of r.getFields()) { if (f === 'class') continue let expected = val[f] - if (f === 'data' && Array.isArray(expected)) expected = expected.join('') // TXT - assert.deepStrictEqual(r.get(f), expected, `${f}: ${r.get(f)} !== ${expected}`) + if (f === 'data' && Array.isArray(expected)) + expected = expected.join('') // TXT + assert.deepStrictEqual( + r.get(f), + expected, + `${f}: ${r.get(f)} !== ${expected}`, + ) } }) } } -export function fromTinydns (type, validRecords) { +export function fromTinydns(type, validRecords) { describe('fromTinydns', function () { checkFromNS(type, validRecords, 'tinydns', 'tinyline') }) } -export function fromBind (type, validRecords) { +export function fromBind(type, validRecords) { describe('fromBind', function () { checkFromNS(type, validRecords, 'BIND', 'bindline') }) } -export function getRdataFields (type, rdataFields) { +export function getRdataFields(type, rdataFields) { describe('getRdataFields', function () { const r = new type(null) it(`can retrieve rdata fields: (${r.getRdataFields('rdata')})`, async function () { @@ -118,7 +128,7 @@ export function getRdataFields (type, rdataFields) { }) } -export function getFields (type, rdataFields) { +export function getFields(type, rdataFields) { describe('getFields', function () { const r = new type(null) it(`can retrieve record fields`, async function () { @@ -128,11 +138,11 @@ export function getFields (type, rdataFields) { }) } -export function getTypeId (type, val) { +export function getTypeId(type, val) { describe('getTypeId', function () { const r = new type(null) it(`can retrieve record type ID (${r.getTypeId()})`, async function () { assert.deepEqual(r.getTypeId(), val) }) }) -} \ No newline at end of file +} diff --git a/test/caa.js b/test/caa.js index 433013d..8abf28b 100644 --- a/test/caa.js +++ b/test/caa.js @@ -1,4 +1,3 @@ - import assert from 'assert' import * as base from './base.js' @@ -8,42 +7,46 @@ import CAA from '../rr/caa.js' const validRecords = [ { owner: 'ns1.example.com.', - ttl : 3600, + ttl: 3600, class: 'IN', - type : 'CAA', + type: 'CAA', flags: 0, - tag : 'issue', + tag: 'issue', value: 'http://letsencrypt.org', testB: `ns1.example.com.\t3600\tIN\tCAA\t0\tissue\t"http://letsencrypt.org"\n`, - testT: ':ns1.example.com:257:\\000\\005issue"http\\072\\057\\057letsencrypt.org":3600::\n', + testT: + ':ns1.example.com:257:\\000\\005issue"http\\072\\057\\057letsencrypt.org":3600::\n', }, { owner: 'ns2.example.com.', - ttl : 3600, + ttl: 3600, class: 'IN', - type : 'CAA', + type: 'CAA', flags: 0, - tag : 'issue', + tag: 'issue', value: 'mailto:lets-crypt.org', testB: `ns2.example.com.\t3600\tIN\tCAA\t0\tissue\t"mailto:lets-crypt.org"\n`, - testT: ':ns2.example.com:257:\\000\\005issue"mailto\\072lets-crypt.org":3600::\n', + testT: + ':ns2.example.com:257:\\000\\005issue"mailto\\072lets-crypt.org":3600::\n', }, { owner: 'example.net.', - ttl : 86400, - type : 'CAA', + ttl: 86400, + type: 'CAA', flags: 0, - tag : 'issuewild', + tag: 'issuewild', value: 'https://letsencrypt.org', - testB: 'example.net.\t86400\tIN\tCAA\t0\tissuewild\t"https://letsencrypt.org"\n', - testT: ':example.net:257:\\000\\011issuewild"https\\072\\057\\057letsencrypt.org":86400::\n', + testB: + 'example.net.\t86400\tIN\tCAA\t0\tissuewild\t"https://letsencrypt.org"\n', + testT: + ':example.net:257:\\000\\011issuewild"https\\072\\057\\057letsencrypt.org":86400::\n', }, { owner: 'certs.example.com.', - ttl : 86400, - type : 'CAA', + ttl: 86400, + type: 'CAA', flags: 0, - tag : 'issue', + tag: 'issue', value: 'ca1.example.net', testB: 'certs.example.com.\t86400\tIN\tCAA\t0\tissue\t"ca1.example.net"\n', testT: ':certs.example.com:257:\\000\\005issue"ca1.example.net":86400::\n', @@ -53,27 +56,27 @@ const validRecords = [ const invalidRecords = [ { owner: 'example.com.', - type : 'CAA', + type: 'CAA', flags: 128, - tag : 'iodef', + tag: 'iodef', value: 'letsencrypt.org', // missing iodef prefix - msg : /RFC/, + msg: /RFC/, }, { owner: 'example.com.', - type : 'CAA', + type: 'CAA', flags: 128, - tag : 'invalid', // invalid + tag: 'invalid', // invalid value: 'http://letsencrypt.org', - msg : /RFC/, + msg: /RFC/, }, { owner: 'example.com.', - type : 'CAA', - flags: 15, // invalid - tag : 'issue', + type: 'CAA', + flags: 15, // invalid + tag: 'issue', value: 'http://letsencrypt.org', - msg : /RFC/, + msg: /RFC/, }, ] @@ -83,7 +86,7 @@ describe('CAA record', function () { base.getDescription(CAA) base.getRFCs(CAA, validRecords[0]) - base.getFields(CAA, [ 'flags', 'tag', 'value' ]) + base.getFields(CAA, ['flags', 'tag', 'value']) base.getTypeId(CAA, 257) base.toBind(CAA, validRecords) @@ -96,8 +99,12 @@ describe('CAA record', function () { it(`imports tinydns CAA (generic) record`, async function () { const r = new CAA({ tinyline: val.testT }) if (process.env.DEBUG) console.dir(r) - for (const f of [ 'owner', 'flags', 'tag', 'value', 'ttl' ]) { - assert.deepStrictEqual(r.get(f), val[f], `${f}: ${r.get(f)} !== ${val[f]}`) + for (const f of ['owner', 'flags', 'tag', 'value', 'ttl']) { + assert.deepStrictEqual( + r.get(f), + val[f], + `${f}: ${r.get(f)} !== ${val[f]}`, + ) } }) } diff --git a/test/cert.js b/test/cert.js index f7cae58..802258e 100644 --- a/test/cert.js +++ b/test/cert.js @@ -1,35 +1,35 @@ - import * as base from './base.js' import CERT from '../rr/cert.js' const validRecords = [ { - owner : 'mail.example.com.', - ttl : 86400, - class : 'IN', - type : 'CERT', - 'cert type' : 'PGP', - 'key tag' : 0, - 'algorithm' : 0, - 'certificate': 'hexidecimalkeystring1', - testB : 'mail.example.com.\t86400\tIN\tCERT\tPGP\t0\t0\thexidecimalkeystring1\n', + owner: 'mail.example.com.', + ttl: 86400, + class: 'IN', + type: 'CERT', + 'cert type': 'PGP', + 'key tag': 0, + algorithm: 0, + certificate: 'hexidecimalkeystring1', + testB: + 'mail.example.com.\t86400\tIN\tCERT\tPGP\t0\t0\thexidecimalkeystring1\n', }, { - owner : 'smith.example.com.', - ttl : 86400, - class : 'IN', - type : 'CERT', - 'cert type' : 'PGP', - 'key tag' : 0, - 'algorithm' : 0, - 'certificate': 'hexidecimalkeystring2', - testB : 'smith.example.com.\t86400\tIN\tCERT\tPGP\t0\t0\thexidecimalkeystring2\n', + owner: 'smith.example.com.', + ttl: 86400, + class: 'IN', + type: 'CERT', + 'cert type': 'PGP', + 'key tag': 0, + algorithm: 0, + certificate: 'hexidecimalkeystring2', + testB: + 'smith.example.com.\t86400\tIN\tCERT\tPGP\t0\t0\thexidecimalkeystring2\n', }, ] -const invalidRecords = [ -] +const invalidRecords = [] describe('CERT record', function () { base.valid(CERT, validRecords) @@ -37,7 +37,7 @@ describe('CERT record', function () { base.getDescription(CERT) base.getRFCs(CERT, validRecords[0]) - base.getFields(CERT, [ 'cert type', 'key tag', 'algorithm', 'certificate' ]) + base.getFields(CERT, ['cert type', 'key tag', 'algorithm', 'certificate']) base.getTypeId(CERT, 37) base.toBind(CERT, validRecords) diff --git a/test/cname.js b/test/cname.js index aba99e3..ca24523 100644 --- a/test/cname.js +++ b/test/cname.js @@ -1,4 +1,3 @@ - import * as base from './base.js' import CNAME from '../rr/cname.js' @@ -19,8 +18,8 @@ const invalidRecords = [ { ...defaults, owner: 'example.com.', - cname: '192.0.2.4', // FQDN required - msg : /cname must be a FQDN/, + cname: '192.0.2.4', // FQDN required + msg: /cname must be a FQDN/, }, ] @@ -30,7 +29,7 @@ describe('CNAME record', function () { base.getDescription(CNAME) base.getRFCs(CNAME, validRecords[0]) - base.getFields(CNAME, [ 'cname' ]) + base.getFields(CNAME, ['cname']) base.getTypeId(CNAME, 5) base.toBind(CNAME, validRecords) diff --git a/test/dname.js b/test/dname.js index 7586b06..c2bf900 100644 --- a/test/dname.js +++ b/test/dname.js @@ -1,4 +1,3 @@ - import assert from 'assert' import * as base from './base.js' @@ -10,19 +9,20 @@ const defaults = { class: 'IN', ttl: 86400, type: 'DNAME' } const validRecords = [ { ...defaults, - owner : '_tcp.example.com.', + owner: '_tcp.example.com.', target: '_tcp.example.net.', - testB : '_tcp.example.com.\t86400\tIN\tDNAME\t_tcp.example.net.\n', - testT : ':_tcp.example.com:39:\\004\\137tcp\\007example\\003net\\000:86400::\n', + testB: '_tcp.example.com.\t86400\tIN\tDNAME\t_tcp.example.net.\n', + testT: + ':_tcp.example.com:39:\\004\\137tcp\\007example\\003net\\000:86400::\n', }, ] const invalidRecords = [ { ...defaults, - owner : 'spf.example.com.', - target: '1.2.3.4', // FQDN required - msg : /target must be a domain name/, + owner: 'spf.example.com.', + target: '1.2.3.4', // FQDN required + msg: /target must be a domain name/, }, ] @@ -32,7 +32,7 @@ describe('DNAME record', function () { base.getDescription(DNAME) base.getRFCs(DNAME, validRecords[0]) - base.getFields(DNAME, [ 'target' ]) + base.getFields(DNAME, ['target']) base.getTypeId(DNAME, 39) base.toBind(DNAME, validRecords) @@ -45,8 +45,12 @@ describe('DNAME record', function () { it.skip(`imports tinydns DNAME (generic) record (${val.owner})`, async function () { const r = new DNAME({ tinyline: val.testT }) if (process.env.DEBUG) console.dir(r) - for (const f of [ 'owner', 'target', 'ttl' ]) { - assert.deepStrictEqual(r.get(f), val[f], `${f}: ${r.get(f)} !== ${val[f]}`) + for (const f of ['owner', 'target', 'ttl']) { + assert.deepStrictEqual( + r.get(f), + val[f], + `${f}: ${r.get(f)} !== ${val[f]}`, + ) } }) } diff --git a/test/dnskey.js b/test/dnskey.js index d1dc28e..2348ab4 100644 --- a/test/dnskey.js +++ b/test/dnskey.js @@ -1,4 +1,3 @@ - import * as base from './base.js' import DNSKEY from '../rr/dnskey.js' @@ -8,22 +7,24 @@ const defaults = { class: 'IN', ttl: 3600, type: 'DNSKEY' } const validRecords = [ { ...defaults, - owner : 'example.com.', - flags : 256, - protocol : 3, + owner: 'example.com.', + flags: 256, + protocol: 3, algorithm: 5, publickey: `( AQPSKmynfzW4kyBv015MUG2DeIQ3 Cbl+BBZH4b/0PY1kxkmvHjcZc8no kfzj31GajIQKY+5CptLr3buXA10h WqTkF7H6RfoRqXQeogmMHfpftf6z Mv1LyBUgia7za6ZEzOJBOztyvhjL 742iU/TpPSEDhm2SNKLijfUppn1U aNvv4w== )`, - testB : 'example.com.\t3600\tIN\tDNSKEY\t256\t3\t5\t( AQPSKmynfzW4kyBv015MUG2DeIQ3 Cbl+BBZH4b/0PY1kxkmvHjcZc8no kfzj31GajIQKY+5CptLr3buXA10h WqTkF7H6RfoRqXQeogmMHfpftf6z Mv1LyBUgia7za6ZEzOJBOztyvhjL 742iU/TpPSEDhm2SNKLijfUppn1U aNvv4w== )\n', - testT : ':example.com:48:\\001\\000\\003\\005( AQPSKmynfzW4kyBv015MUG2DeIQ3 Cbl+BBZH4b\\0570PY1kxkmvHjcZc8no kfzj31GajIQKY+5CptLr3buXA10h WqTkF7H6RfoRqXQeogmMHfpftf6z Mv1LyBUgia7za6ZEzOJBOztyvhjL 742iU\\057TpPSEDhm2SNKLijfUppn1U aNvv4w== ):3600::\n', + testB: + 'example.com.\t3600\tIN\tDNSKEY\t256\t3\t5\t( AQPSKmynfzW4kyBv015MUG2DeIQ3 Cbl+BBZH4b/0PY1kxkmvHjcZc8no kfzj31GajIQKY+5CptLr3buXA10h WqTkF7H6RfoRqXQeogmMHfpftf6z Mv1LyBUgia7za6ZEzOJBOztyvhjL 742iU/TpPSEDhm2SNKLijfUppn1U aNvv4w== )\n', + testT: + ':example.com:48:\\001\\000\\003\\005( AQPSKmynfzW4kyBv015MUG2DeIQ3 Cbl+BBZH4b\\0570PY1kxkmvHjcZc8no kfzj31GajIQKY+5CptLr3buXA10h WqTkF7H6RfoRqXQeogmMHfpftf6z Mv1LyBUgia7za6ZEzOJBOztyvhjL 742iU\\057TpPSEDhm2SNKLijfUppn1U aNvv4w== ):3600::\n', }, ] const invalidRecords = [ { ...defaults, - owner : 'test.example.com.', - algorithm: 257, // invalid - msg : /flags must be a 16-bit integer/, + owner: 'test.example.com.', + algorithm: 257, // invalid + msg: /flags must be a 16-bit integer/, }, ] @@ -33,7 +34,7 @@ describe('DNSKEY record', function () { base.getDescription(DNSKEY) base.getRFCs(DNSKEY, validRecords[0]) - base.getFields(DNSKEY, [ 'flags', 'protocol', 'algorithm', 'publickey' ]) + base.getFields(DNSKEY, ['flags', 'protocol', 'algorithm', 'publickey']) base.getTypeId(DNSKEY, 48) base.toBind(DNSKEY, validRecords) diff --git a/test/ds.js b/test/ds.js index 0f175d0..f66b9b4 100644 --- a/test/ds.js +++ b/test/ds.js @@ -1,4 +1,3 @@ - import * as base from './base.js' import DS from '../rr/ds.js' @@ -8,22 +7,24 @@ const defaults = { class: 'IN', ttl: 3600, type: 'DS' } const validRecords = [ { ...defaults, - owner : 'dskey.example.com.', - 'key tag' : 60485, - algorithm : 5, + owner: 'dskey.example.com.', + 'key tag': 60485, + algorithm: 5, 'digest type': 1, - digest : `( 2BB183AF5F22588179A53B0A 98631FAD1A292118 )`, - testB : 'dskey.example.com.\t3600\tIN\tDS\t60485\t5\t1\t( 2BB183AF5F22588179A53B0A 98631FAD1A292118 )\n', - testT : ':dskey.example.com:43:\\354\\105\\005\\001( 2BB183AF5F22588179A53B0A 98631FAD1A292118 ):3600::\n', + digest: `( 2BB183AF5F22588179A53B0A 98631FAD1A292118 )`, + testB: + 'dskey.example.com.\t3600\tIN\tDS\t60485\t5\t1\t( 2BB183AF5F22588179A53B0A 98631FAD1A292118 )\n', + testT: + ':dskey.example.com:43:\\354\\105\\005\\001( 2BB183AF5F22588179A53B0A 98631FAD1A292118 ):3600::\n', }, ] const invalidRecords = [ { ...defaults, - owner : 'test.example.com.', - algorithm: 6, // invalid - msg : /key tag is required/, + owner: 'test.example.com.', + algorithm: 6, // invalid + msg: /key tag is required/, }, ] @@ -33,7 +34,7 @@ describe('DS record', function () { base.getDescription(DS) base.getRFCs(DS, validRecords[0]) - base.getFields(DS, [ 'key tag', 'algorithm', 'digest type', 'digest' ]) + base.getFields(DS, ['key tag', 'algorithm', 'digest type', 'digest']) base.getTypeId(DS, 43) base.toBind(DS, validRecords) diff --git a/test/fake.js b/test/fake.js index f7dfe39..491b697 100644 --- a/test/fake.js +++ b/test/fake.js @@ -1,26 +1,34 @@ - import assert from 'assert' import * as RR from '../index.js' -const defaults = { owner: 'fake.com.', class: 'IN', ttl: 3600, address: '192.0.2.127' } +const defaults = { + owner: 'fake.com.', + class: 'IN', + ttl: 3600, + address: '192.0.2.127', +} describe('fake', function () { it(`throws on invalid RR class`, async function () { - assert.throws(() => { - new RR.fake({ ...defaults, type: 'A' }) - }, - { - message: /fake is not a constructor/, - }) + assert.throws( + () => { + new RR.fake({ ...defaults, type: 'A' }) + }, + { + message: /fake is not a constructor/, + }, + ) }) it(`throws on invalid RR type`, async function () { - assert.throws(() => { - new RR.A({ ...defaults, type: 'NONEXIST' }) - }, - { - message: /type NONEXIST doesn't match A/, - }) + assert.throws( + () => { + new RR.A({ ...defaults, type: 'NONEXIST' }) + }, + { + message: /type NONEXIST doesn't match A/, + }, + ) }) -}) \ No newline at end of file +}) diff --git a/test/hinfo.js b/test/hinfo.js index 1a81651..28bd989 100644 --- a/test/hinfo.js +++ b/test/hinfo.js @@ -1,4 +1,3 @@ - import assert from 'assert' import * as base from './base.js' @@ -11,16 +10,18 @@ const validRecords = [ { ...defaults, owner: 'server-under-my-desk.example.com.', - cpu : 'PDP-11/73', - os : 'UNIX', - testB: 'server-under-my-desk.example.com.\t86400\tIN\tHINFO\t"PDP-11/73"\t"UNIX"\n', - testT: ':server-under-my-desk.example.com:13:\\011PDP-11/73\\004UNIX:86400::\n', + cpu: 'PDP-11/73', + os: 'UNIX', + testB: + 'server-under-my-desk.example.com.\t86400\tIN\tHINFO\t"PDP-11/73"\t"UNIX"\n', + testT: + ':server-under-my-desk.example.com:13:\\011PDP-11/73\\004UNIX:86400::\n', }, { ...defaults, owner: 'sri-nic.arpa.', - cpu : 'DEC-2060', - os : 'TOPS20', + cpu: 'DEC-2060', + os: 'TOPS20', testB: 'sri-nic.arpa.\t86400\tIN\tHINFO\t"DEC-2060"\t"TOPS20"\n', testT: ':sri-nic.arpa:13:\\010DEC-2060\\006TOPS20:86400::\n', }, @@ -29,9 +30,9 @@ const validRecords = [ const invalidRecords = [ { ...defaults, - owner : 'www.example.com.', + owner: 'www.example.com.', address: '', - msg : /Cannot read proper/, + msg: /Cannot read proper/, }, ] @@ -41,7 +42,7 @@ describe('HINFO record', function () { base.getDescription(HINFO) base.getRFCs(HINFO, validRecords[0]) - base.getFields(HINFO, [ 'cpu', 'os' ]) + base.getFields(HINFO, ['cpu', 'os']) base.getTypeId(HINFO, 13) base.toBind(HINFO, validRecords) @@ -54,20 +55,24 @@ describe('HINFO record', function () { it.skip(`imports tinydns HINFO (generic) record (${val.owner})`, async function () { const r = new HINFO({ tinyline: val.testT }) if (process.env.DEBUG) console.dir(r) - for (const f of [ 'owner', 'address', 'ttl' ]) { - assert.deepStrictEqual(r.get(f), val[f], `${f}: ${r.get(f)} !== ${val[f]}`) + for (const f of ['owner', 'address', 'ttl']) { + assert.deepStrictEqual( + r.get(f), + val[f], + `${f}: ${r.get(f)} !== ${val[f]}`, + ) } }) } - for (const f of [ 'os', 'cpu' ]) { + for (const f of ['os', 'cpu']) { it(`rejects ${f} value longer than 255 chars`, async () => { - const tooLong = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz' + const tooLong = + 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz' const r = new HINFO(null) try { assert.fail(r[`set${r.ucfirst(f)}`](tooLong)) - } - catch (e) { + } catch (e) { assert.equal(e.message, `HINFO ${f} cannot exceed 255 chars`) } }) diff --git a/test/ipseckey.js b/test/ipseckey.js index 4f1e449..5b371db 100644 --- a/test/ipseckey.js +++ b/test/ipseckey.js @@ -1,4 +1,3 @@ - import * as base from './base.js' import IPSECKEY from '../rr/ipseckey.js' @@ -8,92 +7,107 @@ const common = { ttl: 7200, class: 'IN', type: 'IPSECKEY' } const validRecords = [ { ...common, - owner : '38.2.0.192.in-addr.arpa.', - precedence : 10, + owner: '38.2.0.192.in-addr.arpa.', + precedence: 10, 'gateway type': 1, - algorithm : 2, - gateway : '192.0.2.38', - publickey : 'AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==', - testB : '38.2.0.192.in-addr.arpa.\t7200\tIN\tIPSECKEY\t10\t1\t2\t192.0.2.38\tAQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==\n', - testT : ':38.2.0.192.in-addr.arpa:45:\\012\\001\\002\\300\\000\\002\\046\\001\\003QSy\\206\\3555S\\073\\140dG\\216\\356\\262\\173\\133\\327M\\256\\024\\233n\\201\\272\\072\\005\\041\\257\\202\\253x\\001:7200::\n', + algorithm: 2, + gateway: '192.0.2.38', + publickey: 'AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==', + testB: + '38.2.0.192.in-addr.arpa.\t7200\tIN\tIPSECKEY\t10\t1\t2\t192.0.2.38\tAQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==\n', + testT: + ':38.2.0.192.in-addr.arpa:45:\\012\\001\\002\\300\\000\\002\\046\\001\\003QSy\\206\\3555S\\073\\140dG\\216\\356\\262\\173\\133\\327M\\256\\024\\233n\\201\\272\\072\\005\\041\\257\\202\\253x\\001:7200::\n', }, { ...common, - owner : '38.2.0.192.in-addr.arpa.', - precedence : 10, + owner: '38.2.0.192.in-addr.arpa.', + precedence: 10, 'gateway type': 0, - algorithm : 2, - gateway : '.', - publickey : 'AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==', - testB : '38.2.0.192.in-addr.arpa.\t7200\tIN\tIPSECKEY\t10\t0\t2\t.\tAQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==\n', - testT : ':38.2.0.192.in-addr.arpa:45:\\012\\000\\002.\\001\\003QSy\\206\\3555S\\073\\140dG\\216\\356\\262\\173\\133\\327M\\256\\024\\233n\\201\\272\\072\\005\\041\\257\\202\\253x\\001:7200::\n', + algorithm: 2, + gateway: '.', + publickey: 'AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==', + testB: + '38.2.0.192.in-addr.arpa.\t7200\tIN\tIPSECKEY\t10\t0\t2\t.\tAQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==\n', + testT: + ':38.2.0.192.in-addr.arpa:45:\\012\\000\\002.\\001\\003QSy\\206\\3555S\\073\\140dG\\216\\356\\262\\173\\133\\327M\\256\\024\\233n\\201\\272\\072\\005\\041\\257\\202\\253x\\001:7200::\n', }, { ...common, - owner : '38.2.0.192.in-addr.arpa.', - precedence : 10, + owner: '38.2.0.192.in-addr.arpa.', + precedence: 10, 'gateway type': 1, - algorithm : 2, - gateway : '192.0.2.38', - publickey : 'AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==', - testB : '38.2.0.192.in-addr.arpa.\t7200\tIN\tIPSECKEY\t10\t1\t2\t192.0.2.38\tAQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==\n', - testT : ':38.2.0.192.in-addr.arpa:45:\\012\\001\\002\\300\\000\\002\\046\\001\\003QSy\\206\\3555S\\073\\140dG\\216\\356\\262\\173\\133\\327M\\256\\024\\233n\\201\\272\\072\\005\\041\\257\\202\\253x\\001:7200::\n', + algorithm: 2, + gateway: '192.0.2.38', + publickey: 'AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==', + testB: + '38.2.0.192.in-addr.arpa.\t7200\tIN\tIPSECKEY\t10\t1\t2\t192.0.2.38\tAQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==\n', + testT: + ':38.2.0.192.in-addr.arpa:45:\\012\\001\\002\\300\\000\\002\\046\\001\\003QSy\\206\\3555S\\073\\140dG\\216\\356\\262\\173\\133\\327M\\256\\024\\233n\\201\\272\\072\\005\\041\\257\\202\\253x\\001:7200::\n', }, { ...common, - owner : '38.1.0.192.in-addr.arpa.', - precedence : 10, + owner: '38.1.0.192.in-addr.arpa.', + precedence: 10, 'gateway type': 3, - algorithm : 2, - gateway : 'mygateway.example.com.', - publickey : 'AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==', - testB : '38.1.0.192.in-addr.arpa.\t7200\tIN\tIPSECKEY\t10\t3\t2\tmygateway.example.com.\tAQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==\n', - testT : ':38.1.0.192.in-addr.arpa:45:\\012\\003\\002\\011mygateway\\007example\\003com\\000\\001\\003QSy\\206\\3555S\\073\\140dG\\216\\356\\262\\173\\133\\327M\\256\\024\\233n\\201\\272\\072\\005\\041\\257\\202\\253x\\001:7200::\n', + algorithm: 2, + gateway: 'mygateway.example.com.', + publickey: 'AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==', + testB: + '38.1.0.192.in-addr.arpa.\t7200\tIN\tIPSECKEY\t10\t3\t2\tmygateway.example.com.\tAQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==\n', + testT: + ':38.1.0.192.in-addr.arpa:45:\\012\\003\\002\\011mygateway\\007example\\003com\\000\\001\\003QSy\\206\\3555S\\073\\140dG\\216\\356\\262\\173\\133\\327M\\256\\024\\233n\\201\\272\\072\\005\\041\\257\\202\\253x\\001:7200::\n', }, { ...common, - owner : '0.d.4.0.3.0.e.f.f.f.3.f.0.1.2.0.1.0.0.0.0.0.2.8.b.d.0.1.0.0.2.ip6.arpa.', - precedence : 10, + owner: + '0.d.4.0.3.0.e.f.f.f.3.f.0.1.2.0.1.0.0.0.0.0.2.8.b.d.0.1.0.0.2.ip6.arpa.', + precedence: 10, 'gateway type': 2, - algorithm : 2, - gateway : '2001:0db8:0:8002::2000:1', - publickey : 'AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==', - testB : '0.d.4.0.3.0.e.f.f.f.3.f.0.1.2.0.1.0.0.0.0.0.2.8.b.d.0.1.0.0.2.ip6.arpa.\t7200\tIN\tIPSECKEY\t10\t2\t2\t2001:0db8:0:8002::2000:1\tAQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==\n', + algorithm: 2, + gateway: '2001:0db8:0:8002::2000:1', + publickey: 'AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==', + testB: + '0.d.4.0.3.0.e.f.f.f.3.f.0.1.2.0.1.0.0.0.0.0.2.8.b.d.0.1.0.0.2.ip6.arpa.\t7200\tIN\tIPSECKEY\t10\t2\t2\t2001:0db8:0:8002::2000:1\tAQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==\n', }, { ...common, - owner : 'ipsec.simerson.com.', - ttl : 86400, - precedence : 1, + owner: 'ipsec.simerson.com.', + ttl: 86400, + precedence: 1, 'gateway type': 3, - algorithm : 2, - gateway : 'matt.simerson.net.', - publickey : '0sAQPeOwAGDPLrDebL1q5Lg8XW9B/d9MnxqlzIYKXhvZPWEHNYGP7AwART/tmkeDNn7HPMtgM6GIwQ4p0KGLfSRoUKbjtPlRVeWYLbsnNXeFU5bchyYef0efYiKlxZdo', - testB : 'ipsec.simerson.com.\t86400\tIN\tIPSECKEY\t1\t3\t2\tmatt.simerson.net.\t0sAQPeOwAGDPLrDebL1q5Lg8XW9B/d9MnxqlzIYKXhvZPWEHNYGP7AwART/tmkeDNn7HPMtgM6GIwQ4p0KGLfSRoUKbjtPlRVeWYLbsnNXeFU5bchyYef0efYiKlxZdo\n', - testT : ':ipsec.simerson.com:45:\\001\\003\\002\\004matt\\010simerson\\003net\\000\\322\\300\\020\\075\\343\\260\\000\\140\\317.\\260\\336l\\275j\\344\\270\\074\\135oA\\375\\337L\\237\\032\\245\\314\\206\\012\\136\\033\\331\\075a\\0075\\201\\217\\354\\014\\000E\\077\\355\\232G\\2036\\176\\307\\074\\313\\1403\\241\\210\\301\\016\\051\\320\\241\\213\\175\\044hP\\246\\343\\264\\371QU\\345\\230-\\273\\0475w\\205S\\226\\334\\207\\046\\036\\177G\\237b\\042\\245\\305\\227h:86400::\n', + algorithm: 2, + gateway: 'matt.simerson.net.', + publickey: + '0sAQPeOwAGDPLrDebL1q5Lg8XW9B/d9MnxqlzIYKXhvZPWEHNYGP7AwART/tmkeDNn7HPMtgM6GIwQ4p0KGLfSRoUKbjtPlRVeWYLbsnNXeFU5bchyYef0efYiKlxZdo', + testB: + 'ipsec.simerson.com.\t86400\tIN\tIPSECKEY\t1\t3\t2\tmatt.simerson.net.\t0sAQPeOwAGDPLrDebL1q5Lg8XW9B/d9MnxqlzIYKXhvZPWEHNYGP7AwART/tmkeDNn7HPMtgM6GIwQ4p0KGLfSRoUKbjtPlRVeWYLbsnNXeFU5bchyYef0efYiKlxZdo\n', + testT: + ':ipsec.simerson.com:45:\\001\\003\\002\\004matt\\010simerson\\003net\\000\\322\\300\\020\\075\\343\\260\\000\\140\\317.\\260\\336l\\275j\\344\\270\\074\\135oA\\375\\337L\\237\\032\\245\\314\\206\\012\\136\\033\\331\\075a\\0075\\201\\217\\354\\014\\000E\\077\\355\\232G\\2036\\176\\307\\074\\313\\1403\\241\\210\\301\\016\\051\\320\\241\\213\\175\\044hP\\246\\343\\264\\371QU\\345\\230-\\273\\0475w\\205S\\226\\334\\207\\046\\036\\177G\\237b\\042\\245\\305\\227h:86400::\n', }, ] const invalidRecords = [ { ...common, - owner : '0.d.4.0.3.0.e.f.f.f.3.f.0.1.2.0.1.0.0.0.0.0.2.8.b.d.0.1.0.0.2.ip6.arpa.', - precedence : 10, + owner: + '0.d.4.0.3.0.e.f.f.f.3.f.0.1.2.0.1.0.0.0.0.0.2.8.b.d.0.1.0.0.2.ip6.arpa.', + precedence: 10, 'gateway type': 4, - algorithm : 2, - gateway : '2001:0db8:0:8002::2000:1', - publickey : 'AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==', - msg : /Gateway Type is invalid/, + algorithm: 2, + gateway: '2001:0db8:0:8002::2000:1', + publickey: 'AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==', + msg: /Gateway Type is invalid/, }, { ...common, - owner : '0.d.4.0.3.0.e.f.f.f.3.f.0.1.2.0.1.0.0.0.0.0.2.8.b.d.0.1.0.0.2.ip6.arpa.', - precedence : 10, + owner: + '0.d.4.0.3.0.e.f.f.f.3.f.0.1.2.0.1.0.0.0.0.0.2.8.b.d.0.1.0.0.2.ip6.arpa.', + precedence: 10, 'gateway type': 3, - algorithm : 3, - gateway : '2001:0db8:0:8002::2000:1', - publickey : 'AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==', - msg : /Algorithm invalid/, + algorithm: 3, + gateway: '2001:0db8:0:8002::2000:1', + publickey: 'AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==', + msg: /Algorithm invalid/, }, ] @@ -103,8 +117,20 @@ describe('IPSECKEY record', function () { base.getDescription(IPSECKEY) base.getRFCs(IPSECKEY, validRecords[0]) - base.getRdataFields(IPSECKEY, [ 'precedence', 'gateway type', 'algorithm', 'gateway', 'publickey' ]) - base.getFields(IPSECKEY, [ 'precedence', 'gateway type', 'algorithm', 'gateway', 'publickey' ]) + base.getRdataFields(IPSECKEY, [ + 'precedence', + 'gateway type', + 'algorithm', + 'gateway', + 'publickey', + ]) + base.getFields(IPSECKEY, [ + 'precedence', + 'gateway type', + 'algorithm', + 'gateway', + 'publickey', + ]) base.getTypeId(IPSECKEY, 45) base.toBind(IPSECKEY, validRecords) diff --git a/test/key.js b/test/key.js index 8e657f5..c690a97 100644 --- a/test/key.js +++ b/test/key.js @@ -1,24 +1,23 @@ - import * as base from './base.js' import KEY from '../rr/key.js' const validRecords = [ { - owner : 'example.com.', - ttl : 3600, - class : 'IN', - type : 'KEY', - flags : 256, - protocol : 3, + owner: 'example.com.', + ttl: 3600, + class: 'IN', + type: 'KEY', + flags: 256, + protocol: 3, algorithm: 5, publickey: `( AQPSKmynfzW4kyBv015MUG2DeIQ3 Cbl+BBZH4b/0PY1kxkmvHjcZc8no kfzj31GajIQKY+5CptLr3buXA10h WqTkF7H6RfoRqXQeogmMHfpftf6z Mv1LyBUgia7za6ZEzOJBOztyvhjL 742iU/TpPSEDhm2SNKLijfUppn1U aNvv4w== )`, - testB : 'example.com.\t3600\tIN\tKEY\t256\t3\t5\t( AQPSKmynfzW4kyBv015MUG2DeIQ3 Cbl+BBZH4b/0PY1kxkmvHjcZc8no kfzj31GajIQKY+5CptLr3buXA10h WqTkF7H6RfoRqXQeogmMHfpftf6z Mv1LyBUgia7za6ZEzOJBOztyvhjL 742iU/TpPSEDhm2SNKLijfUppn1U aNvv4w== )\n', + testB: + 'example.com.\t3600\tIN\tKEY\t256\t3\t5\t( AQPSKmynfzW4kyBv015MUG2DeIQ3 Cbl+BBZH4b/0PY1kxkmvHjcZc8no kfzj31GajIQKY+5CptLr3buXA10h WqTkF7H6RfoRqXQeogmMHfpftf6z Mv1LyBUgia7za6ZEzOJBOztyvhjL 742iU/TpPSEDhm2SNKLijfUppn1U aNvv4w== )\n', }, ] -const invalidRecords = [ -] +const invalidRecords = [] describe('KEY record', function () { base.valid(KEY, validRecords) @@ -26,7 +25,7 @@ describe('KEY record', function () { base.getDescription(KEY) base.getRFCs(KEY, validRecords[0]) - base.getFields(KEY, [ 'flags', 'protocol', 'algorithm', 'publickey' ]) + base.getFields(KEY, ['flags', 'protocol', 'algorithm', 'publickey']) base.getTypeId(KEY, 25) base.toBind(KEY, validRecords) diff --git a/test/loc.js b/test/loc.js index 2caa31e..87afbf0 100644 --- a/test/loc.js +++ b/test/loc.js @@ -1,4 +1,3 @@ - import assert from 'assert' import * as base from './base.js' @@ -10,33 +9,38 @@ const defaults = { class: 'IN', ttl: 3600, type: 'LOC' } const validRecords = [ { ...defaults, - owner : 'loc.home.example.com.', + owner: 'loc.home.example.com.', address: '47 43 47 N 122 21 35 W 132m 100m 100m 2m', - testB : `loc.home.example.com.\t3600\tIN\tLOC\t47 43 47 N 122 21 35 W 132m 100m 100m 2m\n`, - testT : ':loc.home.example.com:29:\\000\\024\\024\\042\\212\\075\\337\\070\\145\\276\\224\\150\\000\\230\\312\\020:3600::\n', + testB: `loc.home.example.com.\t3600\tIN\tLOC\t47 43 47 N 122 21 35 W 132m 100m 100m 2m\n`, + testT: + ':loc.home.example.com:29:\\000\\024\\024\\042\\212\\075\\337\\070\\145\\276\\224\\150\\000\\230\\312\\020:3600::\n', }, { ...defaults, - owner : 'cambridge-net.kei.com.', + owner: 'cambridge-net.kei.com.', address: '42 21 54 N 71 6 18 W -24m 30m', - testB : 'cambridge-net.kei.com.\t3600\tIN\tLOC\t42 21 54 N 71 6 18 W -24m 30m\n', - testT : ':cambridge-net.kei.com:29:\\000\\063\\000\\000\\211\\027\\055\\320\\160\\276\\025\\360\\000\\230\\215\\040:3600::\n', + testB: + 'cambridge-net.kei.com.\t3600\tIN\tLOC\t42 21 54 N 71 6 18 W -24m 30m\n', + testT: + ':cambridge-net.kei.com:29:\\000\\063\\000\\000\\211\\027\\055\\320\\160\\276\\025\\360\\000\\230\\215\\040:3600::\n', }, { ...defaults, - owner : 'rwy04l.logan-airport.boston.', + owner: 'rwy04l.logan-airport.boston.', address: '42 21 28.764 N 71 0 51.617 W -44m 2000m', - testB : 'rwy04l.logan-airport.boston.\t3600\tIN\tLOC\t42 21 28.764 N 71 0 51.617 W -44m 2000m\n', - testT : ':rwy04l.logan-airport.boston:29:\\000\\045\\000\\000\\211\\026\\313\\074\\160\\303\\020\\337\\000\\230\\205\\120:3600::\n', + testB: + 'rwy04l.logan-airport.boston.\t3600\tIN\tLOC\t42 21 28.764 N 71 0 51.617 W -44m 2000m\n', + testT: + ':rwy04l.logan-airport.boston:29:\\000\\045\\000\\000\\211\\026\\313\\074\\160\\303\\020\\337\\000\\230\\205\\120:3600::\n', }, ] const invalidRecords = [ { ...defaults, - owner : 'server.example.com.', + owner: 'server.example.com.', address: '', // empty - msg : /address is required/, + msg: /address is required/, }, ] @@ -46,7 +50,7 @@ describe('LOC record', function () { base.getDescription(LOC) base.getRFCs(LOC, validRecords[0]) - base.getFields(LOC, [ 'address' ]) + base.getFields(LOC, ['address']) base.getTypeId(LOC, 29) base.toBind(LOC, validRecords) diff --git a/test/mx.js b/test/mx.js index 7b45f55..8396c0f 100644 --- a/test/mx.js +++ b/test/mx.js @@ -1,4 +1,3 @@ - import assert from 'assert' import * as base from './base.js' @@ -10,41 +9,41 @@ const defaults = { class: 'IN', ttl: 3600, type: 'MX', preference: 0 } const validRecords = [ { ...defaults, - owner : 'test.example.com.', + owner: 'test.example.com.', preference: 0, - exchange : 'mail.example.com.', - testB : 'test.example.com.\t3600\tIN\tMX\t0\tmail.example.com.\n', - testT : '@test.example.com::mail.example.com:0:3600::\n', + exchange: 'mail.example.com.', + testB: 'test.example.com.\t3600\tIN\tMX\t0\tmail.example.com.\n', + testT: '@test.example.com::mail.example.com:0:3600::\n', }, { ...defaults, - owner : 'www.example.com.', - ttl : 86400, + owner: 'www.example.com.', + ttl: 86400, preference: 0, - exchange : '.', // null MX, RFC 7505 - testB : 'www.example.com.\t86400\tIN\tMX\t0\t.\n', - testT : '@www.example.com::.:0:86400::\n', + exchange: '.', // null MX, RFC 7505 + testB: 'www.example.com.\t86400\tIN\tMX\t0\t.\n', + testT: '@www.example.com::.:0:86400::\n', }, ] const invalidRecords = [ { ...defaults, - owner : 'test.example.com.', + owner: 'test.example.com.', exchange: 'not-full-qualified.example.com', - msg : /exchange must be fully qualified/, + msg: /exchange must be fully qualified/, }, { ...defaults, - owner : 'test.example.com.', + owner: 'test.example.com.', exchange: '192.0.2.1', - msg : /exchange must be a FQDN/, + msg: /exchange must be a FQDN/, }, { ...defaults, - owner : 'test.example.com.', + owner: 'test.example.com.', exchange: '-blah', - msg : /exchange must be fully qualified/, + msg: /exchange must be fully qualified/, }, ] @@ -54,7 +53,7 @@ describe('MX record', function () { base.getDescription(MX) base.getRFCs(MX, validRecords[0]) - base.getFields(MX, [ 'preference', 'exchange' ]) + base.getFields(MX, ['preference', 'exchange']) base.getTypeId(MX, 15) base.toBind(MX, validRecords) @@ -67,8 +66,12 @@ describe('MX record', function () { it.skip(`imports tinydns MX (@) record (${val.owner})`, async function () { const r = new MX({ tinyline: val.testT }) if (process.env.DEBUG) console.dir(r) - for (const f of [ 'owner', 'exchange', 'preference', 'ttl' ]) { - assert.deepStrictEqual(r.get(f), val[f], `${f}: ${r.get(f)} !== ${val[f]}`) + for (const f of ['owner', 'exchange', 'preference', 'ttl']) { + assert.deepStrictEqual( + r.get(f), + val[f], + `${f}: ${r.get(f)} !== ${val[f]}`, + ) } }) } diff --git a/test/naptr.js b/test/naptr.js index bfad427..e43e3f0 100644 --- a/test/naptr.js +++ b/test/naptr.js @@ -1,27 +1,27 @@ - import * as base from './base.js' import NAPTR from '../rr/naptr.js' const validRecords = [ { - owner : 'cid.urn.arpa.', - ttl : 86400, - class : 'IN', - type : 'NAPTR', - order : 100, - preference : 10, - flags : '', - service : '', - regexp : '!^urn:cid:.+@([^\\.]+\\.)(.*)$!\x02!i', + owner: 'cid.urn.arpa.', + ttl: 86400, + class: 'IN', + type: 'NAPTR', + order: 100, + preference: 10, + flags: '', + service: '', + regexp: '!^urn:cid:.+@([^\\.]+\\.)(.*)$!\x02!i', replacement: '.', - testB : 'cid.urn.arpa.\t86400\tIN\tNAPTR\t100\t10\t""\t""\t"!^urn:cid:.+@([^\\.]+\\.)(.*)$!\x02!i"\t.\n', - testT : ':cid.urn.arpa:35:\\000\\144\\000\\012\\000\\000\\040!^urn\\072cid\\072.+@([^\\134.]+\\134.)(.*)$!\x02!i\\001.\\000:86400::\n', + testB: + 'cid.urn.arpa.\t86400\tIN\tNAPTR\t100\t10\t""\t""\t"!^urn:cid:.+@([^\\.]+\\.)(.*)$!\x02!i"\t.\n', + testT: + ':cid.urn.arpa:35:\\000\\144\\000\\012\\000\\000\\040!^urn\\072cid\\072.+@([^\\134.]+\\134.)(.*)$!\x02!i\\001.\\000:86400::\n', }, ] -const invalidRecords = [ -] +const invalidRecords = [] describe('NAPTR record', function () { base.valid(NAPTR, validRecords) @@ -29,7 +29,14 @@ describe('NAPTR record', function () { base.getDescription(NAPTR) base.getRFCs(NAPTR, validRecords[0]) - base.getFields(NAPTR, [ 'order', 'preference', 'flags', 'service', 'regexp', 'replacement' ]) + base.getFields(NAPTR, [ + 'order', + 'preference', + 'flags', + 'service', + 'regexp', + 'replacement', + ]) base.getTypeId(NAPTR, 35) base.toBind(NAPTR, validRecords) diff --git a/test/ns.js b/test/ns.js index db3791e..a85eee1 100644 --- a/test/ns.js +++ b/test/ns.js @@ -1,4 +1,3 @@ - import assert from 'assert' import * as base from './base.js' @@ -21,8 +20,8 @@ const invalidRecords = [ { ...defaults, owner: 'example.com.', - dname: '1.2.3.4', // FQDN required - msg : /dname must be fully qualified/, + dname: '1.2.3.4', // FQDN required + msg: /dname must be fully qualified/, }, ] @@ -32,7 +31,7 @@ describe('NS record', function () { base.getDescription(NS) base.getRFCs(NS, validRecords[0]) - base.getFields(NS, [ 'dname' ]) + base.getFields(NS, ['dname']) base.getTypeId(NS, 2) base.toBind(NS, validRecords) @@ -45,8 +44,12 @@ describe('NS record', function () { it.skip(`imports tinydns NS (&) record (${val.owner})`, async function () { const r = new NS({ tinyline: val.testT }) if (process.env.DEBUG) console.dir(r) - for (const f of [ 'owner', 'dname', 'ttl' ]) { - assert.deepStrictEqual(r.get(f), val[f], `${f}: ${r.get(f)} !== ${val[f]}`) + for (const f of ['owner', 'dname', 'ttl']) { + assert.deepStrictEqual( + r.get(f), + val[f], + `${f}: ${r.get(f)} !== ${val[f]}`, + ) } }) } diff --git a/test/nsec.js b/test/nsec.js index 837cb3b..ceecb1f 100644 --- a/test/nsec.js +++ b/test/nsec.js @@ -1,17 +1,16 @@ - import * as base from './base.js' import NSEC from '../rr/nsec.js' const validRecords = [ { - owner : 'alfa.example.com.', - ttl : 86400, - class : 'IN', - type : 'NSEC', - 'next domain' : 'host.example.com.', + owner: 'alfa.example.com.', + ttl: 86400, + class: 'IN', + type: 'NSEC', + 'next domain': 'host.example.com.', 'type bit maps': 'A MX RRSIG NSEC TYPE1234', - testB : `alfa.example.com.\t86400\tIN\tNSEC\thost.example.com.\tA MX RRSIG NSEC TYPE1234\n`, + testB: `alfa.example.com.\t86400\tIN\tNSEC\thost.example.com.\tA MX RRSIG NSEC TYPE1234\n`, // testT : '\n', }, ] @@ -27,7 +26,7 @@ describe('NSEC record', function () { base.getDescription(NSEC) base.getRFCs(NSEC, validRecords[0]) - base.getFields(NSEC, [ 'next domain', 'type bit maps' ]) + base.getFields(NSEC, ['next domain', 'type bit maps']) base.getTypeId(NSEC, 47) base.toBind(NSEC, validRecords) diff --git a/test/nsec3.js b/test/nsec3.js index 66f32a4..f3ee009 100644 --- a/test/nsec3.js +++ b/test/nsec3.js @@ -1,4 +1,3 @@ - import * as base from './base.js' import NSEC3 from '../rr/nsec3.js' @@ -8,20 +7,21 @@ const defaults = { class: 'IN', ttl: 3600, type: 'NSEC3' } const validRecords = [ { ...defaults, - owner : 'test.example.com.', - 'hash algorithm' : 1, - flags : 1, - iterations : 12, - salt : 'aabbccdd', - 'type bit maps' : 'A\tRRSIG', + owner: 'test.example.com.', + 'hash algorithm': 1, + flags: 1, + iterations: 12, + salt: 'aabbccdd', + 'type bit maps': 'A\tRRSIG', 'next hashed owner name': '2vptu5timamqttgl4luu9kg21e0aor3s', - testB : 'test.example.com.\t3600\tIN\tNSEC3\t1\t1\t12\taabbccdd\t(2vptu5timamqttgl4luu9kg21e0aor3s\tA\tRRSIG)\n', - testT : ':test.example.com:50:\\001\\001\\000\\014aabbccdd2vptu5timamqttgl4luu9kg21e0aor3sA\\011RRSIG:3600::\n', + testB: + 'test.example.com.\t3600\tIN\tNSEC3\t1\t1\t12\taabbccdd\t(2vptu5timamqttgl4luu9kg21e0aor3s\tA\tRRSIG)\n', + testT: + ':test.example.com:50:\\001\\001\\000\\014aabbccdd2vptu5timamqttgl4luu9kg21e0aor3sA\\011RRSIG:3600::\n', }, ] -const invalidRecords = [ -] +const invalidRecords = [] describe('NSEC3 record', function () { base.valid(NSEC3, validRecords) @@ -29,7 +29,14 @@ describe('NSEC3 record', function () { base.getDescription(NSEC3) base.getRFCs(NSEC3, validRecords[0]) - base.getFields(NSEC3, [ 'hash algorithm', 'flags', 'iterations', 'salt', 'next hashed owner name', 'type bit maps' ]) + base.getFields(NSEC3, [ + 'hash algorithm', + 'flags', + 'iterations', + 'salt', + 'next hashed owner name', + 'type bit maps', + ]) base.getTypeId(NSEC3, 50) base.toBind(NSEC3, validRecords) diff --git a/test/nsec3param.js b/test/nsec3param.js index e59f7c2..c8c8ada 100644 --- a/test/nsec3param.js +++ b/test/nsec3param.js @@ -1,13 +1,10 @@ - import * as base from './base.js' import NSEC3PARAM from '../rr/nsec3param.js' -const validRecords = [ -] +const validRecords = [] -const invalidRecords = [ -] +const invalidRecords = [] describe('NSEC3PARAM record', function () { base.valid(NSEC3PARAM, validRecords) @@ -15,7 +12,7 @@ describe('NSEC3PARAM record', function () { base.getDescription(NSEC3PARAM) base.getRFCs(NSEC3PARAM, validRecords[0]) - base.getFields(NSEC3PARAM, [ 'hash algorithm', 'flags', 'iterations', 'salt' ]) + base.getFields(NSEC3PARAM, ['hash algorithm', 'flags', 'iterations', 'salt']) base.getTypeId(NSEC3PARAM, 51) // base.toBind(NSEC3PARAM, validRecords) diff --git a/test/nxt.js b/test/nxt.js new file mode 100644 index 0000000..e3e1d1a --- /dev/null +++ b/test/nxt.js @@ -0,0 +1,37 @@ +import * as base from './base.js' + +import NXT from '../rr/nxt.js' + +const validRecords = [ + { + owner: 'big.example.com.', + ttl: 86400, + class: 'IN', + type: 'NXT', + 'next domain': 'medium.example.com.', + 'type bit map': 'A SIG NXT', + testB: `big.example.com.\t86400\tIN\tNXT\tmedium.example.com.\tA SIG NXT\n`, + // testT : '\n', + }, +] + +const invalidRecords = [ + // { + // }, +] + +describe('NXT record', function () { + base.valid(NXT, validRecords) + base.invalid(NXT, invalidRecords, { ttl: 3600 }) + + base.getDescription(NXT) + base.getRFCs(NXT, validRecords[0]) + base.getFields(NXT, ['next domain', 'type bit map']) + base.getTypeId(NXT, 30) + + base.toBind(NXT, validRecords) + // base.toTinydns(NXT, validRecords) + + base.fromBind(NXT, validRecords) + // base.fromTinydns(NXT, validRecords) +}) diff --git a/test/openpgpkey.js b/test/openpgpkey.js index 175109d..7f6230d 100644 --- a/test/openpgpkey.js +++ b/test/openpgpkey.js @@ -1,4 +1,3 @@ - import * as base from './base.js' import OPENPGPKEY from '../rr/openpgpkey.js' @@ -15,8 +14,7 @@ const validRecords = [ // }, ] -const invalidRecords = [ -] +const invalidRecords = [] describe('OPENPGPKEY record', function () { base.valid(OPENPGPKEY, validRecords) @@ -24,7 +22,7 @@ describe('OPENPGPKEY record', function () { base.getDescription(OPENPGPKEY) base.getRFCs(OPENPGPKEY) - base.getFields(OPENPGPKEY, [ 'public key' ]) + base.getFields(OPENPGPKEY, ['public key']) base.getTypeId(OPENPGPKEY, 61) base.toBind(OPENPGPKEY, validRecords) diff --git a/test/ptr.js b/test/ptr.js index 01b83b6..53fcd22 100644 --- a/test/ptr.js +++ b/test/ptr.js @@ -1,4 +1,3 @@ - import assert from 'assert' import * as base from './base.js' @@ -21,8 +20,8 @@ const invalidRecords = [ { ...defaults, owner: 'example.com.', - dname: '192.0.2.4', // FQDN required - msg : /dname must be fully qualified/, + dname: '192.0.2.4', // FQDN required + msg: /dname must be fully qualified/, }, ] @@ -32,7 +31,7 @@ describe('PTR record', function () { base.getDescription(PTR) base.getRFCs(PTR, validRecords[0]) - base.getFields(PTR, [ 'dname' ]) + base.getFields(PTR, ['dname']) base.getTypeId(PTR, 12) base.toBind(PTR, validRecords) @@ -42,12 +41,15 @@ describe('PTR record', function () { base.fromTinydns(PTR, validRecords) for (const val of validRecords) { - it.skip(`imports tinydns PTR (^) record (${val.owner})`, async function () { const r = new PTR({ tinyline: val.testT }) if (process.env.DEBUG) console.dir(r) - for (const f of [ 'owner', 'dname', 'ttl' ]) { - assert.deepStrictEqual(r.get(f), val[f], `${f}: ${r.get(f)} !== ${val[f]}`) + for (const f of ['owner', 'dname', 'ttl']) { + assert.deepStrictEqual( + r.get(f), + val[f], + `${f}: ${r.get(f)} !== ${val[f]}`, + ) } }) } diff --git a/test/rr.js b/test/rr.js index ec36ca9..b6005f9 100644 --- a/test/rr.js +++ b/test/rr.js @@ -1,14 +1,21 @@ - import assert from 'assert' import RR from '../rr.js' -import A from '../rr/a.js' +import A from '../rr/a.js' const cases = [ // { name: 'RR class' , obj: RR , expect: [ 'owner', 'ttl', 'class', 'type' ] }, - { name: 'RR instance', obj: new RR(null), expect: [ 'owner', 'ttl', 'class', 'type' ] }, + { + name: 'RR instance', + obj: new RR(null), + expect: ['owner', 'ttl', 'class', 'type'], + }, // { name: 'A class' , obj: A , expect: [ 'owner', 'ttl', 'class', 'type', 'address' ] }, - { name: 'A instance' , obj: new A(null) , expect: [ 'owner', 'ttl', 'class', 'type', 'address' ] }, + { + name: 'A instance', + obj: new A(null), + expect: ['owner', 'ttl', 'class', 'type', 'address'], + }, ] for (const c of cases) { @@ -25,13 +32,12 @@ describe('RR', function () { const r = new RR(null) describe('setTtl', function () { - const invalid = [ -1, -4, -299, 2147483648, undefined ] + const invalid = [-1, -4, -299, 2147483648, undefined] for (const i of invalid) { it(`throws on invalid TTL: ${i}`, async function () { try { assert.deepStrictEqual(r.setTtl(i), false) - } - catch (e) { + } catch (e) { assert.ok(e.message) console.error(e.message) } @@ -40,19 +46,18 @@ describe('RR', function () { }) describe('setClass', function () { - for (const i of [ 'IN', 'CH', 'ANY', 'NONE' ]) { + for (const i of ['IN', 'CH', 'ANY', 'NONE']) { it(`accepts valid class: ${i}`, async function () { r.setClass(i) assert.deepEqual(r.get('class'), i) }) } - for (const i of [ 'matt', 'in', 0 ]) { + for (const i of ['matt', 'in', 0]) { it(`throws on invalid class: ${i}`, async function () { try { assert.strictEqual(r.setClass(i), false) - } - catch (e) { + } catch (e) { assert.ok(e.message) } }) @@ -86,20 +91,25 @@ describe('RR', function () { describe('isFullyQualified', function () { it('should detect FQDNs', async function () { - assert.deepEqual(r.isFullyQualified('$type', '$field', 'host.example.com.'), true) + assert.deepEqual( + r.isFullyQualified('$type', '$field', 'host.example.com.'), + true, + ) try { - assert.deepEqual(r.isFullyQualified('$type', '$field', 'host.example.com'), false) - } - catch (e) { + assert.deepEqual( + r.isFullyQualified('$type', '$field', 'host.example.com'), + false, + ) + } catch (e) { assert.deepEqual(e.message, '$type: $field must be fully qualified') } }) }) describe('is8bitInt', function () { - const valid = [ 1, 2, 255 ] - const invalid = [ -1, 'a', new Date(), undefined, 256 ] + const valid = [1, 2, 255] + const invalid = [-1, 'a', new Date(), undefined, 256] for (const i of valid) { it(`returns true for valid int: ${i}`, async function () { @@ -111,17 +121,19 @@ describe('RR', function () { it(`throws on invalid int: ${i}`, async function () { try { assert.strictEqual(r.is8bitInt('test', 'field', i), false) - } - catch (e) { - assert.strictEqual(e.message, 'test field must be a 8-bit integer (in the range 0-255)') + } catch (e) { + assert.strictEqual( + e.message, + 'test field must be a 8-bit integer (in the range 0-255)', + ) } }) } }) describe('is16bitInt', function () { - const valid = [ 0, 1, 2, 55555, 65535 ] - const invalid = [ 'a', new Date(), undefined, 65536 ] + const valid = [0, 1, 2, 55555, 65535] + const invalid = ['a', new Date(), undefined, 65536] for (const i of valid) { it(`returns true for valid int: ${i}`, async function () { @@ -133,17 +145,19 @@ describe('RR', function () { it(`throws on invalid int: ${i}`, async function () { try { assert.strictEqual(r.is16bitInt('test', 'field', i), false) - } - catch (e) { - assert.strictEqual(e.message, 'test field must be a 16-bit integer (in the range 0-65535)') + } catch (e) { + assert.strictEqual( + e.message, + 'test field must be a 16-bit integer (in the range 0-65535)', + ) } }) } }) describe('is32bitInt', function () { - const valid = [ 1, 2, 55555, 2147483647 ] - const invalid = [ 'a', new Date(), undefined, 2147483648 ] + const valid = [1, 2, 55555, 2147483647] + const invalid = ['a', new Date(), undefined, 2147483648] for (const i of valid) { it(`returns true for valid int: ${i}`, async function () { @@ -155,9 +169,11 @@ describe('RR', function () { it(`throws on invalid int: ${i}`, async function () { try { assert.strictEqual(r.is32bitInt('test', 'field', i), false) - } - catch (e) { - assert.strictEqual(e.message, 'test field must be a 32-bit integer (in the range 0-2147483647)') + } catch (e) { + assert.strictEqual( + e.message, + 'test field must be a 32-bit integer (in the range 0-2147483647)', + ) } }) } @@ -170,7 +186,7 @@ describe('RR', function () { assert.equal(r.getQuoted('cpu'), '"already quoted"') // doesn't double quote }) - it('doesn\'t double quote a quoted string', async () => { + it("doesn't double quote a quoted string", async () => { r.set('cpu', '"already quoted"') assert.equal(r.getQuoted('cpu'), '"already quoted"') }) @@ -187,10 +203,10 @@ describe('RR', function () { }) describe('isValidHostname', function () { - for (const n of [ 'x', '2x', '*', '*.something' ]) { + for (const n of ['x', '2x', '*', '*.something']) { it(`passes name: ${n}`, async function () { assert.deepEqual(r.isValidHostname(n), true) }) } }) -}) \ No newline at end of file +}) diff --git a/test/smimea.js b/test/smimea.js index b177aa5..736337a 100644 --- a/test/smimea.js +++ b/test/smimea.js @@ -1,4 +1,3 @@ - import * as base from './base.js' import SMIMEA from '../rr/smimea.js' @@ -8,13 +7,15 @@ const defaults = { class: 'IN', ttl: 3600, type: 'SMIMEA' } const validRecords = [ { ...defaults, - owner : '_443._tcp.www.example.com.', - ttl : 3600, - 'certificate usage' : 0, - selector : 0, - 'matching type' : 1, - 'certificate association data': '( d2abde240d7cd3ee6b4b28c54df034b9 7983a1d16e8a410e4561cb106618e971 )', - testB : '_443._tcp.www.example.com.\t3600\tIN\tSMIMEA\t0\t0\t1\t( d2abde240d7cd3ee6b4b28c54df034b9 7983a1d16e8a410e4561cb106618e971 )\n', + owner: '_443._tcp.www.example.com.', + ttl: 3600, + 'certificate usage': 0, + selector: 0, + 'matching type': 1, + 'certificate association data': + '( d2abde240d7cd3ee6b4b28c54df034b9 7983a1d16e8a410e4561cb106618e971 )', + testB: + '_443._tcp.www.example.com.\t3600\tIN\tSMIMEA\t0\t0\t1\t( d2abde240d7cd3ee6b4b28c54df034b9 7983a1d16e8a410e4561cb106618e971 )\n', // testT : '', }, ] @@ -22,9 +23,9 @@ const validRecords = [ const invalidRecords = [ { ...defaults, - owner : 'test.example.com.', - selector: 6, // invalid - msg : /certificate usage invalid/, + owner: 'test.example.com.', + selector: 6, // invalid + msg: /certificate usage invalid/, }, ] @@ -34,7 +35,12 @@ describe('SMIMEA record', function () { base.getDescription(SMIMEA) base.getRFCs(SMIMEA, validRecords[0]) - base.getFields(SMIMEA, [ 'certificate usage', 'selector', 'matching type', 'certificate association data' ]) + base.getFields(SMIMEA, [ + 'certificate usage', + 'selector', + 'matching type', + 'certificate association data', + ]) base.getTypeId(SMIMEA, 53) base.toBind(SMIMEA, validRecords) diff --git a/test/soa.js b/test/soa.js index 6b1fca9..8e6dc60 100644 --- a/test/soa.js +++ b/test/soa.js @@ -1,4 +1,3 @@ - import assert from 'assert' import * as base from './base.js' @@ -10,43 +9,45 @@ const defaults = { class: 'IN', ttl: 3600, type: 'SOA' } const validRecords = [ { ...defaults, - owner : 'example.com.', - mname : 'ns1.example.com.', - rname : 'matt.example.com.', - serial : 1, + owner: 'example.com.', + mname: 'ns1.example.com.', + rname: 'matt.example.com.', + serial: 1, refresh: 7200, - retry : 3600, - expire : 1209600, + retry: 3600, + expire: 1209600, minimum: 3600, - testB : `example.com.\t3600\tIN\tSOA\tns1.example.com.\tmatt.example.com.\t1\t7200\t3600\t1209600\t3600\n`, - testT : 'Zexample.com:ns1.example.com:matt.example.com:1:7200:3600:1209600:3600:3600::\n', + testB: `example.com.\t3600\tIN\tSOA\tns1.example.com.\tmatt.example.com.\t1\t7200\t3600\t1209600\t3600\n`, + testT: + 'Zexample.com:ns1.example.com:matt.example.com:1:7200:3600:1209600:3600:3600::\n', }, { ...defaults, - owner : '2.example.com.', - mname : 'ns2.example.com.', - rname : 'matt.example.com.', - serial : 1, + owner: '2.example.com.', + mname: 'ns2.example.com.', + rname: 'matt.example.com.', + serial: 1, refresh: 7200, - retry : 3600, - expire : 1209600, + retry: 3600, + expire: 1209600, minimum: 3600, - testB : `2.example.com.\t3600\tIN\tSOA\tns2.example.com.\tmatt.example.com.\t1\t7200\t3600\t1209600\t3600\n`, - testT : 'Z2.example.com:ns2.example.com:matt.example.com:1:7200:3600:1209600:3600:3600::\n', + testB: `2.example.com.\t3600\tIN\tSOA\tns2.example.com.\tmatt.example.com.\t1\t7200\t3600\t1209600\t3600\n`, + testT: + 'Z2.example.com:ns2.example.com:matt.example.com:1:7200:3600:1209600:3600:3600::\n', }, ] const invalidRecords = [ { ...defaults, - owner : 'example.com.', - mname : 'ns1.example.com.', - rname : 'matt.example.com.', - serial : 4294967296, + owner: 'example.com.', + mname: 'ns1.example.com.', + rname: 'matt.example.com.', + serial: 4294967296, refresh: 7200, - retry : 3600, - expire : 1209600, - msg : /serial must be a 32-bit integer/, + retry: 3600, + expire: 1209600, + msg: /serial must be a 32-bit integer/, }, ] @@ -56,7 +57,15 @@ describe('SOA record', function () { base.getDescription(SOA) base.getRFCs(SOA, validRecords[0]) - base.getFields(SOA, [ 'mname', 'rname', 'serial', 'refresh', 'retry', 'expire', 'minimum' ]) + base.getFields(SOA, [ + 'mname', + 'rname', + 'serial', + 'refresh', + 'retry', + 'expire', + 'minimum', + ]) base.getTypeId(SOA, 6) base.toBind(SOA, validRecords) @@ -69,9 +78,22 @@ describe('SOA record', function () { it.skip(`imports tinydns SOA (Z) record (${val.owner})`, async function () { const r = new SOA({ tinyline: val.testT }) if (process.env.DEBUG) console.dir(r) - for (const f of [ 'owner', 'mname', 'rname', 'serial', 'refresh', 'retry', 'expire', 'ttl' ]) { - assert.deepStrictEqual(r.get(f), val[f], `${f}: ${r.get(f)} !== ${val[f]}`) + for (const f of [ + 'owner', + 'mname', + 'rname', + 'serial', + 'refresh', + 'retry', + 'expire', + 'ttl', + ]) { + assert.deepStrictEqual( + r.get(f), + val[f], + `${f}: ${r.get(f)} !== ${val[f]}`, + ) } }) } -}) \ No newline at end of file +}) diff --git a/test/spf.js b/test/spf.js index a96c69a..fe102f4 100644 --- a/test/spf.js +++ b/test/spf.js @@ -1,4 +1,3 @@ - import assert from 'assert' import * as base from './base.js' @@ -11,15 +10,15 @@ const validRecords = [ { ...defaults, owner: 'example.com.', - data : 'v=spf1 mx a include:mx.example.com -all', - testB: 'example.com.\t86400\tIN\tSPF\t"v=spf1 mx a include:mx.example.com -all"\n', - testT: ':example.com:99:v=spf1 mx a include\\072mx.example.com -all:86400::\n', + data: 'v=spf1 mx a include:mx.example.com -all', + testB: + 'example.com.\t86400\tIN\tSPF\t"v=spf1 mx a include:mx.example.com -all"\n', + testT: + ':example.com:99:v=spf1 mx a include\\072mx.example.com -all:86400::\n', }, ] -const invalidRecords = [ - -] +const invalidRecords = [] describe('SPF record', function () { base.valid(SPF, validRecords) @@ -27,7 +26,7 @@ describe('SPF record', function () { base.getDescription(SPF) base.getRFCs(SPF, validRecords[0]) - base.getFields(SPF, [ 'data' ]) + base.getFields(SPF, ['data']) base.getTypeId(SPF, 99) base.toBind(SPF, validRecords) @@ -40,9 +39,13 @@ describe('SPF record', function () { it.skip(`imports tinydns SPF (generic) record`, async function () { const r = new SPF({ tinyline: val.testT }) if (process.env.DEBUG) console.dir(r) - for (const f of [ 'owner', 'data', 'ttl' ]) { - assert.deepStrictEqual(r.get(f), val[f], `${f}: ${r.get(f)} !== ${val[f]}`) + for (const f of ['owner', 'data', 'ttl']) { + assert.deepStrictEqual( + r.get(f), + val[f], + `${f}: ${r.get(f)} !== ${val[f]}`, + ) } }) } -}) \ No newline at end of file +}) diff --git a/test/srv.js b/test/srv.js index 6211aa1..01644d9 100644 --- a/test/srv.js +++ b/test/srv.js @@ -1,4 +1,3 @@ - import assert from 'assert' import * as base from './base.js' @@ -10,38 +9,42 @@ const defaults = { class: 'IN', ttl: 3600, type: 'SRV' } const validRecords = [ { ...defaults, - owner : '_imaps._tcp.example.com.', + owner: '_imaps._tcp.example.com.', priority: 1, - weight : 0, - port : 993, - target : 'mail.example.com.', - testB : '_imaps._tcp.example.com.\t3600\tIN\tSRV\t1\t0\t993\tmail.example.com.\n', - testT : ':_imaps._tcp.example.com:33:\\000\\001\\000\\000\\003\\341\\004mail\\007example\\003com\\000:3600::\n', + weight: 0, + port: 993, + target: 'mail.example.com.', + testB: + '_imaps._tcp.example.com.\t3600\tIN\tSRV\t1\t0\t993\tmail.example.com.\n', + testT: + ':_imaps._tcp.example.com:33:\\000\\001\\000\\000\\003\\341\\004mail\\007example\\003com\\000:3600::\n', }, { ...defaults, - owner : '_sip._tls.example.com.', + owner: '_sip._tls.example.com.', priority: 100, - weight : 1, - port : 443, - target : 'sipdir.online.lync.com.', - testB : '_sip._tls.example.com.\t3600\tIN\tSRV\t100\t1\t443\tsipdir.online.lync.com.\n', - testT : ':_sip._tls.example.com:33:\\000\\144\\000\\001\\001\\273\\006sipdir\\006online\\004lync\\003com\\000:3600::\n', + weight: 1, + port: 443, + target: 'sipdir.online.lync.com.', + testB: + '_sip._tls.example.com.\t3600\tIN\tSRV\t100\t1\t443\tsipdir.online.lync.com.\n', + testT: + ':_sip._tls.example.com:33:\\000\\144\\000\\001\\001\\273\\006sipdir\\006online\\004lync\\003com\\000:3600::\n', }, ] const invalidRecords = [ { ...defaults, - owner : 'test.example.com.', + owner: 'test.example.com.', target: 'not-full-qualified.example.com', - msg : /must be a 16-bit integer/, + msg: /must be a 16-bit integer/, }, { ...defaults, - owner : 'test.example.com.', + owner: 'test.example.com.', target: '192.168.0.1', - msg : /must be a 16-bit integer/, + msg: /must be a 16-bit integer/, }, ] @@ -51,7 +54,7 @@ describe('SRV record', function () { base.getDescription(SRV) base.getRFCs(SRV, validRecords[0]) - base.getFields(SRV, [ 'priority', 'weight', 'port', 'target' ]) + base.getFields(SRV, ['priority', 'weight', 'port', 'target']) base.getTypeId(SRV, 33) base.toBind(SRV, validRecords) @@ -64,18 +67,35 @@ describe('SRV record', function () { it(`imports tinydns SRV (generic) record (${val.owner})`, async function () { const r = new SRV({ tinyline: val.testT }) if (process.env.DEBUG) console.dir(r) - for (const f of [ 'owner', 'target', 'priority', 'weight', 'port', 'ttl' ]) { - assert.deepStrictEqual(r.get(f), val[f], `${f}: ${r.get(f)} !== ${val[f]}`) + for (const f of [ + 'owner', + 'target', + 'priority', + 'weight', + 'port', + 'ttl', + ]) { + assert.deepStrictEqual( + r.get(f), + val[f], + `${f}: ${r.get(f)} !== ${val[f]}`, + ) } }) } it(`imports tinydns SRV (S) record`, async function () { const val = validRecords[0] - const r = new SRV({ tinyline: 'S_imaps._tcp.example.com:mail.example.com:993:1:0:3600::' }) + const r = new SRV({ + tinyline: 'S_imaps._tcp.example.com:mail.example.com:993:1:0:3600::', + }) if (process.env.DEBUG) console.dir(r) - for (const f of [ 'owner', 'target', 'priority', 'weight', 'port', 'ttl' ]) { - assert.deepStrictEqual(r.get(f), val[f], `${f}: ${r.get(f)} !== ${val[f]}`) + for (const f of ['owner', 'target', 'priority', 'weight', 'port', 'ttl']) { + assert.deepStrictEqual( + r.get(f), + val[f], + `${f}: ${r.get(f)} !== ${val[f]}`, + ) } }) }) diff --git a/test/sshfp.js b/test/sshfp.js index 7074bcc..65e3b73 100644 --- a/test/sshfp.js +++ b/test/sshfp.js @@ -1,4 +1,3 @@ - import * as base from './base.js' import SSHFP from '../rr/sshfp.js' @@ -8,42 +7,50 @@ const common = { type: 'SSHFP', ttl: 86400, class: 'IN' } const validRecords = [ { ...common, - owner : 'mail.example.com.', - algorithm : 1, - fptype : 1, - fingerprint: 'ed8c6e16fdae4f633eee6a7b8f64fdd356bbb32841d535565d777014c9ea4c26', - testB : 'mail.example.com.\t86400\tIN\tSSHFP\t1\t1\ted8c6e16fdae4f633eee6a7b8f64fdd356bbb32841d535565d777014c9ea4c26\n', - testT : ':mail.example.com:44:\\001\\001\\355\\214\\156\\026\\375\\256\\117\\143\\076\\356\\152\\173\\217\\144\\375\\323\\126\\273\\263\\050\\101\\325\\065\\126\\135\\167\\160\\024\\311\\352\\114\\046:86400::\n', + owner: 'mail.example.com.', + algorithm: 1, + fptype: 1, + fingerprint: + 'ed8c6e16fdae4f633eee6a7b8f64fdd356bbb32841d535565d777014c9ea4c26', + testB: + 'mail.example.com.\t86400\tIN\tSSHFP\t1\t1\ted8c6e16fdae4f633eee6a7b8f64fdd356bbb32841d535565d777014c9ea4c26\n', + testT: + ':mail.example.com:44:\\001\\001\\355\\214\\156\\026\\375\\256\\117\\143\\076\\356\\152\\173\\217\\144\\375\\323\\126\\273\\263\\050\\101\\325\\065\\126\\135\\167\\160\\024\\311\\352\\114\\046:86400::\n', }, { ...common, - owner : 'jails.example.com.', - algorithm : 1, - fptype : 1, + owner: 'jails.example.com.', + algorithm: 1, + fptype: 1, fingerprint: '684981f1b57cc6b05bb2a5a7fd51a9114fef064d', - testB : 'jails.example.com.\t86400\tIN\tSSHFP\t1\t1\t684981f1b57cc6b05bb2a5a7fd51a9114fef064d\n', - testT : ':jails.example.com:44:\\001\\001\\150\\111\\201\\361\\265\\174\\306\\260\\133\\262\\245\\247\\375\\121\\251\\021\\117\\357\\006\\115:86400::\n', + testB: + 'jails.example.com.\t86400\tIN\tSSHFP\t1\t1\t684981f1b57cc6b05bb2a5a7fd51a9114fef064d\n', + testT: + ':jails.example.com:44:\\001\\001\\150\\111\\201\\361\\265\\174\\306\\260\\133\\262\\245\\247\\375\\121\\251\\021\\117\\357\\006\\115:86400::\n', }, { ...common, - owner : 'jails.example.com.', - algorithm : 3, - fptype : 2, - fingerprint: '81f9dbc4c009a1297336d69fcc2264f2a28417b781dafdd9c1ef7ff256066a35', - testB : 'jails.example.com.\t86400\tIN\tSSHFP\t3\t2\t81f9dbc4c009a1297336d69fcc2264f2a28417b781dafdd9c1ef7ff256066a35\n', + owner: 'jails.example.com.', + algorithm: 3, + fptype: 2, + fingerprint: + '81f9dbc4c009a1297336d69fcc2264f2a28417b781dafdd9c1ef7ff256066a35', + testB: + 'jails.example.com.\t86400\tIN\tSSHFP\t3\t2\t81f9dbc4c009a1297336d69fcc2264f2a28417b781dafdd9c1ef7ff256066a35\n', }, { ...common, - owner : 'jails.example.com.', - algorithm : 1, - fptype : 2, - fingerprint: 'ed8c6e16fdae4f633eee6a7b8f64fdd356bbb32841d535565d777014c9ea4c26', - testB : 'jails.example.com.\t86400\tIN\tSSHFP\t1\t2\ted8c6e16fdae4f633eee6a7b8f64fdd356bbb32841d535565d777014c9ea4c26\n', + owner: 'jails.example.com.', + algorithm: 1, + fptype: 2, + fingerprint: + 'ed8c6e16fdae4f633eee6a7b8f64fdd356bbb32841d535565d777014c9ea4c26', + testB: + 'jails.example.com.\t86400\tIN\tSSHFP\t1\t2\ted8c6e16fdae4f633eee6a7b8f64fdd356bbb32841d535565d777014c9ea4c26\n', }, ] -const invalidRecords = [ -] +const invalidRecords = [] describe('SSHFP record', function () { base.valid(SSHFP, validRecords) @@ -51,7 +58,7 @@ describe('SSHFP record', function () { base.getDescription(SSHFP) base.getRFCs(SSHFP, validRecords[0]) - base.getFields(SSHFP, [ 'algorithm', 'fptype', 'fingerprint' ]) + base.getFields(SSHFP, ['algorithm', 'fptype', 'fingerprint']) base.getTypeId(SSHFP, 44) base.toBind(SSHFP, validRecords) diff --git a/test/tinydns.js b/test/tinydns.js index b8c1a0e..a607c9a 100644 --- a/test/tinydns.js +++ b/test/tinydns.js @@ -1,13 +1,11 @@ - import assert from 'assert' import * as TINYDNS from '../lib/tinydns.js' describe('TINYDNS', function () { - const b64cases = { '0sAQPeOwAGDPLrDebL1q5Lg8XW9B/d9MnxqlzIYKXhvZPWEHNYGP7AwART/tmkeDNn7HPMtgM6GIwQ4p0KGLfSRoUKbjtPlRVeWYLbsnNXeFU5bchyYef0efYiKlxZdo': - '\\322\\300\\020\\075\\343\\260\\000\\140\\317.\\260\\336l\\275j\\344\\270\\074\\135oA\\375\\337L\\237\\032\\245\\314\\206\\012\\136\\033\\331\\075a\\0075\\201\\217\\354\\014\\000E\\077\\355\\232G\\2036\\176\\307\\074\\313\\1403\\241\\210\\301\\016\\051\\320\\241\\213\\175\\044hP\\246\\343\\264\\371QU\\345\\230-\\273\\0475w\\205S\\226\\334\\207\\046\\036\\177G\\237b\\042\\245\\305\\227h', + '\\322\\300\\020\\075\\343\\260\\000\\140\\317.\\260\\336l\\275j\\344\\270\\074\\135oA\\375\\337L\\237\\032\\245\\314\\206\\012\\136\\033\\331\\075a\\0075\\201\\217\\354\\014\\000E\\077\\355\\232G\\2036\\176\\307\\074\\313\\1403\\241\\210\\301\\016\\051\\320\\241\\213\\175\\044hP\\246\\343\\264\\371QU\\345\\230-\\273\\0475w\\205S\\226\\334\\207\\046\\036\\177G\\237b\\042\\245\\305\\227h', } describe('base64toOctal', function () { @@ -27,17 +25,22 @@ describe('TINYDNS', function () { }) describe('escapeOctal', function () { - const rdataRe = new RegExp(/[\r\n\t:\\/]/, 'g') it('escapes tinydns rdata special chars', async function () { - const e = TINYDNS.escapeOctal(rdataRe, 'v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN/nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64/cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn/LAf+3kzW58AjsERpsNCSTD2RquxbnyoR/1wdGKb8cUlD/EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB') - assert.strictEqual(e, 'v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN\\057nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64\\057cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn\\057LAf+3kzW58AjsERpsNCSTD2RquxbnyoR\\0571wdGKb8cUlD\\057EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB') + const e = TINYDNS.escapeOctal( + rdataRe, + 'v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN/nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64/cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn/LAf+3kzW58AjsERpsNCSTD2RquxbnyoR/1wdGKb8cUlD/EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB', + ) + assert.strictEqual( + e, + 'v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN\\057nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64\\057cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn\\057LAf+3kzW58AjsERpsNCSTD2RquxbnyoR\\0571wdGKb8cUlD\\057EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB', + ) }) const specialChars = { - '/' : '\\057', + '/': '\\057', '\\': '\\134', - ':' : '\\072', + ':': '\\072', } for (const c of Object.keys(specialChars)) { @@ -48,13 +51,17 @@ describe('TINYDNS', function () { }) describe('octaltoChar', function () { - it('converts a string of octal escapes to characters', async () => { - }) + it('converts a string of octal escapes to characters', async () => {}) }) describe('octalToHex', function () { it('unescapes octal to hex digits', function () { - assert.strictEqual(TINYDNS.octalToHex('\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\001'), '00000000000000000000000000000001') + assert.strictEqual( + TINYDNS.octalToHex( + '\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\001', + ), + '00000000000000000000000000000001', + ) }) }) @@ -80,33 +87,44 @@ describe('TINYDNS', function () { describe('UInt32toOctal', function () { it('converts a 32-bit number to escaped octal', function (done) { - assert.strictEqual(TINYDNS.UInt32toOctal(2319310648), '\\212\\075\\337\\070') + assert.strictEqual( + TINYDNS.UInt32toOctal(2319310648), + '\\212\\075\\337\\070', + ) done() }) it('converts a 32-bit number to escaped octal', function (done) { - assert.strictEqual(TINYDNS.UInt32toOctal(1706988648), '\\145\\276\\224\\150') + assert.strictEqual( + TINYDNS.UInt32toOctal(1706988648), + '\\145\\276\\224\\150', + ) done() }) }) describe('octalToUInt32', function () { it('converts escaped octal to 32-bit integer', function () { - assert.strictEqual(TINYDNS.octalToUInt32('\\145\\276\\224\\150'), 1706988648) + assert.strictEqual( + TINYDNS.octalToUInt32('\\145\\276\\224\\150'), + 1706988648, + ) }) }) describe('unpackDomainName', function () { it(`extracts domain name from wire format`, async () => { - const r = TINYDNS.unpackDomainName('\\006sipdir\\006online\\004lync\\003com\\000') + const r = TINYDNS.unpackDomainName( + '\\006sipdir\\006online\\004lync\\003com\\000', + ) assert.strictEqual(r[0], 'sipdir.online.lync.com.') assert.strictEqual(r[1], 40) }) }) const cases = { - '0.0.0.0' : '\\000\\000\\000\\000', - '192.0.2.127' : '\\300\\000\\002\\177', + '0.0.0.0': '\\000\\000\\000\\000', + '192.0.2.127': '\\300\\000\\002\\177', '255.255.255.255': '\\377\\377\\377\\377', } @@ -128,13 +146,18 @@ describe('TINYDNS', function () { describe('packString', function () { it(`packs a string to wire format`, async () => { - assert.strictEqual(TINYDNS.packString('matt wuz here'), '\\015matt wuz here') + assert.strictEqual( + TINYDNS.packString('matt wuz here'), + '\\015matt wuz here', + ) }) }) describe('uppackString', function () { it(`uppacks a string from wire format`, async () => { - assert.deepStrictEqual(TINYDNS.unpackString('\\015matt wuz here'), [ 'matt wuz here' ]) + assert.deepStrictEqual(TINYDNS.unpackString('\\015matt wuz here'), [ + 'matt wuz here', + ]) }) }) }) diff --git a/test/tlsa.js b/test/tlsa.js index 5fc7ba7..cc049e0 100644 --- a/test/tlsa.js +++ b/test/tlsa.js @@ -1,4 +1,3 @@ - import * as base from './base.js' import TLSA from '../rr/tlsa.js' @@ -8,32 +7,37 @@ const defaults = { class: 'IN', ttl: 3600, type: 'TLSA' } const validRecords = [ { ...defaults, - owner : '_443._tcp.www.example.com.', - 'certificate usage' : 0, - selector : 0, - 'matching type' : 1, - 'certificate association data': 'd2abde240d7cd3ee6b4b28c54df034b9 7983a1d16e8a410e4561cb106618e971', - testB : '_443._tcp.www.example.com.\t3600\tIN\tTLSA\t0\t0\t1\td2abde240d7cd3ee6b4b28c54df034b9 7983a1d16e8a410e4561cb106618e971\n', - testT : ':_443._tcp.www.example.com:52:\\000\\000\\001d2abde240d7cd3ee6b4b28c54df034b9 7983a1d16e8a410e4561cb106618e971:3600::\n', + owner: '_443._tcp.www.example.com.', + 'certificate usage': 0, + selector: 0, + 'matching type': 1, + 'certificate association data': + 'd2abde240d7cd3ee6b4b28c54df034b9 7983a1d16e8a410e4561cb106618e971', + testB: + '_443._tcp.www.example.com.\t3600\tIN\tTLSA\t0\t0\t1\td2abde240d7cd3ee6b4b28c54df034b9 7983a1d16e8a410e4561cb106618e971\n', + testT: + ':_443._tcp.www.example.com:52:\\000\\000\\001d2abde240d7cd3ee6b4b28c54df034b9 7983a1d16e8a410e4561cb106618e971:3600::\n', }, { ...defaults, - owner : '_443._tcp.www.example.com.', - 'certificate usage' : 1, - selector : 1, - 'matching type' : 2, - 'certificate association data': '92003ba34942dc74152e2f2c408d29ec a5a520e7f2e06bb944f4dca346baf63c 1b177615d466f6c4b71c216a50292bd5 8c9ebdd2f74e38fe51ffd48c43326cbc', - testB : `_443._tcp.www.example.com.\t3600\tIN\tTLSA\t1\t1\t2\t92003ba34942dc74152e2f2c408d29ec a5a520e7f2e06bb944f4dca346baf63c 1b177615d466f6c4b71c216a50292bd5 8c9ebdd2f74e38fe51ffd48c43326cbc\n`, - testT : ':_443._tcp.www.example.com:52:\\001\\001\\00292003ba34942dc74152e2f2c408d29ec a5a520e7f2e06bb944f4dca346baf63c 1b177615d466f6c4b71c216a50292bd5 8c9ebdd2f74e38fe51ffd48c43326cbc:3600::\n', + owner: '_443._tcp.www.example.com.', + 'certificate usage': 1, + selector: 1, + 'matching type': 2, + 'certificate association data': + '92003ba34942dc74152e2f2c408d29ec a5a520e7f2e06bb944f4dca346baf63c 1b177615d466f6c4b71c216a50292bd5 8c9ebdd2f74e38fe51ffd48c43326cbc', + testB: `_443._tcp.www.example.com.\t3600\tIN\tTLSA\t1\t1\t2\t92003ba34942dc74152e2f2c408d29ec a5a520e7f2e06bb944f4dca346baf63c 1b177615d466f6c4b71c216a50292bd5 8c9ebdd2f74e38fe51ffd48c43326cbc\n`, + testT: + ':_443._tcp.www.example.com:52:\\001\\001\\00292003ba34942dc74152e2f2c408d29ec a5a520e7f2e06bb944f4dca346baf63c 1b177615d466f6c4b71c216a50292bd5 8c9ebdd2f74e38fe51ffd48c43326cbc:3600::\n', }, ] const invalidRecords = [ { ...defaults, - owner : 'test.example.com.', - selector: 6, // invalid - msg : /RFC/, + owner: 'test.example.com.', + selector: 6, // invalid + msg: /RFC/, }, ] @@ -43,7 +47,12 @@ describe('TLSA record', function () { base.getDescription(TLSA) base.getRFCs(TLSA, validRecords[0]) - base.getFields(TLSA, [ 'certificate usage', 'selector', 'matching type', 'certificate association data' ]) + base.getFields(TLSA, [ + 'certificate usage', + 'selector', + 'matching type', + 'certificate association data', + ]) base.getTypeId(TLSA, 52) base.toBind(TLSA, validRecords) diff --git a/test/txt.js b/test/txt.js index 8ccefbf..dd19adb 100644 --- a/test/txt.js +++ b/test/txt.js @@ -1,4 +1,3 @@ - import assert from 'assert' import * as base from './base.js' @@ -8,32 +7,39 @@ import TXT from '../rr/txt.js' const validRecords = [ { owner: 'oct2021._domainkey.example.com.', - ttl : 86400, - type : 'TXT', - data : 'v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN/nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64/cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn/LAf+3kzW58AjsERpsNCSTD2RquxbnyoR/1wdGKb8cUlD/EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB', - testB: 'oct2021._domainkey.example.com.\t86400\tIN\tTXT\t"v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN/nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64/cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob" "4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn/LAf+3kzW58AjsERpsNCSTD2RquxbnyoR/1wdGKb8cUlD/EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB"\n', - testT: '\'oct2021._domainkey.example.com:v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN\\057nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64\\057cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn\\057LAf+3kzW58AjsERpsNCSTD2RquxbnyoR\\0571wdGKb8cUlD\\057EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB:86400::\n', + ttl: 86400, + type: 'TXT', + data: 'v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN/nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64/cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn/LAf+3kzW58AjsERpsNCSTD2RquxbnyoR/1wdGKb8cUlD/EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB', + testB: + 'oct2021._domainkey.example.com.\t86400\tIN\tTXT\t"v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN/nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64/cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob" "4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn/LAf+3kzW58AjsERpsNCSTD2RquxbnyoR/1wdGKb8cUlD/EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB"\n', + testT: + "'oct2021._domainkey.example.com:v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN\\057nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64\\057cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn\\057LAf+3kzW58AjsERpsNCSTD2RquxbnyoR\\0571wdGKb8cUlD\\057EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB:86400::\n", }, { owner: 'oct2021._domainkey.example.com.', - ttl : 86400, - type : 'TXT', - data : [ 'v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN/nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64/cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob', '4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn/LAf+3kzW58AjsERpsNCSTD2RquxbnyoR/1wdGKb8cUlD/EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB' ], - testB: 'oct2021._domainkey.example.com.\t86400\tIN\tTXT\t"v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN/nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64/cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob" "4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn/LAf+3kzW58AjsERpsNCSTD2RquxbnyoR/1wdGKb8cUlD/EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB"\n', - testT: '\'oct2021._domainkey.example.com:v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN\\057nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64\\057cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn\\057LAf+3kzW58AjsERpsNCSTD2RquxbnyoR\\0571wdGKb8cUlD\\057EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB:86400::\n', + ttl: 86400, + type: 'TXT', + data: [ + 'v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN/nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64/cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob', + '4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn/LAf+3kzW58AjsERpsNCSTD2RquxbnyoR/1wdGKb8cUlD/EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB', + ], + testB: + 'oct2021._domainkey.example.com.\t86400\tIN\tTXT\t"v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN/nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64/cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob" "4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn/LAf+3kzW58AjsERpsNCSTD2RquxbnyoR/1wdGKb8cUlD/EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB"\n', + testT: + "'oct2021._domainkey.example.com:v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN\\057nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64\\057cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn\\057LAf+3kzW58AjsERpsNCSTD2RquxbnyoR\\0571wdGKb8cUlD\\057EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB:86400::\n", }, { owner: 'example.com.', - ttl : 86400, - type : 'TXT', - data : 'v=spf1 mx a include:mx.example.com -all', - testB: 'example.com.\t86400\tIN\tTXT\t"v=spf1 mx a include:mx.example.com -all"\n', - testT: '\'example.com:v=spf1 mx a include\\072mx.example.com -all:86400::\n', + ttl: 86400, + type: 'TXT', + data: 'v=spf1 mx a include:mx.example.com -all', + testB: + 'example.com.\t86400\tIN\tTXT\t"v=spf1 mx a include:mx.example.com -all"\n', + testT: "'example.com:v=spf1 mx a include\\072mx.example.com -all:86400::\n", }, ] -const invalidRecords = [ -] +const invalidRecords = [] describe('TXT record', function () { base.valid(TXT, validRecords) @@ -41,7 +47,7 @@ describe('TXT record', function () { base.getDescription(TXT) base.getRFCs(TXT, validRecords[0]) - base.getFields(TXT, [ 'data' ]) + base.getFields(TXT, ['data']) base.getTypeId(TXT, 16) base.toBind(TXT, validRecords) @@ -53,18 +59,24 @@ describe('TXT record', function () { it(`imports tinydns TXT (generic) record`, async function () { const val = { owner: 'nov2021._domainkey.example.com.', - type : 'TXT', - data : 'v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN/nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64/cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn/LAf+3kzW58AjsERpsNCSTD2RquxbnyoR/1wdGKb8cUlD/EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB', - ttl : 86400, - testB: 'nov2021._domainkey.example.com.\t86400\tIN\tTXT\t"v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN/nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64/cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob" "4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn/LAf+3kzW58AjsERpsNCSTD2RquxbnyoR/1wdGKb8cUlD/EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB"\n', - testT: ':nov2021._domainkey.example.com:16:\\622v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN\\057nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64\\057cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn\\057LAf+3kzW58AjsERpsNCSTD2RquxbnyoR\\0571wdGKb8cUlD\\057EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB:86400\n', + type: 'TXT', + data: 'v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN/nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64/cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn/LAf+3kzW58AjsERpsNCSTD2RquxbnyoR/1wdGKb8cUlD/EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB', + ttl: 86400, + testB: + 'nov2021._domainkey.example.com.\t86400\tIN\tTXT\t"v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN/nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64/cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob" "4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn/LAf+3kzW58AjsERpsNCSTD2RquxbnyoR/1wdGKb8cUlD/EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB"\n', + testT: + ':nov2021._domainkey.example.com:16:\\622v=DKIM1;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoyUzGOTSOmakY8BcxXgi0mN\\057nFegLBPs7aaGQUtjHfa8yUrt9T2j6GSXgdjLuG3R43WjePQv3RHzc+bwwOkdw0XDOXiztn5mhrlaflbVr5PMSTrv64\\057cpFQKLtgQx8Vgqp7Dh3jw13rLomRTqJFgMrMHdhIibZEa69gtuAfDqoeXo6QDSGk5JuBAeRHEH27FriHulg5ob4F4lmh7fMFVsDGkQEF6jaIVYqvRjDyyQed3R3aTJX3fpb3QrtRqvfn\\057LAf+3kzW58AjsERpsNCSTD2RquxbnyoR\\0571wdGKb8cUlD\\057EXvqtvpVnOzHeSeMEqex3kQI8HOGsEehWZlKd+GqwIDAQAB:86400\n', } const r = new TXT({ tinyline: val.testT }) if (process.env.DEBUG) console.dir(r) for (const f of r.getFields()) { if (f === 'class') continue - assert.deepStrictEqual(r.get(f), val[f], `${f}: ${r.get(f)} !== ${val[f]}`) + assert.deepStrictEqual( + r.get(f), + val[f], + `${f}: ${r.get(f)} !== ${val[f]}`, + ) } }) -}) \ No newline at end of file +}) diff --git a/test/uri.js b/test/uri.js index 99cd14f..80834ca 100644 --- a/test/uri.js +++ b/test/uri.js @@ -1,4 +1,3 @@ - import assert from 'assert' import * as base from './base.js' @@ -7,32 +6,33 @@ import URI from '../rr/uri.js' const validRecords = [ { - class : 'IN', - owner : 'www.example.com.', - type : 'URI', - target : 'www2.example.com.', + class: 'IN', + owner: 'www.example.com.', + type: 'URI', + target: 'www2.example.com.', priority: 1, - weight : 0, - ttl : 3600, - testB : 'www.example.com.\t3600\tIN\tURI\t1\t0\t"www2.example.com."\n', - testT : ':www.example.com:256:\\000\\001\\000\\000www2.example.com.:3600::\n', + weight: 0, + ttl: 3600, + testB: 'www.example.com.\t3600\tIN\tURI\t1\t0\t"www2.example.com."\n', + testT: + ':www.example.com:256:\\000\\001\\000\\000www2.example.com.:3600::\n', }, { - class : 'IN', - owner : '_http.github.dog.', - type : 'URI', - target : 'http://github.com/dog', + class: 'IN', + owner: '_http.github.dog.', + type: 'URI', + target: 'http://github.com/dog', priority: 2, - weight : 100, - ttl : 3600, - testB : '_http.github.dog.\t3600\tIN\tURI\t2\t100\t"http://github.com/dog"\n', - testT : ':_http.github.dog:256:\\000\\002\\000\\144http\\072\\057\\057github.com\\057dog:3600::\n', + weight: 100, + ttl: 3600, + testB: + '_http.github.dog.\t3600\tIN\tURI\t2\t100\t"http://github.com/dog"\n', + testT: + ':_http.github.dog:256:\\000\\002\\000\\144http\\072\\057\\057github.com\\057dog:3600::\n', }, ] -const invalidRecords = [ - -] +const invalidRecords = [] describe('URI record', function () { base.valid(URI, validRecords) @@ -40,7 +40,7 @@ describe('URI record', function () { base.getDescription(URI) base.getRFCs(URI, validRecords[0]) - base.getFields(URI, [ 'priority', 'weight', 'target' ]) + base.getFields(URI, ['priority', 'weight', 'target']) base.getTypeId(URI, 256) base.toBind(URI, validRecords) @@ -53,8 +53,12 @@ describe('URI record', function () { it.skip(`imports tinydns (generic) record`, async function () { const r = new URI({ tinyline: val.testT }) if (process.env.DEBUG) console.dir(r) - for (const f of [ 'owner', 'priority', 'weight', 'target', 'ttl' ]) { - assert.deepStrictEqual(r.get(f), val[f], `${f}: ${r.get(f)} !== ${val[f]}`) + for (const f of ['owner', 'priority', 'weight', 'target', 'ttl']) { + assert.deepStrictEqual( + r.get(f), + val[f], + `${f}: ${r.get(f)} !== ${val[f]}`, + ) } }) }