1 /*
2     ettercap -- GeoIP interface; IPv4/6 address to geolocation lookup.
3 
4     Copyright (C) ALoR & NaGA
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program 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
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 
20 */
21 
22 #include <ec.h>
23 #include <ec_geoip.h>
24 
25 #ifdef HAVE_GEOIP
26 
27 #include <GeoIP.h>
28 
29 static GeoIP *gi  = NULL;
30 #ifdef WITH_IPV6
31 static GeoIP *gi6 = NULL;
32 #endif
33 
geoip_exit(void)34 static void geoip_exit (void)
35 {
36    GeoIP_delete (gi);
37    gi = NULL;
38 #ifdef WITH_IPV6
39    GeoIP_delete(gi6);
40    gi6 = NULL;
41 #endif
42    GeoIP_cleanup();
43 }
44 
geoip_init(void)45 void geoip_init (void)
46 {
47    char *gi_info;
48 
49    /* try to find and open it in the default location */
50    gi = GeoIP_open_type(GEOIP_COUNTRY_EDITION, GEOIP_MEMORY_CACHE);
51 
52    /* not found, fallback in the configuration file value */
53    if(!gi) {
54 
55       if (!EC_GBL_CONF->geoip_data_file)
56          return;
57 
58       gi = GeoIP_open (EC_GBL_CONF->geoip_data_file, GEOIP_MEMORY_CACHE);
59       if (!gi)
60       {
61          DEBUG_MSG ("geoip_init: %s not found.", EC_GBL_CONF->geoip_data_file);
62          GeoIP_cleanup();
63          return;
64       }
65    }
66    gi_info = GeoIP_database_info (gi);
67 
68    DEBUG_MSG ("geoip_init: Description: %s.",
69          GeoIPDBDescription[GEOIP_COUNTRY_EDITION]);
70    DEBUG_MSG ("geoip_init: Info:        %s. Countries: %u",
71          gi_info ? gi_info : "<none>", GeoIP_num_countries());
72 
73    atexit (geoip_exit);
74 
75    SAFE_FREE(gi_info);
76    gi_info = NULL;
77 
78 #ifdef WITH_IPV6
79 
80    /* try to find and open it in the default location */
81    gi6 = GeoIP_open_type(GEOIP_COUNTRY_EDITION_V6, GEOIP_MEMORY_CACHE);
82 
83    /* not found, fallback in the configuration file value */
84    if (!gi6) {
85       if (!EC_GBL_CONF->geoip_data_file_v6)
86          return;
87 
88       gi6 = GeoIP_open(EC_GBL_CONF->geoip_data_file_v6, GEOIP_MEMORY_CACHE);
89       if (!gi6) {
90          DEBUG_MSG("geoip_init: %s not found.\n",
91                EC_GBL_CONF->geoip_data_file_v6);
92          return;
93       }
94    }
95 
96    gi_info = GeoIP_database_info(gi6);
97 
98    DEBUG_MSG("geoip_init: Description: %s.",
99          GeoIPDBDescription[GEOIP_COUNTRY_EDITION_V6]);
100    DEBUG_MSG("geoip_init: Info:        %s. Countries: %u",
101          gi_info ? gi_info : "<none>", GeoIP_num_countries());
102 
103    SAFE_FREE(gi_info);
104    gi_info = NULL;
105 
106 #endif
107 }
108 
109 /*
110  * returns the country code string for a given IP address ...
111  *  - the two letter country code from GeoIP database
112  *  - "00" if ip address is the default or undefined address
113  *  - "--" if ip address is not global
114  * return NULL if GeoIP API isn't initialized properly
115  */
geoip_ccode_by_ip(struct ip_addr * ip)116 const char* geoip_ccode_by_ip (struct ip_addr *ip)
117 {
118    int id;
119 #ifdef WITH_IPV6
120    struct in6_addr geo_ip6;
121 #endif
122    char tmp[MAX_ASCII_ADDR_LEN];
123 
124    /* 0.0.0.0 or :: */
125    if (ip_addr_is_zero(ip)) {
126       return "00";
127    }
128 
129    /* only global IP addresses can have a location */
130    if (!ip_addr_is_global(ip)) {
131       return "--";
132    }
133 
134    /* Determine country id by IP address */
135    switch (ntohs(ip->addr_type)) {
136       case AF_INET:
137          if (!gi)
138             return NULL;
139          id = GeoIP_id_by_ipnum(gi, ntohl(*ip->addr32));
140          break;
141 #ifdef WITH_IPV6
142       case AF_INET6:
143          if (!gi6)
144             return NULL;
145          ip_addr_cpy((u_char *)geo_ip6.s6_addr, ip);
146          id = GeoIP_id_by_ipnum_v6(gi6, geo_ip6);
147          break;
148 #endif
149       default:
150          return NULL;
151    }
152 
153    DEBUG_MSG("geoip_ccode_by_ip: GeoIP country code for ip %s: %s",
154          ip_addr_ntoa(ip, tmp), GeoIP_code_by_id(id));
155 
156    return GeoIP_code_by_id(id);
157 }
158 
159 /*
160  * returns the country name string for a given IP address
161  * return NULL if GeoIP API isn't initialized properly
162  */
geoip_country_by_ip(struct ip_addr * ip)163 const char* geoip_country_by_ip (struct ip_addr *ip)
164 {
165    int id;
166 #ifdef WITH_IPV6
167    struct in6_addr geo_ip6;
168 #endif
169    char tmp[MAX_ASCII_ADDR_LEN];
170 
171    /* 0.0.0.0 or :: */
172    if (ip_addr_is_zero(ip)) {
173       return "No unique location";
174    }
175 
176    /* only global IP addresses can have a location */
177    if (!ip_addr_is_global(ip)) {
178       return "No unique location";
179    }
180 
181    /* Determine country id by IP address */
182    switch (ntohs(ip->addr_type)) {
183       case AF_INET:
184          if (!gi)
185             return NULL;
186          id = GeoIP_id_by_ipnum(gi, ntohl(*ip->addr32));
187          break;
188 #ifdef WITH_IPV6
189       case AF_INET6:
190          if (!gi6)
191             return NULL;
192          ip_addr_cpy((u_char *)geo_ip6.s6_addr, ip);
193          id = GeoIP_id_by_ipnum_v6(gi6, geo_ip6);
194          break;
195 #endif
196       default:
197          return NULL;
198    }
199 
200    DEBUG_MSG("geoip_country_by_ip: GeoIP country name for ip %s: %s",
201          ip_addr_ntoa(ip, tmp), GeoIP_name_by_id(id));
202 
203    return GeoIP_name_by_id(id);
204 }
205 
206 #endif  /* HAVE_GEOIP */
207