Skip to content

Commit 2fb0e1a

Browse files
committed
Fixed IPv6 not supported error for Teredo/6to4 when using IPv4 BIN
1 parent 3f814b7 commit 2fb0e1a

File tree

3 files changed

+63
-20
lines changed

3 files changed

+63
-20
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ip2location-nodejs",
3-
"version": "9.6.2",
3+
"version": "9.6.3",
44
"description": "IP2Location geolocation component",
55
"keywords": [
66
"ip2location",

src/ip2location.d.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,12 @@ export class IP2Location {
140140
* @returns 0 if successful else -1 for errors.
141141
*/
142142
close(): 0 | -1;
143+
/**
144+
* Resets metadata and closes file handle asynchronously.
145+
*
146+
* @returns The promise of 0 if successful else -1 for errors.
147+
*/
148+
closeAsync(): Promise<0 | -1>;
143149
/**
144150
* Retrieves geolocation data into supplied object.
145151
*
@@ -175,8 +181,8 @@ export class IP2Location {
175181
isp: string;
176182
domain: string;
177183
zipCode: string;
178-
latitude: string;
179-
longitude: string;
184+
latitude: string | number;
185+
longitude: string | number;
180186
timeZone: string;
181187
netSpeed: string;
182188
iddCode: string;
@@ -211,8 +217,8 @@ export class IP2Location {
211217
isp: string;
212218
domain: string;
213219
zipCode: string;
214-
latitude: string;
215-
longitude: string;
220+
latitude: string | number;
221+
longitude: string | number;
216222
timeZone: string;
217223
netSpeed: string;
218224
iddCode: string;

src/ip2location.js

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const https = require("https");
55
const csv = require("csv-parser");
66

77
// For BIN queries
8-
const VERSION = "9.6.1";
8+
const VERSION = "9.6.3";
99
const MAX_INDEX = 65536;
1010
const COUNTRY_POSITION = [
1111
0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -110,6 +110,8 @@ const TO_6TO4 = BigInt("42550872755692912415807417417958686719");
110110
const FROM_TEREDO = BigInt("42540488161975842760550356425300246528");
111111
const TO_TEREDO = BigInt("42540488241204005274814694018844196863");
112112
const LAST_32_BITS = BigInt("4294967295");
113+
const FROM_IPV4_MAPPED_IPV6 = BigInt("281470681743360");
114+
const TO_IPV4_MAPPED_IPV6 = BigInt("281474976710655");
113115

114116
const MODES = {
115117
COUNTRY_SHORT: 1,
@@ -258,6 +260,7 @@ class IP2Location {
258260
fileSize: 0,
259261
};
260262
#fd;
263+
#fh;
261264

262265
constructor() {}
263266

@@ -574,8 +577,8 @@ class IP2Location {
574577

575578
try {
576579
if (this.#binFile && this.#binFile != "") {
577-
let fh = await fsp.open(this.#binFile, "r");
578-
this.#fd = fh.fd;
580+
this.#fh = await fsp.open(this.#binFile, "r");
581+
this.#fd = this.#fh.fd;
579582

580583
let len = 64; // 64-byte header
581584
let row = await this.readRowAsync(len, 1);
@@ -754,7 +757,7 @@ class IP2Location {
754757
}
755758
}
756759

757-
// Reset everything (do not use in async case due to race conditions)
760+
// Reset everything
758761
close() {
759762
try {
760763
this.#myDB.baseAddress = 0;
@@ -773,7 +776,33 @@ class IP2Location {
773776
this.#myDB.productCode = 0;
774777
this.#myDB.productType = 0;
775778
this.#myDB.fileSize = 0;
776-
fs.closeSync(this.#fd);
779+
fs.closeSync(this.#fd); // normal file handle
780+
return 0;
781+
} catch (err) {
782+
return -1;
783+
}
784+
}
785+
786+
// Reset everything
787+
async closeAsync() {
788+
try {
789+
this.#myDB.baseAddress = 0;
790+
this.#myDB.dbCount = 0;
791+
this.#myDB.dbColumn = 0;
792+
this.#myDB.dbType = 0;
793+
this.#myDB.dbDay = 0;
794+
this.#myDB.dbMonth = 0;
795+
this.#myDB.dbYear = 0;
796+
this.#myDB.baseAddressIPV6 = 0;
797+
this.#myDB.dbCountIPV6 = 0;
798+
this.#myDB.indexed = 0;
799+
this.#myDB.indexedIPV6 = 0;
800+
this.#myDB.indexBaseAddress = 0;
801+
this.#myDB.indexBaseAddressIPV6 = 0;
802+
this.#myDB.productCode = 0;
803+
this.#myDB.productType = 0;
804+
this.#myDB.fileSize = 0;
805+
await this.#fh.close(); // FileHandler object opened by fs.Promises
777806
return 0;
778807
} catch (err) {
779808
return -1;
@@ -820,7 +849,8 @@ class IP2Location {
820849

821850
if (
822851
(ipNumber >= FROM_6TO4 && ipNumber <= TO_6TO4) ||
823-
(ipNumber >= FROM_TEREDO && ipNumber <= TO_TEREDO)
852+
(ipNumber >= FROM_TEREDO && ipNumber <= TO_TEREDO) ||
853+
(ipNumber >= FROM_IPV4_MAPPED_IPV6 && ipNumber <= TO_IPV4_MAPPED_IPV6)
824854
) {
825855
ipType = 4;
826856
MAX_IP_RANGE = MAX_IPV4_RANGE;
@@ -830,15 +860,21 @@ class IP2Location {
830860

831861
if (ipNumber >= FROM_6TO4 && ipNumber <= TO_6TO4) {
832862
ipNumber = Number((ipNumber >> BigInt(80)) & LAST_32_BITS);
833-
} else {
863+
} else if (ipNumber >= FROM_TEREDO && ipNumber <= TO_TEREDO) {
834864
ipNumber = Number(~ipNumber & LAST_32_BITS);
865+
} else {
866+
ipNumber = Number(ipNumber - FROM_IPV4_MAPPED_IPV6);
835867
}
836868
if (this.#myDB.indexed == 1) {
837869
indexAddress = ipNumber >>> 16;
838870
low = this.#indexArrayIPV4[indexAddress][0];
839871
high = this.#indexArrayIPV4[indexAddress][1];
840872
}
841873
} else {
874+
if (this.#myDB.dbCountIPV6 == 0) {
875+
loadMesg(data, MSG_IPV6_UNSUPPORTED);
876+
return;
877+
}
842878
firstCol = 16; // IPv6 is 16 bytes
843879
if (this.#myDB.indexedIPV6 == 1) {
844880
indexAddress = Number(ipNumber >> BigInt(112));
@@ -1107,7 +1143,8 @@ class IP2Location {
11071143

11081144
if (
11091145
(ipNumber >= FROM_6TO4 && ipNumber <= TO_6TO4) ||
1110-
(ipNumber >= FROM_TEREDO && ipNumber <= TO_TEREDO)
1146+
(ipNumber >= FROM_TEREDO && ipNumber <= TO_TEREDO) ||
1147+
(ipNumber >= FROM_IPV4_MAPPED_IPV6 && ipNumber <= TO_IPV4_MAPPED_IPV6)
11111148
) {
11121149
ipType = 4;
11131150
MAX_IP_RANGE = MAX_IPV4_RANGE;
@@ -1117,15 +1154,21 @@ class IP2Location {
11171154

11181155
if (ipNumber >= FROM_6TO4 && ipNumber <= TO_6TO4) {
11191156
ipNumber = Number((ipNumber >> BigInt(80)) & LAST_32_BITS);
1120-
} else {
1157+
} else if (ipNumber >= FROM_TEREDO && ipNumber <= TO_TEREDO) {
11211158
ipNumber = Number(~ipNumber & LAST_32_BITS);
1159+
} else {
1160+
ipNumber = Number(ipNumber - FROM_IPV4_MAPPED_IPV6);
11221161
}
11231162
if (this.#myDB.indexed == 1) {
11241163
indexAddress = ipNumber >>> 16;
11251164
low = this.#indexArrayIPV4[indexAddress][0];
11261165
high = this.#indexArrayIPV4[indexAddress][1];
11271166
}
11281167
} else {
1168+
if (this.#myDB.dbCountIPV6 == 0) {
1169+
loadMesg(data, MSG_IPV6_UNSUPPORTED);
1170+
return;
1171+
}
11291172
firstCol = 16; // IPv6 is 16 bytes
11301173
if (this.#myDB.indexedIPV6 == 1) {
11311174
indexAddress = Number(ipNumber >> BigInt(112));
@@ -1409,9 +1452,6 @@ class IP2Location {
14091452
} else if (this.#myDB.dbType == 0) {
14101453
loadMesg(data, MSG_MISSING_FILE);
14111454
return data;
1412-
} else if (ipType == 6 && this.#myDB.dbCountIPV6 == 0) {
1413-
loadMesg(data, MSG_IPV6_UNSUPPORTED);
1414-
return data;
14151455
} else {
14161456
this.geoQueryData(myIP, ipType, data, mode);
14171457
return data;
@@ -1471,9 +1511,6 @@ class IP2Location {
14711511
} else if (this.#myDB.dbType == 0) {
14721512
loadMesg(data, MSG_MISSING_FILE);
14731513
return data;
1474-
} else if (ipType == 6 && this.#myDB.dbCountIPV6 == 0) {
1475-
loadMesg(data, MSG_IPV6_UNSUPPORTED);
1476-
return data;
14771514
} else {
14781515
await this.geoQueryDataAsync(myIP, ipType, data, mode);
14791516
return data;

0 commit comments

Comments
 (0)