2023-04-13 23:13:34 +02:00
|
|
|
/*
|
|
|
|
#!/usr/bin/env zsh
|
|
|
|
|
|
|
|
for i in $(ls *.c)
|
|
|
|
do
|
|
|
|
basename=$(echo ${i}|awk -F '.' '{ print $1}')
|
|
|
|
sudo -u haproxy cc -I/usr/include/ -I/usr/include/lua5.3/ -fPIC -shared -o ${basename}.so ${i} -lcurl -ljansson -lmaxminddb
|
|
|
|
done
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <netdb.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <lua5.3/lua.h>
|
|
|
|
#include <lua5.3/lauxlib.h>
|
|
|
|
#include <curl/curl.h>
|
|
|
|
#include <maxminddb.h>
|
|
|
|
#include <jansson.h>
|
|
|
|
|
2023-04-15 13:51:27 +02:00
|
|
|
static MMDB_s* mmdb;
|
2023-04-13 23:13:34 +02:00
|
|
|
|
|
|
|
static int load_geoip(lua_State *L) {
|
|
|
|
const char *filename = luaL_checkstring(L, 1);
|
2023-04-15 13:51:27 +02:00
|
|
|
int status;
|
|
|
|
mmdb = malloc(sizeof (struct MMDB_s));
|
|
|
|
status = MMDB_open(filename, MMDB_MODE_MMAP, mmdb);
|
2023-04-13 23:13:34 +02:00
|
|
|
if (status != 0) {
|
|
|
|
printf("Error loading geoip database\n");
|
|
|
|
exit(1);
|
|
|
|
} else {
|
|
|
|
printf("Loaded geoip database at: %s\n", filename);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int get_geoip_info(const char* ip_address, MMDB_lookup_result_s* result) {
|
|
|
|
int gai_error, mmdb_error;
|
2023-04-15 13:51:27 +02:00
|
|
|
(*result) = MMDB_lookup_string(mmdb, ip_address, &gai_error, &mmdb_error);
|
2023-04-13 23:13:34 +02:00
|
|
|
|
|
|
|
if (0 != gai_error) {
|
|
|
|
fprintf(stderr, "\n Error from getaddrinfo for %s - %s\n\n", ip_address, gai_strerror(gai_error));
|
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MMDB_SUCCESS != mmdb_error) {
|
|
|
|
fprintf(stderr, "\n Got an error from libmaxminddb: %s\n\n", MMDB_strerror(mmdb_error));
|
|
|
|
exit(3);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-04-15 13:51:27 +02:00
|
|
|
int filter_value(
|
|
|
|
bool found_entry,
|
|
|
|
MMDB_entry_s* entry,
|
|
|
|
MMDB_entry_data_list_s* entry_data_list,
|
2023-04-13 23:13:34 +02:00
|
|
|
MMDB_entry_data_s* entry_data,
|
|
|
|
const char* query) {
|
2023-04-15 13:51:27 +02:00
|
|
|
int status;
|
|
|
|
MMDB_get_entry_data_list(entry, &entry_data_list);
|
|
|
|
MMDB_free_entry_data_list(entry_data_list);
|
2023-04-13 23:13:34 +02:00
|
|
|
|
2023-04-15 13:51:27 +02:00
|
|
|
if (found_entry) {
|
2023-04-13 23:13:34 +02:00
|
|
|
if (strcmp(query, "country") == 0) {
|
2023-04-15 13:51:27 +02:00
|
|
|
status = MMDB_get_value(entry, entry_data, "country", "iso_code", NULL);
|
2023-04-13 23:13:34 +02:00
|
|
|
return status;
|
|
|
|
} else if (strcmp(query, "city") == 0){
|
2023-04-15 13:51:27 +02:00
|
|
|
status = MMDB_get_value(entry, entry_data, "city", "names", "en", NULL);
|
2023-04-13 23:13:34 +02:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int get_country(lua_State *L) {
|
|
|
|
const char *ip_address = luaL_checkstring(L, 1);
|
2023-04-15 13:51:27 +02:00
|
|
|
char* country = malloc(4);
|
|
|
|
int status;
|
2023-04-13 23:13:34 +02:00
|
|
|
|
2023-04-15 13:51:27 +02:00
|
|
|
MMDB_entry_data_list_s *entry_data_list = malloc(sizeof (struct MMDB_entry_data_list_s));
|
|
|
|
MMDB_entry_data_s* entry_data = malloc(sizeof (struct MMDB_entry_data_s));
|
|
|
|
MMDB_lookup_result_s* result = malloc(sizeof (struct MMDB_lookup_result_s));
|
2023-04-13 23:13:34 +02:00
|
|
|
|
2023-04-15 13:51:27 +02:00
|
|
|
status = get_geoip_info(ip_address, result);
|
2023-04-13 23:13:34 +02:00
|
|
|
|
2023-04-15 13:51:27 +02:00
|
|
|
status = filter_value(result->found_entry, &result->entry, entry_data_list, entry_data, "country");
|
|
|
|
free(result);
|
|
|
|
result = NULL;
|
2023-04-13 23:13:34 +02:00
|
|
|
|
|
|
|
if (status == 0) {
|
2023-04-15 13:51:27 +02:00
|
|
|
sprintf(country, "%.*s", entry_data->data_size, entry_data->utf8_string);
|
2023-04-13 23:13:34 +02:00
|
|
|
} else {
|
2024-01-27 10:41:30 +01:00
|
|
|
strcpy(country, "N/A");
|
2023-04-13 23:13:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
lua_pushstring(L, country);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int get_city(lua_State *L) {
|
|
|
|
const char *ip_address = luaL_checkstring(L, 1);
|
2023-04-15 13:51:27 +02:00
|
|
|
char* city = malloc(50);
|
|
|
|
int status;
|
2023-04-13 23:13:34 +02:00
|
|
|
|
2023-04-15 13:51:27 +02:00
|
|
|
MMDB_entry_data_list_s *entry_data_list = malloc(sizeof (struct MMDB_entry_data_list_s));
|
|
|
|
MMDB_entry_data_s* entry_data = malloc(sizeof (struct MMDB_entry_data_s));
|
|
|
|
MMDB_lookup_result_s* result = malloc(sizeof (struct MMDB_lookup_result_s));
|
2023-04-13 23:13:34 +02:00
|
|
|
|
2023-04-15 13:51:27 +02:00
|
|
|
status = get_geoip_info(ip_address, result);
|
2023-04-13 23:13:34 +02:00
|
|
|
|
2023-04-15 13:51:27 +02:00
|
|
|
status = filter_value(result->found_entry, &result->entry, entry_data_list, entry_data, "city");
|
|
|
|
free(result);
|
|
|
|
result = NULL;
|
2023-04-13 23:13:34 +02:00
|
|
|
|
|
|
|
if (status == 0) {
|
2023-04-15 13:51:27 +02:00
|
|
|
sprintf(city, "%.*s", entry_data->data_size, entry_data->utf8_string);
|
2023-04-13 23:13:34 +02:00
|
|
|
} else {
|
|
|
|
strcpy(city, "not found");
|
|
|
|
}
|
|
|
|
|
2023-04-15 13:51:27 +02:00
|
|
|
free(entry_data);
|
|
|
|
entry_data = NULL;
|
|
|
|
|
2023-04-13 23:13:34 +02:00
|
|
|
lua_pushstring(L, city);
|
2023-04-15 13:51:27 +02:00
|
|
|
|
|
|
|
free(city);
|
|
|
|
city = NULL;
|
|
|
|
|
2023-04-13 23:13:34 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int download_file() {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int request(lua_State *L) {
|
|
|
|
const char *url = luaL_checkstring(L, 1);
|
|
|
|
CURL *curl = curl_easy_init();
|
|
|
|
if (curl) {
|
|
|
|
CURLcode res;
|
|
|
|
curl_easy_setopt(curl, CURLOPT_URL, url);
|
|
|
|
res = curl_easy_perform(curl);
|
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
static void stackDump(lua_State *L)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int top = lua_gettop(L);
|
|
|
|
|
|
|
|
for(i = 1; i <= top; i++) {
|
|
|
|
int t = lua_type(L, i);
|
|
|
|
switch(t) {
|
|
|
|
case LUA_TNIL:
|
|
|
|
printf("nil");
|
|
|
|
break;
|
|
|
|
case LUA_TBOOLEAN:
|
|
|
|
printf(lua_toboolean(L, i) ? "true" : "false");
|
|
|
|
break;
|
|
|
|
case LUA_TNUMBER:
|
|
|
|
printf("%g", lua_tonumber(L, i));
|
|
|
|
break;
|
|
|
|
case LUA_TSTRING:
|
|
|
|
printf("%s", lua_tostring(L, i));
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
printf("%s", lua_typename(L, t));
|
|
|
|
}
|
|
|
|
printf(" ");
|
|
|
|
}
|
|
|
|
printf("\n\n");
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
|
|
int get_info(lua_State *L) {
|
|
|
|
lua_getglobal(L, "core");
|
|
|
|
lua_getfield(L, -1, "get_info");
|
|
|
|
|
|
|
|
int err = lua_pcall(L, 0, 1, 0);
|
|
|
|
|
|
|
|
if (err == 0) {
|
|
|
|
lua_getfield(L, -1, "Build info");
|
|
|
|
const char *version = lua_tostring(L, -1);
|
|
|
|
printf("HAProxy version: %s\n",version);
|
|
|
|
} else {
|
|
|
|
printf("%d %s\n", err, lua_tostring(L, -1));
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int luaopen_haproxy(lua_State *L) {
|
|
|
|
printf("Loading C lua module\n");
|
|
|
|
|
|
|
|
lua_pushcfunction(L, load_geoip);
|
|
|
|
lua_setglobal(L, "load_geoip");
|
|
|
|
|
|
|
|
lua_pushcfunction(L, get_country);
|
|
|
|
lua_setglobal(L, "get_country");
|
|
|
|
|
|
|
|
lua_pushcfunction(L, get_city);
|
|
|
|
lua_setglobal(L, "get_city");
|
|
|
|
|
|
|
|
lua_pushcfunction(L, request);
|
|
|
|
lua_setglobal(L, "request");
|
|
|
|
return 0;
|
|
|
|
}
|