summaryrefslogtreecommitdiff
path: root/src/char/geoip.c
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2014-11-16 00:55:41 +0100
committerHaru <haru@dotalux.com>2014-11-16 07:16:21 +0100
commit98809d97bebc734be769318ad374c37b65dfd1e1 (patch)
tree09524df6296f1bd5d1d4ec5fa71ee51c36638fc9 /src/char/geoip.c
parent27cd926dd2f41e008da738e8d9259cd0c33a2f77 (diff)
downloadhercules-98809d97bebc734be769318ad374c37b65dfd1e1.tar.gz
hercules-98809d97bebc734be769318ad374c37b65dfd1e1.tar.bz2
hercules-98809d97bebc734be769318ad374c37b65dfd1e1.tar.xz
hercules-98809d97bebc734be769318ad374c37b65dfd1e1.zip
Moved geoip-related functions to geoip.c
Signed-off-by: Haru <haru@dotalux.com>
Diffstat (limited to 'src/char/geoip.c')
-rw-r--r--src/char/geoip.c173
1 files changed, 164 insertions, 9 deletions
diff --git a/src/char/geoip.c b/src/char/geoip.c
index 9a78c1ebd..34b731af8 100644
--- a/src/char/geoip.c
+++ b/src/char/geoip.c
@@ -6,22 +6,177 @@
#include "geoip.h"
-#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/stat.h> // for stat/lstat/fstat - [Dekamaster/Ultimate GM Tool]
#include "../common/cbasetypes.h"
-#include "../common/mmo.h"
-#include "../common/random.h"
+#include "../common/malloc.h"
#include "../common/showmsg.h"
-#include "../common/socket.h"
-#include "../common/strlib.h"
struct s_geoip geoip_data;
-const char* geoip_getcountry(uint32 ipnum);
-void geoip_final(bool shutdown);
-void geoip_init(void);
+struct geoip_interface geoip_s;
-void geoip_defaults(void) {
+/* [Dekamaster/Nightroad] */
+#define GEOIP_MAX_COUNTRIES 255
+#define GEOIP_STRUCTURE_INFO_MAX_SIZE 20
+#define GEOIP_COUNTRY_BEGIN 16776960
+
+const char * geoip_countryname[GEOIP_MAX_COUNTRIES] = {"Unknown","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Netherlands Antilles",
+ "Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados",
+ "Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia",
+ "Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the",
+ "Central African Republic","Congo","Switzerland","Cote D'Ivoire","Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica",
+ "Cuba","Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany","Djibouti","Denmark","Dominica","Dominican Republic",
+ "Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji",
+ "Falkland Islands (Malvinas)","Micronesia, Federated States of","Faroe Islands","France","France, Metropolitan","Gabon","United Kingdom","Grenada","Georgia","French Guiana",
+ "Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala",
+ "Guam","Guinea-Bissau","Guyana","Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia",
+ "Ireland","Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan",
+ "Japan","Kenya","Kyrgyzstan","Cambodia","Kiribati","Comoros","Saint Kitts and Nevis","Korea, Democratic People's Republic of","Korea, Republic of","Kuwait",
+ "Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania",
+ "Luxembourg","Latvia","Libyan Arab Jamahiriya","Morocco","Monaco","Moldova, Republic of","Madagascar","Marshall Islands","Macedonia","Mali",
+ "Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius","Maldives",
+ "Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua",
+ "Netherlands","Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia",
+ "Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal","Palau",
+ "Paraguay","Qatar","Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia","Solomon Islands","Seychelles","Sudan",
+ "Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname",
+ "Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo","Thailand",
+ "Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu","Taiwan",
+ "Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands","United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines","Venezuela",
+ "Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa",
+ "Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey",
+ "Saint Barthelemy", "Saint Martin", "Bonaire, Saint Eustatius and Saba", "South Sudan"};
+
+/* [Dekamaster/Nightroad] */
+/* WHY NOT A DBMAP: There are millions of entries in GeoIP and it has its own algorithm to go quickly through them, a DBMap wouldn't be efficient */
+const char* geoip_getcountry(uint32 ipnum)
+{
+ int depth;
+ unsigned int x;
+ const unsigned char *buf;
+ unsigned int offset = 0;
+
+ if( geoip->data->active == false )
+ return geoip_countryname[0];
+
+ for (depth = 31; depth >= 0; depth--) {
+ buf = geoip->data->cache + (long)6 *offset;
+ if (ipnum & (1 << depth)) {
+ /* Take the right-hand branch */
+ x = (buf[3*1 + 0] << (0*8))
+ + (buf[3*1 + 1] << (1*8))
+ + (buf[3*1 + 2] << (2*8));
+ } else {
+ /* Take the left-hand branch */
+ x = (buf[3*0 + 0] << (0*8))
+ + (buf[3*0 + 1] << (1*8))
+ + (buf[3*0 + 2] << (2*8));
+ }
+ if (x >= GEOIP_COUNTRY_BEGIN) {
+ x = x-GEOIP_COUNTRY_BEGIN;
+
+ if( x > GEOIP_MAX_COUNTRIES )
+ return geoip_countryname[0];
+
+ return geoip_countryname[x];
+ }
+ offset = x;
+ }
+ ShowError("geoip_getcountry(): Error traversing database for ipnum %d\n", ipnum);
+ ShowWarning("geoip_getcountry(): Possible database corruption!\n");
+
+ return geoip_countryname[0];
+}
+
+/**
+ * Disables GeoIP
+ * frees geoip.cache
+ **/
+void geoip_final(bool shutdown)
+{
+ if (geoip->data->cache) {
+ aFree(geoip->data->cache);
+ geoip->data->cache = NULL;
+ }
+
+ if (geoip->data->active) {
+ if (!shutdown)
+ ShowStatus("GeoIP "CL_RED"disabled"CL_RESET".\n");
+ geoip->data->active = false;
+ }
+}
+
+/**
+ * Reads GeoIP database and stores it into memory
+ * geoip.cache should be freed after use!
+ * http://dev.maxmind.com/geoip/legacy/geolite/
+ **/
+void geoip_init(void)
+{
+ int i, fno;
+ char db_type = 1;
+ unsigned char delim[3];
+ struct stat bufa;
+ FILE *db;
+
+ geoip->data->active = true;
+
+ db = fopen("./db/GeoIP.dat","rb");
+ if (db == NULL) {
+ ShowError("geoip_readdb: Error reading GeoIP.dat!\n");
+ geoip->final(false);
+ return;
+ }
+ fno = fileno(db);
+ if (fstat(fno, &bufa) < 0) {
+ ShowError("geoip_readdb: Error stating GeoIP.dat! Error %d\n", errno);
+ geoip->final(false);
+ return;
+ }
+ geoip->data->cache = aMalloc( (sizeof(geoip->data->cache) * bufa.st_size) );
+ if (fread(geoip->data->cache, sizeof(unsigned char), bufa.st_size, db) != bufa.st_size) {
+ ShowError("geoip_cache: Couldn't read all elements!\n");
+ fclose(db);
+ geoip->final(false);
+ return;
+ }
+
+ // Search database type
+ fseek(db, -3l, SEEK_END);
+ for (i = 0; i < GEOIP_STRUCTURE_INFO_MAX_SIZE; i++) {
+ if (fread(delim, sizeof(delim[0]), 3, db) != 3) {
+ db_type = 0;
+ break;
+ }
+ if (delim[0] == 255 && delim[1] == 255 && delim[2] == 255) {
+ if (fread(&db_type, sizeof(db_type), 1, db) != 1) {
+ db_type = 0;
+ }
+ break;
+ } else {
+ fseek(db, -4l, SEEK_CUR);
+ }
+ }
+
+ fclose(db);
+
+ if (db_type != 1) {
+ if (db_type)
+ ShowError("geoip_init(): Database type is not supported %d!\n", db_type);
+ else
+ ShowError("geoip_init(): GeoIP is corrupted!\n");
+
+ geoip->final(false);
+ return;
+ }
+ ShowStatus("Finished Reading "CL_GREEN"GeoIP"CL_RESET" Database.\n");
+}
+
+void geoip_defaults(void)
+{
geoip = &geoip_s;
geoip->data = &geoip_data;