return ret;
}
+bool queryGeoLocation(const string &ip, bool v6, GeoIPNetmask& gl, double& lat, double& lon,
+ boost::optional<int>& alt, boost::optional<int>& prec)
+{
+ for(auto const& gi: s_geoip_files) {
+ string val;
+ if (v6) {
+ if (gi->queryLocationV6(gl, ip, lat, lon, alt, prec))
+ return true;
+ } else if (gi->queryLocation(gl, ip, lat, lon, alt, prec))
+ return true;
+ }
+ return false;
+}
+
string GeoIPBackend::format2str(string sformat, const string& ip, bool v6, GeoIPNetmask& gl) {
string::size_type cur,last;
+ boost::optional<int> alt, prec;
+ double lat, lon;
time_t t = time((time_t*)NULL);
GeoIPNetmask tmp_gl; // largest wins
struct tm gtm;
rep = queryGeoIP(ip, v6, GeoIPInterface::Name, tmp_gl);
} else if (!sformat.compare(cur,3,"%ci")) {
rep = queryGeoIP(ip, v6, GeoIPInterface::City, tmp_gl);
+ } else if (!sformat.compare(cur,4,"%loc")) {
+ char ns, ew;
+ int d1, d2, m1, m2;
+ double s1, s2;
+ if (!queryGeoLocation(ip, v6, gl, lat, lon, alt, prec)) {
+ rep = "";
+ } else {
+ ns = (lat>0) ? 'N' : 'S';
+ ew = (lon>0) ? 'E' : 'W';
+ /* remove sign */
+ lat = fabs(lat);
+ lon = fabs(lon);
+ d1 = static_cast<int>(lat);
+ d2 = static_cast<int>(lon);
+ m1 = static_cast<int>((lat - d1)*60.0);
+ m2 = static_cast<int>((lon - d2)*60.0);
+ s1 = static_cast<double>(lat - d1 - m1/60.0)*3600.0;
+ s2 = static_cast<double>(lon - d2 - m2/60.0)*3600.0;
+ rep = str(boost::format("%d %d %0.3f %c %d %d %0.3f %c") %
+ d1 % m1 % s1 % ns % d2 % m2 % s2 % ew);
+ if (alt)
+ rep = rep + str(boost::format(" %d.00") % *alt);
+ else
+ rep = rep + string(" 0.00");
+ if (prec)
+ rep = rep + str(boost::format(" %dm") % *prec);
+ }
+ nrep = 4;
+ } else if (!sformat.compare(cur,4,"%lat")) {
+ if (!queryGeoLocation(ip, v6, gl, lat, lon, alt, prec)) {
+ rep = "";
+ } else {
+ rep = str(boost::format("%lf") % lat);
+ }
+ nrep = 4;
+ } else if (!sformat.compare(cur,4,"%lon")) {
+ if (!queryGeoLocation(ip, v6, gl, lat, lon, alt, prec)) {
+ rep = "";
+ } else {
+ rep = str(boost::format("%lf") % lon);
+ }
+ nrep = 4;
} else if (!sformat.compare(cur,3,"%hh")) {
rep = boost::str(boost::format("%02d") % gtm.tm_hour);
tmp_gl.netmask = (v6?128:32);
return false;
}
+ bool queryLocationV6(GeoIPNetmask& gl, const string &ip,
+ double& latitude, double& longitude,
+ boost::optional<int>& alt, boost::optional<int>& prec) override {
+ if (d_db_type == GEOIP_REGION_EDITION_REV0 ||
+ d_db_type == GEOIP_REGION_EDITION_REV1 ||
+ d_db_type == GEOIP_CITY_EDITION_REV0_V6 ||
+ d_db_type == GEOIP_CITY_EDITION_REV1_V6) {
+ GeoIPRecord *gir = GeoIP_record_by_addr_v6(d_gi.get(), ip.c_str());
+ if (gir) {
+ latitude = gir->latitude;
+ longitude = gir->longitude;
+ gl.netmask = gir->netmask;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool queryLocation(GeoIPNetmask& gl, const string &ip,
+ double& latitude, double& longitude,
+ boost::optional<int>& alt, boost::optional<int>& prec) override {
+ if (d_db_type == GEOIP_REGION_EDITION_REV0 ||
+ d_db_type == GEOIP_REGION_EDITION_REV1 ||
+ d_db_type == GEOIP_CITY_EDITION_REV0 ||
+ d_db_type == GEOIP_CITY_EDITION_REV1) {
+ GeoIPRecord *gir = GeoIP_record_by_addr(d_gi.get(), ip.c_str());
+ if (gir) {
+ latitude = gir->latitude;
+ longitude = gir->longitude;
+ gl.netmask = gir->netmask;
+ return true;
+ }
+ }
+ return false;
+ }
+
~GeoIPInterfaceDAT() { }
private:
unsigned int d_db_type;
return true;
}
+ bool queryLocation(GeoIPNetmask& gl, const string &ip,
+ double& latitude, double& longitude,
+ boost::optional<int>& alt, boost::optional<int>& prec) override {
+ MMDB_entry_data_s data;
+ MMDB_lookup_result_s res;
+ if (!mmdbLookup(ip, false, gl, res))
+ return false;
+ if (MMDB_get_value(&res.entry, &data, "location", "latitude", NULL) != MMDB_SUCCESS || !data.has_data)
+ return false;
+ latitude = data.double_value;
+ if (MMDB_get_value(&res.entry, &data, "location", "longitude", NULL) != MMDB_SUCCESS || !data.has_data)
+ return false;
+ longitude = data.double_value;
+ if (MMDB_get_value(&res.entry, &data, "location", "accuracy_radius", NULL) != MMDB_SUCCESS || !data.has_data)
+ return false;
+ prec = data.uint16;
+ return true;
+ }
+
+ bool queryLocationV6(GeoIPNetmask& gl, const string &ip,
+ double& latitude, double& longitude,
+ boost::optional<int>& alt, boost::optional<int>& prec) override {
+ MMDB_entry_data_s data;
+ MMDB_lookup_result_s res;
+ if (!mmdbLookup(ip, true, gl, res))
+ return false;
+ if (MMDB_get_value(&res.entry, &data, "location", "latitude", NULL) != MMDB_SUCCESS || !data.has_data)
+ return false;
+ latitude = data.double_value;
+ if (MMDB_get_value(&res.entry, &data, "location", "longitude", NULL) != MMDB_SUCCESS || !data.has_data)
+ return false;
+ longitude = data.double_value;
+ if (MMDB_get_value(&res.entry, &data, "location", "accuracy_radius", NULL) != MMDB_SUCCESS || !data.has_data)
+ return false;
+ prec = data.uint16;
+ return true;
+ }
+
~GeoIPInterfaceMMDB() { MMDB_close(&d_s); };
private:
MMDB_s d_s;
#ifndef PDNS_GEOIPINTERFACE_HH
#define PDNS_GEOIPINTERFACE_HH
+#include "boost/optional.hpp"
+
class GeoIPInterface {
public:
enum GeoIPQueryAttribute {
virtual bool queryRegionV6(string &ret, GeoIPNetmask& gl, const string &ip) = 0;
virtual bool queryCity(string &ret, GeoIPNetmask& gl, const string &ip) = 0;
virtual bool queryCityV6(string &ret, GeoIPNetmask& gl, const string &ip) = 0;
+ virtual bool queryLocation(GeoIPNetmask& gl, const string &ip,
+ double& latitude, double& longitude,
+ boost::optional<int>& alt, boost::optional<int>& prec) = 0;
+ virtual bool queryLocationV6(GeoIPNetmask& gl, const string &ip,
+ double& latitude, double& longitude,
+ boost::optional<int>& alt, boost::optional<int>& prec) = 0;
virtual ~GeoIPInterface() { }