From: Aki Tuomi Date: Mon, 1 Jan 2018 15:22:40 +0000 (+0200) Subject: geoipbackend: Add location support X-Git-Tag: dnsdist-1.3.0~85^2~12 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5175e0dddf977584aefb5a84be851dc78949ff07;p=thirdparty%2Fpdns.git geoipbackend: Add location support --- diff --git a/modules/geoipbackend/geoipbackend.cc b/modules/geoipbackend/geoipbackend.cc index 724513f3a0..856a3335b3 100644 --- a/modules/geoipbackend/geoipbackend.cc +++ b/modules/geoipbackend/geoipbackend.cc @@ -446,8 +446,24 @@ string queryGeoIP(const string &ip, bool v6, GeoIPInterface::GeoIPQueryAttribute return ret; } +bool queryGeoLocation(const string &ip, bool v6, GeoIPNetmask& gl, double& lat, double& lon, + boost::optional& alt, boost::optional& 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 alt, prec; + double lat, lon; time_t t = time((time_t*)NULL); GeoIPNetmask tmp_gl; // largest wins struct tm gtm; @@ -474,6 +490,48 @@ string GeoIPBackend::format2str(string sformat, const string& ip, bool v6, GeoIP 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(lat); + d2 = static_cast(lon); + m1 = static_cast((lat - d1)*60.0); + m2 = static_cast((lon - d2)*60.0); + s1 = static_cast(lat - d1 - m1/60.0)*3600.0; + s2 = static_cast(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); diff --git a/modules/geoipbackend/geoipinterface-dat.cc b/modules/geoipbackend/geoipinterface-dat.cc index c5d2a0414b..a1754781af 100644 --- a/modules/geoipbackend/geoipinterface-dat.cc +++ b/modules/geoipbackend/geoipinterface-dat.cc @@ -376,6 +376,42 @@ public: return false; } + bool queryLocationV6(GeoIPNetmask& gl, const string &ip, + double& latitude, double& longitude, + boost::optional& alt, boost::optional& 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& alt, boost::optional& 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; diff --git a/modules/geoipbackend/geoipinterface-mmdb.cc b/modules/geoipbackend/geoipinterface-mmdb.cc index 488b97f133..1cb48c6e00 100644 --- a/modules/geoipbackend/geoipinterface-mmdb.cc +++ b/modules/geoipbackend/geoipinterface-mmdb.cc @@ -194,6 +194,44 @@ public: return true; } + bool queryLocation(GeoIPNetmask& gl, const string &ip, + double& latitude, double& longitude, + boost::optional& alt, boost::optional& 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& alt, boost::optional& 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; diff --git a/modules/geoipbackend/geoipinterface.hh b/modules/geoipbackend/geoipinterface.hh index 97dd5ee48d..87d83bf4fb 100644 --- a/modules/geoipbackend/geoipinterface.hh +++ b/modules/geoipbackend/geoipinterface.hh @@ -22,6 +22,8 @@ #ifndef PDNS_GEOIPINTERFACE_HH #define PDNS_GEOIPINTERFACE_HH +#include "boost/optional.hpp" + class GeoIPInterface { public: enum GeoIPQueryAttribute { @@ -48,6 +50,12 @@ public: 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& alt, boost::optional& prec) = 0; + virtual bool queryLocationV6(GeoIPNetmask& gl, const string &ip, + double& latitude, double& longitude, + boost::optional& alt, boost::optional& prec) = 0; virtual ~GeoIPInterface() { }