@@ -21,6 +21,9 @@ protected struct ip2proxymeta {
2121 uint ipv6indexbaseaddr;
2222 uint ipv4columnsize;
2323 uint ipv6columnsize;
24+ ubyte productcode;
25+ ubyte producttype;
26+ uint filesize;
2427}
2528
2629protected struct ip2proxyrecord {
@@ -36,6 +39,7 @@ protected struct ip2proxyrecord {
3639 string as = " -" ;
3740 string last_seen = " -" ;
3841 string threat = " -" ;
42+ string provider = " -" ;
3943 byte is_proxy = - 1 ;
4044}
4145
@@ -45,19 +49,20 @@ protected struct ipv {
4549 uint ipindex = 0 ;
4650}
4751
48- const ubyte [11 ] COUNTRY_POSITION = [0 , 2 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 ];
49- const ubyte [11 ] REGION_POSITION = [0 , 0 , 0 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 ];
50- const ubyte [11 ] CITY_POSITION = [0 , 0 , 0 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 ];
51- const ubyte [11 ] ISP_POSITION = [0 , 0 , 0 , 0 , 6 , 6 , 6 , 6 , 6 , 6 , 6 ];
52- const ubyte [11 ] PROXYTYPE_POSITION = [0 , 0 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ];
53- const ubyte [11 ] DOMAIN_POSITION = [0 , 0 , 0 , 0 , 0 , 7 , 7 , 7 , 7 , 7 , 7 ];
54- const ubyte [11 ] USAGETYPE_POSITION = [0 , 0 , 0 , 0 , 0 , 0 , 8 , 8 , 8 , 8 , 8 ];
55- const ubyte [11 ] ASN_POSITION = [0 , 0 , 0 , 0 , 0 , 0 , 0 , 9 , 9 , 9 , 9 ];
56- const ubyte [11 ] AS_POSITION = [0 , 0 , 0 , 0 , 0 , 0 , 0 , 10 , 10 , 10 , 10 ];
57- const ubyte [11 ] LASTSEEN_POSITION = [0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 11 , 11 , 11 ];
58- const ubyte [11 ] THREAT_POSITION = [0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 12 , 12 ];
52+ const ubyte [12 ] COUNTRY_POSITION = [0 , 2 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 ];
53+ const ubyte [12 ] REGION_POSITION = [0 , 0 , 0 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 ];
54+ const ubyte [12 ] CITY_POSITION = [0 , 0 , 0 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 ];
55+ const ubyte [12 ] ISP_POSITION = [0 , 0 , 0 , 0 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 ];
56+ const ubyte [12 ] PROXYTYPE_POSITION = [0 , 0 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ];
57+ const ubyte [12 ] DOMAIN_POSITION = [0 , 0 , 0 , 0 , 0 , 7 , 7 , 7 , 7 , 7 , 7 , 7 ];
58+ const ubyte [12 ] USAGETYPE_POSITION = [0 , 0 , 0 , 0 , 0 , 0 , 8 , 8 , 8 , 8 , 8 , 8 ];
59+ const ubyte [12 ] ASN_POSITION = [0 , 0 , 0 , 0 , 0 , 0 , 0 , 9 , 9 , 9 , 9 , 9 ];
60+ const ubyte [12 ] AS_POSITION = [0 , 0 , 0 , 0 , 0 , 0 , 0 , 10 , 10 , 10 , 10 , 10 ];
61+ const ubyte [12 ] LASTSEEN_POSITION = [0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 11 , 11 , 11 , 11 ];
62+ const ubyte [12 ] THREAT_POSITION = [0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 12 , 12 , 12 ];
63+ const ubyte [12 ] PROVIDER_POSITION = [0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 13 ];
5964
60- protected const string MODULE_VERSION = " 3.0 .0" ;
65+ protected const string MODULE_VERSION = " 3.1 .0" ;
6166
6267protected const BigInt MAX_IPV4_RANGE = BigInt(" 4294967295" );
6368protected const BigInt MAX_IPV6_RANGE = BigInt(" 340282366920938463463374607431768211455" );
@@ -80,13 +85,15 @@ protected const uint ASN = 0X00200;
8085protected const uint AS = 0X00400 ;
8186protected const uint LASTSEEN = 0X00800 ;
8287protected const uint THREAT = 0X01000 ;
88+ protected const uint PROVIDER = 0X02000 ;
8389
84- protected const uint ALL = COUNTRYSHORT | COUNTRYLONG | REGION | CITY | ISP | PROXYTYPE | ISPROXY | DOMAIN | USAGETYPE | ASN | AS | LASTSEEN | THREAT ;
90+ protected const uint ALL = COUNTRYSHORT | COUNTRYLONG | REGION | CITY | ISP | PROXYTYPE | ISPROXY | DOMAIN | USAGETYPE | ASN | AS | LASTSEEN | THREAT | PROVIDER ;
8591
8692protected const string MSG_NOT_SUPPORTED = " NOT SUPPORTED" ;
8793protected const string MSG_INVALID_IP = " INVALID IP ADDRESS" ;
8894protected const string MSG_MISSING_FILE = " MISSING FILE" ;
8995protected const string MSG_IPV6_UNSUPPORTED = " IPV6 ADDRESS MISSING IN IPV4 BIN" ;
96+ protected const string MSG_INVALID_BIN = " Incorrect IP2Proxy BIN file format. Please make sure that you are using the latest IP2Proxy BIN file." ;
9097
9198class ip2proxy {
9299 protected MmFile db;
@@ -105,6 +112,7 @@ class ip2proxy {
105112 private uint as_position_offset;
106113 private uint lastseen_position_offset;
107114 private uint threat_position_offset;
115+ private uint provider_position_offset;
108116
109117 private bool country_enabled;
110118 private bool region_enabled;
@@ -117,6 +125,7 @@ class ip2proxy {
117125 private bool as_enabled;
118126 private bool lastseen_enabled;
119127 private bool threat_enabled;
128+ private bool provider_enabled;
120129
121130 // constructor
122131 public this () {
@@ -159,6 +168,9 @@ class ip2proxy {
159168 meta.ipv6indexbaseaddr = 0 ;
160169 meta.ipv4columnsize = 0 ;
161170 meta.ipv6columnsize = 0 ;
171+ meta.productcode = 0 ;
172+ meta.producttype = 0 ;
173+ meta.filesize = 0 ;
162174 metaok = false ;
163175 country_position_offset = 0 ;
164176 region_position_offset = 0 ;
@@ -171,6 +183,7 @@ class ip2proxy {
171183 as_position_offset = 0 ;
172184 lastseen_position_offset = 0 ;
173185 threat_position_offset = 0 ;
186+ provider_position_offset = 0 ;
174187 country_enabled = false ;
175188 region_enabled = false ;
176189 city_enabled = false ;
@@ -182,6 +195,7 @@ class ip2proxy {
182195 as_enabled = false ;
183196 lastseen_enabled = false ;
184197 threat_enabled = false ;
198+ provider_enabled = false ;
185199
186200 destroy (db);
187201
@@ -228,27 +242,6 @@ class ip2proxy {
228242 return result;
229243 }
230244
231- // read float from row
232- private float readfloat_row (ref ubyte [] row, uint index) {
233- ubyte [4 ] buf = row[index .. (index + 4 )];
234- float result = 0.0 ;
235- result = littleEndianToNative! float (buf);
236- return result;
237- }
238-
239- // read float
240- private float readfloat (uint index) {
241- uint pos = index - 1 ;
242- ubyte [4 ] fl;
243- float result = 0.0 ;
244- for (int x = 0 ; x < 4 ; x++ ) {
245- fl[x] = cast (ubyte )db[pos + x];
246- }
247-
248- result = littleEndianToNative! float (fl);
249- return result;
250- }
251-
252245 // read BIN file metadata
253246 private byte readmeta () {
254247 if (binfile.length == 0 ) {
@@ -273,25 +266,21 @@ class ip2proxy {
273266 meta.ipv6databaseaddr = readuint(18 );
274267 meta.ipv4indexbaseaddr = readuint(22 );
275268 meta.ipv6indexbaseaddr = readuint(26 );
269+ meta.productcode = db[29 ];
270+ // below 2 fields just read for now, not being used yet
271+ meta.producttype = db[30 ];
272+ meta.filesize = readuint(32 );
273+
274+ // check if is correct BIN (should be 2 for IP2Proxy BIN file), also checking for zipped file (PK being the first 2 chars)
275+ if ((meta.productcode != 2 && meta.databaseyear >= 21 ) || (meta.databasetype == 80 && meta.databasecolumn == 75 )) { // only BINs from Jan 2021 onwards have this byte set
276+ throw new Exception (MSG_INVALID_BIN );
277+ }
278+
276279 meta.ipv4columnsize = meta.databasecolumn << 2 ; // 4 bytes each column
277280 meta.ipv6columnsize = 16 + ((meta.databasecolumn - 1 ) << 2 ); // 4 bytes each column, except IPFrom column which is 16 bytes
278281
279282 uint dbt = meta.databasetype;
280283
281- // since both IPv4 and IPv6 use 4 bytes for the below columns, can just do it once here
282- // country_position_offset = (COUNTRY_POSITION[dbt] != 0) ? (COUNTRY_POSITION[dbt] - 1) << 2 : 0;
283- // region_position_offset = (REGION_POSITION[dbt] != 0) ? (REGION_POSITION[dbt] - 1) << 2 : 0;
284- // city_position_offset = (CITY_POSITION[dbt] != 0) ? (CITY_POSITION[dbt] - 1) << 2 : 0;
285- // isp_position_offset = (ISP_POSITION[dbt] != 0) ? (ISP_POSITION[dbt] - 1) << 2 : 0;
286- // proxytype_position_offset = (PROXYTYPE_POSITION[dbt] != 0) ? (PROXYTYPE_POSITION[dbt] - 1) << 2 : 0;
287- // domain_position_offset = (DOMAIN_POSITION[dbt] != 0) ? (DOMAIN_POSITION[dbt] - 1) << 2 : 0;
288- // usagetype_position_offset = (USAGETYPE_POSITION[dbt] != 0) ? (USAGETYPE_POSITION[dbt] - 1) << 2 : 0;
289- // asn_position_offset = (ASN_POSITION[dbt] != 0) ? (ASN_POSITION[dbt] - 1) << 2 : 0;
290- // as_position_offset = (AS_POSITION[dbt] != 0) ? (AS_POSITION[dbt] - 1) << 2 : 0;
291- // lastseen_position_offset = (LASTSEEN_POSITION[dbt] != 0) ? (LASTSEEN_POSITION[dbt] - 1) << 2 : 0;
292- // threat_position_offset = (THREAT_POSITION[dbt] != 0) ? (THREAT_POSITION[dbt] - 1) << 2 : 0;
293-
294- // offset slightly different when reading by row
295284 country_position_offset = (COUNTRY_POSITION [dbt] != 0 ) ? (COUNTRY_POSITION [dbt] - 2 ) << 2 : 0 ;
296285 region_position_offset = (REGION_POSITION [dbt] != 0 ) ? (REGION_POSITION [dbt] - 2 ) << 2 : 0 ;
297286 city_position_offset = (CITY_POSITION [dbt] != 0 ) ? (CITY_POSITION [dbt] - 2 ) << 2 : 0 ;
@@ -303,18 +292,20 @@ class ip2proxy {
303292 as_position_offset = (AS_POSITION [dbt] != 0 ) ? (AS_POSITION [dbt] - 2 ) << 2 : 0 ;
304293 lastseen_position_offset = (LASTSEEN_POSITION [dbt] != 0 ) ? (LASTSEEN_POSITION [dbt] - 2 ) << 2 : 0 ;
305294 threat_position_offset = (THREAT_POSITION [dbt] != 0 ) ? (THREAT_POSITION [dbt] - 2 ) << 2 : 0 ;
295+ provider_position_offset = (PROVIDER_POSITION [dbt] != 0 ) ? (PROVIDER_POSITION [dbt] - 2 ) << 2 : 0 ;
306296
307- country_enabled = (COUNTRY_POSITION [dbt] != 0 ) ? true : false ;
308- region_enabled = (REGION_POSITION [dbt] != 0 ) ? true : false ;
309- city_enabled = (CITY_POSITION [dbt] != 0 ) ? true : false ;
310- isp_enabled = (ISP_POSITION [dbt] != 0 ) ? true : false ;
311- proxytype_enabled = (PROXYTYPE_POSITION [dbt] != 0 ) ? true : false ;
312- domain_enabled = (DOMAIN_POSITION [dbt] != 0 ) ? true : false ;
313- usagetype_enabled = (USAGETYPE_POSITION [dbt] != 0 ) ? true : false ;
314- asn_enabled = (ASN_POSITION [dbt] != 0 ) ? true : false ;
315- as_enabled = (AS_POSITION [dbt] != 0 ) ? true : false ;
316- lastseen_enabled = (LASTSEEN_POSITION [dbt] != 0 ) ? true : false ;
317- threat_enabled = (THREAT_POSITION [dbt] != 0 ) ? true : false ;
297+ country_enabled = (COUNTRY_POSITION [dbt] != 0 );
298+ region_enabled = (REGION_POSITION [dbt] != 0 );
299+ city_enabled = (CITY_POSITION [dbt] != 0 );
300+ isp_enabled = (ISP_POSITION [dbt] != 0 );
301+ proxytype_enabled = (PROXYTYPE_POSITION [dbt] != 0 );
302+ domain_enabled = (DOMAIN_POSITION [dbt] != 0 );
303+ usagetype_enabled = (USAGETYPE_POSITION [dbt] != 0 );
304+ asn_enabled = (ASN_POSITION [dbt] != 0 );
305+ as_enabled = (AS_POSITION [dbt] != 0 );
306+ lastseen_enabled = (LASTSEEN_POSITION [dbt] != 0 );
307+ threat_enabled = (THREAT_POSITION [dbt] != 0 );
308+ provider_enabled = (PROVIDER_POSITION [dbt] != 0 );
318309
319310 metaok = true ;
320311 }
@@ -436,6 +427,7 @@ class ip2proxy {
436427 x[" AS" ] = data.as;
437428 x[" LastSeen" ] = data.last_seen;
438429 x[" Threat" ] = data.threat;
430+ x[" Provider" ] = data.provider;
439431
440432 return x;
441433 }
@@ -512,6 +504,12 @@ class ip2proxy {
512504 return data.threat;
513505 }
514506
507+ // get provider
508+ public auto get_provider (const string ipaddress) {
509+ auto data = query(ipaddress, PROVIDER );
510+ return data.provider;
511+ }
512+
515513 // is proxy
516514 public auto is_proxy (const string ipaddress) {
517515 auto data = query(ipaddress, ISPROXY );
@@ -594,20 +592,17 @@ class ip2proxy {
594592 uint firstcol = 4 ; // 4 bytes for ip from
595593 if (ipdata.iptype == 6 ) {
596594 firstcol = 16 ; // 16 bytes for ipv6
597- // rowoffset = rowoffset + 12; // coz below is assuming all columns are 4 bytes, so got 12 left to go to make 16 bytes total
598595 }
599596 ubyte [] row = cast (ubyte [])db[(rowoffset + firstcol - 1 ) .. (rowoffset + colsize - 1 )];
600597
601598 if (proxytype_enabled) {
602599 if ((mode & PROXYTYPE ) || (mode & ISPROXY )) {
603- // x.proxy_type = readstr(readuint(rowoffset + proxytype_position_offset));
604600 x.proxy_type = readstr(readuint_row(row, proxytype_position_offset));
605601 }
606602 }
607603
608604 if (country_enabled) {
609605 if ((mode & COUNTRYSHORT ) || (mode & COUNTRYLONG ) || (mode & ISPROXY )) {
610- // countrypos = readuint(rowoffset + country_position_offset);
611606 countrypos = readuint_row(row, country_position_offset);
612607 }
613608 if ((mode & COUNTRYSHORT ) || (mode & ISPROXY )) {
@@ -619,50 +614,45 @@ class ip2proxy {
619614 }
620615
621616 if ((mode & REGION ) && (region_enabled)) {
622- // x.region = readstr(readuint(rowoffset + region_position_offset));
623617 x.region = readstr(readuint_row(row, region_position_offset));
624618 }
625619
626620 if ((mode & CITY ) && (city_enabled)) {
627- // x.city = readstr(readuint(rowoffset + city_position_offset));
628621 x.city = readstr(readuint_row(row, city_position_offset));
629622 }
630623
631624 if ((mode & ISP ) && (isp_enabled)) {
632- // x.isp = readstr(readuint(rowoffset + isp_position_offset));
633625 x.isp = readstr(readuint_row(row, isp_position_offset));
634626 }
635627
636628 if ((mode & DOMAIN ) && (domain_enabled)) {
637- // x.domain = readstr(readuint(rowoffset + domain_position_offset));
638629 x.domain = readstr(readuint_row(row, domain_position_offset));
639630 }
640631
641632 if ((mode & USAGETYPE ) && (usagetype_enabled)) {
642- // x.usage_type = readstr(readuint(rowoffset + usagetype_position_offset));
643633 x.usage_type = readstr(readuint_row(row, usagetype_position_offset));
644634 }
645635
646636 if ((mode & ASN ) && (asn_enabled)) {
647- // x.asn = readstr(readuint(rowoffset + asn_position_offset));
648637 x.asn = readstr(readuint_row(row, asn_position_offset));
649638 }
650639
651640 if ((mode & AS ) && (as_enabled)) {
652- // x.as = readstr(readuint(rowoffset + as_position_offset));
653641 x.as = readstr(readuint_row(row, as_position_offset));
654642 }
655643
656644 if ((mode & LASTSEEN ) && (lastseen_enabled)) {
657- // x.last_seen = readstr(readuint(rowoffset + lastseen_position_offset));
658645 x.last_seen = readstr(readuint_row(row, lastseen_position_offset));
659646 }
660647
661648 if ((mode & THREAT ) && (threat_enabled)) {
662- // x.threat = readstr(readuint(rowoffset + threat_position_offset));
663649 x.threat = readstr(readuint_row(row, threat_position_offset));
664650 }
665651
652+ if ((mode & PROVIDER ) && (provider_enabled)) {
653+ x.provider = readstr(readuint_row(row, provider_position_offset));
654+ }
655+
666656 if ((x.country_short == " -" ) || (x.proxy_type == " -" )) {
667657 x.is_proxy = 0 ;
668658 }
0 commit comments