diff --git a/lib/geoip.js b/lib/geoip.js index 7b6f1cc1..04732abe 100644 --- a/lib/geoip.js +++ b/lib/geoip.js @@ -202,6 +202,18 @@ function lookup6(ip) { } while(1); } +function get4mapped(ip) { + var ipv6 = ip.toUpperCase(); + var v6prefixes = ['0:0:0:0:0:FFFF:', '::FFFF:']; + for (var i = 0; i < v6prefixes.length; i++) { + var v6prefix = v6prefixes[i]; + if (ipv6.indexOf(v6prefix) == 0) { + return ipv6.substring(v6prefix.length); + } + } + return null; +} + function preload(callback) { var datFile; var datSize; @@ -449,7 +461,12 @@ module.exports = { } else if (net.isIP(ip) === 4) { return lookup4(utils.aton4(ip)); } else if (net.isIP(ip) === 6) { - return lookup6(utils.aton6(ip)); + var ipv4 = get4mapped(ip); + if (ipv4) { + return lookup4(utils.aton4(ipv4)); + } else { + return lookup6(utils.aton6(ip)); + } } return null; diff --git a/test/tests.js b/test/tests.js index ed6bf6e0..84d1ba3f 100644 --- a/test/tests.js +++ b/test/tests.js @@ -39,6 +39,17 @@ module.exports = { test.equal(actual.city, "Santa Ana"); test.equal(actual.metro, 803); + test.done(); + }, + + testIPv4MappedIPv6: function (test) { + test.expect(2); + + var actual = geoip.lookup("::ffff:173.185.182.82"); + + test.equal(actual.city, "Glen Rose"); + test.equal(actual.metro, 623); + test.done(); } };