]> jfr.im git - irc/quakenet/newserv.git/blob - geoip/libGeoIP/GeoIP.c
CHANSERV: tell user when they can't attempts to auth any more, and drop max attempts...
[irc/quakenet/newserv.git] / geoip / libGeoIP / GeoIP.c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
2 /* GeoIP.c
3 *
4 * Copyright (C) 2006 MaxMind LLC
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include "GeoIP.h"
22
23 static geoipv6_t IPV6_NULL;
24
25 #if !defined(WIN32) && !defined(WIN64)
26 #include <netdb.h>
27 #include <sys/socket.h>
28 #include <netinet/in.h> /* For ntohl */
29 #include <arpa/inet.h>
30
31 #include <sys/mman.h>
32
33 #else
34 #include <windows.h>
35 #define snprintf _snprintf
36 #endif
37 #include <errno.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <assert.h>
42 #include <sys/types.h> /* for fstat */
43 #include <sys/stat.h> /* for fstat */
44
45 #ifdef HAVE_GETTIMEOFDAY
46 #include <sys/time.h> /* for gettimeofday */
47 #endif
48
49 #ifdef HAVE_STDINT_H
50 #include <stdint.h> /* For uint32_t */
51 #endif
52
53 #ifndef INADDR_NONE
54 #define INADDR_NONE -1
55 #endif
56
57 #define COUNTRY_BEGIN 16776960
58 #define STATE_BEGIN_REV0 16700000
59 #define STATE_BEGIN_REV1 16000000
60 #define STRUCTURE_INFO_MAX_SIZE 20
61 #define DATABASE_INFO_MAX_SIZE 100
62 #define MAX_ORG_RECORD_LENGTH 300
63 #define US_OFFSET 1
64 #define CANADA_OFFSET 677
65 #define WORLD_OFFSET 1353
66 #define FIPS_RANGE 360
67
68 #define CHECK_ERR(err, msg) { \
69 if (err != Z_OK) { \
70 fprintf(stderr, "%s error: %d\n", msg, err); \
71 exit(1); \
72 } \
73 }
74
75 const char GeoIP_country_code[253][3] = { "--","AP","EU","AD","AE","AF","AG","AI","AL","AM","AN",
76 "AO","AQ","AR","AS","AT","AU","AW","AZ","BA","BB",
77 "BD","BE","BF","BG","BH","BI","BJ","BM","BN","BO",
78 "BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD",
79 "CF","CG","CH","CI","CK","CL","CM","CN","CO","CR",
80 "CU","CV","CX","CY","CZ","DE","DJ","DK","DM","DO",
81 "DZ","EC","EE","EG","EH","ER","ES","ET","FI","FJ",
82 "FK","FM","FO","FR","FX","GA","GB","GD","GE","GF",
83 "GH","GI","GL","GM","GN","GP","GQ","GR","GS","GT",
84 "GU","GW","GY","HK","HM","HN","HR","HT","HU","ID",
85 "IE","IL","IN","IO","IQ","IR","IS","IT","JM","JO",
86 "JP","KE","KG","KH","KI","KM","KN","KP","KR","KW",
87 "KY","KZ","LA","LB","LC","LI","LK","LR","LS","LT",
88 "LU","LV","LY","MA","MC","MD","MG","MH","MK","ML",
89 "MM","MN","MO","MP","MQ","MR","MS","MT","MU","MV",
90 "MW","MX","MY","MZ","NA","NC","NE","NF","NG","NI",
91 "NL","NO","NP","NR","NU","NZ","OM","PA","PE","PF",
92 "PG","PH","PK","PL","PM","PN","PR","PS","PT","PW",
93 "PY","QA","RE","RO","RU","RW","SA","SB","SC","SD",
94 "SE","SG","SH","SI","SJ","SK","SL","SM","SN","SO",
95 "SR","ST","SV","SY","SZ","TC","TD","TF","TG","TH",
96 "TJ","TK","TM","TN","TO","TL","TR","TT","TV","TW",
97 "TZ","UA","UG","UM","US","UY","UZ","VA","VC","VE",
98 "VG","VI","VN","VU","WF","WS","YE","YT","RS","ZA",
99 "ZM","ME","ZW","A1","A2","O1","AX","GG","IM","JE",
100 "BL","MF"};
101
102 static const unsigned num_GeoIP_countries = (unsigned)(sizeof(GeoIP_country_code)/sizeof(GeoIP_country_code[0]));
103
104 const char GeoIP_country_code3[253][4] = { "--","AP","EU","AND","ARE","AFG","ATG","AIA","ALB","ARM","ANT",
105 "AGO","AQ","ARG","ASM","AUT","AUS","ABW","AZE","BIH","BRB",
106 "BGD","BEL","BFA","BGR","BHR","BDI","BEN","BMU","BRN","BOL",
107 "BRA","BHS","BTN","BV","BWA","BLR","BLZ","CAN","CC","COD",
108 "CAF","COG","CHE","CIV","COK","CHL","CMR","CHN","COL","CRI",
109 "CUB","CPV","CX","CYP","CZE","DEU","DJI","DNK","DMA","DOM",
110 "DZA","ECU","EST","EGY","ESH","ERI","ESP","ETH","FIN","FJI",
111 "FLK","FSM","FRO","FRA","FX","GAB","GBR","GRD","GEO","GUF",
112 "GHA","GIB","GRL","GMB","GIN","GLP","GNQ","GRC","GS","GTM",
113 "GUM","GNB","GUY","HKG","HM","HND","HRV","HTI","HUN","IDN",
114 "IRL","ISR","IND","IO","IRQ","IRN","ISL","ITA","JAM","JOR",
115 "JPN","KEN","KGZ","KHM","KIR","COM","KNA","PRK","KOR","KWT",
116 "CYM","KAZ","LAO","LBN","LCA","LIE","LKA","LBR","LSO","LTU",
117 "LUX","LVA","LBY","MAR","MCO","MDA","MDG","MHL","MKD","MLI",
118 "MMR","MNG","MAC","MNP","MTQ","MRT","MSR","MLT","MUS","MDV",
119 "MWI","MEX","MYS","MOZ","NAM","NCL","NER","NFK","NGA","NIC",
120 "NLD","NOR","NPL","NRU","NIU","NZL","OMN","PAN","PER","PYF",
121 "PNG","PHL","PAK","POL","SPM","PCN","PRI","PSE","PRT","PLW",
122 "PRY","QAT","REU","ROU","RUS","RWA","SAU","SLB","SYC","SDN",
123 "SWE","SGP","SHN","SVN","SJM","SVK","SLE","SMR","SEN","SOM",
124 "SUR","STP","SLV","SYR","SWZ","TCA","TCD","TF","TGO","THA",
125 "TJK","TKL","TKM","TUN","TON","TLS","TUR","TTO","TUV","TWN",
126 "TZA","UKR","UGA","UM","USA","URY","UZB","VAT","VCT","VEN",
127 "VGB","VIR","VNM","VUT","WLF","WSM","YEM","YT","SRB","ZAF",
128 "ZMB","MNE","ZWE","A1","A2","O1","ALA","GGY","IMN","JEY",
129 "BLM","MAF"};
130
131 const char * GeoIP_country_name[253] = {"N/A","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Netherlands Antilles",
132 "Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados",
133 "Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia",
134 "Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the",
135 "Central African Republic","Congo","Switzerland","Cote D'Ivoire","Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica",
136 "Cuba","Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany","Djibouti","Denmark","Dominica","Dominican Republic",
137 "Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji",
138 "Falkland Islands (Malvinas)","Micronesia, Federated States of","Faroe Islands","France","France, Metropolitan","Gabon","United Kingdom","Grenada","Georgia","French Guiana",
139 "Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala",
140 "Guam","Guinea-Bissau","Guyana","Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia",
141 "Ireland","Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan",
142 "Japan","Kenya","Kyrgyzstan","Cambodia","Kiribati","Comoros","Saint Kitts and Nevis","Korea, Democratic People's Republic of","Korea, Republic of","Kuwait",
143 "Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania",
144 "Luxembourg","Latvia","Libyan Arab Jamahiriya","Morocco","Monaco","Moldova, Republic of","Madagascar","Marshall Islands","Macedonia","Mali",
145 "Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius","Maldives",
146 "Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua",
147 "Netherlands","Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia",
148 "Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal","Palau",
149 "Paraguay","Qatar","Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia","Solomon Islands","Seychelles","Sudan",
150 "Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname",
151 "Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo","Thailand",
152 "Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu","Taiwan",
153 "Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands","United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines","Venezuela",
154 "Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa",
155 "Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey",
156 "Saint Barthelemy","Saint Martin"};
157
158 /* Possible continent codes are AF, AS, EU, NA, OC, SA for Africa, Asia, Europe, North America, Oceania
159 and South America. */
160
161 const char GeoIP_country_continent[253][3] = {"--","AS","EU","EU","AS","AS","SA","SA","EU","AS","SA",
162 "AF","AN","SA","OC","EU","OC","SA","AS","EU","SA",
163 "AS","EU","AF","EU","AS","AF","AF","SA","AS","SA",
164 "SA","SA","AS","AF","AF","EU","SA","NA","AS","AF",
165 "AF","AF","EU","AF","OC","SA","AF","AS","SA","SA",
166 "SA","AF","AS","AS","EU","EU","AF","EU","SA","SA",
167 "AF","SA","EU","AF","AF","AF","EU","AF","EU","OC",
168 "SA","OC","EU","EU","EU","AF","EU","SA","AS","SA",
169 "AF","EU","SA","AF","AF","SA","AF","EU","SA","SA",
170 "OC","AF","SA","AS","AF","SA","EU","SA","EU","AS",
171 "EU","AS","AS","AS","AS","AS","EU","EU","SA","AS",
172 "AS","AF","AS","AS","OC","AF","SA","AS","AS","AS",
173 "SA","AS","AS","AS","SA","EU","AS","AF","AF","EU",
174 "EU","EU","AF","AF","EU","EU","AF","OC","EU","AF",
175 "AS","AS","AS","OC","SA","AF","SA","EU","AF","AS",
176 "AF","NA","AS","AF","AF","OC","AF","OC","AF","SA",
177 "EU","EU","AS","OC","OC","OC","AS","SA","SA","OC",
178 "OC","AS","AS","EU","SA","OC","SA","AS","EU","OC",
179 "SA","AS","AF","EU","AS","AF","AS","OC","AF","AF",
180 "EU","AS","AF","EU","EU","EU","AF","EU","AF","AF",
181 "SA","AF","SA","AS","AF","SA","AF","AF","AF","AS",
182 "AS","OC","AS","AF","OC","AS","AS","SA","OC","AS",
183 "AF","EU","AF","OC","NA","SA","AS","EU","SA","SA",
184 "SA","SA","AS","OC","OC","OC","AS","AF","EU","AF",
185 "AF","EU","AF","--","--","--","EU","EU","EU","EU",
186 "SA","SA"};
187
188 geoipv6_t _GeoIP_lookupaddress_v6 (const char *host);
189
190 int __GEOIP_V6_IS_NULL(geoipv6_t v6) {
191 int i;
192 for (i=0;i<16;i++) {
193 if (v6.s6_addr[i])
194 return 0;
195 }
196 return 1;
197 }
198
199 const char * GeoIPDBDescription[NUM_DB_TYPES] = {NULL, "GeoIP Country Edition", "GeoIP City Edition, Rev 1", "GeoIP Region Edition, Rev 1", "GeoIP ISP Edition", "GeoIP Organization Edition", "GeoIP City Edition, Rev 0", "GeoIP Region Edition, Rev 0","GeoIP Proxy Edition","GeoIP ASNum Edition","GeoIP Netspeed Edition","GeoIP Domain Name Edition", "GeoIP Country V6 Edition"};
200
201 char * custom_directory = NULL;
202
203 void GeoIP_setup_custom_directory (char * dir) {
204 custom_directory = dir;
205 }
206
207 char *_GeoIP_full_path_to(const char *file_name) {
208 int len;
209 char *path = malloc(sizeof(char) * 1024);
210
211 if (custom_directory == NULL){
212 #if !defined(WIN32) && !defined(WIN64)
213 memset(path, 0, sizeof(char) * 1024);
214 snprintf(path, sizeof(char) * 1024 - 1, "%s/%s", GEOIPDATADIR, file_name);
215 #else
216 char buf[MAX_PATH], *p, *q = NULL;
217 memset(buf, 0, sizeof(buf));
218 len = GetModuleFileName(GetModuleHandle(NULL), buf, sizeof(buf) - 1);
219 for (p = buf + len; p > buf; p--)
220 if (*p == '\\')
221 {
222 if (!q)
223 q = p;
224 else
225 *p = '/';
226 }
227 *q = 0;
228 memset(path, 0, sizeof(char) * 1024);
229 snprintf(path, sizeof(char) * 1024 - 1, "%s/%s", buf, file_name);
230 #endif
231 } else {
232 len = strlen(custom_directory);
233 if (custom_directory[len-1] != '/') {
234 snprintf(path, sizeof(char) * 1024 - 1, "%s/%s",custom_directory, file_name);
235 } else {
236 snprintf(path, sizeof(char) * 1024 - 1, "%s%s", custom_directory, file_name);
237 }
238 }
239 return path;
240 }
241
242 char ** GeoIPDBFileName = NULL;
243
244 void _GeoIP_setup_dbfilename() {
245 if (NULL == GeoIPDBFileName) {
246 GeoIPDBFileName = malloc(sizeof(char *) * NUM_DB_TYPES);
247 memset(GeoIPDBFileName, 0, sizeof(char *) * NUM_DB_TYPES);
248
249 GeoIPDBFileName[GEOIP_COUNTRY_EDITION] = _GeoIP_full_path_to("GeoIP.dat");
250 GeoIPDBFileName[GEOIP_REGION_EDITION_REV0] = _GeoIP_full_path_to("GeoIPRegion.dat");
251 GeoIPDBFileName[GEOIP_REGION_EDITION_REV1] = _GeoIP_full_path_to("GeoIPRegion.dat");
252 GeoIPDBFileName[GEOIP_CITY_EDITION_REV0] = _GeoIP_full_path_to("GeoIPCity.dat");
253 GeoIPDBFileName[GEOIP_CITY_EDITION_REV1] = _GeoIP_full_path_to("GeoIPCity.dat");
254 GeoIPDBFileName[GEOIP_ISP_EDITION] = _GeoIP_full_path_to("GeoIPISP.dat");
255 GeoIPDBFileName[GEOIP_ORG_EDITION] = _GeoIP_full_path_to("GeoIPOrg.dat");
256 GeoIPDBFileName[GEOIP_PROXY_EDITION] = _GeoIP_full_path_to("GeoIPProxy.dat");
257 GeoIPDBFileName[GEOIP_ASNUM_EDITION] = _GeoIP_full_path_to("GeoIPASNum.dat");
258 GeoIPDBFileName[GEOIP_NETSPEED_EDITION] = _GeoIP_full_path_to("GeoIPNetSpeed.dat");
259 GeoIPDBFileName[GEOIP_DOMAIN_EDITION] = _GeoIP_full_path_to("GeoIPDomain.dat");
260 GeoIPDBFileName[GEOIP_COUNTRY_EDITION_V6] = _GeoIP_full_path_to("GeoIPv6.dat");
261 }
262 }
263
264 static
265 int _file_exists(const char *file_name) {
266 struct stat file_stat;
267 return( (stat(file_name, &file_stat) == 0) ? 1:0);
268 }
269
270 int GeoIP_db_avail(int type) {
271 const char * filePath;
272 if (type < 0 || type >= NUM_DB_TYPES) {
273 return 0;
274 }
275 _GeoIP_setup_dbfilename();
276 filePath = GeoIPDBFileName[type];
277 if (NULL == filePath) {
278 return 0;
279 }
280 return _file_exists(filePath);
281 }
282
283 static
284 void _setup_segments(GeoIP * gi) {
285 int i, j;
286 unsigned char delim[3];
287 unsigned char buf[SEGMENT_RECORD_LENGTH];
288
289 gi->databaseSegments = NULL;
290
291 /* default to GeoIP Country Edition */
292 gi->databaseType = GEOIP_COUNTRY_EDITION;
293 gi->record_length = STANDARD_RECORD_LENGTH;
294 fseek(gi->GeoIPDatabase, -3l, SEEK_END);
295 for (i = 0; i < STRUCTURE_INFO_MAX_SIZE; i++) {
296 fread(delim, 1, 3, gi->GeoIPDatabase);
297 if (delim[0] == 255 && delim[1] == 255 && delim[2] == 255) {
298 fread(&gi->databaseType, 1, 1, gi->GeoIPDatabase);
299 if (gi->databaseType >= 106) {
300 /* backwards compatibility with databases from April 2003 and earlier */
301 gi->databaseType -= 105;
302 }
303
304 if (gi->databaseType == GEOIP_REGION_EDITION_REV0) {
305 /* Region Edition, pre June 2003 */
306 gi->databaseSegments = malloc(sizeof(int));
307 gi->databaseSegments[0] = STATE_BEGIN_REV0;
308 } else if (gi->databaseType == GEOIP_REGION_EDITION_REV1) {
309 /* Region Edition, post June 2003 */
310 gi->databaseSegments = malloc(sizeof(int));
311 gi->databaseSegments[0] = STATE_BEGIN_REV1;
312 } else if (gi->databaseType == GEOIP_CITY_EDITION_REV0 ||
313 gi->databaseType == GEOIP_CITY_EDITION_REV1 ||
314 gi->databaseType == GEOIP_ORG_EDITION ||
315 gi->databaseType == GEOIP_ISP_EDITION ||
316 gi->databaseType == GEOIP_ASNUM_EDITION) {
317 /* City/Org Editions have two segments, read offset of second segment */
318 gi->databaseSegments = malloc(sizeof(int));
319 gi->databaseSegments[0] = 0;
320 fread(buf, SEGMENT_RECORD_LENGTH, 1, gi->GeoIPDatabase);
321 for (j = 0; j < SEGMENT_RECORD_LENGTH; j++) {
322 gi->databaseSegments[0] += (buf[j] << (j * 8));
323 }
324 if (gi->databaseType == GEOIP_ORG_EDITION ||
325 gi->databaseType == GEOIP_ISP_EDITION)
326 gi->record_length = ORG_RECORD_LENGTH;
327 }
328 break;
329 } else {
330 fseek(gi->GeoIPDatabase, -4l, SEEK_CUR);
331 }
332 }
333 if (gi->databaseType == GEOIP_COUNTRY_EDITION ||
334 gi->databaseType == GEOIP_PROXY_EDITION ||
335 gi->databaseType == GEOIP_NETSPEED_EDITION ||
336 gi->databaseType == GEOIP_COUNTRY_EDITION_V6 ) {
337 gi->databaseSegments = malloc(sizeof(int));
338 gi->databaseSegments[0] = COUNTRY_BEGIN;
339 }
340 }
341
342 static
343 int _check_mtime(GeoIP *gi) {
344 struct stat buf;
345 struct timeval t;
346
347 /* stat only has second granularity, so don't
348 call it more than once a second */
349 gettimeofday(&t, NULL);
350 if (t.tv_sec == gi->last_mtime_check){
351 return 0;
352 }
353 gi->last_mtime_check = t.tv_sec;
354
355 if (gi->flags & GEOIP_CHECK_CACHE) {
356 if (stat(gi->file_path, &buf) != -1) {
357 if (buf.st_mtime != gi->mtime) {
358 /* GeoIP Database file updated */
359 if (gi->flags & (GEOIP_MEMORY_CACHE | GEOIP_MMAP_CACHE)) {
360 if ( gi->flags & GEOIP_MMAP_CACHE) {
361 #if !defined(WIN32) && !defined(WIN64)
362 /* MMAP is only avail on UNIX */
363 munmap(gi->cache, gi->size);
364 gi->cache = NULL;
365 #endif
366 } else {
367 /* reload database into memory cache */
368 if ((gi->cache = (unsigned char*) realloc(gi->cache, buf.st_size)) == NULL) {
369 fprintf(stderr,"Out of memory when reloading %s\n",gi->file_path);
370 return -1;
371 }
372 }
373 }
374 /* refresh filehandle */
375 fclose(gi->GeoIPDatabase);
376 gi->GeoIPDatabase = fopen(gi->file_path,"rb");
377 if (gi->GeoIPDatabase == NULL) {
378 fprintf(stderr,"Error Opening file %s when reloading\n",gi->file_path);
379 return -1;
380 }
381 gi->mtime = buf.st_mtime;
382 gi->size = buf.st_size;
383
384 if ( gi->flags & GEOIP_MMAP_CACHE) {
385 #if defined(WIN32) || defined(WIN64)
386 fprintf(stderr, "GEOIP_MMAP_CACHE is not supported on WIN32\n");
387 gi->cache = 0;
388 return -1;
389 #else
390 gi->cache = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fileno(gi->GeoIPDatabase), 0);
391 if ( gi->cache == MAP_FAILED ) {
392
393 fprintf(stderr,"Error remapping file %s when reloading\n",gi->file_path);
394
395 gi->cache = 0;
396 return -1;
397 }
398 #endif
399 } else if ( gi->flags & GEOIP_MEMORY_CACHE ) {
400 if (fread(gi->cache, sizeof(unsigned char), buf.st_size, gi->GeoIPDatabase) != (size_t) buf.st_size) {
401 fprintf(stderr,"Error reading file %s when reloading\n",gi->file_path);
402 return -1;
403 }
404 }
405
406 if (gi->databaseSegments != NULL) {
407 free(gi->databaseSegments);
408 gi->databaseSegments = NULL;
409 }
410 _setup_segments(gi);
411 if (gi->databaseSegments == NULL) {
412 fprintf(stderr, "Error reading file %s -- corrupt\n", gi->file_path);
413 return -1;
414 }
415 if (gi->flags & GEOIP_INDEX_CACHE) {
416 gi->index_cache = (unsigned char *) realloc(gi->index_cache, sizeof(unsigned char) * ((gi->databaseSegments[0] * (long)gi->record_length * 2)));
417 if (gi->index_cache != NULL) {
418 fseek(gi->GeoIPDatabase, 0, SEEK_SET);
419 if (fread(gi->index_cache, sizeof(unsigned char), gi->databaseSegments[0] * (long)gi->record_length * 2, gi->GeoIPDatabase) != (size_t) (gi->databaseSegments[0]*(long)gi->record_length * 2)) {
420 fprintf(stderr,"Error reading file %s where reloading\n",gi->file_path);
421 return -1;
422 }
423 }
424 }
425 }
426 }
427 }
428 return 0;
429 }
430
431 unsigned int _GeoIP_seek_record_v6 (GeoIP *gi, geoipv6_t ipnum) {
432 int depth;
433 char paddr[8 * 4 + 7 + 1];
434 unsigned int x;
435 unsigned char stack_buffer[2 * MAX_RECORD_LENGTH];
436 const unsigned char *buf = (gi->cache == NULL) ? stack_buffer : NULL;
437 unsigned int offset = 0;
438
439 const unsigned char * p;
440 int j;
441
442 _check_mtime(gi);
443 for (depth = 127; depth >= 0; depth--) {
444 if (gi->cache == NULL && gi->index_cache == NULL) {
445 /* read from disk */
446 fseek(gi->GeoIPDatabase, (long)gi->record_length * 2 * offset, SEEK_SET);
447 fread(stack_buffer,gi->record_length,2,gi->GeoIPDatabase);
448 } else if (gi->index_cache == NULL) {
449 /* simply point to record in memory */
450 buf = gi->cache + (long)gi->record_length * 2 *offset;
451 } else {
452 buf = gi->index_cache + (long)gi->record_length * 2 * offset;
453 }
454
455 if (GEOIP_CHKBIT_V6(depth, ipnum.s6_addr )) {
456 /* Take the right-hand branch */
457 if ( gi->record_length == 3 ) {
458 /* Most common case is completely unrolled and uses constants. */
459 x = (buf[3*1 + 0] << (0*8))
460 + (buf[3*1 + 1] << (1*8))
461 + (buf[3*1 + 2] << (2*8));
462
463 } else {
464 /* General case */
465 j = gi->record_length;
466 p = &buf[2*j];
467 x = 0;
468 do {
469 x <<= 8;
470 x += *(--p);
471 } while ( --j );
472 }
473
474 } else {
475 /* Take the left-hand branch */
476 if ( gi->record_length == 3 ) {
477 /* Most common case is completely unrolled and uses constants. */
478 x = (buf[3*0 + 0] << (0*8))
479 + (buf[3*0 + 1] << (1*8))
480 + (buf[3*0 + 2] << (2*8));
481 } else {
482 /* General case */
483 j = gi->record_length;
484 p = &buf[1*j];
485 x = 0;
486 do {
487 x <<= 8;
488 x += *(--p);
489 } while ( --j );
490 }
491 }
492
493 if (x >= gi->databaseSegments[0]) {
494 gi->netmask = 128 - depth;
495 return x;
496 }
497 offset = x;
498 }
499
500 /* shouldn't reach here */
501 inet_pton(AF_INET6, &ipnum.s6_addr[0], paddr );
502 fprintf(stderr,"Error Traversing Database for ipnum = %s - Perhaps database is corrupt?\n", paddr);
503 return 0;
504 }
505
506 geoipv6_t
507 _GeoIP_addr_to_num_v6(const char *addr)
508 {
509 geoipv6_t ipnum;
510 if ( 1 == inet_pton(AF_INET6, addr, &ipnum.s6_addr[0] ) )
511 return ipnum;
512 return IPV6_NULL;
513 }
514
515 unsigned int _GeoIP_seek_record (GeoIP *gi, unsigned long ipnum) {
516 int depth;
517 unsigned int x;
518 unsigned char stack_buffer[2 * MAX_RECORD_LENGTH];
519 const unsigned char *buf = (gi->cache == NULL) ? stack_buffer : NULL;
520 unsigned int offset = 0;
521
522 const unsigned char * p;
523 int j;
524
525 _check_mtime(gi);
526 for (depth = 31; depth >= 0; depth--) {
527 if (gi->cache == NULL && gi->index_cache == NULL) {
528 /* read from disk */
529 fseek(gi->GeoIPDatabase, (long)gi->record_length * 2 * offset, SEEK_SET);
530 fread(stack_buffer,gi->record_length,2,gi->GeoIPDatabase);
531 } else if (gi->index_cache == NULL) {
532 /* simply point to record in memory */
533 buf = gi->cache + (long)gi->record_length * 2 *offset;
534 } else {
535 buf = gi->index_cache + (long)gi->record_length * 2 * offset;
536 }
537
538 if (ipnum & (1 << depth)) {
539 /* Take the right-hand branch */
540 if ( gi->record_length == 3 ) {
541 /* Most common case is completely unrolled and uses constants. */
542 x = (buf[3*1 + 0] << (0*8))
543 + (buf[3*1 + 1] << (1*8))
544 + (buf[3*1 + 2] << (2*8));
545
546 } else {
547 /* General case */
548 j = gi->record_length;
549 p = &buf[2*j];
550 x = 0;
551 do {
552 x <<= 8;
553 x += *(--p);
554 } while ( --j );
555 }
556
557 } else {
558 /* Take the left-hand branch */
559 if ( gi->record_length == 3 ) {
560 /* Most common case is completely unrolled and uses constants. */
561 x = (buf[3*0 + 0] << (0*8))
562 + (buf[3*0 + 1] << (1*8))
563 + (buf[3*0 + 2] << (2*8));
564 } else {
565 /* General case */
566 j = gi->record_length;
567 p = &buf[1*j];
568 x = 0;
569 do {
570 x <<= 8;
571 x += *(--p);
572 } while ( --j );
573 }
574 }
575
576 if (x >= gi->databaseSegments[0]) {
577 gi->netmask = 32 - depth;
578 return x;
579 }
580 offset = x;
581 }
582
583 /* shouldn't reach here */
584 fprintf(stderr,"Error Traversing Database for ipnum = %lu - Perhaps database is corrupt?\n",ipnum);
585 return 0;
586 }
587
588 unsigned long
589 _GeoIP_addr_to_num(const char *addr)
590 {
591 unsigned int c, octet, t;
592 unsigned long ipnum;
593 int i = 3;
594
595 octet = ipnum = 0;
596 while ((c = *addr++)) {
597 if (c == '.') {
598 if (octet > 255)
599 return 0;
600 ipnum <<= 8;
601 ipnum += octet;
602 i--;
603 octet = 0;
604 } else {
605 t = octet;
606 octet <<= 3;
607 octet += t;
608 octet += t;
609 c -= '0';
610 if (c > 9)
611 return 0;
612 octet += c;
613 }
614 }
615 if ((octet > 255) || (i != 0))
616 return 0;
617 ipnum <<= 8;
618 return ipnum + octet;
619 }
620
621 GeoIP* GeoIP_open_type (int type, int flags) {
622 GeoIP * gi;
623 const char * filePath;
624 if (type < 0 || type >= NUM_DB_TYPES) {
625 printf("Invalid database type %d\n", type);
626 return NULL;
627 }
628 _GeoIP_setup_dbfilename();
629 filePath = GeoIPDBFileName[type];
630 if (filePath == NULL) {
631 printf("Invalid database type %d\n", type);
632 return NULL;
633 }
634 gi = GeoIP_open (filePath, flags);
635 return gi;
636 }
637
638 GeoIP* GeoIP_new (int flags) {
639 GeoIP * gi;
640 _GeoIP_setup_dbfilename();
641 gi = GeoIP_open (GeoIPDBFileName[GEOIP_COUNTRY_EDITION], flags);
642 return gi;
643 }
644
645 GeoIP* GeoIP_open (const char * filename, int flags) {
646 struct stat buf;
647 GeoIP * gi;
648 size_t len;
649
650 #if defined(WIN32) || defined(WIN64)
651 WSADATA wsa;
652 if (WSAStartup(MAKEWORD(1, 1), &wsa) != 0)
653 return NULL;
654 #endif
655
656 gi = (GeoIP *)malloc(sizeof(GeoIP));
657 if (gi == NULL)
658 return NULL;
659 len = sizeof(char) * (strlen(filename)+1);
660 gi->file_path = malloc(len);
661 if (gi->file_path == NULL) {
662 free(gi);
663 return NULL;
664 }
665 strncpy(gi->file_path, filename, len);
666 gi->GeoIPDatabase = fopen(filename,"rb");
667 if (gi->GeoIPDatabase == NULL) {
668 fprintf(stderr,"Error Opening file %s\n",filename);
669 free(gi->file_path);
670 free(gi);
671 return NULL;
672 } else {
673 if (flags & (GEOIP_MEMORY_CACHE | GEOIP_MMAP_CACHE) ) {
674 if (fstat(fileno(gi->GeoIPDatabase), &buf) == -1) {
675 fprintf(stderr,"Error stating file %s\n",filename);
676 free(gi->file_path);
677 free(gi);
678 return NULL;
679 }
680 gi->mtime = buf.st_mtime;
681 gi->size = buf.st_size;
682
683 /* MMAP added my Peter Shipley */
684 if ( flags & GEOIP_MMAP_CACHE ) {
685 #if !defined(WIN32) && !defined(WIN64)
686 gi->cache = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fileno(gi->GeoIPDatabase), 0);
687 if ( gi->cache == MAP_FAILED ) {
688 fprintf(stderr,"Error mmaping file %s\n",filename);
689 free(gi->file_path);
690 free(gi);
691 return NULL;
692 }
693 #endif
694 } else {
695 gi->cache = (unsigned char *) malloc(sizeof(unsigned char) * buf.st_size);
696
697 if (gi->cache != NULL) {
698 if (fread(gi->cache, sizeof(unsigned char), buf.st_size, gi->GeoIPDatabase) != (size_t) buf.st_size) {
699 fprintf(stderr,"Error reading file %s\n",filename);
700 free(gi->cache);
701 free(gi->file_path);
702 free(gi);
703 return NULL;
704 }
705 }
706 }
707 } else {
708 if (flags & GEOIP_CHECK_CACHE) {
709 if (fstat(fileno(gi->GeoIPDatabase), &buf) == -1) {
710 fprintf(stderr,"Error stating file %s\n",filename);
711 free(gi->file_path);
712 free(gi);
713 return NULL;
714 }
715 gi->mtime = buf.st_mtime;
716 }
717 gi->cache = NULL;
718 }
719 gi->flags = flags;
720 gi->charset = GEOIP_CHARSET_ISO_8859_1;
721
722 _setup_segments(gi);
723 if (flags & GEOIP_INDEX_CACHE) {
724 gi->index_cache = (unsigned char *) malloc(sizeof(unsigned char) * ((gi->databaseSegments[0] * (long)gi->record_length * 2)));
725 if (gi->index_cache != NULL) {
726 fseek(gi->GeoIPDatabase, 0, SEEK_SET);
727 if (fread(gi->index_cache, sizeof(unsigned char), gi->databaseSegments[0] * (long)gi->record_length * 2, gi->GeoIPDatabase) != (size_t) (gi->databaseSegments[0]*(long)gi->record_length * 2)) {
728 fprintf(stderr,"Error reading file %s\n",filename);
729 free(gi->databaseSegments);
730 free(gi->index_cache);
731 free(gi);
732 return NULL;
733 }
734 }
735 } else {
736 gi->index_cache = NULL;
737 }
738 return gi;
739 }
740 }
741
742 void GeoIP_delete (GeoIP *gi) {
743 if (gi == NULL )
744 return;
745 if (gi->GeoIPDatabase != NULL)
746 fclose(gi->GeoIPDatabase);
747 if (gi->cache != NULL) {
748 if ( gi->flags & GEOIP_MMAP_CACHE ) {
749 #if !defined(WIN32) && !defined(WIN64)
750 munmap(gi->cache, gi->size);
751 #endif
752 } else {
753 free(gi->cache);
754 }
755 gi->cache = NULL;
756 }
757 if (gi->index_cache != NULL)
758 free(gi->index_cache);
759 if (gi->file_path != NULL)
760 free(gi->file_path);
761 if (gi->databaseSegments != NULL)
762 free(gi->databaseSegments);
763 free(gi);
764 }
765
766 const char *GeoIP_country_code_by_name (GeoIP* gi, const char *name) {
767 int country_id;
768 country_id = GeoIP_id_by_name(gi, name);
769 return (country_id > 0) ? GeoIP_country_code[country_id] : NULL;
770 }
771
772 const char *GeoIP_country_code3_by_name (GeoIP* gi, const char *name) {
773 int country_id;
774 country_id = GeoIP_id_by_name(gi, name);
775 return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL;
776 }
777
778 const char *GeoIP_country_name_by_name (GeoIP* gi, const char *name) {
779 int country_id;
780 country_id = GeoIP_id_by_name(gi, name);
781 return (country_id > 0) ? GeoIP_country_name[country_id] : NULL;
782 }
783
784 unsigned long _GeoIP_lookupaddress (const char *host) {
785 unsigned long addr = inet_addr(host);
786 struct hostent phe2;
787 struct hostent * phe = &phe2;
788 char *buf = NULL;
789 #ifdef HAVE_GETHOSTBYNAME_R
790 int buflength = 16384;
791 int herr = 0;
792 #endif
793 int result = 0;
794 #ifdef HAVE_GETHOSTBYNAME_R
795 buf = malloc(buflength);
796 #endif
797 if (addr == INADDR_NONE) {
798 #ifdef HAVE_GETHOSTBYNAME_R
799 while (1) {
800 /* we use gethostbyname_r here because it is thread-safe and gethostbyname is not */
801 #ifdef GETHOSTBYNAME_R_RETURNS_INT
802 result = gethostbyname_r(host,&phe2,buf,buflength,&phe,&herr);
803 #else
804 phe = gethostbyname_r(host,&phe2,buf,buflength,&herr);
805 #endif
806 if (herr != ERANGE)
807 break;
808 if (result == 0)
809 break;
810 /* double the buffer if the buffer is too small */
811 buflength = buflength * 2;
812 buf = realloc(buf,buflength);
813 }
814 #endif
815 #ifndef HAVE_GETHOSTBYNAME_R
816 /* Some systems do not support gethostbyname_r, such as Mac OS X */
817 phe = gethostbyname(host);
818 #endif
819 if (!phe || result != 0) {
820 free(buf);
821 return 0;
822 }
823 addr = *((unsigned long *) phe->h_addr_list[0]);
824 }
825 #ifdef HAVE_GETHOSTBYNAME_R
826 free(buf);
827 #endif
828 return ntohl(addr);
829 }
830
831 geoipv6_t
832 _GeoIP_lookupaddress_v6(const char *host)
833 {
834 geoipv6_t ipnum;
835 int gaierr;
836 struct addrinfo hints, *aifirst;
837
838 memset(&hints, 0, sizeof(hints));
839 hints.ai_family = AF_INET6;
840 /* hints.ai_flags = AI_V4MAPPED; */
841 hints.ai_socktype = SOCK_STREAM;
842
843 if ((gaierr = getaddrinfo(host, NULL, &hints, &aifirst)) != 0) {
844 /* fprintf(stderr, "Err: %s (%d %s)\n", host, gaierr, gai_strerror(gaierr)); */
845 return IPV6_NULL;
846 }
847 memcpy(ipnum.s6_addr, ((struct sockaddr_in6 *) aifirst->ai_addr)->sin6_addr.s6_addr, sizeof(geoipv6_t));
848 freeaddrinfo(aifirst);
849 /* inet_pton(AF_INET6, host, ipnum.s6_addr); */
850
851 return ipnum;
852 }
853
854 int GeoIP_id_by_name (GeoIP* gi, const char *name) {
855 unsigned long ipnum;
856 int ret;
857 if (name == NULL) {
858 return 0;
859 }
860 if (gi->databaseType != GEOIP_COUNTRY_EDITION && gi->databaseType != GEOIP_PROXY_EDITION && gi->databaseType != GEOIP_NETSPEED_EDITION) {
861 printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_COUNTRY_EDITION]);
862 return 0;
863 }
864 if (!(ipnum = _GeoIP_lookupaddress(name)))
865 return 0;
866 ret = _GeoIP_seek_record(gi, ipnum) - COUNTRY_BEGIN;
867 return ret;
868
869 }
870
871 int GeoIP_id_by_name_v6 (GeoIP* gi, const char *name) {
872 geoipv6_t ipnum;
873 int ret;
874 if (name == NULL) {
875 return 0;
876 }
877 if (gi->databaseType != GEOIP_COUNTRY_EDITION_V6 && gi->databaseType != GEOIP_PROXY_EDITION && gi->databaseType != GEOIP_NETSPEED_EDITION) {
878 printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_COUNTRY_EDITION_V6]);
879 return 0;
880 }
881 ipnum = _GeoIP_lookupaddress_v6(name);
882 if (__GEOIP_V6_IS_NULL(ipnum))
883 return 0;
884 ret = _GeoIP_seek_record_v6(gi, ipnum) - COUNTRY_BEGIN;
885 return ret;
886 }
887
888 const char *GeoIP_country_code_by_addr (GeoIP* gi, const char *addr) {
889 int country_id;
890 country_id = GeoIP_id_by_addr(gi, addr);
891 return (country_id > 0) ? GeoIP_country_code[country_id] : NULL;
892 }
893
894 const char *GeoIP_country_code3_by_addr (GeoIP* gi, const char *addr) {
895 int country_id;
896 country_id = GeoIP_id_by_addr(gi, addr);
897 return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL;
898 }
899
900 const char *GeoIP_country_name_by_addr (GeoIP* gi, const char *addr) {
901 int country_id;
902 country_id = GeoIP_id_by_addr(gi, addr);
903 return (country_id > 0) ? GeoIP_country_name[country_id] : NULL;
904 }
905
906 const char *GeoIP_country_name_by_ipnum (GeoIP* gi, unsigned long ipnum) {
907 int country_id;
908 country_id = GeoIP_id_by_ipnum(gi, ipnum);
909 return (country_id > 0) ? GeoIP_country_name[country_id] : NULL;
910 }
911
912 const char *GeoIP_country_name_by_ipnum_v6 (GeoIP* gi, geoipv6_t ipnum) {
913 int country_id;
914 country_id = GeoIP_id_by_ipnum_v6(gi, ipnum);
915 return (country_id > 0) ? GeoIP_country_name[country_id] : NULL;
916 }
917
918 const char *GeoIP_country_code_by_ipnum (GeoIP* gi, unsigned long ipnum) {
919 int country_id;
920 country_id = GeoIP_id_by_ipnum(gi, ipnum);
921 return (country_id > 0) ? GeoIP_country_code[country_id] : NULL;
922 }
923
924 const char *GeoIP_country_code_by_ipnum_v6 (GeoIP* gi, geoipv6_t ipnum) {
925 int country_id;
926 country_id = GeoIP_id_by_ipnum_v6(gi, ipnum);
927 return (country_id > 0) ? GeoIP_country_code[country_id] : NULL;
928 }
929
930 const char *GeoIP_country_code3_by_ipnum (GeoIP* gi, unsigned long ipnum) {
931 int country_id;
932 country_id = GeoIP_id_by_ipnum(gi, ipnum);
933 return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL;
934 }
935
936 const char *GeoIP_country_code3_by_ipnum_v6 (GeoIP* gi, geoipv6_t ipnum) {
937 int country_id;
938 country_id = GeoIP_id_by_ipnum_v6(gi, ipnum);
939 return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL;
940 }
941
942 int GeoIP_country_id_by_addr (GeoIP* gi, const char *addr) {
943 return GeoIP_id_by_addr(gi, addr);
944 }
945
946 int GeoIP_country_id_by_name (GeoIP* gi, const char *host) {
947 return GeoIP_id_by_name(gi, host);
948 }
949
950 int GeoIP_id_by_addr_v6 (GeoIP* gi, const char *addr) {
951 geoipv6_t ipnum;
952 int ret;
953 if (addr == NULL) {
954 return 0;
955 }
956 if (gi->databaseType != GEOIP_COUNTRY_EDITION_V6 &&
957 gi->databaseType != GEOIP_PROXY_EDITION &&
958 gi->databaseType != GEOIP_NETSPEED_EDITION) {
959 printf("Invalid database type %s, expected %s\n",
960 GeoIPDBDescription[(int)gi->databaseType],
961 GeoIPDBDescription[GEOIP_COUNTRY_EDITION_V6]);
962 return 0;
963 }
964 ipnum = _GeoIP_addr_to_num_v6(addr);
965 ret = _GeoIP_seek_record_v6(gi, ipnum) - COUNTRY_BEGIN;
966 return ret;
967 }
968
969 int GeoIP_id_by_addr (GeoIP* gi, const char *addr) {
970 unsigned long ipnum;
971 int ret;
972 if (addr == NULL) {
973 return 0;
974 }
975 if (gi->databaseType != GEOIP_COUNTRY_EDITION &&
976 gi->databaseType != GEOIP_PROXY_EDITION &&
977 gi->databaseType != GEOIP_NETSPEED_EDITION) {
978 printf("Invalid database type %s, expected %s\n",
979 GeoIPDBDescription[(int)gi->databaseType],
980 GeoIPDBDescription[GEOIP_COUNTRY_EDITION]);
981 return 0;
982 }
983 ipnum = _GeoIP_addr_to_num(addr);
984 ret = _GeoIP_seek_record(gi, ipnum) - COUNTRY_BEGIN;
985 return ret;
986 }
987
988 int GeoIP_id_by_ipnum_v6 (GeoIP* gi, geoipv6_t ipnum) {
989 int ret;
990 /* if (ipnum == 0) {
991 return 0;
992 }
993 */
994 if (gi->databaseType != GEOIP_COUNTRY_EDITION_V6 &&
995 gi->databaseType != GEOIP_PROXY_EDITION &&
996 gi->databaseType != GEOIP_NETSPEED_EDITION) {
997 printf("Invalid database type %s, expected %s\n",
998 GeoIPDBDescription[(int)gi->databaseType],
999 GeoIPDBDescription[GEOIP_COUNTRY_EDITION_V6]);
1000 return 0;
1001 }
1002 ret = _GeoIP_seek_record_v6(gi, ipnum) - COUNTRY_BEGIN;
1003 return ret;
1004 }
1005
1006
1007
1008 int GeoIP_id_by_ipnum (GeoIP* gi, unsigned long ipnum) {
1009 int ret;
1010 if (ipnum == 0) {
1011 return 0;
1012 }
1013 if (gi->databaseType != GEOIP_COUNTRY_EDITION &&
1014 gi->databaseType != GEOIP_PROXY_EDITION &&
1015 gi->databaseType != GEOIP_NETSPEED_EDITION) {
1016 printf("Invalid database type %s, expected %s\n",
1017 GeoIPDBDescription[(int)gi->databaseType],
1018 GeoIPDBDescription[GEOIP_COUNTRY_EDITION]);
1019 return 0;
1020 }
1021 ret = _GeoIP_seek_record(gi, ipnum) - COUNTRY_BEGIN;
1022 return ret;
1023 }
1024
1025 char *GeoIP_database_info (GeoIP* gi) {
1026 int i;
1027 unsigned char buf[3];
1028 char *retval;
1029 int hasStructureInfo = 0;
1030
1031 if(gi == NULL)
1032 return NULL;
1033
1034 _check_mtime(gi);
1035 fseek(gi->GeoIPDatabase, -3l, SEEK_END);
1036
1037 /* first get past the database structure information */
1038 for (i = 0; i < STRUCTURE_INFO_MAX_SIZE; i++) {
1039 fread(buf, 1, 3, gi->GeoIPDatabase);
1040 if (buf[0] == 255 && buf[1] == 255 && buf[2] == 255) {
1041 hasStructureInfo = 1;
1042 break;
1043 }
1044 fseek(gi->GeoIPDatabase, -4l, SEEK_CUR);
1045 }
1046 if (hasStructureInfo == 1) {
1047 fseek(gi->GeoIPDatabase, -6l, SEEK_CUR);
1048 } else {
1049 /* no structure info, must be pre Sep 2002 database, go back to end */
1050 fseek(gi->GeoIPDatabase, -3l, SEEK_END);
1051 }
1052
1053 for (i = 0; i < DATABASE_INFO_MAX_SIZE; i++) {
1054 fread(buf, 1, 3, gi->GeoIPDatabase);
1055 if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0) {
1056 retval = malloc(sizeof(char) * (i+1));
1057 if (retval == NULL) {
1058 return NULL;
1059 }
1060 fread(retval, 1, i, gi->GeoIPDatabase);
1061 retval[i] = '\0';
1062 return retval;
1063 }
1064 fseek(gi->GeoIPDatabase, -4l, SEEK_CUR);
1065 }
1066 return NULL;
1067 }
1068
1069 /* GeoIP Region Edition functions */
1070
1071 void GeoIP_assign_region_by_inetaddr(GeoIP* gi, unsigned long inetaddr, GeoIPRegion *region) {
1072 unsigned int seek_region;
1073
1074 /* This also writes in the terminating NULs (if you decide to
1075 * keep them) and clear any fields that are not set. */
1076 memset(region, 0, sizeof(GeoIPRegion));
1077
1078 seek_region = _GeoIP_seek_record(gi, ntohl(inetaddr));
1079
1080 if (gi->databaseType == GEOIP_REGION_EDITION_REV0) {
1081 /* Region Edition, pre June 2003 */
1082 seek_region -= STATE_BEGIN_REV0;
1083 if (seek_region >= 1000) {
1084 region->country_code[0] = 'U';
1085 region->country_code[1] = 'S';
1086 region->region[0] = (char) ((seek_region - 1000)/26 + 65);
1087 region->region[1] = (char) ((seek_region - 1000)%26 + 65);
1088 } else {
1089 memcpy(region->country_code, GeoIP_country_code[seek_region], 2);
1090 }
1091 } else if (gi->databaseType == GEOIP_REGION_EDITION_REV1) {
1092 /* Region Edition, post June 2003 */
1093 seek_region -= STATE_BEGIN_REV1;
1094 if (seek_region < US_OFFSET) {
1095 /* Unknown */
1096 /* we don't need to do anything here b/c we memset region to 0 */
1097 } else if (seek_region < CANADA_OFFSET) {
1098 /* USA State */
1099 region->country_code[0] = 'U';
1100 region->country_code[1] = 'S';
1101 region->region[0] = (char) ((seek_region - US_OFFSET)/26 + 65);
1102 region->region[1] = (char) ((seek_region - US_OFFSET)%26 + 65);
1103 } else if (seek_region < WORLD_OFFSET) {
1104 /* Canada Province */
1105 region->country_code[0] = 'C';
1106 region->country_code[1] = 'A';
1107 region->region[0] = (char) ((seek_region - CANADA_OFFSET)/26 + 65);
1108 region->region[1] = (char) ((seek_region - CANADA_OFFSET)%26 + 65);
1109 } else {
1110 /* Not US or Canada */
1111 memcpy(region->country_code, GeoIP_country_code[(seek_region - WORLD_OFFSET) / FIPS_RANGE], 2);
1112 }
1113 }
1114 }
1115
1116 void GeoIP_assign_region_by_inetaddr_v6(GeoIP* gi, geoipv6_t inetaddr, GeoIPRegion *region) {
1117 unsigned int seek_region;
1118
1119 /* This also writes in the terminating NULs (if you decide to
1120 * keep them) and clear any fields that are not set. */
1121 memset(region, 0, sizeof(GeoIPRegion));
1122
1123 seek_region = _GeoIP_seek_record_v6(gi, inetaddr);
1124
1125 if (gi->databaseType == GEOIP_REGION_EDITION_REV0) {
1126 /* Region Edition, pre June 2003 */
1127 seek_region -= STATE_BEGIN_REV0;
1128 if (seek_region >= 1000) {
1129 region->country_code[0] = 'U';
1130 region->country_code[1] = 'S';
1131 region->region[0] = (char) ((seek_region - 1000)/26 + 65);
1132 region->region[1] = (char) ((seek_region - 1000)%26 + 65);
1133 } else {
1134 memcpy(region->country_code, GeoIP_country_code[seek_region], 2);
1135 }
1136 } else if (gi->databaseType == GEOIP_REGION_EDITION_REV1) {
1137 /* Region Edition, post June 2003 */
1138 seek_region -= STATE_BEGIN_REV1;
1139 if (seek_region < US_OFFSET) {
1140 /* Unknown */
1141 /* we don't need to do anything here b/c we memset region to 0 */
1142 } else if (seek_region < CANADA_OFFSET) {
1143 /* USA State */
1144 region->country_code[0] = 'U';
1145 region->country_code[1] = 'S';
1146 region->region[0] = (char) ((seek_region - US_OFFSET)/26 + 65);
1147 region->region[1] = (char) ((seek_region - US_OFFSET)%26 + 65);
1148 } else if (seek_region < WORLD_OFFSET) {
1149 /* Canada Province */
1150 region->country_code[0] = 'C';
1151 region->country_code[1] = 'A';
1152 region->region[0] = (char) ((seek_region - CANADA_OFFSET)/26 + 65);
1153 region->region[1] = (char) ((seek_region - CANADA_OFFSET)%26 + 65);
1154 } else {
1155 /* Not US or Canada */
1156 memcpy(region->country_code, GeoIP_country_code[(seek_region - WORLD_OFFSET) / FIPS_RANGE], 2);
1157 }
1158 }
1159 }
1160
1161 static
1162 GeoIPRegion * _get_region(GeoIP* gi, unsigned long ipnum) {
1163 GeoIPRegion * region;
1164
1165 region = malloc(sizeof(GeoIPRegion));
1166 if (region) {
1167 GeoIP_assign_region_by_inetaddr(gi, htonl(ipnum), region);
1168 }
1169 return region;
1170 }
1171
1172 static
1173 GeoIPRegion * _get_region_v6(GeoIP* gi, geoipv6_t ipnum) {
1174 GeoIPRegion * region;
1175
1176 region = malloc(sizeof(GeoIPRegion));
1177 if (region) {
1178 GeoIP_assign_region_by_inetaddr_v6(gi, ipnum, region);
1179 }
1180 return region;
1181 }
1182
1183 GeoIPRegion * GeoIP_region_by_addr (GeoIP* gi, const char *addr) {
1184 unsigned long ipnum;
1185 if (addr == NULL) {
1186 return 0;
1187 }
1188 if (gi->databaseType != GEOIP_REGION_EDITION_REV0 &&
1189 gi->databaseType != GEOIP_REGION_EDITION_REV1) {
1190 printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_REGION_EDITION_REV1]);
1191 return 0;
1192 }
1193 ipnum = _GeoIP_addr_to_num(addr);
1194 return _get_region(gi, ipnum);
1195 }
1196
1197 GeoIPRegion * GeoIP_region_by_addr_v6 (GeoIP* gi, const char *addr) {
1198 geoipv6_t ipnum;
1199 if (addr == NULL) {
1200 return 0;
1201 }
1202 if (gi->databaseType != GEOIP_REGION_EDITION_REV0 &&
1203 gi->databaseType != GEOIP_REGION_EDITION_REV1) {
1204 printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_REGION_EDITION_REV1]);
1205 return 0;
1206 }
1207 ipnum = _GeoIP_addr_to_num_v6(addr);
1208 return _get_region_v6(gi, ipnum);
1209 }
1210
1211 GeoIPRegion * GeoIP_region_by_name (GeoIP* gi, const char *name) {
1212 unsigned long ipnum;
1213 if (name == NULL) {
1214 return 0;
1215 }
1216 if (gi->databaseType != GEOIP_REGION_EDITION_REV0 &&
1217 gi->databaseType != GEOIP_REGION_EDITION_REV1) {
1218 printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_REGION_EDITION_REV1]);
1219 return 0;
1220 }
1221 if (!(ipnum = _GeoIP_lookupaddress(name)))
1222 return 0;
1223 return _get_region(gi, ipnum);
1224 }
1225
1226 GeoIPRegion * GeoIP_region_by_name_v6 (GeoIP* gi, const char *name) {
1227 geoipv6_t ipnum;
1228 if (name == NULL) {
1229 return 0;
1230 }
1231 if (gi->databaseType != GEOIP_REGION_EDITION_REV0 &&
1232 gi->databaseType != GEOIP_REGION_EDITION_REV1) {
1233 printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_REGION_EDITION_REV1]);
1234 return 0;
1235 }
1236
1237 ipnum = _GeoIP_lookupaddress_v6(name);
1238 if (__GEOIP_V6_IS_NULL(ipnum))
1239 return 0;
1240 return _get_region_v6(gi, ipnum);
1241 }
1242
1243 GeoIPRegion * GeoIP_region_by_ipnum (GeoIP* gi, unsigned long ipnum) {
1244 if (gi->databaseType != GEOIP_REGION_EDITION_REV0 &&
1245 gi->databaseType != GEOIP_REGION_EDITION_REV1) {
1246 printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_REGION_EDITION_REV1]);
1247 return 0;
1248 }
1249 return _get_region(gi, ipnum);
1250 }
1251
1252 GeoIPRegion * GeoIP_region_by_ipnum_v6 (GeoIP* gi, geoipv6_t ipnum) {
1253 if (gi->databaseType != GEOIP_REGION_EDITION_REV0 &&
1254 gi->databaseType != GEOIP_REGION_EDITION_REV1) {
1255 printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_REGION_EDITION_REV1]);
1256 return 0;
1257 }
1258 return _get_region_v6(gi, ipnum);
1259 }
1260
1261 void GeoIPRegion_delete (GeoIPRegion *gir) {
1262 free(gir);
1263 }
1264
1265 /* GeoIP Organization, ISP and AS Number Edition private method */
1266 static
1267 char *_get_name (GeoIP* gi, unsigned long ipnum) {
1268 int seek_org;
1269 char buf[MAX_ORG_RECORD_LENGTH];
1270 char * org_buf, * buf_pointer;
1271 int record_pointer;
1272 size_t len;
1273
1274 if (gi->databaseType != GEOIP_ORG_EDITION &&
1275 gi->databaseType != GEOIP_ISP_EDITION &&
1276 gi->databaseType != GEOIP_ASNUM_EDITION) {
1277 printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_ORG_EDITION]);
1278 return NULL;
1279 }
1280
1281 seek_org = _GeoIP_seek_record(gi, ipnum);
1282 if (seek_org == gi->databaseSegments[0])
1283 return NULL;
1284
1285 record_pointer = seek_org + (2 * gi->record_length - 1) * gi->databaseSegments[0];
1286
1287 if (gi->cache == NULL) {
1288 fseek(gi->GeoIPDatabase, record_pointer, SEEK_SET);
1289 fread(buf, sizeof(char), MAX_ORG_RECORD_LENGTH, gi->GeoIPDatabase);
1290 len = sizeof(char) * (strlen(buf)+1);
1291 org_buf = malloc(len);
1292 strncpy(org_buf, buf, len);
1293 } else {
1294 buf_pointer = gi->cache + (long)record_pointer;
1295 len = sizeof(char) * (strlen(buf_pointer)+1);
1296 org_buf = malloc(len);
1297 strncpy(org_buf, buf_pointer, len);
1298 }
1299 return org_buf;
1300 }
1301
1302 char *_get_name_v6 (GeoIP* gi, geoipv6_t ipnum) {
1303 int seek_org;
1304 char buf[MAX_ORG_RECORD_LENGTH];
1305 char * org_buf, * buf_pointer;
1306 int record_pointer;
1307 size_t len;
1308
1309 if (gi->databaseType != GEOIP_ORG_EDITION &&
1310 gi->databaseType != GEOIP_ISP_EDITION &&
1311 gi->databaseType != GEOIP_ASNUM_EDITION) {
1312 printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_ORG_EDITION]);
1313 return NULL;
1314 }
1315
1316 seek_org = _GeoIP_seek_record_v6(gi, ipnum);
1317 if (seek_org == gi->databaseSegments[0])
1318 return NULL;
1319
1320 record_pointer = seek_org + (2 * gi->record_length - 1) * gi->databaseSegments[0];
1321
1322 if (gi->cache == NULL) {
1323 fseek(gi->GeoIPDatabase, record_pointer, SEEK_SET);
1324 fread(buf, sizeof(char), MAX_ORG_RECORD_LENGTH, gi->GeoIPDatabase);
1325 len = sizeof(char) * (strlen(buf)+1);
1326 org_buf = malloc(len);
1327 strncpy(org_buf, buf, len);
1328 } else {
1329 buf_pointer = gi->cache + (long)record_pointer;
1330 len = sizeof(char) * (strlen(buf_pointer)+1);
1331 org_buf = malloc(len);
1332 strncpy(org_buf, buf_pointer, len);
1333 }
1334 return org_buf;
1335 }
1336
1337 char *_GeoIP_num_to_addr (GeoIP* gi, unsigned long ipnum) {
1338 char *ret_str;
1339 char *cur_str;
1340 int octet[4];
1341 int num_chars_written, i;
1342
1343 ret_str = malloc(sizeof(char) * 16);
1344 cur_str = ret_str;
1345
1346 for (i = 0; i<4; i++) {
1347 octet[3 - i] = ipnum % 256;
1348 ipnum >>= 8;
1349 }
1350
1351 for (i = 0; i<4; i++) {
1352 num_chars_written = sprintf(cur_str, "%d", octet[i]);
1353 cur_str += num_chars_written;
1354
1355 if (i < 3) {
1356 cur_str[0] = '.';
1357 cur_str++;
1358 }
1359 }
1360
1361 return ret_str;
1362 }
1363
1364 char **GeoIP_range_by_ip (GeoIP* gi, const char *addr) {
1365 unsigned long ipnum;
1366 unsigned long left_seek;
1367 unsigned long right_seek;
1368 unsigned long mask;
1369 int orig_netmask;
1370 int target_value;
1371 char **ret;
1372
1373 if (addr == NULL) {
1374 return 0;
1375 }
1376
1377 ret = malloc(sizeof(char *) * 2);
1378
1379 ipnum = _GeoIP_addr_to_num(addr);
1380 target_value = _GeoIP_seek_record(gi, ipnum);
1381 orig_netmask = GeoIP_last_netmask(gi);
1382 mask = 0xffffffff << ( 32 - orig_netmask );
1383 left_seek = ipnum & mask;
1384 right_seek = left_seek + ( 0xffffffff & ~mask );
1385
1386 while (left_seek != 0
1387 && target_value == _GeoIP_seek_record(gi, left_seek - 1) ) {
1388
1389 /* Go to beginning of netblock defined by netmask */
1390 mask = 0xffffffff << ( 32 - GeoIP_last_netmask(gi) );
1391 left_seek = --left_seek & mask;
1392 }
1393 ret[0] = _GeoIP_num_to_addr(gi, left_seek);
1394
1395 while (right_seek != 0xffffffff
1396 && target_value == _GeoIP_seek_record(gi, right_seek + 1) ) {
1397
1398 /* Go to end of netblock defined by netmask */
1399 mask = 0xffffffff << ( 32 - GeoIP_last_netmask(gi) );
1400 right_seek = ++right_seek & mask;
1401 right_seek += 0xffffffff & ~mask;
1402 }
1403 ret[1] = _GeoIP_num_to_addr(gi, right_seek);
1404
1405 gi->netmask = orig_netmask;
1406
1407 return ret;
1408 }
1409
1410 void GeoIP_range_by_ip_delete( char ** ptr ){
1411 if ( ptr ){
1412 if ( ptr[0] )
1413 free(ptr[0]);
1414 if ( ptr[1] )
1415 free(ptr[1]);
1416 free(ptr);
1417 }
1418 }
1419
1420 char *GeoIP_name_by_ipnum (GeoIP* gi, unsigned long ipnum) {
1421 return _get_name(gi,ipnum);
1422 }
1423
1424 char *GeoIP_name_by_ipnum_v6 (GeoIP* gi, geoipv6_t ipnum) {
1425 return _get_name_v6(gi,ipnum);
1426 }
1427
1428 char *GeoIP_name_by_addr (GeoIP* gi, const char *addr) {
1429 unsigned long ipnum;
1430 if (addr == NULL) {
1431 return 0;
1432 }
1433 ipnum = _GeoIP_addr_to_num(addr);
1434 return _get_name(gi, ipnum);
1435 }
1436
1437 char *GeoIP_name_by_addr_v6 (GeoIP* gi, const char *addr) {
1438 geoipv6_t ipnum;
1439 if (addr == NULL) {
1440 return 0;
1441 }
1442 ipnum = _GeoIP_addr_to_num_v6(addr);
1443 return _get_name_v6(gi, ipnum);
1444 }
1445
1446 char *GeoIP_name_by_name (GeoIP* gi, const char *name) {
1447 unsigned long ipnum;
1448 if (name == NULL) {
1449 return 0;
1450 }
1451 if (!(ipnum = _GeoIP_lookupaddress(name)))
1452 return 0;
1453 return _get_name(gi, ipnum);
1454 }
1455
1456 char *GeoIP_name_by_name_v6 (GeoIP* gi, const char *name) {
1457 geoipv6_t ipnum;
1458 if (name == NULL) {
1459 return 0;
1460 }
1461 ipnum = _GeoIP_lookupaddress_v6(name);
1462 if (__GEOIP_V6_IS_NULL(ipnum))
1463 return 0;
1464 return _get_name_v6(gi, ipnum);
1465 }
1466
1467 char *GeoIP_org_by_ipnum (GeoIP* gi, unsigned long ipnum) {
1468 return GeoIP_name_by_ipnum(gi, ipnum);
1469 }
1470
1471 char *GeoIP_org_by_ipnum_v6 (GeoIP* gi, geoipv6_t ipnum) {
1472 return GeoIP_name_by_ipnum_v6(gi, ipnum);
1473 }
1474
1475 char *GeoIP_org_by_addr (GeoIP* gi, const char *addr) {
1476 return GeoIP_name_by_addr(gi, addr);
1477 }
1478
1479 char *GeoIP_org_by_addr_v6 (GeoIP* gi, const char *addr) {
1480 return GeoIP_name_by_addr_v6(gi, addr);
1481 }
1482
1483 char *GeoIP_org_by_name (GeoIP* gi, const char *name) {
1484 return GeoIP_name_by_name(gi, name);
1485 }
1486
1487 char *GeoIP_org_by_name_v6 (GeoIP* gi, const char *name) {
1488 return GeoIP_name_by_name_v6(gi, name);
1489 }
1490
1491 unsigned char GeoIP_database_edition (GeoIP* gi) {
1492 return gi->databaseType;
1493 }
1494
1495 int GeoIP_charset( GeoIP* gi){
1496 return gi->charset;
1497 }
1498
1499 int GeoIP_set_charset( GeoIP* gi, int charset ){
1500 int old_charset = gi->charset;
1501 gi->charset = charset;
1502 return old_charset;
1503 }
1504
1505 int GeoIP_last_netmask (GeoIP* gi) {
1506 return gi->netmask;
1507 }
1508
1509
1510 /** return two letter country code */
1511 const char* GeoIP_code_by_id(int id)
1512 {
1513 if (id < 0 || id >= num_GeoIP_countries)
1514 return NULL;
1515
1516 return GeoIP_country_code[id];
1517 }
1518
1519 /** return three letter country code */
1520 const char* GeoIP_code3_by_id(int id)
1521 {
1522 if (id < 0 || id >= num_GeoIP_countries)
1523 return NULL;
1524
1525 return GeoIP_country_code3[id];
1526 }
1527
1528
1529 /** return full name of country */
1530 const char* GeoIP_name_by_id(int id)
1531 {
1532 if (id < 0 || id >= num_GeoIP_countries)
1533 return NULL;
1534
1535 return GeoIP_country_name[id];
1536 }
1537
1538 /** return continent of country */
1539 const char* GeoIP_continent_by_id(int id)
1540 {
1541 if (id < 0 || id >= num_GeoIP_countries)
1542 return NULL;
1543
1544 return GeoIP_country_continent[id];
1545 }
1546
1547 /** return id by country code **/
1548 int GeoIP_id_by_code(const char *country)
1549 {
1550 unsigned i;
1551
1552 for ( i = 0; i < num_GeoIP_countries; ++i)
1553 {
1554 if (strcmp(country, GeoIP_country_code[i]) == 0)
1555 return i;
1556 }
1557
1558 return 0;
1559 }
1560
1561 unsigned GeoIP_num_countries(void)
1562 {
1563 return num_GeoIP_countries;
1564 }