/* * ip2location.c - IP2Location dlfunc for Exim * https://mta.org.ua/exim-4.94-conf/dlfunc/ip2location/ip2location.c * * Copyright (C) 2020 Victor Ustugov * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include //#define DLFUNC_IMPL /* Exim4 dlfunc API header: */ //#include "local_scan.h" //#include "macros.h" #include "exim.h" //# define string_copy(s) string_copy_function(s) //# define string_copyn(s, n) string_copyn_function((s), (n)) //# define string_copy_taint(s, t) string_copy_taint_function((s), (t)) extern uschar * string_copy_function(const uschar *); extern uschar * string_copyn_function(const uschar *, int n); extern uschar * string_copy_taint_function(const uschar *, BOOL tainted); #define string_sprintf(fmt, ...) \ string_sprintf_trc(fmt, US __FUNCTION__, __LINE__, __VA_ARGS__) extern uschar *string_sprintf_trc(const char *, const uschar *, unsigned, ...) ALMOST_PRINTF(1,4); /***************************************************************************** * Configuration settings: * *****************************************************************************/ /* default code returned when country is unknown: */ #define RESULT_UNKNOWN US"--" /* default code returned on lookup failures: */ #define RESULT_LOOKUP_FAILED US"--" //------------------------------------------------------------------------- int ip2location(uschar **yield, int argc, uschar *argv[]) { char *filename = (char *)argv[0]; char *ip_address = (char *)argv[1]; int defer_ok = 0; int status; IP2LocationRecord *record = NULL; if (argc < 2) { debug_printf("ip2location dlfunc: Invalid number of arguments\n"); *yield = string_copy(US"Invalid number of arguments"); return ERROR; } if (argc < 3) { defer_ok = 0; } else if ( (strcmpic(argv[2], US"1") == 0) || (strcmpic(argv[2], US"yes") == 0) || (strcmpic(argv[2], US"true") == 0) || (strcmpic(argv[2], US"defer_ok") == 0) ) { defer_ok = 1; } else { defer_ok = 0; } debug_printf("ip2location dlfunc: defer_ok: %d\n", defer_ok); debug_printf("ip2location dlfunc: IP2Location API version: %s (%lu)\n", IP2Location_api_version_string(), IP2Location_api_version_num()); debug_printf("ip2location dlfunc: try to find country for the host address %s in the %s database\n", ip_address, filename); IP2Location *IP2LocationObj = IP2Location_open(filename); if (IP2LocationObj == NULL) { if (defer_ok) { debug_printf("ip2location dlfunc: Call to IP2Location_open_mem failed\n"); log_write(0, LOG_PANIC, "ip2location dlfunc: Call to IP2Location_open_mem failed"); goto LOOKUP_FAILED_DEFER_OK; } else { *yield = string_sprintf("Call to IP2Location_open_mem failed", ""); return ERROR; } } if(IP2Location_open_mem(IP2LocationObj, IP2LOCATION_SHARED_MEMORY) == -1) { if (defer_ok) { debug_printf("ip2location dlfunc: Can't open %s\n", filename); log_write(0, LOG_PANIC, "ip2location dlfunc: Can't open %s", filename); goto LOOKUP_FAILED_DEFER_OK; } else { *yield = string_sprintf("Can't open %s", filename); goto LOOKUP_FAILED; } } record = IP2Location_get_all(IP2LocationObj, ip_address); if (record != NULL) { *yield = string_sprintf("%s", (record->country_short == NULL ? (char *)RESULT_UNKNOWN : record->country_short)); IP2Location_free_record(record); } else { *yield = string_sprintf("%s", RESULT_UNKNOWN); } IP2Location_close(IP2LocationObj); IP2Location_delete_shm(); return OK; LOOKUP_FAILED_DEFER_OK: *yield = string_sprintf("%s", RESULT_LOOKUP_FAILED); LOOKUP_FAILED: if (IP2LocationObj != NULL) IP2Location_close(IP2LocationObj); return ERROR; }