| /* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| #include "cripts/Preamble.hpp" |
| |
| #if CRIPTS_HAS_MAXMIND |
| #include <maxminddb.h> |
| |
| extern MMDB_s *gMaxMindDB; |
| |
| enum Qualifiers { |
| GEO_QUAL_COUNTRY, |
| GEO_QUAL_COUNTRY_ISO, |
| GEO_QUAL_ASN, |
| GEO_QUAL_ASN_NAME, |
| }; |
| |
| cripts::string |
| get_geo_string(const sockaddr *addr, Qualifiers q) |
| { |
| ink_release_assert(gMaxMindDB != nullptr); |
| ink_release_assert(addr != nullptr); |
| |
| cripts::string ret = "(unknown)"; |
| int mmdb_error; |
| |
| MMDB_lookup_result_s result = MMDB_lookup_sockaddr(gMaxMindDB, addr, &mmdb_error); |
| |
| if (MMDB_SUCCESS != mmdb_error) { |
| return ret; |
| } |
| |
| MMDB_entry_data_list_s *entry_data_list = nullptr; |
| if (!result.found_entry) { |
| return ret; |
| } |
| |
| int status = MMDB_get_entry_data_list(&result.entry, &entry_data_list); |
| if (MMDB_SUCCESS != status) { |
| return ret; |
| } |
| |
| if (entry_data_list == nullptr) { |
| return ret; |
| } |
| |
| const char *field_name; |
| switch (q) { |
| case GEO_QUAL_COUNTRY: |
| field_name = "country_code"; |
| break; |
| case GEO_QUAL_ASN_NAME: |
| field_name = "autonomous_system_organization"; |
| break; |
| default: |
| Error("Cripts: Unsupported field %d", q); |
| return ret; |
| break; |
| } |
| |
| MMDB_entry_data_s entry_data; |
| |
| status = MMDB_get_value(&result.entry, &entry_data, field_name, NULL); |
| if (MMDB_SUCCESS != status) { |
| return ret; |
| } |
| ret = cripts::string(entry_data.utf8_string, entry_data.data_size); |
| |
| if (nullptr != entry_data_list) { |
| MMDB_free_entry_data_list(entry_data_list); |
| } |
| |
| return ret; |
| } |
| |
| // Helper function to convert IP to sockaddr for geo lookup |
| cripts::string |
| get_geo_string_from_ip(const cripts::IP &ip, Qualifiers q) |
| { |
| auto addr = ip.Socket(); |
| return get_geo_string(&addr, q); |
| } |
| |
| // IP class Geo methods - can be used with any IP address |
| cripts::string |
| cripts::IP::ASN() const |
| { |
| return get_geo_string_from_ip(*this, GEO_QUAL_ASN); |
| } |
| |
| cripts::string |
| cripts::IP::ASNName() const |
| { |
| return get_geo_string_from_ip(*this, GEO_QUAL_ASN_NAME); |
| } |
| |
| cripts::string |
| cripts::IP::Country() const |
| { |
| return get_geo_string_from_ip(*this, GEO_QUAL_COUNTRY); |
| } |
| |
| cripts::string |
| cripts::IP::CountryCode() const |
| { |
| return get_geo_string_from_ip(*this, GEO_QUAL_COUNTRY_ISO); |
| } |
| |
| #else |
| |
| // IP class Geo methods - unavailable when MaxMind is not available |
| cripts::string |
| cripts::IP::ASN() const |
| { |
| return "(unavailable)"; |
| } |
| |
| cripts::string |
| cripts::IP::ASNName() const |
| { |
| return "(unavailable)"; |
| } |
| |
| cripts::string |
| cripts::IP::Country() const |
| { |
| return "(unavailable)"; |
| } |
| |
| cripts::string |
| cripts::IP::CountryCode() const |
| { |
| return "(unavailable)"; |
| } |
| |
| #endif // CRIPTS_HAS_MAXMIND |
| |
| // ConnBase::Geo methods - delegate to IP-based implementation for backward compatibility |
| cripts::string |
| detail::ConnBase::Geo::ASN() const |
| { |
| return this->_owner->IP().ASN(); |
| } |
| |
| cripts::string |
| detail::ConnBase::Geo::ASNName() const |
| { |
| return this->_owner->IP().ASNName(); |
| } |
| |
| cripts::string |
| detail::ConnBase::Geo::Country() const |
| { |
| return this->_owner->IP().Country(); |
| } |
| |
| cripts::string |
| detail::ConnBase::Geo::CountryCode() const |
| { |
| return this->_owner->IP().CountryCode(); |
| } |