diff --git a/.eslintignore b/.eslintignore index b4cb86c26bb4..6ac84fe1d179 100644 --- a/.eslintignore +++ b/.eslintignore @@ -332,9 +332,6 @@ testing/raptor/raptor/playback/scripts/catapult/** testing/web-platform/** testing/xpcshell/moz-http2/** testing/xpcshell/node-http2/** -testing/xpcshell/dns-packet/** -testing/xpcshell/node-ip/** - # Third party services services/common/kinto-http-client.js diff --git a/netwerk/test/unit/test_trr.js b/netwerk/test/unit/test_trr.js index 2cf90666c234..b9132fb3856a 100644 --- a/netwerk/test/unit/test_trr.js +++ b/netwerk/test/unit/test_trr.js @@ -1,445 +1,581 @@ -"use strict"; +Cu.import("resource://gre/modules/NetUtil.jsm"); -const {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm"); +var prefs; +var origin; +var h2Port; -const dns = Cc["@mozilla.org/network/dns-service;1"].getService(Ci.nsIDNSService); -const mainThread = Services.tm.currentThread; +var dns = Cc["@mozilla.org/network/dns-service;1"].getService(Ci.nsIDNSService); +var threadManager = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); +var mainThread = threadManager.currentThread; const defaultOriginAttributes = {}; -let h2Port = null; -add_task(function setup() { - dump("start!\n"); +function run_test() { + dump ("start!\n"); - let env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment); + var env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment); h2Port = env.get("MOZHTTP2_PORT"); Assert.notEqual(h2Port, null); Assert.notEqual(h2Port, ""); // Set to allow the cert presented by our H2 server do_get_profile(); + prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch); - Services.prefs.setBoolPref("network.http.spdy.enabled", true); - Services.prefs.setBoolPref("network.http.spdy.enabled.http2", true); + prefs.setBoolPref("network.http.spdy.enabled", true); + prefs.setBoolPref("network.http.spdy.enabled.http2", true); // the TRR server is on 127.0.0.1 - Services.prefs.setCharPref("network.trr.bootstrapAddress", "127.0.0.1"); + prefs.setCharPref("network.trr.bootstrapAddress", "127.0.0.1"); // use the h2 server as DOH provider - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns`); + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns"); // make all native resolve calls "secretly" resolve localhost instead - Services.prefs.setBoolPref("network.dns.native-is-localhost", true); + prefs.setBoolPref("network.dns.native-is-localhost", true); // 0 - off, 1 - race, 2 TRR first, 3 TRR only, 4 shadow - Services.prefs.setIntPref("network.trr.mode", 2); // TRR first - Services.prefs.setBoolPref("network.trr.wait-for-portal", false); + prefs.setIntPref("network.trr.mode", 2); // TRR first + prefs.setBoolPref("network.trr.wait-for-portal", false); // don't confirm that TRR is working, just go! - Services.prefs.setCharPref("network.trr.confirmationNS", "skip"); + prefs.setCharPref("network.trr.confirmationNS", "skip"); // The moz-http2 cert is for foo.example.com and is signed by http2-ca.pem // so add that cert to the trust list as a signing cert. // the foo.example.com domain name. let certdb = Cc["@mozilla.org/security/x509certdb;1"] .getService(Ci.nsIX509CertDB); addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u"); -}); + do_test_pending(); + run_dns_tests(); +} + +function resetTRRPrefs() { + prefs.clearUserPref("network.trr.mode"); + prefs.clearUserPref("network.trr.uri"); + prefs.clearUserPref("network.trr.credentials"); + prefs.clearUserPref("network.trr.wait-for-portal"); + prefs.clearUserPref("network.trr.allow-rfc1918"); + prefs.clearUserPref("network.trr.useGET"); + prefs.clearUserPref("network.trr.confirmationNS"); + prefs.clearUserPref("network.trr.bootstrapAddress"); + prefs.clearUserPref("network.trr.blacklist-duration"); + prefs.clearUserPref("network.trr.request-timeout"); + prefs.clearUserPref("network.trr.disable-ECS"); +} registerCleanupFunction(() => { - Services.prefs.clearUserPref("network.trr.mode"); - Services.prefs.clearUserPref("network.trr.uri"); - Services.prefs.clearUserPref("network.trr.credentials"); - Services.prefs.clearUserPref("network.trr.wait-for-portal"); - Services.prefs.clearUserPref("network.trr.allow-rfc1918"); - Services.prefs.clearUserPref("network.trr.useGET"); - Services.prefs.clearUserPref("network.trr.confirmationNS"); - Services.prefs.clearUserPref("network.trr.bootstrapAddress"); - Services.prefs.clearUserPref("network.trr.blacklist-duration"); - Services.prefs.clearUserPref("network.trr.request-timeout"); - Services.prefs.clearUserPref("network.trr.disable-ECS"); - Services.prefs.clearUserPref("network.trr.excluded-domains"); - - Services.prefs.clearUserPref("network.http.spdy.enabled"); - Services.prefs.clearUserPref("network.http.spdy.enabled.http2"); - Services.prefs.clearUserPref("network.dns.localDomains"); - Services.prefs.clearUserPref("network.dns.native-is-localhost"); + prefs.clearUserPref("network.http.spdy.enabled"); + prefs.clearUserPref("network.http.spdy.enabled.http2"); + prefs.clearUserPref("network.dns.localDomains"); + prefs.clearUserPref("network.dns.native-is-localhost"); + resetTRRPrefs(); }); -class DNSListener { - constructor(name, expectedAnswer, expectedSuccess = true) { - this.name = name; - this.expectedAnswer = expectedAnswer; - this.expectedSuccess = expectedSuccess; - this.promise = new Promise(resolve => { this.resolve = resolve; }); - this.request = dns.asyncResolve(name, 0, this, mainThread, defaultOriginAttributes); - } +function testsDone() +{ + do_test_finished(); + do_test_finished(); +} - onLookupComplete(inRequest, inRecord, inStatus) { - Assert.ok(inRequest == this.request); +var test_loops; +var test_answer="127.0.0.1"; - // If we don't expect success here, just resolve and the caller will - // decide what to do with the results. - if (!this.expectedSuccess) { - this.resolve([inRequest, inRecord, inStatus]); - return; +// check that we do lookup the name fine +var listenerFine = { + onLookupComplete: function(inRequest, inRecord, inStatus) { + if (inRequest == listen) { + Assert.equal(inStatus, Cr.NS_OK); + var answer = inRecord.getNextAddrAsString(); + Assert.equal(answer, test_answer); + do_test_finished(); + run_dns_tests(); } - - Assert.equal(inStatus, Cr.NS_OK); - let answer = inRecord.getNextAddrAsString(); - Assert.equal(answer, this.expectedAnswer); - this.resolve([inRequest, inRecord, inStatus]); - } - - QueryInterface(aIID) { + }, + QueryInterface: function(aIID) { if (aIID.equals(Ci.nsIDNSListener) || aIID.equals(Ci.nsISupports)) { return this; } throw Cr.NS_ERROR_NO_INTERFACE; } +}; - // Implement then so we can await this as a promise. - then() { - return this.promise.then.apply(this.promise, arguments); +// check that the name lookup fails +var listenerFails = { + onLookupComplete: function(inRequest, inRecord, inStatus) { + if (inRequest == listen) { + Assert.ok(!Components.isSuccessCode(inStatus), `must be failure code: ${inStatus}`); + do_test_finished(); + run_dns_tests(); + } + }, + QueryInterface: function(aIID) { + if (aIID.equals(Ci.nsIDNSListener) || + aIID.equals(Ci.nsISupports)) { + return this; + } + throw Cr.NS_ERROR_NO_INTERFACE; } -} +}; +// check that we do lookup the name fine +var listenerUntilFine = { + onLookupComplete: function(inRequest, inRecord, inStatus) { + if ((inRequest == listen) && (inRecord != null)) { + var answer = inRecord.getNextAddrAsString(); + if (answer == test_answer) { + Assert.equal(answer, test_answer); + dump("Got what we were waiting for!\n"); + } + } + else { + // not the one we want, try again + dump("Waiting for " + test_answer + " but got " + answer + "\n"); + --test_loops; + Assert.ok(test_loops != 0); + current_test--; + } + do_test_finished(); + run_dns_tests(); + }, + QueryInterface: function(aIID) { + if (aIID.equals(Ci.nsIDNSListener) || + aIID.equals(Ci.nsISupports)) { + return this; + } + throw Cr.NS_ERROR_NO_INTERFACE; + } +}; + +var listen; // verify basic A record -add_task(async function test1() { +function test1() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 2); // TRR-first - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=2.2.2.2`); - - await new DNSListener("bar.example.com", "2.2.2.2"); -}); + prefs.setIntPref("network.trr.mode", 2); // TRR-first + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns"); + test_answer="127.0.0.1"; + listen = dns.asyncResolve("bar.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} // verify basic A record - without bootstrapping -add_task(async function test1b() { +function test1b() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=3.3.3.3`); - Services.prefs.clearUserPref("network.trr.bootstrapAddress"); - Services.prefs.setCharPref("network.dns.localDomains", "foo.example.com"); - - await new DNSListener("bar.example.com", "3.3.3.3"); -}); + prefs.setIntPref("network.trr.mode", 3); // TRR-only + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns"); + prefs.clearUserPref("network.trr.bootstrapAddress"); + prefs.setCharPref("network.dns.localDomains", "foo.example.com"); + test_answer = "127.0.0.1"; + listen = dns.asyncResolve("bar.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} // verify that the name was put in cache - it works with bad DNS URI -add_task(async function test2() { +function test2() +{ // Don't clear the cache. That is what we're checking. - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/404`); - - await new DNSListener("bar.example.com", "3.3.3.3"); -}); + prefs.setIntPref("network.trr.mode", 3); // TRR-only + //prefs.clearUserPref("network.trr.bootstrapAddress"); + //prefs.setCharPref("network.dns.localDomains", "foo.example.com"); + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/404"); + test_answer = "127.0.0.1"; + listen = dns.asyncResolve("bar.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} // verify working credentials in DOH request -add_task(async function test3() { +function test3() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=4.4.4.4&auth=true`); - Services.prefs.setCharPref("network.trr.credentials", "user:password"); - - await new DNSListener("bar.example.com", "4.4.4.4"); -}); + prefs.setIntPref("network.trr.mode", 3); // TRR-only + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-auth"); + prefs.setCharPref("network.trr.credentials", "user:password"); + test_answer = "127.0.0.1"; + listen = dns.asyncResolve("bar.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} // verify failing credentials in DOH request -add_task(async function test4() { +function test4() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=4.4.4.4&auth=true`); - Services.prefs.setCharPref("network.trr.credentials", "evil:person"); - - let [, , inStatus] = await new DNSListener("wrong.example.com", undefined, false); - Assert.ok(!Components.isSuccessCode(inStatus), `${inStatus} should be an error code`); -}); + prefs.setIntPref("network.trr.mode", 3); // TRR-only + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-auth"); + prefs.setCharPref("network.trr.credentials", "evil:person"); + test_answer = "127.0.0.1"; + listen = dns.asyncResolve("wrong.example.com", 0, listenerFails, mainThread, defaultOriginAttributes); +} // verify DOH push, part A -add_task(async function test5() { +function test5() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=5.5.5.5&push=true`); + prefs.setIntPref("network.trr.mode", 3); // TRR-only + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-push"); + test_answer = "127.0.0.1"; + listen = dns.asyncResolve("first.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} - await new DNSListener("first.example.com", "5.5.5.5"); -}); - -add_task(async function test5b() { +function test5b() +{ // At this point the second host name should've been pushed and we can resolve it using // cache only. Set back the URI to a path that fails. // Don't clear the cache, otherwise we lose the pushed record. - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/404`); + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/404"); dump("test5b - resolve push.example.now please\n"); - - await new DNSListener("push.example.com", "2018::2018"); -}); + test_answer = "2018::2018"; + listen = dns.asyncResolve("push.example.com", 0, listenerUntilFine, mainThread, defaultOriginAttributes); +} // verify AAAA entry -add_task(async function test6() { +function test6() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=2020:2020::2020`); - await new DNSListener("aaaa.example.com", "2020:2020::2020"); -}); + prefs.setIntPref("network.trr.mode", 3); // TRR-only + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-aaaa"); + test_answer = "2020:2020::2020"; + listen = dns.asyncResolve("aaaa.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} // verify RFC1918 address from the server is rejected -add_task(async function test7() { +function test7() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=192.168.0.1`); - let [, , inStatus] = await new DNSListener("rfc1918.example.com", undefined, false); - Assert.ok(!Components.isSuccessCode(inStatus), `${inStatus} should be an error code`); -}); + prefs.setIntPref("network.trr.mode", 3); // TRR-only + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-rfc1918"); + listen = dns.asyncResolve("rfc1918.example.com", 0, listenerFails, mainThread, defaultOriginAttributes); +} // verify RFC1918 address from the server is fine when told so -add_task(async function test8() { +function test8() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=192.168.0.1`); - Services.prefs.setBoolPref("network.trr.allow-rfc1918", true); - await new DNSListener("rfc1918.example.com", "192.168.0.1"); -}); + prefs.setIntPref("network.trr.mode", 3); // TRR-only + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-rfc1918"); + prefs.setBoolPref("network.trr.allow-rfc1918", true); + test_answer = "192.168.0.1"; + listen = dns.asyncResolve("rfc1918.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} // use GET and disable ECS (makes a larger request) // verify URI template cutoff -add_task(async function test8b() { +function test8b() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh{?dns}`); - Services.prefs.clearUserPref("network.trr.allow-rfc1918"); - Services.prefs.setBoolPref("network.trr.useGET", true); - Services.prefs.setBoolPref("network.trr.disable-ECS", true); - await new DNSListener("ecs.example.com", "5.5.5.5"); -}); + prefs.setIntPref("network.trr.mode", 3); // TRR-only + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-ecs{?dns}"); + prefs.clearUserPref("network.trr.allow-rfc1918"); + prefs.setBoolPref("network.trr.useGET", true); + prefs.setBoolPref("network.trr.disable-ECS", true); + test_answer = "5.5.5.5"; + listen = dns.asyncResolve("ecs.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} // use GET -add_task(async function test9() { +function test9() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh`); - Services.prefs.clearUserPref("network.trr.allow-rfc1918"); - Services.prefs.setBoolPref("network.trr.useGET", true); - Services.prefs.setBoolPref("network.trr.disable-ECS", false); - await new DNSListener("get.example.com", "5.5.5.5"); -}); + prefs.setIntPref("network.trr.mode", 3); // TRR-only + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-get"); + prefs.clearUserPref("network.trr.allow-rfc1918"); + prefs.setBoolPref("network.trr.useGET", true); + prefs.setBoolPref("network.trr.disable-ECS", false); + test_answer = "1.2.3.4"; + listen = dns.asyncResolve("get.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} // confirmationNS set without confirmed NS yet // NOTE: this requires test9 to run before, as the http2 server resets state there -add_task(async function test10() { +function test10() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only - Services.prefs.clearUserPref("network.trr.useGET"); - Services.prefs.clearUserPref("network.trr.disable-ECS"); - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-confirm`); - Services.prefs.setCharPref("network.trr.confirmationNS", "confirm.example.com"); - + prefs.setIntPref("network.trr.mode", 3); // TRR-only + prefs.clearUserPref("network.trr.useGET"); + prefs.clearUserPref("network.trr.disable-ECS"); + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-confirm"); + prefs.setCharPref("network.trr.confirmationNS", "confirm.example.com"); + test_loops = 100; // set for test10b try { - let [, , inStatus] = await new DNSListener("wrong.example.com", undefined, false); - Assert.ok(!Components.isSuccessCode(inStatus), `${inStatus} should be an error code`); + listen = dns.asyncResolve("wrong.example.com", 0, listenerFails, + mainThread, defaultOriginAttributes); } catch (e) { - await new Promise(resolve => do_timeout(200, resolve)); + // NS_ERROR_UNKNOWN_HOST exception is expected + do_test_finished(); + do_timeout(200, run_dns_tests); + //run_dns_tests(); } -}); +} // confirmationNS, retry until the confirmed NS works -add_task(async function test10b() { +function test10b() +{ dns.clearCache(true); - let test_loops = 100; print("test confirmationNS, retry until the confirmed NS works"); - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only + prefs.setIntPref("network.trr.mode", 3); // TRR-only // same URI as in test10 - - // this test needs to resolve new names in every attempt since the DNS + test_answer = "1::ffff" + // this test needs to resolve new names in every attempt since the DNS cache // will keep the negative resolved info - while (test_loops > 0) { - print(`loops remaining: ${test_loops}`); - try { - let [, inRecord, inStatus] = await new DNSListener(`10b-${test_loops}.example.com`, undefined, false); - if (inRecord) { - Assert.equal(inStatus, Cr.NS_OK); - break; - } - } catch (e) { - dump(e); - } - + try { + listen = dns.asyncResolve("10b-" + test_loops + ".example.com", 0, listenerUntilFine, + mainThread, defaultOriginAttributes); + } catch(e) { + // wait a while and try again test_loops--; - await new Promise(resolve => do_timeout(0, resolve)); + do_timeout(200, test10b); } - Assert.notEqual(test_loops, 0); -}); - +} // use a slow server and short timeout! -add_task(async function test11() { +function test11() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only - Services.prefs.setCharPref("network.trr.confirmationNS", "skip"); - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-750ms`); - Services.prefs.setIntPref("network.trr.request-timeout", 10); - let [, , inStatus] = await new DNSListener("test11.example.com", undefined, false); - Assert.ok(!Components.isSuccessCode(inStatus), `${inStatus} should be an error code`); -}); + prefs.setIntPref("network.trr.mode", 3); // TRR-only + prefs.setCharPref("network.trr.confirmationNS", "skip"); + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-750ms"); + prefs.setIntPref("network.trr.request-timeout", 10); + listen = dns.asyncResolve("test11.example.com", 0, listenerFails, mainThread, defaultOriginAttributes); +} // gets an NS back from DOH -add_task(async function test12() { +function test12() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 2); // TRR-first - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-ns`); - Services.prefs.clearUserPref("network.trr.request-timeout"); - await new DNSListener("test12.example.com", "127.0.0.1"); -}); + prefs.setIntPref("network.trr.mode", 2); // TRR-first + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-ns"); + prefs.clearUserPref("network.trr.request-timeout"); + test_answer = "127.0.0.1"; + listen = dns.asyncResolve("test12.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} // TRR-first gets a 404 back from DOH -add_task(async function test13() { +function test13() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 2); // TRR-first - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/404`); - await new DNSListener("test13.example.com", "127.0.0.1"); -}); + prefs.setIntPref("network.trr.mode", 2); // TRR-first + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/404"); + test_answer = "127.0.0.1"; + listen = dns.asyncResolve("test13.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} // TRR-shadow gets a 404 back from DOH -add_task(async function test14() { +function test14() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 4); // TRR-shadow - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/404`); - await new DNSListener("test14.example.com", "127.0.0.1"); -}); + prefs.setIntPref("network.trr.mode", 4); // TRR-shadow + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/404"); + test_answer = "127.0.0.1"; + listen = dns.asyncResolve("test14.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} // TRR-shadow and timed out TRR -add_task(async function test15() { +function test15() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 4); // TRR-shadow - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-750ms`); - Services.prefs.setIntPref("network.trr.request-timeout", 10); - await new DNSListener("test15.example.com", "127.0.0.1"); -}); + prefs.setIntPref("network.trr.mode", 4); // TRR-shadow + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-750ms"); + prefs.setIntPref("network.trr.request-timeout", 10); + test_answer = "127.0.0.1"; + listen = dns.asyncResolve("test15.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} // TRR-first and timed out TRR -add_task(async function test16() { +function test16() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 2); // TRR-first - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-750ms`); - Services.prefs.setIntPref("network.trr.request-timeout", 10); - await new DNSListener("test16.example.com", "127.0.0.1"); -}); + prefs.setIntPref("network.trr.mode", 2); // TRR-first + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-750ms"); + prefs.setIntPref("network.trr.request-timeout", 10); + test_answer = "127.0.0.1"; + listen = dns.asyncResolve("test16.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} // TRR-only and chase CNAME -add_task(async function test17() { +function test17() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-cname`); - Services.prefs.clearUserPref("network.trr.request-timeout"); - await new DNSListener("cname.example.com", "99.88.77.66"); -}); + prefs.setIntPref("network.trr.mode", 3); // TRR-only + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-cname"); + prefs.clearUserPref("network.trr.request-timeout"); + test_answer = "99.88.77.66"; + listen = dns.asyncResolve("cname.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} // TRR-only and a CNAME loop -add_task(async function test18() { +function test18() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-cname-loop`); - let [, , inStatus] = await new DNSListener("test18.example.com", undefined, false); - Assert.ok(!Components.isSuccessCode(inStatus), `${inStatus} should be an error code`); -}); + prefs.setIntPref("network.trr.mode", 3); // TRR-only + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-cname-loop"); + listen = dns.asyncResolve("test18.example.com", 0, listenerFails, mainThread, defaultOriginAttributes); +} // TRR-race and a CNAME loop -add_task(async function test19() { +function test19() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 1); // Race them! - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-cname-loop`); - await new DNSListener("test19.example.com", "127.0.0.1"); -}); + prefs.setIntPref("network.trr.mode", 1); // Race them! + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-cname-loop"); + test_answer = "127.0.0.1"; + listen = dns.asyncResolve("test19.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} // TRR-first and a CNAME loop -add_task(async function test20() { +function test20() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 2); // TRR-first - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-cname-loop`); - await new DNSListener("test20.example.com", "127.0.0.1"); -}); + prefs.setIntPref("network.trr.mode", 2); // TRR-first + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-cname-loop"); + test_answer = "127.0.0.1"; + listen = dns.asyncResolve("test20.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} // TRR-shadow and a CNAME loop -add_task(async function test21() { +function test21() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 4); // shadow - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-cname-loop`); - await new DNSListener("test21.example.com", "127.0.0.1"); -}); + prefs.setIntPref("network.trr.mode", 4); // shadow + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-cname-loop"); + test_answer = "127.0.0.1"; + listen = dns.asyncResolve("test21.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} -// verify that basic A record name mismatch gets rejected. -// Gets a response for bar.example.com instead of what it requested -add_task(async function test22() { +// verify that basic A record name mismatch gets rejected. Gets the same DOH +// response back as test1 +function test22() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only to avoid native fallback - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns`); - let [, , inStatus] = await new DNSListener("mismatch.example.com", undefined, false); - Assert.ok(!Components.isSuccessCode(inStatus), `${inStatus} should be an error code`); -}); + prefs.setIntPref("network.trr.mode", 3); // TRR-only to avoid native fallback + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns"); + listen = dns.asyncResolve("mismatch.example.com", 0, listenerFails, mainThread, defaultOriginAttributes); +} // TRR-only, with a CNAME response with a bundled A record for that CNAME! -add_task(async function test23() { +function test23() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-cname-a`); - await new DNSListener("cname-a.example.com", "9.8.7.6"); -}); + prefs.setIntPref("network.trr.mode", 3); // TRR-only + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-cname-a"); + test_answer = "9.8.7.6"; + listen = dns.asyncResolve("cname-a.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} // TRR-first check that TRR result is used -add_task(async function test24() { +function test24() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 2); // TRR-first - Services.prefs.setCharPref("network.trr.excluded-domains", ""); - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=192.192.192.192`); - await new DNSListener("bar.example.com", "192.192.192.192"); -}); + prefs.setIntPref("network.trr.mode", 2); // TRR-first + prefs.setCharPref("network.trr.excluded-domains", ""); + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-ip"); + test_answer = "192.192.192.192"; + listen = dns.asyncResolve("bar.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} // TRR-first check that DNS result is used if domain is part of the excluded-domains pref -add_task(async function test24b() { +function test24b() +{ dns.clearCache(true); - Services.prefs.setCharPref("network.trr.excluded-domains", "bar.example.com"); - await new DNSListener("bar.example.com", "127.0.0.1"); -}); + prefs.setCharPref("network.trr.excluded-domains", "bar.example.com"); + test_answer = "127.0.0.1"; + listen = dns.asyncResolve("bar.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} // TRR-first check that DNS result is used if domain is part of the excluded-domains pref -add_task(async function test24c() { +function test24c() +{ dns.clearCache(true); - Services.prefs.setCharPref("network.trr.excluded-domains", "example.com"); - await new DNSListener("bar.example.com", "127.0.0.1"); -}); + prefs.setCharPref("network.trr.excluded-domains", "example.com"); + test_answer = "127.0.0.1"; + listen = dns.asyncResolve("bar.example.com", 0, listenerFine, mainThread, defaultOriginAttributes); +} -// TRR-only that resolving localhost with TRR-only mode will use the remote -// resolver if it's not in the excluded domains -add_task(async function test25() { +// TRR-only check that localhost doesn't work if not in the excluded-domains list +function test25() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only - Services.prefs.setCharPref("network.trr.excluded-domains", ""); - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=192.192.192.192`); + prefs.setIntPref("network.trr.mode", 3); // TRR-only + prefs.setCharPref("network.trr.excluded-domains", ""); + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-ip"); - await new DNSListener("localhost", "192.192.192.192", true); -}); + test_answer = "127.0.0.1"; + listen = dns.asyncResolve("localhost", 0, listenerFails, mainThread, defaultOriginAttributes); +} -// TRR-only check that localhost goes directly to native lookup when in the excluded-domains -add_task(async function test25b() { +// TRR-only check that localhost goes directly to native lookup when in the excluded-domains +function test25b() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only - Services.prefs.setCharPref("network.trr.excluded-domains", "localhost"); - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=192.192.192.192`); + prefs.setIntPref("network.trr.mode", 3); // TRR-only + prefs.setCharPref("network.trr.excluded-domains", "localhost"); + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-ip"); - await new DNSListener("localhost", "127.0.0.1"); -}); + test_answer = "127.0.0.1"; + listen = dns.asyncResolve("localhost", 0, listenerFine, mainThread, defaultOriginAttributes); +} // TRR-only check that test.local is resolved via native DNS -add_task(async function test25c() { +function test25c() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only - Services.prefs.setCharPref("network.trr.excluded-domains", "localhost,local"); - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=192.192.192.192`); + prefs.setIntPref("network.trr.mode", 3); // TRR-only + prefs.setCharPref("network.trr.excluded-domains", "localhost,local"); + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-ip"); - await new DNSListener("test.local", "127.0.0.1"); -}); + test_answer = "127.0.0.1"; + listen = dns.asyncResolve("test.local", 0, listenerFine, mainThread, defaultOriginAttributes); +} -// TRR-only check that .other is resolved via native DNS when the pref is set -add_task(async function test25d() { +function test25d() +{ dns.clearCache(true); - Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only - Services.prefs.setCharPref("network.trr.excluded-domains", "localhost,local,other"); - Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=192.192.192.192`); + prefs.setIntPref("network.trr.mode", 3); // TRR-only + prefs.setCharPref("network.trr.excluded-domains", "localhost,local,other"); + prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-ip"); - await new DNSListener("domain.other", "127.0.0.1"); -}); + test_answer = "127.0.0.1"; + listen = dns.asyncResolve("domain.other", 0, listenerFine, mainThread, defaultOriginAttributes); +} + +var tests = [ test1, + test1b, + test2, + test3, + test4, + test5, + test5b, + test6, + test7, + test8, + test8b, + test9, + test10, + test10b, + test11, + test12, + test13, + test14, + test15, + test16, + test17, + test18, + test19, + test20, + test21, + test22, + test23, + test24, + test24b, + test24c, + test25, + test25b, + test25c, + test25d, + testsDone + ]; + +var current_test = 0; + +function run_dns_tests() +{ + if (current_test < tests.length) { + dump(`starting test ${tests[current_test].name}`); + do_test_pending(); + tests[current_test++](); + } +} diff --git a/testing/xpcshell/dns-packet/.editorconfig b/testing/xpcshell/dns-packet/.editorconfig deleted file mode 100644 index aaaa7a4baa81..000000000000 --- a/testing/xpcshell/dns-packet/.editorconfig +++ /dev/null @@ -1,10 +0,0 @@ -root = true - -[*] -indent_style = space -indent_size = 2 -tab_width = 2 -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true diff --git a/testing/xpcshell/dns-packet/.eslintrc b/testing/xpcshell/dns-packet/.eslintrc deleted file mode 100644 index d3ed05cf8665..000000000000 --- a/testing/xpcshell/dns-packet/.eslintrc +++ /dev/null @@ -1,9 +0,0 @@ -root: true - -parserOptions: - ecmaVersion: 2015 - -env: - node: true - -extends: standard diff --git a/testing/xpcshell/dns-packet/.gitignore b/testing/xpcshell/dns-packet/.gitignore deleted file mode 100644 index cea4849cd9b1..000000000000 --- a/testing/xpcshell/dns-packet/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -node_modules/ -.nyc_output/ -coverage/ -package-lock.json diff --git a/testing/xpcshell/dns-packet/.travis.yml b/testing/xpcshell/dns-packet/.travis.yml deleted file mode 100644 index e0211604d30b..000000000000 --- a/testing/xpcshell/dns-packet/.travis.yml +++ /dev/null @@ -1,11 +0,0 @@ -language: node_js -node_js: - - node - - lts/* -install: -- npm install -- npm install coveralls -script: -- npm run coverage -after_success: -- npx nyc report --reporter=text-lcov | npx coveralls diff --git a/testing/xpcshell/dns-packet/CHANGELOG.md b/testing/xpcshell/dns-packet/CHANGELOG.md deleted file mode 100644 index 6b714e04c9b1..000000000000 --- a/testing/xpcshell/dns-packet/CHANGELOG.md +++ /dev/null @@ -1,30 +0,0 @@ -# Version 5.2.0 - 2019-02-21 - -- Feature: Added support for de/encoding certain OPT options. - -# Version 5.1.0 - 2019-01-22 - -- Feature: Added support for the RP record type. - -# Version 5.0.0 - 2018-06-01 - -- Breaking: Node.js 6.0.0 or greater is now required. -- Feature: Added support for DNSSEC record types. - -# Version 4.1.0 - 2018-02-11 - -- Feature: Added support for the MX record type. - -# Version 4.0.0 - 2018-02-04 - -- Feature: Added `streamEncode` and `streamDecode` methods for encoding TCP packets. -- Breaking: Changed the decoded value of TXT records to an array of Buffers. This is to accomodate DNS-SD records which rely on the individual strings record being separated. -- Breaking: Renamed the `flag_trunc` and `flag_auth` to `flag_tc` and `flag_aa` to match the names of these in the dns standards. - -# Version 3.0.0 - 2018-01-12 - -- Breaking: The `class` option has been changed from integer to string. - -# Version 2.0.0 - 2018-01-11 - -- Breaking: Converted module to ES2015, now requires Node.js 4.0 or greater diff --git a/testing/xpcshell/dns-packet/LICENSE b/testing/xpcshell/dns-packet/LICENSE deleted file mode 100644 index bae9da7bfae2..000000000000 --- a/testing/xpcshell/dns-packet/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 Mathias Buus - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/testing/xpcshell/dns-packet/README.md b/testing/xpcshell/dns-packet/README.md deleted file mode 100644 index 2a729b3d1074..000000000000 --- a/testing/xpcshell/dns-packet/README.md +++ /dev/null @@ -1,365 +0,0 @@ -# dns-packet -[![](https://img.shields.io/npm/v/dns-packet.svg?style=flat)](https://www.npmjs.org/package/dns-packet) [![](https://img.shields.io/npm/dm/dns-packet.svg)](https://www.npmjs.org/package/dns-packet) [![](https://api.travis-ci.org/mafintosh/dns-packet.svg?style=flat)](https://travis-ci.org/mafintosh/dns-packet) [![Coverage Status](https://coveralls.io/repos/github/mafintosh/dns-packet/badge.svg?branch=master)](https://coveralls.io/github/mafintosh/dns-packet?branch=master) - -An [abstract-encoding](https://github.com/mafintosh/abstract-encoding) compliant module for encoding / decoding DNS packets. Lifted out of [multicast-dns](https://github.com/mafintosh/multicast-dns) as a separate module. - -``` -npm install dns-packet -``` - -## UDP Usage - -``` js -const dnsPacket = require('dns-packet') -const dgram = require('dgram') - -const socket = dgram.createSocket('udp4') - -const buf = dnsPacket.encode({ - type: 'query', - id: 1, - flags: dnsPacket.RECURSION_DESIRED, - questions: [{ - type: 'A', - name: 'google.com' - }] -}) - -socket.on('message', message => { - console.log(dnsPacket.decode(message)) // prints out a response from google dns -}) - -socket.send(buf, 0, buf.length, 53, '8.8.8.8') -``` - -Also see [the UDP example](examples/udp.js). - -## TCP, TLS, HTTPS - -While DNS has traditionally been used over a datagram transport, it is increasingly being carried over TCP for larger responses commonly including DNSSEC responses and TLS or HTTPS for enhanced security. See below examples on how to use `dns-packet` to wrap DNS packets in these protocols: - -- [TCP](examples/tcp.js) -- [DNS over TLS](examples/tls.js) -- [DNS over HTTPS](examples/doh.js) - -## API - -#### `var buf = packets.encode(packet, [buf], [offset])` - -Encodes a DNS packet into a buffer containing a UDP payload. - -#### `var packet = packets.decode(buf, [offset])` - -Decode a DNS packet from a buffer containing a UDP payload. - -#### `var buf = packets.streamEncode(packet, [buf], [offset])` - -Encodes a DNS packet into a buffer containing a TCP payload. - -#### `var packet = packets.streamDecode(buf, [offset])` - -Decode a DNS packet from a buffer containing a TCP payload. - -#### `var len = packets.encodingLength(packet)` - -Returns how many bytes are needed to encode the DNS packet - -## Packets - -Packets look like this - -``` js -{ - type: 'query|response', - id: optionalIdNumber, - flags: optionalBitFlags, - questions: [...], - answers: [...], - additionals: [...], - authorities: [...] -} -``` - -The bit flags available are - -``` js -packet.RECURSION_DESIRED -packet.RECURSION_AVAILABLE -packet.TRUNCATED_RESPONSE -packet.AUTHORITATIVE_ANSWER -packet.AUTHENTIC_DATA -packet.CHECKING_DISABLED -``` - -To use more than one flag bitwise-or them together - -``` js -var flags = packet.RECURSION_DESIRED | packet.RECURSION_AVAILABLE -``` - -And to check for a flag use bitwise-and - -``` js -var isRecursive = message.flags & packet.RECURSION_DESIRED -``` - -A question looks like this - -``` js -{ - type: 'A', // or SRV, AAAA, etc - class: 'IN', // one of IN, CS, CH, HS, ANY. Default: IN - name: 'google.com' // which record are you looking for -} -``` - -And an answer, additional, or authority looks like this - -``` js -{ - type: 'A', // or SRV, AAAA, etc - class: 'IN', // one of IN, CS, CH, HS - name: 'google.com', // which name is this record for - ttl: optionalTimeToLiveInSeconds, - (record specific data, see below) -} -``` - -## Supported record types - -#### `A` - -``` js -{ - data: 'IPv4 address' // fx 127.0.0.1 -} -``` - -#### `AAAA` - -``` js -{ - data: 'IPv6 address' // fx fe80::1 -} -``` - -#### `CAA` - -``` js -{ - flags: 128, // octet - tag: 'issue|issuewild|iodef', - value: 'ca.example.net', - issuerCritical: false -} -``` - -#### `CNAME` - -``` js -{ - data: 'cname.to.another.record' -} -``` - -#### `DNAME` - -``` js -{ - data: 'dname.to.another.record' -} -``` - -#### `DNSKEY` - -``` js -{ - flags: 257, // 16 bits - algorithm: 1, // octet - key: Buffer -} -``` - -#### `DS` - -``` js -{ - keyTag: 12345, - algorithm: 8, - digestType: 1, - digest: Buffer -} -``` - -#### `HINFO` - -``` js -{ - data: { - cpu: 'cpu info', - os: 'os info' - } -} -``` - -#### `MX` - -``` js -{ - preference: 10, - exchange: 'mail.example.net' -} -``` - -#### `NS` - -``` js -{ - data: nameServer -} -``` - -#### `NSEC` - -``` js -{ - nextDomain: 'a.domain', - rrtypes: ['A', 'TXT', 'RRSIG'] -} -``` - -#### `NSEC3` - -``` js -{ - algorithm: 1, - flags: 0, - iterations: 2, - salt: Buffer, - nextDomain: Buffer, // Hashed per RFC5155 - rrtypes: ['A', 'TXT', 'RRSIG'] -} -``` - -#### `NULL` - -``` js -{ - data: Buffer('any binary data') -} -``` - -#### `OPT` - -[EDNS0](https://tools.ietf.org/html/rfc6891) options. - -``` js -{ - type: 'OPT', - name: '.', - udpPayloadSize: 4096, - flags: packet.DNSSEC_OK, - options: [{ - // pass in any code/data for generic EDNS0 options - code: 12, - data: Buffer.alloc(31) - }, { - // Several EDNS0 options have enhanced support - code: 'PADDING', - length: 31, - }, { - code: 'CLIENT_SUBNET', - family: 2, // 1 for IPv4, 2 for IPv6 - sourcePrefixLength: 64, // used to truncate IP address - scopePrefixLength: 0, - ip: 'fe80::', - }, { - code: 'TCP_KEEPALIVE', - timeout: 150 // increments of 100ms. This means 15s. - }, { - code: 'KEY_TAG', - tags: [1, 2, 3], - }] -} -``` - -The options `PADDING`, `CLIENT_SUBNET`, `TCP_KEEPALIVE` and `KEY_TAG` support enhanced de/encoding. See [optionscodes.js](https://github.com/mafintosh/dns-packet/blob/master/optioncodes.js) for all supported option codes. If the `data` property is present on a option, it takes precedence. On decoding, `data` will always be defined. - -#### `PTR` - -``` js -{ - data: 'points.to.another.record' -} -``` - -#### `RP` - -``` js -{ - mbox: 'admin.example.com', - txt: 'txt.example.com' -} -``` - -#### `RRSIG` - -``` js -{ - typeCovered: 'A', - algorithm: 8, - labels: 1, - originalTTL: 3600, - expiration: timestamp, - inception: timestamp, - keyTag: 12345, - signersName: 'a.name', - signature: Buffer -} -``` - -#### `SOA` - -``` js -{ - data: - { - mname: domainName, - rname: mailbox, - serial: zoneSerial, - refresh: refreshInterval, - retry: retryInterval, - expire: expireInterval, - minimum: minimumTTL - } -} -``` - -#### `SRV` - -``` js -{ - data: { - port: servicePort, - target: serviceHostName, - priority: optionalServicePriority, - weight: optionalServiceWeight - } -} -``` - -#### `TXT` - -``` js -{ - data: 'text' || Buffer || [ Buffer || 'text' ] -} -``` - -When encoding, scalar values are converted to an array and strings are converted to UTF-8 encoded Buffers. When decoding, the return value will always be an array of Buffer. - -If you need another record type, open an issue and we'll try to add it. - -## License - -MIT diff --git a/testing/xpcshell/dns-packet/classes.js b/testing/xpcshell/dns-packet/classes.js deleted file mode 100644 index 9a3d9b1e8c77..000000000000 --- a/testing/xpcshell/dns-packet/classes.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict' - -exports.toString = function (klass) { - switch (klass) { - case 1: return 'IN' - case 2: return 'CS' - case 3: return 'CH' - case 4: return 'HS' - case 255: return 'ANY' - } - return 'UNKNOWN_' + klass -} - -exports.toClass = function (name) { - switch (name.toUpperCase()) { - case 'IN': return 1 - case 'CS': return 2 - case 'CH': return 3 - case 'HS': return 4 - case 'ANY': return 255 - } - return 0 -} diff --git a/testing/xpcshell/dns-packet/examples/doh.js b/testing/xpcshell/dns-packet/examples/doh.js deleted file mode 100644 index 37ef19fc3524..000000000000 --- a/testing/xpcshell/dns-packet/examples/doh.js +++ /dev/null @@ -1,52 +0,0 @@ - -'use strict' - -/* - * Sample code to make DNS over HTTPS request using POST - * AUTHOR: Tom Pusateri - * DATE: March 17, 2018 - * LICENSE: MIT - */ - -const dnsPacket = require('..') -const https = require('https') - -function getRandomInt (min, max) { - return Math.floor(Math.random() * (max - min + 1)) + min -} - -const buf = dnsPacket.encode({ - type: 'query', - id: getRandomInt(1, 65534), - flags: dnsPacket.RECURSION_DESIRED, - questions: [{ - type: 'A', - name: 'google.com' - }] -}) - -const options = { - hostname: 'dns.google.com', - port: 443, - path: '/experimental', - method: 'POST', - headers: { - 'Content-Type': 'application/dns-udpwireformat', - 'Content-Length': Buffer.byteLength(buf) - } -} - -const request = https.request(options, (response) => { - console.log('statusCode:', response.statusCode) - console.log('headers:', response.headers) - - response.on('data', (d) => { - console.log(dnsPacket.decode(d)) - }) -}) - -request.on('error', (e) => { - console.error(e) -}) -request.write(buf) -request.end() diff --git a/testing/xpcshell/dns-packet/examples/tcp.js b/testing/xpcshell/dns-packet/examples/tcp.js deleted file mode 100644 index b25c2c41cbb0..000000000000 --- a/testing/xpcshell/dns-packet/examples/tcp.js +++ /dev/null @@ -1,52 +0,0 @@ -'use strict' - -const dnsPacket = require('..') -const net = require('net') - -var response = null -var expectedLength = 0 - -function getRandomInt (min, max) { - return Math.floor(Math.random() * (max - min + 1)) + min -} - -const buf = dnsPacket.streamEncode({ - type: 'query', - id: getRandomInt(1, 65534), - flags: dnsPacket.RECURSION_DESIRED, - questions: [{ - type: 'A', - name: 'google.com' - }] -}) - -const client = new net.Socket() -client.connect(53, '8.8.8.8', function () { - console.log('Connected') - client.write(buf) -}) - -client.on('data', function (data) { - console.log('Received response: %d bytes', data.byteLength) - if (response == null) { - if (data.byteLength > 1) { - const plen = data.readUInt16BE(0) - expectedLength = plen - if (plen < 12) { - throw new Error('below DNS minimum packet length') - } - response = Buffer.from(data) - } - } else { - response = Buffer.concat([response, data]) - } - - if (response.byteLength >= expectedLength) { - console.log(dnsPacket.streamDecode(response)) - client.destroy() - } -}) - -client.on('close', function () { - console.log('Connection closed') -}) diff --git a/testing/xpcshell/dns-packet/examples/tls.js b/testing/xpcshell/dns-packet/examples/tls.js deleted file mode 100644 index 694a4fecfa75..000000000000 --- a/testing/xpcshell/dns-packet/examples/tls.js +++ /dev/null @@ -1,61 +0,0 @@ -'use strict' - -const tls = require('tls') -const dnsPacket = require('..') - -var response = null -var expectedLength = 0 - -function getRandomInt (min, max) { - return Math.floor(Math.random() * (max - min + 1)) + min -} - -const buf = dnsPacket.streamEncode({ - type: 'query', - id: getRandomInt(1, 65534), - flags: dnsPacket.RECURSION_DESIRED, - questions: [{ - type: 'A', - name: 'google.com' - }] -}) - -const context = tls.createSecureContext({ - secureProtocol: 'TLSv1_2_method' -}) - -const options = { - port: 853, - host: 'getdnsapi.net', - secureContext: context -} - -const client = tls.connect(options, () => { - console.log('client connected') - client.write(buf) -}) - -client.on('data', function (data) { - console.log('Received response: %d bytes', data.byteLength) - if (response == null) { - if (data.byteLength > 1) { - const plen = data.readUInt16BE(0) - expectedLength = plen - if (plen < 12) { - throw new Error('below DNS minimum packet length') - } - response = Buffer.from(data) - } - } else { - response = Buffer.concat([response, data]) - } - - if (response.byteLength >= expectedLength) { - console.log(dnsPacket.streamDecode(response)) - client.destroy() - } -}) - -client.on('end', () => { - console.log('Connection ended') -}) diff --git a/testing/xpcshell/dns-packet/examples/udp.js b/testing/xpcshell/dns-packet/examples/udp.js deleted file mode 100644 index 0f9df9d794d4..000000000000 --- a/testing/xpcshell/dns-packet/examples/udp.js +++ /dev/null @@ -1,28 +0,0 @@ -'use strict' - -const dnsPacket = require('..') -const dgram = require('dgram') - -const socket = dgram.createSocket('udp4') - -function getRandomInt (min, max) { - return Math.floor(Math.random() * (max - min + 1)) + min -} - -const buf = dnsPacket.encode({ - type: 'query', - id: getRandomInt(1, 65534), - flags: dnsPacket.RECURSION_DESIRED, - questions: [{ - type: 'A', - name: 'google.com' - }] -}) - -socket.on('message', function (message, rinfo) { - console.log(rinfo) - console.log(dnsPacket.decode(message)) // prints out a response from google dns - socket.close() -}) - -socket.send(buf, 0, buf.length, 53, '8.8.8.8') diff --git a/testing/xpcshell/dns-packet/index.js b/testing/xpcshell/dns-packet/index.js deleted file mode 100644 index c7592f08c1a5..000000000000 --- a/testing/xpcshell/dns-packet/index.js +++ /dev/null @@ -1,1541 +0,0 @@ -'use strict' - -const types = require('./types') -const rcodes = require('./rcodes') -const opcodes = require('./opcodes') -const classes = require('./classes') -const optioncodes = require('./optioncodes') -const ip = require('../node-ip') - -const QUERY_FLAG = 0 -const RESPONSE_FLAG = 1 << 15 -const FLUSH_MASK = 1 << 15 -const NOT_FLUSH_MASK = ~FLUSH_MASK -const QU_MASK = 1 << 15 -const NOT_QU_MASK = ~QU_MASK - -const name = exports.txt = exports.name = {} - -name.encode = function (str, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(name.encodingLength(str)) - if (!offset) offset = 0 - const oldOffset = offset - - // strip leading and trailing . - const n = str.replace(/^\.|\.$/gm, '') - if (n.length) { - const list = n.split('.') - - for (let i = 0; i < list.length; i++) { - const len = buf.write(list[i], offset + 1) - buf[offset] = len - offset += len + 1 - } - } - - buf[offset++] = 0 - - name.encode.bytes = offset - oldOffset - return buf -} - -name.encode.bytes = 0 - -name.decode = function (buf, offset) { - if (!offset) offset = 0 - - const list = [] - const oldOffset = offset - let len = buf[offset++] - - if (len === 0) { - name.decode.bytes = 1 - return '.' - } - if (len >= 0xc0) { - const res = name.decode(buf, buf.readUInt16BE(offset - 1) - 0xc000) - name.decode.bytes = 2 - return res - } - - while (len) { - if (len >= 0xc0) { - list.push(name.decode(buf, buf.readUInt16BE(offset - 1) - 0xc000)) - offset++ - break - } - - list.push(buf.toString('utf-8', offset, offset + len)) - offset += len - len = buf[offset++] - } - - name.decode.bytes = offset - oldOffset - return list.join('.') -} - -name.decode.bytes = 0 - -name.encodingLength = function (n) { - if (n === '.') return 1 - return Buffer.byteLength(n) + 2 -} - -const string = {} - -string.encode = function (s, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(string.encodingLength(s)) - if (!offset) offset = 0 - - const len = buf.write(s, offset + 1) - buf[offset] = len - string.encode.bytes = len + 1 - return buf -} - -string.encode.bytes = 0 - -string.decode = function (buf, offset) { - if (!offset) offset = 0 - - const len = buf[offset] - const s = buf.toString('utf-8', offset + 1, offset + 1 + len) - string.decode.bytes = len + 1 - return s -} - -string.decode.bytes = 0 - -string.encodingLength = function (s) { - return Buffer.byteLength(s) + 1 -} - -const header = {} - -header.encode = function (h, buf, offset) { - if (!buf) buf = header.encodingLength(h) - if (!offset) offset = 0 - - const flags = (h.flags || 0) & 32767 - const type = h.type === 'response' ? RESPONSE_FLAG : QUERY_FLAG - - buf.writeUInt16BE(h.id || 0, offset) - buf.writeUInt16BE(flags | type, offset + 2) - buf.writeUInt16BE(h.questions.length, offset + 4) - buf.writeUInt16BE(h.answers.length, offset + 6) - buf.writeUInt16BE(h.authorities.length, offset + 8) - buf.writeUInt16BE(h.additionals.length, offset + 10) - - return buf -} - -header.encode.bytes = 12 - -header.decode = function (buf, offset) { - if (!offset) offset = 0 - if (buf.length < 12) throw new Error('Header must be 12 bytes') - const flags = buf.readUInt16BE(offset + 2) - - return { - id: buf.readUInt16BE(offset), - type: flags & RESPONSE_FLAG ? 'response' : 'query', - flags: flags & 32767, - flag_qr: ((flags >> 15) & 0x1) === 1, - opcode: opcodes.toString((flags >> 11) & 0xf), - flag_aa: ((flags >> 10) & 0x1) === 1, - flag_tc: ((flags >> 9) & 0x1) === 1, - flag_rd: ((flags >> 8) & 0x1) === 1, - flag_ra: ((flags >> 7) & 0x1) === 1, - flag_z: ((flags >> 6) & 0x1) === 1, - flag_ad: ((flags >> 5) & 0x1) === 1, - flag_cd: ((flags >> 4) & 0x1) === 1, - rcode: rcodes.toString(flags & 0xf), - questions: new Array(buf.readUInt16BE(offset + 4)), - answers: new Array(buf.readUInt16BE(offset + 6)), - authorities: new Array(buf.readUInt16BE(offset + 8)), - additionals: new Array(buf.readUInt16BE(offset + 10)) - } -} - -header.decode.bytes = 12 - -header.encodingLength = function () { - return 12 -} - -const runknown = exports.unknown = {} - -runknown.encode = function (data, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(runknown.encodingLength(data)) - if (!offset) offset = 0 - - buf.writeUInt16BE(data.length, offset) - data.copy(buf, offset + 2) - - runknown.encode.bytes = data.length + 2 - return buf -} - -runknown.encode.bytes = 0 - -runknown.decode = function (buf, offset) { - if (!offset) offset = 0 - - const len = buf.readUInt16BE(offset) - const data = buf.slice(offset + 2, offset + 2 + len) - runknown.decode.bytes = len + 2 - return data -} - -runknown.decode.bytes = 0 - -runknown.encodingLength = function (data) { - return data.length + 2 -} - -const rns = exports.ns = {} - -rns.encode = function (data, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(rns.encodingLength(data)) - if (!offset) offset = 0 - - name.encode(data, buf, offset + 2) - buf.writeUInt16BE(name.encode.bytes, offset) - rns.encode.bytes = name.encode.bytes + 2 - return buf -} - -rns.encode.bytes = 0 - -rns.decode = function (buf, offset) { - if (!offset) offset = 0 - - const len = buf.readUInt16BE(offset) - const dd = name.decode(buf, offset + 2) - - rns.decode.bytes = len + 2 - return dd -} - -rns.decode.bytes = 0 - -rns.encodingLength = function (data) { - return name.encodingLength(data) + 2 -} - -const rsoa = exports.soa = {} - -rsoa.encode = function (data, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(rsoa.encodingLength(data)) - if (!offset) offset = 0 - - const oldOffset = offset - offset += 2 - name.encode(data.mname, buf, offset) - offset += name.encode.bytes - name.encode(data.rname, buf, offset) - offset += name.encode.bytes - buf.writeUInt32BE(data.serial || 0, offset) - offset += 4 - buf.writeUInt32BE(data.refresh || 0, offset) - offset += 4 - buf.writeUInt32BE(data.retry || 0, offset) - offset += 4 - buf.writeUInt32BE(data.expire || 0, offset) - offset += 4 - buf.writeUInt32BE(data.minimum || 0, offset) - offset += 4 - - buf.writeUInt16BE(offset - oldOffset - 2, oldOffset) - rsoa.encode.bytes = offset - oldOffset - return buf -} - -rsoa.encode.bytes = 0 - -rsoa.decode = function (buf, offset) { - if (!offset) offset = 0 - - const oldOffset = offset - - const data = {} - offset += 2 - data.mname = name.decode(buf, offset) - offset += name.decode.bytes - data.rname = name.decode(buf, offset) - offset += name.decode.bytes - data.serial = buf.readUInt32BE(offset) - offset += 4 - data.refresh = buf.readUInt32BE(offset) - offset += 4 - data.retry = buf.readUInt32BE(offset) - offset += 4 - data.expire = buf.readUInt32BE(offset) - offset += 4 - data.minimum = buf.readUInt32BE(offset) - offset += 4 - - rsoa.decode.bytes = offset - oldOffset - return data -} - -rsoa.decode.bytes = 0 - -rsoa.encodingLength = function (data) { - return 22 + name.encodingLength(data.mname) + name.encodingLength(data.rname) -} - -const rtxt = exports.txt = {} - -rtxt.encode = function (data, buf, offset) { - if (!Array.isArray(data)) data = [data] - for (let i = 0; i < data.length; i++) { - if (typeof data[i] === 'string') { - data[i] = Buffer.from(data[i]) - } - if (!Buffer.isBuffer(data[i])) { - throw new Error('Must be a Buffer') - } - } - - if (!buf) buf = Buffer.allocUnsafe(rtxt.encodingLength(data)) - if (!offset) offset = 0 - - const oldOffset = offset - offset += 2 - - data.forEach(function (d) { - buf[offset++] = d.length - d.copy(buf, offset, 0, d.length) - offset += d.length - }) - - buf.writeUInt16BE(offset - oldOffset - 2, oldOffset) - rtxt.encode.bytes = offset - oldOffset - return buf -} - -rtxt.encode.bytes = 0 - -rtxt.decode = function (buf, offset) { - if (!offset) offset = 0 - const oldOffset = offset - let remaining = buf.readUInt16BE(offset) - offset += 2 - - let data = [] - while (remaining > 0) { - const len = buf[offset++] - --remaining - if (remaining < len) { - throw new Error('Buffer overflow') - } - data.push(buf.slice(offset, offset + len)) - offset += len - remaining -= len - } - - rtxt.decode.bytes = offset - oldOffset - return data -} - -rtxt.decode.bytes = 0 - -rtxt.encodingLength = function (data) { - if (!Array.isArray(data)) data = [data] - let length = 2 - data.forEach(function (buf) { - if (typeof buf === 'string') { - length += Buffer.byteLength(buf) + 1 - } else { - length += buf.length + 1 - } - }) - return length -} - -const rnull = exports.null = {} - -rnull.encode = function (data, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(rnull.encodingLength(data)) - if (!offset) offset = 0 - - if (typeof data === 'string') data = Buffer.from(data) - if (!data) data = Buffer.allocUnsafe(0) - - const oldOffset = offset - offset += 2 - - const len = data.length - data.copy(buf, offset, 0, len) - offset += len - - buf.writeUInt16BE(offset - oldOffset - 2, oldOffset) - rnull.encode.bytes = offset - oldOffset - return buf -} - -rnull.encode.bytes = 0 - -rnull.decode = function (buf, offset) { - if (!offset) offset = 0 - const oldOffset = offset - const len = buf.readUInt16BE(offset) - - offset += 2 - - const data = buf.slice(offset, offset + len) - offset += len - - rnull.decode.bytes = offset - oldOffset - return data -} - -rnull.decode.bytes = 0 - -rnull.encodingLength = function (data) { - if (!data) return 2 - return (Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data)) + 2 -} - -const rhinfo = exports.hinfo = {} - -rhinfo.encode = function (data, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(rhinfo.encodingLength(data)) - if (!offset) offset = 0 - - const oldOffset = offset - offset += 2 - string.encode(data.cpu, buf, offset) - offset += string.encode.bytes - string.encode(data.os, buf, offset) - offset += string.encode.bytes - buf.writeUInt16BE(offset - oldOffset - 2, oldOffset) - rhinfo.encode.bytes = offset - oldOffset - return buf -} - -rhinfo.encode.bytes = 0 - -rhinfo.decode = function (buf, offset) { - if (!offset) offset = 0 - - const oldOffset = offset - - const data = {} - offset += 2 - data.cpu = string.decode(buf, offset) - offset += string.decode.bytes - data.os = string.decode(buf, offset) - offset += string.decode.bytes - rhinfo.decode.bytes = offset - oldOffset - return data -} - -rhinfo.decode.bytes = 0 - -rhinfo.encodingLength = function (data) { - return string.encodingLength(data.cpu) + string.encodingLength(data.os) + 2 -} - -const rptr = exports.ptr = {} -const rcname = exports.cname = rptr -const rdname = exports.dname = rptr - -rptr.encode = function (data, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(rptr.encodingLength(data)) - if (!offset) offset = 0 - - name.encode(data, buf, offset + 2) - buf.writeUInt16BE(name.encode.bytes, offset) - rptr.encode.bytes = name.encode.bytes + 2 - return buf -} - -rptr.encode.bytes = 0 - -rptr.decode = function (buf, offset) { - if (!offset) offset = 0 - - const data = name.decode(buf, offset + 2) - rptr.decode.bytes = name.decode.bytes + 2 - return data -} - -rptr.decode.bytes = 0 - -rptr.encodingLength = function (data) { - return name.encodingLength(data) + 2 -} - -const rsrv = exports.srv = {} - -rsrv.encode = function (data, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(rsrv.encodingLength(data)) - if (!offset) offset = 0 - - buf.writeUInt16BE(data.priority || 0, offset + 2) - buf.writeUInt16BE(data.weight || 0, offset + 4) - buf.writeUInt16BE(data.port || 0, offset + 6) - name.encode(data.target, buf, offset + 8) - - const len = name.encode.bytes + 6 - buf.writeUInt16BE(len, offset) - - rsrv.encode.bytes = len + 2 - return buf -} - -rsrv.encode.bytes = 0 - -rsrv.decode = function (buf, offset) { - if (!offset) offset = 0 - - const len = buf.readUInt16BE(offset) - - const data = {} - data.priority = buf.readUInt16BE(offset + 2) - data.weight = buf.readUInt16BE(offset + 4) - data.port = buf.readUInt16BE(offset + 6) - data.target = name.decode(buf, offset + 8) - - rsrv.decode.bytes = len + 2 - return data -} - -rsrv.decode.bytes = 0 - -rsrv.encodingLength = function (data) { - return 8 + name.encodingLength(data.target) -} - -const rcaa = exports.caa = {} - -rcaa.ISSUER_CRITICAL = 1 << 7 - -rcaa.encode = function (data, buf, offset) { - const len = rcaa.encodingLength(data) - - if (!buf) buf = Buffer.allocUnsafe(rcaa.encodingLength(data)) - if (!offset) offset = 0 - - if (data.issuerCritical) { - data.flags = rcaa.ISSUER_CRITICAL - } - - buf.writeUInt16BE(len - 2, offset) - offset += 2 - buf.writeUInt8(data.flags || 0, offset) - offset += 1 - string.encode(data.tag, buf, offset) - offset += string.encode.bytes - buf.write(data.value, offset) - offset += Buffer.byteLength(data.value) - - rcaa.encode.bytes = len - return buf -} - -rcaa.encode.bytes = 0 - -rcaa.decode = function (buf, offset) { - if (!offset) offset = 0 - - const len = buf.readUInt16BE(offset) - offset += 2 - - const oldOffset = offset - const data = {} - data.flags = buf.readUInt8(offset) - offset += 1 - data.tag = string.decode(buf, offset) - offset += string.decode.bytes - data.value = buf.toString('utf-8', offset, oldOffset + len) - - data.issuerCritical = !!(data.flags & rcaa.ISSUER_CRITICAL) - - rcaa.decode.bytes = len + 2 - - return data -} - -rcaa.decode.bytes = 0 - -rcaa.encodingLength = function (data) { - return string.encodingLength(data.tag) + string.encodingLength(data.value) + 2 -} - -const rmx = exports.mx = {} - -rmx.encode = function (data, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(rmx.encodingLength(data)) - if (!offset) offset = 0 - - const oldOffset = offset - offset += 2 - buf.writeUInt16BE(data.preference || 0, offset) - offset += 2 - name.encode(data.exchange, buf, offset) - offset += name.encode.bytes - - buf.writeUInt16BE(offset - oldOffset - 2, oldOffset) - rmx.encode.bytes = offset - oldOffset - return buf -} - -rmx.encode.bytes = 0 - -rmx.decode = function (buf, offset) { - if (!offset) offset = 0 - - const oldOffset = offset - - const data = {} - offset += 2 - data.preference = buf.readUInt16BE(offset) - offset += 2 - data.exchange = name.decode(buf, offset) - offset += name.decode.bytes - - rmx.decode.bytes = offset - oldOffset - return data -} - -rmx.encodingLength = function (data) { - return 4 + name.encodingLength(data.exchange) -} - -const ra = exports.a = {} - -ra.encode = function (host, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(ra.encodingLength(host)) - if (!offset) offset = 0 - - buf.writeUInt16BE(4, offset) - offset += 2 - ip.toBuffer(host, buf, offset) - ra.encode.bytes = 6 - return buf -} - -ra.encode.bytes = 0 - -ra.decode = function (buf, offset) { - if (!offset) offset = 0 - - offset += 2 - const host = ip.toString(buf, offset, 4) - ra.decode.bytes = 6 - return host -} - -ra.decode.bytes = 0 - -ra.encodingLength = function () { - return 6 -} - -const raaaa = exports.aaaa = {} - -raaaa.encode = function (host, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(raaaa.encodingLength(host)) - if (!offset) offset = 0 - - buf.writeUInt16BE(16, offset) - offset += 2 - ip.toBuffer(host, buf, offset) - raaaa.encode.bytes = 18 - return buf -} - -raaaa.encode.bytes = 0 - -raaaa.decode = function (buf, offset) { - if (!offset) offset = 0 - - offset += 2 - const host = ip.toString(buf, offset, 16) - raaaa.decode.bytes = 18 - return host -} - -raaaa.decode.bytes = 0 - -raaaa.encodingLength = function () { - return 18 -} - -const roption = exports.option = {} - -roption.encode = function (option, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(roption.encodingLength(option)) - if (!offset) offset = 0 - const oldOffset = offset - - const code = optioncodes.toCode(option.code) - buf.writeUInt16BE(code, offset) - offset += 2 - if (option.data) { - buf.writeUInt16BE(option.data.length, offset) - offset += 2 - option.data.copy(buf, offset) - offset += option.data.length - } else { - switch (code) { - // case 3: NSID. No encode makes sense. - // case 5,6,7: Not implementable - case 8: // ECS - // note: do IP math before calling - const spl = option.sourcePrefixLength || 0 - const fam = option.family || (ip.isV4Format(option.ip) ? 1 : 2) - const ipBuf = ip.toBuffer(option.ip) - const ipLen = Math.ceil(spl / 8) - buf.writeUInt16BE(ipLen + 4, offset) - offset += 2 - buf.writeUInt16BE(fam, offset) - offset += 2 - buf.writeUInt8(spl, offset++) - buf.writeUInt8(option.scopePrefixLength || 0, offset++) - - ipBuf.copy(buf, offset, 0, ipLen) - offset += ipLen - break - // case 9: EXPIRE (experimental) - // case 10: COOKIE. No encode makes sense. - case 11: // KEEP-ALIVE - if (option.timeout) { - buf.writeUInt16BE(2, offset) - offset += 2 - buf.writeUInt16BE(option.timeout, offset) - offset += 2 - } else { - buf.writeUInt16BE(0, offset) - offset += 2 - } - break - case 12: // PADDING - const len = option.length || 0 - buf.writeUInt16BE(len, offset) - offset += 2 - buf.fill(0, offset, offset + len) - offset += len - break - // case 13: CHAIN. Experimental. - case 14: // KEY-TAG - const tagsLen = option.tags.length * 2 - buf.writeUInt16BE(tagsLen, offset) - offset += 2 - for (const tag of option.tags) { - buf.writeUInt16BE(tag, offset) - offset += 2 - } - break - default: - throw new Error(`Unknown roption code: ${option.code}`) - } - } - - roption.encode.bytes = offset - oldOffset - return buf -} - -roption.encode.bytes = 0 - -roption.decode = function (buf, offset) { - if (!offset) offset = 0 - const option = {} - option.code = buf.readUInt16BE(offset) - option.type = optioncodes.toString(option.code) - offset += 2 - const len = buf.readUInt16BE(offset) - offset += 2 - option.data = buf.slice(offset, offset + len) - switch (option.code) { - // case 3: NSID. No decode makes sense. - case 8: // ECS - option.family = buf.readUInt16BE(offset) - offset += 2 - option.sourcePrefixLength = buf.readUInt8(offset++) - option.scopePrefixLength = buf.readUInt8(offset++) - const padded = Buffer.alloc((option.family === 1) ? 4 : 16) - buf.copy(padded, 0, offset, offset + len - 4) - option.ip = ip.toString(padded) - break - // case 12: Padding. No decode makes sense. - case 11: // KEEP-ALIVE - if (len > 0) { - option.timeout = buf.readUInt16BE(offset) - offset += 2 - } - break - case 14: - option.tags = [] - for (let i = 0; i < len; i += 2) { - option.tags.push(buf.readUInt16BE(offset)) - offset += 2 - } - // don't worry about default. caller will use data if desired - } - - roption.decode.bytes = len + 4 - return option -} - -roption.decode.bytes = 0 - -roption.encodingLength = function (option) { - if (option.data) { - return option.data.length + 4 - } - const code = optioncodes.toCode(option.code) - switch (code) { - case 8: // ECS - const spl = option.sourcePrefixLength || 0 - return Math.ceil(spl / 8) + 8 - case 11: // KEEP-ALIVE - return (typeof option.timeout === 'number') ? 6 : 4 - case 12: // PADDING - return option.length + 4 - case 14: // KEY-TAG - return 4 + (option.tags.length * 2) - } - throw new Error(`Unknown roption code: ${option.code}`) -} - -const ropt = exports.opt = {} - -ropt.encode = function (options, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(ropt.encodingLength(options)) - if (!offset) offset = 0 - const oldOffset = offset - - const rdlen = encodingLengthList(options, roption) - buf.writeUInt16BE(rdlen, offset) - offset = encodeList(options, roption, buf, offset + 2) - - ropt.encode.bytes = offset - oldOffset - return buf -} - -ropt.encode.bytes = 0 - -ropt.decode = function (buf, offset) { - if (!offset) offset = 0 - const oldOffset = offset - - const options = [] - let rdlen = buf.readUInt16BE(offset) - offset += 2 - let o = 0 - while (rdlen > 0) { - options[o++] = roption.decode(buf, offset) - offset += roption.decode.bytes - rdlen -= roption.decode.bytes - } - ropt.decode.bytes = offset - oldOffset - return options -} - -ropt.decode.bytes = 0 - -ropt.encodingLength = function (options) { - return 2 + encodingLengthList(options || [], roption) -} - -const rdnskey = exports.dnskey = {} - -rdnskey.PROTOCOL_DNSSEC = 3 -rdnskey.ZONE_KEY = 0x80 -rdnskey.SECURE_ENTRYPOINT = 0x8000 - -rdnskey.encode = function (key, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(rdnskey.encodingLength(key)) - if (!offset) offset = 0 - const oldOffset = offset - - const keydata = key.key - if (!Buffer.isBuffer(keydata)) { - throw new Error('Key must be a Buffer') - } - - offset += 2 // Leave space for length - buf.writeUInt16BE(key.flags, offset) - offset += 2 - buf.writeUInt8(rdnskey.PROTOCOL_DNSSEC, offset) - offset += 1 - buf.writeUInt8(key.algorithm, offset) - offset += 1 - keydata.copy(buf, offset, 0, keydata.length) - offset += keydata.length - - rdnskey.encode.bytes = offset - oldOffset - buf.writeUInt16BE(rdnskey.encode.bytes - 2, oldOffset) - return buf -} - -rdnskey.encode.bytes = 0 - -rdnskey.decode = function (buf, offset) { - if (!offset) offset = 0 - const oldOffset = offset - - var key = {} - var length = buf.readUInt16BE(offset) - offset += 2 - key.flags = buf.readUInt16BE(offset) - offset += 2 - if (buf.readUInt8(offset) !== rdnskey.PROTOCOL_DNSSEC) { - throw new Error('Protocol must be 3') - } - offset += 1 - key.algorithm = buf.readUInt8(offset) - offset += 1 - key.key = buf.slice(offset, oldOffset + length + 2) - offset += key.key.length - rdnskey.decode.bytes = offset - oldOffset - return key -} - -rdnskey.decode.bytes = 0 - -rdnskey.encodingLength = function (key) { - return 6 + Buffer.byteLength(key.key) -} - -const rrrsig = exports.rrsig = {} - -rrrsig.encode = function (sig, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(rrrsig.encodingLength(sig)) - if (!offset) offset = 0 - const oldOffset = offset - - const signature = sig.signature - if (!Buffer.isBuffer(signature)) { - throw new Error('Signature must be a Buffer') - } - - offset += 2 // Leave space for length - buf.writeUInt16BE(types.toType(sig.typeCovered), offset) - offset += 2 - buf.writeUInt8(sig.algorithm, offset) - offset += 1 - buf.writeUInt8(sig.labels, offset) - offset += 1 - buf.writeUInt32BE(sig.originalTTL, offset) - offset += 4 - buf.writeUInt32BE(sig.expiration, offset) - offset += 4 - buf.writeUInt32BE(sig.inception, offset) - offset += 4 - buf.writeUInt16BE(sig.keyTag, offset) - offset += 2 - name.encode(sig.signersName, buf, offset) - offset += name.encode.bytes - signature.copy(buf, offset, 0, signature.length) - offset += signature.length - - rrrsig.encode.bytes = offset - oldOffset - buf.writeUInt16BE(rrrsig.encode.bytes - 2, oldOffset) - return buf -} - -rrrsig.encode.bytes = 0 - -rrrsig.decode = function (buf, offset) { - if (!offset) offset = 0 - const oldOffset = offset - - var sig = {} - var length = buf.readUInt16BE(offset) - offset += 2 - sig.typeCovered = types.toString(buf.readUInt16BE(offset)) - offset += 2 - sig.algorithm = buf.readUInt8(offset) - offset += 1 - sig.labels = buf.readUInt8(offset) - offset += 1 - sig.originalTTL = buf.readUInt32BE(offset) - offset += 4 - sig.expiration = buf.readUInt32BE(offset) - offset += 4 - sig.inception = buf.readUInt32BE(offset) - offset += 4 - sig.keyTag = buf.readUInt16BE(offset) - offset += 2 - sig.signersName = name.decode(buf, offset) - offset += name.decode.bytes - sig.signature = buf.slice(offset, oldOffset + length + 2) - offset += sig.signature.length - rrrsig.decode.bytes = offset - oldOffset - return sig -} - -rrrsig.decode.bytes = 0 - -rrrsig.encodingLength = function (sig) { - return 20 + - name.encodingLength(sig.signersName) + - Buffer.byteLength(sig.signature) -} - -const rrp = exports.rp = {} - -rrp.encode = function (data, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(rrp.encodingLength(data)) - if (!offset) offset = 0 - const oldOffset = offset - - offset += 2 // Leave space for length - name.encode(data.mbox || '.', buf, offset) - offset += name.encode.bytes - name.encode(data.txt || '.', buf, offset) - offset += name.encode.bytes - rrp.encode.bytes = offset - oldOffset - buf.writeUInt16BE(rrp.encode.bytes - 2, oldOffset) - return buf -} - -rrp.encode.bytes = 0 - -rrp.decode = function (buf, offset) { - if (!offset) offset = 0 - const oldOffset = offset - - const data = {} - offset += 2 - data.mbox = name.decode(buf, offset) || '.' - offset += name.decode.bytes - data.txt = name.decode(buf, offset) || '.' - offset += name.decode.bytes - rrp.decode.bytes = offset - oldOffset - return data -} - -rrp.decode.bytes = 0 - -rrp.encodingLength = function (data) { - return 2 + name.encodingLength(data.mbox || '.') + name.encodingLength(data.txt || '.') -} - -const typebitmap = {} - -typebitmap.encode = function (typelist, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(typebitmap.encodingLength(typelist)) - if (!offset) offset = 0 - const oldOffset = offset - - var typesByWindow = [] - for (var i = 0; i < typelist.length; i++) { - var typeid = types.toType(typelist[i]) - if (typesByWindow[typeid >> 8] === undefined) { - typesByWindow[typeid >> 8] = [] - } - typesByWindow[typeid >> 8][(typeid >> 3) & 0x1F] |= 1 << (7 - (typeid & 0x7)) - } - - for (i = 0; i < typesByWindow.length; i++) { - if (typesByWindow[i] !== undefined) { - var windowBuf = Buffer.from(typesByWindow[i]) - buf.writeUInt8(i, offset) - offset += 1 - buf.writeUInt8(windowBuf.length, offset) - offset += 1 - windowBuf.copy(buf, offset) - offset += windowBuf.length - } - } - - typebitmap.encode.bytes = offset - oldOffset - return buf -} - -typebitmap.encode.bytes = 0 - -typebitmap.decode = function (buf, offset, length) { - if (!offset) offset = 0 - const oldOffset = offset - - var typelist = [] - while (offset - oldOffset < length) { - var window = buf.readUInt8(offset) - offset += 1 - var windowLength = buf.readUInt8(offset) - offset += 1 - for (var i = 0; i < windowLength; i++) { - var b = buf.readUInt8(offset + i) - for (var j = 0; j < 8; j++) { - if (b & (1 << (7 - j))) { - var typeid = types.toString((window << 8) | (i << 3) | j) - typelist.push(typeid) - } - } - } - offset += windowLength - } - - typebitmap.decode.bytes = offset - oldOffset - return typelist -} - -typebitmap.decode.bytes = 0 - -typebitmap.encodingLength = function (typelist) { - var extents = [] - for (var i = 0; i < typelist.length; i++) { - var typeid = types.toType(typelist[i]) - extents[typeid >> 8] = Math.max(extents[typeid >> 8] || 0, typeid & 0xFF) - } - - var len = 0 - for (i = 0; i < extents.length; i++) { - if (extents[i] !== undefined) { - len += 2 + Math.ceil((extents[i] + 1) / 8) - } - } - - return len -} - -const rnsec = exports.nsec = {} - -rnsec.encode = function (record, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(rnsec.encodingLength(record)) - if (!offset) offset = 0 - const oldOffset = offset - - offset += 2 // Leave space for length - name.encode(record.nextDomain, buf, offset) - offset += name.encode.bytes - typebitmap.encode(record.rrtypes, buf, offset) - offset += typebitmap.encode.bytes - - rnsec.encode.bytes = offset - oldOffset - buf.writeUInt16BE(rnsec.encode.bytes - 2, oldOffset) - return buf -} - -rnsec.encode.bytes = 0 - -rnsec.decode = function (buf, offset) { - if (!offset) offset = 0 - const oldOffset = offset - - var record = {} - var length = buf.readUInt16BE(offset) - offset += 2 - record.nextDomain = name.decode(buf, offset) - offset += name.decode.bytes - record.rrtypes = typebitmap.decode(buf, offset, length - (offset - oldOffset)) - offset += typebitmap.decode.bytes - - rnsec.decode.bytes = offset - oldOffset - return record -} - -rnsec.decode.bytes = 0 - -rnsec.encodingLength = function (record) { - return 2 + - name.encodingLength(record.nextDomain) + - typebitmap.encodingLength(record.rrtypes) -} - -const rnsec3 = exports.nsec3 = {} - -rnsec3.encode = function (record, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(rnsec3.encodingLength(record)) - if (!offset) offset = 0 - const oldOffset = offset - - const salt = record.salt - if (!Buffer.isBuffer(salt)) { - throw new Error('salt must be a Buffer') - } - - const nextDomain = record.nextDomain - if (!Buffer.isBuffer(nextDomain)) { - throw new Error('nextDomain must be a Buffer') - } - - offset += 2 // Leave space for length - buf.writeUInt8(record.algorithm, offset) - offset += 1 - buf.writeUInt8(record.flags, offset) - offset += 1 - buf.writeUInt16BE(record.iterations, offset) - offset += 2 - buf.writeUInt8(salt.length, offset) - offset += 1 - salt.copy(buf, offset, 0, salt.length) - offset += salt.length - buf.writeUInt8(nextDomain.length, offset) - offset += 1 - nextDomain.copy(buf, offset, 0, nextDomain.length) - offset += nextDomain.length - typebitmap.encode(record.rrtypes, buf, offset) - offset += typebitmap.encode.bytes - - rnsec3.encode.bytes = offset - oldOffset - buf.writeUInt16BE(rnsec3.encode.bytes - 2, oldOffset) - return buf -} - -rnsec3.encode.bytes = 0 - -rnsec3.decode = function (buf, offset) { - if (!offset) offset = 0 - const oldOffset = offset - - var record = {} - var length = buf.readUInt16BE(offset) - offset += 2 - record.algorithm = buf.readUInt8(offset) - offset += 1 - record.flags = buf.readUInt8(offset) - offset += 1 - record.iterations = buf.readUInt16BE(offset) - offset += 2 - const saltLength = buf.readUInt8(offset) - offset += 1 - record.salt = buf.slice(offset, offset + saltLength) - offset += saltLength - const hashLength = buf.readUInt8(offset) - offset += 1 - record.nextDomain = buf.slice(offset, offset + hashLength) - offset += hashLength - record.rrtypes = typebitmap.decode(buf, offset, length - (offset - oldOffset)) - offset += typebitmap.decode.bytes - - rnsec3.decode.bytes = offset - oldOffset - return record -} - -rnsec3.decode.bytes = 0 - -rnsec3.encodingLength = function (record) { - return 8 + - record.salt.length + - record.nextDomain.length + - typebitmap.encodingLength(record.rrtypes) -} - -const rds = exports.ds = {} - -rds.encode = function (digest, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(rds.encodingLength(digest)) - if (!offset) offset = 0 - const oldOffset = offset - - const digestdata = digest.digest - if (!Buffer.isBuffer(digestdata)) { - throw new Error('Digest must be a Buffer') - } - - offset += 2 // Leave space for length - buf.writeUInt16BE(digest.keyTag, offset) - offset += 2 - buf.writeUInt8(digest.algorithm, offset) - offset += 1 - buf.writeUInt8(digest.digestType, offset) - offset += 1 - digestdata.copy(buf, offset, 0, digestdata.length) - offset += digestdata.length - - rds.encode.bytes = offset - oldOffset - buf.writeUInt16BE(rds.encode.bytes - 2, oldOffset) - return buf -} - -rds.encode.bytes = 0 - -rds.decode = function (buf, offset) { - if (!offset) offset = 0 - const oldOffset = offset - - var digest = {} - var length = buf.readUInt16BE(offset) - offset += 2 - digest.keyTag = buf.readUInt16BE(offset) - offset += 2 - digest.algorithm = buf.readUInt8(offset) - offset += 1 - digest.digestType = buf.readUInt8(offset) - offset += 1 - digest.digest = buf.slice(offset, oldOffset + length + 2) - offset += digest.digest.length - rds.decode.bytes = offset - oldOffset - return digest -} - -rds.decode.bytes = 0 - -rds.encodingLength = function (digest) { - return 6 + Buffer.byteLength(digest.digest) -} - -const renc = exports.record = function (type) { - switch (type.toUpperCase()) { - case 'A': return ra - case 'PTR': return rptr - case 'CNAME': return rcname - case 'DNAME': return rdname - case 'TXT': return rtxt - case 'NULL': return rnull - case 'AAAA': return raaaa - case 'SRV': return rsrv - case 'HINFO': return rhinfo - case 'CAA': return rcaa - case 'NS': return rns - case 'SOA': return rsoa - case 'MX': return rmx - case 'OPT': return ropt - case 'DNSKEY': return rdnskey - case 'RRSIG': return rrrsig - case 'RP': return rrp - case 'NSEC': return rnsec - case 'NSEC3': return rnsec3 - case 'DS': return rds - } - return runknown -} - -const answer = exports.answer = {} - -answer.encode = function (a, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(answer.encodingLength(a)) - if (!offset) offset = 0 - - const oldOffset = offset - - name.encode(a.name, buf, offset) - offset += name.encode.bytes - - buf.writeUInt16BE(types.toType(a.type), offset) - - if (a.type.toUpperCase() === 'OPT') { - if (a.name !== '.') { - throw new Error('OPT name must be root.') - } - buf.writeUInt16BE(a.udpPayloadSize || 4096, offset + 2) - buf.writeUInt8(a.extendedRcode || 0, offset + 4) - buf.writeUInt8(a.ednsVersion || 0, offset + 5) - buf.writeUInt16BE(a.flags || 0, offset + 6) - - offset += 8 - ropt.encode(a.options || [], buf, offset) - offset += ropt.encode.bytes - } else { - let klass = classes.toClass(a.class === undefined ? 'IN' : a.class) - if (a.flush) klass |= FLUSH_MASK // the 1st bit of the class is the flush bit - buf.writeUInt16BE(klass, offset + 2) - buf.writeUInt32BE(a.ttl || 0, offset + 4) - - offset += 8 - const enc = renc(a.type) - enc.encode(a.data, buf, offset) - offset += enc.encode.bytes - } - - answer.encode.bytes = offset - oldOffset - return buf -} - -answer.encode.bytes = 0 - -answer.decode = function (buf, offset) { - if (!offset) offset = 0 - - const a = {} - const oldOffset = offset - - a.name = name.decode(buf, offset) - offset += name.decode.bytes - a.type = types.toString(buf.readUInt16BE(offset)) - if (a.type === 'OPT') { - a.udpPayloadSize = buf.readUInt16BE(offset + 2) - a.extendedRcode = buf.readUInt8(offset + 4) - a.ednsVersion = buf.readUInt8(offset + 5) - a.flags = buf.readUInt16BE(offset + 6) - a.flag_do = ((a.flags >> 15) & 0x1) === 1 - a.options = ropt.decode(buf, offset + 8) - offset += 8 + ropt.decode.bytes - } else { - const klass = buf.readUInt16BE(offset + 2) - a.ttl = buf.readUInt32BE(offset + 4) - - a.class = classes.toString(klass & NOT_FLUSH_MASK) - a.flush = !!(klass & FLUSH_MASK) - - const enc = renc(a.type) - a.data = enc.decode(buf, offset + 8) - offset += 8 + enc.decode.bytes - } - - answer.decode.bytes = offset - oldOffset - return a -} - -answer.decode.bytes = 0 - -answer.encodingLength = function (a) { - const data = (a.data !== null && a.data !== undefined) ? a.data : a.options - return name.encodingLength(a.name) + 8 + renc(a.type).encodingLength(data) -} - -const question = exports.question = {} - -question.encode = function (q, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(question.encodingLength(q)) - if (!offset) offset = 0 - - const oldOffset = offset - - name.encode(q.name, buf, offset) - offset += name.encode.bytes - - buf.writeUInt16BE(types.toType(q.type), offset) - offset += 2 - - buf.writeUInt16BE(classes.toClass(q.class === undefined ? 'IN' : q.class), offset) - offset += 2 - - question.encode.bytes = offset - oldOffset - return q -} - -question.encode.bytes = 0 - -question.decode = function (buf, offset) { - if (!offset) offset = 0 - - const oldOffset = offset - const q = {} - - q.name = name.decode(buf, offset) - offset += name.decode.bytes - - q.type = types.toString(buf.readUInt16BE(offset)) - offset += 2 - - q.class = classes.toString(buf.readUInt16BE(offset)) - offset += 2 - - const qu = !!(q.class & QU_MASK) - if (qu) q.class &= NOT_QU_MASK - - question.decode.bytes = offset - oldOffset - return q -} - -question.decode.bytes = 0 - -question.encodingLength = function (q) { - return name.encodingLength(q.name) + 4 -} - -exports.AUTHORITATIVE_ANSWER = 1 << 10 -exports.TRUNCATED_RESPONSE = 1 << 9 -exports.RECURSION_DESIRED = 1 << 8 -exports.RECURSION_AVAILABLE = 1 << 7 -exports.AUTHENTIC_DATA = 1 << 5 -exports.CHECKING_DISABLED = 1 << 4 -exports.DNSSEC_OK = 1 << 15 - -exports.encode = function (result, buf, offset) { - if (!buf) buf = Buffer.allocUnsafe(exports.encodingLength(result)) - if (!offset) offset = 0 - - const oldOffset = offset - - if (!result.questions) result.questions = [] - if (!result.answers) result.answers = [] - if (!result.authorities) result.authorities = [] - if (!result.additionals) result.additionals = [] - - header.encode(result, buf, offset) - offset += header.encode.bytes - - offset = encodeList(result.questions, question, buf, offset) - offset = encodeList(result.answers, answer, buf, offset) - offset = encodeList(result.authorities, answer, buf, offset) - offset = encodeList(result.additionals, answer, buf, offset) - - exports.encode.bytes = offset - oldOffset - - return buf -} - -exports.encode.bytes = 0 - -exports.decode = function (buf, offset) { - if (!offset) offset = 0 - - const oldOffset = offset - const result = header.decode(buf, offset) - offset += header.decode.bytes - - offset = decodeList(result.questions, question, buf, offset) - offset = decodeList(result.answers, answer, buf, offset) - offset = decodeList(result.authorities, answer, buf, offset) - offset = decodeList(result.additionals, answer, buf, offset) - - exports.decode.bytes = offset - oldOffset - - return result -} - -exports.decode.bytes = 0 - -exports.encodingLength = function (result) { - return header.encodingLength(result) + - encodingLengthList(result.questions || [], question) + - encodingLengthList(result.answers || [], answer) + - encodingLengthList(result.authorities || [], answer) + - encodingLengthList(result.additionals || [], answer) -} - -exports.streamEncode = function (result) { - const buf = exports.encode(result) - const sbuf = Buffer.allocUnsafe(2) - sbuf.writeUInt16BE(buf.byteLength) - const combine = Buffer.concat([sbuf, buf]) - exports.streamEncode.bytes = combine.byteLength - return combine -} - -exports.streamEncode.bytes = 0 - -exports.streamDecode = function (sbuf) { - const len = sbuf.readUInt16BE(0) - if (sbuf.byteLength < len + 2) { - // not enough data - return null - } - const result = exports.decode(sbuf.slice(2)) - exports.streamDecode.bytes = exports.decode.bytes - return result -} - -exports.streamDecode.bytes = 0 - -function encodingLengthList (list, enc) { - let len = 0 - for (let i = 0; i < list.length; i++) len += enc.encodingLength(list[i]) - return len -} - -function encodeList (list, enc, buf, offset) { - for (let i = 0; i < list.length; i++) { - enc.encode(list[i], buf, offset) - offset += enc.encode.bytes - } - return offset -} - -function decodeList (list, enc, buf, offset) { - for (let i = 0; i < list.length; i++) { - list[i] = enc.decode(buf, offset) - offset += enc.decode.bytes - } - return offset -} diff --git a/testing/xpcshell/dns-packet/opcodes.js b/testing/xpcshell/dns-packet/opcodes.js deleted file mode 100644 index 32b0a1b4de77..000000000000 --- a/testing/xpcshell/dns-packet/opcodes.js +++ /dev/null @@ -1,50 +0,0 @@ -'use strict' - -/* - * Traditional DNS header OPCODEs (4-bits) defined by IANA in - * https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-5 - */ - -exports.toString = function (opcode) { - switch (opcode) { - case 0: return 'QUERY' - case 1: return 'IQUERY' - case 2: return 'STATUS' - case 3: return 'OPCODE_3' - case 4: return 'NOTIFY' - case 5: return 'UPDATE' - case 6: return 'OPCODE_6' - case 7: return 'OPCODE_7' - case 8: return 'OPCODE_8' - case 9: return 'OPCODE_9' - case 10: return 'OPCODE_10' - case 11: return 'OPCODE_11' - case 12: return 'OPCODE_12' - case 13: return 'OPCODE_13' - case 14: return 'OPCODE_14' - case 15: return 'OPCODE_15' - } - return 'OPCODE_' + opcode -} - -exports.toOpcode = function (code) { - switch (code.toUpperCase()) { - case 'QUERY': return 0 - case 'IQUERY': return 1 - case 'STATUS': return 2 - case 'OPCODE_3': return 3 - case 'NOTIFY': return 4 - case 'UPDATE': return 5 - case 'OPCODE_6': return 6 - case 'OPCODE_7': return 7 - case 'OPCODE_8': return 8 - case 'OPCODE_9': return 9 - case 'OPCODE_10': return 10 - case 'OPCODE_11': return 11 - case 'OPCODE_12': return 12 - case 'OPCODE_13': return 13 - case 'OPCODE_14': return 14 - case 'OPCODE_15': return 15 - } - return 0 -} diff --git a/testing/xpcshell/dns-packet/optioncodes.js b/testing/xpcshell/dns-packet/optioncodes.js deleted file mode 100644 index 0d66e059ee50..000000000000 --- a/testing/xpcshell/dns-packet/optioncodes.js +++ /dev/null @@ -1,59 +0,0 @@ -'use strict' - -exports.toString = function (type) { - switch (type) { - // list at - // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-11 - case 1: return 'LLQ' - case 2: return 'UL' - case 3: return 'NSID' - case 5: return 'DAU' - case 6: return 'DHU' - case 7: return 'N3U' - case 8: return 'CLIENT_SUBNET' - case 9: return 'EXPIRE' - case 10: return 'COOKIE' - case 11: return 'TCP_KEEPALIVE' - case 12: return 'PADDING' - case 13: return 'CHAIN' - case 14: return 'KEY_TAG' - case 26946: return 'DEVICEID' - } - if (type < 0) { - return null - } - return `OPTION_${type}` -} - -exports.toCode = function (name) { - if (typeof name === 'number') { - return name - } - if (!name) { - return -1 - } - switch (name.toUpperCase()) { - case 'OPTION_0': return 0 - case 'LLQ': return 1 - case 'UL': return 2 - case 'NSID': return 3 - case 'OPTION_4': return 4 - case 'DAU': return 5 - case 'DHU': return 6 - case 'N3U': return 7 - case 'CLIENT_SUBNET': return 8 - case 'EXPIRE': return 9 - case 'COOKIE': return 10 - case 'TCP_KEEPALIVE': return 11 - case 'PADDING': return 12 - case 'CHAIN': return 13 - case 'KEY_TAG': return 14 - case 'DEVICEID': return 26946 - case 'OPTION_65535': return 65535 - } - const m = name.match(/_(\d+)$/) - if (m) { - return parseInt(m[1], 10) - } - return -1 -} diff --git a/testing/xpcshell/dns-packet/package.json b/testing/xpcshell/dns-packet/package.json deleted file mode 100644 index 31a859fc2b3b..000000000000 --- a/testing/xpcshell/dns-packet/package.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "name": "dns-packet", - "version": "5.2.1", - "description": "An abstract-encoding compliant module for encoding / decoding DNS packets", - "author": "Mathias Buus", - "license": "MIT", - "repository": "mafintosh/dns-packet", - "homepage": "https://github.com/mafintosh/dns-packet", - "engines": { - "node": ">=6" - }, - "scripts": { - "clean": "rm -rf coverage .nyc_output/", - "lint": "eslint --color *.js examples/*.js", - "pretest": "npm run lint", - "test": "tape test.js", - "coverage": "nyc -r html npm test" - }, - "dependencies": { - "ip": "^1.1.5" - }, - "devDependencies": { - "eslint": "^5.14.1", - "eslint-config-standard": "^12.0.0", - "eslint-plugin-import": "^2.16.0", - "eslint-plugin-node": "^8.0.1", - "eslint-plugin-promise": "^4.0.1", - "eslint-plugin-standard": "^4.0.0", - "nyc": "^13.3.0", - "tape": "^4.10.1" - }, - "keywords": [ - "dns", - "packet", - "encodings", - "encoding", - "encoder", - "abstract-encoding" - ], - "files": [ - "index.js", - "types.js", - "rcodes.js", - "opcodes.js", - "classes.js", - "optioncodes.js" - ] -} diff --git a/testing/xpcshell/dns-packet/rcodes.js b/testing/xpcshell/dns-packet/rcodes.js deleted file mode 100644 index 0500887c2a15..000000000000 --- a/testing/xpcshell/dns-packet/rcodes.js +++ /dev/null @@ -1,50 +0,0 @@ -'use strict' - -/* - * Traditional DNS header RCODEs (4-bits) defined by IANA in - * https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml - */ - -exports.toString = function (rcode) { - switch (rcode) { - case 0: return 'NOERROR' - case 1: return 'FORMERR' - case 2: return 'SERVFAIL' - case 3: return 'NXDOMAIN' - case 4: return 'NOTIMP' - case 5: return 'REFUSED' - case 6: return 'YXDOMAIN' - case 7: return 'YXRRSET' - case 8: return 'NXRRSET' - case 9: return 'NOTAUTH' - case 10: return 'NOTZONE' - case 11: return 'RCODE_11' - case 12: return 'RCODE_12' - case 13: return 'RCODE_13' - case 14: return 'RCODE_14' - case 15: return 'RCODE_15' - } - return 'RCODE_' + rcode -} - -exports.toRcode = function (code) { - switch (code.toUpperCase()) { - case 'NOERROR': return 0 - case 'FORMERR': return 1 - case 'SERVFAIL': return 2 - case 'NXDOMAIN': return 3 - case 'NOTIMP': return 4 - case 'REFUSED': return 5 - case 'YXDOMAIN': return 6 - case 'YXRRSET': return 7 - case 'NXRRSET': return 8 - case 'NOTAUTH': return 9 - case 'NOTZONE': return 10 - case 'RCODE_11': return 11 - case 'RCODE_12': return 12 - case 'RCODE_13': return 13 - case 'RCODE_14': return 14 - case 'RCODE_15': return 15 - } - return 0 -} diff --git a/testing/xpcshell/dns-packet/test.js b/testing/xpcshell/dns-packet/test.js deleted file mode 100644 index adf4757daebf..000000000000 --- a/testing/xpcshell/dns-packet/test.js +++ /dev/null @@ -1,613 +0,0 @@ -'use strict' - -const tape = require('tape') -const packet = require('./') -const rcodes = require('./rcodes') -const opcodes = require('./opcodes') -const optioncodes = require('./optioncodes') - -tape('unknown', function (t) { - testEncoder(t, packet.unknown, Buffer.from('hello world')) - t.end() -}) - -tape('txt', function (t) { - testEncoder(t, packet.txt, []) - testEncoder(t, packet.txt, ['hello world']) - testEncoder(t, packet.txt, ['hello', 'world']) - testEncoder(t, packet.txt, [Buffer.from([0, 1, 2, 3, 4, 5])]) - testEncoder(t, packet.txt, ['a', 'b', Buffer.from([0, 1, 2, 3, 4, 5])]) - testEncoder(t, packet.txt, ['', Buffer.allocUnsafe(0)]) - t.end() -}) - -tape('txt-scalar-string', function (t) { - const buf = packet.txt.encode('hi') - const val = packet.txt.decode(buf) - t.ok(val.length === 1, 'array length') - t.ok(val[0].toString() === 'hi', 'data') - t.end() -}) - -tape('txt-scalar-buffer', function (t) { - const data = Buffer.from([0, 1, 2, 3, 4, 5]) - const buf = packet.txt.encode(data) - const val = packet.txt.decode(buf) - t.ok(val.length === 1, 'array length') - t.ok(val[0].equals(data), 'data') - t.end() -}) - -tape('txt-invalid-data', function (t) { - t.throws(function () { packet.txt.encode(null) }, 'null') - t.throws(function () { packet.txt.encode(undefined) }, 'undefined') - t.throws(function () { packet.txt.encode(10) }, 'number') - t.end() -}) - -tape('null', function (t) { - testEncoder(t, packet.null, Buffer.from([0, 1, 2, 3, 4, 5])) - t.end() -}) - -tape('hinfo', function (t) { - testEncoder(t, packet.hinfo, { cpu: 'intel', os: 'best one' }) - t.end() -}) - -tape('ptr', function (t) { - testEncoder(t, packet.ptr, 'hello.world.com') - t.end() -}) - -tape('cname', function (t) { - testEncoder(t, packet.cname, 'hello.cname.world.com') - t.end() -}) - -tape('dname', function (t) { - testEncoder(t, packet.dname, 'hello.dname.world.com') - t.end() -}) - -tape('srv', function (t) { - testEncoder(t, packet.srv, { port: 9999, target: 'hello.world.com' }) - testEncoder(t, packet.srv, { port: 9999, target: 'hello.world.com', priority: 42, weight: 10 }) - t.end() -}) - -tape('caa', function (t) { - testEncoder(t, packet.caa, { flags: 128, tag: 'issue', value: 'letsencrypt.org', issuerCritical: true }) - testEncoder(t, packet.caa, { tag: 'issue', value: 'letsencrypt.org', issuerCritical: true }) - testEncoder(t, packet.caa, { tag: 'issue', value: 'letsencrypt.org' }) - t.end() -}) - -tape('mx', function (t) { - testEncoder(t, packet.mx, { preference: 10, exchange: 'mx.hello.world.com' }) - testEncoder(t, packet.mx, { exchange: 'mx.hello.world.com' }) - t.end() -}) - -tape('ns', function (t) { - testEncoder(t, packet.ns, 'ns.world.com') - t.end() -}) - -tape('soa', function (t) { - testEncoder(t, packet.soa, { - mname: 'hello.world.com', - rname: 'root.hello.world.com', - serial: 2018010400, - refresh: 14400, - retry: 3600, - expire: 604800, - minimum: 3600 - }) - t.end() -}) - -tape('a', function (t) { - testEncoder(t, packet.a, '127.0.0.1') - t.end() -}) - -tape('aaaa', function (t) { - testEncoder(t, packet.aaaa, 'fe80::1') - t.end() -}) - -tape('query', function (t) { - testEncoder(t, packet, { - type: 'query', - questions: [{ - type: 'A', - name: 'hello.a.com' - }, { - type: 'SRV', - name: 'hello.srv.com' - }] - }) - - testEncoder(t, packet, { - type: 'query', - id: 42, - questions: [{ - type: 'A', - class: 'IN', - name: 'hello.a.com' - }, { - type: 'SRV', - name: 'hello.srv.com' - }] - }) - - testEncoder(t, packet, { - type: 'query', - id: 42, - questions: [{ - type: 'A', - class: 'CH', - name: 'hello.a.com' - }, { - type: 'SRV', - name: 'hello.srv.com' - }] - }) - - t.end() -}) - -tape('response', function (t) { - testEncoder(t, packet, { - type: 'response', - answers: [{ - type: 'A', - class: 'IN', - flush: true, - name: 'hello.a.com', - data: '127.0.0.1' - }] - }) - - testEncoder(t, packet, { - type: 'response', - flags: packet.TRUNCATED_RESPONSE, - answers: [{ - type: 'A', - class: 'IN', - name: 'hello.a.com', - data: '127.0.0.1' - }, { - type: 'SRV', - class: 'IN', - name: 'hello.srv.com', - data: { - port: 9090, - target: 'hello.target.com' - } - }, { - type: 'CNAME', - class: 'IN', - name: 'hello.cname.com', - data: 'hello.other.domain.com' - }] - }) - - testEncoder(t, packet, { - type: 'response', - id: 100, - flags: 0, - additionals: [{ - type: 'AAAA', - name: 'hello.a.com', - data: 'fe80::1' - }, { - type: 'PTR', - name: 'hello.ptr.com', - data: 'hello.other.ptr.com' - }, { - type: 'SRV', - name: 'hello.srv.com', - ttl: 42, - data: { - port: 9090, - target: 'hello.target.com' - } - }], - answers: [{ - type: 'NULL', - name: 'hello.null.com', - data: Buffer.from([1, 2, 3, 4, 5]) - }] - }) - - testEncoder(t, packet, { - type: 'response', - answers: [{ - type: 'TXT', - name: 'emptytxt.com', - data: '' - }] - }) - - t.end() -}) - -tape('rcode', function (t) { - const errors = ['NOERROR', 'FORMERR', 'SERVFAIL', 'NXDOMAIN', 'NOTIMP', 'REFUSED', 'YXDOMAIN', 'YXRRSET', 'NXRRSET', 'NOTAUTH', 'NOTZONE', 'RCODE_11', 'RCODE_12', 'RCODE_13', 'RCODE_14', 'RCODE_15'] - for (const i in errors) { - const code = rcodes.toRcode(errors[i]) - t.ok(errors[i] === rcodes.toString(code), 'rcode conversion from/to string matches: ' + rcodes.toString(code)) - } - - const ops = ['QUERY', 'IQUERY', 'STATUS', 'OPCODE_3', 'NOTIFY', 'UPDATE', 'OPCODE_6', 'OPCODE_7', 'OPCODE_8', 'OPCODE_9', 'OPCODE_10', 'OPCODE_11', 'OPCODE_12', 'OPCODE_13', 'OPCODE_14', 'OPCODE_15'] - for (const j in ops) { - const ocode = opcodes.toOpcode(ops[j]) - t.ok(ops[j] === opcodes.toString(ocode), 'opcode conversion from/to string matches: ' + opcodes.toString(ocode)) - } - - const buf = packet.encode({ - type: 'response', - id: 45632, - flags: 0x8480, - answers: [{ - type: 'A', - name: 'hello.example.net', - data: '127.0.0.1' - }] - }) - const val = packet.decode(buf) - t.ok(val.type === 'response', 'decode type') - t.ok(val.opcode === 'QUERY', 'decode opcode') - t.ok(val.flag_qr === true, 'decode flag_qr') - t.ok(val.flag_aa === true, 'decode flag_aa') - t.ok(val.flag_tc === false, 'decode flag_tc') - t.ok(val.flag_rd === false, 'decode flag_rd') - t.ok(val.flag_ra === true, 'decode flag_ra') - t.ok(val.flag_z === false, 'decode flag_z') - t.ok(val.flag_ad === false, 'decode flag_ad') - t.ok(val.flag_cd === false, 'decode flag_cd') - t.ok(val.rcode === 'NOERROR', 'decode rcode') - t.end() -}) - -tape('name_encoding', function (t) { - let data = 'foo.example.com' - const buf = Buffer.allocUnsafe(255) - let offset = 0 - packet.name.encode(data, buf, offset) - t.ok(packet.name.encode.bytes === 17, 'name encoding length matches') - let dd = packet.name.decode(buf, offset) - t.ok(data === dd, 'encode/decode matches') - offset += packet.name.encode.bytes - - data = 'com' - packet.name.encode(data, buf, offset) - t.ok(packet.name.encode.bytes === 5, 'name encoding length matches') - dd = packet.name.decode(buf, offset) - t.ok(data === dd, 'encode/decode matches') - offset += packet.name.encode.bytes - - data = 'example.com.' - packet.name.encode(data, buf, offset) - t.ok(packet.name.encode.bytes === 13, 'name encoding length matches') - dd = packet.name.decode(buf, offset) - t.ok(data.slice(0, -1) === dd, 'encode/decode matches') - offset += packet.name.encode.bytes - - data = '.' - packet.name.encode(data, buf, offset) - t.ok(packet.name.encode.bytes === 1, 'name encoding length matches') - dd = packet.name.decode(buf, offset) - t.ok(data === dd, 'encode/decode matches') - t.end() -}) - -tape('stream', function (t) { - const val = { - type: 'query', - id: 45632, - flags: 0x8480, - answers: [{ - type: 'A', - name: 'test2.example.net', - data: '198.51.100.1' - }] - } - const buf = packet.streamEncode(val) - const val2 = packet.streamDecode(buf) - - t.same(buf.length, packet.streamEncode.bytes, 'streamEncode.bytes was set correctly') - t.ok(compare(t, val2.type, val.type), 'streamDecoded type match') - t.ok(compare(t, val2.id, val.id), 'streamDecoded id match') - t.ok(parseInt(val2.flags) === parseInt(val.flags & 0x7FFF), 'streamDecoded flags match') - const answer = val.answers[0] - const answer2 = val2.answers[0] - t.ok(compare(t, answer.type, answer2.type), 'streamDecoded RR type match') - t.ok(compare(t, answer.name, answer2.name), 'streamDecoded RR name match') - t.ok(compare(t, answer.data, answer2.data), 'streamDecoded RR rdata match') - t.end() -}) - -tape('opt', function (t) { - const val = { - type: 'query', - questions: [{ - type: 'A', - name: 'hello.a.com' - }], - additionals: [{ - type: 'OPT', - name: '.', - udpPayloadSize: 1024 - }] - } - testEncoder(t, packet, val) - let buf = packet.encode(val) - let val2 = packet.decode(buf) - const additional1 = val.additionals[0] - let additional2 = val2.additionals[0] - t.ok(compare(t, additional1.name, additional2.name), 'name matches') - t.ok(compare(t, additional1.udpPayloadSize, additional2.udpPayloadSize), 'udp payload size matches') - t.ok(compare(t, 0, additional2.flags), 'flags match') - additional1.flags = packet.DNSSEC_OK - additional1.extendedRcode = 0x80 - additional1.options = [ { - code: 'CLIENT_SUBNET', // edns-client-subnet, see RFC 7871 - ip: 'fe80::', - sourcePrefixLength: 64 - }, { - code: 8, // still ECS - ip: '5.6.0.0', - sourcePrefixLength: 16, - scopePrefixLength: 16 - }, { - code: 'padding', - length: 31 - }, { - code: 'TCP_KEEPALIVE' - }, { - code: 'tcp_keepalive', - timeout: 150 - }, { - code: 'KEY_TAG', - tags: [1, 82, 987] - }] - buf = packet.encode(val) - val2 = packet.decode(buf) - additional2 = val2.additionals[0] - t.ok(compare(t, 1 << 15, additional2.flags), 'DO bit set in flags') - t.ok(compare(t, true, additional2.flag_do), 'DO bit set') - t.ok(compare(t, additional1.extendedRcode, additional2.extendedRcode), 'extended rcode matches') - t.ok(compare(t, 8, additional2.options[0].code)) - t.ok(compare(t, 'fe80::', additional2.options[0].ip)) - t.ok(compare(t, 64, additional2.options[0].sourcePrefixLength)) - t.ok(compare(t, '5.6.0.0', additional2.options[1].ip)) - t.ok(compare(t, 16, additional2.options[1].sourcePrefixLength)) - t.ok(compare(t, 16, additional2.options[1].scopePrefixLength)) - t.ok(compare(t, additional1.options[2].length, additional2.options[2].data.length)) - t.ok(compare(t, additional1.options[3].timeout, undefined)) - t.ok(compare(t, additional1.options[4].timeout, additional2.options[4].timeout)) - t.ok(compare(t, additional1.options[5].tags, additional2.options[5].tags)) - t.end() -}) - -tape('dnskey', function (t) { - testEncoder(t, packet.dnskey, { - flags: packet.dnskey.SECURE_ENTRYPOINT | packet.dnskey.ZONE_KEY, - algorithm: 1, - key: Buffer.from([0, 1, 2, 3, 4, 5]) - }) - t.end() -}) - -tape('rrsig', function (t) { - const testRRSIG = { - typeCovered: 'A', - algorithm: 1, - labels: 2, - originalTTL: 3600, - expiration: 1234, - inception: 1233, - keyTag: 2345, - signersName: 'foo.com', - signature: Buffer.from([0, 1, 2, 3, 4, 5]) - } - testEncoder(t, packet.rrsig, testRRSIG) - - // Check the signature length is correct with extra junk at the end - const buf = Buffer.allocUnsafe(packet.rrsig.encodingLength(testRRSIG) + 4) - packet.rrsig.encode(testRRSIG, buf) - const val2 = packet.rrsig.decode(buf) - t.ok(compare(t, testRRSIG, val2)) - - t.end() -}) - -tape('rrp', function (t) { - testEncoder(t, packet.rp, { - mbox: 'foo.bar.com', - txt: 'baz.bar.com' - }) - testEncoder(t, packet.rp, { - mbox: 'foo.bar.com' - }) - testEncoder(t, packet.rp, { - txt: 'baz.bar.com' - }) - testEncoder(t, packet.rp, {}) - t.end() -}) - -tape('nsec', function (t) { - testEncoder(t, packet.nsec, { - nextDomain: 'foo.com', - rrtypes: ['A', 'DNSKEY', 'CAA', 'DLV'] - }) - testEncoder(t, packet.nsec, { - nextDomain: 'foo.com', - rrtypes: ['TXT'] // 16 - }) - testEncoder(t, packet.nsec, { - nextDomain: 'foo.com', - rrtypes: ['TKEY'] // 249 - }) - testEncoder(t, packet.nsec, { - nextDomain: 'foo.com', - rrtypes: ['RRSIG', 'NSEC'] - }) - testEncoder(t, packet.nsec, { - nextDomain: 'foo.com', - rrtypes: ['TXT', 'RRSIG'] - }) - testEncoder(t, packet.nsec, { - nextDomain: 'foo.com', - rrtypes: ['TXT', 'NSEC'] - }) - - // Test with the sample NSEC from https://tools.ietf.org/html/rfc4034#section-4.3 - var sampleNSEC = Buffer.from('003704686f7374076578616d706c6503636f6d00' + - '0006400100000003041b000000000000000000000000000000000000000000000' + - '000000020', 'hex') - var decoded = packet.nsec.decode(sampleNSEC) - t.ok(compare(t, decoded, { - nextDomain: 'host.example.com', - rrtypes: ['A', 'MX', 'RRSIG', 'NSEC', 'UNKNOWN_1234'] - })) - var reencoded = packet.nsec.encode(decoded) - t.same(sampleNSEC.length, reencoded.length) - t.same(sampleNSEC, reencoded) - t.end() -}) - -tape('nsec3', function (t) { - testEncoder(t, packet.nsec3, { - algorithm: 1, - flags: 0, - iterations: 257, - salt: Buffer.from([42, 42, 42]), - nextDomain: Buffer.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]), - rrtypes: ['A', 'DNSKEY', 'CAA', 'DLV'] - }) - t.end() -}) - -tape('ds', function (t) { - testEncoder(t, packet.ds, { - keyTag: 1234, - algorithm: 1, - digestType: 1, - digest: Buffer.from([0, 1, 2, 3, 4, 5]) - }) - t.end() -}) - -tape('unpack', function (t) { - const buf = Buffer.from([ - 0x00, 0x79, - 0xde, 0xad, 0x85, 0x00, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x02, 0x00, 0x02, 0x02, 0x6f, 0x6a, 0x05, - 0x62, 0x61, 0x6e, 0x67, 0x6a, 0x03, 0x63, 0x6f, - 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0, 0x0c, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x10, - 0x00, 0x04, 0x81, 0xfa, 0x0b, 0xaa, 0xc0, 0x0f, - 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x10, - 0x00, 0x05, 0x02, 0x63, 0x6a, 0xc0, 0x0f, 0xc0, - 0x0f, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x0e, - 0x10, 0x00, 0x02, 0xc0, 0x0c, 0xc0, 0x3a, 0x00, - 0x01, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x10, 0x00, - 0x04, 0x45, 0x4d, 0x9b, 0x9c, 0xc0, 0x0c, 0x00, - 0x1c, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x10, 0x00, - 0x10, 0x20, 0x01, 0x04, 0x18, 0x00, 0x00, 0x50, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf9 - ]) - const val = packet.streamDecode(buf) - const answer = val.answers[0] - const authority = val.authorities[1] - t.ok(val.rcode === 'NOERROR', 'decode rcode') - t.ok(compare(t, answer.type, 'A'), 'streamDecoded RR type match') - t.ok(compare(t, answer.name, 'oj.bangj.com'), 'streamDecoded RR name match') - t.ok(compare(t, answer.data, '129.250.11.170'), 'streamDecoded RR rdata match') - t.ok(compare(t, authority.type, 'NS'), 'streamDecoded RR type match') - t.ok(compare(t, authority.name, 'bangj.com'), 'streamDecoded RR name match') - t.ok(compare(t, authority.data, 'oj.bangj.com'), 'streamDecoded RR rdata match') - t.end() -}) - -tape('optioncodes', function (t) { - const opts = [ - [0, 'OPTION_0'], - [1, 'LLQ'], - [2, 'UL'], - [3, 'NSID'], - [4, 'OPTION_4'], - [5, 'DAU'], - [6, 'DHU'], - [7, 'N3U'], - [8, 'CLIENT_SUBNET'], - [9, 'EXPIRE'], - [10, 'COOKIE'], - [11, 'TCP_KEEPALIVE'], - [12, 'PADDING'], - [13, 'CHAIN'], - [14, 'KEY_TAG'], - [26946, 'DEVICEID'], - [65535, 'OPTION_65535'], - [64000, 'OPTION_64000'], - [65002, 'OPTION_65002'], - [-1, null] - ] - for (const [code, str] of opts) { - const s = optioncodes.toString(code) - t.ok(compare(t, s, str), `${code} => ${str}`) - t.ok(compare(t, optioncodes.toCode(s), code), `${str} => ${code}`) - } - t.ok(compare(t, optioncodes.toCode('INVALIDINVALID'), -1)) - t.end() -}) - -function testEncoder (t, rpacket, val) { - const buf = rpacket.encode(val) - const val2 = rpacket.decode(buf) - - t.same(buf.length, rpacket.encode.bytes, 'encode.bytes was set correctly') - t.same(buf.length, rpacket.encodingLength(val), 'encoding length matches') - t.ok(compare(t, val, val2), 'decoded object match') - - const buf2 = rpacket.encode(val2) - const val3 = rpacket.decode(buf2) - - t.same(buf2.length, rpacket.encode.bytes, 'encode.bytes was set correctly on re-encode') - t.same(buf2.length, rpacket.encodingLength(val), 'encoding length matches on re-encode') - - t.ok(compare(t, val, val3), 'decoded object match on re-encode') - t.ok(compare(t, val2, val3), 're-encoded decoded object match on re-encode') - - const bigger = Buffer.allocUnsafe(buf2.length + 10) - - const buf3 = rpacket.encode(val, bigger, 10) - const val4 = rpacket.decode(buf3, 10) - - t.ok(buf3 === bigger, 'echoes buffer on external buffer') - t.same(rpacket.encode.bytes, buf.length, 'encode.bytes is the same on external buffer') - t.ok(compare(t, val, val4), 'decoded object match on external buffer') -} - -function compare (t, a, b) { - if (Buffer.isBuffer(a)) return a.toString('hex') === b.toString('hex') - if (typeof a === 'object' && a && b) { - const keys = Object.keys(a) - for (let i = 0; i < keys.length; i++) { - if (!compare(t, a[keys[i]], b[keys[i]])) { - return false - } - } - } else if (Array.isArray(b) && !Array.isArray(a)) { - // TXT always decode as array - return a.toString() === b[0].toString() - } else { - return a === b - } - return true -} diff --git a/testing/xpcshell/dns-packet/types.js b/testing/xpcshell/dns-packet/types.js deleted file mode 100644 index 3cd78bd5e061..000000000000 --- a/testing/xpcshell/dns-packet/types.js +++ /dev/null @@ -1,103 +0,0 @@ -'use strict' - -exports.toString = function (type) { - switch (type) { - case 1: return 'A' - case 10: return 'NULL' - case 28: return 'AAAA' - case 18: return 'AFSDB' - case 42: return 'APL' - case 257: return 'CAA' - case 60: return 'CDNSKEY' - case 59: return 'CDS' - case 37: return 'CERT' - case 5: return 'CNAME' - case 49: return 'DHCID' - case 32769: return 'DLV' - case 39: return 'DNAME' - case 48: return 'DNSKEY' - case 43: return 'DS' - case 55: return 'HIP' - case 13: return 'HINFO' - case 45: return 'IPSECKEY' - case 25: return 'KEY' - case 36: return 'KX' - case 29: return 'LOC' - case 15: return 'MX' - case 35: return 'NAPTR' - case 2: return 'NS' - case 47: return 'NSEC' - case 50: return 'NSEC3' - case 51: return 'NSEC3PARAM' - case 12: return 'PTR' - case 46: return 'RRSIG' - case 17: return 'RP' - case 24: return 'SIG' - case 6: return 'SOA' - case 99: return 'SPF' - case 33: return 'SRV' - case 44: return 'SSHFP' - case 32768: return 'TA' - case 249: return 'TKEY' - case 52: return 'TLSA' - case 250: return 'TSIG' - case 16: return 'TXT' - case 252: return 'AXFR' - case 251: return 'IXFR' - case 41: return 'OPT' - case 255: return 'ANY' - } - return 'UNKNOWN_' + type -} - -exports.toType = function (name) { - switch (name.toUpperCase()) { - case 'A': return 1 - case 'NULL': return 10 - case 'AAAA': return 28 - case 'AFSDB': return 18 - case 'APL': return 42 - case 'CAA': return 257 - case 'CDNSKEY': return 60 - case 'CDS': return 59 - case 'CERT': return 37 - case 'CNAME': return 5 - case 'DHCID': return 49 - case 'DLV': return 32769 - case 'DNAME': return 39 - case 'DNSKEY': return 48 - case 'DS': return 43 - case 'HIP': return 55 - case 'HINFO': return 13 - case 'IPSECKEY': return 45 - case 'KEY': return 25 - case 'KX': return 36 - case 'LOC': return 29 - case 'MX': return 15 - case 'NAPTR': return 35 - case 'NS': return 2 - case 'NSEC': return 47 - case 'NSEC3': return 50 - case 'NSEC3PARAM': return 51 - case 'PTR': return 12 - case 'RRSIG': return 46 - case 'RP': return 17 - case 'SIG': return 24 - case 'SOA': return 6 - case 'SPF': return 99 - case 'SRV': return 33 - case 'SSHFP': return 44 - case 'TA': return 32768 - case 'TKEY': return 249 - case 'TLSA': return 52 - case 'TSIG': return 250 - case 'TXT': return 16 - case 'AXFR': return 252 - case 'IXFR': return 251 - case 'OPT': return 41 - case 'ANY': return 255 - case '*': return 255 - } - if (name.toUpperCase().startsWith('UNKNOWN_')) return parseInt(name.slice(8)) - return 0 -} diff --git a/testing/xpcshell/moz-http2/moz-http2.js b/testing/xpcshell/moz-http2/moz-http2.js index 9d2f0c33b665..2511615ff7b8 100644 --- a/testing/xpcshell/moz-http2/moz-http2.js +++ b/testing/xpcshell/moz-http2/moz-http2.js @@ -13,8 +13,6 @@ var http2 = require(node_http2_root); var fs = require('fs'); var url = require('url'); var crypto = require('crypto'); -const dnsPacket = require('../dns-packet'); -const ip = require('../node-ip'); // Hook into the decompression code to log the decompressed name-value pairs var compression_module = node_http2_root + "/lib/protocol/compressor"; @@ -552,97 +550,6 @@ function handleRequest(req, res) { return; } - else if (u.pathname == "/doh") { - ns_confirm = 0; // back to first reply for dns-confirm - cname_confirm = 0; // back to first reply for dns-cname - - let params = new url.URL(`http://localhost${req.url}`).searchParams; - let responseIP = params.get("responseIP"); - if (!responseIP) { - responseIP = "5.5.5.5"; - } - - if (params.get("auth")) { - // There's a Set-Cookie: header in the response for "/dns" , which this - // request subsequently would include if the http channel wasn't - // anonymous. Thus, if there's a cookie in this request, we know Firefox - // mishaved. If there's not, we're fine. - if (req.headers['cookie']) { - res.writeHead(403); - res.end("cookie for me, not for you"); - return; - } - if (req.headers['authorization'] != "user:password") { - res.writeHead(401); - res.end("bad boy!"); - return; - } - } - - if (params.get("push")) { - // push.example.com has AAAA entry 2018::2018 - var pcontent= new Buffer("0000010000010001000000000470757368076578616D706C6503636F6D00001C0001C00C001C000100000037001020180000000000000000000000002018", "hex"); - push = res.push({ - hostname: 'foo.example.com:' + serverPort, - port: serverPort, - path: '/dns-pushed-response?dns=AAAAAAABAAAAAAAABHB1c2gHZXhhbXBsZQNjb20AABwAAQ', - method: 'GET', - headers: { - 'accept' : 'application/dns-message' - } - }); - push.writeHead(200, { - 'content-type': 'application/dns-message', - 'pushed' : 'yes', - 'content-length' : pcontent.length, - 'X-Connection-Http2': 'yes' - }); - push.end(pcontent); - } - - let payload = new Buffer(""); - - function emitResponse(response, requestPayload) { - let packet = dnsPacket.decode(requestPayload); - - let buf = dnsPacket.encode({ - type: 'query', - id: packet.id, - flags: dnsPacket.RECURSION_DESIRED, - questions: packet.questions, - answers: [{ - name: packet.questions[0].name, - ttl: 55, - type: ip.isV4Format(responseIP) ? "A" : "AAAA", - flush: false, - data: responseIP, - }], - }); - - response.setHeader('Content-Length', buf.length); - response.setHeader('Set-Cookie', 'trackyou=yes; path=/; max-age=100000;'); - response.setHeader('Content-Type', 'application/dns-message'); - response.writeHead(200); - response.write(buf); - response.end(""); - return; - } - - if (params.get("dns")) { - payload = Buffer.from(params.get("dns"), 'base64'); - emitResponse(res, payload); - return; - } - - req.on('data', function receiveData(chunk) { - payload = Buffer.concat([payload, chunk]); - }); - req.on('end', function finishedData() { - emitResponse(res, payload); - return; - }); - return; - } else if (u.pathname === "/dns-cname-a") { // test23 asks for cname-a.example.com // this responds with a CNAME to here.example.com *and* an A record @@ -696,6 +603,57 @@ function handleRequest(req, res) { res.end(""); return; + } + // for use with test_trr.js, test8b + else if (u.path === "/dns-ecs?dns=AAABAAABAAAAAAABA2VjcwdleGFtcGxlA2NvbQAAAQABAAApEAAAAAAAAAgACAAEAAEAAA") { + // the query string asks for an A entry for ecs.example.com + // ecs.example.com has A entry 5.5.5.5 + var content= new Buffer("00000100000100010000000003656373076578616D706C6503636F6D0000010001C00C0001000100000037000405050505", "hex"); + res.setHeader('Content-Type', 'application/dns-message'); + res.setHeader('Content-Length', content.length); + res.writeHead(200); + res.write(content); + res.end(""); + return; + } + // for use with test_trr.js + else if (u.path === "/dns-get?dns=AAABAAABAAAAAAAAA2dldAdleGFtcGxlA2NvbQAAAQAB") { + // the query string asks for an A entry for get.example.com + // get.example.com has A entry 1.2.3.4 + var content= new Buffer("00000100000100010000000003676574076578616D706C6503636F6D0000010001C00C0001000100000037000401020304", "hex"); + res.setHeader('Content-Type', 'application/dns-message'); + res.setHeader('Content-Length', content.length); + res.writeHead(200); + res.write(content); + res.end(""); + ns_confirm = 0; // back to first reply for dns-confirm + cname_confirm = 0; // back to first reply for dns-cname + return; + } + // for use with test_trr.js + else if (u.pathname === "/dns") { + // bar.example.com has A entry 127.0.0.1 + var content= new Buffer("00000100000100010000000003626172076578616D706C6503636F6D0000010001C00C000100010000003700047F000001", "hex"); + res.setHeader('Content-Type', 'application/dns-message'); + res.setHeader('Content-Length', content.length); + // pass back a cookie here, check it in /dns-auth + res.setHeader('Set-Cookie', 'trackyou=yes; path=/; max-age=100000;'); + res.writeHead(200); + res.write(content); + res.end(""); + return; + } + else if (u.pathname === "/dns-ip") { + // bar.example.com has A entry 192.192.192.192 + var content= new Buffer("00000100000100010000000003626172076578616D706C6503636F6D0000010001C00C00010001000000370004C0C0C0C0", "hex"); + res.setHeader('Content-Type', 'application/dns-message'); + res.setHeader('Content-Length', content.length); + // pass back a cookie here, check it in /dns-auth + res.setHeader('Set-Cookie', 'trackyou=yes; path=/; max-age=100000;'); + res.writeHead(200); + res.write(content); + res.end(""); + return; } else if (u.pathname === "/dns-ns") { // confirm.example.com has NS entry ns.example.com @@ -736,6 +694,82 @@ function handleRequest(req, res) { res.end(""); return; } + // for use with test_trr.js + else if (u.pathname === "/dns-aaaa") { + // aaaa.example.com has AAAA entry 2020:2020::2020 + var content= new Buffer("0000010000010001000000000461616161076578616D706C6503636F6D00001C0001C00C001C000100000037001020202020000000000000000000002020", "hex"); + res.setHeader('Content-Type', 'application/dns-message'); + res.setHeader('Content-Length', content.length); + res.writeHead(200); + res.write(content); + res.end(""); + return; + } + else if (u.pathname === "/dns-rfc1918") { + // rfc1918.example.com has A entry 192.168.0.1 + var content= new Buffer("0000010000010001000000000772666331393138076578616D706C6503636F6D0000010001C00C00010001000000370004C0A80001", "hex"); + res.setHeader('Content-Type', 'application/dns-message'); + res.setHeader('Content-Length', content.length); + res.writeHead(200); + res.write(content); + res.end(""); + return; + } + // for use with test_trr.js + else if (u.pathname === "/dns-push") { + // first.example.com has A entry 127.0.0.1 + var content= new Buffer("000001000001000100000000056669727374076578616D706C6503636F6D0000010001C00C000100010000003700047F000001", "hex"); + // push.example.com has AAAA entry 2018::2018 + var pcontent= new Buffer("0000010000010001000000000470757368076578616D706C6503636F6D00001C0001C00C001C000100000037001020180000000000000000000000002018", "hex"); + push = res.push({ + hostname: 'foo.example.com:' + serverPort, + port: serverPort, + path: '/dns-pushed-response?dns=AAAAAAABAAAAAAAABHB1c2gHZXhhbXBsZQNjb20AABwAAQ', + method: 'GET', + headers: { + 'accept' : 'application/dns-message' + } + }); + push.writeHead(200, { + 'content-type': 'application/dns-message', + 'pushed' : 'yes', + 'content-length' : pcontent.length, + 'X-Connection-Http2': 'yes' + }); + push.end(pcontent); + res.setHeader('Content-Type', 'application/dns-message'); + res.setHeader('Content-Length', content.length); + res.writeHead(200); + res.write(content); + res.end(""); + return; + } + // for use with test_trr.js + else if (u.pathname === "/dns-auth") { + // There's a Set-Cookie: header in the response for "/dns" , which this + // request subsequently would include if the http channel wasn't + // anonymous. Thus, if there's a cookie in this request, we know Firefox + // mishaved. If there's not, we're fine. + if (req.headers['cookie']) { + res.writeHead(403); + res.end("cookie for me, not for you"); + return; + } + if (req.headers['authorization'] != "user:password") { + res.writeHead(401); + res.end("bad boy!"); + return; + } + // bar.example.com has A entry 127.0.0.1 + var content= new Buffer("00000100000100010000000003626172076578616D706C6503636F6D0000010001C00C000100010000003700047F000001", "hex"); + res.setHeader('Content-Type', 'application/dns-message'); + res.setHeader('Content-Length', content.length); + res.writeHead(200); + res.write(content); + res.end(""); + return; + } + // for use with test_esni_dns_fetch.js else if (u.pathname === "/esni-dns") { content = new Buffer("0000" + diff --git a/testing/xpcshell/node-ip/.gitignore b/testing/xpcshell/node-ip/.gitignore deleted file mode 100644 index 1ca957177f03..000000000000 --- a/testing/xpcshell/node-ip/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules/ -npm-debug.log diff --git a/testing/xpcshell/node-ip/.jscsrc b/testing/xpcshell/node-ip/.jscsrc deleted file mode 100644 index dbaae20574de..000000000000 --- a/testing/xpcshell/node-ip/.jscsrc +++ /dev/null @@ -1,46 +0,0 @@ -{ - "disallowKeywordsOnNewLine": [ "else" ], - "disallowMixedSpacesAndTabs": true, - "disallowMultipleLineStrings": true, - "disallowMultipleVarDecl": true, - "disallowNewlineBeforeBlockStatements": true, - "disallowQuotedKeysInObjects": true, - "disallowSpaceAfterObjectKeys": true, - "disallowSpaceAfterPrefixUnaryOperators": true, - "disallowSpaceBeforePostfixUnaryOperators": true, - "disallowSpacesInCallExpression": true, - "disallowTrailingComma": true, - "disallowTrailingWhitespace": true, - "disallowYodaConditions": true, - - "requireCommaBeforeLineBreak": true, - "requireOperatorBeforeLineBreak": true, - "requireSpaceAfterBinaryOperators": true, - "requireSpaceAfterKeywords": [ "if", "for", "while", "else", "try", "catch" ], - "requireSpaceAfterLineComment": true, - "requireSpaceBeforeBinaryOperators": true, - "requireSpaceBeforeBlockStatements": true, - "requireSpaceBeforeKeywords": [ "else", "catch" ], - "requireSpaceBeforeObjectValues": true, - "requireSpaceBetweenArguments": true, - "requireSpacesInAnonymousFunctionExpression": { - "beforeOpeningCurlyBrace": true - }, - "requireSpacesInFunctionDeclaration": { - "beforeOpeningCurlyBrace": true - }, - "requireSpacesInFunctionExpression": { - "beforeOpeningCurlyBrace": true - }, - "requireSpacesInConditionalExpression": true, - "requireSpacesInForStatement": true, - "requireSpacesInsideArrayBrackets": "all", - "requireSpacesInsideObjectBrackets": "all", - "requireDotNotation": true, - - "maximumLineLength": 80, - "validateIndentation": 2, - "validateLineBreaks": "LF", - "validateParameterSeparator": ", ", - "validateQuoteMarks": "'" -} diff --git a/testing/xpcshell/node-ip/.jshintrc b/testing/xpcshell/node-ip/.jshintrc deleted file mode 100644 index 7e973902952b..000000000000 --- a/testing/xpcshell/node-ip/.jshintrc +++ /dev/null @@ -1,89 +0,0 @@ -{ - // JSHint Default Configuration File (as on JSHint website) - // See http://jshint.com/docs/ for more details - - "maxerr" : 50, // {int} Maximum error before stopping - - // Enforcing - "bitwise" : false, // true: Prohibit bitwise operators (&, |, ^, etc.) - "camelcase" : false, // true: Identifiers must be in camelCase - "curly" : false, // true: Require {} for every new block or scope - "eqeqeq" : true, // true: Require triple equals (===) for comparison - "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty() - "freeze" : true, // true: prohibits overwriting prototypes of native objects such as Array, Date etc. - "immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());` - "indent" : 2, // {int} Number of spaces to use for indentation - "latedef" : true, // true: Require variables/functions to be defined before being used - "newcap" : true, // true: Require capitalization of all constructor functions e.g. `new F()` - "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee` - "noempty" : false, // true: Prohibit use of empty blocks - "nonbsp" : true, // true: Prohibit "non-breaking whitespace" characters. - "nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment) - "plusplus" : false, // true: Prohibit use of `++` & `--` - "quotmark" : "single", // Quotation mark consistency: - // false : do nothing (default) - // true : ensure whatever is used is consistent - // "single" : require single quotes - // "double" : require double quotes - "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks) - "unused" : true, // true: Require all defined variables be used - "strict" : true, // true: Requires all functions run in ES5 Strict Mode - "maxparams" : false, // {int} Max number of formal params allowed per function - "maxdepth" : 3, // {int} Max depth of nested blocks (within functions) - "maxstatements" : false, // {int} Max number statements per function - "maxcomplexity" : false, // {int} Max cyclomatic complexity per function - "maxlen" : false, // {int} Max number of characters per line - - // Relaxing - "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons) - "boss" : false, // true: Tolerate assignments where comparisons would be expected - "debug" : false, // true: Allow debugger statements e.g. browser breakpoints. - "eqnull" : false, // true: Tolerate use of `== null` - "es5" : false, // true: Allow ES5 syntax (ex: getters and setters) - "esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`) - "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features) - // (ex: `for each`, multiple try/catch, function expression…) - "evil" : false, // true: Tolerate use of `eval` and `new Function()` - "expr" : false, // true: Tolerate `ExpressionStatement` as Programs - "funcscope" : false, // true: Tolerate defining variables inside control statements - "globalstrict" : false, // true: Allow global "use strict" (also enables 'strict') - "iterator" : false, // true: Tolerate using the `__iterator__` property - "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block - "laxbreak" : false, // true: Tolerate possibly unsafe line breakings - "laxcomma" : false, // true: Tolerate comma-first style coding - "loopfunc" : false, // true: Tolerate functions being defined in loops - "multistr" : false, // true: Tolerate multi-line strings - "noyield" : false, // true: Tolerate generator functions with no yield statement in them. - "notypeof" : false, // true: Tolerate invalid typeof operator values - "proto" : false, // true: Tolerate using the `__proto__` property - "scripturl" : false, // true: Tolerate script-targeted URLs - "shadow" : true, // true: Allows re-define variables later in code e.g. `var x=1; x=2;` - "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation - "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;` - "validthis" : false, // true: Tolerate using this in a non-constructor function - - // Environments - "browser" : true, // Web Browser (window, document, etc) - "browserify" : true, // Browserify (node.js code in the browser) - "couch" : false, // CouchDB - "devel" : true, // Development/debugging (alert, confirm, etc) - "dojo" : false, // Dojo Toolkit - "jasmine" : false, // Jasmine - "jquery" : false, // jQuery - "mocha" : true, // Mocha - "mootools" : false, // MooTools - "node" : true, // Node.js - "nonstandard" : false, // Widely adopted globals (escape, unescape, etc) - "prototypejs" : false, // Prototype and Scriptaculous - "qunit" : false, // QUnit - "rhino" : false, // Rhino - "shelljs" : false, // ShellJS - "worker" : false, // Web Workers - "wsh" : false, // Windows Scripting Host - "yui" : false, // Yahoo User Interface - - // Custom Globals - "globals" : { - "module": true - } // additional predefined global variables -} diff --git a/testing/xpcshell/node-ip/.travis.yml b/testing/xpcshell/node-ip/.travis.yml deleted file mode 100644 index a3a8fad6b6e3..000000000000 --- a/testing/xpcshell/node-ip/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -sudo: false -language: node_js -node_js: - - "0.8" - - "0.10" - - "0.12" - - "4" - - "6" - -before_install: - - travis_retry npm install -g npm@2.14.5 - - travis_retry npm install - -script: - - npm test diff --git a/testing/xpcshell/node-ip/README.md b/testing/xpcshell/node-ip/README.md deleted file mode 100644 index 22e5819ffaf9..000000000000 --- a/testing/xpcshell/node-ip/README.md +++ /dev/null @@ -1,90 +0,0 @@ -# IP -[![](https://badge.fury.io/js/ip.svg)](https://www.npmjs.com/package/ip) - -IP address utilities for node.js - -## Installation - -### npm -```shell -npm install ip -``` - -### git - -```shell -git clone https://github.com/indutny/node-ip.git -``` - -## Usage -Get your ip address, compare ip addresses, validate ip addresses, etc. - -```js -var ip = require('ip'); - -ip.address() // my ip address -ip.isEqual('::1', '::0:1'); // true -ip.toBuffer('127.0.0.1') // Buffer([127, 0, 0, 1]) -ip.toString(new Buffer([127, 0, 0, 1])) // 127.0.0.1 -ip.fromPrefixLen(24) // 255.255.255.0 -ip.mask('192.168.1.134', '255.255.255.0') // 192.168.1.0 -ip.cidr('192.168.1.134/26') // 192.168.1.128 -ip.not('255.255.255.0') // 0.0.0.255 -ip.or('192.168.1.134', '0.0.0.255') // 192.168.1.255 -ip.isPrivate('127.0.0.1') // true -ip.isV4Format('127.0.0.1'); // true -ip.isV6Format('::ffff:127.0.0.1'); // true - -// operate on buffers in-place -var buf = new Buffer(128); -var offset = 64; -ip.toBuffer('127.0.0.1', buf, offset); // [127, 0, 0, 1] at offset 64 -ip.toString(buf, offset, 4); // '127.0.0.1' - -// subnet information -ip.subnet('192.168.1.134', '255.255.255.192') -// { networkAddress: '192.168.1.128', -// firstAddress: '192.168.1.129', -// lastAddress: '192.168.1.190', -// broadcastAddress: '192.168.1.191', -// subnetMask: '255.255.255.192', -// subnetMaskLength: 26, -// numHosts: 62, -// length: 64, -// contains: function(addr){...} } -ip.cidrSubnet('192.168.1.134/26') -// Same as previous. - -// range checking -ip.cidrSubnet('192.168.1.134/26').contains('192.168.1.190') // true - - -// ipv4 long conversion -ip.toLong('127.0.0.1'); // 2130706433 -ip.fromLong(2130706433); // '127.0.0.1' -``` - -### License - -This software is licensed under the MIT License. - -Copyright Fedor Indutny, 2012. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to permit -persons to whom the Software is furnished to do so, subject to the -following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/testing/xpcshell/node-ip/lib/ip.js b/testing/xpcshell/node-ip/lib/ip.js deleted file mode 100644 index c1799a8c50f4..000000000000 --- a/testing/xpcshell/node-ip/lib/ip.js +++ /dev/null @@ -1,416 +0,0 @@ -'use strict'; - -var ip = exports; -var Buffer = require('buffer').Buffer; -var os = require('os'); - -ip.toBuffer = function(ip, buff, offset) { - offset = ~~offset; - - var result; - - if (this.isV4Format(ip)) { - result = buff || new Buffer(offset + 4); - ip.split(/\./g).map(function(byte) { - result[offset++] = parseInt(byte, 10) & 0xff; - }); - } else if (this.isV6Format(ip)) { - var sections = ip.split(':', 8); - - var i; - for (i = 0; i < sections.length; i++) { - var isv4 = this.isV4Format(sections[i]); - var v4Buffer; - - if (isv4) { - v4Buffer = this.toBuffer(sections[i]); - sections[i] = v4Buffer.slice(0, 2).toString('hex'); - } - - if (v4Buffer && ++i < 8) { - sections.splice(i, 0, v4Buffer.slice(2, 4).toString('hex')); - } - } - - if (sections[0] === '') { - while (sections.length < 8) sections.unshift('0'); - } else if (sections[sections.length - 1] === '') { - while (sections.length < 8) sections.push('0'); - } else if (sections.length < 8) { - for (i = 0; i < sections.length && sections[i] !== ''; i++); - var argv = [ i, 1 ]; - for (i = 9 - sections.length; i > 0; i--) { - argv.push('0'); - } - sections.splice.apply(sections, argv); - } - - result = buff || new Buffer(offset + 16); - for (i = 0; i < sections.length; i++) { - var word = parseInt(sections[i], 16); - result[offset++] = (word >> 8) & 0xff; - result[offset++] = word & 0xff; - } - } - - if (!result) { - throw Error('Invalid ip address: ' + ip); - } - - return result; -}; - -ip.toString = function(buff, offset, length) { - offset = ~~offset; - length = length || (buff.length - offset); - - var result = []; - if (length === 4) { - // IPv4 - for (var i = 0; i < length; i++) { - result.push(buff[offset + i]); - } - result = result.join('.'); - } else if (length === 16) { - // IPv6 - for (var i = 0; i < length; i += 2) { - result.push(buff.readUInt16BE(offset + i).toString(16)); - } - result = result.join(':'); - result = result.replace(/(^|:)0(:0)*:0(:|$)/, '$1::$3'); - result = result.replace(/:{3,4}/, '::'); - } - - return result; -}; - -var ipv4Regex = /^(\d{1,3}\.){3,3}\d{1,3}$/; -var ipv6Regex = - /^(::)?(((\d{1,3}\.){3}(\d{1,3}){1})?([0-9a-f]){0,4}:{0,2}){1,8}(::)?$/i; - -ip.isV4Format = function(ip) { - return ipv4Regex.test(ip); -}; - -ip.isV6Format = function(ip) { - return ipv6Regex.test(ip); -}; -function _normalizeFamily(family) { - return family ? family.toLowerCase() : 'ipv4'; -} - -ip.fromPrefixLen = function(prefixlen, family) { - if (prefixlen > 32) { - family = 'ipv6'; - } else { - family = _normalizeFamily(family); - } - - var len = 4; - if (family === 'ipv6') { - len = 16; - } - var buff = new Buffer(len); - - for (var i = 0, n = buff.length; i < n; ++i) { - var bits = 8; - if (prefixlen < 8) { - bits = prefixlen; - } - prefixlen -= bits; - - buff[i] = ~(0xff >> bits) & 0xff; - } - - return ip.toString(buff); -}; - -ip.mask = function(addr, mask) { - addr = ip.toBuffer(addr); - mask = ip.toBuffer(mask); - - var result = new Buffer(Math.max(addr.length, mask.length)); - - var i = 0; - // Same protocol - do bitwise and - if (addr.length === mask.length) { - for (i = 0; i < addr.length; i++) { - result[i] = addr[i] & mask[i]; - } - } else if (mask.length === 4) { - // IPv6 address and IPv4 mask - // (Mask low bits) - for (i = 0; i < mask.length; i++) { - result[i] = addr[addr.length - 4 + i] & mask[i]; - } - } else { - // IPv6 mask and IPv4 addr - for (var i = 0; i < result.length - 6; i++) { - result[i] = 0; - } - - // ::ffff:ipv4 - result[10] = 0xff; - result[11] = 0xff; - for (i = 0; i < addr.length; i++) { - result[i + 12] = addr[i] & mask[i + 12]; - } - i = i + 12; - } - for (; i < result.length; i++) - result[i] = 0; - - return ip.toString(result); -}; - -ip.cidr = function(cidrString) { - var cidrParts = cidrString.split('/'); - - var addr = cidrParts[0]; - if (cidrParts.length !== 2) - throw new Error('invalid CIDR subnet: ' + addr); - - var mask = ip.fromPrefixLen(parseInt(cidrParts[1], 10)); - - return ip.mask(addr, mask); -}; - -ip.subnet = function(addr, mask) { - var networkAddress = ip.toLong(ip.mask(addr, mask)); - - // Calculate the mask's length. - var maskBuffer = ip.toBuffer(mask); - var maskLength = 0; - - for (var i = 0; i < maskBuffer.length; i++) { - if (maskBuffer[i] === 0xff) { - maskLength += 8; - } else { - var octet = maskBuffer[i] & 0xff; - while (octet) { - octet = (octet << 1) & 0xff; - maskLength++; - } - } - } - - var numberOfAddresses = Math.pow(2, 32 - maskLength); - - return { - networkAddress: ip.fromLong(networkAddress), - firstAddress: numberOfAddresses <= 2 ? - ip.fromLong(networkAddress) : - ip.fromLong(networkAddress + 1), - lastAddress: numberOfAddresses <= 2 ? - ip.fromLong(networkAddress + numberOfAddresses - 1) : - ip.fromLong(networkAddress + numberOfAddresses - 2), - broadcastAddress: ip.fromLong(networkAddress + numberOfAddresses - 1), - subnetMask: mask, - subnetMaskLength: maskLength, - numHosts: numberOfAddresses <= 2 ? - numberOfAddresses : numberOfAddresses - 2, - length: numberOfAddresses, - contains: function(other) { - return networkAddress === ip.toLong(ip.mask(other, mask)); - } - }; -}; - -ip.cidrSubnet = function(cidrString) { - var cidrParts = cidrString.split('/'); - - var addr = cidrParts[0]; - if (cidrParts.length !== 2) - throw new Error('invalid CIDR subnet: ' + addr); - - var mask = ip.fromPrefixLen(parseInt(cidrParts[1], 10)); - - return ip.subnet(addr, mask); -}; - -ip.not = function(addr) { - var buff = ip.toBuffer(addr); - for (var i = 0; i < buff.length; i++) { - buff[i] = 0xff ^ buff[i]; - } - return ip.toString(buff); -}; - -ip.or = function(a, b) { - a = ip.toBuffer(a); - b = ip.toBuffer(b); - - // same protocol - if (a.length === b.length) { - for (var i = 0; i < a.length; ++i) { - a[i] |= b[i]; - } - return ip.toString(a); - - // mixed protocols - } else { - var buff = a; - var other = b; - if (b.length > a.length) { - buff = b; - other = a; - } - - var offset = buff.length - other.length; - for (var i = offset; i < buff.length; ++i) { - buff[i] |= other[i - offset]; - } - - return ip.toString(buff); - } -}; - -ip.isEqual = function(a, b) { - a = ip.toBuffer(a); - b = ip.toBuffer(b); - - // Same protocol - if (a.length === b.length) { - for (var i = 0; i < a.length; i++) { - if (a[i] !== b[i]) return false; - } - return true; - } - - // Swap - if (b.length === 4) { - var t = b; - b = a; - a = t; - } - - // a - IPv4, b - IPv6 - for (var i = 0; i < 10; i++) { - if (b[i] !== 0) return false; - } - - var word = b.readUInt16BE(10); - if (word !== 0 && word !== 0xffff) return false; - - for (var i = 0; i < 4; i++) { - if (a[i] !== b[i + 12]) return false; - } - - return true; -}; - -ip.isPrivate = function(addr) { - return /^(::f{4}:)?10\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i - .test(addr) || - /^(::f{4}:)?192\.168\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) || - /^(::f{4}:)?172\.(1[6-9]|2\d|30|31)\.([0-9]{1,3})\.([0-9]{1,3})$/i - .test(addr) || - /^(::f{4}:)?127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) || - /^(::f{4}:)?169\.254\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) || - /^f[cd][0-9a-f]{2}:/i.test(addr) || - /^fe80:/i.test(addr) || - /^::1$/.test(addr) || - /^::$/.test(addr); -}; - -ip.isPublic = function(addr) { - return !ip.isPrivate(addr); -}; - -ip.isLoopback = function(addr) { - return /^(::f{4}:)?127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/ - .test(addr) || - /^fe80::1$/.test(addr) || - /^::1$/.test(addr) || - /^::$/.test(addr); -}; - -ip.loopback = function(family) { - // - // Default to `ipv4` - // - family = _normalizeFamily(family); - - if (family !== 'ipv4' && family !== 'ipv6') { - throw new Error('family must be ipv4 or ipv6'); - } - - return family === 'ipv4' ? '127.0.0.1' : 'fe80::1'; -}; - -// -// ### function address (name, family) -// #### @name {string|'public'|'private'} **Optional** Name or security -// of the network interface. -// #### @family {ipv4|ipv6} **Optional** IP family of the address (defaults -// to ipv4). -// -// Returns the address for the network interface on the current system with -// the specified `name`: -// * String: First `family` address of the interface. -// If not found see `undefined`. -// * 'public': the first public ip address of family. -// * 'private': the first private ip address of family. -// * undefined: First address with `ipv4` or loopback address `127.0.0.1`. -// -ip.address = function(name, family) { - var interfaces = os.networkInterfaces(); - var all; - - // - // Default to `ipv4` - // - family = _normalizeFamily(family); - - // - // If a specific network interface has been named, - // return the address. - // - if (name && name !== 'private' && name !== 'public') { - var res = interfaces[name].filter(function(details) { - var itemFamily = details.family.toLowerCase(); - return itemFamily === family; - }); - if (res.length === 0) - return undefined; - return res[0].address; - } - - var all = Object.keys(interfaces).map(function (nic) { - // - // Note: name will only be `public` or `private` - // when this is called. - // - var addresses = interfaces[nic].filter(function (details) { - details.family = details.family.toLowerCase(); - if (details.family !== family || ip.isLoopback(details.address)) { - return false; - } else if (!name) { - return true; - } - - return name === 'public' ? ip.isPrivate(details.address) : - ip.isPublic(details.address); - }); - - return addresses.length ? addresses[0].address : undefined; - }).filter(Boolean); - - return !all.length ? ip.loopback(family) : all[0]; -}; - -ip.toLong = function(ip) { - var ipl = 0; - ip.split('.').forEach(function(octet) { - ipl <<= 8; - ipl += parseInt(octet); - }); - return(ipl >>> 0); -}; - -ip.fromLong = function(ipl) { - return ((ipl >>> 24) + '.' + - (ipl >> 16 & 255) + '.' + - (ipl >> 8 & 255) + '.' + - (ipl & 255) ); -}; diff --git a/testing/xpcshell/node-ip/package.json b/testing/xpcshell/node-ip/package.json deleted file mode 100644 index c783fdd43767..000000000000 --- a/testing/xpcshell/node-ip/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "ip", - "version": "1.1.5", - "author": "Fedor Indutny ", - "homepage": "https://github.com/indutny/node-ip", - "repository": { - "type": "git", - "url": "http://github.com/indutny/node-ip.git" - }, - "main": "lib/ip", - "devDependencies": { - "jscs": "^2.1.1", - "jshint": "^2.8.0", - "mocha": "~1.3.2" - }, - "scripts": { - "test": "jscs lib/*.js test/*.js && jshint lib/*.js && mocha --reporter spec test/*-test.js", - "fix": "jscs lib/*.js test/*.js --fix" - }, - "license": "MIT" -} diff --git a/testing/xpcshell/node-ip/test/api-test.js b/testing/xpcshell/node-ip/test/api-test.js deleted file mode 100644 index 2e390f986d0b..000000000000 --- a/testing/xpcshell/node-ip/test/api-test.js +++ /dev/null @@ -1,407 +0,0 @@ -'use strict'; - -var ip = require('..'); -var assert = require('assert'); -var net = require('net'); -var os = require('os'); - -describe('IP library for node.js', function() { - describe('toBuffer()/toString() methods', function() { - it('should convert to buffer IPv4 address', function() { - var buf = ip.toBuffer('127.0.0.1'); - assert.equal(buf.toString('hex'), '7f000001'); - assert.equal(ip.toString(buf), '127.0.0.1'); - }); - - it('should convert to buffer IPv4 address in-place', function() { - var buf = new Buffer(128); - var offset = 64; - ip.toBuffer('127.0.0.1', buf, offset); - assert.equal(buf.toString('hex', offset, offset + 4), '7f000001'); - assert.equal(ip.toString(buf, offset, 4), '127.0.0.1'); - }); - - it('should convert to buffer IPv6 address', function() { - var buf = ip.toBuffer('::1'); - assert(/(00){15,15}01/.test(buf.toString('hex'))); - assert.equal(ip.toString(buf), '::1'); - assert.equal(ip.toString(ip.toBuffer('1::')), '1::'); - assert.equal(ip.toString(ip.toBuffer('abcd::dcba')), 'abcd::dcba'); - }); - - it('should convert to buffer IPv6 address in-place', function() { - var buf = new Buffer(128); - var offset = 64; - ip.toBuffer('::1', buf, offset); - assert(/(00){15,15}01/.test(buf.toString('hex', offset, offset + 16))); - assert.equal(ip.toString(buf, offset, 16), '::1'); - assert.equal(ip.toString(ip.toBuffer('1::', buf, offset), - offset, 16), '1::'); - assert.equal(ip.toString(ip.toBuffer('abcd::dcba', buf, offset), - offset, 16), 'abcd::dcba'); - }); - - it('should convert to buffer IPv6 mapped IPv4 address', function() { - var buf = ip.toBuffer('::ffff:127.0.0.1'); - assert.equal(buf.toString('hex'), '00000000000000000000ffff7f000001'); - assert.equal(ip.toString(buf), '::ffff:7f00:1'); - - buf = ip.toBuffer('ffff::127.0.0.1'); - assert.equal(buf.toString('hex'), 'ffff000000000000000000007f000001'); - assert.equal(ip.toString(buf), 'ffff::7f00:1'); - - buf = ip.toBuffer('0:0:0:0:0:ffff:127.0.0.1'); - assert.equal(buf.toString('hex'), '00000000000000000000ffff7f000001'); - assert.equal(ip.toString(buf), '::ffff:7f00:1'); - }); - }); - - describe('fromPrefixLen() method', function() { - it('should create IPv4 mask', function() { - assert.equal(ip.fromPrefixLen(24), '255.255.255.0'); - }); - it('should create IPv6 mask', function() { - assert.equal(ip.fromPrefixLen(64), 'ffff:ffff:ffff:ffff::'); - }); - it('should create IPv6 mask explicitly', function() { - assert.equal(ip.fromPrefixLen(24, 'IPV6'), 'ffff:ff00::'); - }); - }); - - describe('not() method', function() { - it('should reverse bits in address', function() { - assert.equal(ip.not('255.255.255.0'), '0.0.0.255'); - }); - }); - - describe('or() method', function() { - it('should or bits in ipv4 addresses', function() { - assert.equal(ip.or('0.0.0.255', '192.168.1.10'), '192.168.1.255'); - }); - it('should or bits in ipv6 addresses', function() { - assert.equal(ip.or('::ff', '::abcd:dcba:abcd:dcba'), - '::abcd:dcba:abcd:dcff'); - }); - it('should or bits in mixed addresses', function() { - assert.equal(ip.or('0.0.0.255', '::abcd:dcba:abcd:dcba'), - '::abcd:dcba:abcd:dcff'); - }); - }); - - describe('mask() method', function() { - it('should mask bits in address', function() { - assert.equal(ip.mask('192.168.1.134', '255.255.255.0'), '192.168.1.0'); - assert.equal(ip.mask('192.168.1.134', '::ffff:ff00'), '::ffff:c0a8:100'); - }); - - it('should not leak data', function() { - for (var i = 0; i < 10; i++) - assert.equal(ip.mask('::1', '0.0.0.0'), '::'); - }); - }); - - describe('subnet() method', function() { - // Test cases calculated with http://www.subnet-calculator.com/ - var ipv4Subnet = ip.subnet('192.168.1.134', '255.255.255.192'); - - it('should compute ipv4 network address', function() { - assert.equal(ipv4Subnet.networkAddress, '192.168.1.128'); - }); - - it('should compute ipv4 network\'s first address', function() { - assert.equal(ipv4Subnet.firstAddress, '192.168.1.129'); - }); - - it('should compute ipv4 network\'s last address', function() { - assert.equal(ipv4Subnet.lastAddress, '192.168.1.190'); - }); - - it('should compute ipv4 broadcast address', function() { - assert.equal(ipv4Subnet.broadcastAddress, '192.168.1.191'); - }); - - it('should compute ipv4 subnet number of addresses', function() { - assert.equal(ipv4Subnet.length, 64); - }); - - it('should compute ipv4 subnet number of addressable hosts', function() { - assert.equal(ipv4Subnet.numHosts, 62); - }); - - it('should compute ipv4 subnet mask', function() { - assert.equal(ipv4Subnet.subnetMask, '255.255.255.192'); - }); - - it('should compute ipv4 subnet mask\'s length', function() { - assert.equal(ipv4Subnet.subnetMaskLength, 26); - }); - - it('should know whether a subnet contains an address', function() { - assert.equal(ipv4Subnet.contains('192.168.1.180'), true); - }); - - it('should know whether a subnet does not contain an address', function() { - assert.equal(ipv4Subnet.contains('192.168.1.195'), false); - }); - }); - - describe('subnet() method with mask length 32', function() { - // Test cases calculated with http://www.subnet-calculator.com/ - var ipv4Subnet = ip.subnet('192.168.1.134', '255.255.255.255'); - it('should compute ipv4 network\'s first address', function() { - assert.equal(ipv4Subnet.firstAddress, '192.168.1.134'); - }); - - it('should compute ipv4 network\'s last address', function() { - assert.equal(ipv4Subnet.lastAddress, '192.168.1.134'); - }); - - it('should compute ipv4 subnet number of addressable hosts', function() { - assert.equal(ipv4Subnet.numHosts, 1); - }); - }); - - describe('subnet() method with mask length 31', function() { - // Test cases calculated with http://www.subnet-calculator.com/ - var ipv4Subnet = ip.subnet('192.168.1.134', '255.255.255.254'); - it('should compute ipv4 network\'s first address', function() { - assert.equal(ipv4Subnet.firstAddress, '192.168.1.134'); - }); - - it('should compute ipv4 network\'s last address', function() { - assert.equal(ipv4Subnet.lastAddress, '192.168.1.135'); - }); - - it('should compute ipv4 subnet number of addressable hosts', function() { - assert.equal(ipv4Subnet.numHosts, 2); - }); - }); - - describe('cidrSubnet() method', function() { - // Test cases calculated with http://www.subnet-calculator.com/ - var ipv4Subnet = ip.cidrSubnet('192.168.1.134/26'); - - it('should compute an ipv4 network address', function() { - assert.equal(ipv4Subnet.networkAddress, '192.168.1.128'); - }); - - it('should compute an ipv4 network\'s first address', function() { - assert.equal(ipv4Subnet.firstAddress, '192.168.1.129'); - }); - - it('should compute an ipv4 network\'s last address', function() { - assert.equal(ipv4Subnet.lastAddress, '192.168.1.190'); - }); - - it('should compute an ipv4 broadcast address', function() { - assert.equal(ipv4Subnet.broadcastAddress, '192.168.1.191'); - }); - - it('should compute an ipv4 subnet number of addresses', function() { - assert.equal(ipv4Subnet.length, 64); - }); - - it('should compute an ipv4 subnet number of addressable hosts', function() { - assert.equal(ipv4Subnet.numHosts, 62); - }); - - it('should compute an ipv4 subnet mask', function() { - assert.equal(ipv4Subnet.subnetMask, '255.255.255.192'); - }); - - it('should compute an ipv4 subnet mask\'s length', function() { - assert.equal(ipv4Subnet.subnetMaskLength, 26); - }); - - it('should know whether a subnet contains an address', function() { - assert.equal(ipv4Subnet.contains('192.168.1.180'), true); - }); - - it('should know whether a subnet contains an address', function() { - assert.equal(ipv4Subnet.contains('192.168.1.195'), false); - }); - - }); - - describe('cidr() method', function() { - it('should mask address in CIDR notation', function() { - assert.equal(ip.cidr('192.168.1.134/26'), '192.168.1.128'); - assert.equal(ip.cidr('2607:f0d0:1002:51::4/56'), '2607:f0d0:1002::'); - }); - }); - - describe('isEqual() method', function() { - it('should check if addresses are equal', function() { - assert(ip.isEqual('127.0.0.1', '::7f00:1')); - assert(!ip.isEqual('127.0.0.1', '::7f00:2')); - assert(ip.isEqual('127.0.0.1', '::ffff:7f00:1')); - assert(!ip.isEqual('127.0.0.1', '::ffaf:7f00:1')); - assert(ip.isEqual('::ffff:127.0.0.1', '::ffff:127.0.0.1')); - assert(ip.isEqual('::ffff:127.0.0.1', '127.0.0.1')); - }); - }); - - - describe('isPrivate() method', function() { - it('should check if an address is localhost', function() { - assert.equal(ip.isPrivate('127.0.0.1'), true); - }); - - it('should check if an address is from a 192.168.x.x network', function() { - assert.equal(ip.isPrivate('192.168.0.123'), true); - assert.equal(ip.isPrivate('192.168.122.123'), true); - assert.equal(ip.isPrivate('192.162.1.2'), false); - }); - - it('should check if an address is from a 172.16.x.x network', function() { - assert.equal(ip.isPrivate('172.16.0.5'), true); - assert.equal(ip.isPrivate('172.16.123.254'), true); - assert.equal(ip.isPrivate('171.16.0.5'), false); - assert.equal(ip.isPrivate('172.25.232.15'), true); - assert.equal(ip.isPrivate('172.15.0.5'), false); - assert.equal(ip.isPrivate('172.32.0.5'), false); - }); - - it('should check if an address is from a 169.254.x.x network', function() { - assert.equal(ip.isPrivate('169.254.2.3'), true); - assert.equal(ip.isPrivate('169.254.221.9'), true); - assert.equal(ip.isPrivate('168.254.2.3'), false); - }); - - it('should check if an address is from a 10.x.x.x network', function() { - assert.equal(ip.isPrivate('10.0.2.3'), true); - assert.equal(ip.isPrivate('10.1.23.45'), true); - assert.equal(ip.isPrivate('12.1.2.3'), false); - }); - - it('should check if an address is from a private IPv6 network', function() { - assert.equal(ip.isPrivate('fd12:3456:789a:1::1'), true); - assert.equal(ip.isPrivate('fe80::f2de:f1ff:fe3f:307e'), true); - assert.equal(ip.isPrivate('::ffff:10.100.1.42'), true); - assert.equal(ip.isPrivate('::FFFF:172.16.200.1'), true); - assert.equal(ip.isPrivate('::ffff:192.168.0.1'), true); - }); - - it('should check if an address is from the internet', function() { - assert.equal(ip.isPrivate('165.225.132.33'), false); // joyent.com - }); - - it('should check if an address is a loopback IPv6 address', function() { - assert.equal(ip.isPrivate('::'), true); - assert.equal(ip.isPrivate('::1'), true); - assert.equal(ip.isPrivate('fe80::1'), true); - }); - }); - - describe('loopback() method', function() { - describe('undefined', function() { - it('should respond with 127.0.0.1', function() { - assert.equal(ip.loopback(), '127.0.0.1') - }); - }); - - describe('ipv4', function() { - it('should respond with 127.0.0.1', function() { - assert.equal(ip.loopback('ipv4'), '127.0.0.1') - }); - }); - - describe('ipv6', function() { - it('should respond with fe80::1', function() { - assert.equal(ip.loopback('ipv6'), 'fe80::1') - }); - }); - }); - - describe('isLoopback() method', function() { - describe('127.0.0.1', function() { - it('should respond with true', function() { - assert.ok(ip.isLoopback('127.0.0.1')) - }); - }); - - describe('127.8.8.8', function () { - it('should respond with true', function () { - assert.ok(ip.isLoopback('127.8.8.8')) - }); - }); - - describe('8.8.8.8', function () { - it('should respond with false', function () { - assert.equal(ip.isLoopback('8.8.8.8'), false); - }); - }); - - describe('fe80::1', function() { - it('should respond with true', function() { - assert.ok(ip.isLoopback('fe80::1')) - }); - }); - - describe('::1', function() { - it('should respond with true', function() { - assert.ok(ip.isLoopback('::1')) - }); - }); - - describe('::', function() { - it('should respond with true', function() { - assert.ok(ip.isLoopback('::')) - }); - }); - }); - - describe('address() method', function() { - describe('undefined', function() { - it('should respond with a private ip', function() { - assert.ok(ip.isPrivate(ip.address())); - }); - }); - - describe('private', function() { - [ undefined, 'ipv4', 'ipv6' ].forEach(function(family) { - describe(family, function() { - it('should respond with a private ip', function() { - assert.ok(ip.isPrivate(ip.address('private', family))); - }); - }); - }); - }); - - var interfaces = os.networkInterfaces(); - - Object.keys(interfaces).forEach(function(nic) { - describe(nic, function() { - [ undefined, 'ipv4' ].forEach(function(family) { - describe(family, function() { - it('should respond with an ipv4 address', function() { - var addr = ip.address(nic, family); - assert.ok(!addr || net.isIPv4(addr)); - }); - }); - }); - - describe('ipv6', function() { - it('should respond with an ipv6 address', function() { - var addr = ip.address(nic, 'ipv6'); - assert.ok(!addr || net.isIPv6(addr)); - }); - }) - }); - }); - }); - - describe('toLong() method', function() { - it('should respond with a int', function() { - assert.equal(ip.toLong('127.0.0.1'), 2130706433); - assert.equal(ip.toLong('255.255.255.255'), 4294967295); - }); - }); - - describe('fromLong() method', function() { - it('should repond with ipv4 address', function() { - assert.equal(ip.fromLong(2130706433), '127.0.0.1'); - assert.equal(ip.fromLong(4294967295), '255.255.255.255'); - }); - }) -}); diff --git a/tools/rewriting/ThirdPartyPaths.txt b/tools/rewriting/ThirdPartyPaths.txt index 0dcd84d97b7b..e6ec25fe4f42 100644 --- a/tools/rewriting/ThirdPartyPaths.txt +++ b/tools/rewriting/ThirdPartyPaths.txt @@ -105,8 +105,6 @@ testing/talos/talos/tests/kraken/ testing/talos/talos/tests/v8_7/ testing/web-platform/tests/resources/webidl2/ testing/web-platform/tests/tools/third_party/ -testing/xpcshell/node-ip/ -testing/xpcshell/dns-packet/ third_party/ toolkit/components/jsoncpp/ toolkit/components/protobuf/