mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2025-06-30 22:18:19 -04:00
Feature: Added basic geoip lookup
This commit is contained in:
parent
2952a29c1e
commit
1963562d58
@ -243,6 +243,14 @@ PKG_HAVE_WITH_MODULES([OPENSSL], [openssl >= 1.1.0], [
|
|||||||
LIBS="${LIBS} ${OPENSSL_LIBS}"
|
LIBS="${LIBS} ${OPENSSL_LIBS}"
|
||||||
])
|
])
|
||||||
|
|
||||||
|
dnl
|
||||||
|
dnl libmaxminddb
|
||||||
|
dnl
|
||||||
|
PKG_HAVE_WITH_MODULES([MAXMINDDB], [libmaxminddb >= 1.3.2], [
|
||||||
|
CFLAGS="${CFLAGS} ${MAXMINDDB_CFLAGS}"
|
||||||
|
LIBS="${LIBS} ${MAXMINDDB_LIBS}"
|
||||||
|
])
|
||||||
|
|
||||||
dnl
|
dnl
|
||||||
dnl librhash - first try pkgconfig and then basic search
|
dnl librhash - first try pkgconfig and then basic search
|
||||||
dnl since the function is defined in rhash.h we need to check for that first,
|
dnl since the function is defined in rhash.h we need to check for that first,
|
||||||
|
@ -34,6 +34,7 @@ noinst_HEADERS = \
|
|||||||
prng.h \
|
prng.h \
|
||||||
matchfile.h \
|
matchfile.h \
|
||||||
tls.h \
|
tls.h \
|
||||||
|
geoip.h \
|
||||||
refobject.h \
|
refobject.h \
|
||||||
module.h \
|
module.h \
|
||||||
reportxml.h \
|
reportxml.h \
|
||||||
@ -88,6 +89,7 @@ icecast_SOURCES = \
|
|||||||
prng.c \
|
prng.c \
|
||||||
matchfile.c \
|
matchfile.c \
|
||||||
tls.c \
|
tls.c \
|
||||||
|
geoip.c \
|
||||||
refobject.c \
|
refobject.c \
|
||||||
module.c \
|
module.c \
|
||||||
reportxml.c \
|
reportxml.c \
|
||||||
|
@ -922,6 +922,12 @@ static inline xmlNodePtr __add_listener(client_t *client,
|
|||||||
|
|
||||||
xmlNewTextChild(node, NULL, XMLSTR("protocol"), XMLSTR(client_protocol_to_string(client->protocol)));
|
xmlNewTextChild(node, NULL, XMLSTR("protocol"), XMLSTR(client_protocol_to_string(client->protocol)));
|
||||||
|
|
||||||
|
if (client->con && *client->con->geoip.iso_3166_1_alpha_2) {
|
||||||
|
xmlNodePtr geoip = xmlNewChild(node, NULL, XMLSTR("geoip"), NULL);
|
||||||
|
xmlNodePtr country = xmlNewChild(geoip, NULL, XMLSTR("country"), NULL);
|
||||||
|
xmlSetProp(country, XMLSTR("iso-alpha-2"), XMLSTR(client->con->geoip.iso_3166_1_alpha_2));
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
xmlNodePtr history = xmlNewChild(node, NULL, XMLSTR("history"), NULL);
|
xmlNodePtr history = xmlNewChild(node, NULL, XMLSTR("history"), NULL);
|
||||||
size_t i;
|
size_t i;
|
||||||
|
@ -55,6 +55,7 @@
|
|||||||
#include "slave.h"
|
#include "slave.h"
|
||||||
#include "xslt.h"
|
#include "xslt.h"
|
||||||
#include "prng.h"
|
#include "prng.h"
|
||||||
|
#include "geoip.h"
|
||||||
|
|
||||||
#define CATMODULE "CONFIG"
|
#define CATMODULE "CONFIG"
|
||||||
#define RANGE_PORT 1, 65535
|
#define RANGE_PORT 1, 65535
|
||||||
@ -914,6 +915,7 @@ void config_clear(ice_config_t *c)
|
|||||||
if (c->log_dir) xmlFree(c->log_dir);
|
if (c->log_dir) xmlFree(c->log_dir);
|
||||||
if (c->webroot_dir) xmlFree(c->webroot_dir);
|
if (c->webroot_dir) xmlFree(c->webroot_dir);
|
||||||
if (c->adminroot_dir) xmlFree(c->adminroot_dir);
|
if (c->adminroot_dir) xmlFree(c->adminroot_dir);
|
||||||
|
if (c->geoipdbfile) xmlFree(c->geoipdbfile);
|
||||||
if (c->null_device) xmlFree(c->null_device);
|
if (c->null_device) xmlFree(c->null_device);
|
||||||
if (c->pidfile) xmlFree(c->pidfile);
|
if (c->pidfile) xmlFree(c->pidfile);
|
||||||
if (c->banfile) xmlFree(c->banfile);
|
if (c->banfile) xmlFree(c->banfile);
|
||||||
@ -1004,6 +1006,8 @@ void config_reread_config(void)
|
|||||||
restart_logging(config);
|
restart_logging(config);
|
||||||
prng_configure(config);
|
prng_configure(config);
|
||||||
main_config_reload(config);
|
main_config_reload(config);
|
||||||
|
igloo_ro_unref(&global.geoip_db);
|
||||||
|
global.geoip_db = geoip_db_new(config->geoipdbfile);
|
||||||
connection_reread_config(config);
|
connection_reread_config(config);
|
||||||
yp_recheck_config(config);
|
yp_recheck_config(config);
|
||||||
fserve_recheck_mime_types(config);
|
fserve_recheck_mime_types(config);
|
||||||
@ -2719,6 +2723,14 @@ static void _parse_paths(xmlDocPtr doc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
xmlFree(temp);
|
xmlFree(temp);
|
||||||
|
} else if (xmlStrcmp(node->name, XMLSTR("geoipdb")) == 0) {
|
||||||
|
if (!(temp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1))) {
|
||||||
|
ICECAST_LOG_WARN("<geoipdb> setting must not be empty.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (configuration->geoipdbfile)
|
||||||
|
xmlFree(configuration->geoipdbfile);
|
||||||
|
configuration->geoipdbfile = (char *)temp;
|
||||||
} else if (xmlStrcmp(node->name, XMLSTR("resource")) == 0 || xmlStrcmp(node->name, XMLSTR("alias")) == 0) {
|
} else if (xmlStrcmp(node->name, XMLSTR("resource")) == 0 || xmlStrcmp(node->name, XMLSTR("alias")) == 0) {
|
||||||
_parse_resource(doc, node, configuration);
|
_parse_resource(doc, node, configuration);
|
||||||
} else {
|
} else {
|
||||||
|
@ -288,6 +288,7 @@ struct ice_config_tag {
|
|||||||
char *allowfile;
|
char *allowfile;
|
||||||
char *webroot_dir;
|
char *webroot_dir;
|
||||||
char *adminroot_dir;
|
char *adminroot_dir;
|
||||||
|
char *geoipdbfile;
|
||||||
prng_seed_config_t *prng_seed;
|
prng_seed_config_t *prng_seed;
|
||||||
resource_t *resources;
|
resource_t *resources;
|
||||||
reportxml_database_t *reportxml_db;
|
reportxml_database_t *reportxml_db;
|
||||||
|
@ -57,6 +57,7 @@
|
|||||||
#include "acl.h"
|
#include "acl.h"
|
||||||
#include "listensocket.h"
|
#include "listensocket.h"
|
||||||
#include "fastevent.h"
|
#include "fastevent.h"
|
||||||
|
#include "geoip.h"
|
||||||
|
|
||||||
/* for ADMIN_COMMAND_ERROR, and ADMIN_ICESTATS_LEGACY_EXTENSION_APPLICATION */
|
/* for ADMIN_COMMAND_ERROR, and ADMIN_ICESTATS_LEGACY_EXTENSION_APPLICATION */
|
||||||
#include "admin.h"
|
#include "admin.h"
|
||||||
@ -189,6 +190,8 @@ int client_create(client_t **c_ptr, connection_t *con, http_parser_t *parser)
|
|||||||
|
|
||||||
fastevent_emit(FASTEVENT_TYPE_CLIENT_CREATE, FASTEVENT_FLAG_MODIFICATION_ALLOWED, FASTEVENT_DATATYPE_CLIENT, client);
|
fastevent_emit(FASTEVENT_TYPE_CLIENT_CREATE, FASTEVENT_FLAG_MODIFICATION_ALLOWED, FASTEVENT_DATATYPE_CLIENT, client);
|
||||||
|
|
||||||
|
geoip_lookup_client(global.geoip_db, client);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +64,10 @@ struct connection_tag {
|
|||||||
|
|
||||||
/* IP Address of the client as seen by the server */
|
/* IP Address of the client as seen by the server */
|
||||||
char *ip;
|
char *ip;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
char iso_3166_1_alpha_2[3]; /* 2 bytes plus \0 */
|
||||||
|
} geoip;
|
||||||
};
|
};
|
||||||
|
|
||||||
void connection_initialize(void);
|
void connection_initialize(void);
|
||||||
|
115
src/geoip.c
Normal file
115
src/geoip.c
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/* Icecast
|
||||||
|
*
|
||||||
|
* This program is distributed under the GNU General Public License, version 2.
|
||||||
|
* A copy of this license is included with this source.
|
||||||
|
*
|
||||||
|
* Copyright 2023 , Philipp Schafft <lion@lion.leolix.org>,
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "icecasttypes.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_MAXMINDDB
|
||||||
|
#include <maxminddb.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <igloo/error.h>
|
||||||
|
#include <igloo/ro.h>
|
||||||
|
|
||||||
|
#include "geoip.h"
|
||||||
|
#include "global.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "connection.h"
|
||||||
|
#include "util_string.h"
|
||||||
|
#include "logging.h"
|
||||||
|
#define CATMODULE "geoip"
|
||||||
|
|
||||||
|
struct geoip_db_tag {
|
||||||
|
igloo_ro_full_t __parent;
|
||||||
|
|
||||||
|
#ifdef HAVE_MAXMINDDB
|
||||||
|
MMDB_s mmdb;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static void geoip_db_free(igloo_ro_t self)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_MAXMINDDB
|
||||||
|
geoip_db_t *db = igloo_ro_to_type(self, geoip_db_t);
|
||||||
|
|
||||||
|
MMDB_close(&(db->mmdb));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
igloo_RO_PUBLIC_TYPE(geoip_db_t, igloo_ro_full_t,
|
||||||
|
igloo_RO_TYPEDECL_FREE(geoip_db_free)
|
||||||
|
);
|
||||||
|
|
||||||
|
#ifdef HAVE_MAXMINDDB
|
||||||
|
geoip_db_t * geoip_db_new(const char *filename)
|
||||||
|
{
|
||||||
|
geoip_db_t *ret;
|
||||||
|
MMDB_s mmdb;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = MMDB_open(filename, MMDB_MODE_MMAP, &mmdb);
|
||||||
|
if (status != MMDB_SUCCESS) {
|
||||||
|
if (status == MMDB_IO_ERROR) {
|
||||||
|
ICECAST_LOG_ERROR("Cannot open geoip database: %s: %s", MMDB_strerror(status), strerror(errno));
|
||||||
|
} else {
|
||||||
|
ICECAST_LOG_ERROR("Cannot open geoip database: %s", MMDB_strerror(status));
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (igloo_ro_new_raw(&ret, geoip_db_t, igloo_instance) != igloo_ERROR_NONE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret->mmdb = mmdb;
|
||||||
|
|
||||||
|
ICECAST_LOG_INFO("Loaded geoip database: %s", filename);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void geoip_lookup_client(geoip_db_t *self, client_t * client)
|
||||||
|
{
|
||||||
|
int gai_error, mmdb_error;
|
||||||
|
MMDB_lookup_result_s result;
|
||||||
|
connection_t *con;
|
||||||
|
|
||||||
|
if (!self || !client)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!client->con && !client->con->ip)
|
||||||
|
return;
|
||||||
|
|
||||||
|
con = client->con;
|
||||||
|
|
||||||
|
result = MMDB_lookup_string(&(self->mmdb), client->con->ip, &gai_error, &mmdb_error);
|
||||||
|
|
||||||
|
if (gai_error || mmdb_error != MMDB_SUCCESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (result.found_entry) {
|
||||||
|
MMDB_entry_data_s entry_data;
|
||||||
|
int status = MMDB_get_value(&result.entry, &entry_data, "country", "iso_code", (const char*)NULL);
|
||||||
|
|
||||||
|
if (status == MMDB_SUCCESS && entry_data.has_data) {
|
||||||
|
if (entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) {
|
||||||
|
if (entry_data.data_size < sizeof(con->geoip.iso_3166_1_alpha_2)) {
|
||||||
|
memcpy(con->geoip.iso_3166_1_alpha_2, entry_data.utf8_string, entry_data.data_size);
|
||||||
|
con->geoip.iso_3166_1_alpha_2[entry_data.data_size] = 0;
|
||||||
|
util_strtolower(con->geoip.iso_3166_1_alpha_2);
|
||||||
|
ICECAST_LOG_DINFO("FOUND: <%zu> <%H>", (size_t)entry_data.data_size, con->geoip.iso_3166_1_alpha_2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
25
src/geoip.h
Normal file
25
src/geoip.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/* Icecast
|
||||||
|
*
|
||||||
|
* This program is distributed under the GNU General Public License, version 2.
|
||||||
|
* A copy of this license is included with this source.
|
||||||
|
*
|
||||||
|
* Copyright 2023-2023, Philipp Schafft <lion@lion.leolix.org>,
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GEOIP_H__
|
||||||
|
#define __GEOIP_H__
|
||||||
|
|
||||||
|
#include "icecasttypes.h"
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
|
igloo_RO_FORWARD_TYPE(geoip_db_t);
|
||||||
|
|
||||||
|
#ifdef HAVE_MAXMINDDB
|
||||||
|
geoip_db_t * geoip_db_new(const char *filename);
|
||||||
|
void geoip_lookup_client(geoip_db_t *self, client_t * client);
|
||||||
|
#else
|
||||||
|
#define geoip_db_new(filename) NULL
|
||||||
|
#define geoip_lookup_client(self,client)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __GEOIP_H__ */
|
@ -51,6 +51,7 @@ void global_shutdown(void)
|
|||||||
{
|
{
|
||||||
thread_mutex_destroy(&_global_mutex);
|
thread_mutex_destroy(&_global_mutex);
|
||||||
igloo_ro_unref(&global.modulecontainer);
|
igloo_ro_unref(&global.modulecontainer);
|
||||||
|
igloo_ro_unref(&global.geoip_db);
|
||||||
avl_tree_free(global.source_tree, NULL);
|
avl_tree_free(global.source_tree, NULL);
|
||||||
igloo_sp_unref(&_instance_uuid, igloo_instance);
|
igloo_sp_unref(&_instance_uuid, igloo_instance);
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,7 @@ typedef struct ice_global_tag
|
|||||||
relay_t *master_relays;
|
relay_t *master_relays;
|
||||||
|
|
||||||
module_container_t *modulecontainer;
|
module_container_t *modulecontainer;
|
||||||
|
geoip_db_t *geoip_db;
|
||||||
|
|
||||||
|
|
||||||
/* state */
|
/* state */
|
||||||
|
@ -134,6 +134,10 @@ typedef struct mount_identifier_tag mount_identifier_t;
|
|||||||
|
|
||||||
typedef struct string_renderer_tag string_renderer_t;
|
typedef struct string_renderer_tag string_renderer_t;
|
||||||
|
|
||||||
|
/* ---[ geoip.[ch] ]--- */
|
||||||
|
|
||||||
|
typedef struct geoip_db_tag geoip_db_t;
|
||||||
|
|
||||||
/* ---[ event.[ch] ]--- */
|
/* ---[ event.[ch] ]--- */
|
||||||
|
|
||||||
typedef struct event_tag event_t;
|
typedef struct event_tag event_t;
|
||||||
@ -160,6 +164,7 @@ typedef void * refobject_t;
|
|||||||
/* --- [ For libigloo ]--- */
|
/* --- [ For libigloo ]--- */
|
||||||
#define igloo_RO_APPTYPES \
|
#define igloo_RO_APPTYPES \
|
||||||
igloo_RO_TYPE(string_renderer_t) \
|
igloo_RO_TYPE(string_renderer_t) \
|
||||||
|
igloo_RO_TYPE(geoip_db_t) \
|
||||||
igloo_RO_TYPE(event_t) \
|
igloo_RO_TYPE(event_t) \
|
||||||
igloo_RO_TYPE(event_registration_t) \
|
igloo_RO_TYPE(event_registration_t) \
|
||||||
igloo_RO_TYPE(module_t) \
|
igloo_RO_TYPE(module_t) \
|
||||||
|
@ -91,6 +91,7 @@
|
|||||||
#include "listensocket.h"
|
#include "listensocket.h"
|
||||||
#include "fastevent.h"
|
#include "fastevent.h"
|
||||||
#include "prng.h"
|
#include "prng.h"
|
||||||
|
#include "geoip.h"
|
||||||
#include "navigation.h"
|
#include "navigation.h"
|
||||||
|
|
||||||
#include <libxml/xmlmemory.h>
|
#include <libxml/xmlmemory.h>
|
||||||
@ -755,6 +756,10 @@ int main(int argc, char **argv)
|
|||||||
ICECAST_LOG_INFO("Server's PID is %lli", (long long int)getpid());
|
ICECAST_LOG_INFO("Server's PID is %lli", (long long int)getpid());
|
||||||
__log_system_name();
|
__log_system_name();
|
||||||
|
|
||||||
|
config = config_get_config();
|
||||||
|
global.geoip_db = geoip_db_new(config->geoipdbfile);
|
||||||
|
config_release_config();
|
||||||
|
|
||||||
/* REM 3D Graphics */
|
/* REM 3D Graphics */
|
||||||
|
|
||||||
/* let her rip */
|
/* let her rip */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user