diff --git a/lib/structs.js b/lib/structs.js index 807c975..005ed1f 100644 --- a/lib/structs.js +++ b/lib/structs.js @@ -429,10 +429,17 @@ function inet_ntop(buf) { function inet_pton(str) { var buf = new Buffer(16); buf.fill(0); + // IPv4-mapped IPv6. + if (str.indexOf("::ffff:") === 0) { + str = str.slice(7); + } // IPv4. if (str.indexOf(":") === -1) { IPv4_MAPPING.copy(buf); - var octets = str.split(/\./g).map(function(s) {return parseInt(s, 10);}); + var octets = str.split(/\./g).map(function(o) { + assert(/^\d+$/.test(o), "Bad octet"); + return parseInt(o, 10); + }); // Support short form from inet_aton(3) man page. if (octets.length === 1) { buf.writeUInt32BE(octets[0], 12); @@ -487,6 +494,8 @@ function inet_pton(str) { assert(groups.length === 8, "Bad IPv6 address"); } for (i = 0; i < Math.min(groups.length, 8); i++) { + // Check against parseInt("127.0.0.1", 16) -> 295 + assert(/^[0-9a-f]+$/.test(groups[i]), "Bad group"); buf.writeUInt16BE(parseInt(groups[i], 16), i * 2); } } diff --git a/tests/unit.js b/tests/unit.js index 8cc20bb..0d5340f 100644 --- a/tests/unit.js +++ b/tests/unit.js @@ -346,6 +346,16 @@ describe("Common structures", function() { expect(net_addr.encode({short: true, services: ServicesBitfield().set(ServicesBitfield.NODE_NETWORK), host: "127.0.0.1", port: 8444}).toString("hex")).to.equal("000000000000000100000000000000000000ffff7f00000120fc"); expect(net_addr.encode({short: true, host: "::1", port: 65000}).toString("hex")).to.equal("000000000000000100000000000000000000000000000001fde8"); }); + + it("should encode IPv4-mapped IPv6", function() { + var encoded = net_addr.encode({host: "::ffff:127.0.0.1", port: 1234}); + expect(net_addr.decode(encoded).host).to.equal("127.0.0.1"); + }); + + it("should encode bad IPv4", function() { + var opts = {host: " 127.0.0.1", port: 1234}; + expect(net_addr.encode.bind(null, opts)).to.throw(/bad octet/i); + }); }); describe("inv_vect", function() {