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