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
23static geoipv6_t IPV6_NULL;
24
25#if !defined(_WIN32)
26#include <unistd.h>
27#include <netdb.h>
28#include <sys/mman.h>
29#endif /* !defined(_WIN32) */
30
31#include <errno.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <assert.h>
36#include <sys/types.h> /* for fstat */
37#include <sys/stat.h>	/* for fstat */
38
39#ifdef HAVE_GETTIMEOFDAY
40#include <sys/time.h> /* for gettimeofday */
41#endif
42
43#ifdef HAVE_STDINT_H
44#include <stdint.h>     /* For uint32_t */
45#endif
46
47#ifdef _UNUSED
48#elif defined(__GNUC__)
49#define _UNUSED __attribute__ ((unused))
50#else
51#define _UNUSED
52#endif
53
54#ifndef        INADDR_NONE
55#define        INADDR_NONE     -1
56#endif
57
58#define COUNTRY_BEGIN 16776960
59#define LARGE_COUNTRY_BEGIN 16515072
60#define STATE_BEGIN_REV0 16700000
61#define STATE_BEGIN_REV1 16000000
62#define STRUCTURE_INFO_MAX_SIZE 20
63#define DATABASE_INFO_MAX_SIZE 100
64#define MAX_ORG_RECORD_LENGTH 300
65#define US_OFFSET 1
66#define CANADA_OFFSET 677
67#define WORLD_OFFSET 1353
68#define FIPS_RANGE 360
69
70#define CHECK_ERR(err, msg) { \
71		if (err != Z_OK) { \
72				fprintf(stderr, "%s error: %d\n", msg, err); \
73				exit(1); \
74		} \
75}
76
77#ifndef HAVE_PREAD
78#define pread(fd, buf, count, offset) \
79        ( \
80        lseek(fd, offset, SEEK_SET) == offset ? \
81                read(fd, buf, count) : \
82                -1 \
83                )
84#endif /* HAVE_PREAD */
85
86
87
88const char GeoIP_country_code[255][3] = { "--","AP","EU","AD","AE","AF","AG","AI","AL","AM","CW",
89	"AO","AQ","AR","AS","AT","AU","AW","AZ","BA","BB",
90	"BD","BE","BF","BG","BH","BI","BJ","BM","BN","BO",
91	"BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD",
92	"CF","CG","CH","CI","CK","CL","CM","CN","CO","CR",
93	"CU","CV","CX","CY","CZ","DE","DJ","DK","DM","DO",
94	"DZ","EC","EE","EG","EH","ER","ES","ET","FI","FJ",
95	"FK","FM","FO","FR","SX","GA","GB","GD","GE","GF",
96	"GH","GI","GL","GM","GN","GP","GQ","GR","GS","GT",
97	"GU","GW","GY","HK","HM","HN","HR","HT","HU","ID",
98	"IE","IL","IN","IO","IQ","IR","IS","IT","JM","JO",
99	"JP","KE","KG","KH","KI","KM","KN","KP","KR","KW",
100	"KY","KZ","LA","LB","LC","LI","LK","LR","LS","LT",
101	"LU","LV","LY","MA","MC","MD","MG","MH","MK","ML",
102	"MM","MN","MO","MP","MQ","MR","MS","MT","MU","MV",
103	"MW","MX","MY","MZ","NA","NC","NE","NF","NG","NI",
104	"NL","NO","NP","NR","NU","NZ","OM","PA","PE","PF",
105	"PG","PH","PK","PL","PM","PN","PR","PS","PT","PW",
106	"PY","QA","RE","RO","RU","RW","SA","SB","SC","SD",
107	"SE","SG","SH","SI","SJ","SK","SL","SM","SN","SO",
108	"SR","ST","SV","SY","SZ","TC","TD","TF","TG","TH",
109	"TJ","TK","TM","TN","TO","TL","TR","TT","TV","TW",
110	"TZ","UA","UG","UM","US","UY","UZ","VA","VC","VE",
111	"VG","VI","VN","VU","WF","WS","YE","YT","RS","ZA",
112	"ZM","ME","ZW","A1","A2","O1","AX","GG","IM","JE",
113  "BL","MF", "BQ", "SS" };
114
115static const unsigned num_GeoIP_countries = (unsigned)(sizeof(GeoIP_country_code)/sizeof(GeoIP_country_code[0]));
116
117const char GeoIP_country_code3[255][4] = { "--","AP","EU","AND","ARE","AFG","ATG","AIA","ALB","ARM","CUW",
118	"AGO","ATA","ARG","ASM","AUT","AUS","ABW","AZE","BIH","BRB",
119	"BGD","BEL","BFA","BGR","BHR","BDI","BEN","BMU","BRN","BOL",
120	"BRA","BHS","BTN","BVT","BWA","BLR","BLZ","CAN","CCK","COD",
121	"CAF","COG","CHE","CIV","COK","CHL","CMR","CHN","COL","CRI",
122	"CUB","CPV","CXR","CYP","CZE","DEU","DJI","DNK","DMA","DOM",
123	"DZA","ECU","EST","EGY","ESH","ERI","ESP","ETH","FIN","FJI",
124	"FLK","FSM","FRO","FRA","SXM","GAB","GBR","GRD","GEO","GUF",
125	"GHA","GIB","GRL","GMB","GIN","GLP","GNQ","GRC","SGS","GTM",
126	"GUM","GNB","GUY","HKG","HMD","HND","HRV","HTI","HUN","IDN",
127	"IRL","ISR","IND","IOT","IRQ","IRN","ISL","ITA","JAM","JOR",
128	"JPN","KEN","KGZ","KHM","KIR","COM","KNA","PRK","KOR","KWT",
129	"CYM","KAZ","LAO","LBN","LCA","LIE","LKA","LBR","LSO","LTU",
130	"LUX","LVA","LBY","MAR","MCO","MDA","MDG","MHL","MKD","MLI",
131	"MMR","MNG","MAC","MNP","MTQ","MRT","MSR","MLT","MUS","MDV",
132	"MWI","MEX","MYS","MOZ","NAM","NCL","NER","NFK","NGA","NIC",
133	"NLD","NOR","NPL","NRU","NIU","NZL","OMN","PAN","PER","PYF",
134	"PNG","PHL","PAK","POL","SPM","PCN","PRI","PSE","PRT","PLW",
135	"PRY","QAT","REU","ROU","RUS","RWA","SAU","SLB","SYC","SDN",
136	"SWE","SGP","SHN","SVN","SJM","SVK","SLE","SMR","SEN","SOM",
137	"SUR","STP","SLV","SYR","SWZ","TCA","TCD","ATF","TGO","THA",
138	"TJK","TKL","TKM","TUN","TON","TLS","TUR","TTO","TUV","TWN",
139	"TZA","UKR","UGA","UMI","USA","URY","UZB","VAT","VCT","VEN",
140	"VGB","VIR","VNM","VUT","WLF","WSM","YEM","MYT","SRB","ZAF",
141	"ZMB","MNE","ZWE","A1","A2","O1","ALA","GGY","IMN","JEY",
142  "BLM","MAF", "BES", "SSD" };
143
144const char * GeoIP_utf8_country_name[255] = {"N/A","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Cura" "\xc3\xa7" "ao",
145	"Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados",
146	"Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia",
147	"Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the",
148	"Central African Republic","Congo","Switzerland","Cote D'Ivoire","Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica",
149	"Cuba","Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany","Djibouti","Denmark","Dominica","Dominican Republic",
150	"Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji",
151	"Falkland Islands (Malvinas)","Micronesia, Federated States of","Faroe Islands","France","Sint Maarten (Dutch part)","Gabon","United Kingdom","Grenada","Georgia","French Guiana",
152	"Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala",
153	"Guam","Guinea-Bissau","Guyana","Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia",
154	"Ireland","Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan",
155	"Japan","Kenya","Kyrgyzstan","Cambodia","Kiribati","Comoros","Saint Kitts and Nevis","Korea, Democratic People's Republic of","Korea, Republic of","Kuwait",
156	"Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania",
157	"Luxembourg","Latvia","Libya","Morocco","Monaco","Moldova, Republic of","Madagascar","Marshall Islands","Macedonia","Mali",
158	"Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius","Maldives",
159	"Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua",
160	"Netherlands","Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia",
161	"Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal","Palau",
162	"Paraguay","Qatar","Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia","Solomon Islands","Seychelles","Sudan",
163	"Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname",
164	"Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo","Thailand",
165	"Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu","Taiwan",
166	"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",
167	"Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa",
168	"Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey",
169  "Saint Barthelemy","Saint Martin", "Bonaire, Saint Eustatius and Saba", "South Sudan"};
170
171const char * GeoIP_country_name[255] = {"N/A","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Curacao",
172	"Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados",
173	"Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia",
174	"Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the",
175	"Central African Republic","Congo","Switzerland","Cote D'Ivoire","Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica",
176	"Cuba","Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany","Djibouti","Denmark","Dominica","Dominican Republic",
177	"Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji",
178	"Falkland Islands (Malvinas)","Micronesia, Federated States of","Faroe Islands","France","Sint Maarten (Dutch part)","Gabon","United Kingdom","Grenada","Georgia","French Guiana",
179	"Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala",
180	"Guam","Guinea-Bissau","Guyana","Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia",
181	"Ireland","Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan",
182	"Japan","Kenya","Kyrgyzstan","Cambodia","Kiribati","Comoros","Saint Kitts and Nevis","Korea, Democratic People's Republic of","Korea, Republic of","Kuwait",
183	"Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania",
184	"Luxembourg","Latvia","Libya","Morocco","Monaco","Moldova, Republic of","Madagascar","Marshall Islands","Macedonia","Mali",
185	"Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius","Maldives",
186	"Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua",
187	"Netherlands","Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia",
188	"Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal","Palau",
189	"Paraguay","Qatar","Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia","Solomon Islands","Seychelles","Sudan",
190	"Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname",
191	"Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo","Thailand",
192	"Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu","Taiwan",
193	"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",
194	"Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa",
195	"Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey",
196  "Saint Barthelemy","Saint Martin", "Bonaire, Saint Eustatius and Saba", "South Sudan"};
197
198/* Possible continent codes are AF, AS, EU, NA, OC, SA for Africa, Asia, Europe, North America, Oceania
199and South America. */
200
201const char GeoIP_country_continent[255][3] = {
202  "--", "AS","EU","EU","AS","AS","NA","NA","EU","AS","NA",
203        "AF","AN","SA","OC","EU","OC","NA","AS","EU","NA",
204        "AS","EU","AF","EU","AS","AF","AF","NA","AS","SA",
205        "SA","NA","AS","AN","AF","EU","NA","NA","AS","AF",
206        "AF","AF","EU","AF","OC","SA","AF","AS","SA","NA",
207        "NA","AF","AS","AS","EU","EU","AF","EU","NA","NA",
208        "AF","SA","EU","AF","AF","AF","EU","AF","EU","OC",
209        "SA","OC","EU","EU","NA","AF","EU","NA","AS","SA",
210        "AF","EU","NA","AF","AF","NA","AF","EU","AN","NA",
211        "OC","AF","SA","AS","AN","NA","EU","NA","EU","AS",
212        "EU","AS","AS","AS","AS","AS","EU","EU","NA","AS",
213        "AS","AF","AS","AS","OC","AF","NA","AS","AS","AS",
214        "NA","AS","AS","AS","NA","EU","AS","AF","AF","EU",
215        "EU","EU","AF","AF","EU","EU","AF","OC","EU","AF",
216        "AS","AS","AS","OC","NA","AF","NA","EU","AF","AS",
217        "AF","NA","AS","AF","AF","OC","AF","OC","AF","NA",
218        "EU","EU","AS","OC","OC","OC","AS","NA","SA","OC",
219        "OC","AS","AS","EU","NA","OC","NA","AS","EU","OC",
220        "SA","AS","AF","EU","EU","AF","AS","OC","AF","AF",
221        "EU","AS","AF","EU","EU","EU","AF","EU","AF","AF",
222        "SA","AF","NA","AS","AF","NA","AF","AN","AF","AS",
223        "AS","OC","AS","AF","OC","AS","EU","NA","OC","AS",
224        "AF","EU","AF","OC","NA","SA","AS","EU","NA","SA",
225        "NA","NA","AS","OC","OC","OC","AS","AF","EU","AF",
226        "AF","EU","AF","--","--","--","EU","EU","EU","EU",
227        "NA","NA","NA", "AF"
228};
229
230static const char * get_db_description(int dbtype){
231    const char * ptr;
232    if ( dbtype >= NUM_DB_TYPES || dbtype < 0 )
233        return "Unknown";
234    ptr = GeoIPDBDescription[dbtype];
235    return ptr == NULL ? "Unknown" : ptr;
236}
237
238geoipv6_t _GeoIP_lookupaddress_v6 (const char *host);
239
240#if defined(_WIN32)
241/* http://www.mail-archive.com/users@ipv6.org/msg02107.html */
242static const char * _GeoIP_inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
243{
244        if (af == AF_INET)
245        {
246                struct sockaddr_in in;
247                memset(&in, 0, sizeof(in));
248                in.sin_family = AF_INET;
249                memcpy(&in.sin_addr, src, sizeof(struct in_addr));
250                getnameinfo((struct sockaddr *)&in, sizeof(struct
251sockaddr_in), dst, cnt, NULL, 0, NI_NUMERICHOST);
252                return dst;
253        }
254        else if (af == AF_INET6)
255        {
256                struct sockaddr_in6 in;
257                memset(&in, 0, sizeof(in));
258                in.sin6_family = AF_INET6;
259                memcpy(&in.sin6_addr, src, sizeof(struct in_addr6));
260                getnameinfo((struct sockaddr *)&in, sizeof(struct
261sockaddr_in6), dst, cnt, NULL, 0, NI_NUMERICHOST);
262                return dst;
263        }
264        return NULL;
265}
266
267static int _GeoIP_inet_pton(int af, const char *src, void *dst)
268{
269        struct addrinfo hints, *res, *ressave;
270
271        memset(&hints, 0, sizeof(struct addrinfo));
272        hints.ai_family = af;
273
274        if (getaddrinfo(src, NULL, &hints, &res) != 0)
275        {
276                fprintf(stderr, "Couldn't resolve host %s\n", src);
277                return -1;
278        }
279
280        ressave = res;
281
282        while (res)
283        {
284                memcpy(dst, res->ai_addr, res->ai_addrlen);
285                res = res->ai_next;
286        }
287
288        freeaddrinfo(ressave);
289        return 0;
290}
291#else
292static int _GeoIP_inet_pton(int af, const char *src, void *dst) {
293  return inet_pton(af, src, dst);
294}
295static const char * _GeoIP_inet_ntop(int af, const void *src, char *dst, socklen_t cnt) {
296  return inet_ntop(af, src, dst, cnt);
297}
298
299#endif /* defined(_WIN32) */
300
301
302int __GEOIP_V6_IS_NULL(geoipv6_t v6) {
303        int i;
304        for (i=0;i<16;i++) {
305                if (v6.s6_addr[i])
306                        return 0;
307        }
308        return 1;
309}
310
311void __GEOIP_PREPARE_TEREDO(geoipv6_t* v6){
312   int i;
313   if ((v6->s6_addr[0]) != 0x20) return;
314   if ((v6->s6_addr[1]) != 0x01) return;
315   if ((v6->s6_addr[2]) != 0x00) return;
316   if ((v6->s6_addr[3]) != 0x00) return;
317
318   for ( i = 0; i< 12; i++)
319     v6->s6_addr[i] = 0;
320   for ( ; i < 16; i++)
321     v6->s6_addr[i]^=0xff;
322}
323
324const char * GeoIPDBDescription[NUM_DB_TYPES] = {
325  NULL,
326  "GeoIP Country Edition",
327  "GeoIP City Edition, Rev 1",
328  "GeoIP Region Edition, Rev 1",
329  "GeoIP ISP Edition",
330  "GeoIP Organization Edition",
331  "GeoIP City Edition, Rev 0",
332  "GeoIP Region Edition, Rev 0",
333  "GeoIP Proxy Edition",
334  "GeoIP ASNum Edition",
335  "GeoIP Netspeed Edition",
336  "GeoIP Domain Name Edition",
337  "GeoIP Country V6 Edition",
338  "GeoIP LocationID ASCII Edition",
339  "GeoIP Accuracy Radius Edition",
340  NULL,
341  NULL,
342  "GeoIP Large Country Edition",
343  "GeoIP Large Country V6 Edition",
344  NULL,
345  "GeoIP CCM Edition",
346  "GeoIP ASNum V6 Edition",
347  "GeoIP ISP V6 Edition",
348  "GeoIP Organization V6 Edition",
349  "GeoIP Domain Name V6 Edition",
350  "GeoIP LocationID ASCII V6 Edition",
351  "GeoIP Registrar Edition",
352  "GeoIP Registrar V6 Edition",
353  "GeoIP UserType Edition",
354  "GeoIP UserType V6 Edition",
355  "GeoIP City Edition V6, Rev 1",
356  "GeoIP City Edition V6, Rev 0",
357  "GeoIP Netspeed Edition, Rev 1",
358  "GeoIP Netspeed Edition V6, Rev1",
359  "GeoIP Country Confidence Edition",
360  "GeoIP City Confidence Edition",
361  "GeoIP Region Confidence Edition",
362  "GeoIP Postal Confidence Edition",
363  "GeoIP Accuracy Radius Edition V6"
364};
365
366char * GeoIP_custom_directory = NULL;
367
368void GeoIP_setup_custom_directory (char * dir) {
369	GeoIP_custom_directory = dir;
370}
371
372char *_GeoIP_full_path_to(const char *file_name) {
373	int len;
374	char *path = malloc(sizeof(char) * 1024);
375
376	if (GeoIP_custom_directory == NULL){
377#if !defined(_WIN32)
378		memset(path, 0, sizeof(char) * 1024);
379		snprintf(path, sizeof(char) * 1024 - 1, "%s/%s", GEOIPDATADIR, file_name);
380#else
381		char buf[MAX_PATH], *p, *q = NULL;
382		memset(buf, 0, sizeof(buf));
383		len = GetModuleFileNameA(GetModuleHandle(NULL), buf, sizeof(buf) - 1);
384		for (p = buf + len; p > buf; p--)
385			if (*p == '\\')
386				{
387					if (!q)
388						q = p;
389					else
390						*p = '/';
391				}
392		*q = 0;
393		memset(path, 0, sizeof(char) * 1024);
394		snprintf(path, sizeof(char) * 1024 - 1, "%s/%s", buf, file_name);
395#endif
396	} else {
397		len = strlen(GeoIP_custom_directory);
398		if (GeoIP_custom_directory[len-1] != '/') {
399			snprintf(path, sizeof(char) * 1024 - 1, "%s/%s", GeoIP_custom_directory, file_name);
400		} else {
401			snprintf(path, sizeof(char) * 1024 - 1, "%s%s", GeoIP_custom_directory, file_name);
402		}
403	}
404	return path;
405}
406
407char ** GeoIPDBFileName = NULL;
408
409void _GeoIP_setup_dbfilename() {
410	if (NULL == GeoIPDBFileName) {
411		GeoIPDBFileName = malloc(sizeof(char *) * NUM_DB_TYPES);
412		memset(GeoIPDBFileName, 0, sizeof(char *) * NUM_DB_TYPES);
413
414		GeoIPDBFileName[GEOIP_COUNTRY_EDITION]		= _GeoIP_full_path_to("GeoIP.dat");
415		GeoIPDBFileName[GEOIP_REGION_EDITION_REV0]	= _GeoIP_full_path_to("GeoIPRegion.dat");
416		GeoIPDBFileName[GEOIP_REGION_EDITION_REV1]	= _GeoIP_full_path_to("GeoIPRegion.dat");
417		GeoIPDBFileName[GEOIP_CITY_EDITION_REV0]	= _GeoIP_full_path_to("GeoIPCity.dat");
418		GeoIPDBFileName[GEOIP_CITY_EDITION_REV1]	= _GeoIP_full_path_to("GeoIPCity.dat");
419		GeoIPDBFileName[GEOIP_ISP_EDITION]		= _GeoIP_full_path_to("GeoIPISP.dat");
420		GeoIPDBFileName[GEOIP_ORG_EDITION]		= _GeoIP_full_path_to("GeoIPOrg.dat");
421		GeoIPDBFileName[GEOIP_PROXY_EDITION]		= _GeoIP_full_path_to("GeoIPProxy.dat");
422		GeoIPDBFileName[GEOIP_ASNUM_EDITION]		= _GeoIP_full_path_to("GeoIPASNum.dat");
423		GeoIPDBFileName[GEOIP_NETSPEED_EDITION]		= _GeoIP_full_path_to("GeoIPNetSpeed.dat");
424		GeoIPDBFileName[GEOIP_DOMAIN_EDITION]		= _GeoIP_full_path_to("GeoIPDomain.dat");
425                GeoIPDBFileName[GEOIP_COUNTRY_EDITION_V6]       = _GeoIP_full_path_to("GeoIPv6.dat");
426                GeoIPDBFileName[GEOIP_LOCATIONA_EDITION]        = _GeoIP_full_path_to("GeoIPLocA.dat");
427                GeoIPDBFileName[GEOIP_ACCURACYRADIUS_EDITION]   = _GeoIP_full_path_to("GeoIPDistance.dat");
428                GeoIPDBFileName[GEOIP_LARGE_COUNTRY_EDITION]    = _GeoIP_full_path_to("GeoIP.dat");
429                GeoIPDBFileName[GEOIP_LARGE_COUNTRY_EDITION_V6] = _GeoIP_full_path_to("GeoIPv6.dat");
430		GeoIPDBFileName[GEOIP_ASNUM_EDITION_V6]		= _GeoIP_full_path_to("GeoIPASNumv6.dat");
431		GeoIPDBFileName[GEOIP_ISP_EDITION_V6]		= _GeoIP_full_path_to("GeoIPISPv6.dat");
432		GeoIPDBFileName[GEOIP_ORG_EDITION_V6]		= _GeoIP_full_path_to("GeoIPOrgv6.dat");
433		GeoIPDBFileName[GEOIP_DOMAIN_EDITION_V6]	= _GeoIP_full_path_to("GeoIPDomainv6.dat");
434                GeoIPDBFileName[GEOIP_LOCATIONA_EDITION_V6]     = _GeoIP_full_path_to("GeoIPLocAv6.dat");
435                GeoIPDBFileName[GEOIP_REGISTRAR_EDITION]        = _GeoIP_full_path_to("GeoIPRegistrar.dat");
436                GeoIPDBFileName[GEOIP_REGISTRAR_EDITION_V6]     = _GeoIP_full_path_to("GeoIPRegistrarv6.dat");
437                GeoIPDBFileName[GEOIP_USERTYPE_EDITION]         = _GeoIP_full_path_to("GeoIPUserType.dat");
438                GeoIPDBFileName[GEOIP_USERTYPE_EDITION_V6]      = _GeoIP_full_path_to("GeoIPUserTypev6.dat");
439		GeoIPDBFileName[GEOIP_CITY_EDITION_REV0_V6]	= _GeoIP_full_path_to("GeoIPCityv6.dat");
440		GeoIPDBFileName[GEOIP_CITY_EDITION_REV1_V6]	= _GeoIP_full_path_to("GeoIPCityv6.dat");
441		GeoIPDBFileName[GEOIP_NETSPEED_EDITION_REV1]	= _GeoIP_full_path_to("GeoIPNetSpeedCell.dat");
442		GeoIPDBFileName[GEOIP_NETSPEED_EDITION_REV1_V6]	= _GeoIP_full_path_to("GeoIPNetSpeedCellv6.dat");
443		GeoIPDBFileName[GEOIP_COUNTRYCONF_EDITION]	= _GeoIP_full_path_to("GeoIPCountryConf.dat");
444		GeoIPDBFileName[GEOIP_CITYCONF_EDITION]         = _GeoIP_full_path_to("GeoIPCityConf.dat");
445		GeoIPDBFileName[GEOIP_REGIONCONF_EDITION]	= _GeoIP_full_path_to("GeoIPRegionConf.dat");
446		GeoIPDBFileName[GEOIP_POSTALCONF_EDITION]	= _GeoIP_full_path_to("GeoIPPostalConf.dat");
447                GeoIPDBFileName[GEOIP_ACCURACYRADIUS_EDITION_V6] = _GeoIP_full_path_to("GeoIPDistancev6.dat");
448	  }
449}
450
451static
452int _file_exists(const char *file_name) {
453	struct stat file_stat;
454	return( (stat(file_name, &file_stat) == 0) ? 1:0);
455}
456
457char * _GeoIP_iso_8859_1__utf8(const char * iso) {
458	signed char c;
459	char k;
460	char * p;
461	char * t = (char *)iso;
462	int len = 0;
463	while ( ( c = *t++) ){
464		if ( c < 0 )
465			len++;
466	}
467	len += t - iso;
468	t = p = malloc( len );
469
470	if ( p ){
471		while ( ( c = *iso++ ) ) {
472			if (c < 0 ) {
473				k = 0xc2;
474				if (c >= -64 )
475					k++;
476				*t++ = k;
477				c &= ~0x40;
478			}
479			*t++ = c;
480		}
481		*t++ = 0x00;
482	}
483	return p;
484}
485
486int GeoIP_is_private_ipnum_v4( unsigned long ipnum ){
487return ((ipnum >= 167772160U && ipnum <= 184549375U)
488    || (ipnum >= 2851995648U && ipnum <= 2852061183U)
489    || (ipnum >= 2886729728U && ipnum <= 2887778303U)
490    || (ipnum >= 3232235520U && ipnum <= 3232301055U)
491    || (ipnum >= 2130706432U && ipnum <= 2147483647U))? 1 : 0;
492}
493
494int GeoIP_is_private_v4( const char * addr ){
495  unsigned long ipnum = GeoIP_addr_to_num(addr);
496  return GeoIP_is_private_ipnum_v4(ipnum);
497}
498
499int GeoIP_db_avail(int type) {
500	const char * filePath;
501	if (type < 0 || type >= NUM_DB_TYPES) {
502		return 0;
503	}
504	_GeoIP_setup_dbfilename();
505	filePath = GeoIPDBFileName[type];
506	if (NULL == filePath) {
507		return 0;
508	}
509	return _file_exists(filePath);
510}
511
512static int _database_has_content( int database_type ){
513	return ((database_type != GEOIP_COUNTRY_EDITION
514	        && database_type != GEOIP_PROXY_EDITION
515		&& database_type != GEOIP_NETSPEED_EDITION
516		&& database_type != GEOIP_COUNTRY_EDITION_V6
517		&& database_type != GEOIP_LARGE_COUNTRY_EDITION
518		&& database_type != GEOIP_LARGE_COUNTRY_EDITION_V6
519		&& database_type != GEOIP_REGION_EDITION_REV0
520		&& database_type != GEOIP_REGION_EDITION_REV1) ? 1 : 0 );
521}
522
523static
524void _setup_segments(GeoIP * gi) {
525	int i, j, segment_record_length;
526	unsigned char delim[3];
527	unsigned char buf[LARGE_SEGMENT_RECORD_LENGTH];
528	ssize_t silence _UNUSED;
529        int fno = fileno(gi->GeoIPDatabase);
530
531	gi->databaseSegments = NULL;
532
533	/* default to GeoIP Country Edition */
534	gi->databaseType = GEOIP_COUNTRY_EDITION;
535	gi->record_length = STANDARD_RECORD_LENGTH;
536	lseek(fno, -3l, SEEK_END);
537	for (i = 0; i < STRUCTURE_INFO_MAX_SIZE; i++) {
538		silence = read(fno, delim, 3);
539		if (delim[0] == 255 && delim[1] == 255 && delim[2] == 255) {
540			silence = read(fno, &gi->databaseType, 1 );
541			if (gi->databaseType >= 106) {
542				/* backwards compatibility with databases from April 2003 and earlier */
543				gi->databaseType -= 105;
544			}
545
546			if (gi->databaseType == GEOIP_REGION_EDITION_REV0) {
547				/* Region Edition, pre June 2003 */
548				gi->databaseSegments = malloc(sizeof(int));
549				gi->databaseSegments[0] = STATE_BEGIN_REV0;
550			} else if (gi->databaseType == GEOIP_REGION_EDITION_REV1) {
551				/* Region Edition, post June 2003 */
552				gi->databaseSegments = malloc(sizeof(int));
553				gi->databaseSegments[0] = STATE_BEGIN_REV1;
554                       } else if (gi->databaseType == GEOIP_CITY_EDITION_REV0 ||
555				   gi->databaseType == GEOIP_CITY_EDITION_REV1 ||
556		                   gi->databaseType == GEOIP_ORG_EDITION ||
557		                   gi->databaseType == GEOIP_ORG_EDITION_V6 ||
558		                   gi->databaseType == GEOIP_DOMAIN_EDITION ||
559		                   gi->databaseType == GEOIP_DOMAIN_EDITION_V6 ||
560		 		   gi->databaseType == GEOIP_ISP_EDITION ||
561		 		   gi->databaseType == GEOIP_ISP_EDITION_V6 ||
562			  	   gi->databaseType == GEOIP_REGISTRAR_EDITION ||
563			  	   gi->databaseType == GEOIP_REGISTRAR_EDITION_V6 ||
564			  	   gi->databaseType == GEOIP_USERTYPE_EDITION ||
565			  	   gi->databaseType == GEOIP_USERTYPE_EDITION_V6 ||
566			  	   gi->databaseType == GEOIP_ASNUM_EDITION ||
567			  	   gi->databaseType == GEOIP_ASNUM_EDITION_V6 ||
568			  	   gi->databaseType == GEOIP_NETSPEED_EDITION_REV1 ||
569			  	   gi->databaseType == GEOIP_NETSPEED_EDITION_REV1_V6 ||
570			  	   gi->databaseType == GEOIP_LOCATIONA_EDITION ||
571			  	   gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION ||
572                                   gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION_V6 ||
573                                   gi->databaseType == GEOIP_CITY_EDITION_REV0_V6 ||
574				   gi->databaseType == GEOIP_CITY_EDITION_REV1_V6 ||
575				   gi->databaseType == GEOIP_CITYCONF_EDITION ||
576				   gi->databaseType == GEOIP_COUNTRYCONF_EDITION ||
577				   gi->databaseType == GEOIP_REGIONCONF_EDITION ||
578				   gi->databaseType == GEOIP_POSTALCONF_EDITION
579                                   ) {
580				/* City/Org Editions have two segments, read offset of second segment */
581				gi->databaseSegments = malloc(sizeof(int));
582				gi->databaseSegments[0] = 0;
583
584                                segment_record_length = SEGMENT_RECORD_LENGTH;
585
586				silence = read(fno, buf, segment_record_length );
587				for (j = 0; j < segment_record_length; j++) {
588					gi->databaseSegments[0] += (buf[j] << (j * 8));
589				}
590
591                                /* the record_length must be correct from here on */
592				if (gi->databaseType == GEOIP_ORG_EDITION    ||
593				    gi->databaseType == GEOIP_ORG_EDITION_V6 ||
594		                    gi->databaseType == GEOIP_DOMAIN_EDITION ||
595		                    gi->databaseType == GEOIP_DOMAIN_EDITION_V6 ||
596			 	    gi->databaseType == GEOIP_ISP_EDITION    ||
597				    gi->databaseType == GEOIP_ISP_EDITION_V6 )
598					gi->record_length = ORG_RECORD_LENGTH;
599			}
600			break;
601		} else {
602			lseek(fno, -4l, SEEK_CUR);
603		}
604	}
605	if (gi->databaseType == GEOIP_COUNTRY_EDITION ||
606			gi->databaseType == GEOIP_PROXY_EDITION ||
607			gi->databaseType == GEOIP_NETSPEED_EDITION ||
608			gi->databaseType == GEOIP_COUNTRY_EDITION_V6 ) {
609		gi->databaseSegments = malloc(sizeof(int));
610		gi->databaseSegments[0] = COUNTRY_BEGIN;
611	}
612        else if ( gi->databaseType == GEOIP_LARGE_COUNTRY_EDITION ||
613          gi->databaseType == GEOIP_LARGE_COUNTRY_EDITION_V6 ) {
614		gi->databaseSegments = malloc(sizeof(int));
615		gi->databaseSegments[0] = LARGE_COUNTRY_BEGIN;
616	                        }
617
618}
619
620static
621int _check_mtime(GeoIP *gi) {
622	struct stat buf;
623	unsigned int idx_size;
624
625#if !defined(_WIN32)
626        struct timeval t;
627#else /* !defined(_WIN32) */
628        FILETIME ft;
629        ULONGLONG t;
630#endif /* !defined(_WIN32) */
631
632        if (gi->flags & GEOIP_CHECK_CACHE) {
633
634#if !defined(_WIN32)
635                /* stat only has second granularity, so don't
636	         * call it more than once a second */
637	        gettimeofday(&t, NULL);
638	        if (t.tv_sec == gi->last_mtime_check){
639		        return 0;
640	        }
641	        gi->last_mtime_check = t.tv_sec;
642
643#else /* !defined(_WIN32) */
644
645                /* stat only has second granularity, so don't
646                  call it more than once a second */
647                GetSystemTimeAsFileTime(&ft);
648                t = FILETIME_TO_USEC(ft) / 1000 / 1000;
649                if (t == gi->last_mtime_check){
650                        return 0;
651                }
652                gi->last_mtime_check = t;
653
654#endif /* !defined(_WIN32) */
655
656                if (stat(gi->file_path, &buf) != -1) {
657                        /* make sure that the database file is at least 60
658                         * seconds untouched. Otherwise we might load the
659                         * database only partly and crash
660                         */
661			if (buf.st_mtime != gi->mtime && ( buf.st_mtime + 60 < gi->last_mtime_check  ) ) {
662				/* GeoIP Database file updated */
663				if (gi->flags & (GEOIP_MEMORY_CACHE | GEOIP_MMAP_CACHE)) {
664				   if ( gi->flags & GEOIP_MMAP_CACHE) {
665#if !defined(_WIN32)
666							/* MMAP is only avail on UNIX */
667					munmap(gi->cache, gi->size);
668					gi->cache = NULL;
669#endif
670                                   } else {
671					/* reload database into memory cache */
672					if ((gi->cache = (unsigned char*) realloc(gi->cache, buf.st_size)) == NULL) {
673						fprintf(stderr,"Out of memory when reloading %s\n",gi->file_path);
674						return -1;
675					}
676				    }
677				}
678				/* refresh filehandle */
679				fclose(gi->GeoIPDatabase);
680				gi->GeoIPDatabase = fopen(gi->file_path,"rb");
681				if (gi->GeoIPDatabase == NULL) {
682					fprintf(stderr,"Error Opening file %s when reloading\n",gi->file_path);
683					return -1;
684				}
685				gi->mtime = buf.st_mtime;
686				gi->size = buf.st_size;
687
688				if ( gi->flags & GEOIP_MMAP_CACHE) {
689#if defined(_WIN32)
690					fprintf(stderr, "GEOIP_MMAP_CACHE is not supported on WIN32\n");
691					gi->cache = 0;
692					return -1;
693#else
694				    gi->cache = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fileno(gi->GeoIPDatabase), 0);
695				    if ( gi->cache == MAP_FAILED ) {
696
697					    fprintf(stderr,"Error remapping file %s when reloading\n",gi->file_path);
698
699					    gi->cache = NULL;
700					    return -1;
701				    }
702#endif
703				} else if ( gi->flags & GEOIP_MEMORY_CACHE ) {
704				    if (pread(fileno(gi->GeoIPDatabase), gi->cache,  buf.st_size, 0) != (ssize_t) buf.st_size) {
705					    fprintf(stderr,"Error reading file %s when reloading\n",gi->file_path);
706					    return -1;
707					}
708				}
709
710				if (gi->databaseSegments != NULL) {
711					free(gi->databaseSegments);
712					gi->databaseSegments = NULL;
713				}
714				_setup_segments(gi);
715				if (gi->databaseSegments == NULL) {
716					fprintf(stderr, "Error reading file %s -- corrupt\n", gi->file_path);
717					return -1;
718				}
719
720				/* make sure the index is <= file size
721				 * This test makes sense for all modes - not
722				 * only index
723				 */
724				idx_size = _database_has_content(gi->databaseType) ? gi->databaseSegments[0] * (long)gi->record_length * 2 :  buf.st_size;
725				if ( idx_size >  buf.st_size ){
726					fprintf(stderr, "Error file %s -- corrupt\n", gi->file_path);
727					return -1;
728				}
729
730				if (gi->flags & GEOIP_INDEX_CACHE) {
731					gi->index_cache = (unsigned char *) realloc(gi->index_cache, sizeof(unsigned char) * idx_size );
732					if (gi->index_cache != NULL) {
733						if (pread(fileno(gi->GeoIPDatabase), gi->index_cache,
734                                                  idx_size, 0 ) != (ssize_t) idx_size) {
735							fprintf(stderr,"Error reading file %s where reloading\n",gi->file_path);
736							return -1;
737						}
738					}
739				}
740			}
741		}
742	}
743	return 0;
744}
745
746#define ADDR_STR_LEN (8 * 4 + 7 + 1)
747unsigned int _GeoIP_seek_record_v6_gl (GeoIP *gi, geoipv6_t ipnum, GeoIPLookup * gl) {
748       int depth;
749       char paddr[ADDR_STR_LEN];
750       unsigned int x;
751       unsigned char stack_buffer[2 * MAX_RECORD_LENGTH];
752       const unsigned char *buf = (gi->cache == NULL) ? stack_buffer : NULL;
753       unsigned int offset = 0;
754
755       const unsigned char * p;
756       int j;
757       ssize_t silence _UNUSED;
758       int fno = fileno(gi->GeoIPDatabase);
759       _check_mtime(gi);
760       if ( GeoIP_teredo(gi) )
761         __GEOIP_PREPARE_TEREDO(&ipnum);
762       for (depth = 127; depth >= 0; depth--) {
763               if (gi->cache == NULL && gi->index_cache == NULL) {
764                       /* read from disk */
765                       silence = pread(fno, stack_buffer,gi->record_length * 2, (long)gi->record_length * 2 * offset );
766               } else if (gi->index_cache == NULL) {
767                       /* simply point to record in memory */
768                       buf = gi->cache + (long)gi->record_length * 2 *offset;
769               } else {
770                       buf = gi->index_cache + (long)gi->record_length * 2 * offset;
771               }
772
773               if (GEOIP_CHKBIT_V6(depth, ipnum.s6_addr )) {
774                       /* Take the right-hand branch */
775                       if ( gi->record_length == 3 ) {
776                               /* Most common case is completely unrolled and uses constants. */
777                               x =   (buf[3*1 + 0] << (0*8))
778                                       + (buf[3*1 + 1] << (1*8))
779                                       + (buf[3*1 + 2] << (2*8));
780
781                       } else {
782                               /* General case */
783                               j = gi->record_length;
784                               p = &buf[2*j];
785                               x = 0;
786                               do {
787                                       x <<= 8;
788                                       x += *(--p);
789                               } while ( --j );
790                       }
791
792               } else {
793                       /* Take the left-hand branch */
794                       if ( gi->record_length == 3 ) {
795                               /* Most common case is completely unrolled and uses constants. */
796                               x =   (buf[3*0 + 0] << (0*8))
797                                       + (buf[3*0 + 1] << (1*8))
798                                       + (buf[3*0 + 2] << (2*8));
799                       } else {
800                               /* General case */
801                               j = gi->record_length;
802                               p = &buf[1*j];
803                               x = 0;
804                               do {
805                                       x <<= 8;
806                                       x += *(--p);
807                               } while ( --j );
808                       }
809               }
810
811               if (x >= gi->databaseSegments[0]) {
812                       gi->netmask = gl->netmask = 128 - depth;
813                       return x;
814               }
815               offset = x;
816       }
817
818       /* shouldn't reach here */
819        _GeoIP_inet_ntop(AF_INET6, &ipnum.s6_addr[0], paddr, ADDR_STR_LEN);
820       fprintf(stderr,"Error Traversing Database for ipnum = %s - Perhaps database is corrupt?\n", paddr);
821       return 0;
822}
823
824geoipv6_t
825_GeoIP_addr_to_num_v6(const char *addr)
826{
827       geoipv6_t       ipnum;
828        if ( 1 == _GeoIP_inet_pton(AF_INET6, addr, &ipnum.s6_addr[0] ) )
829          return ipnum;
830       return IPV6_NULL;
831}
832
833
834unsigned int _GeoIP_seek_record_gl (GeoIP *gi, unsigned long ipnum, GeoIPLookup *gl) {
835	int depth;
836	unsigned int x;
837	unsigned char stack_buffer[2 * MAX_RECORD_LENGTH];
838	const unsigned char *buf = (gi->cache == NULL) ? stack_buffer : NULL;
839	unsigned int offset = 0;
840	ssize_t silence _UNUSED;
841
842	const unsigned char * p;
843	int j;
844        int fno = fileno(gi->GeoIPDatabase);
845	_check_mtime(gi);
846	for (depth = 31; depth >= 0; depth--) {
847		if (gi->cache == NULL && gi->index_cache == NULL) {
848			/* read from disk */
849                       silence = pread(fno, stack_buffer, gi->record_length * 2, gi->record_length * 2 * offset);
850		} else if (gi->index_cache == NULL) {
851			/* simply point to record in memory */
852			buf = gi->cache + (long)gi->record_length * 2 *offset;
853		} else {
854			buf = gi->index_cache + (long)gi->record_length * 2 * offset;
855		}
856
857		if (ipnum & (1 << depth)) {
858			/* Take the right-hand branch */
859			if ( gi->record_length == 3 ) {
860				/* Most common case is completely unrolled and uses constants. */
861				x =   (buf[3*1 + 0] << (0*8))
862					+ (buf[3*1 + 1] << (1*8))
863					+ (buf[3*1 + 2] << (2*8));
864
865			} else {
866				/* General case */
867				j = gi->record_length;
868				p = &buf[2*j];
869				x = 0;
870				do {
871					x <<= 8;
872					x += *(--p);
873				} while ( --j );
874			}
875
876		} else {
877			/* Take the left-hand branch */
878			if ( gi->record_length == 3 ) {
879				/* Most common case is completely unrolled and uses constants. */
880				x =   (buf[3*0 + 0] << (0*8))
881					+ (buf[3*0 + 1] << (1*8))
882					+ (buf[3*0 + 2] << (2*8));
883			} else {
884				/* General case */
885				j = gi->record_length;
886				p = &buf[1*j];
887				x = 0;
888				do {
889					x <<= 8;
890					x += *(--p);
891				} while ( --j );
892			}
893		}
894
895		if (x >= gi->databaseSegments[0]) {
896			gi->netmask = gl->netmask = 32 - depth;
897			return x;
898		}
899		offset = x;
900	}
901	/* shouldn't reach here */
902	fprintf(stderr,"Error Traversing Database for ipnum = %lu - Perhaps database is corrupt?\n",ipnum);
903	return 0;
904}
905
906unsigned long
907GeoIP_addr_to_num(const char *addr)
908{
909	unsigned int    c, octet, t;
910	unsigned long   ipnum;
911	int             i = 3;
912
913	octet = ipnum = 0;
914	while ((c = *addr++)) {
915		if (c == '.') {
916			if (octet > 255)
917				return 0;
918			ipnum <<= 8;
919			ipnum += octet;
920			i--;
921			octet = 0;
922		} else {
923			t = octet;
924			octet <<= 3;
925			octet += t;
926			octet += t;
927			c -= '0';
928			if (c > 9)
929				return 0;
930			octet += c;
931		}
932	}
933	if ((octet > 255) || (i != 0))
934		return 0;
935	ipnum <<= 8;
936	return ipnum + octet;
937}
938
939GeoIP* GeoIP_open_type (int type, int flags) {
940	GeoIP * gi;
941	const char * filePath;
942	if (type < 0 || type >= NUM_DB_TYPES) {
943		printf("Invalid database type %d\n", type);
944		return NULL;
945	}
946	_GeoIP_setup_dbfilename();
947	filePath = GeoIPDBFileName[type];
948	if (filePath == NULL) {
949		printf("Invalid database type %d\n", type);
950		return NULL;
951	}
952	gi = GeoIP_open (filePath, flags);
953
954        if ( gi ){
955	        /* make sure this is the requested database type */
956		int database_type = gi->databaseType ;
957		if ( database_type > 105 )
958		        database_type -= 105;
959		/*  type must match, but we accept org and asnum,
960		 *  since domain and *conf database have always the wrong type
961		 *  for historical reason. Maybe we fix it at some point.
962		 */
963	        if (    database_type == type
964		     || database_type == GEOIP_ASNUM_EDITION
965		     || database_type == GEOIP_ORG_EDITION )
966	                return gi;
967	        GeoIP_delete(gi);
968	}
969
970	return NULL;
971}
972
973GeoIP* GeoIP_new (int flags) {
974	GeoIP * gi;
975	_GeoIP_setup_dbfilename();
976	gi = GeoIP_open (GeoIPDBFileName[GEOIP_COUNTRY_EDITION], flags);
977	return gi;
978}
979
980GeoIP* GeoIP_open (const char * filename, int flags) {
981	struct stat buf;
982	unsigned int idx_size;
983	GeoIP * gi;
984	size_t len;
985
986	gi = (GeoIP *)malloc(sizeof(GeoIP));
987	if (gi == NULL)
988		return NULL;
989       	len = sizeof(char) * (strlen(filename)+1);
990	gi->file_path = malloc(len);
991	if (gi->file_path == NULL) {
992		free(gi);
993		return NULL;
994	}
995	strncpy(gi->file_path, filename, len);
996	gi->GeoIPDatabase = fopen(filename,"rb");
997	if (gi->GeoIPDatabase == NULL) {
998		fprintf(stderr,"Error Opening file %s\n",filename);
999		free(gi->file_path);
1000		free(gi);
1001		return NULL;
1002	} else {
1003		if (fstat(fileno(gi->GeoIPDatabase), &buf) == -1) {
1004			fprintf(stderr,"Error stating file %s\n",filename);
1005			free(gi->file_path);
1006			free(gi);
1007			return NULL;
1008		}
1009		if (flags & (GEOIP_MEMORY_CACHE | GEOIP_MMAP_CACHE) ) {
1010			gi->mtime = buf.st_mtime;
1011			gi->size = buf.st_size;
1012
1013			/* MMAP added my Peter Shipley */
1014			if ( flags & GEOIP_MMAP_CACHE ) {
1015#if !defined(_WIN32)
1016			    gi->cache = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fileno(gi->GeoIPDatabase), 0);
1017			    if ( gi->cache == MAP_FAILED ) {
1018				fprintf(stderr,"Error mmaping file %s\n",filename);
1019				free(gi->file_path);
1020				free(gi);
1021				return NULL;
1022			    }
1023#endif
1024			} else {
1025			    gi->cache = (unsigned char *) malloc(sizeof(unsigned char) * buf.st_size);
1026
1027			    if (gi->cache != NULL) {
1028				if (pread(fileno(gi->GeoIPDatabase),gi->cache, buf.st_size, 0) != (ssize_t) buf.st_size) {
1029					fprintf(stderr,"Error reading file %s\n",filename);
1030					free(gi->cache);
1031					free(gi->file_path);
1032					free(gi);
1033					return NULL;
1034				}
1035			    }
1036			}
1037		} else {
1038			if (flags & GEOIP_CHECK_CACHE) {
1039				if (fstat(fileno(gi->GeoIPDatabase), &buf) == -1) {
1040					fprintf(stderr,"Error stating file %s\n",filename);
1041					free(gi->file_path);
1042					free(gi);
1043					return NULL;
1044				}
1045				gi->mtime = buf.st_mtime;
1046			}
1047			gi->cache = NULL;
1048		}
1049		gi->flags = flags;
1050		gi->charset = GEOIP_CHARSET_ISO_8859_1;
1051                gi->ext_flags = 1U << GEOIP_TEREDO_BIT;
1052		_setup_segments(gi);
1053
1054		idx_size = _database_has_content(gi->databaseType) ? gi->databaseSegments[0] * (long)gi->record_length * 2 :  buf.st_size;
1055
1056                /* make sure the index is <= file size */
1057	        if ( idx_size >  buf.st_size ){
1058		        fprintf(stderr, "Error file %s -- corrupt\n", gi->file_path);
1059			if (flags & GEOIP_MEMORY_CACHE) {
1060				free(gi->cache);
1061			}
1062#if !defined(_WIN32)
1063			else if ( flags & GEOIP_MMAP_CACHE) {
1064			        /* MMAP is only avail on UNIX */
1065				munmap(gi->cache, gi->size);
1066				gi->cache = NULL;
1067			}
1068#endif
1069			free(gi->file_path);
1070                        free(gi);
1071                        return NULL;
1072	        }
1073
1074		if (flags & GEOIP_INDEX_CACHE) {
1075			gi->index_cache = (unsigned char *) malloc(sizeof(unsigned char) * idx_size);
1076			if (gi->index_cache != NULL) {
1077				if (pread(fileno(gi->GeoIPDatabase),gi->index_cache, idx_size, 0) != idx_size ) {
1078					fprintf(stderr,"Error reading file %s\n",filename);
1079					free(gi->databaseSegments);
1080					free(gi->index_cache);
1081					free(gi);
1082					return NULL;
1083				}
1084			}
1085		} else {
1086			gi->index_cache = NULL;
1087		}
1088		return gi;
1089	}
1090}
1091
1092void GeoIP_delete (GeoIP *gi) {
1093	if (gi == NULL )
1094		return;
1095	if (gi->GeoIPDatabase != NULL)
1096		fclose(gi->GeoIPDatabase);
1097	if (gi->cache != NULL) {
1098	    if ( gi->flags & GEOIP_MMAP_CACHE ) {
1099#if !defined(_WIN32)
1100		munmap(gi->cache, gi->size);
1101#endif
1102	    } else {
1103		free(gi->cache);
1104	    }
1105	    gi->cache = NULL;
1106	}
1107	if (gi->index_cache != NULL)
1108		free(gi->index_cache);
1109	if (gi->file_path != NULL)
1110		free(gi->file_path);
1111	if (gi->databaseSegments != NULL)
1112		free(gi->databaseSegments);
1113	free(gi);
1114}
1115
1116const char *GeoIP_country_code_by_name_v6_gl (GeoIP* gi, const char *name, GeoIPLookup * gl) {
1117	int country_id;
1118	country_id = GeoIP_id_by_name_v6_gl(gi, name, gl);
1119	return (country_id > 0) ? GeoIP_country_code[country_id] : NULL;
1120}
1121
1122const char *GeoIP_country_code_by_name_gl (GeoIP* gi, const char *name, GeoIPLookup * gl) {
1123	int country_id;
1124	country_id = GeoIP_id_by_name_gl(gi, name, gl);
1125	return (country_id > 0) ? GeoIP_country_code[country_id] : NULL;
1126}
1127
1128const char *GeoIP_country_code3_by_name_v6_gl (GeoIP* gi, const char *name, GeoIPLookup * gl) {
1129	int country_id;
1130	country_id = GeoIP_id_by_name_v6_gl(gi, name, gl);
1131	return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL;
1132}
1133
1134const char *GeoIP_country_code3_by_name_gl (GeoIP* gi, const char *name, GeoIPLookup * gl) {
1135	int country_id;
1136	country_id = GeoIP_id_by_name_gl(gi, name, gl);
1137	return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL;
1138}
1139
1140const char *GeoIP_country_name_by_name_v6_gl (GeoIP* gi, const char *name, GeoIPLookup * gl) {
1141	int country_id;
1142	country_id = GeoIP_id_by_name_v6_gl(gi, name, gl);
1143        return GeoIP_country_name_by_id(gi, country_id );
1144}
1145
1146const char *GeoIP_country_name_by_name_gl (GeoIP* gi, const char *name, GeoIPLookup * gl) {
1147	int country_id;
1148	country_id = GeoIP_id_by_name_gl(gi, name, gl);
1149        return GeoIP_country_name_by_id(gi, country_id );
1150}
1151
1152unsigned long _GeoIP_lookupaddress (const char *host) {
1153	unsigned long addr = inet_addr(host);
1154	struct hostent phe2;
1155	struct hostent * phe = &phe2;
1156	char *buf = NULL;
1157#ifdef HAVE_GETHOSTBYNAME_R
1158	int buflength = 16384;
1159	int herr = 0;
1160#endif
1161	int result = 0;
1162#ifdef HAVE_GETHOSTBYNAME_R
1163	buf = malloc(buflength);
1164#endif
1165	if (addr == INADDR_NONE) {
1166#ifdef HAVE_GETHOSTBYNAME_R
1167		while (1) {
1168			/* we use gethostbyname_r here because it is thread-safe and gethostbyname is not */
1169#ifdef GETHOSTBYNAME_R_RETURNS_INT
1170			result = gethostbyname_r(host,&phe2,buf,buflength,&phe,&herr);
1171#else
1172			phe = gethostbyname_r(host,&phe2,buf,buflength,&herr);
1173#endif
1174			if (herr != ERANGE)
1175				break;
1176			if (result == 0)
1177				break;
1178			/* double the buffer if the buffer is too small */
1179			buflength = buflength * 2;
1180			buf = realloc(buf,buflength);
1181		}
1182#else
1183		/* Some systems do not support gethostbyname_r, such as Mac OS X */
1184		phe = gethostbyname(host);
1185#endif
1186		if (!phe || result != 0) {
1187			free(buf);
1188			return 0;
1189		}
1190#if !defined(_WIN32)
1191		addr = *((in_addr_t *) phe->h_addr_list[0]);
1192#else
1193                addr = ((IN_ADDR *) phe->h_addr_list[0])->S_un.S_addr;
1194#endif
1195	}
1196#ifdef HAVE_GETHOSTBYNAME_R
1197	free(buf);
1198#endif
1199	return ntohl(addr);
1200}
1201
1202geoipv6_t
1203_GeoIP_lookupaddress_v6(const char *host)
1204{
1205  geoipv6_t       ipnum;
1206  int             gaierr;
1207  struct addrinfo hints, *aifirst;
1208
1209  memset(&hints, 0, sizeof(hints));
1210  hints.ai_family = AF_INET6;
1211  /* hints.ai_flags = AI_V4MAPPED; */
1212  hints.ai_socktype = SOCK_STREAM;
1213
1214  if ((gaierr = getaddrinfo(host, NULL, &hints, &aifirst)) != 0) {
1215          /* fprintf(stderr, "Err: %s (%d %s)\n", host, gaierr, gai_strerror(gaierr)); */
1216    return IPV6_NULL;
1217  }
1218  memcpy(ipnum.s6_addr, ((struct sockaddr_in6 *) aifirst->ai_addr)->sin6_addr.s6_addr, sizeof(geoipv6_t));
1219  freeaddrinfo(aifirst);
1220  /* inet_pton(AF_INET6, host, ipnum.s6_addr); */
1221
1222  return ipnum;
1223}
1224
1225int GeoIP_id_by_name_gl (GeoIP* gi, const char *name, GeoIPLookup *gl ) {
1226	unsigned long ipnum;
1227	int ret;
1228	if (name == NULL) {
1229		return 0;
1230	}
1231	if (gi->databaseType != GEOIP_LARGE_COUNTRY_EDITION && gi->databaseType != GEOIP_COUNTRY_EDITION && gi->databaseType != GEOIP_PROXY_EDITION && gi->databaseType != GEOIP_NETSPEED_EDITION) {
1232		printf("Invalid database type %s, expected %s\n", get_db_description(gi->databaseType), get_db_description(GEOIP_COUNTRY_EDITION));
1233		return 0;
1234	}
1235	if (!(ipnum = _GeoIP_lookupaddress(name)))
1236		return 0;
1237	ret = _GeoIP_seek_record_gl(gi, ipnum, gl) - gi->databaseSegments[0];
1238	return ret;
1239}
1240
1241int GeoIP_id_by_name_v6_gl (GeoIP* gi, const char *name, GeoIPLookup * gl) {
1242       geoipv6_t ipnum;
1243       int ret;
1244       if (name == NULL) {
1245               return 0;
1246       }
1247       if (gi->databaseType != GEOIP_LARGE_COUNTRY_EDITION_V6 && gi->databaseType != GEOIP_COUNTRY_EDITION_V6) {
1248               printf("Invalid database type %s, expected %s\n", get_db_description(gi->databaseType), get_db_description(GEOIP_COUNTRY_EDITION_V6));
1249               return 0;
1250       }
1251        ipnum = _GeoIP_lookupaddress_v6(name);
1252       if (__GEOIP_V6_IS_NULL(ipnum))
1253               return 0;
1254
1255       ret = _GeoIP_seek_record_v6_gl(gi, ipnum, gl) - gi->databaseSegments[0];
1256       return ret;
1257}
1258
1259const char *GeoIP_country_code_by_addr_v6_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) {
1260	int country_id;
1261	country_id = GeoIP_id_by_addr_v6_gl(gi, addr, gl);
1262	return (country_id > 0) ? GeoIP_country_code[country_id] : NULL;
1263}
1264
1265
1266const char *GeoIP_country_code_by_addr_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) {
1267	int country_id;
1268	country_id = GeoIP_id_by_addr_gl(gi, addr, gl);
1269	return (country_id > 0) ? GeoIP_country_code[country_id] : NULL;
1270}
1271const char *GeoIP_country_code3_by_addr_v6_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) {
1272	int country_id;
1273	country_id = GeoIP_id_by_addr_v6_gl(gi, addr, gl);
1274	return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL;
1275}
1276
1277const char *GeoIP_country_code3_by_addr_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) {
1278	int country_id;
1279	country_id = GeoIP_id_by_addr_gl(gi, addr, gl);
1280	return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL;
1281}
1282
1283const char *GeoIP_country_name_by_addr_v6_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl ) {
1284	int country_id;
1285	country_id = GeoIP_id_by_addr_v6_gl(gi, addr, gl);
1286        return GeoIP_country_name_by_id(gi, country_id );
1287}
1288
1289const char *GeoIP_country_name_by_addr_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl ) {
1290	int country_id;
1291	country_id = GeoIP_id_by_addr_gl(gi, addr, gl);
1292        return GeoIP_country_name_by_id(gi, country_id );
1293}
1294
1295const char *GeoIP_country_name_by_ipnum_gl (GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl) {
1296	int country_id;
1297	country_id = GeoIP_id_by_ipnum_gl(gi, ipnum, gl);
1298        return GeoIP_country_name_by_id(gi, country_id );
1299}
1300
1301const char *GeoIP_country_name_by_ipnum_v6_gl (GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl) {
1302       int country_id;
1303       country_id = GeoIP_id_by_ipnum_v6_gl(gi, ipnum, gl);
1304       return GeoIP_country_name_by_id(gi, country_id );
1305}
1306
1307const char *GeoIP_country_code_by_ipnum_gl (GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl) {
1308	int country_id;
1309	country_id = GeoIP_id_by_ipnum_gl(gi, ipnum, gl);
1310	return (country_id > 0) ? GeoIP_country_code[country_id] : NULL;
1311}
1312
1313const char *GeoIP_country_code_by_ipnum_v6_gl (GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl) {
1314       int country_id;
1315       country_id = GeoIP_id_by_ipnum_v6_gl(gi, ipnum, gl);
1316       return (country_id > 0) ? GeoIP_country_code[country_id] : NULL;
1317}
1318
1319const char *GeoIP_country_code3_by_ipnum_gl (GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl) {
1320	int country_id;
1321	country_id = GeoIP_id_by_ipnum_gl(gi, ipnum, gl);
1322	return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL;
1323}
1324
1325const char *GeoIP_country_code3_by_ipnum_v6_gl (GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl) {
1326       int country_id;
1327       country_id = GeoIP_id_by_ipnum_v6_gl(gi, ipnum, gl);
1328       return (country_id > 0) ? GeoIP_country_code3[country_id] : NULL;
1329}
1330
1331int GeoIP_country_id_by_addr_v6_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) {
1332        GeoIPLookup n;
1333	return GeoIP_id_by_addr_v6_gl(gi, addr, &n);
1334}
1335
1336int GeoIP_country_id_by_addr_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) {
1337	return GeoIP_id_by_addr_gl(gi, addr, gl);
1338}
1339
1340int GeoIP_country_id_by_name_v6_gl (GeoIP* gi, const char *host, GeoIPLookup * gl) {
1341	return GeoIP_id_by_name_v6_gl(gi, host, gl);
1342}
1343
1344int GeoIP_country_id_by_name_gl (GeoIP* gi, const char *host, GeoIPLookup * gl) {
1345	return GeoIP_id_by_name_gl(gi, host, gl);
1346}
1347
1348int GeoIP_id_by_addr_v6_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) {
1349       geoipv6_t ipnum;
1350       int ret;
1351       if (addr == NULL) {
1352               return 0;
1353       }
1354       if  (gi->databaseType != GEOIP_COUNTRY_EDITION_V6
1355         && gi->databaseType != GEOIP_LARGE_COUNTRY_EDITION_V6) {
1356               printf("Invalid database type %s, expected %s\n",
1357                                        get_db_description(gi->databaseType),
1358                                        get_db_description(GEOIP_COUNTRY_EDITION_V6));
1359               return 0;
1360       }
1361       ipnum = _GeoIP_addr_to_num_v6(addr);
1362       ret = _GeoIP_seek_record_v6_gl(gi, ipnum, gl) - gi->databaseSegments[0];
1363       return ret;
1364}
1365
1366
1367int GeoIP_id_by_addr_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) {
1368	unsigned long ipnum;
1369	int ret;
1370	if (addr == NULL) {
1371		return 0;
1372	}
1373	if (gi->databaseType != GEOIP_COUNTRY_EDITION &&
1374            gi->databaseType != GEOIP_LARGE_COUNTRY_EDITION &&
1375			gi->databaseType != GEOIP_PROXY_EDITION &&
1376			gi->databaseType != GEOIP_NETSPEED_EDITION) {
1377		printf("Invalid database type %s, expected %s\n",
1378					 get_db_description(gi->databaseType),
1379					 get_db_description(GEOIP_COUNTRY_EDITION));
1380		return 0;
1381	}
1382	ipnum = GeoIP_addr_to_num(addr);
1383	ret = _GeoIP_seek_record_gl(gi, ipnum, gl) -  gi->databaseSegments[0];
1384	return ret;
1385}
1386
1387int GeoIP_id_by_ipnum_v6_gl (GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl) {
1388       int ret;
1389       if (gi->databaseType != GEOIP_COUNTRY_EDITION_V6
1390         && gi->databaseType != GEOIP_LARGE_COUNTRY_EDITION_V6) {
1391               printf("Invalid database type %s, expected %s\n",
1392                                        get_db_description(gi->databaseType),
1393                                        get_db_description(GEOIP_COUNTRY_EDITION_V6));
1394               return 0;
1395       }
1396       ret = _GeoIP_seek_record_v6_gl(gi, ipnum, gl) - gi->databaseSegments[0];
1397       return ret;
1398}
1399
1400int GeoIP_id_by_ipnum_gl (GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl) {
1401	int ret;
1402	if (ipnum == 0) {
1403		return 0;
1404	}
1405	if (gi->databaseType != GEOIP_COUNTRY_EDITION &&
1406          gi->databaseType != GEOIP_LARGE_COUNTRY_EDITION &&
1407			gi->databaseType != GEOIP_PROXY_EDITION &&
1408			gi->databaseType != GEOIP_NETSPEED_EDITION) {
1409		printf("Invalid database type %s, expected %s\n",
1410					 get_db_description(gi->databaseType),
1411					 get_db_description(GEOIP_COUNTRY_EDITION));
1412		return 0;
1413	}
1414	ret = _GeoIP_seek_record_gl(gi, ipnum, gl) - gi->databaseSegments[0];
1415	return ret;
1416}
1417
1418char *GeoIP_database_info (GeoIP* gi) {
1419	int i;
1420	unsigned char buf[3];
1421	char *retval;
1422	int hasStructureInfo = 0;
1423	ssize_t silence _UNUSED;
1424        int fno;
1425
1426	if(gi == NULL)
1427		return NULL;
1428
1429        fno = fileno(gi->GeoIPDatabase);
1430
1431	_check_mtime(gi);
1432	lseek(fno, -3l, SEEK_END);
1433
1434	/* first get past the database structure information */
1435	for (i = 0; i < STRUCTURE_INFO_MAX_SIZE; i++) {
1436		silence = read(fno, buf, 3 );
1437		if (buf[0] == 255 && buf[1] == 255 && buf[2] == 255) {
1438			hasStructureInfo = 1;
1439			break;
1440		}
1441		lseek(fno, -4l, SEEK_CUR);
1442	}
1443	if (hasStructureInfo == 1) {
1444		lseek(fno, -6l, SEEK_CUR);
1445	} else {
1446		/* no structure info, must be pre Sep 2002 database, go back to end */
1447		lseek(fno, -3l, SEEK_END);
1448	}
1449
1450	for (i = 0; i < DATABASE_INFO_MAX_SIZE; i++) {
1451		silence = read(fno, buf, 3 );
1452		if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0) {
1453			retval = malloc(sizeof(char) * (i+1));
1454			if (retval == NULL) {
1455				return NULL;
1456			}
1457			silence = read(fno, retval, i);
1458			retval[i] = '\0';
1459			return retval;
1460		}
1461		lseek(fno, -4l, SEEK_CUR);
1462	}
1463	return NULL;
1464}
1465
1466/* GeoIP Region Edition functions */
1467
1468void GeoIP_assign_region_by_inetaddr_gl(GeoIP* gi, unsigned long inetaddr, GeoIPRegion *region, GeoIPLookup * gl) {
1469	unsigned int seek_region;
1470
1471	/* This also writes in the terminating NULs (if you decide to
1472	 * keep them) and clear any fields that are not set. */
1473	memset(region, 0, sizeof(GeoIPRegion));
1474
1475	seek_region = _GeoIP_seek_record_gl(gi, ntohl(inetaddr), gl);
1476
1477	if (gi->databaseType == GEOIP_REGION_EDITION_REV0) {
1478		/* Region Edition, pre June 2003 */
1479		seek_region -= STATE_BEGIN_REV0;
1480		if (seek_region >= 1000) {
1481			region->country_code[0] = 'U';
1482			region->country_code[1] = 'S';
1483			region->region[0] = (char) ((seek_region - 1000)/26 + 65);
1484			region->region[1] = (char) ((seek_region - 1000)%26 + 65);
1485		} else {
1486			memcpy(region->country_code, GeoIP_country_code[seek_region], 2);
1487		}
1488	} else if (gi->databaseType == GEOIP_REGION_EDITION_REV1) {
1489		/* Region Edition, post June 2003 */
1490		seek_region -= STATE_BEGIN_REV1;
1491		if (seek_region < US_OFFSET) {
1492			/* Unknown */
1493			/* we don't need to do anything here b/c we memset region to 0 */
1494		} else if (seek_region < CANADA_OFFSET) {
1495			/* USA State */
1496			region->country_code[0] = 'U';
1497			region->country_code[1] = 'S';
1498			region->region[0] = (char) ((seek_region - US_OFFSET)/26 + 65);
1499			region->region[1] = (char) ((seek_region - US_OFFSET)%26 + 65);
1500		} else if (seek_region < WORLD_OFFSET) {
1501			/* Canada Province */
1502			region->country_code[0] = 'C';
1503			region->country_code[1] = 'A';
1504			region->region[0] = (char) ((seek_region - CANADA_OFFSET)/26 + 65);
1505			region->region[1] = (char) ((seek_region - CANADA_OFFSET)%26 + 65);
1506		} else {
1507			/* Not US or Canada */
1508			memcpy(region->country_code, GeoIP_country_code[(seek_region - WORLD_OFFSET) / FIPS_RANGE], 2);
1509		}
1510	}
1511}
1512
1513void GeoIP_assign_region_by_inetaddr_v6_gl(GeoIP* gi, geoipv6_t inetaddr, GeoIPRegion *region, GeoIPLookup * gl) {
1514       unsigned int seek_region;
1515
1516       /* This also writes in the terminating NULs (if you decide to
1517        * keep them) and clear any fields that are not set. */
1518       memset(region, 0, sizeof(GeoIPRegion));
1519
1520       seek_region = _GeoIP_seek_record_v6_gl(gi, inetaddr, gl);
1521
1522       if (gi->databaseType == GEOIP_REGION_EDITION_REV0) {
1523               /* Region Edition, pre June 2003 */
1524               seek_region -= STATE_BEGIN_REV0;
1525               if (seek_region >= 1000) {
1526                       region->country_code[0] = 'U';
1527                       region->country_code[1] = 'S';
1528                       region->region[0] = (char) ((seek_region - 1000)/26 + 65);
1529                       region->region[1] = (char) ((seek_region - 1000)%26 + 65);
1530               } else {
1531                       memcpy(region->country_code, GeoIP_country_code[seek_region], 2);
1532               }
1533       } else if (gi->databaseType == GEOIP_REGION_EDITION_REV1) {
1534               /* Region Edition, post June 2003 */
1535               seek_region -= STATE_BEGIN_REV1;
1536               if (seek_region < US_OFFSET) {
1537                       /* Unknown */
1538                       /* we don't need to do anything here b/c we memset region to 0 */
1539               } else if (seek_region < CANADA_OFFSET) {
1540                       /* USA State */
1541                       region->country_code[0] = 'U';
1542                       region->country_code[1] = 'S';
1543                       region->region[0] = (char) ((seek_region - US_OFFSET)/26 + 65);
1544                       region->region[1] = (char) ((seek_region - US_OFFSET)%26 + 65);
1545               } else if (seek_region < WORLD_OFFSET) {
1546                       /* Canada Province */
1547                       region->country_code[0] = 'C';
1548                       region->country_code[1] = 'A';
1549                       region->region[0] = (char) ((seek_region - CANADA_OFFSET)/26 + 65);
1550                       region->region[1] = (char) ((seek_region - CANADA_OFFSET)%26 + 65);
1551               } else {
1552                       /* Not US or Canada */
1553                       memcpy(region->country_code, GeoIP_country_code[(seek_region - WORLD_OFFSET) / FIPS_RANGE], 2);
1554               }
1555       }
1556}
1557
1558static
1559GeoIPRegion * _get_region_gl(GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl) {
1560	GeoIPRegion * region;
1561
1562	region = malloc(sizeof(GeoIPRegion));
1563	if (region) {
1564		GeoIP_assign_region_by_inetaddr_gl(gi, htonl(ipnum), region, gl);
1565	}
1566	return region;
1567}
1568
1569static
1570GeoIPRegion * _get_region_v6_gl(GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl) {
1571       GeoIPRegion * region;
1572
1573       region = malloc(sizeof(GeoIPRegion));
1574       if (region) {
1575               GeoIP_assign_region_by_inetaddr_v6_gl(gi, ipnum, region, gl);
1576       }
1577       return region;
1578}
1579
1580GeoIPRegion * GeoIP_region_by_addr_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) {
1581	unsigned long ipnum;
1582	if (addr == NULL) {
1583		return NULL;
1584	}
1585	if (gi->databaseType != GEOIP_REGION_EDITION_REV0 &&
1586			gi->databaseType != GEOIP_REGION_EDITION_REV1) {
1587		printf("Invalid database type %s, expected %s\n", get_db_description(gi->databaseType), get_db_description(GEOIP_REGION_EDITION_REV1));
1588		return NULL;
1589	}
1590	ipnum = GeoIP_addr_to_num(addr);
1591	return _get_region_gl(gi, ipnum, gl);
1592}
1593
1594GeoIPRegion * GeoIP_region_by_addr_v6_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) {
1595       geoipv6_t ipnum;
1596       if (addr == NULL) {
1597               return NULL;
1598       }
1599       if (gi->databaseType != GEOIP_REGION_EDITION_REV0 &&
1600                       gi->databaseType != GEOIP_REGION_EDITION_REV1) {
1601               printf("Invalid database type %s, expected %s\n", get_db_description(gi->databaseType), get_db_description(GEOIP_REGION_EDITION_REV1));
1602               return NULL;
1603       }
1604       ipnum = _GeoIP_addr_to_num_v6(addr);
1605       return _get_region_v6_gl(gi, ipnum, gl);
1606}
1607
1608GeoIPRegion * GeoIP_region_by_name_gl (GeoIP* gi, const char *name, GeoIPLookup * gl) {
1609	unsigned long ipnum;
1610	if (name == NULL) {
1611		return NULL;
1612	}
1613	if (gi->databaseType != GEOIP_REGION_EDITION_REV0 &&
1614			gi->databaseType != GEOIP_REGION_EDITION_REV1) {
1615		printf("Invalid database type %s, expected %s\n", get_db_description(gi->databaseType), get_db_description(GEOIP_REGION_EDITION_REV1));
1616		return NULL;
1617	}
1618	if (!(ipnum = _GeoIP_lookupaddress(name)))
1619		return NULL;
1620	return _get_region_gl(gi, ipnum, gl);
1621}
1622
1623GeoIPRegion * GeoIP_region_by_name_v6_gl (GeoIP* gi, const char *name, GeoIPLookup * gl) {
1624       geoipv6_t ipnum;
1625       if (name == NULL) {
1626               return NULL;
1627       }
1628       if (gi->databaseType != GEOIP_REGION_EDITION_REV0 &&
1629                       gi->databaseType != GEOIP_REGION_EDITION_REV1) {
1630               printf("Invalid database type %s, expected %s\n", get_db_description(gi->databaseType), get_db_description(GEOIP_REGION_EDITION_REV1));
1631               return NULL;
1632       }
1633
1634        ipnum = _GeoIP_lookupaddress_v6(name);
1635       if (__GEOIP_V6_IS_NULL(ipnum))
1636               return NULL;
1637       return _get_region_v6_gl(gi, ipnum, gl);
1638}
1639
1640GeoIPRegion * GeoIP_region_by_ipnum_gl (GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl) {
1641	if (gi->databaseType != GEOIP_REGION_EDITION_REV0 &&
1642			gi->databaseType != GEOIP_REGION_EDITION_REV1) {
1643		printf("Invalid database type %s, expected %s\n", get_db_description(gi->databaseType), get_db_description(GEOIP_REGION_EDITION_REV1));
1644		return NULL;
1645	}
1646	return _get_region_gl(gi, ipnum, gl);
1647}
1648
1649GeoIPRegion * GeoIP_region_by_ipnum_v6_gl (GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl) {
1650       if (gi->databaseType != GEOIP_REGION_EDITION_REV0 &&
1651                       gi->databaseType != GEOIP_REGION_EDITION_REV1) {
1652               printf("Invalid database type %s, expected %s\n", get_db_description(gi->databaseType),get_db_description(GEOIP_REGION_EDITION_REV1));
1653               return NULL;
1654       }
1655       return _get_region_v6_gl(gi, ipnum, gl);
1656}
1657
1658void GeoIPRegion_delete (GeoIPRegion *gir) {
1659	free(gir);
1660}
1661
1662/* GeoIP Organization, ISP and AS Number Edition private method */
1663static
1664char *_get_name_gl (GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl) {
1665	int seek_org;
1666	char buf[MAX_ORG_RECORD_LENGTH];
1667	char * org_buf, * buf_pointer;
1668	int record_pointer;
1669	size_t len;
1670        ssize_t silence _UNUSED;
1671
1672	if (gi->databaseType != GEOIP_ORG_EDITION &&
1673			gi->databaseType != GEOIP_ISP_EDITION &&
1674			gi->databaseType != GEOIP_DOMAIN_EDITION &&
1675			gi->databaseType != GEOIP_ASNUM_EDITION &&
1676			gi->databaseType != GEOIP_ACCURACYRADIUS_EDITION &&
1677			gi->databaseType != GEOIP_NETSPEED_EDITION_REV1 &&
1678			gi->databaseType != GEOIP_USERTYPE_EDITION &&
1679			gi->databaseType != GEOIP_REGISTRAR_EDITION &&
1680			gi->databaseType != GEOIP_LOCATIONA_EDITION &&
1681			gi->databaseType != GEOIP_CITYCONF_EDITION &&
1682			gi->databaseType != GEOIP_COUNTRYCONF_EDITION &&
1683			gi->databaseType != GEOIP_REGIONCONF_EDITION &&
1684			gi->databaseType != GEOIP_POSTALCONF_EDITION
1685                        ) {
1686		printf("Invalid database type %s, expected %s\n", get_db_description(gi->databaseType), get_db_description(GEOIP_ORG_EDITION));
1687		return NULL;
1688	}
1689
1690	seek_org = _GeoIP_seek_record_gl(gi, ipnum, gl);
1691	if (seek_org == gi->databaseSegments[0])
1692		return NULL;
1693
1694	record_pointer = seek_org + (2 * gi->record_length - 1) * gi->databaseSegments[0];
1695
1696	if (gi->cache == NULL) {
1697                silence = pread(fileno(gi->GeoIPDatabase), buf, MAX_ORG_RECORD_LENGTH, record_pointer);
1698                if ( gi->charset == GEOIP_CHARSET_UTF8 ) {
1699	          org_buf = _GeoIP_iso_8859_1__utf8( (const char * ) buf );
1700	        } else {
1701		  len = sizeof(char) * (strlen(buf)+1);
1702		  org_buf = malloc(len);
1703		  strncpy(org_buf, buf, len);
1704                }
1705	} else {
1706		buf_pointer = (char *)(gi->cache + (long)record_pointer);
1707                if ( gi->charset == GEOIP_CHARSET_UTF8 ) {
1708	          org_buf = _GeoIP_iso_8859_1__utf8( (const char * ) buf_pointer );
1709	        } else {
1710		  len = sizeof(char) * (strlen(buf_pointer)+1);
1711		  org_buf = malloc(len);
1712		  strncpy(org_buf, buf_pointer, len);
1713                }
1714	}
1715	return org_buf;
1716}
1717
1718static
1719char *_get_name_v6_gl (GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl) {
1720  int seek_org;
1721  char buf[MAX_ORG_RECORD_LENGTH];
1722  char * org_buf, * buf_pointer;
1723  int record_pointer;
1724  size_t len;
1725  ssize_t silence _UNUSED;
1726
1727  if (
1728      gi->databaseType != GEOIP_ORG_EDITION_V6 &&
1729      gi->databaseType != GEOIP_ISP_EDITION_V6 &&
1730      gi->databaseType != GEOIP_DOMAIN_EDITION_V6 &&
1731      gi->databaseType != GEOIP_ASNUM_EDITION_V6 &&
1732      gi->databaseType != GEOIP_ACCURACYRADIUS_EDITION_V6 &&
1733      gi->databaseType != GEOIP_NETSPEED_EDITION_REV1_V6 &&
1734      gi->databaseType != GEOIP_USERTYPE_EDITION_V6 &&
1735      gi->databaseType != GEOIP_REGISTRAR_EDITION_V6 &&
1736      gi->databaseType != GEOIP_LOCATIONA_EDITION_V6
1737      ) {
1738    printf("Invalid database type %s, expected %s\n", get_db_description(gi->databaseType), get_db_description(GEOIP_ORG_EDITION));
1739    return NULL;
1740  }
1741
1742  seek_org = _GeoIP_seek_record_v6_gl(gi, ipnum, gl);
1743  if (seek_org == gi->databaseSegments[0])
1744    return NULL;
1745
1746  record_pointer = seek_org + (2 * gi->record_length - 1) * gi->databaseSegments[0];
1747
1748  if (gi->cache == NULL) {
1749     silence = pread(fileno(gi->GeoIPDatabase), buf, MAX_ORG_RECORD_LENGTH, record_pointer);
1750    if ( gi->charset == GEOIP_CHARSET_UTF8 ) {
1751      org_buf = _GeoIP_iso_8859_1__utf8( (const char * ) buf );
1752    } else {
1753      len = sizeof(char) * (strlen(buf)+1);
1754      org_buf = malloc(len);
1755      strncpy(org_buf, buf, len);
1756    }
1757  } else {
1758    buf_pointer = (char *)(gi->cache + (long)record_pointer);
1759    if ( gi->charset == GEOIP_CHARSET_UTF8 ) {
1760      org_buf = _GeoIP_iso_8859_1__utf8( (const char * ) buf_pointer );
1761    } else {
1762      len = sizeof(char) * (strlen(buf_pointer)+1);
1763      org_buf = malloc(len);
1764      strncpy(org_buf, buf_pointer, len);
1765    }
1766  }
1767  return org_buf;
1768}
1769
1770char * GeoIP_num_to_addr (unsigned long ipnum) {
1771	char *ret_str;
1772	char *cur_str;
1773	int octet[4];
1774	int num_chars_written, i;
1775
1776	ret_str = malloc(sizeof(char) * 16);
1777	cur_str = ret_str;
1778
1779	for (i = 0; i<4; i++) {
1780		octet[3 - i] = ipnum % 256;
1781		ipnum >>= 8;
1782	}
1783
1784	for (i = 0; i<4; i++) {
1785		num_chars_written = sprintf(cur_str, "%d", octet[i]);
1786		cur_str += num_chars_written;
1787
1788		if (i < 3) {
1789			cur_str[0] = '.';
1790			cur_str++;
1791		}
1792	}
1793
1794	return ret_str;
1795}
1796
1797char **GeoIP_range_by_ip_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) {
1798	unsigned long ipnum;
1799	unsigned long left_seek;
1800	unsigned long right_seek;
1801	unsigned long mask;
1802	int orig_netmask;
1803	int target_value;
1804	char **ret;
1805	GeoIPLookup t;
1806
1807	if (addr == NULL) {
1808		return NULL;
1809	}
1810
1811	ret = malloc(sizeof(char *) * 2);
1812
1813	ipnum = GeoIP_addr_to_num(addr);
1814	target_value = _GeoIP_seek_record_gl(gi, ipnum, gl);
1815	orig_netmask = gl->netmask;
1816	mask = 0xffffffff << ( 32 - orig_netmask );
1817	left_seek = ipnum & mask;
1818	right_seek = left_seek + ( 0xffffffff & ~mask );
1819
1820	while (left_seek != 0
1821	  && target_value == _GeoIP_seek_record_gl(gi, left_seek - 1, &t) ) {
1822
1823		/* Go to beginning of netblock defined by netmask */
1824		mask = 0xffffffff << ( 32 - t.netmask );
1825		left_seek = ( left_seek - 1 ) & mask;
1826	}
1827	ret[0] = GeoIP_num_to_addr(left_seek);
1828
1829	while (right_seek != 0xffffffff
1830	  && target_value == _GeoIP_seek_record_gl(gi, right_seek + 1, &t) ) {
1831
1832		/* Go to end of netblock defined by netmask */
1833		mask = 0xffffffff << ( 32 - t.netmask );
1834		right_seek = ( right_seek + 1 ) & mask;
1835		right_seek += 0xffffffff & ~mask;
1836	}
1837	ret[1] = GeoIP_num_to_addr(right_seek);
1838
1839	gi->netmask = orig_netmask;
1840
1841	return ret;
1842}
1843void GeoIP_range_by_ip_delete( char ** ptr ){
1844	if ( ptr ){
1845		if ( ptr[0] )
1846			free(ptr[0]);
1847		if ( ptr[1] )
1848			free(ptr[1]);
1849		free(ptr);
1850	}
1851}
1852
1853char *GeoIP_name_by_ipnum_gl (GeoIP* gi, unsigned long ipnum, GeoIPLookup * gl) {
1854	return _get_name_gl(gi,ipnum, gl);
1855}
1856
1857char *GeoIP_name_by_ipnum_v6_gl (GeoIP* gi, geoipv6_t ipnum, GeoIPLookup * gl) {
1858       return _get_name_v6_gl(gi,ipnum, gl);
1859}
1860
1861char *GeoIP_name_by_addr_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) {
1862	unsigned long ipnum;
1863	if (addr == NULL) {
1864		return NULL;
1865	}
1866	ipnum = GeoIP_addr_to_num(addr);
1867	return _get_name_gl(gi, ipnum, gl);
1868}
1869
1870char *GeoIP_name_by_addr_v6_gl (GeoIP* gi, const char *addr, GeoIPLookup * gl) {
1871  geoipv6_t ipnum;
1872  if (addr == NULL) {
1873    return NULL;
1874  }
1875  ipnum = _GeoIP_addr_to_num_v6(addr);
1876  return _get_name_v6_gl(gi, ipnum, gl);
1877}
1878
1879char *GeoIP_name_by_name_gl (GeoIP* gi, const char *name, GeoIPLookup * gl) {
1880	unsigned long ipnum;
1881	if (name == NULL) {
1882		return NULL;
1883	}
1884	if (!(ipnum = _GeoIP_lookupaddress(name)))
1885		return NULL;
1886	return _get_name_gl(gi, ipnum, gl);
1887}
1888
1889char *GeoIP_name_by_name_v6_gl (GeoIP* gi, const char *name, GeoIPLookup *gl) {
1890  geoipv6_t ipnum;
1891  if (name == NULL) {
1892    return NULL;
1893  }
1894        ipnum = _GeoIP_lookupaddress_v6(name);
1895  if (__GEOIP_V6_IS_NULL(ipnum))
1896    return NULL;
1897  return _get_name_v6_gl(gi, ipnum, gl);
1898}
1899
1900unsigned char GeoIP_database_edition (GeoIP* gi) {
1901	return gi->databaseType;
1902}
1903
1904int GeoIP_enable_teredo(GeoIP* gi, int true_false){
1905  unsigned int mask = ( 1U << GEOIP_TEREDO_BIT );
1906  int b = ( gi->ext_flags & mask ) ? 1 : 0;
1907  gi->ext_flags &= ~mask ;
1908  if ( true_false )
1909    gi->ext_flags |= true_false;
1910  return b;
1911}
1912
1913int GeoIP_teredo ( GeoIP* gi ){
1914  unsigned int mask = ( 1U << GEOIP_TEREDO_BIT );
1915  return ( gi->ext_flags & mask ) ? 1 : 0;
1916}
1917
1918int GeoIP_charset( GeoIP* gi){
1919  return gi->charset;
1920}
1921
1922int GeoIP_set_charset(  GeoIP* gi, int charset ){
1923  int old_charset = gi->charset;
1924  gi->charset = charset;
1925  return old_charset;
1926}
1927
1928/** return two letter country code */
1929const char* GeoIP_code_by_id(int id)
1930{
1931       if (id < 0 || id >= (int) num_GeoIP_countries)
1932               return NULL;
1933
1934       return GeoIP_country_code[id];
1935}
1936
1937/** return three letter country code */
1938const char* GeoIP_code3_by_id(int id)
1939{
1940       if (id < 0 || id >= (int) num_GeoIP_countries)
1941               return NULL;
1942
1943       return GeoIP_country_code3[id];
1944}
1945
1946
1947/** return full name of country in utf8 or iso-8859-1 */
1948const char* GeoIP_country_name_by_id(GeoIP * gi, int id)
1949{
1950       /* return NULL also even for index 0 for backward compatibility */
1951       if (id <= 0 || id >= (int) num_GeoIP_countries)
1952               return NULL;
1953       return ((gi->charset == GEOIP_CHARSET_UTF8)
1954         ? GeoIP_utf8_country_name[id]
1955         : GeoIP_country_name[id]);
1956}
1957
1958/** return full name of country in iso-8859-1 */
1959const char* GeoIP_name_by_id(int id)
1960{
1961       if (id < 0 || id >= (int) num_GeoIP_countries)
1962               return NULL;
1963
1964       return GeoIP_country_name[id];
1965}
1966
1967/** return continent of country */
1968const char* GeoIP_continent_by_id(int id)
1969{
1970       if (id < 0 || id >= (int) num_GeoIP_countries)
1971               return NULL;
1972
1973       return GeoIP_country_continent[id];
1974}
1975
1976/** return id by country code **/
1977int GeoIP_id_by_code(const char *country)
1978{
1979       unsigned i;
1980
1981       for ( i = 0; i < num_GeoIP_countries; ++i)
1982       {
1983               if (strcmp(country, GeoIP_country_code[i]) == 0)
1984                       return i;
1985       }
1986
1987       return 0;
1988}
1989
1990unsigned GeoIP_num_countries(void)
1991{
1992       return num_GeoIP_countries;
1993}
1994
1995const char * GeoIP_lib_version(void)
1996{
1997       return PACKAGE_VERSION;
1998}
1999
2000int GeoIP_cleanup(void)
2001{
2002	int i, result = 0;
2003	if (GeoIPDBFileName) {
2004
2005		for (i = 0; i < NUM_DB_TYPES; i++) {
2006			if (GeoIPDBFileName[i]) free(GeoIPDBFileName[i]);
2007		}
2008
2009		free(GeoIPDBFileName);
2010		GeoIPDBFileName = NULL;
2011		result = 1;
2012	}
2013
2014	return result;
2015}
2016
2017