1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
2/* geoiplookup.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#include "GeoIPCity.h"
23#include "GeoIP_internal.h"
24
25#if defined(_WIN32)
26# ifndef uint32_t
27typedef unsigned int uint32_t;
28# endif
29#endif
30
31void geoiplookup(GeoIP * gi, char *hostname, int i, char *ccode);
32
33char *geoiplookup_by_ip(char *hostname)
34{
35    GeoIP * gi;
36    int i;
37    int charset = GEOIP_CHARSET_UTF8;
38    char ccode[3];
39
40    if (hostname == NULL)
41        return "";
42
43    memset(ccode, 0, sizeof(ccode));
44
45    _GeoIP_setup_dbfilename();
46
47    /* iterate through different database types */
48    for (i = 0; i < NUM_DB_TYPES; ++i) {
49        if (GeoIP_db_avail(i)) {
50            gi = GeoIP_open_type(i, GEOIP_STANDARD);
51            if (NULL == gi) {
52                /* Ignore these errors. It's possible
53                 * to use the same database name for
54                 * different databases.
55                 */
56                ;
57            } else {
58                gi->charset = charset;
59                geoiplookup(gi, hostname, i, ccode);
60            }
61            GeoIP_delete(gi);
62        }
63    }
64
65    return strdup(ccode);
66}
67
68static const char * _mk_NA( const char * p )
69{
70    return p ? p : "N/A";
71}
72
73void
74geoiplookup(GeoIP * gi, char *hostname, int i, char *ccode)
75{
76    const char *country_code;
77    const char *country_name;
78    const char *domain_name;
79    const char *asnum_name;
80    int netspeed;
81    int country_id;
82    GeoIPRegion *region;
83    GeoIPRecord *gir;
84    const char *org;
85    uint32_t ipnum;
86
87    ipnum = _GeoIP_lookupaddress(hostname);
88    if (ipnum == 0) {
89        printf("%s: can't resolve hostname ( %s )\n", GeoIPDBDescription[i],
90               hostname);
91
92    }else {
93
94        if (GEOIP_DOMAIN_EDITION == i) {
95            domain_name = GeoIP_name_by_ipnum(gi, ipnum);
96            if (domain_name == NULL) {
97                printf("%s: IP Address not found\n", GeoIPDBDescription[i]);
98            }else {
99                printf("%s: %s\n", GeoIPDBDescription[i], domain_name);
100            }
101        }else if (GEOIP_LOCATIONA_EDITION == i ||
102                  GEOIP_ACCURACYRADIUS_EDITION == i
103                  || GEOIP_ASNUM_EDITION == i || GEOIP_USERTYPE_EDITION == i
104                  || GEOIP_REGISTRAR_EDITION == i ||
105                  GEOIP_NETSPEED_EDITION_REV1 == i
106                  || GEOIP_COUNTRYCONF_EDITION == i ||
107                  GEOIP_CITYCONF_EDITION == i
108                  || GEOIP_REGIONCONF_EDITION == i ||
109                  GEOIP_POSTALCONF_EDITION == i) {
110            asnum_name = GeoIP_name_by_ipnum(gi, ipnum);
111            if (asnum_name == NULL) {
112                printf("%s: IP Address not found\n", GeoIPDBDescription[i]);
113            }else {
114                printf("%s: %s\n", GeoIPDBDescription[i], asnum_name);
115            }
116        }else if (GEOIP_COUNTRY_EDITION == i) {
117            country_id = GeoIP_id_by_ipnum(gi, ipnum);
118            country_code = GeoIP_country_code[country_id];
119            country_name = GeoIP_country_name[country_id];
120            if (country_id == 0) {
121                printf("%s: IP Address not found\n", GeoIPDBDescription[i]);
122            }else {
123		memcpy(ccode, country_code, 2);
124                ccode[2] = '\0';
125                printf("%s: %s, %s\n", GeoIPDBDescription[i], country_code,
126                       country_name);
127            }
128        }else if (GEOIP_REGION_EDITION_REV0 == i ||
129                  GEOIP_REGION_EDITION_REV1 == i) {
130            region = GeoIP_region_by_ipnum(gi, ipnum);
131            if (NULL == region || region->country_code[0] == '\0') {
132                printf("%s: IP Address not found\n", GeoIPDBDescription[i]);
133            }else {
134		memcpy(ccode, region->country_code, 2);
135                ccode[2] = '\0';
136                printf("%s: %s, %s\n", GeoIPDBDescription[i],
137                       region->country_code,
138                       region->region);
139            }
140            if (region) {
141                GeoIPRegion_delete(region);
142            }
143        }else if (GEOIP_CITY_EDITION_REV0 == i) {
144            gir = GeoIP_record_by_ipnum(gi, ipnum);
145            if (NULL == gir) {
146                printf("%s: IP Address not found\n", GeoIPDBDescription[i]);
147            }else {
148		memcpy(ccode, gir->country_code, 2);
149                ccode[2] = '\0';
150                printf("%s: %s, %s, %s, %s, %s, %f, %f\n",
151                       GeoIPDBDescription[i], gir->country_code, _mk_NA(
152                           gir->region),
153                       _mk_NA(GeoIP_region_name_by_code(gir->country_code,
154                                                        gir->region)),
155                       _mk_NA(gir->city), _mk_NA(
156                           gir->postal_code), gir->latitude, gir->longitude);
157                GeoIPRecord_delete(gir);
158            }
159        }else if (GEOIP_CITY_EDITION_REV1 == i) {
160            gir = GeoIP_record_by_ipnum(gi, ipnum);
161            if (NULL == gir) {
162                printf("%s: IP Address not found\n", GeoIPDBDescription[i]);
163            }else {
164		memcpy(ccode, gir->country_code, 2);
165                ccode[2] = '\0';
166                printf("%s: %s, %s, %s, %s, %s, %f, %f, %d, %d\n",
167                       GeoIPDBDescription[i], gir->country_code, _mk_NA(
168                           gir->region),
169                       _mk_NA(GeoIP_region_name_by_code(gir->country_code,
170                                                        gir->region)),
171                       _mk_NA(gir->city), _mk_NA(
172                           gir->postal_code),
173                       gir->latitude, gir->longitude, gir->metro_code,
174                       gir->area_code);
175                GeoIPRecord_delete(gir);
176            }
177        }else if (GEOIP_ORG_EDITION == i || GEOIP_ISP_EDITION == i) {
178            org = GeoIP_org_by_ipnum(gi, ipnum);
179            if (org == NULL) {
180                printf("%s: IP Address not found\n", GeoIPDBDescription[i]);
181            }else {
182                printf("%s: %s\n", GeoIPDBDescription[i], org);
183            }
184        }else if (GEOIP_NETSPEED_EDITION == i) {
185            netspeed = GeoIP_id_by_ipnum(gi, ipnum);
186            if (netspeed == GEOIP_UNKNOWN_SPEED) {
187                printf("%s: Unknown\n", GeoIPDBDescription[i]);
188            }else if (netspeed == GEOIP_DIALUP_SPEED) {
189                printf("%s: Dialup\n", GeoIPDBDescription[i]);
190            }else if (netspeed == GEOIP_CABLEDSL_SPEED) {
191                printf("%s: Cable/DSL\n", GeoIPDBDescription[i]);
192            }else if (netspeed == GEOIP_CORPORATE_SPEED) {
193                printf("%s: Corporate\n", GeoIPDBDescription[i]);
194            }
195        }else {
196
197            /*
198             * Silent ignore IPv6 databases. Otherwise we get annoying
199             * messages whenever we have a mixed environment IPv4 and
200             *  IPv6
201             */
202
203            /*
204             * printf("Can not handle database type -- try geoiplookup6\n");
205             */
206            ;
207        }
208    }
209}
210