"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/geoip1.c" between
goaccess-1.6.5.tar.gz and goaccess-1.7.tar.gz

About: GoAccess is a real-time web log analyzer and interactive viewer ("text-based").

geoip1.c  (goaccess-1.6.5):geoip1.c  (goaccess-1.7)
/** /**
* geoip.c -- implementation of GeoIP * geoip.c -- implementation of GeoIP (legacy)
* ______ ___ * ______ ___
* / ____/___ / | _____________ __________ * / ____/___ / | _____________ __________
* / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/
* / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ )
* \____/\____/_/ |_\___/\___/\___/____/____/ * \____/\____/_/ |_\___/\___/\___/____/____/
* *
* The MIT License (MIT) * The MIT License (MIT)
* Copyright (c) 2009-2022 Gerardo Orellana <hello @ goaccess.io> * Copyright (c) 2009-2022 Gerardo Orellana <hello @ goaccess.io>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
skipping to change at line 45 skipping to change at line 45
#ifdef HAVE_LIBGEOIP #ifdef HAVE_LIBGEOIP
#include <GeoIP.h> #include <GeoIP.h>
#include <GeoIPCity.h> #include <GeoIPCity.h>
#endif #endif
#include "geoip1.h" #include "geoip1.h"
#include "error.h" #include "error.h"
#include "util.h" #include "util.h"
static GeoIP *geo_location_data; static GeoIP **geoips = NULL;
static GeoIP *geo_location_data = NULL;
static int db_cnt = 0;
static int legacy_db = 0;
/* Determine if we have a valid geoip resource. /* Determine if we have a valid geoip resource.
* *
* If the geoip resource is NULL, 0 is returned. * If the geoip resource is NULL, 0 is returned.
* If the geoip resource is valid and malloc'd, 1 is returned. */ * If the geoip resource is valid and malloc'd, 1 is returned. */
int int
is_geoip_resource (void) { is_geoip_resource (void) {
return geo_location_data != NULL ? 1 : 0; return ((geoips && db_cnt) || (legacy_db && geo_location_data));
} }
/* Free up GeoIP resources */ /* Free up GeoIP resources */
void void
geoip_free (void) { geoip_free (void) {
int idx = 0;
if (!is_geoip_resource ()) if (!is_geoip_resource ())
return; return;
GeoIP_delete (geo_location_data); for (idx = 0; idx < db_cnt; idx++)
GeoIP_delete (geoips[idx]);
if (legacy_db)
GeoIP_delete (geo_location_data);
GeoIP_cleanup (); GeoIP_cleanup ();
free (geoips);
geoips = NULL;
} }
/* Open the given GeoLocation database and set its charset. /* Open the given GeoLocation database and set its charset.
* *
* On error, it aborts. * On error, it aborts.
* On success, a new geolocation structure is returned. */ * On success, a new geolocation structure is returned. */
static GeoIP * static GeoIP *
geoip_open_db (const char *db) { geoip_open_db (const char *db) {
GeoIP *geoip; GeoIP *geoip = GeoIP_open (db, GEOIP_MEMORY_CACHE);
geoip = GeoIP_open (db, GEOIP_MEMORY_CACHE);
if (geoip == NULL) if (geoip == NULL)
FATAL ("Unable to open GeoIP database: %s\n", db); return NULL;
GeoIP_set_charset (geoip, GEOIP_CHARSET_UTF8); GeoIP_set_charset (geoip, GEOIP_CHARSET_UTF8);
LOG_DEBUG (("Opened GeoIP City database: %s\n", db)); LOG_DEBUG (("Opened legacy GeoIP database: %s\n", db));
return geoip; return geoip;
} }
static int
set_geoip_db_by_type (GeoIP * geoip, GO_GEOIP_DB type) {
unsigned char rec = GeoIP_database_edition (geoip);
switch (rec) {
case GEOIP_ASNUM_EDITION:
if (type != TYPE_ASN)
break;
geo_location_data = geoip;
return 0;
case GEOIP_COUNTRY_EDITION:
case GEOIP_COUNTRY_EDITION_V6:
if (type != TYPE_COUNTRY && type != TYPE_CITY)
break;
geo_location_data = geoip;
return 0;
case GEOIP_CITY_EDITION_REV0:
case GEOIP_CITY_EDITION_REV1:
case GEOIP_CITY_EDITION_REV0_V6:
case GEOIP_CITY_EDITION_REV1_V6:
if (type != TYPE_CITY)
break;
geo_location_data = geoip;
return 0;
}
return 1;
}
static int
set_conf_by_type (GeoIP * geoip) {
unsigned char rec = GeoIP_database_edition (geoip);
switch (rec) {
case GEOIP_ASNUM_EDITION:
conf.has_geoasn = 1;
return 0;
case GEOIP_COUNTRY_EDITION:
case GEOIP_COUNTRY_EDITION_V6:
conf.has_geocountry = 1;
return 0;
case GEOIP_CITY_EDITION_REV0:
case GEOIP_CITY_EDITION_REV1:
case GEOIP_CITY_EDITION_REV0_V6:
case GEOIP_CITY_EDITION_REV1_V6:
conf.has_geocountry = conf.has_geocity = 1;
return 0;
}
return 1;
}
/* Look up for a database on our array and set it as our current handlers.
* Note: this is not ideal, for now. However, legacy will go out of support at s
ome point.
*
* On error or if no entry is found, 1 is returned.
* On success, GeoIP struct is set as our handler and 0 is returned. */
static int
set_geoip_db (GO_GEOIP_DB type) {
int idx = 0;
if (!is_geoip_resource ())
return 1;
/* in memory legacy DB */
if (legacy_db && geo_location_data)
return 0;
for (idx = 0; idx < db_cnt; idx++) {
if (set_geoip_db_by_type (geoips[idx], type) == 0)
return 0;
}
return 1;
}
static void
set_geoip (const char *db) {
GeoIP **new_geoips = NULL, *geoip = NULL;
if (db == NULL || *db == '\0')
return;
if (!(geoip = geoip_open_db (db)))
FATAL ("Unable to open GeoIP database %s\n", db);
db_cnt++;
new_geoips = realloc (geoips, sizeof (*geoips) * db_cnt);
if (new_geoips == NULL)
FATAL ("Unable to realloc GeoIP database %s\n", db);
geoips = new_geoips;
geoips[db_cnt - 1] = geoip;
set_conf_by_type (geoip);
}
/* Set up and open GeoIP database */ /* Set up and open GeoIP database */
void void
init_geoip (void) { init_geoip (void) {
/* open custom city GeoIP database */ int i;
if (conf.geoip_database != NULL)
geo_location_data = geoip_open_db (conf.geoip_database); for (i = 0; i < conf.geoip_db_idx; ++i)
set_geoip (conf.geoip_databases[i]);
/* fall back to legacy GeoIP database */ /* fall back to legacy GeoIP database */
else if (!conf.geoip_db_idx) {
geo_location_data = GeoIP_new (conf.geo_db); geo_location_data = GeoIP_new (conf.geo_db);
legacy_db = 1;
}
} }
static char ip4to6_out_buffer[17]; static char ip4to6_out_buffer[17];
static char * static char *
ip4to6 (const char *ipv4) { ip4to6 (const char *ipv4) {
unsigned int b[4]; unsigned int b[4];
int n = sscanf (ipv4, "%u.%u.%u.%u", b, b + 1, b + 2, b + 3); int n = sscanf (ipv4, "%u.%u.%u.%u", b, b + 1, b + 2, b + 3);
if (n == 4) { if (n == 4) {
snprintf (ip4to6_out_buffer, sizeof (ip4to6_out_buffer), "::ffff:%02x%02x:%0 2x%02x", b[0], snprintf (ip4to6_out_buffer, sizeof (ip4to6_out_buffer), "::ffff:%02x%02x:%0 2x%02x", b[0],
b[1], b[2], b[3]); b[1], b[2], b[3]);
skipping to change at line 159 skipping to change at line 270
/* Compose a string with the continent name and store it in the given /* Compose a string with the continent name and store it in the given
* buffer. */ * buffer. */
static void static void
geoip_set_continent (const char *continent, char *loc) { geoip_set_continent (const char *continent, char *loc) {
if (continent) if (continent)
snprintf (loc, CONTINENT_LEN, "%s", get_continent_name_and_code (continent)) ; snprintf (loc, CONTINENT_LEN, "%s", get_continent_name_and_code (continent)) ;
else else
snprintf (loc, CONTINENT_LEN, "%s", "Unknown"); snprintf (loc, CONTINENT_LEN, "%s", "Unknown");
} }
/* Compose a string with the continent name and store it in the given
* buffer. */
static void
geoip_set_asn (const char *name, char *asn) {
if (name)
snprintf (asn, ASN_LEN, "%s", name);
else
snprintf (asn, ASN_LEN, "%s", "Unknown");
}
/* Get detailed information found in the GeoIP Database about the /* Get detailed information found in the GeoIP Database about the
* given IPv4 or IPv6. * given IPv4 or IPv6.
* *
* On error, NULL is returned * On error, NULL is returned
* On success, GeoIPRecord structure is returned */ * On success, GeoIPRecord structure is returned */
static GeoIPRecord * static GeoIPRecord *
get_geoip_record (const char *addr, GTypeIP type_ip) { get_geoip_record (const char *addr, GTypeIP type_ip) {
GeoIPRecord *rec = NULL; GeoIPRecord *rec = NULL;
if (TYPE_IPV4 == type_ip) if (TYPE_IPV4 == type_ip)
skipping to change at line 183 skipping to change at line 304
return rec; return rec;
} }
/* Set country data by record into the given `location` buffer based /* Set country data by record into the given `location` buffer based
* on the IP version. */ * on the IP version. */
static void static void
geoip_set_country_by_record (const char *ip, char *location, GTypeIP type_ip) { geoip_set_country_by_record (const char *ip, char *location, GTypeIP type_ip) {
GeoIPRecord *rec = NULL; GeoIPRecord *rec = NULL;
const char *country = NULL, *code = NULL, *addr = ip; const char *country = NULL, *code = NULL, *addr = ip;
if (conf.geoip_database == NULL || geo_location_data == NULL) if (geo_location_data == NULL)
return; return;
/* Custom GeoIP database */ /* Custom GeoIP database */
if ((rec = get_geoip_record (addr, type_ip))) { if ((rec = get_geoip_record (addr, type_ip))) {
country = rec->country_name; country = rec->country_name;
code = rec->country_code; code = rec->country_code;
} }
geoip_set_country (country, code, location); geoip_set_country (country, code, location);
if (rec != NULL) { if (rec != NULL) {
skipping to change at line 252 skipping to change at line 373
/* return two letter country code */ /* return two letter country code */
if (!(geoid = geoip_get_geoid (addr, type_ip))) if (!(geoid = geoip_get_geoid (addr, type_ip)))
goto out; goto out;
code = GeoIP_code_by_id (geoid); code = GeoIP_code_by_id (geoid);
out: out:
geoip_set_country (country, code, location); geoip_set_country (country, code, location);
} }
/* Set continent data by record into the given `location` buffer based
* on the IP version. */
static void
geoip_set_continent_by_record (const char *ip, char *location, GTypeIP type_ip)
{
GeoIPRecord *rec = NULL;
const char *continent = NULL, *addr = ip;
if (geo_location_data == NULL)
return;
/* Custom GeoIP database */
if ((rec = get_geoip_record (addr, type_ip)))
continent = rec->continent_code;
geoip_set_continent (continent, location);
if (rec != NULL) {
GeoIPRecord_delete (rec);
}
}
/* Set continent data by geoid into the given `location` buffer based
* on the IP version. */
static void
geoip_set_continent_by_geoid (const char *ip, char *location, GTypeIP type_ip) {
const char *continent = NULL, *addr = ip;
int geoid = 0;
if (!is_geoip_resource ())
return;
if (!(geoid = geoip_get_geoid (addr, type_ip)))
goto out;
continent = GeoIP_continent_by_id (geoid);
out:
geoip_set_continent (continent, location);
}
/* Set city data by record into the given `location` buffer based on
* the IP version. */
static void
geoip_set_city_by_record (const char *ip, char *location, GTypeIP type_ip) {
GeoIPRecord *rec = NULL;
const char *city = NULL, *region = NULL, *addr = ip;
/* Custom GeoIP database */
if ((rec = get_geoip_record (addr, type_ip))) {
city = rec->city;
region = rec->region;
}
geoip_set_city (city, region, location);
if (rec != NULL) {
GeoIPRecord_delete (rec);
}
}
/* Set city data by geoid or record into the given `location` buffer
* based on the IP version and currently used database edition.
* It uses the custom GeoIP database - i.e., GeoLiteCity.dat */
static void
geoip_get_city (const char *ip, char *location, GTypeIP type_ip) {
unsigned char rec = 0;
if (geo_location_data == NULL)
return;
rec = GeoIP_database_edition (geo_location_data);
switch (rec) {
case GEOIP_CITY_EDITION_REV0:
case GEOIP_CITY_EDITION_REV1:
if (TYPE_IPV4 == type_ip)
geoip_set_city_by_record (ip, location, TYPE_IPV4);
else
geoip_set_city (NULL, NULL, location);
break;
case GEOIP_CITY_EDITION_REV0_V6:
case GEOIP_CITY_EDITION_REV1_V6:
if (TYPE_IPV6 == type_ip)
geoip_set_city_by_record (ip, location, TYPE_IPV6);
else {
char *ipv6 = ip4to6 (ip);
if (ipv6)
geoip_set_city_by_record (ipv6, location, TYPE_IPV6);
else
geoip_set_city (NULL, NULL, location);
}
break;
}
}
/* Set country data by geoid or record into the given `location` buffer /* Set country data by geoid or record into the given `location` buffer
* based on the IP version and currently used database edition. */ * based on the IP version and currently used database edition. */
void void
geoip_get_country (const char *ip, char *location, GTypeIP type_ip) { geoip_get_country (const char *ip, char *location, GTypeIP type_ip) {
unsigned char rec = GeoIP_database_edition (geo_location_data); unsigned char rec = 0;
if (set_geoip_db (TYPE_COUNTRY) && set_geoip_db (TYPE_CITY)) {
geoip_set_country (NULL, NULL, location);
return;
}
rec = GeoIP_database_edition (geo_location_data);
switch (rec) { switch (rec) {
case GEOIP_COUNTRY_EDITION: case GEOIP_COUNTRY_EDITION:
if (TYPE_IPV4 == type_ip) if (TYPE_IPV4 == type_ip)
geoip_set_country_by_geoid (ip, location, TYPE_IPV4); geoip_set_country_by_geoid (ip, location, TYPE_IPV4);
else else
geoip_set_country (NULL, NULL, location); geoip_set_country (NULL, NULL, location);
break; break;
case GEOIP_COUNTRY_EDITION_V6: case GEOIP_COUNTRY_EDITION_V6:
if (TYPE_IPV6 == type_ip) if (TYPE_IPV6 == type_ip)
geoip_set_country_by_geoid (ip, location, TYPE_IPV6); geoip_set_country_by_geoid (ip, location, TYPE_IPV6);
skipping to change at line 298 skipping to change at line 516
char *ipv6 = ip4to6 (ip); char *ipv6 = ip4to6 (ip);
if (ipv6) if (ipv6)
geoip_set_country_by_record (ipv6, location, TYPE_IPV6); geoip_set_country_by_record (ipv6, location, TYPE_IPV6);
else else
geoip_set_country (NULL, NULL, location); geoip_set_country (NULL, NULL, location);
} }
break; break;
} }
} }
/* Set continent data by record into the given `location` buffer based
* on the IP version. */
static void
geoip_set_continent_by_record (const char *ip, char *location, GTypeIP type_ip)
{
GeoIPRecord *rec = NULL;
const char *continent = NULL, *addr = ip;
if (conf.geoip_database == NULL || geo_location_data == NULL)
return;
/* Custom GeoIP database */
if ((rec = get_geoip_record (addr, type_ip)))
continent = rec->continent_code;
geoip_set_continent (continent, location);
if (rec != NULL) {
GeoIPRecord_delete (rec);
}
}
/* Set continent data by geoid into the given `location` buffer based
* on the IP version. */
static void
geoip_set_continent_by_geoid (const char *ip, char *location, GTypeIP type_ip) {
const char *continent = NULL, *addr = ip;
int geoid = 0;
if (!is_geoip_resource ())
return;
if (!(geoid = geoip_get_geoid (addr, type_ip)))
goto out;
continent = GeoIP_continent_by_id (geoid);
out:
geoip_set_continent (continent, location);
}
/* Set continent data by geoid or record into the given `location` buffer /* Set continent data by geoid or record into the given `location` buffer
* based on the IP version and currently used database edition. */ * based on the IP version and currently used database edition. */
void void
geoip_get_continent (const char *ip, char *location, GTypeIP type_ip) { geoip_get_continent (const char *ip, char *location, GTypeIP type_ip) {
unsigned char rec = GeoIP_database_edition (geo_location_data); unsigned char rec = 0;
if (set_geoip_db (TYPE_COUNTRY) && set_geoip_db (TYPE_CITY)) {
geoip_set_continent (NULL, location);
return;
}
rec = GeoIP_database_edition (geo_location_data);
switch (rec) { switch (rec) {
case GEOIP_COUNTRY_EDITION: case GEOIP_COUNTRY_EDITION:
if (TYPE_IPV4 == type_ip) if (TYPE_IPV4 == type_ip)
geoip_set_continent_by_geoid (ip, location, TYPE_IPV4); geoip_set_continent_by_geoid (ip, location, TYPE_IPV4);
else else
geoip_set_continent (NULL, location); geoip_set_continent (NULL, location);
break; break;
case GEOIP_COUNTRY_EDITION_V6: case GEOIP_COUNTRY_EDITION_V6:
if (TYPE_IPV6 == type_ip) if (TYPE_IPV6 == type_ip)
geoip_set_continent_by_geoid (ip, location, TYPE_IPV6); geoip_set_continent_by_geoid (ip, location, TYPE_IPV6);
skipping to change at line 382 skipping to change at line 568
char *ipv6 = ip4to6 (ip); char *ipv6 = ip4to6 (ip);
if (ipv6) if (ipv6)
geoip_set_continent_by_record (ipv6, location, TYPE_IPV6); geoip_set_continent_by_record (ipv6, location, TYPE_IPV6);
else else
geoip_set_continent (NULL, location); geoip_set_continent (NULL, location);
} }
break; break;
} }
} }
/* Set city data by record into the given `location` buffer based on
* the IP version. */
static void
geoip_set_city_by_record (const char *ip, char *location, GTypeIP type_ip) {
GeoIPRecord *rec = NULL;
const char *city = NULL, *region = NULL, *addr = ip;
/* Custom GeoIP database */
if ((rec = get_geoip_record (addr, type_ip))) {
city = rec->city;
region = rec->region;
}
geoip_set_city (city, region, location);
if (rec != NULL) {
GeoIPRecord_delete (rec);
}
}
/* Set city data by geoid or record into the given `location` buffer
* based on the IP version and currently used database edition.
* It uses the custom GeoIP database - i.e., GeoLiteCity.dat */
void void
geoip_get_city (const char *ip, char *location, GTypeIP type_ip) { geoip_asn (char *host, char *asn) {
unsigned char rec = GeoIP_database_edition (geo_location_data); char *name = NULL;
if (conf.geoip_database == NULL || geo_location_data == NULL) if (legacy_db || set_geoip_db (TYPE_ASN)) {
geoip_set_asn (NULL, asn);
return; return;
switch (rec) {
case GEOIP_CITY_EDITION_REV0:
case GEOIP_CITY_EDITION_REV1:
if (TYPE_IPV4 == type_ip)
geoip_set_city_by_record (ip, location, TYPE_IPV4);
else
geoip_set_city (NULL, NULL, location);
break;
case GEOIP_CITY_EDITION_REV0_V6:
case GEOIP_CITY_EDITION_REV1_V6:
if (TYPE_IPV6 == type_ip)
geoip_set_city_by_record (ip, location, TYPE_IPV6);
else {
char *ipv6 = ip4to6 (ip);
if (ipv6)
geoip_set_city_by_record (ipv6, location, TYPE_IPV6);
else
geoip_set_city (NULL, NULL, location);
}
break;
} }
/* Custom GeoIP database */
name = GeoIP_org_by_name (geo_location_data, (const char *) host);
geoip_set_asn (name, asn);
free (name);
} }
/* Entry point to set GeoIP location into the corresponding buffers, /* Entry point to set GeoIP location into the corresponding buffers,
* (continent, country, city). * (continent, country, city).
* *
* On error, 1 is returned * On error, 1 is returned
* On success, buffers are set and 0 is returned */ * On success, buffers are set and 0 is returned */
int int
set_geolocation (char *host, char *continent, char *country, char *city) { set_geolocation (char *host, char *continent, char *country, char *city, GO_UNUS ED char *asn) {
int type_ip = 0; int type_ip = 0;
if (!is_geoip_resource ()) if (!is_geoip_resource ())
return 1; return 1;
if (invalid_ipaddr (host, &type_ip)) if (invalid_ipaddr (host, &type_ip))
return 1; return 1;
geoip_get_country (host, country, type_ip); /* set ASN data */
geoip_get_continent (host, continent, type_ip); geoip_asn (host, asn);
if (conf.geoip_database)
/* set Country/City data */
if (set_geoip_db (TYPE_COUNTRY) == 0 || set_geoip_db (TYPE_CITY) == 0) {
geoip_get_country (host, country, type_ip);
geoip_get_continent (host, continent, type_ip);
}
if (set_geoip_db (TYPE_CITY) == 0)
geoip_get_city (host, city, type_ip); geoip_get_city (host, city, type_ip);
return 0; return 0;
} }
 End of changes. 28 change blocks. 
104 lines changed or deleted 260 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)